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.it;
11 import static org.junit.Assert.assertNotEquals;
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.util.ArrayList;
30 import java.util.HashSet;
31 import java.util.Iterator;
32 import java.util.List;
34 import java.util.Properties;
36 import java.util.concurrent.atomic.AtomicBoolean;
38 import org.junit.After;
39 import org.junit.Assert;
40 import org.junit.Before;
41 import org.junit.Ignore;
42 import org.junit.Test;
43 import org.junit.runner.RunWith;
44 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
45 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
46 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
47 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
48 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
49 import org.opendaylight.controller.mdsal.it.base.AbstractMdsalTestBase;
50 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
51 import org.opendaylight.ovsdb.openstack.netvirt.api.BridgeConfigurationManager;
52 import org.opendaylight.ovsdb.openstack.netvirt.api.Southbound;
53 import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.PipelineOrchestrator;
54 import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.Service;
55 import org.opendaylight.ovsdb.openstack.netvirt.sfc.NshUtils;
56 import org.opendaylight.ovsdb.openstack.netvirt.sfc.SfcUtils;
57 import org.opendaylight.ovsdb.openstack.netvirt.sfc.it.utils.RenderedServicePathUtils;
58 import org.opendaylight.ovsdb.openstack.netvirt.sfc.standalone.openflow13.SfcClassifier;
59 import org.opendaylight.ovsdb.openstack.netvirt.sfc.it.utils.AclUtils;
60 import org.opendaylight.ovsdb.openstack.netvirt.sfc.it.utils.ClassifierUtils;
61 import org.opendaylight.ovsdb.openstack.netvirt.sfc.it.utils.NetvirtConfigUtils;
62 import org.opendaylight.ovsdb.openstack.netvirt.sfc.it.utils.ServiceFunctionChainUtils;
63 import org.opendaylight.ovsdb.openstack.netvirt.sfc.it.utils.ServiceFunctionForwarderUtils;
64 import org.opendaylight.ovsdb.openstack.netvirt.sfc.it.utils.ServiceFunctionPathUtils;
65 import org.opendaylight.ovsdb.openstack.netvirt.sfc.it.utils.ServiceFunctionUtils;
66 import org.opendaylight.ovsdb.openstack.netvirt.sfc.it.utils.SfcConfigUtils;
67 import org.opendaylight.ovsdb.openstack.netvirt.sfc.it.utils.NetvirtSfcUtils;
68 import org.opendaylight.ovsdb.openstack.netvirt.sfc.workaround.services.FlowNames;
69 import org.opendaylight.ovsdb.southbound.SouthboundConstants;
70 import org.opendaylight.ovsdb.utils.mdsal.openflow.FlowUtils;
71 import org.opendaylight.ovsdb.utils.mdsal.utils.MdsalUtils;
72 import org.opendaylight.ovsdb.utils.servicehelper.ServiceHelper;
73 import org.opendaylight.ovsdb.utils.southbound.utils.SouthboundUtils;
74 import org.opendaylight.sfc.provider.api.SfcProviderRenderedPathAPI;
75 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.RspName;
76 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SftType;
77 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.CreateRenderedPathInputBuilder;
78 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.RenderedServicePaths;
79 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.paths.RenderedServicePath;
80 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.paths.RenderedServicePathKey;
81 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.paths.rendered.service.path.RenderedServicePathHop;
82 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.ServiceFunctions;
83 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.ServiceFunctionsBuilder;
84 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.service.functions.ServiceFunction;
85 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.service.functions.ServiceFunctionBuilder;
86 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfc.rev140701.ServiceFunctionChains;
87 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfc.rev140701.ServiceFunctionChainsBuilder;
88 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfc.rev140701.service.function.chain.grouping.ServiceFunctionChain;
89 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfc.rev140701.service.function.chain.grouping.ServiceFunctionChainBuilder;
90 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfc.rev140701.service.function.chain.grouping.service.function.chain.SfcServiceFunction;
91 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfc.rev140701.service.function.chain.grouping.service.function.chain.SfcServiceFunctionBuilder;
92 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.ServiceFunctionForwarders;
93 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.ServiceFunctionForwardersBuilder;
94 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.ServiceFunctionForwarder;
95 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.ServiceFunctionForwarderBuilder;
96 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.ServiceFunctionPaths;
97 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.ServiceFunctionPathsBuilder;
98 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.service.function.paths.ServiceFunctionPath;
99 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.service.function.paths.ServiceFunctionPathBuilder;
100 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.sfc.of.renderer.rev151123.SfcOfRendererConfig;
101 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.sfc.of.renderer.rev151123.SfcOfRendererConfigBuilder;
102 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.AccessLists;
103 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.AccessListsBuilder;
104 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.AclBuilder;
105 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.AccessListEntriesBuilder;
106 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.access.list.entries.AceBuilder;
107 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;
108 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;
109 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
110 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
111 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
112 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
113 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
114 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.providers.config.rev160109.NetvirtProvidersConfig;
115 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.providers.config.rev160109.NetvirtProvidersConfigBuilder;
116 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.Classifiers;
117 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.ClassifiersBuilder;
118 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.classifiers.ClassifierBuilder;
119 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.classifiers.classifier.SffsBuilder;
120 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.classifiers.classifier.sffs.SffBuilder;
121 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.rev150105.Sfc;
122 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.rev150105.SfcBuilder;
123 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
124 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntry;
125 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfo;
126 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
127 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
128 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
129 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
130 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
131 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
132 import org.opendaylight.yangtools.concepts.Builder;
133 import org.opendaylight.yangtools.concepts.ListenerRegistration;
134 import org.opendaylight.yangtools.yang.binding.DataObject;
135 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
136 import org.ops4j.pax.exam.Configuration;
137 import org.ops4j.pax.exam.Option;
138 import org.ops4j.pax.exam.junit.PaxExam;
139 import org.ops4j.pax.exam.karaf.options.LogLevelOption;
140 import org.ops4j.pax.exam.karaf.options.LogLevelOption.LogLevel;
141 import org.ops4j.pax.exam.options.MavenUrlReference;
142 import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
143 import org.ops4j.pax.exam.spi.reactors.PerClass;
144 import org.slf4j.Logger;
145 import org.slf4j.LoggerFactory;
147 import com.google.common.collect.Maps;
149 @RunWith(PaxExam.class)
150 @ExamReactorStrategy(PerClass.class)
151 public class NetvirtSfcIT extends AbstractMdsalTestBase {
152 private static final Logger LOG = LoggerFactory.getLogger(NetvirtSfcIT.class);
153 private static final int MDSAL_TIMEOUT = 10000;
154 private static final int NO_MDSAL_TIMEOUT = 0;
155 private static AclUtils aclUtils = new AclUtils();
156 private static ClassifierUtils classifierUtils = new ClassifierUtils();
157 private static NetvirtSfcUtils netvirtSfcUtils = new NetvirtSfcUtils();
158 private static ServiceFunctionUtils serviceFunctionUtils = new ServiceFunctionUtils();
159 private static ServiceFunctionForwarderUtils serviceFunctionForwarderUtils = new ServiceFunctionForwarderUtils();
160 private static ServiceFunctionChainUtils serviceFunctionChainUtils = new ServiceFunctionChainUtils();
161 private static ServiceFunctionPathUtils serviceFunctionPathUtils = new ServiceFunctionPathUtils();
162 private static RenderedServicePathUtils renderedServicePathUtils = new RenderedServicePathUtils();
163 private static SfcConfigUtils sfcConfigUtils = new SfcConfigUtils();
164 private static NetvirtConfigUtils netvirtConfigUtils = new NetvirtConfigUtils();
165 private static MdsalUtils mdsalUtils;
166 private static AtomicBoolean setup = new AtomicBoolean(false);
167 private static SouthboundUtils southboundUtils;
168 private static SfcUtils sfcUtils;
169 private static String addressStr;
170 private static String portStr;
171 private static String connectionType;
172 private static String controllerStr;
173 private static boolean ovsdb_wait = false;
174 private static String userSpaceEnabled = "no";
175 private static PipelineOrchestrator pipelineOrchestrator;
176 private static Southbound southbound;
177 private static DataBroker dataBroker;
178 public static final String CONTROLLER_IPADDRESS = "ovsdb.controller.address";
179 public static final String SERVER_IPADDRESS = "ovsdbserver.ipaddress";
180 public static final String SERVER_PORT = "ovsdbserver.port";
181 public static final String CONNECTION_TYPE = "ovsdbserver.connection";
182 public static final String CONNECTION_TYPE_ACTIVE = "active";
183 public static final String CONNECTION_TYPE_PASSIVE = "passive";
184 public static final String DEFAULT_SERVER_PORT = "6640";
185 public static final String USERSPACE_ENABLED = "ovsdb.userspace.enabled";
186 public static final String INTEGRATION_BRIDGE_NAME = "br-int";
187 private static final String NETVIRT_TOPOLOGY_ID = "netvirt:1";
188 private static final String OVSDB_TRACE = "ovsdb.trace";
189 private static final String OVSDB_WAIT = "ovsdb.wait";
190 private static final String SF1NAME = "firewall-72";
191 private static final String SF2NAME = "dpi-72";
192 private static final String SF1IP = "10.2.1.1";//"192.168.50.70";//"192.168.120.31";
193 private static final String SF2IP = "10.2.1.2";
194 private static final String SF1DPLNAME = "sf1";
195 private static final String SF2DPLNAME = "sf2";
196 // Use 192.168.50.70 when running against vagrant vm for workaround testing, eg. netvirtsfc-env
197 // Use 192.168.1.129 (or whatever address is dhcp'ed) for tacker-vm
198 // "192.168.50.70"; "127.0.0.1"; "192.168.1.129";
199 private static final String SFF1IP = "192.168.50.70";
200 private static final String SFF2IP = "127.0.0.1";
201 private static final String SFF1NAME = "sff1";
202 private static final String SFF2NAME = "sff2";
203 private static final String SFFDPL1NAME = "vxgpe";
204 private static final String SFFDPL2NAME = "vxgpe";
205 private static final String SN1NAME = "ovsdb1";
206 private static final String SN2NAME = "ovsdb2";
207 private static final String BRIDGE1NAME= "br-int";
208 private static final String BRIDGE2NAME= "br-int";
209 private static final String ACLNAME= "httpAcl";
210 private static final String RULENAME= "httpRule";
211 private static final String SFCNAME = "SFC";
212 private static final String SFCPATH = "SFC-Path";
213 private static final String RSPNAME = SFCPATH + "_rsp";
214 private static final String SFCSF1NAME = "firewall-abstract";
215 private static final SftType SFCSF1TYPE = new SftType("firewall");
216 private static final int GPEUDPPORT = 6633;
219 public String getModuleName() {
220 return "netvirt-sfc";
224 public String getInstanceName() {
225 return "netvirt-sfc-default";
229 public MavenUrlReference getFeatureRepo() {
231 .groupId("org.opendaylight.ovsdb")
232 .artifactId("openstack.net-virt-sfc-features-test")
233 .classifier("features")
235 .versionAsInProject();
239 public String getFeatureName() {
240 return "odl-ovsdb-sfc-test";
245 public Option[] config() {
246 Option[] parentOptions = super.config();
247 Option[] propertiesOptions = getPropertiesOptions();
248 Option[] otherOptions = getOtherOptions();
249 Option[] options = new Option[parentOptions.length + propertiesOptions.length + otherOptions.length];
250 System.arraycopy(parentOptions, 0, options, 0, parentOptions.length);
251 System.arraycopy(propertiesOptions, 0, options, parentOptions.length, propertiesOptions.length);
252 System.arraycopy(otherOptions, 0, options, parentOptions.length + propertiesOptions.length,
253 otherOptions.length);
257 private Option[] getOtherOptions() {
258 return new Option[] {
260 mavenBundle("org.opendaylight.ovsdb", "utils.mdsal-openflow")
261 .version(asInProject())
263 configureConsole().startLocalConsole(),
264 //vmOption("-verbose:class"),
265 vmOption("-javaagent:../jars/org.jacoco.agent.jar=destfile=../../jacoco-it.exec"),
270 public Option[] getPropertiesOptions() {
271 return new Option[] {
272 propagateSystemProperties(SERVER_IPADDRESS, SERVER_PORT, CONNECTION_TYPE,
273 CONTROLLER_IPADDRESS, OVSDB_TRACE, OVSDB_WAIT, USERSPACE_ENABLED),
278 public Option getLoggingOption() {
280 when(Boolean.getBoolean(OVSDB_TRACE)).useOptions(
281 editConfigurationFilePut(ORG_OPS4J_PAX_LOGGING_CFG,
282 "log4j.logger.org.opendaylight.ovsdb",
283 LogLevelOption.LogLevel.TRACE.name())),
284 //editConfigurationFilePut(ORG_OPS4J_PAX_LOGGING_CFG,
285 // "log4j.logger.org.opendaylight.ovsdb",
286 // LogLevelOption.LogLevel.TRACE.name()),
287 editConfigurationFilePut(ORG_OPS4J_PAX_LOGGING_CFG,
288 "log4j.logger.org.opendaylight.ovsdb.library",
289 LogLevel.INFO.name()),
290 editConfigurationFilePut(ORG_OPS4J_PAX_LOGGING_CFG,
291 logConfiguration(NetvirtSfcIT.class),
292 LogLevel.INFO.name()),
293 editConfigurationFilePut(ORG_OPS4J_PAX_LOGGING_CFG,
294 "log4j.logger.org.opendaylight.ovsdb.openstack.netvirt.sfc",
295 LogLevel.TRACE.name()),
296 editConfigurationFilePut(ORG_OPS4J_PAX_LOGGING_CFG,
297 "log4j.logger.org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13",
298 LogLevel.TRACE.name()),
299 editConfigurationFilePut(ORG_OPS4J_PAX_LOGGING_CFG,
300 "log4j.logger.org.opendaylight.sfc",
301 LogLevel.TRACE.name()),
302 super.getLoggingOption());
305 protected String usage() {
306 return "Integration Test needs a valid connection configuration as follows :\n"
307 + "active connection : mvn -Dovsdbserver.ipaddress=x.x.x.x -Dovsdbserver.port=yyyy verify\n"
308 + "passive connection : mvn -Dovsdbserver.connection=passive verify\n";
311 private void getProperties() {
312 Properties props = System.getProperties();
313 addressStr = props.getProperty(SERVER_IPADDRESS);
314 portStr = props.getProperty(SERVER_PORT, DEFAULT_SERVER_PORT);
315 connectionType = props.getProperty(CONNECTION_TYPE, "active");
316 controllerStr = props.getProperty(CONTROLLER_IPADDRESS, "0.0.0.0");
317 userSpaceEnabled = props.getProperty(USERSPACE_ENABLED, "no");
318 LOG.info("setUp: Using the following properties: mode= {}, ip:port= {}:{}, controller ip: {}, " +
319 "userspace.enabled: {}",
320 connectionType, addressStr, portStr, controllerStr, userSpaceEnabled);
321 if (connectionType.equalsIgnoreCase(CONNECTION_TYPE_ACTIVE)) {
322 if (addressStr == null) {
326 LOG.info("getProperties {}: {}", OVSDB_TRACE, props.getProperty(OVSDB_TRACE));
327 LOG.info("getProperties {}: {}", OVSDB_WAIT, props.getProperty(OVSDB_WAIT));
328 if (props.getProperty(OVSDB_WAIT) != null && props.getProperty(OVSDB_WAIT).equals("true")) {
335 public void setup() {
337 LOG.info("Skipping setUp, already initialized");
344 } catch (Exception e) {
345 LOG.warn("Failed to setup test", e);
346 fail("Failed to setup test: " + e);
351 dataBroker = getDatabroker(getProviderContext());
352 mdsalUtils = new MdsalUtils(dataBroker);
353 assertNotNull("mdsalUtils should not be null", mdsalUtils);
354 southboundUtils = new SouthboundUtils(mdsalUtils);
355 sfcUtils = new SfcUtils(mdsalUtils);
356 assertTrue("Did not find " + NETVIRT_TOPOLOGY_ID, getNetvirtTopology());
357 southbound = (Southbound) ServiceHelper.getGlobalInstance(Southbound.class, this);
358 assertNotNull("southbound should not be null", southbound);
359 pipelineOrchestrator =
360 (PipelineOrchestrator) ServiceHelper.getGlobalInstance(PipelineOrchestrator.class, this);
361 assertNotNull("pipelineOrchestrator should not be null", pipelineOrchestrator);
367 public void teardown() {
371 private ProviderContext getProviderContext() {
372 ProviderContext providerContext = null;
373 for (int i=0; i < 60; i++) {
374 providerContext = getSession();
375 if (providerContext != null) {
380 } catch (InterruptedException e) {
381 LOG.warn("Interrupted while waiting for provider context", e);
385 assertNotNull("providercontext should not be null", providerContext);
386 /* One more second to let the provider finish initialization */
389 } catch (InterruptedException e) {
390 LOG.warn("Interrupted while waiting for other provider", e);
392 return providerContext;
395 private DataBroker getDatabroker(ProviderContext providerContext) {
396 DataBroker dataBroker = providerContext.getSALService(DataBroker.class);
397 assertNotNull("dataBroker should not be null", dataBroker);
401 private Boolean getNetvirtTopology() {
402 LOG.info("getNetvirtTopology: looking for {}...", NETVIRT_TOPOLOGY_ID);
403 Boolean found = false;
404 final TopologyId topologyId = new TopologyId(new Uri(NETVIRT_TOPOLOGY_ID));
405 InstanceIdentifier<Topology> path =
406 InstanceIdentifier.create(NetworkTopology.class).child(Topology.class, new TopologyKey(topologyId));
407 for (int i = 0; i < 60; i++) {
408 Topology topology = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, path);
409 if (topology != null) {
410 LOG.info("getNetvirtTopology: found {}...", NETVIRT_TOPOLOGY_ID);
414 LOG.info("getNetvirtTopology: still looking ({})...", i);
417 } catch (InterruptedException e) {
418 LOG.warn("Interrupted while waiting for {}", NETVIRT_TOPOLOGY_ID, e);
425 private AccessListsBuilder accessListsBuilder() {
426 return accessListsBuilder(false);
429 private AccessListsBuilder accessListsBuilder(boolean renderRsp) {
430 String ruleName = RULENAME;
431 String sfcName = SFCNAME;
432 MatchesBuilder matchesBuilder = aclUtils.matchesBuilder(new MatchesBuilder(), 80);
433 LOG.info("Matches: {}", matchesBuilder.build());
434 ActionsBuilder actionsBuilder = aclUtils.actionsBuilder(new ActionsBuilder(), sfcName, renderRsp);
435 AceBuilder accessListEntryBuilder =
436 aclUtils.aceBuilder(new AceBuilder(), ruleName, matchesBuilder, actionsBuilder);
437 AccessListEntriesBuilder accessListEntriesBuilder =
438 aclUtils.accessListEntriesBuidler(new AccessListEntriesBuilder(), accessListEntryBuilder);
439 AclBuilder accessListBuilder =
440 aclUtils.aclBuilder(new AclBuilder(), ACLNAME, accessListEntriesBuilder);
441 AccessListsBuilder accessListsBuilder =
442 aclUtils.accesslistsbuilder(new AccessListsBuilder(), accessListBuilder);
443 LOG.info("AccessLists: {}", accessListsBuilder.build());
444 return accessListsBuilder;
448 public void testAccessLists() throws InterruptedException {
449 testModel(accessListsBuilder(), AccessLists.class, 0);
452 private ClassifiersBuilder classifiersBuilder() {
453 SffBuilder sffBuilder = classifierUtils.sffBuilder(new SffBuilder(), SFF1NAME);
454 SffsBuilder sffsBuilder = classifierUtils.sffsBuilder(new SffsBuilder(), sffBuilder);
455 ClassifierBuilder classifierBuilder = classifierUtils.classifierBuilder(new ClassifierBuilder(),
456 "classifierName", ACLNAME, sffsBuilder);
457 ClassifiersBuilder classifiersBuilder = classifierUtils.classifiersBuilder(new ClassifiersBuilder(),
459 LOG.info("Classifiers: {}", classifiersBuilder.build());
460 return classifiersBuilder;
464 public void testClassifiers() throws InterruptedException {
465 testModel(classifiersBuilder(), Classifiers.class, 0);
468 private SfcBuilder netvirtSfcBuilder() {
469 return netvirtSfcUtils.sfcBuilder(new SfcBuilder(), "sfc");
473 public void testNetvirtSfcModel() throws InterruptedException {
474 testModel(netvirtSfcBuilder(), Sfc.class, 0);
477 private <T extends DataObject> void testModelPut(Builder<T> builder, Class<T> clazz) {
478 InstanceIdentifier<T> path = InstanceIdentifier.create(clazz);
479 assertTrue(mdsalUtils.put(LogicalDatastoreType.CONFIGURATION, path, builder.build()));
480 T result = mdsalUtils.read(LogicalDatastoreType.CONFIGURATION, path);
481 assertNotNull(clazz.getSimpleName() + " should not be null", result);
484 private <T extends DataObject> void testModelDelete(Builder<T> builder, Class<T> clazz)
485 throws InterruptedException {
486 InstanceIdentifier<T> path = InstanceIdentifier.create(clazz);
487 assertTrue("Failed to remove " + clazz.getSimpleName(),
488 mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, path));
489 T result = mdsalUtils.read(LogicalDatastoreType.CONFIGURATION, path);
490 assertNull(clazz.getSimpleName() + " should be null", result);
493 private <T extends DataObject> void testModel(Builder<T> builder, Class<T> clazz, long wait)
494 throws InterruptedException {
495 testModelPut(builder, clazz);
497 testModelDelete(builder, clazz);
500 private <T extends DataObject> void testModel(Builder<T> builder, Class<T> clazz)
501 throws InterruptedException {
502 testModelPut(builder, clazz);
504 testModelDelete(builder, clazz);
507 private ServiceFunctionsBuilder serviceFunctionsBuilder() {
508 String sf1Name = SF1NAME;
509 String sf1Ip = SF1IP;
510 String sff1Name = SFF1NAME;
511 String sf1DplName = SF1DPLNAME;
512 int port = GPEUDPPORT;
514 ServiceFunctionBuilder serviceFunctionBuilder =
515 serviceFunctionUtils.serviceFunctionBuilder(sf1Ip, port, sf1DplName, sff1Name, sf1Name);
516 List<ServiceFunction> serviceFunctionList = serviceFunctionUtils.list(
517 new ArrayList<ServiceFunction>(), serviceFunctionBuilder);
519 ServiceFunctionsBuilder serviceFunctionsBuilder =
520 serviceFunctionUtils.serviceFunctionsBuilder(new ServiceFunctionsBuilder(),
521 serviceFunctionList);
522 LOG.info("ServiceFunctions: {}", serviceFunctionsBuilder.build());
523 return serviceFunctionsBuilder;
526 private ServiceFunctionForwardersBuilder serviceFunctionForwardersBuilder() {
527 String sf1Name = SF1NAME;
528 String sf1Ip = SF1IP;
529 String sf1DplName = SF1DPLNAME;
530 String sff1Ip = SFF1IP;
531 String sff1Name = SFF1NAME;
532 String sffDpl1Name = SFFDPL1NAME;
533 String sn1Name = SN1NAME;
534 String bridge1Name= BRIDGE1NAME;
535 int port = GPEUDPPORT;
537 ServiceFunctionForwarderBuilder serviceFunctionForwarderBuilder =
538 serviceFunctionForwarderUtils.serviceFunctionForwarderBuilder(
539 sff1Name, sff1Ip, port, sffDpl1Name, sf1Ip, sn1Name, bridge1Name, sf1Name, sf1DplName);
540 List<ServiceFunctionForwarder> serviceFunctionForwarderList = serviceFunctionForwarderUtils.list(
541 new ArrayList<ServiceFunctionForwarder>(), serviceFunctionForwarderBuilder);
543 ServiceFunctionForwardersBuilder serviceFunctionForwardersBuilder =
544 serviceFunctionForwarderUtils.serviceFunctionForwardersBuilder(
545 new ServiceFunctionForwardersBuilder(), serviceFunctionForwarderList);
546 LOG.info("ServiceFunctionForwarders: {}", serviceFunctionForwardersBuilder.build());
547 return serviceFunctionForwardersBuilder;
550 private ServiceFunctionChainsBuilder serviceFunctionChainsBuilder() {
551 String sf1Name = SFCSF1NAME;
552 SftType sfType = SFCSF1TYPE;
553 String sfcName = SFCNAME;
555 SfcServiceFunctionBuilder sfcServiceFunctionBuilder = serviceFunctionChainUtils.sfcServiceFunctionBuilder(
556 new SfcServiceFunctionBuilder(), sf1Name, sfType);
557 List<SfcServiceFunction> sfcServiceFunctionList =
558 serviceFunctionChainUtils.list(new ArrayList<SfcServiceFunction>(), sfcServiceFunctionBuilder);
560 ServiceFunctionChainBuilder serviceFunctionChainBuilder =
561 serviceFunctionChainUtils.serviceFunctionChainBuilder(
562 new ServiceFunctionChainBuilder(), sfcName, false, sfcServiceFunctionList);
563 ServiceFunctionChainsBuilder serviceFunctionChainsBuilder =
564 serviceFunctionChainUtils.serviceFunctionChainsBuilder(
565 new ServiceFunctionChainsBuilder(),
566 serviceFunctionChainUtils.list(new ArrayList<ServiceFunctionChain>(),
567 serviceFunctionChainBuilder));
568 LOG.info("ServiceFunctionChains: {}", serviceFunctionChainBuilder.build());
569 return serviceFunctionChainsBuilder;
572 private ServiceFunctionPathsBuilder serviceFunctionPathsBuilder() {
573 String sfpName = SFCPATH;
574 String sfcName = SFCNAME;
575 short startingIndex = 255;
577 ServiceFunctionPathBuilder serviceFunctionPathBuilder =
578 serviceFunctionPathUtils.serviceFunctionPathBuilder(
579 new ServiceFunctionPathBuilder(), sfpName, sfcName, startingIndex, false);
580 ServiceFunctionPathsBuilder serviceFunctionPathsBuilder =
581 serviceFunctionPathUtils.serviceFunctionPathsBuilder(
582 serviceFunctionPathUtils.list(new ArrayList<ServiceFunctionPath>(),
583 serviceFunctionPathBuilder));
584 LOG.info("ServiceFunctionPaths: {}", serviceFunctionPathsBuilder.build());
585 return serviceFunctionPathsBuilder;
588 private SfcOfRendererConfigBuilder sfcOfRendererConfigBuilder(short tableOffset, short egressTable) {
589 SfcOfRendererConfigBuilder sfcOfRendererConfigBuilder =
590 sfcConfigUtils.sfcOfRendererConfigBuilder(new SfcOfRendererConfigBuilder(), tableOffset, egressTable);
591 LOG.info("SfcOfRendererConfig: {}", sfcOfRendererConfigBuilder.build());
592 return sfcOfRendererConfigBuilder;
595 private NetvirtProvidersConfigBuilder netvirtProvidersConfigBuilder(short tableOffset) {
596 NetvirtProvidersConfigBuilder netvirtProvidersConfigBuilder =
597 netvirtConfigUtils.netvirtProvidersConfigBuilder(new NetvirtProvidersConfigBuilder(), tableOffset);
598 LOG.info("NetvirtProvidersConfig: {}", netvirtProvidersConfigBuilder.build());
599 return netvirtProvidersConfigBuilder;
603 public void testSfcModel() throws InterruptedException {
605 testModel(serviceFunctionsBuilder(), ServiceFunctions.class, timeout);
606 testModel(serviceFunctionForwardersBuilder(), ServiceFunctionForwarders.class, timeout);
607 testModel(serviceFunctionChainsBuilder(), ServiceFunctionChains.class, timeout);
608 testModel(serviceFunctionPathsBuilder(), ServiceFunctionPaths.class, timeout);
612 public void testSfcModels() throws InterruptedException {
613 testModel(serviceFunctionsBuilder(), ServiceFunctions.class);
614 testModel(serviceFunctionForwardersBuilder(), ServiceFunctionForwarders.class);
615 testModel(serviceFunctionChainsBuilder(), ServiceFunctionChains.class);
616 testModel(serviceFunctionPathsBuilder(), ServiceFunctionPaths.class);
618 testModel(accessListsBuilder(), AccessLists.class);
619 testModel(classifiersBuilder(), Classifiers.class);
622 private class NodeInfo {
623 private ConnectionInfo connectionInfo;
624 private InstanceIdentifier<Node> ovsdbIid;
625 private String bridgeName = INTEGRATION_BRIDGE_NAME;
626 InstanceIdentifier<Node> bridgeIid;
627 NotifyingDataChangeListener ovsdbOperationalListener;
628 NotifyingDataChangeListener bridgeOperationalListener;
633 NodeInfo(ConnectionInfo connectionInfo) {
634 this.connectionInfo = connectionInfo;
635 ovsdbIid = SouthboundUtils.createInstanceIdentifier(connectionInfo);
636 bridgeIid = SouthboundUtils.createInstanceIdentifier(connectionInfo, bridgeName);
639 private void connect() throws InterruptedException {
640 ovsdbOperationalListener = new NotifyingDataChangeListener(LogicalDatastoreType.OPERATIONAL, ovsdbIid);
641 ovsdbOperationalListener.registerDataChangeListener();
642 bridgeOperationalListener = new NotifyingDataChangeListener(LogicalDatastoreType.OPERATIONAL, bridgeIid);
643 bridgeOperationalListener.registerDataChangeListener();
644 assertNotNull("connection failed", southboundUtils.addOvsdbNode(connectionInfo, NO_MDSAL_TIMEOUT));
646 ovsdbOperationalListener.waitForCreation();
647 ovsdbNode = southboundUtils.getOvsdbNode(connectionInfo);
648 assertNotNull("node is not connected", ovsdbNode);
650 bridgeOperationalListener.waitForCreation();
651 assertTrue("Controller " + SouthboundUtils.connectionInfoToString(connectionInfo)
652 + " is not connected", isControllerConnected(connectionInfo));
654 bridgeNode = southbound.getBridgeNode(ovsdbNode, bridgeName);
655 assertNotNull("bridge " + bridgeName + " was not found", bridgeNode);
656 datapathId = southbound.getDataPathId(bridgeNode);
657 String datapathIdString = southbound.getDatapathId(bridgeNode);
658 LOG.info("testNetVirt: bridgeNode: {}, datapathId: {} - {}", bridgeNode, datapathIdString, datapathId);
659 assertNotEquals("datapathId was not found", datapathId, 0);
662 void disconnect() throws InterruptedException {
663 assertTrue(southboundUtils.deleteBridge(connectionInfo, bridgeName, NO_MDSAL_TIMEOUT));
664 bridgeOperationalListener.waitForDeletion();
665 Node bridgeNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, bridgeIid);
666 assertNull("Bridge should not be found", bridgeNode);
667 assertTrue(southboundUtils.disconnectOvsdbNode(connectionInfo, NO_MDSAL_TIMEOUT));
668 ovsdbOperationalListener.waitForDeletion();
669 Node ovsdbNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, ovsdbIid);
670 assertNull("Ovsdb node should not be found", ovsdbNode);
675 * Test that the NetvirtSfc SfcClassifierService is added to the Netvirt pipeline. The test
676 * sets the table offset and verifies the correct flow is programmed with the offset.
679 public void testNetvirtSfcPipeline() throws InterruptedException {
680 short netvirtTableOffset = 1;
681 testModelPut(netvirtProvidersConfigBuilder(netvirtTableOffset), NetvirtProvidersConfig.class);
683 NodeInfo nodeInfo = new NodeInfo(SouthboundUtils.getConnectionInfo(addressStr, portStr));
686 String flowId = "DEFAULT_PIPELINE_FLOW_" + pipelineOrchestrator.getTable(Service.SFC_CLASSIFIER);
687 verifyFlow(nodeInfo.datapathId, flowId, Service.SFC_CLASSIFIER);
689 nodeInfo.disconnect();
693 * Test the full NetvirtSfc functionality by creating everything needed to realize a chain and
694 * then verify all flows have been created.
695 * NOTE: This test requires an OVS with the NSH v8 patch, otherwise it will fail miserably.
696 * @throws InterruptedException
699 public void testNetvirtSfcAll() throws Exception {
700 if (userSpaceEnabled.equals("yes")) {
701 LOG.info("testNetvirtSfcAll: skipping test because userSpaceEnabled {}", userSpaceEnabled);
705 String sfpName = SFCPATH;
706 String sfcName = SFCNAME;
707 short startingIndex = 255;
709 short netvirtTableOffset = 1;
710 testModelPut(netvirtProvidersConfigBuilder(netvirtTableOffset), NetvirtProvidersConfig.class);
711 short sfcTableoffset = 150;
712 short egressTable = pipelineOrchestrator.getTable(Service.SFC_CLASSIFIER);
713 testModelPut(sfcOfRendererConfigBuilder(sfcTableoffset, egressTable), SfcOfRendererConfig.class);
715 NodeInfo nodeInfo = new NodeInfo(SouthboundUtils.getConnectionInfo(addressStr, portStr));
718 String flowId = "DEFAULT_PIPELINE_FLOW_" + pipelineOrchestrator.getTable(Service.SFC_CLASSIFIER);
719 verifyFlow(nodeInfo.datapathId, flowId, Service.SFC_CLASSIFIER);
721 Map<String, String> externalIds = Maps.newHashMap();
722 externalIds.put("attached-mac", "f6:00:00:0f:00:01");
723 southboundUtils.addTerminationPoint(nodeInfo.bridgeNode, SF1DPLNAME, "internal", null, externalIds);
725 externalIds.put("attached-mac", "f6:00:00:0c:00:01");
726 southboundUtils.addTerminationPoint(nodeInfo.bridgeNode, "vm1", "internal");
728 externalIds.put("attached-mac", "f6:00:00:0c:00:02");
729 southboundUtils.addTerminationPoint(nodeInfo.bridgeNode, "vm2", "internal");
731 InstanceIdentifier<TerminationPoint> tpIid =
732 southboundUtils.createTerminationPointInstanceIdentifier(nodeInfo.bridgeNode, SFFDPL1NAME);
733 final NotifyingDataChangeListener portOperationalListener =
734 new NotifyingDataChangeListener(LogicalDatastoreType.OPERATIONAL, tpIid);
735 portOperationalListener.registerDataChangeListener();
737 InstanceIdentifier<RenderedServicePath> rspIid = sfcUtils.getRspId(RSPNAME);
738 final NotifyingDataChangeListener rspOperationalListener =
739 new NotifyingDataChangeListener(LogicalDatastoreType.OPERATIONAL, rspIid);
740 rspOperationalListener.registerDataChangeListener();
742 testModelPut(serviceFunctionsBuilder(), ServiceFunctions.class);
743 testModelPut(serviceFunctionForwardersBuilder(), ServiceFunctionForwarders.class);
744 testModelPut(serviceFunctionChainsBuilder(), ServiceFunctionChains.class);
745 testModelPut(serviceFunctionPathsBuilder(), ServiceFunctionPaths.class);
747 testModelPut(accessListsBuilder(false), AccessLists.class);
748 testModelPut(classifiersBuilder(), Classifiers.class);
749 ServiceFunctionPathBuilder serviceFunctionPathBuilder =
750 serviceFunctionPathUtils.serviceFunctionPathBuilder(
751 new ServiceFunctionPathBuilder(), sfpName, sfcName, startingIndex, false);
752 SfcProviderRenderedPathAPI.createRenderedServicePathAndState(serviceFunctionPathBuilder.build(),
753 renderedServicePathUtils.createRenderedPathInputBuilder(new CreateRenderedPathInputBuilder(),
754 SFCPATH, RSPNAME).build());
756 portOperationalListener.waitForCreation();
757 long vxGpeOfPort = southbound.getOFPort(nodeInfo.bridgeNode, SFFDPL1NAME);
758 assertNotEquals("vxGpePort was not found", 0, vxGpeOfPort);
760 rspOperationalListener.waitForCreation();
761 RenderedServicePath rsp = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, rspIid);
762 assertNotNull("RSP was not found", rsp);
764 flowId = FlowNames.getSfcIngressClass(RULENAME, rsp.getPathId(), rsp.getStartingIndex());
765 verifyFlow(nodeInfo.datapathId, flowId, Service.SFC_CLASSIFIER);
766 RenderedServicePathHop lastHop = sfcUtils.getLastHop(rsp);
767 short lastServiceindex = (short)((lastHop.getServiceIndex()).intValue() - 1);
768 flowId = FlowNames.getSfcEgressClass(vxGpeOfPort, rsp.getPathId(), lastServiceindex);
769 verifyFlow(nodeInfo.datapathId, flowId, Service.SFC_CLASSIFIER);
770 flowId = FlowNames.getSfcEgressClassBypass(rsp.getPathId(), lastServiceindex, 1);
771 verifyFlow(nodeInfo.datapathId, flowId, Service.CLASSIFIER);
772 flowId = FlowNames.getArpResponder(SF1IP);
773 verifyFlow(nodeInfo.datapathId, flowId, Service.ARP_RESPONDER);
775 InstanceIdentifier<Flow> flowIid = createFlowIid(nodeInfo.datapathId, flowId,
776 pipelineOrchestrator.getTable(Service.CLASSIFIER));
778 final NotifyingDataChangeListener flowConfigurationListener =
779 new NotifyingDataChangeListener(LogicalDatastoreType.CONFIGURATION, flowIid);
780 flowConfigurationListener.registerDataChangeListener();
781 final NotifyingDataChangeListener flowOperationalListener =
782 new NotifyingDataChangeListener(LogicalDatastoreType.OPERATIONAL, flowIid);
783 flowOperationalListener.registerDataChangeListener();
786 rspOperationalListener.waitForDeletion();
787 rsp = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, rspIid);
788 assertNull("RSP should not be found", rsp);
790 flowConfigurationListener.waitForDeletion();
791 Flow flow = mdsalUtils.read(LogicalDatastoreType.CONFIGURATION, flowIid);
792 assertNull("Flow should not be found in CONFIGURATION " + flowIid, flow);
794 flowOperationalListener.waitForDeletion();
795 flow = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, flowIid);
796 assertNull("Flow should not be found in OPERATIONAL " + flowIid, flow);
798 nodeInfo.disconnect();
801 private void deleteRsp(String rspName) {
802 RenderedServicePathKey renderedServicePathKey =
803 new RenderedServicePathKey(RspName.getDefaultInstance(rspName));
804 InstanceIdentifier<RenderedServicePath> path =
805 InstanceIdentifier.create(RenderedServicePaths.class)
806 .child(RenderedServicePath.class, renderedServicePathKey);
807 mdsalUtils.delete(LogicalDatastoreType.OPERATIONAL, path);
811 * Test the standalone NetvirtSfc implementation
812 * NOTE: This test requires an OVS with the NSH v8 patch, otherwise it will fail miserably.
813 * @throws InterruptedException
817 public void testStandalone() throws InterruptedException {
818 String bridgeName = "sw1";
819 ConnectionInfo connectionInfo = SouthboundUtils.getConnectionInfo(addressStr, portStr);
820 assertNotNull("connection failed", southboundUtils.connectOvsdbNode(connectionInfo));
821 Node ovsdbNode = southboundUtils.getOvsdbNode(connectionInfo);
822 assertNotNull("node is not connected", ovsdbNode);
824 String controllerTarget = "tcp:192.168.50.1:6653";
825 List<ControllerEntry> setControllerEntry = southboundUtils.createControllerEntry(controllerTarget);
826 Assert.assertTrue(southboundUtils.addBridge(connectionInfo, null, bridgeName, null, true,
827 SouthboundConstants.OVSDB_FAIL_MODE_MAP.inverse().get("secure"), true, null, null,
828 setControllerEntry, null, "00:00:00:00:00:00:00:01"));
829 assertTrue("Controller " + SouthboundUtils.connectionInfoToString(connectionInfo)
830 + " is not connected", isControllerConnected(connectionInfo));
832 Node bridgeNode = southbound.getBridgeNode(ovsdbNode, bridgeName);
833 assertNotNull("bridge " + bridgeName + " was not found", bridgeNode);
834 long datapathId = southbound.getDataPathId(bridgeNode);
835 String datapathIdString = southbound.getDatapathId(bridgeNode);
836 LOG.info("testNetVirt: bridgeNode: {}, datapathId: {} - {}", bridgeNode, datapathIdString, datapathId);
837 assertNotEquals("datapathId was not found", datapathId, 0);
839 SfcClassifier sfcClassifier = new SfcClassifier(dataBroker, southbound, mdsalUtils);
840 //sfcClassifier.programLocalInPort(datapathId, "4096", (long)1, (short)0, (short)50, true);
842 NshUtils nshUtils = new NshUtils(new Ipv4Address("192.168.50.71"), new PortNumber(6633),
843 (long)10, (short)255, (long)4096, (long)4096);
844 MatchesBuilder matchesBuilder = aclUtils.matchesBuilder(new MatchesBuilder(), 80);
845 sfcClassifier.programSfcClassiferFlows(datapathId, (short)0, "test", matchesBuilder.build(),
846 nshUtils, (long)2, true);
848 //nshUtils = new NshUtils(null, null, (long)10, (short)253, 0, 0);
849 //sfcClassifier.programEgressSfcClassiferFlows(datapathId, (short)0, "test", null,
850 // nshUtils, (long)2, (long)3, true);
852 //NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(datapathId);
853 //FlowBuilder flowBuilder = getLocalInPortFlow(datapathId, "4096", (long) 1,
854 // pipelineOrchestrator.getTable(Service.CLASSIFIER));
855 //Flow flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.CONFIGURATION);
856 //assertNotNull("Could not find flow in config", flow);
857 //flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.OPERATIONAL);
858 //assertNotNull("Could not find flow in operational", flow);
860 //MatchBuilder matchBuilder = sfcClassifier.buildMatch(matchesBuilder.build());
861 //NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(datapathId);
862 //FlowBuilder flowBuilder = getSfcClassifierFlow(datapathId,
863 // pipelineOrchestrator.getTable(Service.CLASSIFIER), "test", null,
864 // nshUtils, (long) 2, matchBuilder);
865 //Flow flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.CONFIGURATION);
866 //assertNotNull("Could not find flow in config", flow);
867 //flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.OPERATIONAL);
868 //assertNotNull("Could not find flow in operational", flow);
870 //nodeBuilder = FlowUtils.createNodeBuilder(datapathId);
871 //flowBuilder = getEgressSfcClassifierFlow(datapathId,
872 //pipelineOrchestrator.getTable(Service.CLASSIFIER),
873 //"test", nshUtils, (long) 2);
874 //flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.CONFIGURATION);
875 //assertNotNull("Could not find flow in config", flow);
876 //flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.OPERATIONAL);
877 //assertNotNull("Could not find flow in operational", flow);
879 LOG.info("***** Go look for flows *****");
881 assertTrue(southboundUtils.deleteBridge(connectionInfo, bridgeName));
883 assertTrue(southboundUtils.deleteBridge(connectionInfo, INTEGRATION_BRIDGE_NAME));
885 assertTrue(southboundUtils.disconnectOvsdbNode(connectionInfo));
888 private InstanceIdentifier<Flow> createFlowIid(long datapathId, String flowId, short table) {
889 org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder nodeBuilder =
890 FlowUtils.createNodeBuilder(datapathId);
891 FlowBuilder flowBuilder =
892 FlowUtils.initFlowBuilder(new FlowBuilder(), flowId, table);
893 return FlowUtils.createFlowPath(flowBuilder, nodeBuilder);
896 private Flow getFlow (
897 FlowBuilder flowBuilder,
898 org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder nodeBuilder,
899 LogicalDatastoreType store) throws InterruptedException {
902 for (int i = 0; i < 10; i++) {
903 LOG.info("getFlow try {} from {}: looking for flow: {}, node: {}",
904 i, store, flowBuilder.build(), nodeBuilder.build());
905 flow = FlowUtils.getFlow(flowBuilder, nodeBuilder, dataBroker.newReadOnlyTransaction(), store);
907 LOG.info("getFlow try {} from {}: found flow: {}", i, store, flow);
915 private void verifyFlow(long datapathId, String flowId, short table) throws InterruptedException {
916 org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder nodeBuilder =
917 FlowUtils.createNodeBuilder(datapathId);
918 FlowBuilder flowBuilder =
919 FlowUtils.initFlowBuilder(new FlowBuilder(), flowId, table);
920 Flow flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.CONFIGURATION);
921 assertNotNull("Could not find flow in config: " + flowBuilder.build() + "--" + nodeBuilder.build(), flow);
922 flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.OPERATIONAL);
923 assertNotNull("Could not find flow in operational: " + flowBuilder.build() + "--" + nodeBuilder.build(),
927 private void verifyFlow(long datapathId, String flowId, Service service) throws InterruptedException {
928 verifyFlow(datapathId, flowId, pipelineOrchestrator.getTable(service));
931 private void readwait() {
933 LOG.warn("Waiting, kill with ps -ef | grep java, kill xxx... ");
936 } catch (IOException e) {
942 private boolean isControllerConnected(ConnectionInfo connectionInfo) throws InterruptedException {
943 LOG.info("isControllerConnected enter");
944 Boolean connected = false;
945 ControllerEntry controllerEntry;
946 Node ovsdbNode = southboundUtils.getOvsdbNode(connectionInfo);
947 assertNotNull("ovsdb node not found", ovsdbNode);
949 BridgeConfigurationManager bridgeConfigurationManager =
950 (BridgeConfigurationManager) ServiceHelper.getGlobalInstance(BridgeConfigurationManager.class, this);
951 assertNotNull("Could not find BridgeConfigurationManager Service", bridgeConfigurationManager);
952 String controllerTarget = bridgeConfigurationManager.getControllersFromOvsdbNode(ovsdbNode).get(0);
953 Assert.assertNotNull("Failed to get controller target", controllerTarget);
955 for (int i = 0; i < 10; i++) {
956 LOG.info("isControllerConnected try {}: looking for controller: {}", i, controllerTarget);
957 OvsdbBridgeAugmentation bridge =
958 southboundUtils.getBridge(connectionInfo, INTEGRATION_BRIDGE_NAME);
959 Assert.assertNotNull(bridge);
960 Assert.assertNotNull(bridge.getControllerEntry());
961 controllerEntry = bridge.getControllerEntry().iterator().next();
962 Assert.assertEquals(controllerTarget, controllerEntry.getTarget().getValue());
963 if (controllerEntry.isIsConnected()) {
964 Assert.assertTrue("Controller is not connected", controllerEntry.isIsConnected());
970 LOG.info("isControllerConnected exit: {} - {}", connected, controllerTarget);
974 private List<NotifyingDataChangeListener> waitList = new ArrayList<>();
976 private void closeWaitFors() {
977 for (Iterator<NotifyingDataChangeListener> iterator = waitList.iterator(); iterator.hasNext();) {
978 NotifyingDataChangeListener listener = iterator.next();
982 } catch (Exception ex) {
983 LOG.warn("Failed to close registration {}", listener, ex);
986 LOG.info("waitList size {}", waitList.size());
989 public class NotifyingDataChangeListener implements AutoCloseable, DataChangeListener {
990 private LogicalDatastoreType type;
991 private final Set<InstanceIdentifier<?>> createdIids = new HashSet<>();
992 private final Set<InstanceIdentifier<?>> removedIids = new HashSet<>();
993 private final Set<InstanceIdentifier<?>> updatedIids = new HashSet<>();
994 private InstanceIdentifier<?> iid;
995 private final int RETRY_WAIT = 100;
996 private final int MDSAL_TIMEOUT = 1000;
997 private ListenerRegistration<?> listenerRegistration;
999 private NotifyingDataChangeListener(LogicalDatastoreType type, InstanceIdentifier<?> iid) {
1005 private void modify(LogicalDatastoreType type, InstanceIdentifier<?> iid) throws Exception {
1013 public void onDataChanged(
1014 AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> asyncDataChangeEvent) {
1015 LOG.info("{} DataChanged: created {}", type, asyncDataChangeEvent.getCreatedData().keySet());
1016 LOG.info("{} DataChanged: updated {}", type, asyncDataChangeEvent.getUpdatedData().keySet());
1017 LOG.info("{} DataChanged: removed {}", type, asyncDataChangeEvent.getRemovedPaths());
1018 createdIids.addAll(asyncDataChangeEvent.getCreatedData().keySet());
1019 removedIids.addAll(asyncDataChangeEvent.getRemovedPaths());
1020 updatedIids.addAll(asyncDataChangeEvent.getUpdatedData().keySet());
1021 synchronized(this) {
1026 public boolean isCreated(InstanceIdentifier<?> iid) {
1027 return createdIids.remove(iid);
1030 public boolean isUpdated(InstanceIdentifier<?> iid) {
1031 return updatedIids.remove(iid);
1034 public boolean isRemoved(InstanceIdentifier<?> iid) {
1035 return removedIids.remove(iid);
1038 public void clear() {
1039 createdIids.clear();
1040 removedIids.clear();
1041 updatedIids.clear();
1044 public void registerDataChangeListener() {
1045 listenerRegistration = dataBroker.registerDataChangeListener(type, iid, this,
1046 AsyncDataBroker.DataChangeScope.SUBTREE);
1049 public void waitForCreation() throws InterruptedException {
1050 waitForCreation(MDSAL_TIMEOUT);
1053 public void waitForCreation(long timeout) throws InterruptedException {
1054 synchronized (this) {
1055 long _start = System.currentTimeMillis();
1056 LOG.info("Waiting for {} DataChanged creation on {}", type, iid);
1057 while (!isCreated(iid) && (System.currentTimeMillis() - _start) < timeout) {
1060 LOG.info("Woke up, waited {}ms for creation of {}", (System.currentTimeMillis() - _start), iid);
1064 public void waitForUpdate() throws InterruptedException {
1065 waitForUpdate(MDSAL_TIMEOUT);
1068 public void waitForUpdate(long timeout) throws InterruptedException {
1069 synchronized (this) {
1070 long _start = System.currentTimeMillis();
1071 LOG.info("Waiting for {} DataChanged update on {}", type, iid);
1072 while (!isUpdated(iid) && (System.currentTimeMillis() - _start) < timeout) {
1075 LOG.info("Woke up, waited {}ms for update of {}", (System.currentTimeMillis() - _start), iid);
1079 public void waitForDeletion() throws InterruptedException {
1080 waitForDeletion(MDSAL_TIMEOUT);
1083 public void waitForDeletion(long timeout) throws InterruptedException {
1084 synchronized (this) {
1085 long _start = System.currentTimeMillis();
1086 LOG.info("Waiting for {} DataChanged deletion on {}", type, iid);
1087 while (!isRemoved(iid) && (System.currentTimeMillis() - _start) < timeout) {
1090 LOG.info("Woke up, waited {}ms for deletion of {}", (System.currentTimeMillis() - _start), iid);
1095 public void close() throws Exception {
1096 if (listenerRegistration != null) {
1098 listenerRegistration.close();
1099 } catch (final Exception ex) {
1100 LOG.warn("Failed to close registration {}, iid {}", listenerRegistration, iid, ex);
1103 waitList.remove(this);
1104 listenerRegistration = null;