From 6145aa7fe775f136802b18046298c4e3a9a2e2d9 Mon Sep 17 00:00:00 2001 From: Sam Hague Date: Mon, 11 Jan 2016 14:57:15 -0500 Subject: [PATCH] Add support for table offset This commit adds a new config parameter table-offset to allow setting the openflow table base. The default value is 0. The user can change the value via the config file netvirt-providers-impl-default-config.xml or by using the restconf api show below. The value used must be between 1 and 145 - with 145 coming from 255-110 - 110 is the max table in the netvirt pipeline. The following curl commands can be used to configure the value: - Get the current value: curl -u admin:admin http://localhost:8181/restconf/config/netvirt-providers-config:netvirt-providers-config - Change the value: In this example the value is changed to 1 curl -u admin:admin http://localhost:8181/restconf/config/netvirt-providers-config:netvirt-providers-config -i -H "Content-Type: application/json" --data '{"netvirt-providers-config": {"table-offset": 1}}' -X PUT If the table-offset is set, then an extra flow is added to the br-ex and br-int switches to steer packets from table 0 to the first table in the pipeline. IT tests were all updated to check for the new table-offsets as well as adding unti-tests. Some IT tests have a little more due to the Yang pacth that enforces strictre rules on the Yang files and was failing the tests. Further patches should add config service in netvirt to be a central point handling all the config updates. SG is also adding a config value that should be included. Change-Id: I44b3a442e8050d8f1ef1c5cd9db5c32af2d5ce19 Signed-off-by: Sam Hague --- .../ovsdb/openstack/netvirt/it/NetvirtIT.java | 106 +++-- .../src/main/config/default-config.xml | 1 + .../netvirt/providers/ConfigActivator.java | 20 +- .../providers/NetvirtProvidersConfigImpl.java | 118 +++++ .../providers/NetvirtProvidersProvider.java | 26 +- .../openflow13/AbstractServiceInstance.java | 29 +- .../providers/openflow13/OF13Provider.java | 7 +- .../openflow13/PipelineOrchestrator.java | 2 + .../openflow13/PipelineOrchestratorImpl.java | 31 +- .../services/ClassifierService.java | 30 +- .../arp/GatewayMacResolverService.java | 3 +- .../rev150513/NetvirtProvidersImplModule.java | 3 +- .../main/yang/netvirt-providers-config.yang | 20 + .../src/main/yang/netvirt-providers-impl.yang | 6 + .../NetvirtProvidersProviderTest.java | 61 +++ .../AbstractServiceInstanceTest.java | 22 +- .../PipelineOrchestratorImplTest.java | 20 +- .../services/SfcClassifierService.java | 16 +- .../openstack/netvirt/sfc/NetvirtSfcIT.java | 410 ++++++++++-------- .../openstack/netvirt/sfc/utils/AclUtils.java | 7 + .../netvirt/api/ClassifierProvider.java | 1 + 21 files changed, 682 insertions(+), 257 deletions(-) create mode 100644 openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/NetvirtProvidersConfigImpl.java create mode 100644 openstack/net-virt-providers/src/main/yang/netvirt-providers-config.yang create mode 100644 openstack/net-virt-providers/src/test/java/org/opendaylight/ovsdb/openstack/netvirt/providers/NetvirtProvidersProviderTest.java diff --git a/openstack/net-virt-it/src/test/java/org/opendaylight/ovsdb/openstack/netvirt/it/NetvirtIT.java b/openstack/net-virt-it/src/test/java/org/opendaylight/ovsdb/openstack/netvirt/it/NetvirtIT.java index 2bef4e5279..f35a1f1050 100644 --- a/openstack/net-virt-it/src/test/java/org/opendaylight/ovsdb/openstack/netvirt/it/NetvirtIT.java +++ b/openstack/net-virt-it/src/test/java/org/opendaylight/ovsdb/openstack/netvirt/it/NetvirtIT.java @@ -26,11 +26,7 @@ import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.keepRunti import com.google.common.collect.Lists; import com.google.common.collect.Maps; -import java.net.InetAddress; -import java.net.NetworkInterface; -import java.net.UnknownHostException; import java.util.ArrayList; -import java.util.Enumeration; import java.util.List; import java.util.Map; import java.util.Properties; @@ -56,12 +52,10 @@ import org.opendaylight.neutron.spi.NeutronSubnet; import org.opendaylight.ovsdb.lib.notation.Version; import org.opendaylight.ovsdb.openstack.netvirt.NetworkHandler; import org.opendaylight.ovsdb.openstack.netvirt.api.BridgeConfigurationManager; -import org.opendaylight.ovsdb.openstack.netvirt.api.Constants; import org.opendaylight.ovsdb.openstack.netvirt.api.Southbound; +import org.opendaylight.ovsdb.openstack.netvirt.providers.NetvirtProvidersProvider; import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.PipelineOrchestrator; import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.Service; -import org.opendaylight.ovsdb.southbound.SouthboundMapper; -import org.opendaylight.ovsdb.utils.config.ConfigProperties; import org.opendaylight.ovsdb.utils.mdsal.openflow.FlowUtils; import org.opendaylight.ovsdb.utils.mdsal.utils.MdsalUtils; import org.opendaylight.ovsdb.utils.servicehelper.ServiceHelper; @@ -72,19 +66,12 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.ta import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.*; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntry; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfo; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.InterfaceTypeEntryBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ManagerEntry; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.OpenvswitchOtherConfigs; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology; -import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId; -import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node; -import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder; -import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointBuilder; -import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.ops4j.pax.exam.Configuration; import org.ops4j.pax.exam.Option; @@ -105,7 +92,6 @@ import org.slf4j.LoggerFactory; @ExamReactorStrategy(PerClass.class) public class NetvirtIT extends AbstractMdsalTestBase { private static final Logger LOG = LoggerFactory.getLogger(NetvirtIT.class); - private static final int OVSDB_UPDATE_TIMEOUT = 1000; private static DataBroker dataBroker = null; private static String addressStr; private static String portStr; @@ -114,6 +100,7 @@ public class NetvirtIT extends AbstractMdsalTestBase { private static AtomicBoolean setup = new AtomicBoolean(false); private static MdsalUtils mdsalUtils = null; private static Southbound southbound = null; + private static PipelineOrchestrator pipelineOrchestrator = null; private static SouthboundUtils southboundUtils; private static NeutronUtils neutronUtils = new NeutronUtils(); private static final String NETVIRT_TOPOLOGY_ID = "netvirt:1"; @@ -258,6 +245,9 @@ public class NetvirtIT extends AbstractMdsalTestBase { southbound = (Southbound) ServiceHelper.getGlobalInstance(Southbound.class, this); assertNotNull("southbound should not be null", southbound); southboundUtils = new SouthboundUtils(mdsalUtils); + pipelineOrchestrator = + (PipelineOrchestrator) ServiceHelper.getGlobalInstance(PipelineOrchestrator.class, this); + assertNotNull("pipelineOrchestrator should not be null", pipelineOrchestrator); setup.set(true); } @@ -348,11 +338,15 @@ public class NetvirtIT extends AbstractMdsalTestBase { return true; } + // This is an extra test for local testing and testNetVirt covers this is more detail + @Ignore @Test public void testAddDeleteOvsdbNode() throws InterruptedException { LOG.info("testAddDeleteOvsdbNode enter"); ConnectionInfo connectionInfo = SouthboundUtils.getConnectionInfo(addressStr, portStr); - connectOvsdbNode(connectionInfo); + Node ovsdbNode = connectOvsdbNode(connectionInfo); + assertNotNull("connection failed", ovsdbNode); + LOG.info("testNetVirt: should be connected: {}", ovsdbNode.getNodeId()); assertTrue("Controller " + SouthboundUtils.connectionInfoToString(connectionInfo) + " is not connected", isControllerConnected(connectionInfo)); @@ -363,6 +357,51 @@ public class NetvirtIT extends AbstractMdsalTestBase { LOG.info("testAddDeleteOvsdbNode exit"); } + // TODO add tests for when L3 is enabled and check for br-ex + + // This is an extra test for local testing and testNetVirt covers this is more detail + @Ignore + @Test + public void testAddDeleteOvsdbNodeWithTableOffset() throws InterruptedException { + LOG.info("testAddDeleteOvsdbNodeWithTableOffset enter"); + NetvirtProvidersProvider.setTableOffset((short)1); + ConnectionInfo connectionInfo = SouthboundUtils.getConnectionInfo(addressStr, portStr); + Node ovsdbNode = connectOvsdbNode(connectionInfo); + assertNotNull("connection failed", ovsdbNode); + LOG.info("testNetVirt: should be connected: {}", ovsdbNode.getNodeId()); + + assertTrue("Controller " + SouthboundUtils.connectionInfoToString(connectionInfo) + + " is not connected", isControllerConnected(connectionInfo)); + + // Verify the pipeline flows were installed + Node bridgeNode = southbound.getBridgeNode(ovsdbNode, NetvirtITConstants.INTEGRATION_BRIDGE_NAME); + assertNotNull("bridge " + NetvirtITConstants.INTEGRATION_BRIDGE_NAME + " was not found", bridgeNode); + long datapathId = southbound.getDataPathId(bridgeNode); + String datapathIdString = southbound.getDatapathId(bridgeNode); + LOG.info("testNetVirt: bridgeNode: {}, datapathId: {} - {}", bridgeNode, datapathIdString, datapathId); + assertNotEquals("datapathId was not found", datapathId, 0); + + List staticPipeline = pipelineOrchestrator.getStaticPipeline(); + List staticPipelineFound = Lists.newArrayList(); + for (Service service : pipelineOrchestrator.getServiceRegistry().keySet()) { + if (staticPipeline.contains(service)) { + staticPipelineFound.add(service); + } + String flowId = "DEFAULT_PIPELINE_FLOW_" + pipelineOrchestrator.getTable(service); + verifyFlow(datapathId, flowId, service); + } + assertEquals("did not find all expected flows in static pipeline", + staticPipeline.size(), staticPipelineFound.size()); + + String flowId = "TableOffset_" + pipelineOrchestrator.getTable(Service.CLASSIFIER); + verifyFlow(datapathId, flowId, Service.CLASSIFIER.getTable()); + + Assert.assertTrue(southboundUtils.deleteBridge(connectionInfo, NetvirtITConstants.INTEGRATION_BRIDGE_NAME)); + Thread.sleep(1000); + Assert.assertTrue(disconnectOvsdbNode(connectionInfo)); + LOG.info("testAddDeleteOvsdbNodeWithTableOffset exit"); + } + private boolean isControllerConnected(ConnectionInfo connectionInfo) throws InterruptedException { LOG.info("isControllerConnected enter"); Boolean connected = false; @@ -372,7 +411,7 @@ public class NetvirtIT extends AbstractMdsalTestBase { BridgeConfigurationManager bridgeConfigurationManager = (BridgeConfigurationManager) ServiceHelper.getGlobalInstance(BridgeConfigurationManager.class, this); - assertNotNull("Could not find PipelineOrchestrator Service", bridgeConfigurationManager); + assertNotNull("Could not find BridgeConfigurationManager Service", bridgeConfigurationManager); String controllerTarget = bridgeConfigurationManager.getControllersFromOvsdbNode(ovsdbNode).get(0); Assert.assertNotNull("Failed to get controller target", controllerTarget); @@ -434,20 +473,19 @@ public class NetvirtIT extends AbstractMdsalTestBase { LOG.info("testNetVirt: starting test"); ConnectionInfo connectionInfo = SouthboundUtils.getConnectionInfo(addressStr, portStr); Node ovsdbNode = connectOvsdbNode(connectionInfo); - LOG.info("testNetVirt: should be connected"); + assertNotNull("connection failed", ovsdbNode); + LOG.info("testNetVirt: should be connected: {}", ovsdbNode.getNodeId()); //TODO use controller value rather that ovsdb connectionInfo or change log assertTrue("Controller " + SouthboundUtils.connectionInfoToString(connectionInfo) + " is not connected", isControllerConnected(connectionInfo)); // Verify the pipeline flows were installed - PipelineOrchestrator pipelineOrchestrator = - (PipelineOrchestrator) ServiceHelper.getGlobalInstance(PipelineOrchestrator.class, this); - assertNotNull("Could not find PipelineOrchestrator Service", pipelineOrchestrator); Node bridgeNode = southbound.getBridgeNode(ovsdbNode, NetvirtITConstants.INTEGRATION_BRIDGE_NAME); assertNotNull("bridge " + NetvirtITConstants.INTEGRATION_BRIDGE_NAME + " was not found", bridgeNode); - LOG.info("testNetVirt: bridgeNode: {}", bridgeNode); long datapathId = southbound.getDataPathId(bridgeNode); + String datapathIdString = southbound.getDatapathId(bridgeNode); + LOG.info("testNetVirt: bridgeNode: {}, datapathId: {} - {}", bridgeNode, datapathIdString, datapathId); assertNotEquals("datapathId was not found", datapathId, 0); List staticPipeline = pipelineOrchestrator.getStaticPipeline(); @@ -456,8 +494,8 @@ public class NetvirtIT extends AbstractMdsalTestBase { if (staticPipeline.contains(service)) { staticPipelineFound.add(service); } - String flowId = "DEFAULT_PIPELINE_FLOW_" + service.getTable(); - verifyFlow(datapathId, flowId, service.getTable()); + String flowId = "DEFAULT_PIPELINE_FLOW_" + pipelineOrchestrator.getTable(service); + verifyFlow(datapathId, flowId, service); } assertEquals("did not find all expected flows in static pipeline", staticPipeline.size(), staticPipelineFound.size()); @@ -467,7 +505,6 @@ public class NetvirtIT extends AbstractMdsalTestBase { OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation = southbound.getTerminationPointOfBridge(bridgeNode, NetvirtITConstants.PORT_NAME); Assert.assertNotNull("Did not find " + NetvirtITConstants.PORT_NAME, ovsdbTerminationPointAugmentation); - Thread.sleep(1000); Assert.assertTrue(southboundUtils.deleteBridge(connectionInfo, NetvirtITConstants.INTEGRATION_BRIDGE_NAME)); Thread.sleep(1000); Assert.assertTrue(disconnectOvsdbNode(connectionInfo)); @@ -484,9 +521,9 @@ public class NetvirtIT extends AbstractMdsalTestBase { final String dhcpPortId ="521e29d6-67b8-4b3c-8633-027d21195115"; ConnectionInfo connectionInfo = SouthboundUtils.getConnectionInfo(addressStr, portStr); - assertNotNull("connection failed", southboundUtils.connectOvsdbNode(connectionInfo)); Node ovsdbNode = connectOvsdbNode(connectionInfo); - assertNotNull("node is not connected", ovsdbNode); + assertNotNull("connection failed", ovsdbNode); + LOG.info("testNetVirtFixedSG: should be connected: {}", ovsdbNode.getNodeId()); // Verify the minimum version required for this test OvsdbNodeAugmentation ovsdbNodeAugmentation = ovsdbNode.getAugmentation(OvsdbNodeAugmentation.class); @@ -509,6 +546,8 @@ public class NetvirtIT extends AbstractMdsalTestBase { Node bridgeNode = southbound.getBridgeNode(ovsdbNode, NetvirtITConstants.INTEGRATION_BRIDGE_NAME); assertNotNull("bridge " + NetvirtITConstants.INTEGRATION_BRIDGE_NAME + " was not found", bridgeNode); long datapathId = southbound.getDataPathId(bridgeNode); + String datapathIdString = southbound.getDatapathId(bridgeNode); + LOG.info("testNetVirtFixedSG: bridgeNode: {}, datapathId: {} - {}", bridgeNode, datapathIdString, datapathId); assertNotEquals("datapathId was not found", datapathId, 0); NeutronNetwork nn = neutronUtils.createNeutronNetwork(networkId, tenantId, @@ -533,7 +572,7 @@ public class NetvirtIT extends AbstractMdsalTestBase { Thread.sleep(1000); String flowId = "Egress_DHCP_Client" + "_Permit_"; - verifyFlow(datapathId, flowId, Service.EGRESS_ACL.getTable()); + verifyFlow(datapathId, flowId, Service.EGRESS_ACL); testDefaultSG(nport, datapathId, nn, tenantId, portId); Thread.sleep(1000); @@ -596,10 +635,10 @@ public class NetvirtIT extends AbstractMdsalTestBase { Thread.sleep(10000); String flowId = "Egress_IP" + nn.getProviderSegmentationID() + "_" + nport.getMacAddress() + "_Permit_"; - verifyFlow(datapathId, flowId, Service.EGRESS_ACL.getTable()); + verifyFlow(datapathId, flowId, Service.EGRESS_ACL); flowId = "Ingress_IP" + nn.getProviderSegmentationID() + "_" + nport.getMacAddress() + "_Permit_"; - verifyFlow(datapathId, flowId, Service.INGRESS_ACL.getTable()); + verifyFlow(datapathId, flowId, Service.INGRESS_ACL); } private Flow getFlow ( @@ -629,6 +668,11 @@ public class NetvirtIT extends AbstractMdsalTestBase { Flow flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.CONFIGURATION); assertNotNull("Could not find flow in config: " + flowBuilder.build() + "--" + nodeBuilder.build(), flow); flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.OPERATIONAL); - assertNotNull("Could not find flow in operational: " + flowBuilder.build() + "--" + nodeBuilder.build(), flow); + assertNotNull("Could not find flow in operational: " + flowBuilder.build() + "--" + nodeBuilder.build(), + flow); + } + + private void verifyFlow(long datapathId, String flowId, Service service) throws InterruptedException { + verifyFlow(datapathId, flowId, pipelineOrchestrator.getTable(service)); } } diff --git a/openstack/net-virt-providers/src/main/config/default-config.xml b/openstack/net-virt-providers/src/main/config/default-config.xml index cdbbec28ac..50c4d778ff 100644 --- a/openstack/net-virt-providers/src/main/config/default-config.xml +++ b/openstack/net-virt-providers/src/main/config/default-config.xml @@ -13,6 +13,7 @@ prefix:netvirt-providers-impl netvirt-providers-default + 0 binding:binding-broker-osgi-registry binding-osgi-broker diff --git a/openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/ConfigActivator.java b/openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/ConfigActivator.java index 9da80ffdfb..690fee0522 100644 --- a/openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/ConfigActivator.java +++ b/openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/ConfigActivator.java @@ -8,6 +8,12 @@ package org.opendaylight.ovsdb.openstack.netvirt.providers; +import java.util.ArrayList; +import java.util.Dictionary; +import java.util.Hashtable; +import java.util.List; + +import org.opendaylight.controller.md.sal.binding.api.DataBroker; import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext; import org.opendaylight.controller.sal.binding.api.NotificationProviderService; import org.opendaylight.ovsdb.openstack.netvirt.api.ArpProvider; @@ -53,11 +59,6 @@ import org.osgi.util.tracker.ServiceTracker; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.ArrayList; -import java.util.Dictionary; -import java.util.Hashtable; -import java.util.List; - public class ConfigActivator implements BundleActivator { private static final Logger LOG = LoggerFactory.getLogger(ConfigActivator.class); private List> registrations = new ArrayList<>(); @@ -71,6 +72,13 @@ public class ConfigActivator implements BundleActivator { public void start(BundleContext context) throws Exception { LOG.info("ConfigActivator start:"); + NetvirtProvidersConfigImpl netvirtProvidersConfig = + new NetvirtProvidersConfigImpl(providerContext.getSALService(DataBroker.class), + NetvirtProvidersProvider.getTableOffset()); + registerService(context, + new String[] {NetvirtProvidersConfigImpl.class.getName()}, + null, netvirtProvidersConfig); + PipelineOrchestratorImpl pipelineOrchestrator = new PipelineOrchestratorImpl(); registerService(context, new String[] {PipelineOrchestrator.class.getName(),NodeCacheListener.class.getName()}, @@ -133,7 +141,7 @@ public class ConfigActivator implements BundleActivator { gatewayMacResolverService, Service.GATEWAY_RESOLVER); getNotificationProviderService().registerNotificationListener(gatewayMacResolverService); - + netvirtProvidersConfig.setDependencies(context, null); pipelineOrchestrator.setDependencies(context, null); outboundNatService.setDependencies(context, null); egressAclService.setDependencies(context, null); diff --git a/openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/NetvirtProvidersConfigImpl.java b/openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/NetvirtProvidersConfigImpl.java new file mode 100644 index 0000000000..d2536b6d6c --- /dev/null +++ b/openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/NetvirtProvidersConfigImpl.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2016 Red Hat, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.ovsdb.openstack.netvirt.providers; + +import java.util.Map; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.DataChangeListener; +import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker; +import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.ovsdb.openstack.netvirt.api.Action; +import org.opendaylight.ovsdb.openstack.netvirt.api.OvsdbInventoryListener; +import org.opendaylight.ovsdb.utils.mdsal.utils.MdsalUtils; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.providers.config.rev160109.*; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceReference; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class NetvirtProvidersConfigImpl implements AutoCloseable, ConfigInterface, DataChangeListener { + private static final Logger LOG = LoggerFactory.getLogger(NetvirtProvidersConfigImpl.class); + private final DataBroker dataBroker; + private final ListenerRegistration registration; + private final ExecutorService executorService = Executors.newFixedThreadPool(1); + private final MdsalUtils mdsalUtils; + + public NetvirtProvidersConfigImpl(final DataBroker dataBroker, final short tableOffset) { + this.dataBroker = dataBroker; + mdsalUtils = new MdsalUtils(dataBroker); + + InstanceIdentifier path = + InstanceIdentifier.builder(NetvirtProvidersConfig.class).build(); + registration = dataBroker.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION, path, this, + AsyncDataBroker.DataChangeScope.SUBTREE); + + NetvirtProvidersConfigBuilder netvirtProvidersConfigBuilder = new NetvirtProvidersConfigBuilder(); + NetvirtProvidersConfig netvirtProvidersConfig = + mdsalUtils.read(LogicalDatastoreType.CONFIGURATION, path); + if (netvirtProvidersConfig != null) { + netvirtProvidersConfigBuilder = new NetvirtProvidersConfigBuilder(netvirtProvidersConfig); + } + if (netvirtProvidersConfigBuilder.getTableOffset() == null) { + netvirtProvidersConfigBuilder.setTableOffset(tableOffset); + } + boolean result = mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, path, + netvirtProvidersConfigBuilder.build()); + + LOG.info("NetvirtProvidersConfigImpl: dataBroker= {}, registration= {}, tableOffset= {}, result= {}", + dataBroker, registration, tableOffset, result); + } + + @Override + public void close() throws Exception { + registration.close(); + executorService.shutdown(); + } + + @Override + public void onDataChanged(final AsyncDataChangeEvent, DataObject> asyncDataChangeEvent) { + executorService.submit(new Runnable() { + + @Override + public void run() { + LOG.info("onDataChanged: {}", asyncDataChangeEvent); + processConfigCreate(asyncDataChangeEvent); + processConfigUpdate(asyncDataChangeEvent); + } + }); + } + + private void processConfigCreate(AsyncDataChangeEvent, DataObject> changes) { + for (Map.Entry, DataObject> entry : changes.getCreatedData().entrySet()) { + if (entry.getValue() instanceof NetvirtProvidersConfig) { + NetvirtProvidersConfig netvirtProvidersConfig = (NetvirtProvidersConfig) entry.getValue(); + applyConfig(netvirtProvidersConfig); + } + } + } + + private void processConfigUpdate(AsyncDataChangeEvent, DataObject> changes) { + for (Map.Entry, DataObject> entry : changes.getUpdatedData().entrySet()) { + if (entry.getValue() instanceof NetvirtProvidersConfig) { + LOG.info("processConfigUpdate: {}", entry); + NetvirtProvidersConfig netvirtProvidersConfig = (NetvirtProvidersConfig) entry.getValue(); + applyConfig(netvirtProvidersConfig); + } + } + } + + private void applyConfig(NetvirtProvidersConfig netvirtProvidersConfig) { + LOG.info("processConfigUpdate: {}", netvirtProvidersConfig); + if (netvirtProvidersConfig.getTableOffset() != null) { + NetvirtProvidersProvider.setTableOffset(netvirtProvidersConfig.getTableOffset()); + } + } + + @Override + public void setDependencies(BundleContext bundleContext, ServiceReference serviceReference) { + + } + + @Override + public void setDependencies(Object impl) { + + } +} diff --git a/openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/NetvirtProvidersProvider.java b/openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/NetvirtProvidersProvider.java index 86556f6d48..e370ed142c 100644 --- a/openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/NetvirtProvidersProvider.java +++ b/openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/NetvirtProvidersProvider.java @@ -20,6 +20,8 @@ import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipL import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService; import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext; import org.opendaylight.controller.sal.binding.api.BindingAwareProvider; +import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.Service; +import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.TableId; import org.osgi.framework.BundleContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -39,11 +41,14 @@ public class NetvirtProvidersProvider implements BindingAwareProvider, AutoClose private static EntityOwnershipService entityOwnershipService; private ProviderEntityListener providerEntityListener = null; private static AtomicBoolean hasProviderEntityOwnership = new AtomicBoolean(false); + private static short tableOffset; + private NetvirtProvidersConfigImpl netvirtProvidersConfig = null; - public NetvirtProvidersProvider(BundleContext bundleContext, EntityOwnershipService eos) { + public NetvirtProvidersProvider(BundleContext bundleContext, EntityOwnershipService eos, short tableOffset) { LOG.info("NetvirtProvidersProvider: bundleContext: {}", bundleContext); this.bundleContext = bundleContext; - entityOwnershipService = eos; + entityOwnershipService = eos; + setTableOffset(tableOffset); } public static DataBroker getDataBroker() { @@ -58,6 +63,23 @@ public class NetvirtProvidersProvider implements BindingAwareProvider, AutoClose return hasProviderEntityOwnership.get(); } + public static void setTableOffset(short tableOffset) { + try { + new TableId((short) (tableOffset + Service.L2_FORWARDING.getTable())); + } catch (IllegalArgumentException e) { + LOG.warn("Invalid table offset: {}", tableOffset, e); + return; + } + + LOG.info("setTableOffset: changing from {} to {}", + NetvirtProvidersProvider.tableOffset, tableOffset); + NetvirtProvidersProvider.tableOffset = tableOffset; + } + + public static short getTableOffset() { + return tableOffset; + } + @Override public void close() throws Exception { LOG.info("NetvirtProvidersProvider closed"); diff --git a/openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/AbstractServiceInstance.java b/openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/AbstractServiceInstance.java index 0727f3e0bf..3835bed28d 100644 --- a/openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/AbstractServiceInstance.java +++ b/openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/AbstractServiceInstance.java @@ -86,8 +86,21 @@ public abstract class AbstractServiceInstance { return bridgeName != null && Constants.INTEGRATION_BRIDGE.equals(bridgeName); } + /** + * Return the offset adjusted table for this {@link Service} + * @return The table id + */ public short getTable() { - return service.getTable(); + return (short)(orchestrator.getTableOffset() + service.getTable()); + } + + /** + * Return the offset adjusted table for the given {@link Service} + * @param service Identifies the openflow {@link Service} + * @return The table id + */ + public short getTable(Service service) { + return (short)(orchestrator.getTableOffset() + service.getTable()); } public Service getService() { @@ -132,7 +145,8 @@ public abstract class AbstractServiceInstance { protected final InstructionBuilder getMutablePipelineInstructionBuilder() { Service nextService = orchestrator.getNextServiceInPipeline(service); if (nextService != null) { - return InstructionUtils.createGotoTableInstructions(new InstructionBuilder(), nextService.getTable()); + return InstructionUtils.createGotoTableInstructions(new InstructionBuilder(), + orchestrator.getTable(nextService)); } else { return InstructionUtils.createDropInstructions(new InstructionBuilder()); } @@ -140,19 +154,14 @@ public abstract class AbstractServiceInstance { protected void writeFlow(FlowBuilder flowBuilder, NodeBuilder nodeBuilder) { if (NetvirtProvidersProvider.isMasterProviderInstance()) { - LOG.debug("writeFlow 3: flowBuilder: {}, nodeBuilder: {}", + LOG.debug("writeFlow: flowBuilder: {}, nodeBuilder: {}", flowBuilder.build(), nodeBuilder.build()); WriteTransaction modification = dataBroker.newWriteOnlyTransaction(); - LOG.debug("writeFlow: about to put nodePath for Flow {}, nodePath: {}", - flowBuilder.getFlowName(), createNodePath(nodeBuilder)); modification.put(LogicalDatastoreType.CONFIGURATION, createNodePath(nodeBuilder), nodeBuilder.build(), true /*createMissingParents*/); - LOG.debug("writeFlow: about to put Flow {}", flowBuilder.getFlowName()); modification.put(LogicalDatastoreType.CONFIGURATION, createFlowPath(flowBuilder, nodeBuilder), flowBuilder.build(), true /*createMissingParents*/); - LOG.debug("writeFlow: about to submit Flow {}", flowBuilder.getFlowName()); CheckedFuture commitFuture = modification.submit(); - LOG.debug("writeFlow: checking status of Flow {}", flowBuilder.getFlowName()); try { commitFuture.checkedGet(); // TODO: Make it async (See bug 1362) LOG.debug("Transaction success for write of Flow {}", flowBuilder.getFlowName()); @@ -259,13 +268,13 @@ public abstract class AbstractServiceInstance { // Add InstructionsBuilder to FlowBuilder flowBuilder.setInstructions(isb.build()); - String flowId = "DEFAULT_PIPELINE_FLOW_"+service.getTable(); + String flowId = "DEFAULT_PIPELINE_FLOW_" + getTable(); flowBuilder.setId(new FlowId(flowId)); FlowKey key = new FlowKey(new FlowId(flowId)); flowBuilder.setMatch(matchBuilder.build()); flowBuilder.setPriority(0); flowBuilder.setBarrier(false); - flowBuilder.setTableId(service.getTable()); + flowBuilder.setTableId(getTable()); flowBuilder.setKey(key); flowBuilder.setFlowName(flowId); flowBuilder.setHardTimeout(0); diff --git a/openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/OF13Provider.java b/openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/OF13Provider.java index c46211f46c..f27e742e46 100644 --- a/openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/OF13Provider.java +++ b/openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/OF13Provider.java @@ -1259,6 +1259,11 @@ public class OF13Provider implements ConfigInterface, NetworkingProvider { writeLLDPRule(dpid); + if (bridgeName.equals(configurationService.getIntegrationBridgeName()) && + NetvirtProvidersProvider.getTableOffset() != 0) { + classifierProvider.programGotoTable(dpid,true); + } + if (bridgeName.equals(configurationService.getExternalBridgeName())) { writeNormalRule(dpid); } @@ -1286,7 +1291,7 @@ public class OF13Provider implements ConfigInterface, NetworkingProvider { NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong); FlowBuilder flowBuilder = new FlowBuilder(); String flowName = "NORMAL"; - FlowUtils.initFlowBuilder(flowBuilder, flowName, (short)0).setPriority(0); + FlowUtils.initFlowBuilder(flowBuilder, flowName, Service.CLASSIFIER.getTable()).setPriority(0); MatchBuilder matchBuilder = new MatchBuilder(); flowBuilder.setMatch(matchBuilder.build()); diff --git a/openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/PipelineOrchestrator.java b/openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/PipelineOrchestrator.java index 6f8a197282..327f45ecb8 100644 --- a/openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/PipelineOrchestrator.java +++ b/openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/PipelineOrchestrator.java @@ -24,6 +24,8 @@ public interface PipelineOrchestrator { Service getNextServiceInPipeline(Service service); AbstractServiceInstance getServiceInstance(Service service); Map getServiceRegistry(); + short getTableOffset(); + short getTable(Service service); List getStaticPipeline(); void enqueue(Node node); void registerService(final ServiceReference ref, AbstractServiceInstance serviceInstance); diff --git a/openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/PipelineOrchestratorImpl.java b/openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/PipelineOrchestratorImpl.java index 299ab21a08..47ddf3329c 100644 --- a/openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/PipelineOrchestratorImpl.java +++ b/openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/PipelineOrchestratorImpl.java @@ -21,6 +21,7 @@ import org.opendaylight.ovsdb.openstack.netvirt.api.NodeCacheListener; import org.opendaylight.ovsdb.openstack.netvirt.api.NodeCacheManager; import org.opendaylight.ovsdb.openstack.netvirt.api.Southbound; import org.opendaylight.ovsdb.openstack.netvirt.providers.ConfigInterface; +import org.opendaylight.ovsdb.openstack.netvirt.providers.NetvirtProvidersProvider; import org.opendaylight.ovsdb.utils.servicehelper.ServiceHelper; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node; import org.osgi.framework.BundleContext; @@ -34,6 +35,25 @@ import com.google.common.collect.Maps; public class PipelineOrchestratorImpl implements ConfigInterface, NodeCacheListener, PipelineOrchestrator { private static final Logger LOG = LoggerFactory.getLogger(PipelineOrchestratorImpl.class); + /** + * Return the current table offset + * @return The table offset + */ + @Override + public short getTableOffset() { + return NetvirtProvidersProvider.getTableOffset(); + } + + /** + * Return the offset adjusted table for the given {@link Service} + * @param service Identifies the openflow {@link Service} + * @return The table id + */ + @Override + public short getTable(Service service) { + return (short)(getTableOffset() + service.getTable()); + } + public List getStaticPipeline() { return staticPipeline; } @@ -119,11 +139,14 @@ public class PipelineOrchestratorImpl implements ConfigInterface, NodeCacheListe while (true) { Node node = queue.take(); LOG.info(">>>>> dequeue: {}", node); - for (Service service : staticPipeline) { - AbstractServiceInstance serviceInstance = getServiceInstance(service); - if (serviceInstance != null && southbound.getBridge(node) != null) { - serviceInstance.programDefaultPipelineRule(node); + if (southbound.getBridge(node) != null) { + for (Service service : staticPipeline) { + AbstractServiceInstance serviceInstance = getServiceInstance(service); + if (serviceInstance != null) { + serviceInstance.programDefaultPipelineRule(node); + } } + // TODO: might need a flow to go from table 0 to the pipeline } } } catch (Exception e) { diff --git a/openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/services/ClassifierService.java b/openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/services/ClassifierService.java index 385628fa94..b0b84209e3 100644 --- a/openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/services/ClassifierService.java +++ b/openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/services/ClassifierService.java @@ -334,7 +334,7 @@ public class ClassifierService extends AbstractServiceInstance implements Classi NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong); FlowBuilder flowBuilder = new FlowBuilder(); String flowName = "LLDP"; - FlowUtils.initFlowBuilder(flowBuilder, flowName, getTable()); + FlowUtils.initFlowBuilder(flowBuilder, flowName, Service.CLASSIFIER.getTable()); MatchBuilder matchBuilder = new MatchBuilder(); MatchUtils.createEtherTypeMatch(matchBuilder, new EtherType(0x88CCL)); @@ -362,6 +362,34 @@ public class ClassifierService extends AbstractServiceInstance implements Classi writeFlow(flowBuilder, nodeBuilder); } + @Override + public void programGotoTable(Long dpidLong, boolean write) { + NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong); + FlowBuilder flowBuilder = new FlowBuilder(); + String flowName = "TableOffset_" + getTable(); + FlowUtils.initFlowBuilder(flowBuilder, flowName, Service.CLASSIFIER.getTable()) + .setPriority(0); + + MatchBuilder matchBuilder = new MatchBuilder(); + flowBuilder.setMatch(matchBuilder.build()); + + if (write) { + InstructionsBuilder isb = new InstructionsBuilder(); + List instructions = Lists.newArrayList(); + InstructionBuilder ib = + InstructionUtils.createGotoTableInstructions(new InstructionBuilder(), getTable()); + ib.setOrder(0); + ib.setKey(new InstructionKey(0)); + instructions.add(ib.build()); + + isb.setInstruction(instructions); + flowBuilder.setInstructions(isb.build()); + writeFlow(flowBuilder, nodeBuilder); + } else { + removeFlow(flowBuilder, nodeBuilder); + } + } + @Override public void setDependencies(BundleContext bundleContext, ServiceReference serviceReference) { super.setDependencies(bundleContext.getServiceReference(ClassifierProvider.class.getName()), this); diff --git a/openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/services/arp/GatewayMacResolverService.java b/openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/services/arp/GatewayMacResolverService.java index be01ac5a0c..1113038033 100644 --- a/openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/services/arp/GatewayMacResolverService.java +++ b/openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/services/arp/GatewayMacResolverService.java @@ -93,7 +93,6 @@ public class GatewayMacResolverService extends AbstractServiceInstance implements ConfigInterface, GatewayMacResolver,PacketProcessingListener { private static final Logger LOG = LoggerFactory.getLogger(GatewayMacResolverService.class); - private static final short TABLE_FOR_ARP_FLOW = 0; private static final String ARP_REPLY_TO_CONTROLLER_FLOW_NAME = "GatewayArpReplyRouter"; private static final int ARP_REPLY_TO_CONTROLLER_FLOW_PRIORITY = 10000; private static final Instruction SEND_TO_CONTROLLER_INSTRUCTION; @@ -383,7 +382,7 @@ public class GatewayMacResolverService extends AbstractServiceInstance private Flow createArpReplyToControllerFlow(final ArpMessageAddress senderAddress, final Ipv4Address ipForRequestedMac) { checkNotNull(senderAddress); checkNotNull(ipForRequestedMac); - FlowBuilder arpFlow = new FlowBuilder().setTableId(TABLE_FOR_ARP_FLOW) + FlowBuilder arpFlow = new FlowBuilder().setTableId(Service.CLASSIFIER.getTable()) .setFlowName(ARP_REPLY_TO_CONTROLLER_FLOW_NAME) .setPriority(ARP_REPLY_TO_CONTROLLER_FLOW_PRIORITY) .setBufferId(OFConstants.OFP_NO_BUFFER) diff --git a/openstack/net-virt-providers/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/netvirt/providers/impl/rev150513/NetvirtProvidersImplModule.java b/openstack/net-virt-providers/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/netvirt/providers/impl/rev150513/NetvirtProvidersImplModule.java index eaed95c249..cd0a23c096 100644 --- a/openstack/net-virt-providers/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/netvirt/providers/impl/rev150513/NetvirtProvidersImplModule.java +++ b/openstack/net-virt-providers/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/netvirt/providers/impl/rev150513/NetvirtProvidersImplModule.java @@ -22,7 +22,8 @@ public class NetvirtProvidersImplModule extends org.opendaylight.yang.gen.v1.urn @Override public java.lang.AutoCloseable createInstance() { - NetvirtProvidersProvider provider = new NetvirtProvidersProvider(bundleContext, getClusteringEntityOwnershipServiceDependency()); + NetvirtProvidersProvider provider = new NetvirtProvidersProvider(bundleContext, + getClusteringEntityOwnershipServiceDependency(), getTableOffset()); BindingAwareBroker localBroker = getBrokerDependency(); localBroker.registerProvider(provider); return provider; diff --git a/openstack/net-virt-providers/src/main/yang/netvirt-providers-config.yang b/openstack/net-virt-providers/src/main/yang/netvirt-providers-config.yang new file mode 100644 index 0000000000..780b0204e9 --- /dev/null +++ b/openstack/net-virt-providers/src/main/yang/netvirt-providers-config.yang @@ -0,0 +1,20 @@ +module netvirt-providers-config { + yang-version 1; + namespace "urn:opendaylight:params:xml:ns:yang:netvirt:providers:config"; + prefix "netvirt-providers-config"; + + revision "2016-01-09" { + description "Initial revision of the netvirt providers config"; + } + + container netvirt-providers-config { + description "Configuration for NetvirtProviders"; + + config true; + + leaf table-offset { + description "The table-offset is used to set the starting table for the netvirt pipeline"; + type uint8; + } + } +} diff --git a/openstack/net-virt-providers/src/main/yang/netvirt-providers-impl.yang b/openstack/net-virt-providers/src/main/yang/netvirt-providers-impl.yang index a784a4b6f1..b02b37e2ad 100644 --- a/openstack/net-virt-providers/src/main/yang/netvirt-providers-impl.yang +++ b/openstack/net-virt-providers/src/main/yang/netvirt-providers-impl.yang @@ -31,6 +31,7 @@ module netvirt-providers-impl { } } } + container clustering-entity-ownership-service { uses config:service-ref { refine type { @@ -39,6 +40,11 @@ module netvirt-providers-impl { } } } + + leaf table-offset { + description "The table-offset is used to set the starting table for the netvirt pipeline"; + type uint8; + } } } } diff --git a/openstack/net-virt-providers/src/test/java/org/opendaylight/ovsdb/openstack/netvirt/providers/NetvirtProvidersProviderTest.java b/openstack/net-virt-providers/src/test/java/org/opendaylight/ovsdb/openstack/netvirt/providers/NetvirtProvidersProviderTest.java new file mode 100644 index 0000000000..32d2f72cf7 --- /dev/null +++ b/openstack/net-virt-providers/src/test/java/org/opendaylight/ovsdb/openstack/netvirt/providers/NetvirtProvidersProviderTest.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2016 Red Hat, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.ovsdb.openstack.netvirt.providers; + +import static org.junit.Assert.assertEquals; + +import org.junit.Before; +import org.junit.Test; +import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.PipelineOrchestratorImpl; +import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.Service; +import org.osgi.framework.BundleContext; + +/** + * Unit tests for {@link NetvirtProvidersProvider} + */ +public class NetvirtProvidersProviderTest { + + /** + * Test for {@link NetvirtProvidersProvider#getTableOffset()} + */ + @Test + public void testGetTableOffset() { + short tableOffset = 10; + NetvirtProvidersProvider netvirtProvidersProvider = new NetvirtProvidersProvider(null, null, tableOffset); + assertEquals("Table offset was not set", tableOffset, NetvirtProvidersProvider.getTableOffset()); + } + + /** + * Test for method {@link NetvirtProvidersProvider#setTableOffset(short)} + */ + @Test + public void testSetTableOffset() { + // verify a good value can be set + short tableOffset = 0; + NetvirtProvidersProvider netvirtProvidersProvider = new NetvirtProvidersProvider(null, null, tableOffset); + + tableOffset = 10; + NetvirtProvidersProvider.setTableOffset(tableOffset); + assertEquals("tableOffset was not set", tableOffset, NetvirtProvidersProvider.getTableOffset()); + } + + /** + * Negative test for method {@link NetvirtProvidersProvider#setTableOffset(short)} + */ + @Test + public void testTableOffsetNegative() { + // verify an out of range value is not set + short tableOffset = 0; + NetvirtProvidersProvider netvirtProvidersProvider = new NetvirtProvidersProvider(null, null, tableOffset); + + short tableOffsetBad = (short)(256 - Service.L2_FORWARDING.getTable()); + NetvirtProvidersProvider.setTableOffset(tableOffsetBad); + assertEquals("tableOffset should not be set", 0, NetvirtProvidersProvider.getTableOffset()); + } +} diff --git a/openstack/net-virt-providers/src/test/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/AbstractServiceInstanceTest.java b/openstack/net-virt-providers/src/test/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/AbstractServiceInstanceTest.java index 50727a188e..bf5bed2383 100644 --- a/openstack/net-virt-providers/src/test/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/AbstractServiceInstanceTest.java +++ b/openstack/net-virt-providers/src/test/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/AbstractServiceInstanceTest.java @@ -75,7 +75,7 @@ public class AbstractServiceInstanceTest { private final String NODE_ID = Constants.INTEGRATION_BRIDGE + ":" + ID; /** - * Test method {@link AbstractServiceInstance#isBridgeInPipeline(String)} + * Test method {@link AbstractServiceInstance#isBridgeInPipeline(Node)} */ @Test public void testIsBridgeInPipeline() { @@ -89,7 +89,23 @@ public class AbstractServiceInstanceTest { @Test public void testGetTable() { abstractServiceInstance.setService(service); - assertEquals("Error, getTable() did not return the correct value", 70, abstractServiceInstance.getTable()); + assertEquals("Error, getTable() did not return the correct value", + service.getTable(), abstractServiceInstance.getTable()); + + when(orchestrator.getTableOffset()).thenReturn(Service.DIRECTOR.getTable()); + assertEquals("Error, getTable() did not return the correct value", + (short)(Service.DIRECTOR.getTable() + service.getTable()), abstractServiceInstance.getTable()); + } + + /** + * Test method {@link AbstractServiceInstance@getTable(Service} + */ + @Test + public void testGetTableWithService() { + when(orchestrator.getTableOffset()).thenReturn((short)0); + abstractServiceInstance.setService(service); + assertEquals("Error, getTables(service) did not return the correct value", + Service.L2_FORWARDING.getTable(), abstractServiceInstance.getTable(Service.L2_FORWARDING)); } @Test @@ -203,7 +219,7 @@ public class AbstractServiceInstanceTest { } /** - * Test method {@link AbstractServiceInstance#programDefaultPipelineRule(String)} + * Test method {@link AbstractServiceInstance#programDefaultPipelineRule(Node)} */ @Test public void testProgramDefaultPipelineRule() { diff --git a/openstack/net-virt-providers/src/test/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/PipelineOrchestratorImplTest.java b/openstack/net-virt-providers/src/test/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/PipelineOrchestratorImplTest.java index 947cde3338..98d6c97b7d 100644 --- a/openstack/net-virt-providers/src/test/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/PipelineOrchestratorImplTest.java +++ b/openstack/net-virt-providers/src/test/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/PipelineOrchestratorImplTest.java @@ -41,6 +41,24 @@ public class PipelineOrchestratorImplTest { @Mock private ExecutorService eventHandler; @Mock private Southbound southbound; + /** + * Test for method {@link PipelineOrchestratorImpl#getTableOffset()} + */ + @Test + public void testGetTableOffset() { + short tableOffset = 0; + assertEquals("tableOffset was not set", tableOffset, orchestrator.getTableOffset()); + } + + /** + * Test for {@link PipelineOrchestratorImpl#getTable(Service)} + */ + @Test + public void testGetTableOffsetWithService() { + assertEquals("tableOffset was not set", Service.CLASSIFIER.getTable(), + orchestrator.getTable(Service.CLASSIFIER)); + } + /*** * Registers a mock service and verifies the registration by asking the * pipeline orchestrator to return the associated service from its internal @@ -65,7 +83,7 @@ public class PipelineOrchestratorImplTest { /** * Test method - * {@link PipelineOrchestratorImplr#getNextServiceInPipeline(Service)} + * {@link PipelineOrchestratorImpl#getNextServiceInPipeline(Service)} */ @Test public void testGetNextServiceInPipeline() { diff --git a/openstack/net-virt-sfc/impl/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/workaround/services/SfcClassifierService.java b/openstack/net-virt-sfc/impl/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/workaround/services/SfcClassifierService.java index 3055544ad9..1f06202b07 100644 --- a/openstack/net-virt-sfc/impl/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/workaround/services/SfcClassifierService.java +++ b/openstack/net-virt-sfc/impl/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/workaround/services/SfcClassifierService.java @@ -53,7 +53,6 @@ import org.slf4j.LoggerFactory; public class SfcClassifierService extends AbstractServiceInstance implements ConfigInterface, ISfcClassifierService { private static final Logger LOG = LoggerFactory.getLogger(SfcClassifierService.class); - private static final short TABLE_0 = 0; private static final short UDP_SHORT = 17; static int cookieIndex = 0; @@ -161,7 +160,7 @@ public class SfcClassifierService extends AbstractServiceInstance implements Con flowBuilder.setId(new FlowId(flowId)); FlowKey key = new FlowKey(new FlowId(flowId)); flowBuilder.setBarrier(true); - flowBuilder.setTableId(TABLE_0); + flowBuilder.setTableId(getTable(Service.CLASSIFIER)); flowBuilder.setKey(key); flowBuilder.setFlowName(flowId); flowBuilder.setHardTimeout(0); @@ -203,7 +202,7 @@ public class SfcClassifierService extends AbstractServiceInstance implements Con flowBuilder.setId(new FlowId(flowId)); FlowKey key = new FlowKey(new FlowId(flowId)); flowBuilder.setBarrier(true); - flowBuilder.setTableId(TABLE_0); + flowBuilder.setTableId(getTable(Service.CLASSIFIER)); flowBuilder.setKey(key); flowBuilder.setFlowName(flowId); flowBuilder.setHardTimeout(0); @@ -244,7 +243,7 @@ public class SfcClassifierService extends AbstractServiceInstance implements Con flowBuilder.setId(new FlowId(flowId)); FlowKey key = new FlowKey(new FlowId(flowId)); flowBuilder.setBarrier(true); - flowBuilder.setTableId(TABLE_0); + flowBuilder.setTableId(getTable(Service.CLASSIFIER)); flowBuilder.setKey(key); flowBuilder.setFlowName(flowId); flowBuilder.setHardTimeout(0); @@ -271,7 +270,7 @@ public class SfcClassifierService extends AbstractServiceInstance implements Con ab.setKey(new ActionKey(actionList.size())); actionList.add(ab.build()); - ab.setAction(ActionUtils.nxResubmitAction((int)sfOfPort, TABLE_0)); + ab.setAction(ActionUtils.nxResubmitAction((int)sfOfPort, Service.CLASSIFIER.getTable())); ab.setOrder(actionList.size()); ab.setKey(new ActionKey(actionList.size())); actionList.add(ab.build()); @@ -306,7 +305,8 @@ public class SfcClassifierService extends AbstractServiceInstance implements Con NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dataPathId); FlowBuilder flowBuilder = new FlowBuilder(); String flowName = "sfcEgressClassBypass_" + nsp + "_" + + nsi + "_" + sfOfPort; - initFlowBuilder(flowBuilder, flowName, TABLE_0, FlowID.FLOW_EGRESSCLASSBYPASS).setPriority(40000); + initFlowBuilder(flowBuilder, flowName, Service.CLASSIFIER.getTable(), + FlowID.FLOW_EGRESSCLASSBYPASS).setPriority(40000); MatchBuilder matchBuilder = new MatchBuilder(); MatchUtils.createInPortMatch(matchBuilder, dataPathId, sfOfPort); @@ -373,7 +373,7 @@ public class SfcClassifierService extends AbstractServiceInstance implements Con NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dataPathId); FlowBuilder flowBuilder = new FlowBuilder(); String flowName = "sfIngress_" + dstPort + "_" + ipAddress; - initFlowBuilder(flowBuilder, flowName, TABLE_0, FlowID.FLOW_SFINGRESS); + initFlowBuilder(flowBuilder, flowName, Service.CLASSIFIER.getTable(), FlowID.FLOW_SFINGRESS); MatchBuilder matchBuilder = new MatchBuilder(); MatchUtils.createIpProtocolMatch(matchBuilder, UDP_SHORT); @@ -406,7 +406,7 @@ public class SfcClassifierService extends AbstractServiceInstance implements Con NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dataPathId); FlowBuilder flowBuilder = new FlowBuilder(); String flowName = "ArpResponder_" + ipAddress; - initFlowBuilder(flowBuilder, flowName, TABLE_0, FlowID.FLOW_SFARP).setPriority(1024); + initFlowBuilder(flowBuilder, flowName, Service.CLASSIFIER.getTable(), FlowID.FLOW_SFARP).setPriority(1024); MacAddress macAddress = new MacAddress(macAddressStr); diff --git a/openstack/net-virt-sfc/it/src/test/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/NetvirtSfcIT.java b/openstack/net-virt-sfc/it/src/test/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/NetvirtSfcIT.java index 1870c1a467..771921a768 100644 --- a/openstack/net-virt-sfc/it/src/test/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/NetvirtSfcIT.java +++ b/openstack/net-virt-sfc/it/src/test/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/NetvirtSfcIT.java @@ -8,7 +8,7 @@ package org.opendaylight.ovsdb.openstack.netvirt.sfc; -import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; @@ -26,7 +26,6 @@ import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.editConfi import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.keepRuntimeFolder; import java.io.IOException; -import java.math.BigInteger; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -42,7 +41,9 @@ import org.opendaylight.controller.md.sal.binding.api.DataBroker; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.controller.mdsal.it.base.AbstractMdsalTestBase; import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext; +import org.opendaylight.ovsdb.openstack.netvirt.api.BridgeConfigurationManager; import org.opendaylight.ovsdb.openstack.netvirt.api.Southbound; +import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.PipelineOrchestrator; import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.Service; import org.opendaylight.ovsdb.openstack.netvirt.sfc.standalone.openflow13.SfcClassifier; import org.opendaylight.ovsdb.openstack.netvirt.sfc.utils.AclUtils; @@ -53,9 +54,7 @@ import org.opendaylight.ovsdb.openstack.netvirt.sfc.utils.ServiceFunctionPathUti import org.opendaylight.ovsdb.openstack.netvirt.sfc.utils.ServiceFunctionUtils; import org.opendaylight.ovsdb.openstack.netvirt.sfc.utils.SfcUtils; import org.opendaylight.ovsdb.southbound.SouthboundConstants; -import org.opendaylight.ovsdb.southbound.SouthboundUtil; import org.opendaylight.ovsdb.utils.mdsal.openflow.FlowUtils; -import org.opendaylight.ovsdb.utils.mdsal.openflow.MatchUtils; import org.opendaylight.ovsdb.utils.mdsal.utils.MdsalUtils; import org.opendaylight.ovsdb.utils.servicehelper.ServiceHelper; import org.opendaylight.ovsdb.utils.southbound.utils.SouthboundUtils; @@ -84,17 +83,12 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.cont import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.AccessListEntriesBuilder; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.access.list.entries.AceBuilder; 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; -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; 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; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.Classifiers; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.ClassifiersBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.classifiers.ClassifierBuilder; @@ -103,6 +97,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt. import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.rev150105.Sfc; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.rev150105.SfcBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntry; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfo; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology; @@ -110,6 +105,7 @@ import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology. import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint; import org.opendaylight.yangtools.concepts.Builder; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; @@ -143,7 +139,10 @@ public class NetvirtSfcIT extends AbstractMdsalTestBase { private static String addressStr; private static String portStr; private static String connectionType; + private static String controllerStr; private static boolean ovsdb_wait = false; + private static String userSpaceEnabled = "no"; + private static PipelineOrchestrator pipelineOrchestrator; private static Southbound southbound; private static DataBroker dataBroker; public static final String CONTROLLER_IPADDRESS = "ovsdb.controller.address"; @@ -153,6 +152,7 @@ public class NetvirtSfcIT extends AbstractMdsalTestBase { public static final String CONNECTION_TYPE_ACTIVE = "active"; public static final String CONNECTION_TYPE_PASSIVE = "passive"; public static final String DEFAULT_SERVER_PORT = "6640"; + public static final String USERSPACE_ENABLED = "ovsdb.userspace.enabled"; public static final String INTEGRATION_BRIDGE_NAME = "br-int"; private static final String NETVIRT_TOPOLOGY_ID = "netvirt:1"; private static final String OVSDB_TRACE = "ovsdb.trace"; @@ -179,7 +179,7 @@ public class NetvirtSfcIT extends AbstractMdsalTestBase { private static final String SFCPATH = "SFC-Path"; private static final String SFCSF1NAME = "firewall-abstract"; private static final SftType SFCSF1TYPE = new SftType("firewall"); - private static final int GPEPORT = 6633; + private static final int GPEUDPPORT = 6633; @Override public String getModuleName() { @@ -235,7 +235,7 @@ public class NetvirtSfcIT extends AbstractMdsalTestBase { public Option[] getPropertiesOptions() { return new Option[] { propagateSystemProperties(SERVER_IPADDRESS, SERVER_PORT, CONNECTION_TYPE, - CONTROLLER_IPADDRESS, OVSDB_TRACE, OVSDB_WAIT), + CONTROLLER_IPADDRESS, OVSDB_TRACE, OVSDB_WAIT, USERSPACE_ENABLED), }; } @@ -255,9 +255,9 @@ public class NetvirtSfcIT extends AbstractMdsalTestBase { editConfigurationFilePut(ORG_OPS4J_PAX_LOGGING_CFG, "log4j.logger.org.opendaylight.ovsdb.openstack.netvirt.sfc", LogLevel.TRACE.name()), - //editConfigurationFilePut(ORG_OPS4J_PAX_LOGGING_CFG, - // "log4j.logger.org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13", - // LogLevel.TRACE.name()), + editConfigurationFilePut(ORG_OPS4J_PAX_LOGGING_CFG, + "log4j.logger.org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13", + LogLevel.TRACE.name()), editConfigurationFilePut(ORG_OPS4J_PAX_LOGGING_CFG, "log4j.logger.org.opendaylight.sfc", LogLevel.TRACE.name()), @@ -275,8 +275,11 @@ public class NetvirtSfcIT extends AbstractMdsalTestBase { addressStr = props.getProperty(SERVER_IPADDRESS); portStr = props.getProperty(SERVER_PORT, DEFAULT_SERVER_PORT); connectionType = props.getProperty(CONNECTION_TYPE, "active"); - LOG.info("setUp: Using the following properties: mode= {}, ip:port= {}:{}", - connectionType, addressStr, portStr); + controllerStr = props.getProperty(CONTROLLER_IPADDRESS, "0.0.0.0"); + userSpaceEnabled = props.getProperty(USERSPACE_ENABLED, "no"); + LOG.info("setUp: Using the following properties: mode= {}, ip:port= {}:{}, controller ip: {}, " + + "userspace.enabled: {}", + connectionType, addressStr, portStr, controllerStr, userSpaceEnabled); if (connectionType.equalsIgnoreCase(CONNECTION_TYPE_ACTIVE)) { if (addressStr == null) { fail(usage()); @@ -284,7 +287,7 @@ public class NetvirtSfcIT extends AbstractMdsalTestBase { } LOG.info("getProperties {}: {}", OVSDB_TRACE, props.getProperty(OVSDB_TRACE)); LOG.info("getProperties {}: {}", OVSDB_WAIT, props.getProperty(OVSDB_WAIT)); - if (props.getProperty(OVSDB_WAIT).equals("true")) { + if (props.getProperty(OVSDB_WAIT) != null && props.getProperty(OVSDB_WAIT).equals("true")) { ovsdb_wait = true; } } @@ -313,6 +316,9 @@ public class NetvirtSfcIT extends AbstractMdsalTestBase { assertTrue("Did not find " + NETVIRT_TOPOLOGY_ID, getNetvirtTopology()); southbound = (Southbound) ServiceHelper.getGlobalInstance(Southbound.class, this); assertNotNull("southbound should not be null", southbound); + pipelineOrchestrator = + (PipelineOrchestrator) ServiceHelper.getGlobalInstance(PipelineOrchestrator.class, this); + assertNotNull("pipelineOrchestrator should not be null", pipelineOrchestrator); setup.set(true); } @@ -446,6 +452,13 @@ public class NetvirtSfcIT extends AbstractMdsalTestBase { testModelDelete(builder, clazz); } + private void testModel(Builder builder, Class clazz) + throws InterruptedException { + testModelPut(builder, clazz); + Thread.sleep(1000); + testModelDelete(builder, clazz); + } + private ServiceFunctionsBuilder serviceFunctionsBuilder() { String sf1Name = SF1NAME; String sf1Ip = SF1IP; @@ -461,7 +474,7 @@ public class NetvirtSfcIT extends AbstractMdsalTestBase { String sf2DplName = SF2DPLNAME; String sn2Name = SN2NAME; String bridge2Name= BRIDGE2NAME; - int port = GPEPORT; + int port = GPEUDPPORT; ServiceFunctionBuilder serviceFunctionBuilder = serviceFunctionUtils.serviceFunctionBuilder(sf1Ip, port, sf1DplName, sff1Name, sf1Name); @@ -497,7 +510,7 @@ public class NetvirtSfcIT extends AbstractMdsalTestBase { String sn2Name = SN2NAME; String bridge2Name= BRIDGE2NAME; String aclName = ACLNAME; - int port = GPEPORT; + int port = GPEUDPPORT; ServiceFunctionForwarderBuilder serviceFunctionForwarderBuilder = serviceFunctionForwarderUtils.serviceFunctionForwarderBuilder( @@ -562,24 +575,84 @@ public class NetvirtSfcIT extends AbstractMdsalTestBase { @Test public void testSfcModel() throws InterruptedException { - testModel(serviceFunctionsBuilder(), ServiceFunctions.class, 3000); - testModel(serviceFunctionForwardersBuilder(), ServiceFunctionForwarders.class, 3000); - testModel(serviceFunctionChainsBuilder(), ServiceFunctionChains.class, 3000); - testModel(serviceFunctionPathsBuilder(), ServiceFunctionPaths.class, 3000); + int timeout = 1000; + testModel(serviceFunctionsBuilder(), ServiceFunctions.class, timeout); + testModel(serviceFunctionForwardersBuilder(), ServiceFunctionForwarders.class, timeout); + testModel(serviceFunctionChainsBuilder(), ServiceFunctionChains.class, timeout); + testModel(serviceFunctionPathsBuilder(), ServiceFunctionPaths.class, timeout); } @Test public void testSfcModels() throws InterruptedException { + testModel(serviceFunctionsBuilder(), ServiceFunctions.class); + testModel(serviceFunctionForwardersBuilder(), ServiceFunctionForwarders.class); + testModel(serviceFunctionChainsBuilder(), ServiceFunctionChains.class); + testModel(serviceFunctionPathsBuilder(), ServiceFunctionPaths.class); + + testModel(accessListsBuilder(), AccessLists.class); + testModel(classifiersBuilder(), Classifiers.class); + } + + /** + * Test that the NetvirtSfc SfcClassifierService is added to the Netvirt pipeline. + * @throws InterruptedException + */ + @Test + public void testNetvirtSfcPipeline() throws InterruptedException { String bridgeName = INTEGRATION_BRIDGE_NAME; - ConnectionInfo connectionInfo = southboundUtils.getConnectionInfo(addressStr, portStr); + ConnectionInfo connectionInfo = SouthboundUtils.getConnectionInfo(addressStr, portStr); + assertNotNull("connection failed", southboundUtils.connectOvsdbNode(connectionInfo)); + Node ovsdbNode = southboundUtils.getOvsdbNode(connectionInfo); + assertNotNull("node is not connected", ovsdbNode); + + assertTrue("Controller " + SouthboundUtils.connectionInfoToString(connectionInfo) + + " is not connected", isControllerConnected(connectionInfo)); + + Node bridgeNode = southbound.getBridgeNode(ovsdbNode, bridgeName); + assertNotNull("bridge " + bridgeName + " was not found", bridgeNode); + long datapathId = southbound.getDataPathId(bridgeNode); + String datapathIdString = southbound.getDatapathId(bridgeNode); + LOG.info("testNetVirt: bridgeNode: {}, datapathId: {} - {}", bridgeNode, datapathIdString, datapathId); + assertNotEquals("datapathId was not found", datapathId, 0); + + String flowId = "DEFAULT_PIPELINE_FLOW_" + Service.SFC_CLASSIFIER.getTable(); + verifyFlow(datapathId, flowId, Service.SFC_CLASSIFIER); + + assertTrue(southboundUtils.deleteBridge(connectionInfo, bridgeName)); + Thread.sleep(1000); + assertTrue(southboundUtils.disconnectOvsdbNode(connectionInfo)); + } + + /** + * Test the full NetvirtSfc functionality by creating everything needed to realize a chain and + * then verify all flows have been created. + * NOTE: This test requires an OVS with the NSH v8 patch, otherwise it will fail miserably. + * @throws InterruptedException + */ + @Test + public void testNetvirtSfcAll() throws InterruptedException { + if (userSpaceEnabled.equals("yes")) { + LOG.info("testNetvirtSfcAll: skipping test because userSpaceEnabled {}", userSpaceEnabled); + return; + } + String bridgeName = INTEGRATION_BRIDGE_NAME; + ConnectionInfo connectionInfo = SouthboundUtils.getConnectionInfo(addressStr, portStr); assertNotNull("connection failed", southboundUtils.connectOvsdbNode(connectionInfo)); Node ovsdbNode = southboundUtils.getOvsdbNode(connectionInfo); assertNotNull("node is not connected", ovsdbNode); - Thread.sleep(5000); + assertTrue("Controller " + SouthboundUtils.connectionInfoToString(connectionInfo) + + " is not connected", isControllerConnected(connectionInfo)); + Node bridgeNode = southbound.getBridgeNode(ovsdbNode, bridgeName); assertNotNull("bridge " + bridgeName + " was not found", bridgeNode); long datapathId = southbound.getDataPathId(bridgeNode); + String datapathIdString = southbound.getDatapathId(bridgeNode); + LOG.info("testNetVirt: bridgeNode: {}, datapathId: {} - {}", bridgeNode, datapathIdString, datapathId); + assertNotEquals("datapathId was not found", datapathId, 0); + + String flowId = "DEFAULT_PIPELINE_FLOW_" + Service.SFC_CLASSIFIER.getTable(); + verifyFlow(datapathId, flowId, Service.SFC_CLASSIFIER); Map externalIds = Maps.newHashMap(); externalIds.put("attached-mac", "f6:00:00:0f:00:01"); @@ -588,86 +661,50 @@ public class NetvirtSfcIT extends AbstractMdsalTestBase { southboundUtils.addTerminationPoint(bridgeNode, "vm2", "internal"); Map options = Maps.newHashMap(); options.put("key", "flow"); + options.put("dst_port", String.valueOf(GPEUDPPORT)); + options.put("remote_ip", "flow"); + options.put("nshc1", "flow"); + options.put("nshc2", "flow"); + options.put("nsp", "flow"); + options.put("nsi", "flow"); + southboundUtils.addTerminationPoint(bridgeNode, "vxgpe", "vxlan", options, null); + options.clear(); + options.put("key", "flow"); options.put("remote_ip", "192.168.120.32"); southboundUtils.addTerminationPoint(bridgeNode, "vx", "vxlan", options, null); - Thread.sleep(1000); + long vxGpeOfPort = getOFPort(bridgeNode, "vxgpe"); testModelPut(serviceFunctionsBuilder(), ServiceFunctions.class); testModelPut(serviceFunctionForwardersBuilder(), ServiceFunctionForwarders.class); testModelPut(serviceFunctionChainsBuilder(), ServiceFunctionChains.class); testModelPut(serviceFunctionPathsBuilder(), ServiceFunctionPaths.class); - Thread.sleep(5000); - testModelPut(accessListsBuilder(), AccessLists.class); testModelPut(classifiersBuilder(), Classifiers.class); - Thread.sleep(10000); - readwait(); - NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(datapathId); - FlowBuilder flowBuilder = getSfcIngressClassifierFlowBuilder(); - Flow flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.CONFIGURATION); - assertNotNull("Could not find flow in config", flow); - flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.OPERATIONAL); - assertNotNull("Could not find flow in operational", flow); + flowId = "sfcIngressClass_" + "httpRule"; + verifyFlow(datapathId, flowId, Service.SFC_CLASSIFIER); + flowId = "sfcTable_" + vxGpeOfPort; + verifyFlow(datapathId, flowId, Service.CLASSIFIER); + flowId = "sfEgress_" + GPEUDPPORT; + verifyFlow(datapathId, flowId, Service.SFC_CLASSIFIER); + flowId = "sfIngress_" + GPEUDPPORT + "_" + SF1IP; + verifyFlow(datapathId, flowId, Service.CLASSIFIER); + flowId = "ArpResponder_" + SF1IP; + verifyFlow(datapathId, flowId, Service.CLASSIFIER); assertTrue(southboundUtils.deleteBridge(connectionInfo, bridgeName)); Thread.sleep(1000); assertTrue(southboundUtils.disconnectOvsdbNode(connectionInfo)); } - /* - * Connect to an ovsdb node. Netvirt should add br-int, add the controller address - * and program the pipeline flows. + /** + * Test the standalone NetvirtSfc implementation + * NOTE: This test requires an OVS with the NSH v8 patch, otherwise it will fail miserably. + * @throws InterruptedException */ - @Test - public void testNetvirtSfc() throws InterruptedException { - String bridgeName = INTEGRATION_BRIDGE_NAME; - ConnectionInfo connectionInfo = SouthboundUtils.getConnectionInfo(addressStr, portStr); - assertNotNull("connection failed", southboundUtils.connectOvsdbNode(connectionInfo)); - Node ovsdbNode = southboundUtils.getOvsdbNode(connectionInfo); - assertNotNull("node is not connected", ovsdbNode); - ControllerEntry controllerEntry; - // Loop 10s checking if the controller was added - for (int i = 0; i < 10; i++) { - ovsdbNode = southboundUtils.getOvsdbNode(connectionInfo); - assertNotNull("ovsdb node not found", ovsdbNode); - String controllerTarget = SouthboundUtil.getControllerTarget(ovsdbNode); - assertNotNull("Failed to get controller target", controllerTarget); - OvsdbBridgeAugmentation bridge = southboundUtils.getBridge(connectionInfo, bridgeName); - if (bridge != null) { - assertNotNull("Failed to read bridge", bridge); - assertNotNull("Failed to extract controllerEntry", bridge.getControllerEntry()); - controllerEntry = bridge.getControllerEntry().iterator().next(); - assertEquals(controllerTarget, controllerEntry.getTarget().getValue()); - if (controllerEntry.isIsConnected()) { - Assert.assertTrue("switch is not connected to the controller", controllerEntry.isIsConnected()); - break; - } - } - Thread.sleep(1000); - } - - Node bridgeNode = southbound.getBridgeNode(ovsdbNode, bridgeName); - assertNotNull("bridge " + bridgeName + " was not found", bridgeNode); - long datapathId = southbound.getDataPathId(bridgeNode); - - //Thread.sleep(10000); - - NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(datapathId); - FlowBuilder flowBuilder = FlowUtils.getPipelineFlow(Service.SFC_CLASSIFIER.getTable(), (short)0); - Flow flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.CONFIGURATION); - assertNotNull("Could not find flow in config", flow); - flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.OPERATIONAL); - assertNotNull("Could not find flow in operational", flow); - - assertTrue(southboundUtils.deleteBridge(connectionInfo, bridgeName)); - Thread.sleep(1000); - assertTrue(southboundUtils.disconnectOvsdbNode(connectionInfo)); - } - @Ignore @Test public void testStandalone() throws InterruptedException { @@ -676,31 +713,21 @@ public class NetvirtSfcIT extends AbstractMdsalTestBase { assertNotNull("connection failed", southboundUtils.connectOvsdbNode(connectionInfo)); Node ovsdbNode = southboundUtils.getOvsdbNode(connectionInfo); assertNotNull("node is not connected", ovsdbNode); + String controllerTarget = "tcp:192.168.50.1:6653"; List setControllerEntry = southboundUtils.createControllerEntry(controllerTarget); Assert.assertTrue(southboundUtils.addBridge(connectionInfo, null, bridgeName, null, true, SouthboundConstants.OVSDB_FAIL_MODE_MAP.inverse().get("secure"), true, null, null, setControllerEntry, null, "00:00:00:00:00:00:00:01")); - // Loop 10s checking if the controller was added - for (int i = 0; i < 10; i++) { - ovsdbNode = southboundUtils.getOvsdbNode(connectionInfo); - assertNotNull("ovsdb node not found", ovsdbNode); - assertNotNull("Failed to get controller target", controllerTarget); - OvsdbBridgeAugmentation bridge = southboundUtils.getBridge(connectionInfo, bridgeName); - assertNotNull(bridge); - assertNotNull(bridge.getControllerEntry()); - ControllerEntry controllerEntry = bridge.getControllerEntry().iterator().next(); - assertEquals(controllerTarget, controllerEntry.getTarget().getValue()); - if (controllerEntry.isIsConnected()) { - Assert.assertTrue(controllerEntry.isIsConnected()); - break; - } - Thread.sleep(1000); - } + assertTrue("Controller " + SouthboundUtils.connectionInfoToString(connectionInfo) + + " is not connected", isControllerConnected(connectionInfo)); Node bridgeNode = southbound.getBridgeNode(ovsdbNode, bridgeName); assertNotNull("bridge " + bridgeName + " was not found", bridgeNode); long datapathId = southbound.getDataPathId(bridgeNode); + String datapathIdString = southbound.getDatapathId(bridgeNode); + LOG.info("testNetVirt: bridgeNode: {}, datapathId: {} - {}", bridgeNode, datapathIdString, datapathId); + assertNotEquals("datapathId was not found", datapathId, 0); SfcClassifier sfcClassifier = new SfcClassifier(dataBroker, southbound, mdsalUtils); //sfcClassifier.programLocalInPort(datapathId, "4096", (long)1, (short)0, (short)50, true); @@ -711,7 +738,7 @@ public class NetvirtSfcIT extends AbstractMdsalTestBase { sfcClassifier.programSfcClassiferFlows(datapathId, (short)0, "test", matchesBuilder.build(), nshUtils, (long)2, true); - nshUtils = new NshUtils(null, null, (long)10, (short)253, 0, 0); + //nshUtils = new NshUtils(null, null, (long)10, (short)253, 0, 0); //sfcClassifier.programEgressSfcClassiferFlows(datapathId, (short)0, "test", null, // nshUtils, (long)2, (long)3, true); @@ -722,23 +749,27 @@ public class NetvirtSfcIT extends AbstractMdsalTestBase { //} //NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(datapathId); - //FlowBuilder flowBuilder = getLocalInPortFlow(datapathId, "4096", (long) 1, (short) 0); + //FlowBuilder flowBuilder = getLocalInPortFlow(datapathId, "4096", (long) 1, + // pipelineOrchestrator.getTable(Service.CLASSIFIER)); //Flow flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.CONFIGURATION); //assertNotNull("Could not find flow in config", flow); //flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.OPERATIONAL); //assertNotNull("Could not find flow in operational", flow); - MatchBuilder matchBuilder = sfcClassifier.buildMatch(matchesBuilder.build()); - NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(datapathId); - FlowBuilder flowBuilder = getSfcClassifierFlow(datapathId, (short) 0, "test", null, - nshUtils, (long) 2, matchBuilder); - Flow flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.CONFIGURATION); - assertNotNull("Could not find flow in config", flow); - flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.OPERATIONAL); - assertNotNull("Could not find flow in operational", flow); + //MatchBuilder matchBuilder = sfcClassifier.buildMatch(matchesBuilder.build()); + //NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(datapathId); + //FlowBuilder flowBuilder = getSfcClassifierFlow(datapathId, + // pipelineOrchestrator.getTable(Service.CLASSIFIER), "test", null, + // nshUtils, (long) 2, matchBuilder); + //Flow flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.CONFIGURATION); + //assertNotNull("Could not find flow in config", flow); + //flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.OPERATIONAL); + //assertNotNull("Could not find flow in operational", flow); //nodeBuilder = FlowUtils.createNodeBuilder(datapathId); - //flowBuilder = getEgressSfcClassifierFlow(datapathId, (short) 0, "test", nshUtils, (long) 2); + //flowBuilder = getEgressSfcClassifierFlow(datapathId, + //pipelineOrchestrator.getTable(Service.CLASSIFIER), + //"test", nshUtils, (long) 2); //flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.CONFIGURATION); //assertNotNull("Could not find flow in config", flow); //flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.OPERATIONAL); @@ -753,85 +784,18 @@ public class NetvirtSfcIT extends AbstractMdsalTestBase { assertTrue(southboundUtils.disconnectOvsdbNode(connectionInfo)); } - private FlowBuilder getLocalInPortFlow(long dpidLong, String segmentationId, long inPort, short writeTable) { - MatchBuilder matchBuilder = new MatchBuilder(); - - FlowBuilder flowBuilder = new FlowBuilder(); - - flowBuilder.setMatch(MatchUtils.createInPortMatch(matchBuilder, dpidLong, inPort).build()); - String flowId = "sfcIngress_" + segmentationId + "_" + inPort; - flowBuilder.setId(new FlowId(flowId)); - FlowKey key = new FlowKey(new FlowId(flowId)); - flowBuilder.setStrict(true); - flowBuilder.setBarrier(false); - flowBuilder.setTableId(writeTable); - flowBuilder.setKey(key); - flowBuilder.setFlowName(flowId); - flowBuilder.setHardTimeout(0); - flowBuilder.setIdleTimeout(0); - return flowBuilder; - } - - public FlowBuilder getSfcClassifierFlow(long dpidLong, short writeTable, String ruleName, Matches match, - NshUtils nshHeader, long tunnelOfPort, MatchBuilder matchBuilder) { - FlowBuilder flowBuilder = new FlowBuilder(); - - flowBuilder.setMatch(matchBuilder.build()); - - String flowId = "sfcClass_" + ruleName + "_" + nshHeader.getNshNsp(); - flowBuilder.setId(new FlowId(flowId)); - FlowKey key = new FlowKey(new FlowId(flowId)); - flowBuilder.setBarrier(true); - flowBuilder.setTableId(writeTable); - flowBuilder.setKey(key); - flowBuilder.setFlowName(flowId); - flowBuilder.setHardTimeout(0); - flowBuilder.setIdleTimeout(0); - return flowBuilder; - } - - private FlowBuilder getEgressSfcClassifierFlow(long dpidLong, short writeTable, String ruleName, - NshUtils nshHeader, long tunnelOfPort) { - FlowBuilder flowBuilder = new FlowBuilder(); - - MatchBuilder matchBuilder = new MatchBuilder(); - flowBuilder.setMatch(MatchUtils.createInPortMatch(matchBuilder, dpidLong, tunnelOfPort).build()); - flowBuilder.setMatch( - MatchUtils.createTunnelIDMatch(matchBuilder, BigInteger.valueOf(nshHeader.getNshNsp())).build()); - flowBuilder.setMatch(MatchUtils.addNxNspMatch(matchBuilder, nshHeader.getNshNsp()).build()); - flowBuilder.setMatch(MatchUtils.addNxNsiMatch(matchBuilder, nshHeader.getNshNsi()).build()); - - String flowId = "egressSfcClass_" + ruleName + "_" + nshHeader.getNshNsp() + "_" + nshHeader.getNshNsi(); - flowBuilder.setId(new FlowId(flowId)); - FlowKey key = new FlowKey(new FlowId(flowId)); - flowBuilder.setStrict(true); - flowBuilder.setBarrier(false); - flowBuilder.setTableId(writeTable); - flowBuilder.setKey(key); - flowBuilder.setFlowName(flowId); - flowBuilder.setHardTimeout(0); - flowBuilder.setIdleTimeout(0); - return flowBuilder; - } - - private FlowBuilder getSfcIngressClassifierFlowBuilder() { - FlowBuilder flowBuilder = new FlowBuilder(); - String flowId = "sfcIngressClass_" + "httpRule"; - flowBuilder.setId(new FlowId(flowId)); - FlowKey key = new FlowKey(new FlowId(flowId)); - flowBuilder.setKey(key); - flowBuilder.setFlowName(flowId); - flowBuilder.setTableId((short)10); - return flowBuilder; - } - - private Flow getFlow (FlowBuilder flowBuilder, NodeBuilder nodeBuilder, LogicalDatastoreType store) - throws InterruptedException { + private Flow getFlow ( + FlowBuilder flowBuilder, + org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder nodeBuilder, + LogicalDatastoreType store) throws InterruptedException { + Flow flow = null; for (int i = 0; i < 10; i++) { + LOG.info("getFlow try {} from {}: looking for flow: {}, node: {}", + i, store, flowBuilder.build(), nodeBuilder.build()); flow = FlowUtils.getFlow(flowBuilder, nodeBuilder, dataBroker.newReadOnlyTransaction(), store); if (flow != null) { - LOG.info("getFlow: flow: {}: {}", store, flow); + LOG.info("getFlow try {} from {}: found flow: {}", i, store, flow); break; } Thread.sleep(1000); @@ -839,6 +803,17 @@ public class NetvirtSfcIT extends AbstractMdsalTestBase { return flow; } + private void verifyFlow(long datapathId, String flowId, Service service) throws InterruptedException { + org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder nodeBuilder = + FlowUtils.createNodeBuilder(datapathId); + FlowBuilder flowBuilder = + FlowUtils.initFlowBuilder(new FlowBuilder(), flowId, pipelineOrchestrator.getTable(service)); + Flow flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.CONFIGURATION); + assertNotNull("Could not find flow in config: " + flowBuilder.build() + "--" + nodeBuilder.build(), flow); + flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.OPERATIONAL); + assertNotNull("Could not find flow in operational: " + flowBuilder.build() + "--" + nodeBuilder.build(), flow); + } + private void readwait() { if (ovsdb_wait) { LOG.warn("Waiting, kill with ps -ef | grep java, kill xxx... "); @@ -849,4 +824,65 @@ public class NetvirtSfcIT extends AbstractMdsalTestBase { } } } + + private boolean isControllerConnected(ConnectionInfo connectionInfo) throws InterruptedException { + LOG.info("isControllerConnected enter"); + Boolean connected = false; + ControllerEntry controllerEntry; + Node ovsdbNode = southboundUtils.getOvsdbNode(connectionInfo); + assertNotNull("ovsdb node not found", ovsdbNode); + + BridgeConfigurationManager bridgeConfigurationManager = + (BridgeConfigurationManager) ServiceHelper.getGlobalInstance(BridgeConfigurationManager.class, this); + assertNotNull("Could not find BridgeConfigurationManager Service", bridgeConfigurationManager); + String controllerTarget = bridgeConfigurationManager.getControllersFromOvsdbNode(ovsdbNode).get(0); + Assert.assertNotNull("Failed to get controller target", controllerTarget); + + for (int i = 0; i < 10; i++) { + LOG.info("isControllerConnected try {}: looking for controller: {}", i, controllerTarget); + OvsdbBridgeAugmentation bridge = + southboundUtils.getBridge(connectionInfo, INTEGRATION_BRIDGE_NAME); + Assert.assertNotNull(bridge); + Assert.assertNotNull(bridge.getControllerEntry()); + controllerEntry = bridge.getControllerEntry().iterator().next(); + Assert.assertEquals(controllerTarget, controllerEntry.getTarget().getValue()); + if (controllerEntry.isIsConnected()) { + Assert.assertTrue("Controller is not connected", controllerEntry.isIsConnected()); + connected = true; + break; + } + Thread.sleep(1000); + } + LOG.info("isControllerConnected exit: {} - {}", connected, controllerTarget); + return connected; + } + + private long getOFPort(Node bridgeNode, String portName) { + long ofPort = 0L; + OvsdbTerminationPointAugmentation port = + southbound.extractTerminationPointAugmentation(bridgeNode, portName); + if (port != null) { + ofPort = southbound.getOFPort(port); + } + if (ofPort == 0L) { + for (int i = 0; i < 10; i++) { + LOG.info("Looking for ofPort {}, try: {}", portName, i); + TerminationPoint tp = southbound.readTerminationPoint(bridgeNode, null, portName); + if (tp != null) { + port = tp.getAugmentation(OvsdbTerminationPointAugmentation.class); + if (port != null) { + ofPort = southbound.getOFPort(port); + LOG.info("found ofPort {} - {}, try: {}", portName, ofPort, i); + break; + } + } + try { + Thread.sleep(500); + } catch (InterruptedException e) { + LOG.error("Interrupted while waiting for ofPort {}", portName, e); + } + } + } + return ofPort; + } } diff --git a/openstack/net-virt-sfc/it/src/test/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/utils/AclUtils.java b/openstack/net-virt-sfc/it/src/test/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/utils/AclUtils.java index 7657f2eee3..85eb8295e8 100644 --- a/openstack/net-virt-sfc/it/src/test/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/utils/AclUtils.java +++ b/openstack/net-virt-sfc/it/src/test/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/utils/AclUtils.java @@ -23,17 +23,24 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.cont 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.ace.type.ace.ip.ace.ip.version.AceIpv4Builder; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.packet.fields.rev150611.acl.transport.header.fields.DestinationPortRangeBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.packet.fields.rev150611.acl.transport.header.fields.SourcePortRange; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.packet.fields.rev150611.acl.transport.header.fields.SourcePortRangeBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.acl.rev150105.RedirectToSfc; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.acl.rev150105.RedirectToSfcBuilder; public class AclUtils extends AbstractUtils { public MatchesBuilder matchesBuilder(MatchesBuilder matchesBuilder, int destPort) { + SourcePortRangeBuilder sourcePortRangeBuilder = new SourcePortRangeBuilder() + .setLowerPort(PortNumber.getDefaultInstance("0")) + .setUpperPort(PortNumber.getDefaultInstance("0")); + PortNumber portNumber = new PortNumber(destPort); DestinationPortRangeBuilder destinationPortRangeBuilder = new DestinationPortRangeBuilder() .setLowerPort(portNumber) .setUpperPort(portNumber); AceIpBuilder aceIpBuilder = new AceIpBuilder() + .setSourcePortRange(sourcePortRangeBuilder.build()) .setDestinationPortRange(destinationPortRangeBuilder.build()) .setProtocol((short)6) .setAceIpVersion(new AceIpv4Builder().build()); diff --git a/openstack/net-virt/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/api/ClassifierProvider.java b/openstack/net-virt/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/api/ClassifierProvider.java index 27611fb228..d2805c30c6 100644 --- a/openstack/net-virt/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/api/ClassifierProvider.java +++ b/openstack/net-virt/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/api/ClassifierProvider.java @@ -19,4 +19,5 @@ public interface ClassifierProvider { void programTunnelIn(Long dpidLong, String segmentationId, Long ofPort, boolean write); void programVlanIn(Long dpidLong, String segmentationId, Long ethPort, boolean write); void programLLDPPuntRule(Long dpidLong); + void programGotoTable(Long dpidLong, boolean write); } -- 2.36.6