2 * Copyright © 2015 Red Hat, Inc. and others. All rights reserved.
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
9 package org.opendaylight.ovsdb.openstack.netvirt.sfc;
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;
28 import java.io.IOException;
29 import java.math.BigInteger;
30 import java.util.ArrayList;
31 import java.util.List;
33 import java.util.Properties;
34 import java.util.concurrent.atomic.AtomicBoolean;
36 import org.junit.Assert;
37 import org.junit.Before;
38 import org.junit.Ignore;
39 import org.junit.Test;
40 import org.junit.runner.RunWith;
41 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
42 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
43 import org.opendaylight.controller.mdsal.it.base.AbstractMdsalTestBase;
44 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
45 import org.opendaylight.ovsdb.openstack.netvirt.api.Southbound;
46 import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.Service;
47 import org.opendaylight.ovsdb.openstack.netvirt.sfc.standalone.openflow13.SfcClassifier;
48 import org.opendaylight.ovsdb.openstack.netvirt.sfc.utils.AclUtils;
49 import org.opendaylight.ovsdb.openstack.netvirt.sfc.utils.ClassifierUtils;
50 import org.opendaylight.ovsdb.openstack.netvirt.sfc.utils.ServiceFunctionChainUtils;
51 import org.opendaylight.ovsdb.openstack.netvirt.sfc.utils.ServiceFunctionForwarderUtils;
52 import org.opendaylight.ovsdb.openstack.netvirt.sfc.utils.ServiceFunctionPathUtils;
53 import org.opendaylight.ovsdb.openstack.netvirt.sfc.utils.ServiceFunctionUtils;
54 import org.opendaylight.ovsdb.openstack.netvirt.sfc.utils.SfcUtils;
55 import org.opendaylight.ovsdb.southbound.SouthboundConstants;
56 import org.opendaylight.ovsdb.southbound.SouthboundUtil;
57 import org.opendaylight.ovsdb.utils.mdsal.openflow.FlowUtils;
58 import org.opendaylight.ovsdb.utils.mdsal.openflow.MatchUtils;
59 import org.opendaylight.ovsdb.utils.mdsal.utils.MdsalUtils;
60 import org.opendaylight.ovsdb.utils.servicehelper.ServiceHelper;
61 import org.opendaylight.ovsdb.utils.southbound.utils.SouthboundUtils;
62 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SftType;
63 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.ServiceFunctions;
64 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.ServiceFunctionsBuilder;
65 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.service.functions.ServiceFunction;
66 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.service.functions.ServiceFunctionBuilder;
67 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfc.rev140701.ServiceFunctionChains;
68 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfc.rev140701.ServiceFunctionChainsBuilder;
69 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfc.rev140701.service.function.chain.grouping.ServiceFunctionChain;
70 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfc.rev140701.service.function.chain.grouping.ServiceFunctionChainBuilder;
71 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfc.rev140701.service.function.chain.grouping.service.function.chain.SfcServiceFunction;
72 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfc.rev140701.service.function.chain.grouping.service.function.chain.SfcServiceFunctionBuilder;
73 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.ServiceFunctionForwarders;
74 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.ServiceFunctionForwardersBuilder;
75 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.ServiceFunctionForwarder;
76 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.ServiceFunctionForwarderBuilder;
77 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.ServiceFunctionPaths;
78 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.ServiceFunctionPathsBuilder;
79 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.service.function.paths.ServiceFunctionPath;
80 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.service.function.paths.ServiceFunctionPathBuilder;
81 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.AccessLists;
82 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.AccessListsBuilder;
83 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.AclBuilder;
84 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.AccessListEntriesBuilder;
85 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.access.list.entries.AceBuilder;
86 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;
87 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;
88 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;
89 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
90 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
91 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.Classifiers;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.ClassifiersBuilder;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.classifiers.ClassifierBuilder;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.classifiers.classifier.SffsBuilder;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.classifiers.classifier.sffs.SffBuilder;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.rev150105.Sfc;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.rev150105.SfcBuilder;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntry;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfo;
108 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
109 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
110 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
111 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
112 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
113 import org.opendaylight.yangtools.concepts.Builder;
114 import org.opendaylight.yangtools.yang.binding.DataObject;
115 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
116 import org.ops4j.pax.exam.Configuration;
117 import org.ops4j.pax.exam.Option;
118 import org.ops4j.pax.exam.junit.PaxExam;
119 import org.ops4j.pax.exam.karaf.options.LogLevelOption;
120 import org.ops4j.pax.exam.karaf.options.LogLevelOption.LogLevel;
121 import org.ops4j.pax.exam.options.MavenUrlReference;
122 import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
123 import org.ops4j.pax.exam.spi.reactors.PerClass;
124 import org.slf4j.Logger;
125 import org.slf4j.LoggerFactory;
127 import com.google.common.collect.Maps;
129 @RunWith(PaxExam.class)
130 @ExamReactorStrategy(PerClass.class)
131 public class NetvirtSfcIT extends AbstractMdsalTestBase {
132 private static final Logger LOG = LoggerFactory.getLogger(NetvirtSfcIT.class);
133 private static AclUtils aclUtils = new AclUtils();
134 private static ClassifierUtils classifierUtils = new ClassifierUtils();
135 private static SfcUtils sfcUtils = new SfcUtils();
136 private static ServiceFunctionUtils serviceFunctionUtils = new ServiceFunctionUtils();
137 private static ServiceFunctionForwarderUtils serviceFunctionForwarderUtils = new ServiceFunctionForwarderUtils();
138 private static ServiceFunctionChainUtils serviceFunctionChainUtils = new ServiceFunctionChainUtils();
139 private static ServiceFunctionPathUtils serviceFunctionPathUtils = new ServiceFunctionPathUtils();
140 private static MdsalUtils mdsalUtils;
141 private static AtomicBoolean setup = new AtomicBoolean(false);
142 private static SouthboundUtils southboundUtils;
143 private static String addressStr;
144 private static String portStr;
145 private static String connectionType;
146 private static Southbound southbound;
147 private static DataBroker dataBroker;
148 public static final String CONTROLLER_IPADDRESS = "ovsdb.controller.address";
149 public static final String SERVER_IPADDRESS = "ovsdbserver.ipaddress";
150 public static final String SERVER_PORT = "ovsdbserver.port";
151 public static final String CONNECTION_TYPE = "ovsdbserver.connection";
152 public static final String CONNECTION_TYPE_ACTIVE = "active";
153 public static final String CONNECTION_TYPE_PASSIVE = "passive";
154 public static final String DEFAULT_SERVER_PORT = "6640";
155 public static final String INTEGRATION_BRIDGE_NAME = "br-int";
156 private static final String NETVIRT_TOPOLOGY_ID = "netvirt:1";
157 private static final String OVSDB_TRACE = "ovsdb.trace";
158 private static final String SF1NAME = "firewall-72";
159 private static final String SF2NAME = "dpi-72";
160 private static final String SF1IP = "10.2.1.1";//"192.168.50.70";//"192.168.120.31";
161 private static final String SF2IP = "10.2.1.2";
162 private static final String SF1DPLNAME = "sf1";
163 private static final String SF2DPLNAME = "sf2";
164 private static final String SFF1IP = "127.0.0.1"; //"192.168.1.129"
165 private static final String SFF2IP = "192.168.1.129";//"127.0.0.1";
166 private static final String SFF1NAME = "SFF1";
167 private static final String SFF2NAME = "SFF2";
168 private static final String SFFDPL1NAME = "vxgpe";
169 private static final String SFFDPL2NAME = "vxgpe";
170 private static final String SN1NAME = "OVSDB1";
171 private static final String SN2NAME = "OVSDB2";
172 private static final String BRIDGE1NAME= "br-int";
173 private static final String BRIDGE2NAME= "br-int";
174 private static final String ACLNAME= "httpAcl";
175 private static final String SFCNAME = "SFC";
176 private static final int GPEPORT = 6633;
179 public String getModuleName() {
180 return "netvirt-sfc";
184 public String getInstanceName() {
185 return "netvirt-sfc-default";
189 public MavenUrlReference getFeatureRepo() {
191 .groupId("org.opendaylight.ovsdb")
192 .artifactId("openstack.net-virt-sfc-features-test")
193 .classifier("features")
195 .versionAsInProject();
199 public String getFeatureName() {
200 return "odl-ovsdb-sfc-test";
205 public Option[] config() {
206 Option[] parentOptions = super.config();
207 Option[] propertiesOptions = getPropertiesOptions();
208 Option[] otherOptions = getOtherOptions();
209 Option[] options = new Option[parentOptions.length + propertiesOptions.length + otherOptions.length];
210 System.arraycopy(parentOptions, 0, options, 0, parentOptions.length);
211 System.arraycopy(propertiesOptions, 0, options, parentOptions.length, propertiesOptions.length);
212 System.arraycopy(otherOptions, 0, options, parentOptions.length + propertiesOptions.length,
213 otherOptions.length);
217 private Option[] getOtherOptions() {
218 return new Option[] {
220 mavenBundle("org.opendaylight.ovsdb", "utils.mdsal-openflow")
221 .version(asInProject())
223 configureConsole().startLocalConsole(),
224 vmOption("-javaagent:../jars/org.jacoco.agent.jar=destfile=../../jacoco-it.exec"),
229 public Option[] getPropertiesOptions() {
230 return new Option[] {
231 propagateSystemProperties(SERVER_IPADDRESS, SERVER_PORT, CONNECTION_TYPE,
232 CONTROLLER_IPADDRESS, OVSDB_TRACE),
237 public Option getLoggingOption() {
239 when(Boolean.getBoolean(OVSDB_TRACE)).useOptions(
240 editConfigurationFilePut(ORG_OPS4J_PAX_LOGGING_CFG,
241 "log4j.logger.org.opendaylight.ovsdb",
242 LogLevelOption.LogLevel.TRACE.name())),
243 //editConfigurationFilePut(ORG_OPS4J_PAX_LOGGING_CFG,
244 // "log4j.logger.org.opendaylight.ovsdb",
245 // LogLevelOption.LogLevel.TRACE.name()),
246 editConfigurationFilePut(ORG_OPS4J_PAX_LOGGING_CFG,
247 logConfiguration(NetvirtSfcIT.class),
248 LogLevel.INFO.name()),
249 editConfigurationFilePut(ORG_OPS4J_PAX_LOGGING_CFG,
250 "log4j.logger.org.opendaylight.ovsdb.openstack.netvirt.sfc",
251 LogLevel.TRACE.name()),
252 editConfigurationFilePut(ORG_OPS4J_PAX_LOGGING_CFG,
253 "log4j.logger.org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13",
254 LogLevel.TRACE.name()),
255 editConfigurationFilePut(ORG_OPS4J_PAX_LOGGING_CFG,
256 "log4j.logger.org.opendaylight.sfc",
257 LogLevel.TRACE.name()),
258 super.getLoggingOption());
261 protected String usage() {
262 return "Integration Test needs a valid connection configuration as follows :\n"
263 + "active connection : mvn -Dovsdbserver.ipaddress=x.x.x.x -Dovsdbserver.port=yyyy verify\n"
264 + "passive connection : mvn -Dovsdbserver.connection=passive verify\n";
267 private void getProperties() {
268 Properties props = System.getProperties();
269 addressStr = props.getProperty(SERVER_IPADDRESS);
270 portStr = props.getProperty(SERVER_PORT, DEFAULT_SERVER_PORT);
271 connectionType = props.getProperty(CONNECTION_TYPE, "active");
272 LOG.info("setUp: Using the following properties: mode= {}, ip:port= {}:{}",
273 connectionType, addressStr, portStr);
274 if (connectionType.equalsIgnoreCase(CONNECTION_TYPE_ACTIVE)) {
275 if (addressStr == null) {
279 LOG.info("getProperties {}: {}", OVSDB_TRACE, props.getProperty(OVSDB_TRACE));
284 public void setup() {
286 LOG.info("Skipping setUp, already initialized");
293 } catch (Exception e) {
299 dataBroker = getDatabroker(getProviderContext());
300 mdsalUtils = new MdsalUtils(dataBroker);
301 assertNotNull("mdsalUtils should not be null", mdsalUtils);
302 southboundUtils = new SouthboundUtils(mdsalUtils);
303 assertTrue("Did not find " + NETVIRT_TOPOLOGY_ID, getNetvirtTopology());
304 southbound = (Southbound) ServiceHelper.getGlobalInstance(Southbound.class, this);
305 assertNotNull("southbound should not be null", southbound);
309 private ProviderContext getProviderContext() {
310 ProviderContext providerContext = null;
311 for (int i=0; i < 60; i++) {
312 providerContext = getSession();
313 if (providerContext != null) {
318 } catch (InterruptedException e) {
323 assertNotNull("providercontext should not be null", providerContext);
324 /* One more second to let the provider finish initialization */
327 } catch (InterruptedException e) {
330 return providerContext;
333 private DataBroker getDatabroker(ProviderContext providerContext) {
334 DataBroker dataBroker = providerContext.getSALService(DataBroker.class);
335 assertNotNull("dataBroker should not be null", dataBroker);
339 private Boolean getNetvirtTopology() {
340 LOG.info("getNetvirtTopology: looking for {}...", NETVIRT_TOPOLOGY_ID);
341 Boolean found = false;
342 final TopologyId topologyId = new TopologyId(new Uri(NETVIRT_TOPOLOGY_ID));
343 InstanceIdentifier<Topology> path =
344 InstanceIdentifier.create(NetworkTopology.class).child(Topology.class, new TopologyKey(topologyId));
345 for (int i = 0; i < 60; i++) {
346 Topology topology = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, path);
347 if (topology != null) {
348 LOG.info("getNetvirtTopology: found {}...", NETVIRT_TOPOLOGY_ID);
352 LOG.info("getNetvirtTopology: still looking ({})...", i);
355 } catch (InterruptedException e) {
364 public void testNetvirtSfcFeatureLoad() {
368 private AccessListsBuilder accessListsBuilder() {
369 MatchesBuilder matchesBuilder = aclUtils.matchesBuilder(new MatchesBuilder(), 80);
370 LOG.info("Matches: {}", matchesBuilder.build());
371 //ActionsBuilder actionsBuilder = aclUtils.actionsBuilder(new ActionsBuilder(), Boolean.TRUE);
372 ActionsBuilder actionsBuilder = aclUtils.actionsBuilder(new ActionsBuilder(), SFCNAME);
373 AceBuilder accessListEntryBuilder =
374 aclUtils.aceBuilder(new AceBuilder(), "httpRule", matchesBuilder, actionsBuilder);
375 AccessListEntriesBuilder accessListEntriesBuilder =
376 aclUtils.accessListEntriesBuidler(new AccessListEntriesBuilder(), accessListEntryBuilder);
377 AclBuilder accessListBuilder =
378 aclUtils.aclBuilder(new AclBuilder(), ACLNAME, accessListEntriesBuilder);
379 AccessListsBuilder accessListsBuilder =
380 aclUtils.accesslistsbuilder(new AccessListsBuilder(), accessListBuilder);
381 LOG.info("AccessLists: {}", accessListsBuilder.build());
382 return accessListsBuilder;
386 public void testAccessLists() throws InterruptedException {
387 testModel(accessListsBuilder(), AccessLists.class, 0);
390 private ClassifiersBuilder classifiersBuilder() {
391 SffBuilder sffBuilder = classifierUtils.sffBuilder(new SffBuilder(), SFF1NAME);
392 SffsBuilder sffsBuilder = classifierUtils.sffsBuilder(new SffsBuilder(), sffBuilder);
393 ClassifierBuilder classifierBuilder = classifierUtils.classifierBuilder(new ClassifierBuilder(),
394 "classifierName", ACLNAME, sffsBuilder);
395 ClassifiersBuilder classifiersBuilder = classifierUtils.ClassifiersBuilder(new ClassifiersBuilder(),
397 LOG.info("Classifiers: {}", classifiersBuilder.build());
398 return classifiersBuilder;
402 public void testClassifiers() throws InterruptedException {
403 testModel(classifiersBuilder(), Classifiers.class, 0);
406 private SfcBuilder netvirtSfcBuilder() {
407 return sfcUtils.sfcBuilder(new SfcBuilder(), "sfc");
411 public void testNetvirtSfcModel() throws InterruptedException {
412 testModel(netvirtSfcBuilder(), Sfc.class, 0);
415 private <T extends DataObject> void testModelPut(Builder<T> builder, Class<T> clazz) {
416 InstanceIdentifier<T> path = InstanceIdentifier.create(clazz);
417 assertTrue(mdsalUtils.put(LogicalDatastoreType.CONFIGURATION, path, builder.build()));
418 T result = mdsalUtils.read(LogicalDatastoreType.CONFIGURATION, path);
419 assertNotNull(clazz.getSimpleName() + " should not be null", result);
422 private <T extends DataObject> void testModelDelete(Builder<T> builder, Class<T> clazz)
423 throws InterruptedException {
424 InstanceIdentifier<T> path = InstanceIdentifier.create(clazz);
425 assertTrue("Failed to remove " + clazz.getSimpleName(),
426 mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, path));
427 T result = mdsalUtils.read(LogicalDatastoreType.CONFIGURATION, path);
428 assertNull(clazz.getSimpleName() + " should be null", result);
431 private <T extends DataObject> void testModel(Builder<T> builder, Class<T> clazz, long wait)
432 throws InterruptedException {
433 testModelPut(builder, clazz);
435 testModelDelete(builder, clazz);
438 private ServiceFunctionsBuilder serviceFunctionsBuilder() {
439 String sf1Name = SF1NAME;
440 String sf1Ip = SF1IP;
441 String sff1Ip = SF1IP;
442 String sff1Name = SFF1NAME;
443 String sf1DplName = SF1DPLNAME;
444 String sn1Name = SN1NAME;
445 String bridge1Name= BRIDGE1NAME;
446 String sf2Name = SF2NAME;
447 String sf2Ip = SF2IP;
448 String sff2Ip = SF2IP;
449 String sff2Name = SFF2NAME;
450 String sf2DplName = SF2DPLNAME;
451 String sn2Name = SN2NAME;
452 String bridge2Name= BRIDGE2NAME;
455 ServiceFunctionBuilder serviceFunctionBuilder =
456 serviceFunctionUtils.serviceFunctionBuilder(sf1Ip, port, sf1DplName, sff1Name, sf1Name);
457 List<ServiceFunction> serviceFunctionList = serviceFunctionUtils.list(
458 new ArrayList<ServiceFunction>(), serviceFunctionBuilder);
460 //serviceFunctionBuilder =
461 // serviceFunctionUtils.serviceFunctionBuilder(sf2Ip, port, sffDpl2Name, sff2Name, sf2Name);
462 //serviceFunctionList = serviceFunctionUtils.list(
463 // serviceFunctionList, serviceFunctionBuilder);
465 ServiceFunctionsBuilder serviceFunctionsBuilder =
466 serviceFunctionUtils.serviceFunctionsBuilder(new ServiceFunctionsBuilder(),
467 serviceFunctionList);
468 LOG.info("ServiceFunctions: {}", serviceFunctionsBuilder.build());
469 return serviceFunctionsBuilder;
472 private ServiceFunctionForwardersBuilder serviceFunctionForwardersBuilder() {
473 String sf1Name = SF1NAME;
474 String sf1Ip = SF1IP;
475 String sff1Ip = SFF1IP;
476 String sff1Name = SFF1NAME;
477 String sffDpl1Name = SFFDPL1NAME;
478 String sn1Name = SN1NAME;
479 String bridge1Name= BRIDGE1NAME;
480 String sf2Name = SF2NAME;
481 String sf2Ip = SF2IP;
482 String sff2Ip = SFF2IP;
483 String sff2Name = SFF2NAME;
484 String sffDpl2Name = SFFDPL2NAME;
485 String sn2Name = SN2NAME;
486 String bridge2Name= BRIDGE2NAME;
487 String aclName = ACLNAME;
490 ServiceFunctionForwarderBuilder serviceFunctionForwarderBuilder =
491 serviceFunctionForwarderUtils.serviceFunctionForwarderBuilder(
492 sff1Name, sff1Ip, port, sffDpl1Name, sf1Ip, sn1Name, bridge1Name);
493 List<ServiceFunctionForwarder> serviceFunctionForwarderList = serviceFunctionForwarderUtils.list(
494 new ArrayList<ServiceFunctionForwarder>(), serviceFunctionForwarderBuilder);
496 //serviceFunctionForwarderBuilder =
497 // serviceFunctionForwarderUtils.serviceFunctionForwarderBuilder(
498 // sff2Name, sff2Ip, port, sffDpl2Name, sf2Name, sff2Ip, sn2Name, bridge2Name, Dpi.class);
499 //serviceFunctionForwarderList = serviceFunctionForwarderUtils.list(
500 // serviceFunctionForwarderList, serviceFunctionForwarderBuilder);
502 ServiceFunctionForwardersBuilder serviceFunctionForwardersBuilder =
503 serviceFunctionForwarderUtils.serviceFunctionForwardersBuilder(
504 new ServiceFunctionForwardersBuilder(), serviceFunctionForwarderList);
505 LOG.info("ServiceFunctionForwarders: {}", serviceFunctionForwardersBuilder.build());
506 return serviceFunctionForwardersBuilder;
509 private ServiceFunctionChainsBuilder serviceFunctionChainsBuilder() {
510 String sf1Name = "firewall-abstract1";
511 SftType sfType = new SftType("firewall");
512 String sfcName = SFCNAME;
514 SfcServiceFunctionBuilder sfcServiceFunctionBuilder = serviceFunctionChainUtils.sfcServiceFunctionBuilder(
515 new SfcServiceFunctionBuilder(), sf1Name, sfType);
516 List<SfcServiceFunction> sfcServiceFunctionList =
517 serviceFunctionChainUtils.list(new ArrayList<SfcServiceFunction>(), sfcServiceFunctionBuilder);
519 //sfcServiceFunctionBuilder = serviceFunctionChainUtils.sfcServiceFunctionBuilder(
520 // sfcServiceFunctionBuilder, sf2Name, Dpi.class);
521 //sfcServiceFunctionList = serviceFunctionChainUtils.list(sfcServiceFunctionList, sfcServiceFunctionBuilder);
523 ServiceFunctionChainBuilder serviceFunctionChainBuilder =
524 serviceFunctionChainUtils.serviceFunctionChainBuilder(
525 new ServiceFunctionChainBuilder(), sfcName, false, sfcServiceFunctionList);
526 ServiceFunctionChainsBuilder serviceFunctionChainsBuilder =
527 serviceFunctionChainUtils.serviceFunctionChainsBuilder(
528 new ServiceFunctionChainsBuilder(),
529 serviceFunctionChainUtils.list(new ArrayList<ServiceFunctionChain>(),
530 serviceFunctionChainBuilder));
531 LOG.info("ServiceFunctionChains: {}", serviceFunctionChainBuilder.build());
532 return serviceFunctionChainsBuilder;
535 private ServiceFunctionPathsBuilder serviceFunctionPathsBuilder() {
536 String sfpName = "SFC-Path";
537 String sfcName = "SFC";
538 short startingIndex = 255;
540 ServiceFunctionPathBuilder serviceFunctionPathBuilder =
541 serviceFunctionPathUtils.serviceFunctionPathBuilder(
542 new ServiceFunctionPathBuilder(), sfpName, sfcName, startingIndex, false);
543 ServiceFunctionPathsBuilder serviceFunctionPathsBuilder =
544 serviceFunctionPathUtils.serviceFunctionPathsBuilder(
545 serviceFunctionPathUtils.list(new ArrayList<ServiceFunctionPath>(),
546 serviceFunctionPathBuilder));
547 LOG.info("ServiceFunctionPaths: {}", serviceFunctionPathsBuilder.build());
548 return serviceFunctionPathsBuilder;
552 public void testSfcModel() throws InterruptedException {
553 testModel(serviceFunctionsBuilder(), ServiceFunctions.class, 3000);
554 testModel(serviceFunctionForwardersBuilder(), ServiceFunctionForwarders.class, 3000);
555 testModel(serviceFunctionChainsBuilder(), ServiceFunctionChains.class, 3000);
556 testModel(serviceFunctionPathsBuilder(), ServiceFunctionPaths.class, 3000);
560 public void testSfcModels() throws InterruptedException {
561 String bridgeName = INTEGRATION_BRIDGE_NAME;
562 ConnectionInfo connectionInfo = southboundUtils.getConnectionInfo(addressStr, portStr);
563 assertNotNull("connection failed", southboundUtils.connectOvsdbNode(connectionInfo));
564 Node ovsdbNode = southboundUtils.getOvsdbNode(connectionInfo);
565 assertNotNull("node is not connected", ovsdbNode);
568 Node bridgeNode = southbound.getBridgeNode(ovsdbNode, bridgeName);
569 assertNotNull("bridge " + bridgeName + " was not found", bridgeNode);
570 long datapathId = southbound.getDataPathId(bridgeNode);
572 Map<String, String> externalIds = Maps.newHashMap();
573 externalIds.put("attached-mac", "f6:00:00:0f:00:01");
574 southboundUtils.addTerminationPoint(bridgeNode, null, SF1DPLNAME, "internal", null, externalIds);
575 southboundUtils.addTerminationPoint(bridgeNode, null, "vm1", "internal");
576 southboundUtils.addTerminationPoint(bridgeNode, null, "vm2", "internal");
577 Map<String, String> options = Maps.newHashMap();
578 options.put("key", "flow");
579 options.put("remote_ip", "192.168.120.32");
580 southboundUtils.addTerminationPoint(bridgeNode, null, "vx", "vxlan", options, null);
583 testModelPut(serviceFunctionsBuilder(), ServiceFunctions.class);
584 testModelPut(serviceFunctionForwardersBuilder(), ServiceFunctionForwarders.class);
585 testModelPut(serviceFunctionChainsBuilder(), ServiceFunctionChains.class);
586 testModelPut(serviceFunctionPathsBuilder(), ServiceFunctionPaths.class);
590 testModelPut(accessListsBuilder(), AccessLists.class);
591 testModelPut(classifiersBuilder(), Classifiers.class);
595 ISfcClassifierService sfcClassifierService = (ISfcClassifierService) ServiceHelper.getGlobalInstance(ISfcClassifierService.class, this);
596 LOG.info("SfcClassifierService: {}", sfcClassifierService);
598 //sfcClassifierService.programIngressClassifier(datapathId);
600 NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(datapathId);
601 FlowBuilder flowBuilder = getSfcIngressClassifierFlowBuilder();
602 Flow flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.CONFIGURATION);
603 assertNotNull("Could not find flow in config", flow);
604 flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.OPERATIONAL);
605 assertNotNull("Could not find flow in operational", flow);
607 assertTrue(southboundUtils.deleteBridge(connectionInfo, bridgeName));
609 assertTrue(southboundUtils.disconnectOvsdbNode(connectionInfo));
613 * Connect to an ovsdb node. Netvirt should add br-int, add the controller address
614 * and program the pipeline flows.
617 public void testNetvirtSfc() throws InterruptedException {
618 String bridgeName = INTEGRATION_BRIDGE_NAME;
619 ConnectionInfo connectionInfo = southboundUtils.getConnectionInfo(addressStr, portStr);
620 assertNotNull("connection failed", southboundUtils.connectOvsdbNode(connectionInfo));
621 Node ovsdbNode = southboundUtils.getOvsdbNode(connectionInfo);
622 assertNotNull("node is not connected", ovsdbNode);
623 ControllerEntry controllerEntry;
624 // Loop 10s checking if the controller was added
625 for (int i = 0; i < 10; i++) {
626 ovsdbNode = southboundUtils.getOvsdbNode(connectionInfo);
627 assertNotNull("ovsdb node not found", ovsdbNode);
628 String controllerTarget = SouthboundUtil.getControllerTarget(ovsdbNode);
629 assertNotNull("Failed to get controller target", controllerTarget);
630 OvsdbBridgeAugmentation bridge = southboundUtils.getBridge(connectionInfo, bridgeName);
631 if (bridge != null) {
632 assertNotNull("Failed to read bridge", bridge);
633 assertNotNull("Failed to extract controllerEntry", bridge.getControllerEntry());
634 controllerEntry = bridge.getControllerEntry().iterator().next();
635 assertEquals(controllerTarget, controllerEntry.getTarget().getValue());
636 if (controllerEntry.isIsConnected()) {
637 Assert.assertTrue("switch is not connected to the controller", controllerEntry.isIsConnected());
644 Node bridgeNode = southbound.getBridgeNode(ovsdbNode, bridgeName);
645 assertNotNull("bridge " + bridgeName + " was not found", bridgeNode);
646 long datapathId = southbound.getDataPathId(bridgeNode);
648 //Thread.sleep(10000);
650 NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(datapathId);
651 FlowBuilder flowBuilder = FlowUtils.getPipelineFlow(Service.SFC_CLASSIFIER.getTable(), (short)0);
652 Flow flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.CONFIGURATION);
653 assertNotNull("Could not find flow in config", flow);
654 flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.OPERATIONAL);
655 assertNotNull("Could not find flow in operational", flow);
657 assertTrue(southboundUtils.deleteBridge(connectionInfo, bridgeName));
659 assertTrue(southboundUtils.disconnectOvsdbNode(connectionInfo));
664 public void testStandalone() throws InterruptedException {
665 String bridgeName = "sw1";
666 ConnectionInfo connectionInfo = southboundUtils.getConnectionInfo(addressStr, portStr);
667 assertNotNull("connection failed", southboundUtils.connectOvsdbNode(connectionInfo));
668 Node ovsdbNode = southboundUtils.getOvsdbNode(connectionInfo);
669 assertNotNull("node is not connected", ovsdbNode);
670 String controllerTarget = "tcp:192.168.50.1:6653";
671 List<ControllerEntry> setControllerEntry = southboundUtils.createControllerEntry(controllerTarget);
672 Assert.assertTrue(southboundUtils.addBridge(connectionInfo, null, bridgeName, null, true,
673 SouthboundConstants.OVSDB_FAIL_MODE_MAP.inverse().get("secure"), true, null, null,
674 setControllerEntry, null, "00:00:00:00:00:00:00:01"));
675 // Loop 10s checking if the controller was added
676 for (int i = 0; i < 10; i++) {
677 ovsdbNode = southboundUtils.getOvsdbNode(connectionInfo);
678 assertNotNull("ovsdb node not found", ovsdbNode);
679 assertNotNull("Failed to get controller target", controllerTarget);
680 OvsdbBridgeAugmentation bridge = southboundUtils.getBridge(connectionInfo, bridgeName);
681 assertNotNull(bridge);
682 assertNotNull(bridge.getControllerEntry());
683 ControllerEntry controllerEntry = bridge.getControllerEntry().iterator().next();
684 assertEquals(controllerTarget, controllerEntry.getTarget().getValue());
685 if (controllerEntry.isIsConnected()) {
686 Assert.assertTrue(controllerEntry.isIsConnected());
692 Node bridgeNode = southbound.getBridgeNode(ovsdbNode, bridgeName);
693 assertNotNull("bridge " + bridgeName + " was not found", bridgeNode);
694 long datapathId = southbound.getDataPathId(bridgeNode);
696 SfcClassifier sfcClassifier = new SfcClassifier(dataBroker, southbound, mdsalUtils);
697 //sfcClassifier.programLocalInPort(datapathId, "4096", (long)1, (short)0, (short)50, true);
699 NshUtils nshUtils = new NshUtils(new Ipv4Address("192.168.50.71"), new PortNumber(6633),
700 (long)10, (short)255, (long)4096, (long)4096);
701 MatchesBuilder matchesBuilder = aclUtils.matchesBuilder(new MatchesBuilder(), 80);
702 sfcClassifier.programSfcClassiferFlows(datapathId, (short)0, "test", matchesBuilder.build(),
703 nshUtils, (long)2, true);
705 nshUtils = new NshUtils(null, null, (long)10, (short)253, 0, 0);
706 //sfcClassifier.programEgressSfcClassiferFlows(datapathId, (short)0, "test", null,
707 // nshUtils, (long)2, (long)3, true);
711 //} catch (IOException e) {
712 // e.printStackTrace();
715 //NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(datapathId);
716 //FlowBuilder flowBuilder = getLocalInPortFlow(datapathId, "4096", (long) 1, (short) 0);
717 //Flow flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.CONFIGURATION);
718 //assertNotNull("Could not find flow in config", flow);
719 //flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.OPERATIONAL);
720 //assertNotNull("Could not find flow in operational", flow);
722 MatchBuilder matchBuilder = sfcClassifier.buildMatch(matchesBuilder.build());
723 NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(datapathId);
724 FlowBuilder flowBuilder = getSfcClassifierFlow(datapathId, (short) 0, "test", null,
725 nshUtils, (long) 2, matchBuilder);
726 Flow flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.CONFIGURATION);
727 assertNotNull("Could not find flow in config", flow);
728 flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.OPERATIONAL);
729 assertNotNull("Could not find flow in operational", flow);
731 //nodeBuilder = FlowUtils.createNodeBuilder(datapathId);
732 //flowBuilder = getEgressSfcClassifierFlow(datapathId, (short) 0, "test", nshUtils, (long) 2);
733 //flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.CONFIGURATION);
734 //assertNotNull("Could not find flow in config", flow);
735 //flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.OPERATIONAL);
736 //assertNotNull("Could not find flow in operational", flow);
738 LOG.info("***** Go look for flows *****");
740 assertTrue(southboundUtils.deleteBridge(connectionInfo, bridgeName));
742 assertTrue(southboundUtils.deleteBridge(connectionInfo, INTEGRATION_BRIDGE_NAME));
744 assertTrue(southboundUtils.disconnectOvsdbNode(connectionInfo));
747 private FlowBuilder getLocalInPortFlow(long dpidLong, String segmentationId, long inPort, short writeTable) {
748 MatchBuilder matchBuilder = new MatchBuilder();
750 FlowBuilder flowBuilder = new FlowBuilder();
752 flowBuilder.setMatch(MatchUtils.createInPortMatch(matchBuilder, dpidLong, inPort).build());
753 String flowId = "sfcIngress_" + segmentationId + "_" + inPort;
754 flowBuilder.setId(new FlowId(flowId));
755 FlowKey key = new FlowKey(new FlowId(flowId));
756 flowBuilder.setStrict(true);
757 flowBuilder.setBarrier(false);
758 flowBuilder.setTableId(writeTable);
759 flowBuilder.setKey(key);
760 flowBuilder.setFlowName(flowId);
761 flowBuilder.setHardTimeout(0);
762 flowBuilder.setIdleTimeout(0);
766 public FlowBuilder getSfcClassifierFlow(long dpidLong, short writeTable, String ruleName, Matches match,
767 NshUtils nshHeader, long tunnelOfPort, MatchBuilder matchBuilder) {
768 FlowBuilder flowBuilder = new FlowBuilder();
770 flowBuilder.setMatch(matchBuilder.build());
772 String flowId = "sfcClass_" + ruleName + "_" + nshHeader.getNshNsp();
773 flowBuilder.setId(new FlowId(flowId));
774 FlowKey key = new FlowKey(new FlowId(flowId));
775 flowBuilder.setBarrier(true);
776 flowBuilder.setTableId(writeTable);
777 flowBuilder.setKey(key);
778 flowBuilder.setFlowName(flowId);
779 flowBuilder.setHardTimeout(0);
780 flowBuilder.setIdleTimeout(0);
784 private FlowBuilder getEgressSfcClassifierFlow(long dpidLong, short writeTable, String ruleName,
785 NshUtils nshHeader, long tunnelOfPort) {
786 FlowBuilder flowBuilder = new FlowBuilder();
788 MatchBuilder matchBuilder = new MatchBuilder();
789 flowBuilder.setMatch(MatchUtils.createInPortMatch(matchBuilder, dpidLong, tunnelOfPort).build());
790 flowBuilder.setMatch(
791 MatchUtils.createTunnelIDMatch(matchBuilder, BigInteger.valueOf(nshHeader.getNshNsp())).build());
792 flowBuilder.setMatch(MatchUtils.addNxNspMatch(matchBuilder, nshHeader.getNshNsp()).build());
793 flowBuilder.setMatch(MatchUtils.addNxNsiMatch(matchBuilder, nshHeader.getNshNsi()).build());
795 String flowId = "egressSfcClass_" + ruleName + "_" + nshHeader.getNshNsp() + "_" + nshHeader.getNshNsi();
796 flowBuilder.setId(new FlowId(flowId));
797 FlowKey key = new FlowKey(new FlowId(flowId));
798 flowBuilder.setStrict(true);
799 flowBuilder.setBarrier(false);
800 flowBuilder.setTableId(writeTable);
801 flowBuilder.setKey(key);
802 flowBuilder.setFlowName(flowId);
803 flowBuilder.setHardTimeout(0);
804 flowBuilder.setIdleTimeout(0);
808 private FlowBuilder getSfcIngressClassifierFlowBuilder() {
809 FlowBuilder flowBuilder = new FlowBuilder();
810 String flowId = "sfcClass_" + "httpRule";
811 flowBuilder.setId(new FlowId(flowId));
812 FlowKey key = new FlowKey(new FlowId(flowId));
813 flowBuilder.setKey(key);
814 flowBuilder.setFlowName(flowId);
815 flowBuilder.setTableId((short)10);
819 private Flow getFlow (FlowBuilder flowBuilder, NodeBuilder nodeBuilder, LogicalDatastoreType store)
820 throws InterruptedException {
822 for (int i = 0; i < 10; i++) {
823 flow = FlowUtils.getFlow(flowBuilder, nodeBuilder, dataBroker.newReadOnlyTransaction(), store);
825 LOG.info("getFlow: flow: {}: {}", store, flow);
833 private void readwait() {
836 } catch (IOException e) {