f59ca24f59190e6d14c389d2ba83a192b235634d
[ovsdb.git] / openstack / net-virt-sfc / it / src / test / java / org / opendaylight / ovsdb / openstack / netvirt / sfc / NetvirtSfcIT.java
1 /*
2  * Copyright © 2015 Red Hat, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.ovsdb.openstack.netvirt.sfc;
10
11 import static org.junit.Assert.assertEquals;
12 import static org.junit.Assert.assertNotNull;
13 import static org.junit.Assert.assertNull;
14 import static org.junit.Assert.assertTrue;
15 import static org.junit.Assert.fail;
16 import static org.ops4j.pax.exam.CoreOptions.composite;
17 import static org.ops4j.pax.exam.CoreOptions.maven;
18 import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
19 import static org.ops4j.pax.exam.CoreOptions.propagateSystemProperties;
20 import static org.ops4j.pax.exam.CoreOptions.vmOption;
21 import static org.ops4j.pax.exam.CoreOptions.wrappedBundle;
22 import static org.ops4j.pax.exam.MavenUtils.asInProject;
23 import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.configureConsole;
24 import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.editConfigurationFilePut;
25 import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.keepRuntimeFolder;
26
27 import java.math.BigInteger;
28 import java.util.List;
29 import java.util.Properties;
30 import java.util.concurrent.atomic.AtomicBoolean;
31 import org.junit.Assert;
32 import org.junit.Before;
33 import org.junit.Test;
34 import org.junit.runner.RunWith;
35 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
36 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
37 import org.opendaylight.controller.mdsal.it.base.AbstractMdsalTestBase;
38 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
39 import org.opendaylight.ovsdb.openstack.netvirt.api.Southbound;
40 import org.opendaylight.ovsdb.openstack.netvirt.sfc.openflow13.NshUtils;
41 import org.opendaylight.ovsdb.openstack.netvirt.sfc.openflow13.SfcClassifier;
42 import org.opendaylight.ovsdb.openstack.netvirt.sfc.utils.AclUtils;
43 import org.opendaylight.ovsdb.openstack.netvirt.sfc.utils.ClassifierUtils;
44 import org.opendaylight.ovsdb.openstack.netvirt.sfc.utils.SfcUtils;
45 import org.opendaylight.ovsdb.southbound.SouthboundConstants;
46 import org.opendaylight.ovsdb.southbound.SouthboundUtil;
47 import org.opendaylight.ovsdb.utils.mdsal.openflow.FlowUtils;
48 import org.opendaylight.ovsdb.utils.mdsal.openflow.MatchUtils;
49 import org.opendaylight.ovsdb.utils.mdsal.utils.MdsalUtils;
50 import org.opendaylight.ovsdb.utils.servicehelper.ServiceHelper;
51 import org.opendaylight.ovsdb.utils.southbound.utils.SouthboundUtils;
52 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.AccessLists;
53 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.AccessListsBuilder;
54 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.AclBuilder;
55 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.AccessListEntriesBuilder;
56 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.access.list.entries.AceBuilder;
57 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.access.list.entries.ace.ActionsBuilder;
58 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.access.list.entries.ace.Matches;
59 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.access.list.entries.ace.MatchesBuilder;
60 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
61 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
62 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.oxm.container.match.entry.value.Nshc1CaseValue;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.Classifiers;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.ClassifiersBuilder;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.classifiers.ClassifierBuilder;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.classifiers.classifier.SffsBuilder;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.classifiers.classifier.sffs.SffBuilder;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.rev150105.Sfc;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.rev150105.SfcBuilder;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntry;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfo;
80 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
81 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
82 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
83 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
84 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
85 import org.opendaylight.yangtools.concepts.Builder;
86 import org.opendaylight.yangtools.yang.binding.DataObject;
87 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
88
89 import org.ops4j.pax.exam.Configuration;
90 import org.ops4j.pax.exam.Option;
91 import org.ops4j.pax.exam.junit.PaxExam;
92 import org.ops4j.pax.exam.karaf.options.LogLevelOption.LogLevel;
93 import org.ops4j.pax.exam.options.MavenUrlReference;
94 import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
95 import org.ops4j.pax.exam.spi.reactors.PerClass;
96 import org.slf4j.Logger;
97 import org.slf4j.LoggerFactory;
98
99 @RunWith(PaxExam.class)
100 @ExamReactorStrategy(PerClass.class)
101 public class NetvirtSfcIT extends AbstractMdsalTestBase {
102     private static final Logger LOG = LoggerFactory.getLogger(NetvirtSfcIT.class);
103     private static AclUtils aclUtils = new AclUtils();
104     private static ClassifierUtils classifierUtils = new ClassifierUtils();
105     private static SfcUtils sfcUtils = new SfcUtils();
106     private static MdsalUtils mdsalUtils;
107     private static AtomicBoolean setup = new AtomicBoolean(false);
108     private static SouthboundUtils southboundUtils;
109     private static String addressStr;
110     private static String portStr;
111     private static String connectionType;
112     private static Southbound southbound;
113     private static DataBroker dataBroker;
114     public static final String CONTROLLER_IPADDRESS = "ovsdb.controller.address";
115     public static final String SERVER_IPADDRESS = "ovsdbserver.ipaddress";
116     public static final String SERVER_PORT = "ovsdbserver.port";
117     public static final String CONNECTION_TYPE = "ovsdbserver.connection";
118     public static final String CONNECTION_TYPE_ACTIVE = "active";
119     public static final String CONNECTION_TYPE_PASSIVE = "passive";
120     public static final String DEFAULT_SERVER_PORT = "6640";
121     public static final String INTEGRATION_BRIDGE_NAME = "br-int";
122     private static final String NETVIRT_TOPOLOGY_ID = "netvirt:1";
123
124     @Override
125     public String getModuleName() {
126         return "netvirt-sfc";
127     }
128
129     @Override
130     public String getInstanceName() {
131         return "netvirt-sfc-default";
132     }
133
134     @Override
135     public MavenUrlReference getFeatureRepo() {
136         return maven()
137                 .groupId("org.opendaylight.ovsdb")
138                 .artifactId("openstack.net-virt-sfc-features-test")
139                 .classifier("features")
140                 .type("xml")
141                 .versionAsInProject();
142     }
143
144     @Override
145     public String getFeatureName() {
146         return "odl-ovsdb-sfc-test";
147     }
148
149     @Configuration
150     @Override
151     public Option[] config() {
152         Option[] parentOptions = super.config();
153         Option[] propertiesOptions = getPropertiesOptions();
154         Option[] otherOptions = getOtherOptions();
155         Option[] options = new Option[parentOptions.length + propertiesOptions.length + otherOptions.length];
156         System.arraycopy(parentOptions, 0, options, 0, parentOptions.length);
157         System.arraycopy(propertiesOptions, 0, options, parentOptions.length, propertiesOptions.length);
158         System.arraycopy(otherOptions, 0, options, parentOptions.length + propertiesOptions.length,
159                 otherOptions.length);
160         return options;
161     }
162
163     private Option[] getOtherOptions() {
164         return new Option[] {
165                 wrappedBundle(
166                         mavenBundle("org.opendaylight.ovsdb", "utils.mdsal-openflow")
167                                 .version(asInProject())
168                                 .type("jar")),
169                 configureConsole().startLocalConsole(),
170                 vmOption("-javaagent:../jars/org.jacoco.agent.jar=destfile=../../jacoco-it.exec"),
171                         keepRuntimeFolder()
172         };
173     }
174
175     public Option[] getPropertiesOptions() {
176         return new Option[] {
177                 propagateSystemProperties(SERVER_IPADDRESS, SERVER_PORT, CONNECTION_TYPE, CONTROLLER_IPADDRESS),
178         };
179     }
180
181     @Override
182     public Option getLoggingOption() {
183         return composite(
184                 editConfigurationFilePut(ORG_OPS4J_PAX_LOGGING_CFG,
185                         logConfiguration(NetvirtSfcIT.class),
186                         LogLevel.INFO.name()),
187                 editConfigurationFilePut(ORG_OPS4J_PAX_LOGGING_CFG,
188                         "log4j.logger.org.opendaylight.ovsdb.openstack.netvirt.sfc",
189                         LogLevel.TRACE.name()),
190                 /*editConfigurationFilePut(ORG_OPS4J_PAX_LOGGING_CFG,
191                         "log4j.logger.org.opendaylight.ovsdb",
192                         LogLevelOption.LogLevel.TRACE.name()),*/
193                 super.getLoggingOption());
194     }
195
196     protected String usage() {
197         return "Integration Test needs a valid connection configuration as follows :\n"
198                 + "active connection : mvn -Dovsdbserver.ipaddress=x.x.x.x -Dovsdbserver.port=yyyy verify\n"
199                 + "passive connection : mvn -Dovsdbserver.connection=passive verify\n";
200     }
201
202     private void getProperties() {
203         Properties props = System.getProperties();
204         addressStr = props.getProperty(SERVER_IPADDRESS);
205         portStr = props.getProperty(SERVER_PORT, DEFAULT_SERVER_PORT);
206         connectionType = props.getProperty(CONNECTION_TYPE, "active");
207         LOG.info("setUp: Using the following properties: mode= {}, ip:port= {}:{}",
208                 connectionType, addressStr, portStr);
209         if (connectionType.equalsIgnoreCase(CONNECTION_TYPE_ACTIVE)) {
210             if (addressStr == null) {
211                 fail(usage());
212             }
213         }
214     }
215
216     @Before
217     @Override
218     public void setup() {
219         if (setup.get()) {
220             LOG.info("Skipping setUp, already initialized");
221             return;
222         }
223
224         try {
225             Thread.sleep(1000);
226             super.setup();
227         } catch (Exception e) {
228             e.printStackTrace();
229         }
230
231         getProperties();
232
233         dataBroker = getDatabroker(getProviderContext());
234         mdsalUtils = new MdsalUtils(dataBroker);
235         assertNotNull("mdsalUtils should not be null", mdsalUtils);
236         southboundUtils = new SouthboundUtils(mdsalUtils);
237         assertTrue("Did not find " + NETVIRT_TOPOLOGY_ID, getNetvirtTopology());
238         southbound = (Southbound) ServiceHelper.getGlobalInstance(Southbound.class, this);
239         assertNotNull("southbound should not be null", southbound);
240         setup.set(true);
241     }
242
243     private ProviderContext getProviderContext() {
244         ProviderContext providerContext = null;
245         for (int i=0; i < 60; i++) {
246             providerContext = getSession();
247             if (providerContext != null) {
248                 break;
249             } else {
250                 try {
251                     Thread.sleep(1000);
252                 } catch (InterruptedException e) {
253                     e.printStackTrace();
254                 }
255             }
256         }
257         assertNotNull("providercontext should not be null", providerContext);
258         /* One more second to let the provider finish initialization */
259         try {
260             Thread.sleep(1000);
261         } catch (InterruptedException e) {
262             e.printStackTrace();
263         }
264         return providerContext;
265     }
266
267     private DataBroker getDatabroker(ProviderContext providerContext) {
268         DataBroker dataBroker = providerContext.getSALService(DataBroker.class);
269         assertNotNull("dataBroker should not be null", dataBroker);
270         return dataBroker;
271     }
272
273     private Boolean getNetvirtTopology() {
274         LOG.info("getNetvirtTopology: looking for {}...", NETVIRT_TOPOLOGY_ID);
275         Boolean found = false;
276         final TopologyId topologyId = new TopologyId(new Uri(NETVIRT_TOPOLOGY_ID));
277         InstanceIdentifier<Topology> path =
278                 InstanceIdentifier.create(NetworkTopology.class).child(Topology.class, new TopologyKey(topologyId));
279         for (int i = 0; i < 60; i++) {
280             Topology topology = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, path);
281             if (topology != null) {
282                 LOG.info("getNetvirtTopology: found {}...", NETVIRT_TOPOLOGY_ID);
283                 found = true;
284                 break;
285             } else {
286                 LOG.info("getNetvirtTopology: still looking ({})...", i);
287                 try {
288                     Thread.sleep(1000);
289                 } catch (InterruptedException e) {
290                     e.printStackTrace();
291                 }
292             }
293         }
294         return found;
295     }
296
297     @Test
298     public void testNetvirtSfcFeatureLoad() {
299         assertTrue(true);
300     }
301
302     private AccessListsBuilder setAccessLists () {
303         MatchesBuilder matchesBuilder = aclUtils.createMatches(new MatchesBuilder(), 80);
304         ActionsBuilder actionsBuilder = aclUtils.createActions(new ActionsBuilder(), Boolean.TRUE);
305         AceBuilder accessListEntryBuilder = aclUtils.createAccessListEntryBuilder(
306                 new AceBuilder(), "http", matchesBuilder, actionsBuilder);
307         AccessListEntriesBuilder accessListEntriesBuilder = aclUtils.createAccessListEntries(
308                 new AccessListEntriesBuilder(), accessListEntryBuilder);
309         AclBuilder accessListBuilder = aclUtils.createAccessList(new AclBuilder(),
310                 "http", accessListEntriesBuilder);
311         AccessListsBuilder accessListsBuilder = aclUtils.createAccessLists(new AccessListsBuilder(),
312                 accessListBuilder);
313         LOG.info("AccessLists: {}", accessListsBuilder.build());
314         return accessListsBuilder;
315     }
316
317     @Test
318     public void testAccessLists() {
319         testModel(setAccessLists(), AccessLists.class);
320     }
321
322     private ClassifiersBuilder setClassifiers() {
323         SffBuilder sffBuilder = classifierUtils.createSff(new SffBuilder(), "sffname");
324         SffsBuilder sffsBuilder = classifierUtils.createSffs(new SffsBuilder(), sffBuilder);
325         ClassifierBuilder classifierBuilder = classifierUtils.createClassifier(new ClassifierBuilder(),
326                 "classifierName", "aclName", sffsBuilder);
327         ClassifiersBuilder classifiersBuilder = classifierUtils.createClassifiers(new ClassifiersBuilder(),
328                 classifierBuilder);
329         LOG.info("Classifiers: {}", classifiersBuilder.build());
330         return classifiersBuilder;
331     }
332
333     @Test
334     public void testClassifiers() {
335         testModel(setClassifiers(), Classifiers.class);
336     }
337
338     private SfcBuilder setSfc() {
339         return sfcUtils.createSfc(new SfcBuilder(), "sfc");
340     }
341
342     @Test
343     public void testSfc() {
344         testModel(setSfc(), Sfc.class);
345     }
346
347     private <T extends DataObject> void testModel(Builder<T> builder, Class<T> clazz) {
348         InstanceIdentifier<T> path = InstanceIdentifier.create(clazz);
349         assertTrue(mdsalUtils.put(LogicalDatastoreType.CONFIGURATION, path, builder.build()));
350         T result = mdsalUtils.read(LogicalDatastoreType.CONFIGURATION, path);
351         assertNotNull(clazz.getSimpleName() + " should not be null", result);
352         assertTrue("Failed to remove " + clazz.getSimpleName(),
353                 mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, path));
354         result = mdsalUtils.read(LogicalDatastoreType.CONFIGURATION, path);
355         assertNull(clazz.getSimpleName() + " should be null", result);
356     }
357
358     /*
359      * Connect to an ovsdb node. Netvirt should add br-int, add the controller address
360      * and program the pipeline flows.
361      */
362     @Test
363     public void testDoIt() throws InterruptedException {
364         String bridgeName = INTEGRATION_BRIDGE_NAME;
365         ConnectionInfo connectionInfo = southboundUtils.getConnectionInfo(addressStr, portStr);
366         assertNotNull("connection failed", southboundUtils.connectOvsdbNode(connectionInfo));
367         Node ovsdbNode = southboundUtils.getOvsdbNode(connectionInfo);
368         assertNotNull("node is not connected", ovsdbNode);
369         ControllerEntry controllerEntry;
370         // Loop 10s checking if the controller was added
371         for (int i = 0; i < 10; i++) {
372             ovsdbNode = southboundUtils.getOvsdbNode(connectionInfo);
373             assertNotNull("ovsdb node not found", ovsdbNode);
374             String controllerTarget = "tcp:192.168.50.1:6653";//SouthboundUtil.getControllerTarget(ovsdbNode);
375             assertNotNull("Failed to get controller target", controllerTarget);
376             OvsdbBridgeAugmentation bridge = southboundUtils.getBridge(connectionInfo, bridgeName);
377             assertNotNull(bridge);
378             assertNotNull(bridge.getControllerEntry());
379             controllerEntry = bridge.getControllerEntry().iterator().next();
380             assertEquals(controllerTarget, controllerEntry.getTarget().getValue());
381             if (controllerEntry.isIsConnected()) {
382                 Assert.assertTrue(controllerEntry.isIsConnected());
383                 break;
384             }
385             Thread.sleep(1000);
386         }
387
388         /* TODO: add code to write to mdsal to exercise the sfc dataChangeListener */
389         /* allow some time to let the impl code do it's work to push flows */
390         /* or just comment out below lines and just manually verify on the bridges and reset them */
391         //Thread.sleep(10000);
392
393         assertTrue(southboundUtils.deleteBridge(connectionInfo, bridgeName));
394         Thread.sleep(1000);
395         assertTrue(southboundUtils.disconnectOvsdbNode(connectionInfo));
396     }
397
398     @Test
399     public void testDemo() throws InterruptedException {
400         for (DemoVm vm : demoVms){
401             ConnectionInfo connectionInfo = southboundUtils.getConnectionInfo(vm.ipAddr, vm.ipPort);
402             assertNotNull("connection failed", southboundUtils.connectOvsdbNode(connectionInfo));
403             Node ovsdbNode = southboundUtils.getOvsdbNode(connectionInfo);
404             assertNotNull("node is not connected", ovsdbNode);
405             String controllerTarget = SouthboundUtil.getControllerTarget(ovsdbNode);
406             assertNotNull("Failed to get controller target", controllerTarget);
407             List<ControllerEntry> setControllerEntry = southboundUtils.createControllerEntry(controllerTarget);
408             Uri setUri = new Uri(controllerTarget);
409             assertTrue(southboundUtils.addBridge(connectionInfo, null, vm.name, null, true,
410                     SouthboundConstants.OVSDB_FAIL_MODE_MAP.inverse().get("secure"), true, null, null,
411                     setControllerEntry, null));
412
413             for (int i = 0; i < 10; i++) {
414                 OvsdbBridgeAugmentation bridge = southboundUtils.getBridge(connectionInfo, vm.name);
415                 assertNotNull("bridge was not found: " + vm.name, bridge);
416                 assertNotNull("ControllerEntry was not found: "
417                                 + southboundUtils.createControllerEntry(controllerTarget),
418                         bridge.getControllerEntry());
419                 List<ControllerEntry> getControllerEntries = bridge.getControllerEntry();
420                 for (ControllerEntry entry : getControllerEntries) {
421                     if (entry.isIsConnected()) {
422                         assertTrue(entry.isIsConnected());
423                         break;
424                     }
425                 }
426                 Thread.sleep(1000);
427             }
428
429             assertTrue(southboundUtils.deleteBridge(connectionInfo, vm.name));
430             Thread.sleep(1000);
431             assertTrue(southboundUtils.disconnectOvsdbNode(connectionInfo));
432         }
433     }
434
435     private class DemoVm {
436         String name;
437         String ipAddr;
438         String ipPort;
439
440         DemoVm(String name, String ipAddr, String ipPort) {
441             this.name = name;
442             this.ipAddr = ipAddr;
443             this.ipPort = ipPort;
444         }
445     }
446
447     private DemoVm[] demoVms = {
448             new DemoVm("sw1", "192.168.50.70", "6640"),
449             //new DemoVm("sw2", "192.168.50.71", "6640"),
450     };
451
452     @Test
453     public void testDoIt2() throws InterruptedException {
454         String bridgeName = "sw1";
455         ConnectionInfo connectionInfo = southboundUtils.getConnectionInfo(addressStr, portStr);
456         assertNotNull("connection failed", southboundUtils.connectOvsdbNode(connectionInfo));
457         Node ovsdbNode = southboundUtils.getOvsdbNode(connectionInfo);
458         assertNotNull("node is not connected", ovsdbNode);
459         String controllerTarget = "tcp:192.168.50.1:6653";
460         List<ControllerEntry> setControllerEntry = southboundUtils.createControllerEntry(controllerTarget);
461         Assert.assertTrue(southboundUtils.addBridge(connectionInfo, null, bridgeName, null, true,
462                 SouthboundConstants.OVSDB_FAIL_MODE_MAP.inverse().get("secure"), true, null, null,
463                 setControllerEntry, null, "00:00:00:00:00:00:00:01"));
464         // Loop 10s checking if the controller was added
465         for (int i = 0; i < 10; i++) {
466             ovsdbNode = southboundUtils.getOvsdbNode(connectionInfo);
467             assertNotNull("ovsdb node not found", ovsdbNode);
468             assertNotNull("Failed to get controller target", controllerTarget);
469             OvsdbBridgeAugmentation bridge = southboundUtils.getBridge(connectionInfo, bridgeName);
470             assertNotNull(bridge);
471             assertNotNull(bridge.getControllerEntry());
472             ControllerEntry controllerEntry = bridge.getControllerEntry().iterator().next();
473             assertEquals(controllerTarget, controllerEntry.getTarget().getValue());
474             if (controllerEntry.isIsConnected()) {
475                 Assert.assertTrue(controllerEntry.isIsConnected());
476                 break;
477             }
478             Thread.sleep(1000);
479         }
480
481         Node bridgeNode = southbound.getBridgeNode(ovsdbNode, bridgeName);
482         assertNotNull("bridge " + bridgeName + " was not found", bridgeNode);
483         long datapathId = southbound.getDataPathId(bridgeNode);
484
485         SfcClassifier sfcClassifier = new SfcClassifier(dataBroker, southbound, mdsalUtils);
486         //sfcClassifier.programLocalInPort(datapathId, "4096", (long)1, (short)0, (short)50, true);
487
488         NshUtils nshUtils = new NshUtils(new Ipv4Address("192.168.50.71"), new PortNumber(6633),
489                 (long)10, (short)255, (long)4096, (long)4096);
490         MatchesBuilder matchesBuilder = aclUtils.createMatches(new MatchesBuilder(), 80);
491         sfcClassifier.programSfcClassiferFlows(datapathId, (short)0, "test", matchesBuilder.build(),
492                 nshUtils, (long)2, true);
493
494         nshUtils = new NshUtils(null, null, (long)10, (short)253, 0, 0);
495         //sfcClassifier.programEgressSfcClassiferFlows(datapathId, (short)0, "test", null,
496         //        nshUtils, (long)2, (long)3, true);
497
498         //try {
499         //    System.in.read();
500         //} catch (IOException e) {
501         //    e.printStackTrace();
502         //}
503
504         /*NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(datapathId);
505         FlowBuilder flowBuilder = getLocalInPortFlow(datapathId, "4096", (long) 1, (short) 0);
506         Flow flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.CONFIGURATION);
507         assertNotNull("Could not find flow in config", flow);
508         flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.OPERATIONAL);
509         assertNotNull("Could not find flow in operational", flow);*/
510
511         MatchBuilder matchBuilder = sfcClassifier.buildMatch(matchesBuilder.build());
512         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(datapathId);
513         FlowBuilder flowBuilder = getSfcClassifierFlow(datapathId, (short) 0, "test", null,
514                 nshUtils, (long) 2, matchBuilder);
515         Flow flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.CONFIGURATION);
516         assertNotNull("Could not find flow in config", flow);
517         flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.OPERATIONAL);
518         assertNotNull("Could not find flow in operational", flow);
519
520         //nodeBuilder = FlowUtils.createNodeBuilder(datapathId);
521         //flowBuilder = getEgressSfcClassifierFlow(datapathId, (short) 0, "test", nshUtils, (long) 2);
522         //flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.CONFIGURATION);
523         //assertNotNull("Could not find flow in config", flow);
524         //flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.OPERATIONAL);
525         //assertNotNull("Could not find flow in operational", flow);
526
527         LOG.info("***** Go look for flows *****");
528         Thread.sleep(30000);
529         assertTrue(southboundUtils.deleteBridge(connectionInfo, bridgeName));
530         Thread.sleep(1000);
531         assertTrue(southboundUtils.deleteBridge(connectionInfo, INTEGRATION_BRIDGE_NAME));
532         Thread.sleep(1000);
533         assertTrue(southboundUtils.disconnectOvsdbNode(connectionInfo));
534     }
535
536     private FlowBuilder getLocalInPortFlow(long dpidLong, String segmentationId, long inPort, short writeTable) {
537         MatchBuilder matchBuilder = new MatchBuilder();
538
539         FlowBuilder flowBuilder = new FlowBuilder();
540
541         flowBuilder.setMatch(MatchUtils.createInPortMatch(matchBuilder, dpidLong, inPort).build());
542         String flowId = "sfcIngress_" + segmentationId + "_" + inPort;
543         flowBuilder.setId(new FlowId(flowId));
544         FlowKey key = new FlowKey(new FlowId(flowId));
545         flowBuilder.setStrict(true);
546         flowBuilder.setBarrier(false);
547         flowBuilder.setTableId(writeTable);
548         flowBuilder.setKey(key);
549         flowBuilder.setFlowName(flowId);
550         flowBuilder.setHardTimeout(0);
551         flowBuilder.setIdleTimeout(0);
552         return flowBuilder;
553     }
554
555     public FlowBuilder getSfcClassifierFlow(long dpidLong, short writeTable, String ruleName, Matches match,
556                                              NshUtils nshHeader, long tunnelOfPort, MatchBuilder matchBuilder) {
557         FlowBuilder flowBuilder = new FlowBuilder();
558
559         flowBuilder.setMatch(matchBuilder.build());
560
561         String flowId = "sfcClass_" + ruleName + "_" + nshHeader.getNshNsp();
562         flowBuilder.setId(new FlowId(flowId));
563         FlowKey key = new FlowKey(new FlowId(flowId));
564         flowBuilder.setBarrier(true);
565         flowBuilder.setTableId(writeTable);
566         flowBuilder.setKey(key);
567         flowBuilder.setFlowName(flowId);
568         flowBuilder.setHardTimeout(0);
569         flowBuilder.setIdleTimeout(0);
570         return flowBuilder;
571     }
572
573     private FlowBuilder getEgressSfcClassifierFlow(long dpidLong, short writeTable, String ruleName,
574                                                    NshUtils nshHeader, long tunnelOfPort) {
575         FlowBuilder flowBuilder = new FlowBuilder();
576
577         MatchBuilder matchBuilder = new MatchBuilder();
578         flowBuilder.setMatch(MatchUtils.createInPortMatch(matchBuilder, dpidLong, tunnelOfPort).build());
579         flowBuilder.setMatch(
580                 MatchUtils.createTunnelIDMatch(matchBuilder, BigInteger.valueOf(nshHeader.getNshNsp())).build());
581         flowBuilder.setMatch(MatchUtils.addNxNspMatch(matchBuilder, nshHeader.getNshNsp()).build());
582         flowBuilder.setMatch(MatchUtils.addNxNsiMatch(matchBuilder, nshHeader.getNshNsi()).build());
583
584         String flowId = "egressSfcClass_" + ruleName + "_" + nshHeader.getNshNsp() + "_" + nshHeader.getNshNsi();
585         flowBuilder.setId(new FlowId(flowId));
586         FlowKey key = new FlowKey(new FlowId(flowId));
587         flowBuilder.setStrict(true);
588         flowBuilder.setBarrier(false);
589         flowBuilder.setTableId(writeTable);
590         flowBuilder.setKey(key);
591         flowBuilder.setFlowName(flowId);
592         flowBuilder.setHardTimeout(0);
593         flowBuilder.setIdleTimeout(0);
594         return flowBuilder;
595     }
596
597     private Flow getFlow (FlowBuilder flowBuilder, NodeBuilder nodeBuilder, LogicalDatastoreType store)
598             throws InterruptedException {
599         Flow flow = null;
600         for (int i = 0; i < 10; i++) {
601             flow = FlowUtils.getFlow(flowBuilder, nodeBuilder, dataBroker.newReadOnlyTransaction(), store);
602             if (flow != null) {
603                 LOG.info("flow({}): {}", store, flow);
604                 break;
605             }
606             Thread.sleep(1000);
607         }
608         return flow;
609     }
610 }