<classifier>features</classifier>
<type>xml</type>
</dependency>
+
+ <!-- openflowplugin dependencies for net-virt clustering-->
+ <dependency>
+ <groupId>org.opendaylight.openflowplugin</groupId>
+ <artifactId>features-openflowplugin-li</artifactId>
+ <version>${openflowplugin.version}</version>
+ <classifier>features</classifier>
+ <type>xml</type>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.openflowplugin</groupId>
+ <artifactId>features-openflowplugin-extension-li</artifactId>
+ <version>${openflowplugin.version}</version>
+ <classifier>features</classifier>
+ <type>xml</type>
+ </dependency>
+
<!-- project specific dependencies -->
<dependency>
<groupId>${project.groupId}</groupId>
xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0">
<repository>mvn:org.opendaylight.openflowplugin/features-openflowplugin-extension/{{VERSION}}/xml/features</repository>
<repository>mvn:org.opendaylight.openflowplugin/features-openflowplugin/{{VERSION}}/xml/features</repository>
+ <repository>mvn:org.opendaylight.openflowplugin/features-openflowplugin-extension-li/{{VERSION}}/xml/features</repository>
+ <repository>mvn:org.opendaylight.openflowplugin/features-openflowplugin-li/{{VERSION}}/xml/features</repository>
<repository>mvn:org.opendaylight.neutron/features-neutron/{{VERSION}}/xml/features</repository>
<repository>mvn:org.opendaylight.ovsdb/southbound-features/1.2.1-SNAPSHOT/xml/features</repository>
<repository>mvn:org.opendaylight.controller/features-mdsal/{{VERSION}}/xml/features</repository>
<configfile finalname="etc/opendaylight/karaf/netvirt-impl-default-config.xml">mvn:org.opendaylight.ovsdb/openstack.net-virt/{{VERSION}}/xml/config</configfile>
<configfile finalname="etc/opendaylight/karaf/netvirt-providers-impl-default-config.xml">mvn:org.opendaylight.ovsdb/openstack.net-virt-providers/{{VERSION}}/xml/config</configfile>
</feature>
+
+ <feature name="odl-ovsdb-openstack-clusteraware" description="OpenDaylight :: OVSDB :: OpenStack Network Virtualization - Cluster Aware"
+ version='${project.version}'>
+ <feature version='${mdsal.version}'>odl-mdsal-broker</feature>
+ <feature version="${openflowplugin.version}">odl-openflowplugin-nsf-model-li</feature>
+ <feature version="${neutron.version}">odl-neutron-service</feature>
+ <feature version="${project.version}">odl-ovsdb-southbound-impl-ui</feature>
+ <feature version="${openflowplugin.version}">odl-openflowplugin-flow-services-li</feature>
+ <feature version="${openflowplugin.version}">odl-openflowplugin-nxm-extensions-li</feature>
+ <bundle>mvn:org.opendaylight.ovsdb/utils.servicehelper/{{VERSION}}</bundle>
+ <bundle>mvn:org.opendaylight.ovsdb/utils.neutron-utils/{{VERSION}}</bundle>
+ <bundle>mvn:org.opendaylight.ovsdb/utils.mdsal-utils/{{VERSION}}</bundle>
+ <bundle>mvn:org.opendaylight.ovsdb/utils.southbound-utils/{{VERSION}}</bundle>
+ <bundle>mvn:org.opendaylight.ovsdb/openstack.net-virt/{{VERSION}}</bundle>
+ <bundle>mvn:org.opendaylight.ovsdb/openstack.net-virt-providers/{{VERSION}}</bundle>
+ <bundle>mvn:org.opendaylight.neutron/dummyprovider/{{VERSION}}</bundle>
+ <configfile finalname="etc/opendaylight/karaf/netvirt-impl-default-config.xml">mvn:org.opendaylight.ovsdb/openstack.net-virt/{{VERSION}}/xml/config</configfile>
+ <configfile finalname="etc/opendaylight/karaf/netvirt-providers-impl-default-config.xml">mvn:org.opendaylight.ovsdb/openstack.net-virt-providers/{{VERSION}}/xml/config</configfile>
+ </feature>
+
<feature name="odl-ovsdb-ui" description="OpenDaylight :: OVSDB :: DLUX Integration Plugin" version='${project.version}'>
<feature version="${dlux.version}">odl-dlux-core</feature>
<bundle>mvn:org.opendaylight.ovsdb/ovsdb-ui-bundle/{{VERSION}}</bundle>
</prerequisites>
<properties>
<!-- uncomment the next line if you want karaf to automatically load the feature -->
- <karaf.localFeature>odl-ovsdb-openstack</karaf.localFeature>
+ <!-- <karaf.localFeature>odl-ovsdb-openstack</karaf.localFeature> -->
</properties>
<description>The OVSDB Plugin integration project is a project for OpenDaylight that will implement the Open vSwitch Database RFC 7047 management protocol allowing the Southbound configuration of vSwitches and a network virtualization implementation.</description>
<url>https://wiki.opendaylight.org/view/OVSDB_Integration:Main</url>
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;
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;
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;
@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;
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";
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);
}
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));
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<Service> staticPipeline = pipelineOrchestrator.getStaticPipeline();
+ List<Service> 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;
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);
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<Service> staticPipeline = pipelineOrchestrator.getStaticPipeline();
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());
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));
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);
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,
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);
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 (
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));
}
}
<properties>
<liblldp.version>0.10.0-SNAPSHOT</liblldp.version>
<openflowplugin.version>0.2.0-SNAPSHOT</openflowplugin.version>
- <powermock.version>1.5.2</powermock.version>
+ <powermock.version>1.6.4</powermock.version>
<sonar.jacoco.itReportPath>../net-virt-it/target/jacoco-it.exec</sonar.jacoco.itReportPath>
</properties>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
+ <version>1.10.19</version>
<scope>test</scope>
</dependency>
<dependency>
</properties>
</configuration>
</plugin>
+ <plugin>
+ <groupId>org.jacoco</groupId>
+ <artifactId>jacoco-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>default-instrument</id>
+ <goals>
+ <goal>instrument</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>default-restore-instrumented-classes</id>
+ <goals>
+ <goal>restore-instrumented-classes</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
</plugins>
</build>
</project>
<module>
<type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:netvirt:providers:impl">prefix:netvirt-providers-impl</type>
<name>netvirt-providers-default</name>
+ <table-offset>0</table-offset>
<broker>
<type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-broker-osgi-registry</type>
<name>binding-osgi-broker</name>
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;
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<ServiceRegistration<?>> registrations = new ArrayList<>();
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()},
gatewayMacResolverService, Service.GATEWAY_RESOLVER);
getNotificationProviderService().registerNotificationListener(gatewayMacResolverService);
-
+ netvirtProvidersConfig.setDependencies(context, null);
pipelineOrchestrator.setDependencies(context, null);
outboundNatService.setDependencies(context, null);
egressAclService.setDependencies(context, null);
--- /dev/null
+/*
+ * 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<DataChangeListener> 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<NetvirtProvidersConfig> 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<InstanceIdentifier<?>, DataObject> asyncDataChangeEvent) {
+ executorService.submit(new Runnable() {
+
+ @Override
+ public void run() {
+ LOG.info("onDataChanged: {}", asyncDataChangeEvent);
+ processConfigCreate(asyncDataChangeEvent);
+ processConfigUpdate(asyncDataChangeEvent);
+ }
+ });
+ }
+
+ private void processConfigCreate(AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changes) {
+ for (Map.Entry<InstanceIdentifier<?>, DataObject> entry : changes.getCreatedData().entrySet()) {
+ if (entry.getValue() instanceof NetvirtProvidersConfig) {
+ NetvirtProvidersConfig netvirtProvidersConfig = (NetvirtProvidersConfig) entry.getValue();
+ applyConfig(netvirtProvidersConfig);
+ }
+ }
+ }
+
+ private void processConfigUpdate(AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changes) {
+ for (Map.Entry<InstanceIdentifier<?>, 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) {
+
+ }
+}
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;
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() {
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");
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() {
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());
}
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<Void, TransactionCommitFailedException> 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());
// 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);
}
}
ingressAclProvider.programFixedSecurityGroup(dpid, segmentationId, dhcpPort.getMacAddress(), localPort,
- isLastPortinSubnet, isComputePort, write);
+ isLastPortinSubnet, isComputePort, attachedMac, write);
egressAclProvider.programFixedSecurityGroup(dpid, segmentationId, attachedMac, localPort,
srcAddressList, isLastPortinBridge, isComputePort,write);
/* If the network type is tunnel based (VXLAN/GRRE/etc) with Neutron Port Security ACLs */
writeLLDPRule(dpid);
+ if (bridgeName.equals(configurationService.getIntegrationBridgeName()) &&
+ NetvirtProvidersProvider.getTableOffset() != 0) {
+ classifierProvider.programGotoTable(dpid,true);
+ }
+
if (bridgeName.equals(configurationService.getExternalBridgeName())) {
writeNormalRule(dpid);
}
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());
Service getNextServiceInPipeline(Service service);
AbstractServiceInstance getServiceInstance(Service service);
Map<Service, AbstractServiceInstance> getServiceRegistry();
+ short getTableOffset();
+ short getTable(Service service);
List<Service> getStaticPipeline();
void enqueue(Node node);
void registerService(final ServiceReference ref, AbstractServiceInstance serviceInstance);
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;
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<Service> getStaticPipeline() {
return staticPipeline;
}
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) {
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));
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<Instruction> 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);
import org.opendaylight.ovsdb.openstack.netvirt.translator.NeutronSecurityGroup;
import org.opendaylight.ovsdb.openstack.netvirt.translator.NeutronSecurityRule;
import org.opendaylight.ovsdb.openstack.netvirt.translator.Neutron_IPs;
+import org.opendaylight.ovsdb.utils.mdsal.openflow.ActionUtils;
import org.opendaylight.ovsdb.utils.mdsal.openflow.FlowUtils;
import org.opendaylight.ovsdb.utils.mdsal.openflow.InstructionUtils;
import org.opendaylight.ovsdb.utils.mdsal.openflow.MatchUtils;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
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.yang.types.rev100924.MacAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionKey;
+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.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.InstructionsBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.EtherType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.arp.match.fields.ArpSourceHardwareAddressBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetTypeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.ArpMatchBuilder;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.slf4j.Logger;
}
flowId = flowId + "_Permit";
NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
- syncFlow(flowId, nodeBuilder, matchBuilder, priority, write, false);
+ syncFlow(flowId, nodeBuilder, matchBuilder, priority, write, false, securityServicesManager.isConntrackEnabled());
}
@Override
long localPort, List<Neutron_IPs> srcAddressList,
boolean isLastPortinBridge, boolean isComputePort ,boolean write) {
// If it is the only port in the bridge add the rule to allow any DHCP client traffic
- if (isLastPortinBridge) {
+ //if (isLastPortinBridge) {
egressAclDhcpAllowClientTrafficFromVm(dpid, write, Constants.PROTO_DHCP_CLIENT_TRAFFIC_MATCH_PRIORITY);
- }
+ // }
if (isComputePort) {
+ programArpRule(dpid, segmentationId, localPort, attachedMac, write);
+ if (securityServicesManager.isConntrackEnabled()) {
+ programEgressAclFixedConntrackRule(dpid, segmentationId, localPort, attachedMac, write);
+ }
// add rule to drop the DHCP server traffic originating from the vm.
egressAclDhcpDropServerTrafficfromVm(dpid, localPort, write,
Constants.PROTO_DHCP_CLIENT_SPOOF_MATCH_PRIORITY_DROP);
}
}
+ private void programArpRule(Long dpid, String segmentationId, long localPort, String attachedMac, boolean write) {
+ String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpid;
+ MatchBuilder matchBuilder = new MatchBuilder();
+ NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
+ String flowId = "Egress_ARP_" + segmentationId + "_" + localPort + "_";
+
+ EthernetMatchBuilder ethernetType = new EthernetMatchBuilder();
+ EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder();
+ ethTypeBuilder.setType(new EtherType(0x0806L));
+ ethernetType.setEthernetType(ethTypeBuilder.build());
+ matchBuilder.setEthernetMatch(ethernetType.build());
+
+ ArpMatchBuilder arpDstMatch = new ArpMatchBuilder();
+ ArpSourceHardwareAddressBuilder arpSrc = new ArpSourceHardwareAddressBuilder();
+ arpSrc.setAddress(new MacAddress(attachedMac));
+ arpDstMatch.setArpSourceHardwareAddress(arpSrc.build());
+ matchBuilder.setLayer3Match(arpDstMatch.build());
+
+ syncFlow(flowId, nodeBuilder, matchBuilder, Constants.PROTO_MATCH_PRIORITY, write, false, false);
+ }
+
+ private void programEgressAclFixedConntrackRule(Long dpid,
+ String segmentationId, long localPort, String attachMac, boolean write) {
+ try {
+ String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpid;
+ programConntrackUntrackRule(nodeName, segmentationId, localPort,attachMac,
+ Constants.CT_STATE_UNTRACKED_PRIORITY, write );
+ programConntrackTrackedPlusEstRule(nodeName, dpid, segmentationId, localPort,
+ Constants.CT_STATE_TRACKED_EST_PRIORITY, write );
+ programConntrackNewDropRule(nodeName, dpid, segmentationId, localPort,
+ Constants.CT_STATE_NEW_PRIORITY_DROP, write );
+ LOG.info("programEgressAclFixedConntrackRule : default connection tracking rule are added.");
+ } catch (Exception e) {
+ LOG.error("Failed to add default conntrack rules : " , e);
+ }
+ }
+
+ private void programConntrackUntrackRule(String nodeName, String segmentationId,
+ long localPort, String attachMac, Integer priority, boolean write) {
+ MatchBuilder matchBuilder = new MatchBuilder();
+ NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
+ String flowName = "Egress_Fixed_Conntrk_Untrk_" + segmentationId + "_" + localPort + "_";
+ matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder, attachMac, null);
+ matchBuilder = MatchUtils.addCtState(matchBuilder,0x00,0X80);
+ FlowBuilder flowBuilder = new FlowBuilder();
+ flowBuilder.setMatch(matchBuilder.build());
+ FlowUtils.initFlowBuilder(flowBuilder, flowName, getTable()).setPriority(priority);
+ if (write) {
+ InstructionBuilder ib = new InstructionBuilder();
+ List<Instruction> instructionsList = Lists.newArrayList();
+ InstructionsBuilder isb = new InstructionsBuilder();
+ ActionBuilder ab = new ActionBuilder();
+ ab.setAction(ActionUtils.nxConntrackAction(0, 0L, 0, (short)0x0));
+ // 0xff means no table, 0x0 is table = 0
+ ab.setOrder(0);
+ ab.setKey(new ActionKey(0));
+ List<Action> actionList = Lists.newArrayList();
+ actionList.add(ab.build());
+ ApplyActionsBuilder aab = new ApplyActionsBuilder();
+ aab.setAction(actionList);
+ ib.setOrder(0);
+ ib.setKey(new InstructionKey(0));
+ ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
+ instructionsList.add(ib.build());
+ isb.setInstruction(instructionsList);
+ flowBuilder.setInstructions(isb.build());
+ writeFlow(flowBuilder, nodeBuilder);
+ LOG.info("EGRESS:default programConntrackUntrackRule() flows are written");
+ } else {
+ removeFlow(flowBuilder, nodeBuilder);
+ }
+ }
+
+ private void programConntrackTrackedPlusEstRule(String nodeName, Long dpid, String segmentationId,
+ long localPort,Integer priority, boolean write) {
+ MatchBuilder matchBuilder = new MatchBuilder();
+ NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
+ String flowName = "Egress_Fixed_Conntrk_TrkEst_" + segmentationId + "_" + localPort + "_";
+ matchBuilder = MatchUtils.createInPortMatch(matchBuilder, dpid, localPort);
+ matchBuilder = MatchUtils.addCtState(matchBuilder,0x82, 0x82);
+ FlowBuilder flowBuilder = new FlowBuilder();
+ flowBuilder.setMatch(matchBuilder.build());
+ FlowUtils.initFlowBuilder(flowBuilder, flowName, getTable()).setPriority(priority);
+ if (write) {
+ InstructionBuilder ib = new InstructionBuilder();
+ List<Instruction> instructionsList = Lists.newArrayList();
+ InstructionsBuilder isb = new InstructionsBuilder();
+ // got to next table instruction
+ ib = this.getMutablePipelineInstructionBuilder();
+ ib.setOrder(0);
+ ib.setKey(new InstructionKey(0));
+ instructionsList.add(ib.build());
+ isb.setInstruction(instructionsList);
+ flowBuilder.setInstructions(isb.build());
+ writeFlow(flowBuilder, nodeBuilder);
+ LOG.info("EGRESS:default programConntrackTrackedPlusEstRule() flows are written");
+ } else {
+ removeFlow(flowBuilder, nodeBuilder);
+ }
+ }
+
+ private void programConntrackNewDropRule(String nodeName, Long dpid, String segmentationId,
+ long localPort, Integer priority, boolean write) {
+ MatchBuilder matchBuilder = new MatchBuilder();
+ NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
+ String flowName = "Egress_Fixed_Conntrk_NewDrop_" + segmentationId + "_" + localPort + "_";
+ matchBuilder = MatchUtils.createInPortMatch(matchBuilder, dpid, localPort);
+ matchBuilder = MatchUtils.addCtState(matchBuilder,0x01, 0x01);
+ FlowBuilder flowBuilder = new FlowBuilder();
+ flowBuilder.setMatch(matchBuilder.build());
+ FlowUtils.initFlowBuilder(flowBuilder, flowName, getTable()).setPriority(priority);
+ if (write) {
+ InstructionBuilder ib = new InstructionBuilder();
+ InstructionsBuilder isb = new InstructionsBuilder();
+ List<Instruction> instructions = Lists.newArrayList();
+ InstructionUtils.createDropInstructions(ib);
+ ib.setOrder(0);
+ ib.setKey(new InstructionKey(0));
+ instructions.add(ib.build());
+ isb.setInstruction(instructions);
+ LOG.debug("Instructions contain: {}", ib.getInstruction());
+ flowBuilder.setInstructions(isb.build());
+ writeFlow(flowBuilder, nodeBuilder);
+ LOG.info("EGRESS:default programConntrackNewDropRule() flows are written");
+ } else {
+ removeFlow(flowBuilder, nodeBuilder);
+ }
+ }
+
/**
* Allows IPv4 packet egress from the src mac address.
* @param dpidLong the dpid
MatchBuilder matchBuilder = new MatchBuilder();
String flowId = "Egress_IP" + segmentationId + "_" + srcMac + "_Permit_";
matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,srcMac,null);
- syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false);
+ syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false, false);
}
/**
rangeflowId = rangeflowId + "_Permit";
MatchUtils.addLayer4MatchWithMask(matchBuilder, MatchUtils.TCP_SHORT,
0, port, portMaskMap.get(port));
- syncFlow(rangeflowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false);
+ syncFlow(rangeflowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false, securityServicesManager.isConntrackEnabled());
}
} else {
flowId = flowId + "_Permit";
- syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false);
+ syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false, securityServicesManager.isConntrackEnabled());
}
}
MatchUtils.iPv4PrefixFromIPv4Address(dstAddress));
} else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) {
flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix();
- matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,null,
+ if (!portSecurityRule.getSecurityRuleRemoteIpPrefix().contains("/0")) {
+ matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,null,
new Ipv4Prefix(portSecurityRule.getSecurityRuleRemoteIpPrefix()));
+ }
}
flowId = flowId + "_Permit";
NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
- syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false);
+ syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false, securityServicesManager.isConntrackEnabled());
}
/**
rangeflowId = rangeflowId + "_Permit";
MatchUtils.addLayer4MatchWithMask(matchBuilder, MatchUtils.UDP_SHORT,
0, port, portMaskMap.get(port));
- syncFlow(rangeflowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false);
+ syncFlow(rangeflowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false, securityServicesManager.isConntrackEnabled());
}
} else {
flowId = flowId + "_Permit";
- syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false);
+ syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false, securityServicesManager.isConntrackEnabled());
}
}
String flowName = "Egress_DHCP_Client" + "_Permit_";
MatchBuilder matchBuilder = new MatchBuilder();
MatchUtils.createDhcpMatch(matchBuilder, DHCP_DESTINATION_PORT, DHCP_SOURCE_PORT);
- syncFlow(flowName, nodeBuilder, matchBuilder, priority, write, false);
+ syncFlow(flowName, nodeBuilder, matchBuilder, priority, write, false, false);
}
/**
MatchBuilder matchBuilder = new MatchBuilder();
MatchUtils.createInPortMatch(matchBuilder, dpidLong, localPort);
MatchUtils.createDhcpMatch(matchBuilder, DHCP_SOURCE_PORT, DHCP_DESTINATION_PORT);
- syncFlow(flowName, nodeBuilder, matchBuilder, priority, write, true);
+ syncFlow(flowName, nodeBuilder, matchBuilder, priority, write, true, false);
}
/**
MatchUtils.createSrcL3Ipv4MatchWithMac(matchBuilder, new Ipv4Prefix(srcIp),new MacAddress(attachedMac));
MatchUtils.createInPortMatch(matchBuilder, dpidLong, localPort);
LOG.debug("egressAclAllowTrafficFromVmIpMacPair: MatchBuilder contains: {}", matchBuilder);
- syncFlow(flowName, nodeBuilder, matchBuilder, priority, write, false);
+ syncFlow(flowName, nodeBuilder, matchBuilder, priority, write, false, false);
}
/**
* @param priority the protocol priority
* @param write whether it is a write
* @param drop whether it is a drop or forward
+ * @param isCtCommit commit the connection or CT to track
*/
private void syncFlow(String flowName, NodeBuilder nodeBuilder,
MatchBuilder matchBuilder, Integer priority,
- boolean write, boolean drop) {
+ boolean write, boolean drop, boolean isCtCommit) {
+ MatchBuilder matchBuilder1 = matchBuilder;
+ if (isCtCommit) {
+ matchBuilder1 = MatchUtils.addCtState(matchBuilder1,0x81, 0x81);
+ }
FlowBuilder flowBuilder = new FlowBuilder();
- flowBuilder.setMatch(matchBuilder.build());
+ flowBuilder.setMatch(matchBuilder1.build());
FlowUtils.initFlowBuilder(flowBuilder, flowName, getTable()).setPriority(priority);
if (write) {
InstructionBuilder ib = this.getMutablePipelineInstructionBuilder();
+ InstructionBuilder ib1 = new InstructionBuilder();
+ ActionBuilder ab = new ActionBuilder();
+ ApplyActionsBuilder aab = new ApplyActionsBuilder();
if (drop) {
InstructionUtils.createDropInstructions(ib);
}
InstructionsBuilder isb = new InstructionsBuilder();
List<Instruction> instructionsList = Lists.newArrayList();
instructionsList.add(ib.build());
+ if (isCtCommit) {
+ LOG.info("Adding Conntarck rule, flowname = " + flowName);
+ ab.setAction(ActionUtils.nxConntrackAction(1, 0L, 0, (short)0xff));
+ ab.setOrder(0);
+ ab.setKey(new ActionKey(0));
+ List<Action> actionList = Lists.newArrayList();
+ actionList.add(ab.build());
+ aab.setAction(actionList);
+ ib1.setOrder(1);
+ ib1.setKey(new InstructionKey(1));
+ ib1.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
+ instructionsList.add(ib1.build());
+ }
isb.setInstruction(instructionsList);
flowBuilder.setInstructions(isb.build());
writeFlow(flowBuilder, nodeBuilder);
import org.opendaylight.ovsdb.openstack.netvirt.translator.NeutronSecurityGroup;
import org.opendaylight.ovsdb.openstack.netvirt.translator.NeutronSecurityRule;
import org.opendaylight.ovsdb.openstack.netvirt.translator.Neutron_IPs;
+import org.opendaylight.ovsdb.utils.mdsal.openflow.ActionUtils;
import org.opendaylight.ovsdb.utils.mdsal.openflow.FlowUtils;
import org.opendaylight.ovsdb.utils.mdsal.openflow.InstructionUtils;
import org.opendaylight.ovsdb.utils.mdsal.openflow.MatchUtils;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
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.yang.types.rev100924.MacAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionKey;
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.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.instruction.list.Instruction;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.EtherType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.arp.match.fields.ArpTargetHardwareAddressBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetTypeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.ArpMatchBuilder;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.slf4j.Logger;
}
NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
flowId = flowId + "_Permit";
- syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false);
+ syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false, securityServicesManager.isConntrackEnabled());
}
@Override
public void programFixedSecurityGroup(Long dpid, String segmentationId, String dhcpMacAddress,
long localPort, boolean isLastPortinSubnet,
- boolean isComputePort, boolean write) {
+ boolean isComputePort, String attachMac, boolean write) {
//If this port is the only port in the compute node add the DHCP server rule.
if (isLastPortinSubnet && isComputePort ) {
ingressAclDhcpAllowServerTraffic(dpid, segmentationId,dhcpMacAddress,
write,Constants.PROTO_DHCP_SERVER_MATCH_PRIORITY);
}
+ if (isComputePort) {
+ if (securityServicesManager.isConntrackEnabled()) {
+ programIngressAclFixedConntrackRule(dpid, segmentationId, attachMac, localPort, write);
+ }
+ programArpRule(dpid, segmentationId, localPort, attachMac, write);
+ }
+ }
+
+ private void programArpRule(Long dpid, String segmentationId, long localPort, String attachMac, boolean write) {
+ String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpid;
+ MatchBuilder matchBuilder = new MatchBuilder();
+ NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
+ String flowId = "Ingress_ARP_" + segmentationId + "_" + localPort + "_";
+ EthernetMatchBuilder ethernetType = new EthernetMatchBuilder();
+ EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder();
+ ethTypeBuilder.setType(new EtherType(0x0806L));
+ ethernetType.setEthernetType(ethTypeBuilder.build());
+ matchBuilder.setEthernetMatch(ethernetType.build());
+
+ ArpMatchBuilder arpDstMatch = new ArpMatchBuilder();
+ ArpTargetHardwareAddressBuilder arpDst = new ArpTargetHardwareAddressBuilder();
+ arpDst.setAddress(new MacAddress(attachMac));
+ arpDstMatch.setArpTargetHardwareAddress(arpDst.build());
+ matchBuilder.setLayer3Match(arpDstMatch.build());
+ syncFlow(flowId, nodeBuilder, matchBuilder, Constants.PROTO_MATCH_PRIORITY, write, false, securityServicesManager.isConntrackEnabled());
+ }
+
+ private void programIngressAclFixedConntrackRule(Long dpid,
+ String segmentationId, String attachMac, long localPort, boolean write) {
+ try {
+ String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpid;
+ programConntrackUntrackRule(nodeName, segmentationId, localPort, attachMac,
+ Constants.CT_STATE_UNTRACKED_PRIORITY, write );
+ programConntrackTrackedPlusEstRule(nodeName, segmentationId, localPort, attachMac,
+ Constants.CT_STATE_TRACKED_EST_PRIORITY, write );
+ programConntrackNewDropRule(nodeName, segmentationId, localPort, attachMac,
+ Constants.CT_STATE_NEW_PRIORITY_DROP, write );
+ LOG.info("programIngressAclFixedConntrackRule : default connection tracking rule are added.");
+ } catch (Exception e) {
+ LOG.error("Failed to add default conntrack rules : " , e);
+ }
+ }
+
+ private void programConntrackUntrackRule(String nodeName, String segmentationId,
+ long localPort, String attachMac, Integer priority, boolean write) {
+ MatchBuilder matchBuilder = new MatchBuilder();
+ NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
+ String flowName = "Ingress_Fixed_Conntrk_Untrk_" + segmentationId + "_" + localPort + "_";
+ matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,null,attachMac);
+ matchBuilder = MatchUtils.addCtState(matchBuilder,0x00, 0x80);
+ FlowBuilder flowBuilder = new FlowBuilder();
+ flowBuilder.setMatch(matchBuilder.build());
+ FlowUtils.initFlowBuilder(flowBuilder, flowName, getTable()).setPriority(priority);
+ if (write) {
+ InstructionBuilder ib = new InstructionBuilder();
+ List<Instruction> instructionsList = Lists.newArrayList();
+ InstructionsBuilder isb = new InstructionsBuilder();
+ ActionBuilder ab = new ActionBuilder();
+ ab.setAction(ActionUtils.nxConntrackAction(0, 0L, 0, (short)0x0));
+ // 0xff means no table, 0x0 is table = 0
+ // nxConntrackAction(Integer flags, Long zoneSrc,Integer conntrackZone, Short recircTable)
+ ab.setOrder(0);
+ ab.setKey(new ActionKey(0));
+ List<Action> actionList = Lists.newArrayList();
+ actionList.add(ab.build());
+ ApplyActionsBuilder aab = new ApplyActionsBuilder();
+ aab.setAction(actionList);
+
+ ib.setOrder(0);
+ ib.setKey(new InstructionKey(0));
+ ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
+ instructionsList.add(ib.build());
+ isb.setInstruction(instructionsList);
+ flowBuilder.setInstructions(isb.build());
+ writeFlow(flowBuilder, nodeBuilder);
+ LOG.info("INGRESS:default programConntrackUntrackRule() flows are written");
+ } else {
+ removeFlow(flowBuilder, nodeBuilder);
+ }
+ }
+
+ private void programConntrackTrackedPlusEstRule(String nodeName, String segmentationId,
+ long localPort, String attachMac,Integer priority, boolean write) {
+ MatchBuilder matchBuilder = new MatchBuilder();
+ NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
+ String flowName = "Ingress_Fixed_Conntrk_TrkEst_" + segmentationId + "_" + localPort + "_";
+ matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,null,attachMac);
+ matchBuilder = MatchUtils.addCtState(matchBuilder,0x82, 0x82);
+ FlowBuilder flowBuilder = new FlowBuilder();
+ flowBuilder.setMatch(matchBuilder.build());
+ FlowUtils.initFlowBuilder(flowBuilder, flowName, getTable()).setPriority(priority);
+ if (write) {
+ InstructionBuilder ib = new InstructionBuilder();
+ List<Instruction> instructionsList = Lists.newArrayList();
+ InstructionsBuilder isb = new InstructionsBuilder();
+
+ ib = this.getMutablePipelineInstructionBuilder();
+ ib.setOrder(0);
+ ib.setKey(new InstructionKey(0));
+ instructionsList.add(ib.build());
+ isb.setInstruction(instructionsList);
+ flowBuilder.setInstructions(isb.build());
+ writeFlow(flowBuilder, nodeBuilder);
+ LOG.info("INGRESS:default programConntrackTrackedPlusEstRule() flows are written");
+ } else {
+ removeFlow(flowBuilder, nodeBuilder);
+ }
+ }
+
+ private void programConntrackNewDropRule(String nodeName, String segmentationId,
+ long localPort, String attachMac, Integer priority, boolean write) {
+ MatchBuilder matchBuilder = new MatchBuilder();
+ NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
+ String flowName = "Ingress_Fixed_Conntrk_NewDrop_" + segmentationId + "_" + localPort + "_";
+ matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,null,attachMac);
+ matchBuilder = MatchUtils.addCtState(matchBuilder,0x01, 0x01);
+ FlowBuilder flowBuilder = new FlowBuilder();
+ flowBuilder.setMatch(matchBuilder.build());
+ FlowUtils.initFlowBuilder(flowBuilder, flowName, getTable()).setPriority(priority);
+ if (write) {
+ // Instantiate the Builders for the OF Actions and Instructions
+ InstructionBuilder ib = new InstructionBuilder();
+ InstructionsBuilder isb = new InstructionsBuilder();
+
+ // Instructions List Stores Individual Instructions
+ List<Instruction> instructions = Lists.newArrayList();
+
+ // Set the Output Port/Iface
+ InstructionUtils.createDropInstructions(ib);
+ ib.setOrder(0);
+ ib.setKey(new InstructionKey(0));
+ instructions.add(ib.build());
+
+ // Add InstructionBuilder to the Instruction(s)Builder List
+ isb.setInstruction(instructions);
+ LOG.debug("Instructions contain: {}", ib.getInstruction());
+ // Add InstructionsBuilder to FlowBuilder
+ flowBuilder.setInstructions(isb.build());
+ writeFlow(flowBuilder, nodeBuilder);
+ LOG.info("INGRESS:default programConntrackNewDropRule flows are written");
+ } else {
+ removeFlow(flowBuilder, nodeBuilder);
+ }
}
/**
MatchBuilder matchBuilder = new MatchBuilder();
String flowId = "Ingress_IP" + segmentationId + "_" + dstMac + "_Permit_";
matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,null,dstMac);
- syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false);
+ syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false, securityServicesManager.isConntrackEnabled());
}
/**
rangeflowId = rangeflowId + "_Permit";
MatchUtils.addLayer4MatchWithMask(matchBuilder, MatchUtils.TCP_SHORT,
0, port, portMaskMap.get(port));
- syncFlow(rangeflowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false);
+ syncFlow(rangeflowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false, securityServicesManager.isConntrackEnabled());
}
} else {
flowId = flowId + "_Permit";
- syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false);
+ syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false, securityServicesManager.isConntrackEnabled());
}
}
rangeflowId = rangeflowId + "_Permit";
MatchUtils.addLayer4MatchWithMask(matchBuilder, MatchUtils.UDP_SHORT,
0, port, portMaskMap.get(port));
- syncFlow(rangeflowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false);
+ syncFlow(rangeflowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false, securityServicesManager.isConntrackEnabled());
}
} else {
flowId = flowId + "_Permit";
- syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false);
+ syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false, securityServicesManager.isConntrackEnabled());
}
}
MatchUtils.iPv4PrefixFromIPv4Address(srcAddress), null);
} else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) {
flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix();
- matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,
- new Ipv4Prefix(portSecurityRule
- .getSecurityRuleRemoteIpPrefix()),null);
+ if (!portSecurityRule.getSecurityRuleRemoteIpPrefix().contains("/0")) {
+ matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,
+ new Ipv4Prefix(portSecurityRule.getSecurityRuleRemoteIpPrefix()),null);
+ }
}
NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
flowId = flowId + "_Permit";
- syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false);
+ syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false, securityServicesManager.isConntrackEnabled());
}
MatchBuilder matchBuilder = new MatchBuilder();
MatchUtils.createDhcpServerMatch(matchBuilder, dhcpMacAddress, 67, 68).build();
String flowId = "Ingress_DHCP_Server" + segmentationId + "_" + dhcpMacAddress + "_Permit_";
- syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false);
+ syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false, false);
}
/**
* @param priority the protocol priority
* @param write whether it is a write
* @param drop whether it is a drop or forward
+ * @param isCtCommit commit the connection or CT to track
*/
private void syncFlow(String flowName, NodeBuilder nodeBuilder,
MatchBuilder matchBuilder, Integer priority,
- boolean write, boolean drop) {
+ boolean write, boolean drop, boolean isCtCommit) {
+ MatchBuilder matchBuilder1 = matchBuilder;
+ if (isCtCommit) {
+ matchBuilder1 = MatchUtils.addCtState(matchBuilder1,0x81, 0x81);
+ }
FlowBuilder flowBuilder = new FlowBuilder();
- flowBuilder.setMatch(matchBuilder.build());
+ flowBuilder.setMatch(matchBuilder1.build());
FlowUtils.initFlowBuilder(flowBuilder, flowName, getTable()).setPriority(priority);
if (write) {
InstructionBuilder ib = this.getMutablePipelineInstructionBuilder();
+ InstructionBuilder ib1 = new InstructionBuilder();
+ ActionBuilder ab = new ActionBuilder();
+ ApplyActionsBuilder aab = new ApplyActionsBuilder();
if (drop) {
InstructionUtils.createDropInstructions(ib);
}
List<Instruction> instructionsList = Lists.newArrayList();
ib.setKey(new InstructionKey(0));
instructionsList.add(ib.build());
+ if (isCtCommit) {
+ LOG.info("Adding Conntarck rule, flowname = " + flowName);
+ ab.setAction(ActionUtils.nxConntrackAction(1, 0L, 0, (short)0xff));
+ ab.setOrder(0);
+ ab.setKey(new ActionKey(0));
+ List<Action> actionList = Lists.newArrayList();
+ actionList.add(ab.build());
+ aab.setAction(actionList);
+ ib1.setOrder(1);
+ ib1.setKey(new InstructionKey(1));
+ ib1.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
+ instructionsList.add(ib1.build());
+ }
isb.setInstruction(instructionsList);
flowBuilder.setInstructions(isb.build());
writeFlow(flowBuilder, nodeBuilder);
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;
for(final Entry<Ipv4Address, ArpResolverMetadata> gatewayToArpMetadataEntry : gatewayToArpMetadataMap.entrySet()){
final Ipv4Address gatewayIp = gatewayToArpMetadataEntry.getKey();
final ArpResolverMetadata gatewayMetaData =
- checkAndGetExternalBridgeDpid(gatewayToArpMetadataEntry.getValue());
+ checkAndGetExternalBridgeDpid(
+ resetFlowToRemove(gatewayIp, gatewayToArpMetadataEntry.getValue()));
gatewayMacRefresherPool.schedule(new Runnable(){
@Override
ArpResolverMetadata arpResolverMetadata = gatewayToArpMetadataMap.get(gatewayIp);
if(arpResolverMetadata != null && arpResolverMetadata.getGatewayMacAddress() != null){
if(!arpResolverMetadata.isPeriodicRefresh()){
+ resetFlowToRemove(gatewayIp, arpResolverMetadata);
return gatewayToArpMetadataMap.remove(gatewayIp).getGatewayMacAddress();
}
return arpResolverMetadata.getGatewayMacAddress();
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)
if(candidateGatewayIp != null){
LOG.debug("Resolved MAC for Gateway Ip {} is {}",gatewayIpAddress.getValue(),gatewayMacAddress.getValue());
candidateGatewayIp.setGatewayMacAddress(gatewayMacAddress);
- flowService.removeFlow(candidateGatewayIp.getFlowToRemove());
+ resetFlowToRemove(gatewayIpAddress, candidateGatewayIp);
}
}
}
@Override
public void stopPeriodicRefresh(Ipv4Address gatewayIp) {
init();
+ resetFlowToRemove(gatewayIp, null);
gatewayToArpMetadataMap.remove(gatewayIp);
}
+ private ArpResolverMetadata resetFlowToRemove(
+ final Ipv4Address gatewayIp, ArpResolverMetadata gatewayArpMetadata) {
+ checkNotNull(gatewayIp);
+
+ // If gatewayArpMetadata was not provided, look it up
+ if (gatewayArpMetadata == null) {
+ gatewayArpMetadata = gatewayToArpMetadataMap.get(gatewayIp);
+ }
+ if (gatewayArpMetadata != null && gatewayArpMetadata.getFlowToRemove() != null) {
+ LOG.debug("Flow to route ARP Reply to Controller from {} being removed from node {}",
+ gatewayIp, gatewayArpMetadata.getFlowToRemove().getNode());
+ flowService.removeFlow(gatewayArpMetadata.getFlowToRemove());
+ gatewayArpMetadata.setFlowToRemove(null);
+ }
+ return gatewayArpMetadata;
+ }
+
}
@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;
--- /dev/null
+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;
+ }
+ }
+}
}
}
}
+
container clustering-entity-ownership-service {
uses config:service-ref {
refine type {
}
}
}
+
+ leaf table-offset {
+ description "The table-offset is used to set the starting table for the netvirt pipeline";
+ type uint8;
+ }
}
}
}
--- /dev/null
+/*
+ * 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());
+ }
+}
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() {
@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
}
/**
- * Test method {@link AbstractServiceInstance#programDefaultPipelineRule(String)}
+ * Test method {@link AbstractServiceInstance#programDefaultPipelineRule(Node)}
*/
@Test
public void testProgramDefaultPipelineRule() {
@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
/**
* Test method
- * {@link PipelineOrchestratorImplr#getNextServiceInPipeline(Service)}
+ * {@link PipelineOrchestratorImpl#getNextServiceInPipeline(Service)}
*/
@Test
public void testGetNextServiceInPipeline() {
*/
@Test
public void testProgramFixedSecurityACLAdd1() throws Exception {
- ingressAclServiceSpy.programFixedSecurityGroup(Long.valueOf(1554), "2", MAC_ADDRESS, 1, false, false, true);
+ ingressAclServiceSpy.programFixedSecurityGroup(Long.valueOf(1554), "2", MAC_ADDRESS, 1, false, false, null, true);
verify(writeTransaction, times(0)).put(any(LogicalDatastoreType.class), any(InstanceIdentifier.class), any(Node.class), eq(true));
verify(writeTransaction, times(0)).submit();
@Test
public void testProgramFixedSecurityACLRemove1() throws Exception {
- ingressAclServiceSpy.programFixedSecurityGroup(Long.valueOf(1554), "2", MAC_ADDRESS, 1, false, false, false);
+ ingressAclServiceSpy.programFixedSecurityGroup(Long.valueOf(1554), "2", MAC_ADDRESS, 1, false, false, null, false);
verify(writeTransaction, times(0)).delete(any(LogicalDatastoreType.class), any(InstanceIdentifier.class));
verify(writeTransaction, times(0)).submit();
<properties>
<openflowplugin.version>0.2.0-SNAPSHOT</openflowplugin.version>
- <powermock.version>1.5.2</powermock.version>
+ <powermock.version>1.6.4</powermock.version>
<sfc.version>0.2.0-SNAPSHOT</sfc.version>
<sonar.jacoco.itReportPath>../it/target/jacoco-it.exec</sonar.jacoco.itReportPath>
</properties>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
+ <version>1.10.19</version>
<scope>test</scope>
</dependency>
<dependency>
</properties>
</configuration>
</plugin>
+ <plugin>
+ <groupId>org.jacoco</groupId>
+ <artifactId>jacoco-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>default-instrument</id>
+ <goals>
+ <goal>instrument</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>default-restore-instrumented-classes</id>
+ <goals>
+ <goal>restore-instrumented-classes</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
</plugins>
</build>
</project>
sfcClassifierService.program_sfEgress(dataPathId, sfIpPort, true);
sfcClassifierService.program_sfIngress(dataPathId, sfIpPort, sfOfPort, sfIpAddr, sfDplName, true);
sfcClassifierService.programStaticArpEntry(dataPathId, 0L, sfMac, sfIpAddr, true);
+ } else {
+ LOG.info("handleSf: sf and bridge are not on the same node: {} - {}, do nothing",
+ bridgeNode.getNodeId(), serviceFunction.getName());
}
}
String localIp = "";
Ip ip = sfcUtils.getSffIp(serviceFunctionForwarder);
Node ovsdbNode = southbound.readOvsdbNode(bridgeNode);
+ if (ovsdbNode != null) {
+ localIp = getLocalip(ovsdbNode);
+ }
+ return localIp.equals(String.valueOf(ip.getIp().getValue()));
+ }
+
+ private String getLocalip(Node ovsdbNode) {
+ Preconditions.checkNotNull("The ovsdbNode was null", ovsdbNode);
+ String localIp = null;
if (ovsdbNode != null) {
OvsdbNodeAugmentation ovsdbNodeAugmentation = ovsdbNode.getAugmentation(OvsdbNodeAugmentation.class);
if (ovsdbNodeAugmentation != null && ovsdbNodeAugmentation.getOpenvswitchOtherConfigs() != null) {
localIp = southbound.getOtherConfig(ovsdbNode, OvsdbTables.OPENVSWITCH, TUNNEL_ENDPOINT_KEY);
}
-
}
- return localIp.equals(String.valueOf(ip.getIp().getValue()));
+ if (localIp == null) {
+ LOG.warn("local_ip was not found for node: {}", ovsdbNode);
+ localIp = "";
+ }
+ return localIp;
}
private boolean isSfOnBridge(Node bridgeNode, ServiceFunction serviceFunction) {
port = tp.getAugmentation(OvsdbTerminationPointAugmentation.class);
if (port != null) {
ofPort = southbound.getOFPort(port);
+ LOG.info("found ofPort {} - {}, try: {}", portName, ofPort, i);
break;
}
}
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;
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);
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);
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);
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());
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);
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);
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);
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;
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;
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;
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;
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;
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;
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;
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";
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";
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() {
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),
};
}
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()),
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());
}
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;
}
}
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);
}
testModelDelete(builder, clazz);
}
+ private <T extends DataObject> void testModel(Builder<T> builder, Class<T> clazz)
+ throws InterruptedException {
+ testModelPut(builder, clazz);
+ Thread.sleep(1000);
+ testModelDelete(builder, clazz);
+ }
+
private ServiceFunctionsBuilder serviceFunctionsBuilder() {
String sf1Name = SF1NAME;
String sf1Ip = SF1IP;
String sf2DplName = SF2DPLNAME;
String sn2Name = SN2NAME;
String bridge2Name= BRIDGE2NAME;
- int port = GPEPORT;
+ int port = GPEUDPPORT;
ServiceFunctionBuilder serviceFunctionBuilder =
serviceFunctionUtils.serviceFunctionBuilder(sf1Ip, port, sf1DplName, sff1Name, sf1Name);
String sn2Name = SN2NAME;
String bridge2Name= BRIDGE2NAME;
String aclName = ACLNAME;
- int port = GPEPORT;
+ int port = GPEUDPPORT;
ServiceFunctionForwarderBuilder serviceFunctionForwarderBuilder =
serviceFunctionForwarderUtils.serviceFunctionForwarderBuilder(
@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<String, String> externalIds = Maps.newHashMap();
externalIds.put("attached-mac", "f6:00:00:0f:00:01");
southboundUtils.addTerminationPoint(bridgeNode, "vm2", "internal");
Map<String, String> 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 {
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<ControllerEntry> 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);
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);
//}
//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);
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);
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... ");
}
}
}
+
+ 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;
+ }
}
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());
<properties>
<neutron.model.version>0.6.0-SNAPSHOT</neutron.model.version>
- <powermock.version>1.5.2</powermock.version>
+ <powermock.version>1.6.4</powermock.version>
<sonar.jacoco.itReportPath>../net-virt-it/target/jacoco-it.exec</sonar.jacoco.itReportPath>
</properties>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
+ <version>1.10.19</version>
<scope>test</scope>
</dependency>
<dependency>
</properties>
</configuration>
</plugin>
+ <plugin>
+ <groupId>org.jacoco</groupId>
+ <artifactId>jacoco-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>default-instrument</id>
+ <goals>
+ <goal>instrument</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>default-restore-instrumented-classes</id>
+ <goals>
+ <goal>restore-instrumented-classes</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
</plugins>
</build>
</project>
<module>
<type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:netvirt:impl">prefix:netvirt-impl</type>
<name>netvirt-default</name>
+ <conntrack-enabled>false</conntrack-enabled>
<broker>
<type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-broker-osgi-registry</type>
<name>binding-osgi-broker</name>
--- /dev/null
+/*
+ * Copyright (c) 2016 Brocade Communications Systems, 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;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.ovsdb.utils.mdsal.utils.MdsalUtils;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+/**
+ * Class is a wrapper for MdsalUtils.java class. It wrap all the methods
+ * from MdsalUtils and call it only when *this* instance is net-virt master
+ * instances.
+ *
+ * Created by vishnoianil on 1/11/16.
+ */
+
+public class ClusterAwareMdsalUtils {
+
+ private static final Logger LOG = LoggerFactory.getLogger(ClusterAwareMdsalUtils.class);
+ private final MdsalUtils mdsalUtils;
+
+ /**
+ * Class constructor setting the MdsalUtils instance.
+ *
+ * @param dataBroker the {@link org.opendaylight.controller.md.sal.binding.api.DataBroker}
+ */
+ public ClusterAwareMdsalUtils(DataBroker dataBroker) {
+ mdsalUtils = new MdsalUtils(dataBroker);
+ }
+
+ /**
+ * Wrapper method to executes delete as a blocking transaction.
+ *
+ * @param store {@link LogicalDatastoreType} which should be modified
+ * @param path {@link InstanceIdentifier} to read from
+ * @param <D> the data object type
+ * @return the result of the request
+ */
+ public <D extends org.opendaylight.yangtools.yang.binding.DataObject> boolean delete(
+ final LogicalDatastoreType store, final InstanceIdentifier<D> path) {
+ if (NetvirtProvider.isMasterProviderInstance()) {
+ return mdsalUtils.delete(store,path);
+ }
+ return true;
+ }
+
+ /**
+ * Wrapper method to executes merge as a blocking transaction.
+ *
+ * @param logicalDatastoreType {@link LogicalDatastoreType} which should be modified
+ * @param path {@link InstanceIdentifier} for path to read
+ * @param data object of type D
+ * @return the result of the request
+ */
+ public <D extends org.opendaylight.yangtools.yang.binding.DataObject> boolean merge(
+ final LogicalDatastoreType logicalDatastoreType, final InstanceIdentifier<D> path, D data) {
+ if (NetvirtProvider.isMasterProviderInstance()) {
+ return mdsalUtils.merge(logicalDatastoreType,path, data);
+ }
+ return true;
+ }
+
+ /**
+ * Wrapper method to executes put as a blocking transaction.
+ *
+ * @param logicalDatastoreType {@link LogicalDatastoreType} which should be modified
+ * @param path {@link InstanceIdentifier} for path to read
+ * @param data object of type D
+ * @return the result of the request
+ */
+ public <D extends org.opendaylight.yangtools.yang.binding.DataObject> boolean put(
+ final LogicalDatastoreType logicalDatastoreType, final InstanceIdentifier<D> path, D data) {
+ if (NetvirtProvider.isMasterProviderInstance()) {
+ return mdsalUtils.put(logicalDatastoreType,path, data);
+ }
+ return true;
+ }
+
+ /**
+ * Wrapper method to executes read as a blocking transaction.
+ * Read is open for all instances to execute their normal
+ * control flow. Because with current implementation all the
+ * net-virt instances execute in similar way, because they want
+ * to build their local caches so that all the instances has same
+ * state of internal cache.
+ *
+ * @param store {@link LogicalDatastoreType} to read
+ * @param path {@link InstanceIdentifier} for path to read
+ * @param <D> the data object type
+ * @return the result as the data object requested
+ */
+ public <D extends org.opendaylight.yangtools.yang.binding.DataObject> D read(
+ final LogicalDatastoreType store, final InstanceIdentifier<D> path) {
+ return mdsalUtils.read(store,path);
+ }
+}
private List<ServiceRegistration<?>> translatorCRUDRegistrations = new ArrayList<>();
private List<Pair<Object, ServiceRegistration>> servicesAndRegistrations = new ArrayList<>();
private ProviderContext providerContext;
+ private boolean conntrackEnabled = false;
public ConfigActivator(ProviderContext providerContext) {
this.providerContext = providerContext;
new Class[] {INeutronSecurityRuleAware.class, INeutronSecurityGroupAware.class},
AbstractEvent.HandlerType.NEUTRON_PORT_SECURITY, portSecurityHandler);
- final SecurityServicesImpl securityServices = new SecurityServicesImpl();
+ final SecurityServicesImpl securityServices = new SecurityServicesImpl(conntrackEnabled);
registerService(context,
new String[]{SecurityServicesManager.class.getName()}, null, securityServices);
servicesAndRegistrations.add(Pair.of(impl, serviceRegistration));
return serviceRegistration;
}
+
+ public void setConntrackEnabled(boolean conntrackEnabled) {
+ this.conntrackEnabled = conntrackEnabled;
+ }
}
private static EntityOwnershipService entityOwnershipService;
private static final Entity ownerInstanceEntity = new Entity(
Constants.NETVIRT_OWNER_ENTITY_TYPE, Constants.NETVIRT_OWNER_ENTITY_TYPE);
+ private boolean conntrackEnabled = false;
public NetvirtProvider(BundleContext bundleContext, EntityOwnershipService eos) {
LOG.info("NetvirtProvider: bundleContext: {}", bundleContext);
public void onSessionInitiated(ProviderContext providerContext) {
dataBroker = providerContext.getSALService(DataBroker.class);
LOG.info("NetvirtProvider: onSessionInitiated dataBroker: {}", dataBroker);
+ LOG.info("NetvirtProvider: onSessionInitiated isConntrackEnabled: {}", this.conntrackEnabled);
this.activator = new ConfigActivator(providerContext);
+ activator.setConntrackEnabled(this.conntrackEnabled);
try {
activator.start(bundleContext);
} catch (Exception e) {
LOG.warn("Failed to start Netvirt: ", e);
}
}
+
+ public boolean isConntrackEnabled() {
+ return conntrackEnabled;
+ }
+
+ public void setConntrackEnabled(boolean conntackEnabled) {
+ this.conntrackEnabled = conntackEnabled;
+ }
}
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);
}
public static final Integer PREFIX_MATCH_PRIORITY_DROP = 36004;
public static final Integer PROTO_PREFIX_MATCH_PRIORITY_DROP = 36003;
public static final Integer PREFIX_PORT_MATCH_PRIORITY_DROP = 36002;
- public static final Integer PROTO_PORT_PREFIX_MATCH_PRIORITY_DROP = 36001;
public static final Integer PROTO_DHCP_CLIENT_TRAFFIC_MATCH_PRIORITY = 61012;
public static final Integer PROTO_MATCH_PRIORITY = 61010;
public static final Integer PROTO_PORT_PREFIX_MATCH_PRIORITY = 61007;
public static final Integer PROTO_DHCP_SERVER_MATCH_PRIORITY = 61006;
public static final Integer PROTO_VM_IP_MAC_MATCH_PRIORITY = 36001;
+ public static final Integer CT_STATE_UNTRACKED_PRIORITY = 62030;
+ public static final Integer CT_STATE_TRACKED_EST_PRIORITY = 62020;
+ public static final Integer CT_STATE_TRACKED_NEW_PRIORITY = 62010;
+ public static final Integer CT_STATE_NEW_PRIORITY_DROP = 36007;
public static final int TCP_SYN = 0x002;
public static final short INGRESS_ACL = 40; // Flows Destined to the VM Port go here
* *
* @param dpid the dpid
* @param segmentationId the segmentation id
- * @param attachedMac the attached mac
+ * @param attachedMac the dhcp mac
* @param localPort the local port
* @param isLastPortinSubnet is this the last port in the subnet
* @param isComputePort indicates whether this port is a compute port or not
+ * @param attachedMac2 the src mac
* @param write is this flow writing or deleting
*/
void programFixedSecurityGroup(Long dpid, String segmentationId, String attachedMac, long localPort,
- boolean isLastPortinSubnet, boolean isComputePort, boolean write);
+ boolean isLastPortinSubnet, boolean isComputePort, String attachedMac2, boolean write);
}
\ No newline at end of file
* @param write whether to add/delete flow.
*/
void syncSecurityRule(NeutronPort port, NeutronSecurityRule securityRule,Neutron_IPs vmIp, boolean write);
+ /**
+ * Is connection tracking enabled or not by the user (default is false).
+ * @return whether connection tracking enabled.
+ */
+ boolean isConntrackEnabled();
}
\ No newline at end of file
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
+import org.opendaylight.ovsdb.openstack.netvirt.ClusterAwareMdsalUtils;
import org.opendaylight.ovsdb.openstack.netvirt.ConfigInterface;
import org.opendaylight.ovsdb.openstack.netvirt.api.Constants;
import org.opendaylight.ovsdb.openstack.netvirt.api.OvsdbInventoryService;
import org.opendaylight.ovsdb.openstack.netvirt.translator.iaware.impl.NeutronSubnetChangeListener;
import org.opendaylight.ovsdb.openstack.netvirt.translator.iaware.impl.NeutronLoadBalancerPoolChangeListener;
import org.opendaylight.ovsdb.openstack.netvirt.translator.iaware.impl.NeutronLoadBalancerPoolMemberChangeListener;
-import org.opendaylight.ovsdb.utils.mdsal.utils.MdsalUtils;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
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.TopologyId;
private static DataBroker dataBroker = null;
private static Set<OvsdbInventoryListener> ovsdbInventoryListeners = Sets.newCopyOnWriteArraySet();
private OvsdbDataChangeListener ovsdbDataChangeListener = null;
- private static MdsalUtils mdsalUtils = null;
+ private static ClusterAwareMdsalUtils mdsalUtils = null;
public OvsdbInventoryServiceImpl(ProviderContext providerContext) {
dataBroker = providerContext.getSALService(DataBroker.class);
LOG.info("OvsdbInventoryServiceImpl initialized");
ovsdbDataChangeListener = new OvsdbDataChangeListener(dataBroker);
- mdsalUtils = new MdsalUtils(dataBroker);
+ mdsalUtils = new ClusterAwareMdsalUtils(dataBroker);
}
@Override
import java.util.List;
public class SecurityServicesImpl implements ConfigInterface, SecurityServicesManager {
+
private static final Logger LOG = LoggerFactory.getLogger(TenantNetworkManagerImpl.class);
private volatile INeutronPortCRUD neutronPortCache;
private volatile INeutronSubnetCRUD neutronSubnetCache;
private volatile ConfigurationService configurationService;
private volatile IngressAclProvider ingressAclProvider;
private volatile EgressAclProvider egressAclProvider;
+ private boolean isConntrackEnabled = false;
+
+ public SecurityServicesImpl() {
+ super();
+ }
+
+ public SecurityServicesImpl(boolean isConntrack) {
+ super();
+ this.isConntrackEnabled = isConntrack;
+ }
@Override
public boolean isPortSecurityReady(OvsdbTerminationPointAugmentation terminationPointAugmentation) {
egressAclProvider = (EgressAclProvider) impl;
}
}
+
+ @Override
+ public boolean isConntrackEnabled() {
+ return isConntrackEnabled;
+ }
}
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.ovsdb.openstack.netvirt.ClusterAwareMdsalUtils;
import org.opendaylight.ovsdb.openstack.netvirt.MdsalHelper;
import org.opendaylight.ovsdb.openstack.netvirt.NetworkHandler;
import org.opendaylight.ovsdb.openstack.netvirt.api.OvsdbTables;
import org.opendaylight.ovsdb.openstack.netvirt.api.Southbound;
-import org.opendaylight.ovsdb.utils.mdsal.utils.MdsalUtils;
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.params.xml.ns.yang.ovsdb.rev150105.*;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeExternalIds;
private static final Logger LOG = LoggerFactory.getLogger(SouthboundImpl.class);
private final DataBroker databroker;
private static final String PATCH_PORT_TYPE = "patch";
- private final MdsalUtils mdsalUtils;
+ private final ClusterAwareMdsalUtils mdsalUtils;
/**
* Class constructor setting the data broker.
*/
public SouthboundImpl(DataBroker dataBroker) {
this.databroker = dataBroker;
- mdsalUtils = new MdsalUtils(dataBroker);
+ mdsalUtils = new ClusterAwareMdsalUtils(dataBroker);
}
public DataBroker getDatabroker() {
@Override
public java.lang.AutoCloseable createInstance() {
NetvirtProvider provider = new NetvirtProvider(bundleContext, getClusteringEntityOwnershipServiceDependency());
+ provider.setConntrackEnabled(getConntrackEnabled());
BindingAwareBroker localBroker = getBrokerDependency();
localBroker.registerProvider(provider);
return provider;
}
}
}
+ leaf conntrack-enabled {
+ type boolean;
+ }
}
}
-}
+}
\ No newline at end of file
--- /dev/null
+/**
+ * Copyright (c) 2015 NEC Corporation 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.translator.crud.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+
+import static org.powermock.api.mockito.PowerMockito.mockStatic;
+import static org.powermock.api.mockito.PowerMockito.mock;
+import static org.powermock.api.mockito.PowerMockito.spy;
+import static org.powermock.api.mockito.PowerMockito.verifyStatic;
+import static org.powermock.api.mockito.PowerMockito.when;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.CheckedFuture;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
+import org.opendaylight.ovsdb.openstack.netvirt.translator.NeutronFloatingIP;
+import org.opendaylight.ovsdb.openstack.netvirt.translator.crud.INeutronFloatingIPCRUD;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.floatingips.attributes.Floatingips;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.floatingips.attributes.floatingips.Floatingip;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.floatingips.attributes.floatingips.FloatingipBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+
+/**
+ * Unit test for {@link NeutronFloatingIPInterface}
+ */
+@PrepareForTest({NeutronFloatingIPInterface.class})
+@RunWith(PowerMockRunner.class)
+public class NeutronFloatingIPInterfaceTest {
+ /**
+ * UUID_VALUE used for testing different scenarios.
+ */
+ private static final String UUID_VALUE = "b9a13232-525e-4d8c-be21-cd65e3436034";
+ /**
+ * FIXED_IP_ADDRESS used for testing different scenarios.
+ */
+ private static final String FIXED_IP_ADDRESS = "10.0.0.3";
+ /**
+ * FLOATING_IP_ADDRESS used for testing different scenarios.
+ */
+ private static final String FLOATING_IP_ADDRESS = "172.24.4.228";
+ /**
+ * STATUS used for testing different scenarios.
+ */
+ private static final String STATUS = "ACTIVE";
+ /**
+ * Floatingip object reference for unit testing.
+ */
+ private Floatingip floatingip = new FloatingipBuilder().setUuid(new Uuid(UUID_VALUE)).build();
+
+ /**
+ * Test that checks if @{NeutronFloatingIPInterface#floatingIPExists} is called
+ * and then checks that floating Ip exists or not.
+ */
+ @Test
+ public void testFloatingIPExists() throws Exception {
+ ProviderContext providerContext = mock(ProviderContext.class);
+ DataBroker broker = mock(DataBroker.class);
+ when(providerContext.getSALService(DataBroker.class)).thenReturn(broker);
+ ReadOnlyTransaction readOnlyTransaction = mock(ReadOnlyTransaction.class);
+ when(broker.newReadOnlyTransaction()).thenReturn(readOnlyTransaction);
+ NeutronFloatingIPInterface neutronFloatingIPInterface = new NeutronFloatingIPInterface(providerContext);
+ // First case: floatingIPExists() is expected to return true because the datastore contains a matching floating IP.
+ CheckedFuture succeedingFuture = mock(CheckedFuture.class);
+ when(succeedingFuture.checkedGet()).thenReturn(Optional.of(floatingip));
+ when(readOnlyTransaction.read(eq(LogicalDatastoreType.CONFIGURATION), any(InstanceIdentifier.class))).thenReturn(succeedingFuture);
+ assertTrue("Should return true, when floatingIPExists success.", neutronFloatingIPInterface.floatingIPExists(UUID_VALUE));
+ // Second case: the datastore has no matching floating IP, expect false
+ CheckedFuture failingFuture = mock(CheckedFuture.class);
+ when(failingFuture.checkedGet()).thenReturn(Optional.absent());
+ when(readOnlyTransaction.read(eq(LogicalDatastoreType.CONFIGURATION), any(InstanceIdentifier.class))).thenReturn(failingFuture);
+ assertFalse("Should return false for negative case.", neutronFloatingIPInterface.floatingIPExists(UUID_VALUE));
+ }
+
+ /**
+ * Test that checks if @{NeutronFloatingIPInterface#getFloatingIP} is called
+ * and then checks that it gets floating Ip or not.
+ */
+ @Test
+ public void testGetFloatingIP() throws Exception {
+ ProviderContext providerContext = mock(ProviderContext.class);
+ DataBroker broker = mock(DataBroker.class);
+ when(providerContext.getSALService(DataBroker.class)).thenReturn(broker);
+ ReadOnlyTransaction readOnlyTransaction = mock(ReadOnlyTransaction.class);
+ when(broker.newReadOnlyTransaction()).thenReturn(readOnlyTransaction);
+ NeutronFloatingIPInterface neutronFloatingIPInterface = new NeutronFloatingIPInterface(providerContext);
+ // First case: getFloatingIP is expected to return a valid object.
+ CheckedFuture succeedingFuture = mock(CheckedFuture.class);
+ when(succeedingFuture.checkedGet()).thenReturn(Optional.of(floatingip));
+ when(readOnlyTransaction.read(eq(LogicalDatastoreType.CONFIGURATION), any(InstanceIdentifier.class))).thenReturn(succeedingFuture);
+ NeutronFloatingIP neutronFloatingIPReceived = neutronFloatingIPInterface.getFloatingIP(UUID_VALUE);
+ assertEquals("UUID mismatch", UUID_VALUE, neutronFloatingIPReceived.getID());
+ // Second case: getFloatingIP returns null object.
+ CheckedFuture failingFuture = mock(CheckedFuture.class);
+ when(failingFuture.checkedGet()).thenReturn(Optional.absent());
+ when(readOnlyTransaction.read(eq(LogicalDatastoreType.CONFIGURATION), any(InstanceIdentifier.class))).thenReturn(failingFuture);
+ assertNull("Should be null for negative case.", neutronFloatingIPInterface.getFloatingIP(UUID_VALUE));
+ }
+
+ /**
+ * Test that checks if @{NeutronFloatingIPInterface#getAllFloatingIPs} is called
+ * and then checks that it gets all floating Ips in a list or not.
+ */
+ @Test
+ public void testGetAllFloatingIPs() throws Exception {
+ ProviderContext providerContext = mock(ProviderContext.class);
+ DataBroker broker = mock(DataBroker.class);
+ when(providerContext.getSALService(DataBroker.class)).thenReturn(broker);
+ ReadOnlyTransaction readOnlyTransaction = mock(ReadOnlyTransaction.class);
+ when(broker.newReadOnlyTransaction()).thenReturn(readOnlyTransaction);
+ NeutronFloatingIPInterface neutronFloatingIPInterface = new NeutronFloatingIPInterface(providerContext);
+ // First case: getAllFloatingIPs returns a list of valid objects.
+ CheckedFuture succeedingFuture = mock(CheckedFuture.class);
+ List<Floatingip> floatingipList = new ArrayList<>();
+ floatingipList.add(floatingip);
+ Floatingips floatingips = mock(Floatingips.class);
+ NeutronFloatingIP neutronFloatingIP = mock(NeutronFloatingIP.class);
+ when(floatingips.getFloatingip()).thenReturn(floatingipList);
+ when(succeedingFuture.checkedGet()).thenReturn(Optional.of(floatingips));
+ when(readOnlyTransaction.read(eq(LogicalDatastoreType.CONFIGURATION), any(InstanceIdentifier.class))).thenReturn(succeedingFuture);
+ List<NeutronFloatingIP> actualFloatingIps = neutronFloatingIPInterface.getAllFloatingIPs();
+ assertEquals("There should be one floating IP", 1, actualFloatingIps.size());
+ assertEquals("UUID mismatch", UUID_VALUE, actualFloatingIps.get(0).getID());
+ // Second case: getAllFloatingIPs not returns a list of valid objects.
+ CheckedFuture failingFuture = mock(CheckedFuture.class);
+ when(failingFuture.checkedGet()).thenReturn(Optional.absent());
+ when(readOnlyTransaction.read(eq(LogicalDatastoreType.CONFIGURATION), any(InstanceIdentifier.class))).thenReturn(failingFuture);
+ assertTrue("Non-empty list of floating IPs", neutronFloatingIPInterface.getAllFloatingIPs().isEmpty());
+ }
+
+ /**
+ * Test that checks if @{NeutronFloatingIPInterface#addFloatingIP} is called
+ * and then verifies whether floating Ip already exists in datastore if not then
+ * ensures floating ip addition by invoking MD-SAL add.
+ */
+ @Test
+ public void testAddFloatingIP() throws Exception {
+ ProviderContext providerContext = mock(ProviderContext.class);
+ DataBroker broker = mock(DataBroker.class);
+ WriteTransaction writeTransaction = mock(WriteTransaction.class);
+ NeutronFloatingIP neutronFloatingIP = mock(NeutronFloatingIP.class);
+ when(providerContext.getSALService(DataBroker.class)).thenReturn(broker);
+ ReadOnlyTransaction readOnlyTransaction = mock(ReadOnlyTransaction.class);
+ when(broker.newReadOnlyTransaction()).thenReturn(readOnlyTransaction);
+ NeutronFloatingIPInterface neutronFloatingIPInterface = new NeutronFloatingIPInterface(providerContext);
+ when(neutronFloatingIP.getID()).thenReturn(UUID_VALUE);
+ //First case: addFloatingIP returns false, the datastore has a matching floating IP.
+ CheckedFuture succeedingFuture = mock(CheckedFuture.class);
+ when(succeedingFuture.checkedGet()).thenReturn(Optional.of(floatingip));
+ when(readOnlyTransaction.read(eq(LogicalDatastoreType.CONFIGURATION), any(InstanceIdentifier.class))).thenReturn(succeedingFuture);
+ assertFalse("Should return false, floating Ip already exists.", neutronFloatingIPInterface.addFloatingIP(neutronFloatingIP));
+ //Second case: addFloatingIP returns true, the datastore has no matching floating IP, so invokes addMd() to write on datastore.
+ CheckedFuture failingFuture = mock(CheckedFuture.class);
+ when(broker.newWriteOnlyTransaction()).thenReturn(writeTransaction);
+ when(failingFuture.checkedGet()).thenReturn(Optional.absent());
+ when(writeTransaction.submit()).thenReturn(failingFuture);
+ when(readOnlyTransaction.read(eq(LogicalDatastoreType.CONFIGURATION), any(InstanceIdentifier.class))).thenReturn(failingFuture);
+ assertTrue("Should return true for addFloatingIP success.", neutronFloatingIPInterface.addFloatingIP(neutronFloatingIP));
+ }
+
+ /**
+ * Test that checks if @{NeutronFloatingIPInterface#removeFloatingIP} is called
+ * and then verifies by reading floating ip from datastore and ensures floating ip
+ * removal by invoking MD-SAL remove.
+ */
+ @Test
+ public void testRemoveFloatingIP() throws Exception {
+ ProviderContext providerContext = mock(ProviderContext.class);
+ DataBroker broker = mock(DataBroker.class);
+ WriteTransaction writeTransaction = mock(WriteTransaction.class);
+ NeutronFloatingIP neutronFloatingIP = mock(NeutronFloatingIP.class);
+ when(providerContext.getSALService(DataBroker.class)).thenReturn(broker);
+ ReadOnlyTransaction readOnlyTransaction = mock(ReadOnlyTransaction.class);
+ when(broker.newReadOnlyTransaction()).thenReturn(readOnlyTransaction);
+ NeutronFloatingIPInterface neutronFloatingIPInterface = new NeutronFloatingIPInterface(providerContext);
+ when(neutronFloatingIP.getID()).thenReturn(UUID_VALUE);
+ //First case: removeFloatingIP returns true by ensuring floating ip removal in datastore.
+ CheckedFuture succeedingFuture = mock(CheckedFuture.class);
+ when(succeedingFuture.checkedGet()).thenReturn(Optional.of(floatingip));
+ when(writeTransaction.submit()).thenReturn(succeedingFuture);
+ when(broker.newWriteOnlyTransaction()).thenReturn(writeTransaction);
+ when(readOnlyTransaction.read(eq(LogicalDatastoreType.CONFIGURATION), any(InstanceIdentifier.class))).thenReturn(succeedingFuture);
+ assertTrue("Should return true for removeFloatingIP success.", neutronFloatingIPInterface.removeFloatingIP(UUID_VALUE));
+ // Second case: removeFloatingIP returns false for negative case.
+ CheckedFuture failingFuture = mock(CheckedFuture.class);
+ when(broker.newWriteOnlyTransaction()).thenReturn(writeTransaction);
+ when(failingFuture.checkedGet()).thenReturn(Optional.absent());
+ when(writeTransaction.submit()).thenReturn(failingFuture);
+ when(readOnlyTransaction.read(eq(LogicalDatastoreType.CONFIGURATION), any(InstanceIdentifier.class))).thenReturn(failingFuture);
+ assertFalse("Should return false for negative case.", neutronFloatingIPInterface.removeFloatingIP(UUID_VALUE));
+ }
+
+ /**
+ * Test that checks if @{NeutronFloatingIPInterface#updateFloatingIP} is called
+ * and then verifies by reading floating ip from datastore and ensures floating ip
+ * updation by invoking MD-SAL update.
+ */
+ @Test
+ public void testUpdateFloatingIP() throws Exception {
+ ProviderContext providerContext = mock(ProviderContext.class);
+ DataBroker broker = mock(DataBroker.class);
+ WriteTransaction writeTransaction = mock(WriteTransaction.class);
+ NeutronFloatingIP neutronFloatingIP = mock(NeutronFloatingIP.class);
+ when(providerContext.getSALService(DataBroker.class)).thenReturn(broker);
+ ReadOnlyTransaction readOnlyTransaction = mock(ReadOnlyTransaction.class);
+ when(broker.newReadOnlyTransaction()).thenReturn(readOnlyTransaction);
+ NeutronFloatingIPInterface neutronFloatingIPInterface = new NeutronFloatingIPInterface(providerContext);
+ when(neutronFloatingIP.getID()).thenReturn(UUID_VALUE);
+ //First case: updateFloatingIP returns true by ensuring floating ip updation in datastore.
+ CheckedFuture succeedingFuture = mock(CheckedFuture.class);
+ when(succeedingFuture.checkedGet()).thenReturn(Optional.of(floatingip));
+ when(writeTransaction.submit()).thenReturn(succeedingFuture);
+ when(broker.newWriteOnlyTransaction()).thenReturn(writeTransaction);
+ when(readOnlyTransaction.read(eq(LogicalDatastoreType.CONFIGURATION), any(InstanceIdentifier.class))).thenReturn(succeedingFuture);
+ assertTrue("Should return true for updateFloatingIP success.", neutronFloatingIPInterface.updateFloatingIP(UUID_VALUE, neutronFloatingIP));
+ //Second case: updateFloatingIP returns false for negative case.
+ CheckedFuture failingFuture = mock(CheckedFuture.class);
+ when(broker.newWriteOnlyTransaction()).thenReturn(writeTransaction);
+ when(failingFuture.checkedGet()).thenReturn(Optional.absent());
+ when(writeTransaction.submit()).thenReturn(failingFuture);
+ when(readOnlyTransaction.read(eq(LogicalDatastoreType.CONFIGURATION), any(InstanceIdentifier.class))).thenReturn(failingFuture);
+ assertFalse("Should return false for negative case.", neutronFloatingIPInterface.updateFloatingIP(UUID_VALUE, neutronFloatingIP));
+ }
+
+ /**
+ * Test that checks if @{NeutronFloatingIPInterface#toMd} is called
+ * and then checks that it sets vales into floating Ip.
+ */
+ @Test
+ public void testToMd() throws Exception {
+ ProviderContext providerContext = mock(ProviderContext.class);
+ DataBroker broker = mock(DataBroker.class);
+ when(providerContext.getSALService(DataBroker.class)).thenReturn(broker);
+ NeutronFloatingIPInterface neutronFloatingIPInterface = new NeutronFloatingIPInterface(providerContext);
+ NeutronFloatingIP neutronFloatingIP = new NeutronFloatingIP();
+ neutronFloatingIP.setID(UUID_VALUE);
+ neutronFloatingIP.setFloatingNetworkUUID(UUID_VALUE);
+ neutronFloatingIP.setPortUUID(UUID_VALUE);
+ neutronFloatingIP.setFixedIPAddress(FIXED_IP_ADDRESS);
+ neutronFloatingIP.setFloatingIPAddress(FLOATING_IP_ADDRESS);
+ neutronFloatingIP.setTenantUUID(UUID_VALUE);
+ neutronFloatingIP.setRouterUUID(UUID_VALUE);
+ neutronFloatingIP.setStatus(STATUS);
+ Floatingip floatingipReceived = neutronFloatingIPInterface.toMd(neutronFloatingIP);
+ assertEquals("UUID mismatch", UUID_VALUE, String.valueOf(floatingipReceived.getUuid().getValue()));
+ assertEquals("FloatingNetworkId mismatch", UUID_VALUE, String.valueOf(floatingipReceived.getFloatingNetworkId().getValue()));
+ assertEquals("Port ID mismatch", UUID_VALUE, String.valueOf(floatingipReceived.getPortId().getValue()));
+ assertEquals("Fixed IP Address mismatch", FIXED_IP_ADDRESS, String.valueOf(floatingipReceived.getFixedIpAddress().getValue()));
+ assertEquals("Floating IP Address mismatch", FLOATING_IP_ADDRESS, String.valueOf(floatingipReceived.getFloatingIpAddress().getValue()));
+ assertEquals("Tenant Id mismatch", UUID_VALUE, String.valueOf(floatingipReceived.getTenantId().getValue()));
+ assertEquals("Router Id mismatch", UUID_VALUE, String.valueOf(floatingipReceived.getRouterId().getValue()));
+ assertEquals("Status mismatch", STATUS, String.valueOf(floatingipReceived.getStatus()));
+ }
+
+ /**
+ * Test that checks if @{NeutronFloatingIPInterface#fromMd} is called
+ * and then checks that it gets values from Floating Ip.
+ */
+ @Test
+ public void testFromMd() throws Exception {
+ ProviderContext providerContext = mock(ProviderContext.class);
+ DataBroker broker = mock(DataBroker.class);
+ when(providerContext.getSALService(DataBroker.class)).thenReturn(broker);
+ Floatingip actualfloatingip = new FloatingipBuilder()
+ .setUuid(new Uuid(UUID_VALUE))
+ .setFixedIpAddress(
+ new IpAddress(FIXED_IP_ADDRESS.toCharArray()))
+ .setFloatingIpAddress(
+ new IpAddress(FLOATING_IP_ADDRESS.toCharArray()))
+ .setFloatingNetworkId(new Uuid(UUID_VALUE))
+ .setPortId(new Uuid(UUID_VALUE))
+ .setRouterId(new Uuid(UUID_VALUE)).setStatus(STATUS)
+ .setTenantId(new Uuid(UUID_VALUE)).build();
+ NeutronFloatingIPInterface neutronFloatingIPInterface = new NeutronFloatingIPInterface(providerContext);
+ NeutronFloatingIP neutronFloatingIPReceived = neutronFloatingIPInterface.fromMd(actualfloatingip);
+ assertEquals("UUID mismatch", UUID_VALUE, neutronFloatingIPReceived.getID());
+ assertEquals("FloatingNetworkId mismatch", UUID_VALUE, neutronFloatingIPReceived.getFloatingNetworkUUID());
+ assertEquals("Port ID mismatch", UUID_VALUE, neutronFloatingIPReceived.getPortUUID());
+ assertEquals("Fixed IP Address mismatch", FIXED_IP_ADDRESS, neutronFloatingIPReceived.getFixedIPAddress());
+ assertEquals("Floating IP Address mismatch", FLOATING_IP_ADDRESS, neutronFloatingIPReceived.getFloatingIPAddress());
+ assertEquals("Tenant Id mismatch", UUID_VALUE, neutronFloatingIPReceived.getTenantUUID());
+ assertEquals("Router Id mismatch", UUID_VALUE, neutronFloatingIPReceived.getRouterUUID());
+ assertEquals("Status mismatch", STATUS, neutronFloatingIPReceived.getStatus());
+ }
+
+ /**
+ * Test that checks if @{NeutronFloatingIPInterface#registerNewInterface} is called
+ * and then checks that it register service or not.
+ */
+ @Ignore
+ @Test
+ public void testRegisterNewInterface() throws Exception {
+ ProviderContext providerContext = mock(ProviderContext.class);
+ DataBroker broker = mock(DataBroker.class);
+ BundleContext bundleContext = mock(BundleContext.class);
+ ServiceRegistration serviceRegistration = mock(ServiceRegistration.class);
+ mockStatic(NeutronFloatingIPInterface.class);
+ List<ServiceRegistration<?>> serviceRegistrationList = new ArrayList<>();
+ serviceRegistrationList.add(serviceRegistration);
+ when(providerContext.getSALService(DataBroker.class)).thenReturn(broker);
+ NeutronFloatingIPInterface neutronFloatingIPInterface = spy(new NeutronFloatingIPInterface(providerContext));
+ when(bundleContext.registerService(INeutronFloatingIPCRUD.class, neutronFloatingIPInterface, null)).thenReturn(serviceRegistration);
+ NeutronFloatingIPInterface.registerNewInterface(bundleContext, providerContext, serviceRegistrationList);
+ verifyStatic();
+ NeutronFloatingIPInterface.registerNewInterface(any(BundleContext.class), any(ProviderContext.class), any(List.class));
+ }
+}
\ No newline at end of file
</scm>
<properties>
- <powermock.version>1.5.2</powermock.version>
+ <powermock.version>1.6.4</powermock.version>
</properties>
<dependencies>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
+ <version>1.10.19</version>
<scope>test</scope>
</dependency>
<dependency>
<version>${powermock.version}</version>
</dependency>
</dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.jacoco</groupId>
+ <artifactId>jacoco-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>default-instrument</id>
+ <goals>
+ <goal>instrument</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>default-restore-instrumented-classes</id>
+ <goals>
+ <goal>restore-instrumented-classes</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
</project>
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.Address;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.TunnelBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.OfjNxHashFields;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.OfjNxMpAlgorithm;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.DstChoice;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.*;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxArpShaCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxArpThaCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxNshc1CaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxNshc2CaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxRegCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxTunIdCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxTunIpv4DstCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstOfArpOpCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstOfArpSpaCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstOfArpTpaCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstOfEthDstCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.group.buckets.bucket.action.action.NxActionRegLoadNodesNodeGroupBucketsBucketActionsCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.group.buckets.bucket.action.action.NxActionRegMoveNodesNodeGroupBucketsBucketActionsCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.table.flow.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.*;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.table.flow.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.NxActionConntrackNodesNodeTableFlowApplyActionsCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.table.flow.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.NxActionMultipathNodesNodeTableFlowApplyActionsCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.table.flow.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.NxActionOutputRegNodesNodeTableFlowApplyActionsCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.table.flow.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.NxActionRegLoadNodesNodeTableFlowApplyActionsCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.table.flow.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.NxActionRegMoveNodesNodeTableFlowApplyActionsCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.table.flow.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.NxActionResubmitNodesNodeTableFlowApplyActionsCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.table.flow.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.NxActionSetNshc1NodesNodeTableFlowApplyActionsCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.table.flow.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.NxActionSetNshc2NodesNodeTableFlowApplyActionsCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.table.flow.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.NxActionSetNshc3NodesNodeTableFlowApplyActionsCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.table.flow.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.NxActionSetNshc4NodesNodeTableFlowApplyActionsCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.table.flow.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.NxActionSetNsiNodesNodeTableFlowApplyActionsCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.table.flow.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.NxActionSetNspNodesNodeTableFlowApplyActionsCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.conntrack.grouping.NxConntrack;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.conntrack.grouping.NxConntrackBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.multipath.grouping.NxMultipath;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.multipath.grouping.NxMultipathBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.output.reg.grouping.NxOutputReg;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.output.reg.grouping.NxOutputRegBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.reg.load.grouping.NxRegLoad;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.reg.move.grouping.NxRegMove;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.reg.move.grouping.NxRegMoveBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.reg.move.grouping.nx.reg.move.SrcBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.resubmit.grouping.NxResubmit;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.resubmit.grouping.NxResubmitBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.set.nshc._1.grouping.NxSetNshc1;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.set.nshc._1.grouping.NxSetNshc1Builder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.set.nshc._2.grouping.NxSetNshc2;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.set.nshc._3.grouping.NxSetNshc3Builder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.set.nshc._4.grouping.NxSetNshc4;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.set.nshc._4.grouping.NxSetNshc4Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.set.nsi.grouping.NxSetNsi;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.set.nsi.grouping.NxSetNsiBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.set.nsp.grouping.NxSetNsp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.set.nsp.grouping.NxSetNspBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.SrcChoice;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxArpShaCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxNshc1CaseBuilder;
return new NxActionMultipathNodesNodeTableFlowApplyActionsCaseBuilder().setNxMultipath(r).build();
}
+ public static Action nxConntrackAction(Integer flags, Long zoneSrc,
+ Integer conntrackZone, Short recircTable) {
+ NxConntrack r = new NxConntrackBuilder()
+ .setFlags(flags)
+ .setZoneSrc(zoneSrc)
+ .setConntrackZone(conntrackZone)
+ .setRecircTable(recircTable)
+ .build();
+ return new NxActionConntrackNodesNodeTableFlowApplyActionsCaseBuilder().setNxConntrack(r).build();
+ }
+
/**
* Accepts a MAC address and returns the corresponding long, where the
* MAC bytes are set on the lower order bytes of the long.
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg4;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg5;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg6;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmOfEthDst;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.ExtensionKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralAugMatchNodesNodeTableFlow;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralAugMatchNodesNodeTableFlowBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.general.extension.list.grouping.ExtensionListBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxAugMatchNodesNodeTableFlow;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxAugMatchNodesNodeTableFlowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxmNxCtStateKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxmNxCtZoneKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxmNxReg0Key;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxmNxReg1Key;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxmNxReg2Key;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxmOfTcpSrcKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxmOfUdpDstKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxmOfUdpSrcKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.nxm.nx.ct.state.grouping.NxmNxCtStateBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.nxm.nx.ct.zone.grouping.NxmNxCtZoneBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.nxm.nx.reg.grouping.NxmNxRegBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.nxm.nx.tun.id.grouping.NxmNxTunIdBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxmNxNspKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.nxm.nx.nsp.grouping.NxmNxNspBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxmNxNsiKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.nxm.nx.nsi.grouping.NxmNxNsiBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.nxm.of.tcp.dst.grouping.NxmOfTcpDstBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.nxm.of.eth.dst.grouping.NxmOfEthDstBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.nxm.of.tcp.src.grouping.NxmOfTcpSrcBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.nxm.of.tcp.dst.grouping.NxmOfTcpDstBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.nxm.of.udp.dst.grouping.NxmOfUdpDstBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.nxm.of.udp.src.grouping.NxmOfUdpSrcBuilder;
import org.slf4j.Logger;
return matchBuilder;
}
+ public static MatchBuilder addCtState(MatchBuilder matchBuilder,int ct_state, int mask) {
+ NxmNxCtStateBuilder ctStateBuilder = new NxmNxCtStateBuilder();
+ ctStateBuilder.setCtState((long)ct_state);
+ ctStateBuilder.setMask((long)mask);
+ NxAugMatchNodesNodeTableFlow nxAugMatch = new NxAugMatchNodesNodeTableFlowBuilder()
+ .setNxmNxCtState(ctStateBuilder.build())
+ .build();
+ GeneralAugMatchNodesNodeTableFlow genAugMatch = new GeneralAugMatchNodesNodeTableFlowBuilder()
+ .setExtensionList(ImmutableList.of(new ExtensionListBuilder().setExtensionKey(NxmNxCtStateKey.class)
+ .setExtension(new ExtensionBuilder()
+ .addAugmentation(NxAugMatchNodesNodeTableFlow.class, nxAugMatch)
+ .build()).build())).build();
+ matchBuilder.addAugmentation(GeneralAugMatchNodesNodeTableFlow.class, genAugMatch);
+ return matchBuilder;
+ }
+
+ public static MatchBuilder addCtZone(MatchBuilder matchBuilder,int ct_zone) {
+ NxmNxCtZoneBuilder ctZoneBuilder = new NxmNxCtZoneBuilder();
+ ctZoneBuilder.setCtZone(ct_zone);
+ NxAugMatchNodesNodeTableFlow nxAugMatch = new NxAugMatchNodesNodeTableFlowBuilder()
+ .setNxmNxCtZone(ctZoneBuilder.build())
+ .build();
+ GeneralAugMatchNodesNodeTableFlow genAugMatch = new GeneralAugMatchNodesNodeTableFlowBuilder()
+ .setExtensionList(ImmutableList.of(new ExtensionListBuilder().setExtensionKey(NxmNxCtZoneKey.class)
+ .setExtension(new ExtensionBuilder()
+ .addAugmentation(NxAugMatchNodesNodeTableFlow.class, nxAugMatch)
+ .build()).build())).build();
+ matchBuilder.addAugmentation(GeneralAugMatchNodesNodeTableFlow.class, genAugMatch);
+ return matchBuilder;
+ }
+
public static class RegMatch {
final Class<? extends NxmNxReg> reg;
final Long value;
</scm>
<properties>
- <powermock.version>1.5.2</powermock.version>
+ <powermock.version>1.6.4</powermock.version>
</properties>
<dependencies>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
+ <version>1.10.19</version>
<scope>test</scope>
</dependency>
<dependency>
</instructions>
</configuration>
</plugin>
+ <plugin>
+ <groupId>org.jacoco</groupId>
+ <artifactId>jacoco-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>default-instrument</id>
+ <goals>
+ <goal>instrument</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>default-restore-instrumented-classes</id>
+ <goals>
+ <goal>restore-instrumented-classes</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
</plugins>
</build>
</project>