Merge "Added command patterns to update OperDS"
[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.when;
22 import static org.ops4j.pax.exam.CoreOptions.wrappedBundle;
23 import static org.ops4j.pax.exam.MavenUtils.asInProject;
24 import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.configureConsole;
25 import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.editConfigurationFilePut;
26 import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.keepRuntimeFolder;
27
28 import java.math.BigInteger;
29 import java.util.ArrayList;
30 import java.util.List;
31 import java.util.Properties;
32 import java.util.concurrent.atomic.AtomicBoolean;
33 import org.junit.Assert;
34 import org.junit.Before;
35 import org.junit.Ignore;
36 import org.junit.Test;
37 import org.junit.runner.RunWith;
38 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
39 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
40 import org.opendaylight.controller.mdsal.it.base.AbstractMdsalTestBase;
41 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
42 import org.opendaylight.ovsdb.openstack.netvirt.api.Southbound;
43 import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.Service;
44 import org.opendaylight.ovsdb.openstack.netvirt.sfc.standalone.openflow13.SfcClassifier;
45 import org.opendaylight.ovsdb.openstack.netvirt.sfc.utils.AclUtils;
46 import org.opendaylight.ovsdb.openstack.netvirt.sfc.utils.ClassifierUtils;
47 import org.opendaylight.ovsdb.openstack.netvirt.sfc.utils.SfcUtils;
48 import org.opendaylight.ovsdb.openstack.netvirt.sfc.utils.ServiceFunctionForwarderUtils;
49 import org.opendaylight.ovsdb.openstack.netvirt.sfc.utils.ServiceFunctionUtils;
50 import org.opendaylight.ovsdb.southbound.SouthboundConstants;
51 import org.opendaylight.ovsdb.southbound.SouthboundUtil;
52 import org.opendaylight.ovsdb.utils.mdsal.openflow.FlowUtils;
53 import org.opendaylight.ovsdb.utils.mdsal.openflow.MatchUtils;
54 import org.opendaylight.ovsdb.utils.mdsal.utils.MdsalUtils;
55 import org.opendaylight.ovsdb.utils.servicehelper.ServiceHelper;
56 import org.opendaylight.ovsdb.utils.southbound.utils.SouthboundUtils;
57 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.ServiceFunctions;
58 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.ServiceFunctionsBuilder;
59 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.service.function.entry.SfDataPlaneLocator;
60 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.service.function.entry.SfDataPlaneLocatorBuilder;
61 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.service.functions.ServiceFunction;
62 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.service.functions.ServiceFunctionBuilder;
63 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.ServiceFunctionForwarders;
64 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.ServiceFunctionForwardersBuilder;
65 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.ServiceFunctionForwarder;
66 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.ServiceFunctionForwarderBuilder;
67 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.service.function.forwarder.ServiceFunctionDictionary;
68 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.service.function.forwarder.ServiceFunctionDictionaryBuilder;
69 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.service.function.forwarder.SffDataPlaneLocator;
70 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.service.function.forwarder.SffDataPlaneLocatorBuilder;
71 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.service.function.forwarder.service.function.dictionary.SffSfDataPlaneLocatorBuilder;
72 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.service.function.forwarder.sff.data.plane.locator.DataPlaneLocatorBuilder;
73 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sft.rev140701.Dpi;
74 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sft.rev140701.Firewall;
75 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.AccessLists;
76 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.AccessListsBuilder;
77 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.AclBuilder;
78 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.AccessListEntriesBuilder;
79 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.access.list.entries.AceBuilder;
80 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;
81 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;
82 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;
83 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
84 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
85 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.Classifiers;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.ClassifiersBuilder;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.classifiers.ClassifierBuilder;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.classifiers.classifier.SffsBuilder;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.classifiers.classifier.sffs.SffBuilder;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.rev150105.Sfc;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.rev150105.SfcBuilder;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntry;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfo;
102 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
103 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
104 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
105 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
106 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
107 import org.opendaylight.yangtools.concepts.Builder;
108 import org.opendaylight.yangtools.yang.binding.DataObject;
109 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
110
111 import org.ops4j.pax.exam.Configuration;
112 import org.ops4j.pax.exam.Option;
113 import org.ops4j.pax.exam.junit.PaxExam;
114 import org.ops4j.pax.exam.karaf.options.LogLevelOption;
115 import org.ops4j.pax.exam.karaf.options.LogLevelOption.LogLevel;
116 import org.ops4j.pax.exam.options.MavenUrlReference;
117 import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
118 import org.ops4j.pax.exam.spi.reactors.PerClass;
119 import org.slf4j.Logger;
120 import org.slf4j.LoggerFactory;
121
122 @RunWith(PaxExam.class)
123 @ExamReactorStrategy(PerClass.class)
124 public class NetvirtSfcIT extends AbstractMdsalTestBase {
125     private static final Logger LOG = LoggerFactory.getLogger(NetvirtSfcIT.class);
126     private static AclUtils aclUtils = new AclUtils();
127     private static ClassifierUtils classifierUtils = new ClassifierUtils();
128     private static SfcUtils sfcUtils = new SfcUtils();
129     private static ServiceFunctionUtils serviceFunctionUtils = new ServiceFunctionUtils();
130     private static ServiceFunctionForwarderUtils serviceFunctionForwarderUtils = new ServiceFunctionForwarderUtils();
131     private static MdsalUtils mdsalUtils;
132     private static AtomicBoolean setup = new AtomicBoolean(false);
133     private static SouthboundUtils southboundUtils;
134     private static String addressStr;
135     private static String portStr;
136     private static String connectionType;
137     private static Southbound southbound;
138     private static DataBroker dataBroker;
139     public static final String CONTROLLER_IPADDRESS = "ovsdb.controller.address";
140     public static final String SERVER_IPADDRESS = "ovsdbserver.ipaddress";
141     public static final String SERVER_PORT = "ovsdbserver.port";
142     public static final String CONNECTION_TYPE = "ovsdbserver.connection";
143     public static final String CONNECTION_TYPE_ACTIVE = "active";
144     public static final String CONNECTION_TYPE_PASSIVE = "passive";
145     public static final String DEFAULT_SERVER_PORT = "6640";
146     public static final String INTEGRATION_BRIDGE_NAME = "br-int";
147     private static final String NETVIRT_TOPOLOGY_ID = "netvirt:1";
148     private static final String OVSDB_TRACE = "ovsdb.trace";
149
150     @Override
151     public String getModuleName() {
152         return "netvirt-sfc";
153     }
154
155     @Override
156     public String getInstanceName() {
157         return "netvirt-sfc-default";
158     }
159
160     @Override
161     public MavenUrlReference getFeatureRepo() {
162         return maven()
163                 .groupId("org.opendaylight.ovsdb")
164                 .artifactId("openstack.net-virt-sfc-features-test")
165                 .classifier("features")
166                 .type("xml")
167                 .versionAsInProject();
168     }
169
170     @Override
171     public String getFeatureName() {
172         return "odl-ovsdb-sfc-test";
173     }
174
175     @Configuration
176     @Override
177     public Option[] config() {
178         Option[] parentOptions = super.config();
179         Option[] propertiesOptions = getPropertiesOptions();
180         Option[] otherOptions = getOtherOptions();
181         Option[] options = new Option[parentOptions.length + propertiesOptions.length + otherOptions.length];
182         System.arraycopy(parentOptions, 0, options, 0, parentOptions.length);
183         System.arraycopy(propertiesOptions, 0, options, parentOptions.length, propertiesOptions.length);
184         System.arraycopy(otherOptions, 0, options, parentOptions.length + propertiesOptions.length,
185                 otherOptions.length);
186         return options;
187     }
188
189     private Option[] getOtherOptions() {
190         return new Option[] {
191                 wrappedBundle(
192                         mavenBundle("org.opendaylight.ovsdb", "utils.mdsal-openflow")
193                                 .version(asInProject())
194                                 .type("jar")),
195                 configureConsole().startLocalConsole(),
196                 vmOption("-javaagent:../jars/org.jacoco.agent.jar=destfile=../../jacoco-it.exec"),
197                         keepRuntimeFolder()
198         };
199     }
200
201     public Option[] getPropertiesOptions() {
202         return new Option[] {
203                 propagateSystemProperties(SERVER_IPADDRESS, SERVER_PORT, CONNECTION_TYPE,
204                         CONTROLLER_IPADDRESS, OVSDB_TRACE),
205         };
206     }
207
208     @Override
209     public Option getLoggingOption() {
210         return composite(
211                 when(Boolean.getBoolean(OVSDB_TRACE)).useOptions(
212                         editConfigurationFilePut(ORG_OPS4J_PAX_LOGGING_CFG,
213                                 "log4j.logger.org.opendaylight.ovsdb",
214                                 LogLevelOption.LogLevel.TRACE.name())),
215                 editConfigurationFilePut(ORG_OPS4J_PAX_LOGGING_CFG,
216                         logConfiguration(NetvirtSfcIT.class),
217                         LogLevel.INFO.name()),
218                 editConfigurationFilePut(ORG_OPS4J_PAX_LOGGING_CFG,
219                         "log4j.logger.org.opendaylight.ovsdb.openstack.netvirt.sfc",
220                         LogLevel.TRACE.name()),
221                 editConfigurationFilePut(ORG_OPS4J_PAX_LOGGING_CFG,
222                         "log4j.logger.org.opendaylight.ovsdb.sfc",
223                         LogLevel.TRACE.name()),
224                 super.getLoggingOption());
225     }
226
227     protected String usage() {
228         return "Integration Test needs a valid connection configuration as follows :\n"
229                 + "active connection : mvn -Dovsdbserver.ipaddress=x.x.x.x -Dovsdbserver.port=yyyy verify\n"
230                 + "passive connection : mvn -Dovsdbserver.connection=passive verify\n";
231     }
232
233     private void getProperties() {
234         Properties props = System.getProperties();
235         addressStr = props.getProperty(SERVER_IPADDRESS);
236         portStr = props.getProperty(SERVER_PORT, DEFAULT_SERVER_PORT);
237         connectionType = props.getProperty(CONNECTION_TYPE, "active");
238         LOG.info("setUp: Using the following properties: mode= {}, ip:port= {}:{}",
239                 connectionType, addressStr, portStr);
240         if (connectionType.equalsIgnoreCase(CONNECTION_TYPE_ACTIVE)) {
241             if (addressStr == null) {
242                 fail(usage());
243             }
244         }
245         LOG.info("getProperties {}: {}", OVSDB_TRACE, props.getProperty(OVSDB_TRACE));
246     }
247
248     @Before
249     @Override
250     public void setup() {
251         if (setup.get()) {
252             LOG.info("Skipping setUp, already initialized");
253             return;
254         }
255
256         try {
257             Thread.sleep(1000);
258             super.setup();
259         } catch (Exception e) {
260             e.printStackTrace();
261         }
262
263         getProperties();
264
265         dataBroker = getDatabroker(getProviderContext());
266         mdsalUtils = new MdsalUtils(dataBroker);
267         assertNotNull("mdsalUtils should not be null", mdsalUtils);
268         southboundUtils = new SouthboundUtils(mdsalUtils);
269         assertTrue("Did not find " + NETVIRT_TOPOLOGY_ID, getNetvirtTopology());
270         southbound = (Southbound) ServiceHelper.getGlobalInstance(Southbound.class, this);
271         assertNotNull("southbound should not be null", southbound);
272         setup.set(true);
273     }
274
275     private ProviderContext getProviderContext() {
276         ProviderContext providerContext = null;
277         for (int i=0; i < 60; i++) {
278             providerContext = getSession();
279             if (providerContext != null) {
280                 break;
281             } else {
282                 try {
283                     Thread.sleep(1000);
284                 } catch (InterruptedException e) {
285                     e.printStackTrace();
286                 }
287             }
288         }
289         assertNotNull("providercontext should not be null", providerContext);
290         /* One more second to let the provider finish initialization */
291         try {
292             Thread.sleep(1000);
293         } catch (InterruptedException e) {
294             e.printStackTrace();
295         }
296         return providerContext;
297     }
298
299     private DataBroker getDatabroker(ProviderContext providerContext) {
300         DataBroker dataBroker = providerContext.getSALService(DataBroker.class);
301         assertNotNull("dataBroker should not be null", dataBroker);
302         return dataBroker;
303     }
304
305     private Boolean getNetvirtTopology() {
306         LOG.info("getNetvirtTopology: looking for {}...", NETVIRT_TOPOLOGY_ID);
307         Boolean found = false;
308         final TopologyId topologyId = new TopologyId(new Uri(NETVIRT_TOPOLOGY_ID));
309         InstanceIdentifier<Topology> path =
310                 InstanceIdentifier.create(NetworkTopology.class).child(Topology.class, new TopologyKey(topologyId));
311         for (int i = 0; i < 60; i++) {
312             Topology topology = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, path);
313             if (topology != null) {
314                 LOG.info("getNetvirtTopology: found {}...", NETVIRT_TOPOLOGY_ID);
315                 found = true;
316                 break;
317             } else {
318                 LOG.info("getNetvirtTopology: still looking ({})...", i);
319                 try {
320                     Thread.sleep(1000);
321                 } catch (InterruptedException e) {
322                     e.printStackTrace();
323                 }
324             }
325         }
326         return found;
327     }
328
329     @Test
330     public void testNetvirtSfcFeatureLoad() {
331         assertTrue(true);
332     }
333
334     private AccessListsBuilder setAccessLists () {
335         MatchesBuilder matchesBuilder = aclUtils.matchesBuilder(new MatchesBuilder(), 80);
336         ActionsBuilder actionsBuilder = aclUtils.actionsBuilder(new ActionsBuilder(), Boolean.TRUE);
337         AceBuilder accessListEntryBuilder = aclUtils.aceBuilder(
338                 new AceBuilder(), "http", matchesBuilder, actionsBuilder);
339         AccessListEntriesBuilder accessListEntriesBuilder = aclUtils.accessListEntriesBuidler(
340                 new AccessListEntriesBuilder(), accessListEntryBuilder);
341         AclBuilder accessListBuilder = aclUtils.aclBuilder(new AclBuilder(),
342                 "http", accessListEntriesBuilder);
343         AccessListsBuilder accessListsBuilder = aclUtils.accessListsBuidler(new AccessListsBuilder(),
344                 accessListBuilder);
345         LOG.info("AccessLists: {}", accessListsBuilder.build());
346         return accessListsBuilder;
347     }
348
349     @Test
350     public void testAccessLists() throws InterruptedException {
351         testModel(setAccessLists(), AccessLists.class, 0);
352     }
353
354     private ClassifiersBuilder setClassifiers() {
355         SffBuilder sffBuilder = classifierUtils.sffBuilder(new SffBuilder(), "sffname");
356         SffsBuilder sffsBuilder = classifierUtils.sffsBuilder(new SffsBuilder(), sffBuilder);
357         ClassifierBuilder classifierBuilder = classifierUtils.classifierBuilder(new ClassifierBuilder(),
358                 "classifierName", "aclName", sffsBuilder);
359         ClassifiersBuilder classifiersBuilder = classifierUtils.ClassifiersBuilder(new ClassifiersBuilder(),
360                 classifierBuilder);
361         LOG.info("Classifiers: {}", classifiersBuilder.build());
362         return classifiersBuilder;
363     }
364
365     @Test
366     public void testClassifiers() throws InterruptedException {
367         testModel(setClassifiers(), Classifiers.class, 0);
368     }
369
370     private SfcBuilder netvirtSfcBuilder() {
371         return sfcUtils.sfcBuilder(new SfcBuilder(), "sfc");
372     }
373
374     @Test
375     public void testNetvirtSfcModel() throws InterruptedException {
376         testModel(netvirtSfcBuilder(), Sfc.class, 0);
377     }
378
379     private <T extends DataObject> void testModel(Builder<T> builder, Class<T> clazz, long wait)
380             throws InterruptedException {
381         InstanceIdentifier<T> path = InstanceIdentifier.create(clazz);
382         assertTrue(mdsalUtils.put(LogicalDatastoreType.CONFIGURATION, path, builder.build()));
383         T result = mdsalUtils.read(LogicalDatastoreType.CONFIGURATION, path);
384         assertNotNull(clazz.getSimpleName() + " should not be null", result);
385         Thread.sleep(wait);
386         assertTrue("Failed to remove " + clazz.getSimpleName(),
387                 mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, path));
388         result = mdsalUtils.read(LogicalDatastoreType.CONFIGURATION, path);
389         assertNull(clazz.getSimpleName() + " should be null", result);
390     }
391
392     private ServiceFunctionsBuilder serviceFunctionsBuilder() {
393         SfDataPlaneLocatorBuilder sfDataPlaneLocator =
394                 serviceFunctionUtils.sfDataPlaneLocatorBuilder(new SfDataPlaneLocatorBuilder(),
395                         "192.168.120.31", 6633, "testDpl1-1234-uuid", "testSff1");
396         List<SfDataPlaneLocator> sfDataPlaneLocatorList = serviceFunctionUtils.list(
397                 new ArrayList<SfDataPlaneLocator>(), sfDataPlaneLocator);
398         ServiceFunctionBuilder serviceFunctionBuilder =
399                 serviceFunctionUtils.serviceFunctionBuidler(new ServiceFunctionBuilder(),
400                         "192.168.120.31", "testSf", sfDataPlaneLocatorList, Firewall.class);
401         List<ServiceFunction> serviceFunctionList = serviceFunctionUtils.list(
402                 new ArrayList<ServiceFunction>(), serviceFunctionBuilder);
403
404         sfDataPlaneLocator =
405                 serviceFunctionUtils.sfDataPlaneLocatorBuilder(new SfDataPlaneLocatorBuilder(),
406                         "192.168.120.32", 6633, "testDpl2-1234-uuid", "testSff2");
407         sfDataPlaneLocatorList = serviceFunctionUtils.list(
408                 new ArrayList<SfDataPlaneLocator>(), sfDataPlaneLocator);
409         serviceFunctionBuilder =
410                 serviceFunctionUtils.serviceFunctionBuidler(new ServiceFunctionBuilder(),
411                         "192.168.120.32", "testSf2", sfDataPlaneLocatorList, Dpi.class);
412         serviceFunctionList = serviceFunctionUtils.list(
413                 serviceFunctionList, serviceFunctionBuilder);
414
415         ServiceFunctionsBuilder serviceFunctionsBuilder =
416                 serviceFunctionUtils.serviceFunctionsBuilder(new ServiceFunctionsBuilder(),
417                         serviceFunctionList);
418         LOG.info("ServiceFunctions: {}", serviceFunctionsBuilder.build());
419         return serviceFunctionsBuilder;
420     }
421
422     private ServiceFunctionForwardersBuilder serviceFunctionForwardersBuilder() {
423         String sf1Name = "firewall-72";
424         String sff1Ip = "192.168.120.31";
425         String sff1Name = "SFF1";
426         String sffDpl1Name = "sfc-tun2";
427         String sn1Name = "OVSDB2";
428         String bridge1Name= "sw2";
429         int port = 6633;
430
431         DataPlaneLocatorBuilder dataPlaneLocatorBuilder =
432                 serviceFunctionForwarderUtils.dataPlaneLocatorBuilder(
433                         new DataPlaneLocatorBuilder(), sff1Ip, port);
434         SffDataPlaneLocatorBuilder sffDataPlaneLocatorBuilder =
435                 serviceFunctionForwarderUtils.sffDataPlaneLocatorBuilder(
436                         new SffDataPlaneLocatorBuilder(), dataPlaneLocatorBuilder, sffDpl1Name);
437         List<SffDataPlaneLocator> sffDataPlaneLocatorList = serviceFunctionForwarderUtils.list(
438                 new ArrayList<SffDataPlaneLocator>(), sffDataPlaneLocatorBuilder);
439
440         SffSfDataPlaneLocatorBuilder sffSfDataPlaneLocatorBuilder =
441                 serviceFunctionForwarderUtils.sffSfDataPlaneLocatorBuilder(
442                         new SffSfDataPlaneLocatorBuilder(), sff1Ip, port);
443         ServiceFunctionDictionaryBuilder serviceFunctionDictionaryBuilder =
444                 serviceFunctionForwarderUtils.serviceFunctionDictionaryBuilder(
445                         new ServiceFunctionDictionaryBuilder(), sf1Name, Firewall.class,
446                         sffSfDataPlaneLocatorBuilder);
447         List<ServiceFunctionDictionary> serviceFunctionDictionaryList = serviceFunctionForwarderUtils.list(
448                 new ArrayList<ServiceFunctionDictionary>(), serviceFunctionDictionaryBuilder);
449
450         ServiceFunctionForwarderBuilder serviceFunctionForwarderBuilder =
451                 serviceFunctionForwarderUtils.serviceFunctionForwarderBuilder(
452                         new ServiceFunctionForwarderBuilder(), sff1Name, sn1Name, bridge1Name,
453                         sffDataPlaneLocatorList, serviceFunctionDictionaryList);
454         List<ServiceFunctionForwarder>  serviceFunctionForwarderList = serviceFunctionForwarderUtils.list(
455                 new ArrayList<ServiceFunctionForwarder>(), serviceFunctionForwarderBuilder);
456         ServiceFunctionForwardersBuilder serviceFunctionForwardersBuilder =
457                 serviceFunctionForwarderUtils.serviceFunctionForwardersBuilder(
458                         new ServiceFunctionForwardersBuilder(), serviceFunctionForwarderList);
459         LOG.info("ServiceFunctionForwarders: {}", serviceFunctionForwardersBuilder.build());
460         return serviceFunctionForwardersBuilder;
461     }
462
463     @Test
464     public void testSfcModel() throws InterruptedException {
465         testModel(serviceFunctionsBuilder(), ServiceFunctions.class, 3000);
466         testModel(serviceFunctionForwardersBuilder(), ServiceFunctionForwarders.class, 3000);
467     }
468
469     /*
470      * Connect to an ovsdb node. Netvirt should add br-int, add the controller address
471      * and program the pipeline flows.
472      */
473     @Test
474     public void testNetvirtSfc() throws InterruptedException {
475         String bridgeName = INTEGRATION_BRIDGE_NAME;
476         ConnectionInfo connectionInfo = southboundUtils.getConnectionInfo(addressStr, portStr);
477         assertNotNull("connection failed", southboundUtils.connectOvsdbNode(connectionInfo));
478         Node ovsdbNode = southboundUtils.getOvsdbNode(connectionInfo);
479         assertNotNull("node is not connected", ovsdbNode);
480         ControllerEntry controllerEntry;
481         // Loop 10s checking if the controller was added
482         for (int i = 0; i < 10; i++) {
483             ovsdbNode = southboundUtils.getOvsdbNode(connectionInfo);
484             assertNotNull("ovsdb node not found", ovsdbNode);
485             String controllerTarget = SouthboundUtil.getControllerTarget(ovsdbNode);
486             assertNotNull("Failed to get controller target", controllerTarget);
487             OvsdbBridgeAugmentation bridge = southboundUtils.getBridge(connectionInfo, bridgeName);
488             if (bridge != null) {
489                 assertNotNull("Failed to read bridge", bridge);
490                 assertNotNull("Failed to extract controllerEntry", bridge.getControllerEntry());
491                 controllerEntry = bridge.getControllerEntry().iterator().next();
492                 assertEquals(controllerTarget, controllerEntry.getTarget().getValue());
493                 if (controllerEntry.isIsConnected()) {
494                     Assert.assertTrue("switch is not connected to the controller", controllerEntry.isIsConnected());
495                     break;
496                 }
497             }
498             Thread.sleep(1000);
499         }
500
501         Node bridgeNode = southbound.getBridgeNode(ovsdbNode, bridgeName);
502         assertNotNull("bridge " + bridgeName + " was not found", bridgeNode);
503         long datapathId = southbound.getDataPathId(bridgeNode);
504
505         //Thread.sleep(10000);
506
507         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(datapathId);
508         FlowBuilder flowBuilder = FlowUtils.getPipelineFlow(Service.SFC_CLASSIFIER.getTable(), (short)0);
509         Flow flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.CONFIGURATION);
510         assertNotNull("Could not find flow in config", flow);
511         flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.OPERATIONAL);
512         assertNotNull("Could not find flow in operational", flow);
513
514         assertTrue(southboundUtils.deleteBridge(connectionInfo, bridgeName));
515         Thread.sleep(1000);
516         assertTrue(southboundUtils.disconnectOvsdbNode(connectionInfo));
517     }
518
519     @Ignore
520     @Test
521     public void testStandalone() throws InterruptedException {
522         String bridgeName = "sw1";
523         ConnectionInfo connectionInfo = southboundUtils.getConnectionInfo(addressStr, portStr);
524         assertNotNull("connection failed", southboundUtils.connectOvsdbNode(connectionInfo));
525         Node ovsdbNode = southboundUtils.getOvsdbNode(connectionInfo);
526         assertNotNull("node is not connected", ovsdbNode);
527         String controllerTarget = "tcp:192.168.50.1:6653";
528         List<ControllerEntry> setControllerEntry = southboundUtils.createControllerEntry(controllerTarget);
529         Assert.assertTrue(southboundUtils.addBridge(connectionInfo, null, bridgeName, null, true,
530                 SouthboundConstants.OVSDB_FAIL_MODE_MAP.inverse().get("secure"), true, null, null,
531                 setControllerEntry, null, "00:00:00:00:00:00:00:01"));
532         // Loop 10s checking if the controller was added
533         for (int i = 0; i < 10; i++) {
534             ovsdbNode = southboundUtils.getOvsdbNode(connectionInfo);
535             assertNotNull("ovsdb node not found", ovsdbNode);
536             assertNotNull("Failed to get controller target", controllerTarget);
537             OvsdbBridgeAugmentation bridge = southboundUtils.getBridge(connectionInfo, bridgeName);
538             assertNotNull(bridge);
539             assertNotNull(bridge.getControllerEntry());
540             ControllerEntry controllerEntry = bridge.getControllerEntry().iterator().next();
541             assertEquals(controllerTarget, controllerEntry.getTarget().getValue());
542             if (controllerEntry.isIsConnected()) {
543                 Assert.assertTrue(controllerEntry.isIsConnected());
544                 break;
545             }
546             Thread.sleep(1000);
547         }
548
549         Node bridgeNode = southbound.getBridgeNode(ovsdbNode, bridgeName);
550         assertNotNull("bridge " + bridgeName + " was not found", bridgeNode);
551         long datapathId = southbound.getDataPathId(bridgeNode);
552
553         SfcClassifier sfcClassifier = new SfcClassifier(dataBroker, southbound, mdsalUtils);
554         //sfcClassifier.programLocalInPort(datapathId, "4096", (long)1, (short)0, (short)50, true);
555
556         NshUtils nshUtils = new NshUtils(new Ipv4Address("192.168.50.71"), new PortNumber(6633),
557                 (long)10, (short)255, (long)4096, (long)4096);
558         MatchesBuilder matchesBuilder = aclUtils.matchesBuilder(new MatchesBuilder(), 80);
559         sfcClassifier.programSfcClassiferFlows(datapathId, (short)0, "test", matchesBuilder.build(),
560                 nshUtils, (long)2, true);
561
562         nshUtils = new NshUtils(null, null, (long)10, (short)253, 0, 0);
563         //sfcClassifier.programEgressSfcClassiferFlows(datapathId, (short)0, "test", null,
564         //        nshUtils, (long)2, (long)3, true);
565
566         //try {
567         //    System.in.read();
568         //} catch (IOException e) {
569         //    e.printStackTrace();
570         //}
571
572         //NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(datapathId);
573         //FlowBuilder flowBuilder = getLocalInPortFlow(datapathId, "4096", (long) 1, (short) 0);
574         //Flow flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.CONFIGURATION);
575         //assertNotNull("Could not find flow in config", flow);
576         //flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.OPERATIONAL);
577         //assertNotNull("Could not find flow in operational", flow);
578
579         MatchBuilder matchBuilder = sfcClassifier.buildMatch(matchesBuilder.build());
580         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(datapathId);
581         FlowBuilder flowBuilder = getSfcClassifierFlow(datapathId, (short) 0, "test", null,
582                 nshUtils, (long) 2, matchBuilder);
583         Flow flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.CONFIGURATION);
584         assertNotNull("Could not find flow in config", flow);
585         flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.OPERATIONAL);
586         assertNotNull("Could not find flow in operational", flow);
587
588         //nodeBuilder = FlowUtils.createNodeBuilder(datapathId);
589         //flowBuilder = getEgressSfcClassifierFlow(datapathId, (short) 0, "test", nshUtils, (long) 2);
590         //flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.CONFIGURATION);
591         //assertNotNull("Could not find flow in config", flow);
592         //flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.OPERATIONAL);
593         //assertNotNull("Could not find flow in operational", flow);
594
595         LOG.info("***** Go look for flows *****");
596         Thread.sleep(30000);
597         assertTrue(southboundUtils.deleteBridge(connectionInfo, bridgeName));
598         Thread.sleep(1000);
599         assertTrue(southboundUtils.deleteBridge(connectionInfo, INTEGRATION_BRIDGE_NAME));
600         Thread.sleep(1000);
601         assertTrue(southboundUtils.disconnectOvsdbNode(connectionInfo));
602     }
603
604     private FlowBuilder getLocalInPortFlow(long dpidLong, String segmentationId, long inPort, short writeTable) {
605         MatchBuilder matchBuilder = new MatchBuilder();
606
607         FlowBuilder flowBuilder = new FlowBuilder();
608
609         flowBuilder.setMatch(MatchUtils.createInPortMatch(matchBuilder, dpidLong, inPort).build());
610         String flowId = "sfcIngress_" + segmentationId + "_" + inPort;
611         flowBuilder.setId(new FlowId(flowId));
612         FlowKey key = new FlowKey(new FlowId(flowId));
613         flowBuilder.setStrict(true);
614         flowBuilder.setBarrier(false);
615         flowBuilder.setTableId(writeTable);
616         flowBuilder.setKey(key);
617         flowBuilder.setFlowName(flowId);
618         flowBuilder.setHardTimeout(0);
619         flowBuilder.setIdleTimeout(0);
620         return flowBuilder;
621     }
622
623     public FlowBuilder getSfcClassifierFlow(long dpidLong, short writeTable, String ruleName, Matches match,
624                                              NshUtils nshHeader, long tunnelOfPort, MatchBuilder matchBuilder) {
625         FlowBuilder flowBuilder = new FlowBuilder();
626
627         flowBuilder.setMatch(matchBuilder.build());
628
629         String flowId = "sfcClass_" + ruleName + "_" + nshHeader.getNshNsp();
630         flowBuilder.setId(new FlowId(flowId));
631         FlowKey key = new FlowKey(new FlowId(flowId));
632         flowBuilder.setBarrier(true);
633         flowBuilder.setTableId(writeTable);
634         flowBuilder.setKey(key);
635         flowBuilder.setFlowName(flowId);
636         flowBuilder.setHardTimeout(0);
637         flowBuilder.setIdleTimeout(0);
638         return flowBuilder;
639     }
640
641     private FlowBuilder getEgressSfcClassifierFlow(long dpidLong, short writeTable, String ruleName,
642                                                    NshUtils nshHeader, long tunnelOfPort) {
643         FlowBuilder flowBuilder = new FlowBuilder();
644
645         MatchBuilder matchBuilder = new MatchBuilder();
646         flowBuilder.setMatch(MatchUtils.createInPortMatch(matchBuilder, dpidLong, tunnelOfPort).build());
647         flowBuilder.setMatch(
648                 MatchUtils.createTunnelIDMatch(matchBuilder, BigInteger.valueOf(nshHeader.getNshNsp())).build());
649         flowBuilder.setMatch(MatchUtils.addNxNspMatch(matchBuilder, nshHeader.getNshNsp()).build());
650         flowBuilder.setMatch(MatchUtils.addNxNsiMatch(matchBuilder, nshHeader.getNshNsi()).build());
651
652         String flowId = "egressSfcClass_" + ruleName + "_" + nshHeader.getNshNsp() + "_" + nshHeader.getNshNsi();
653         flowBuilder.setId(new FlowId(flowId));
654         FlowKey key = new FlowKey(new FlowId(flowId));
655         flowBuilder.setStrict(true);
656         flowBuilder.setBarrier(false);
657         flowBuilder.setTableId(writeTable);
658         flowBuilder.setKey(key);
659         flowBuilder.setFlowName(flowId);
660         flowBuilder.setHardTimeout(0);
661         flowBuilder.setIdleTimeout(0);
662         return flowBuilder;
663     }
664
665     private Flow getFlow (FlowBuilder flowBuilder, NodeBuilder nodeBuilder, LogicalDatastoreType store)
666             throws InterruptedException {
667         Flow flow = null;
668         for (int i = 0; i < 10; i++) {
669             flow = FlowUtils.getFlow(flowBuilder, nodeBuilder, dataBroker.newReadOnlyTransaction(), store);
670             if (flow != null) {
671                 LOG.info("getFlow: flow({}): {}", store, flow);
672                 break;
673             }
674             Thread.sleep(1000);
675         }
676         return flow;
677     }
678 }