Merge "UT for ProtocolRemovedCommand class"
authorSam Hague <shague@redhat.com>
Wed, 25 Nov 2015 14:41:47 +0000 (14:41 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Wed, 25 Nov 2015 14:41:48 +0000 (14:41 +0000)
40 files changed:
commons/parent/pom.xml
features/ovsdb/pom.xml
features/ovsdb/src/main/features/features.xml
openstack/net-virt-it/pom.xml
openstack/net-virt-it/src/test/java/org/opendaylight/ovsdb/openstack/netvirt/it/NetvirtIT.java
openstack/net-virt-it/src/test/java/org/opendaylight/ovsdb/openstack/netvirt/it/NetvirtITConstants.java
openstack/net-virt-it/src/test/java/org/opendaylight/ovsdb/openstack/netvirt/it/SouthboundMapper.java
openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/services/EgressAclService.java
openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/services/IngressAclService.java
openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/services/L2ForwardingService.java
openstack/net-virt-providers/src/test/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/services/EgressAclServiceTest.java
openstack/net-virt-providers/src/test/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/services/IngressAclServiceTest.java
openstack/net-virt-sfc/api/pom.xml
openstack/net-virt-sfc/api/src/main/yang/netvirt-acl.yang
openstack/net-virt-sfc/features/production/pom.xml
openstack/net-virt-sfc/features/production/src/main/features/features.xml
openstack/net-virt-sfc/features/test/src/main/features/features.xml
openstack/net-virt-sfc/impl/pom.xml
openstack/net-virt-sfc/impl/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/ISfcClassifierService.java
openstack/net-virt-sfc/impl/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/SfcUtils.java
openstack/net-virt-sfc/impl/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/standalone/openflow13/NetvirtSfcStandaloneOF13Provider.java
openstack/net-virt-sfc/impl/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/standalone/openflow13/services/SfcClassifierService.java
openstack/net-virt-sfc/impl/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/workaround/NetvirtSfcWorkaroundOF13Provider.java
openstack/net-virt-sfc/impl/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/workaround/services/SfcClassifierService.java
openstack/net-virt-sfc/it/src/test/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/NetvirtSfcIT.java
openstack/net-virt-sfc/it/src/test/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/utils/AclUtils.java
openstack/net-virt/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/MdsalHelper.java
openstack/net-virt/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/NorthboundEvent.java
openstack/net-virt/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/PortSecurityHandler.java
openstack/net-virt/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/api/BridgeConfigurationManager.java
openstack/net-virt/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/impl/BridgeConfigurationManagerImpl.java
openstack/net-virt/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/impl/OvsdbInventoryServiceImpl.java
openstack/net-virt/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/impl/SouthboundImpl.java
openstack/net-virt/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/translator/iaware/impl/NeutronSecurityRuleDataChangeListener.java
openstack/net-virt/src/test/java/org/opendaylight/ovsdb/openstack/netvirt/PortSecurityHandlerTest.java
resources/commons/Ovsdb-HwvtepSouthbound-Collection.json.postman_collection [new file with mode: 0755]
resources/commons/README
utils/mdsal-openflow/src/main/java/org/opendaylight/ovsdb/utils/mdsal/openflow/FlowUtils.java
utils/mdsal-openflow/src/main/java/org/opendaylight/ovsdb/utils/mdsal/openflow/InstructionUtils.java
utils/mdsal-openflow/src/main/java/org/opendaylight/ovsdb/utils/mdsal/openflow/MatchUtils.java

index 641001fb555920ebbc27971422eb667bffe82349..073bc212466cfa1816a2b3780064353c1cbefac0 100644 (file)
@@ -96,10 +96,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
     <sal.version>0.10.0-SNAPSHOT</sal.version>
     <switchmanager.api.version>0.9.0-SNAPSHOT</switchmanager.api.version>
     <yangtools.version>0.8.0-SNAPSHOT</yangtools.version>
-    <!-- 3rd Pary Dependency Versions -->
-    <commons.collection.version>1.0</commons.collection.version>
-    <httpcomponents.version>4.2.1</httpcomponents.version>
-    <portlet.version>2.0</portlet.version>
+    <!-- 3rd Party Dependency Versions -->
     <powermock.version>1.5.2</powermock.version>
     <dlux.version>0.3.0-SNAPSHOT</dlux.version>
     <ovsdb.ui.version>0.1.0-SNAPSHOT</ovsdb.ui.version>
@@ -121,46 +118,16 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
         <type>pom</type>
         <scope>import</scope>
       </dependency>
-      <dependency>
-        <groupId>commons-collections</groupId>
-        <artifactId>commons-collections</artifactId>
-        <version>${commons.collection.version}</version>
-      </dependency>
       <dependency>
         <groupId>io.netty</groupId>
         <artifactId>netty-all</artifactId>
         <version>${netty.version}</version>
       </dependency>
-      <dependency>
-        <groupId>javax.portlet</groupId>
-        <artifactId>portlet-api</artifactId>
-        <version>${portlet.version}</version>
-      </dependency>
-      <dependency>
-        <groupId>org.apache.httpcomponents</groupId>
-        <artifactId>httpcore-nio</artifactId>
-        <version>${httpcomponents.version}</version>
-      </dependency>
-      <dependency>
-        <groupId>org.opendaylight.controller</groupId>
-        <artifactId>commons.northbound</artifactId>
-        <version>${northbound.commons.version}</version>
-      </dependency>
       <dependency>
         <groupId>org.opendaylight.controller</groupId>
         <artifactId>config-api</artifactId>
         <version>${controller.config.version}</version>
       </dependency>
-      <dependency>
-        <groupId>org.opendaylight.controller</groupId>
-        <artifactId>containermanager</artifactId>
-        <version>${containermanager.version}</version>
-      </dependency>
-      <dependency>
-        <groupId>org.opendaylight.controller</groupId>
-        <artifactId>forwardingrulesmanager</artifactId>
-        <version>${forwardingrulesmanager.version}</version>
-      </dependency>
       <dependency>
         <groupId>org.opendaylight.neutron</groupId>
         <artifactId>neutron-spi</artifactId>
@@ -172,11 +139,6 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
         <version>1.6.0-SNAPSHOT</version>
         <type>zip</type>
       </dependency>
-      <dependency>
-        <groupId>org.opendaylight.controller</groupId>
-        <artifactId>sal</artifactId>
-        <version>${sal.version}</version>
-      </dependency>
 
       <dependency>
         <groupId>org.opendaylight.yangtools</groupId>
@@ -207,11 +169,6 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
         <scope>import</scope>
       </dependency>
 
-      <dependency>
-        <groupId>org.opendaylight.controller</groupId>
-        <artifactId>switchmanager</artifactId>
-        <version>${switchmanager.api.version}</version>
-      </dependency>
       <dependency>
         <groupId>org.opendaylight.openflowplugin.model</groupId>
         <artifactId>model-flow-base</artifactId>
index 4d7745686318a066b5bff51f346db2fd0f337059..a5d890a212116632d84761ebfa27ebd9a61e073d 100644 (file)
@@ -15,7 +15,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
     <groupId>org.opendaylight.odlparent</groupId>
     <artifactId>features-parent</artifactId>
     <version>1.6.0-SNAPSHOT</version>
-    <relativePath></relativePath>
+    <relativePath/>
   </parent>
 
   <groupId>org.opendaylight.ovsdb</groupId>
@@ -47,7 +47,6 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
   <properties>
     <odl.karaf.base.version>1.6.0-SNAPSHOT</odl.karaf.base.version>
     <mdsal.version>1.3.0-SNAPSHOT</mdsal.version>
-    <io.netty.version>3.8.0.Final</io.netty.version>
     <networkconfig.neutron.version>0.6.0-SNAPSHOT</networkconfig.neutron.version>
     <ovsdb.library.version>1.2.1-SNAPSHOT</ovsdb.library.version>
     <openstack.netvirt.version>1.2.1-SNAPSHOT</openstack.netvirt.version>
@@ -118,12 +117,6 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
     <dependency>
       <groupId>org.apache.commons</groupId>
       <artifactId>commons-lang3</artifactId>
-      <version>${commons.lang3.version}</version>
-    </dependency>
-    <dependency>
-      <groupId>io.netty</groupId>
-      <artifactId>netty</artifactId>
-      <version>${io.netty.version}</version>
     </dependency>
     <dependency>
       <groupId>io.netty</groupId>
@@ -133,42 +126,34 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
     <dependency>
       <groupId>io.netty</groupId>
       <artifactId>netty-buffer</artifactId>
-      <version>${netty.version}</version>
     </dependency>
     <dependency>
       <groupId>io.netty</groupId>
       <artifactId>netty-codec</artifactId>
-      <version>${netty.version}</version>
     </dependency>
     <dependency>
       <groupId>io.netty</groupId>
       <artifactId>netty-codec-http</artifactId>
-      <version>${netty.version}</version>
     </dependency>
     <dependency>
       <groupId>io.netty</groupId>
       <artifactId>netty-common</artifactId>
-      <version>${netty.version}</version>
     </dependency>
     <dependency>
       <groupId>io.netty</groupId>
       <artifactId>netty-handler</artifactId>
-      <version>${netty.version}</version>
     </dependency>
     <dependency>
       <groupId>io.netty</groupId>
       <artifactId>netty-transport</artifactId>
-      <version>${netty.version}</version>
     </dependency>
     <dependency>
       <groupId>equinoxSDK381</groupId>
       <artifactId>javax.servlet</artifactId>
-      <version>3.0.0.v201112011016</version>
     </dependency>
     <dependency>
       <groupId>equinoxSDK381</groupId>
       <artifactId>javax.servlet.jsp</artifactId>
-      <version>2.2.0.v201112011158</version>
     </dependency>
     <dependency>
       <groupId>equinoxSDK381</groupId>
@@ -327,10 +312,5 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
       <classifier>features</classifier>
       <type>xml</type>
     </dependency>
-    <dependency>
-        <groupId>org.opendaylight.ovsdb</groupId>
-        <artifactId>ovsdb-ui-bundle</artifactId>
-        <version>${ovsdb.ui.version}</version>
-    </dependency>
   </dependencies>
 </project>
index f301542343636a8668e8747223f4d55369f82516..e36f3d1158e9e9a233463fb9a8e221fef4bbf6b5 100644 (file)
@@ -2,13 +2,13 @@
 <features name="ovsdb-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.2.0"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           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/${openflowplugin.version}/xml/features</repository>
-  <repository>mvn:org.opendaylight.openflowplugin/features-openflowplugin/${openflowplugin.version}/xml/features</repository>
-  <repository>mvn:org.opendaylight.neutron/features-neutron/${networkconfig.neutron.version}/xml/features</repository>
+  <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.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/${mdsal.version}/xml/features</repository>
-  <repository>mvn:org.opendaylight.ovsdb/library-features/${ovsdb.library.version}/xml/features</repository>
-  <repository>mvn:org.opendaylight.dlux/features-dlux/${dlux.version}/xml/features</repository>
+  <repository>mvn:org.opendaylight.controller/features-mdsal/{{VERSION}}/xml/features</repository>
+  <repository>mvn:org.opendaylight.ovsdb/library-features/{{VERSION}}/xml/features</repository>
+  <repository>mvn:org.opendaylight.dlux/features-dlux/{{VERSION}}/xml/features</repository>
 
   <feature name="odl-ovsdb-all" description="OpenDaylight :: OVSDB :: all"
            version='${project.version}'>
   <feature name="odl-ovsdb-schema-openvswitch" description="OVSDB :: Schema :: Open_vSwitch"
            version='${schema.openvswitch.version}'>
     <feature version="${ovsdb.library.version}">odl-ovsdb-library</feature>
-    <bundle>mvn:org.opendaylight.ovsdb/schema.openvswitch/${schema.openvswitch.version}</bundle>
+    <bundle>mvn:org.opendaylight.ovsdb/schema.openvswitch/{{VERSION}}</bundle>
   </feature>
 
   <feature name="odl-ovsdb-schema-hardwarevtep" description="OVSDB :: Schema :: hardware_vtep"
            version='${schema.hardwarevtep.version}'>
     <feature version="${ovsdb.library.version}">odl-ovsdb-library</feature>
-    <bundle>mvn:org.opendaylight.ovsdb/schema.hardwarevtep/${schema.hardwarevtep.version}</bundle>
+    <bundle>mvn:org.opendaylight.ovsdb/schema.hardwarevtep/{{VERSION}}</bundle>
   </feature>
 
   <feature name="odl-ovsdb-openstack" description="OpenDaylight :: OVSDB :: OpenStack Network Virtualization"
     <feature version='${mdsal.version}'>odl-mdsal-broker</feature>
     <feature version="${openflowplugin.version}">odl-openflowplugin-nsf-model</feature>
     <feature version="${networkconfig.neutron.version}">odl-neutron-service</feature>
-    <feature version="1.2.1-SNAPSHOT">odl-ovsdb-southbound-impl-ui</feature>
+    <feature version="${project.version}">odl-ovsdb-southbound-impl-ui</feature>
     <feature version="${openflowplugin.version}">odl-openflowplugin-flow-services</feature>
     <feature version="${openflowplugin.version}">odl-openflowplugin-nxm-extensions</feature>
-    <bundle>mvn:org.opendaylight.ovsdb/utils.servicehelper/${ovsdb.utils.servicehelper.version}</bundle>
-    <bundle>mvn:org.opendaylight.ovsdb/utils.mdsal-utils/${project.version}</bundle>
-    <bundle>mvn:org.opendaylight.ovsdb/openstack.net-virt/${openstack.netvirt.version}</bundle>
-    <bundle>mvn:org.opendaylight.ovsdb/openstack.net-virt-providers/${openstack.netvirt.providers.version}</bundle>
-    <bundle>mvn:org.opendaylight.neutron/dummyprovider/${networkconfig.neutron.version}</bundle>
-    <configfile finalname="etc/opendaylight/karaf/netvirt-impl-default-config.xml">mvn:org.opendaylight.ovsdb/openstack.net-virt/${project.version}/xml/config</configfile>
-    <configfile finalname="etc/opendaylight/karaf/netvirt-providers-impl-default-config.xml">mvn:org.opendaylight.ovsdb/openstack.net-virt-providers/${project.version}/xml/config</configfile>
+    <bundle>mvn:org.opendaylight.ovsdb/utils.servicehelper/{{VERSION}}</bundle>
+    <bundle>mvn:org.opendaylight.ovsdb/utils.mdsal-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='${ovsdb.ui.version}'>
     <feature version="${dlux.version}">odl-dlux-core</feature>
-    <bundle>mvn:org.opendaylight.ovsdb/ovsdb-ui-bundle/${ovsdb.ui.version}</bundle>
+    <bundle>mvn:org.opendaylight.ovsdb/ovsdb-ui-bundle/{{VERSION}}</bundle>
   </feature>
 </features>
index 4bf8c654b5455ea490664f375b9b040e743c0df0..45699700631e75cf822ff6fa19e6a8a19b573fdc 100644 (file)
@@ -40,6 +40,14 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
     <tag>HEAD</tag>
     <url>https://wiki.opendaylight.org/view/OVSDB_Integration:Main</url>
   </scm>
+
+  <properties>
+    <karaf.distro.groupId>org.opendaylight.ovsdb</karaf.distro.groupId>
+    <karaf.distro.artifactId>karaf</karaf.distro.artifactId>
+    <karaf.distro.version>${project.version}</karaf.distro.version>
+    <karaf.distro.type>zip</karaf.distro.type>
+  </properties>
+
   <dependencyManagement>
     <dependencies>
       <dependency>
@@ -85,61 +93,11 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>config-util</artifactId>
     </dependency>
-    <!-- Dependencies for pax exam karaf container -->
-    <dependency>
-      <groupId>org.ops4j.pax.exam</groupId>
-      <artifactId>pax-exam-container-karaf</artifactId>
-      <scope>compile</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.ops4j.pax.exam</groupId>
-      <artifactId>pax-exam-junit4</artifactId>
-      <scope>compile</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.ops4j.pax.exam</groupId>
-      <artifactId>pax-exam</artifactId>
-      <scope>compile</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.ops4j.pax.url</groupId>
-      <artifactId>pax-url-aether</artifactId>
-      <scope>compile</scope>
-    </dependency>
-    <dependency>
-      <groupId>javax.inject</groupId>
-      <artifactId>javax.inject</artifactId>
-      <version>1</version>
-      <scope>compile</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.karaf.features</groupId>
-      <artifactId>org.apache.karaf.features.core</artifactId>
-      <version>${karaf.version}</version>
-      <scope>compile</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.osgi</groupId>
-      <artifactId>org.osgi.core</artifactId>
-      <scope>compile</scope>
-    </dependency>
-    <dependency>
-      <groupId>junit</groupId>
-      <artifactId>junit</artifactId>
-      <scope>compile</scope>
-    </dependency>
     <dependency>
       <groupId>org.codehaus.sonar-plugins.java</groupId>
       <artifactId>sonar-jacoco-listeners</artifactId>
       <scope>test</scope>
     </dependency>
-    <!-- AbstractConfigTestBase::getKarafDistro() needs this to find its version -->
-    <dependency>
-      <groupId>org.opendaylight.ovsdb</groupId>
-      <artifactId>karaf</artifactId>
-      <version>${project.version}</version>
-      <scope>test</scope>
-    </dependency>
   </dependencies>
   <build>
     <plugins>
@@ -155,40 +113,6 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-failsafe-plugin</artifactId>
       </plugin>
-      <!-- Needed if you use versionAsInProject() -->
-      <plugin>
-        <groupId>org.apache.servicemix.tooling</groupId>
-        <artifactId>depends-maven-plugin</artifactId>
-        <version>1.2</version>
-        <executions>
-          <execution>
-            <id>generate-depends-file</id>
-            <goals>
-              <goal>generate-depends-file</goal>
-            </goals>
-          </execution>
-        </executions>
-      </plugin>
     </plugins>
   </build>
-  <profiles>
-    <profile>
-      <id>default</id>
-      <activation>
-        <activeByDefault>true</activeByDefault>
-      </activation>
-      <properties>
-        <skipITs>true</skipITs>
-      </properties>
-    </profile>
-    <profile>
-      <id>integrationtest</id>
-      <activation>
-        <activeByDefault>false</activeByDefault>
-      </activation>
-      <properties>
-        <skipITs>false</skipITs>
-      </properties>
-    </profile>
-  </profiles>
 </project>
index c49173d9d6a6dc13a85089086641c1cb11ebae89..d335bfa6765694408e31655a38ffb204b32bf20e 100644 (file)
@@ -8,23 +8,24 @@
 package org.opendaylight.ovsdb.openstack.netvirt.it;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 import static org.ops4j.pax.exam.CoreOptions.composite;
 import static org.ops4j.pax.exam.CoreOptions.maven;
 import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
+import static org.ops4j.pax.exam.CoreOptions.propagateSystemProperties;
 import static org.ops4j.pax.exam.CoreOptions.vmOption;
-import static org.ops4j.pax.exam.CoreOptions.when;
 import static org.ops4j.pax.exam.CoreOptions.wrappedBundle;
 import static org.ops4j.pax.exam.MavenUtils.asInProject;
+import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.configureConsole;
 import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.editConfigurationFilePut;
-import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.karafDistributionConfiguration;
 import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.keepRuntimeFolder;
 
 import com.google.common.collect.ImmutableBiMap;
 import com.google.common.collect.Lists;
 
-import java.io.File;
 import java.net.InetAddress;
 import java.net.NetworkInterface;
 import java.net.UnknownHostException;
@@ -34,7 +35,6 @@ import java.util.List;
 import java.util.Map;
 import java.util.Properties;
 import java.util.concurrent.atomic.AtomicBoolean;
-import javax.inject.Inject;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Ignore;
@@ -43,15 +43,19 @@ import org.junit.runner.RunWith;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.mdsal.it.base.AbstractMdsalTestBase;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
+import org.opendaylight.ovsdb.openstack.netvirt.api.Constants;
 import org.opendaylight.ovsdb.openstack.netvirt.api.SecurityServicesManager;
 import org.opendaylight.ovsdb.openstack.netvirt.api.Southbound;
 import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.AbstractServiceInstance;
 import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.PipelineOrchestrator;
 import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.Service;
+import org.opendaylight.ovsdb.utils.config.ConfigProperties;
 import org.opendaylight.ovsdb.utils.mdsal.openflow.FlowUtils;
 import org.opendaylight.ovsdb.utils.servicehelper.ServiceHelper;
 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.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.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.params.xml.ns.yang.ovsdb.rev150105.*;
@@ -63,9 +67,14 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.re
 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.ConnectionInfoBuilder;
 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;
@@ -74,13 +83,10 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.ops4j.pax.exam.Configuration;
 import org.ops4j.pax.exam.Option;
 import org.ops4j.pax.exam.junit.PaxExam;
-import org.ops4j.pax.exam.karaf.options.KarafDistributionOption;
 import org.ops4j.pax.exam.karaf.options.LogLevelOption;
 import org.ops4j.pax.exam.options.MavenUrlReference;
 import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
 import org.ops4j.pax.exam.spi.reactors.PerClass;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -98,63 +104,11 @@ public class NetvirtIT extends AbstractMdsalTestBase {
     private static String addressStr;
     private static String portStr;
     private static String connectionType;
+    private static String controllerStr;
     private static AtomicBoolean setup = new AtomicBoolean(false);
     private static MdsalUtils mdsalUtils = null;
     private static Southbound southbound = null;
-    private static final String NETVIRT = "org.opendaylight.ovsdb.openstack.net-virt";
-    private static final String NETVIRTPROVIDERS = "org.opendaylight.ovsdb.openstack.net-virt-providers";
-
-    // TODO Constants copied frmo AbstractConfigTestBase, need to be removed (see TODO below)
-    private static final String PAX_EXAM_UNPACK_DIRECTORY = "target/exam";
-    private static final String KARAF_DEBUG_PORT = "5005";
-    private static final String KARAF_DEBUG_PROP = "karaf.debug";
-    private static final String KEEP_UNPACK_DIRECTORY_PROP = "karaf.keep.unpack";
-
-    @Inject
-    private BundleContext bundleContext;
-
-    @Configuration
-    public Option[] config() {
-        // TODO Figure out how to use the parent Karaf setup, then just use super.config()
-        Option[] options = new Option[] {
-                when(Boolean.getBoolean(KARAF_DEBUG_PROP))
-                        .useOptions(KarafDistributionOption.debugConfiguration(KARAF_DEBUG_PORT, true)),
-                karafDistributionConfiguration().frameworkUrl(getKarafDistro())
-                        .unpackDirectory(new File(PAX_EXAM_UNPACK_DIRECTORY))
-                        .useDeployFolder(false),
-                when(Boolean.getBoolean(KEEP_UNPACK_DIRECTORY_PROP)).useOptions(keepRuntimeFolder()),
-                // Works only if we don't specify the feature repo and name
-                getLoggingOption()};
-        Option[] propertyOptions = getPropertiesOptions();
-        Option[] otherOptions = getOtherOptions();
-        Option[] combinedOptions = new Option[options.length + propertyOptions.length + otherOptions.length];
-        System.arraycopy(options, 0, combinedOptions, 0, options.length);
-        System.arraycopy(propertyOptions, 0, combinedOptions, options.length, propertyOptions.length);
-        System.arraycopy(otherOptions, 0, combinedOptions, options.length + propertyOptions.length,
-                otherOptions.length);
-        return combinedOptions;
-    }
-
-    private Option[] getOtherOptions() {
-        return new Option[] {
-                wrappedBundle(
-                        mavenBundle("org.opendaylight.ovsdb", "utils.mdsal-openflow")
-                                .version(asInProject())
-                                .type("jar")),
-                vmOption("-javaagent:../jars/org.jacoco.agent.jar=destfile=../../jacoco-it.exec"),
-                keepRuntimeFolder()
-        };
-    }
-
-    @Override
-    public String getKarafDistro() {
-        return maven()
-                .groupId("org.opendaylight.ovsdb")
-                .artifactId("karaf")
-                .versionAsInProject()
-                .type("zip")
-                .getURL();
-    }
+    private static final String NETVIRT_TOPOLOGY_ID = "netvirt:1";
 
     @Override
     public String getModuleName() {
@@ -181,10 +135,42 @@ public class NetvirtIT extends AbstractMdsalTestBase {
         return "odl-ovsdb-openstack";
     }
 
-    protected String usage() {
-        return "Integration Test needs a valid connection configuration as follows :\n"
-                + "active connection : mvn -Dovsdbserver.ipaddress=x.x.x.x -Dovsdbserver.port=yyyy verify\n"
-                + "passive connection : mvn -Dovsdbserver.connection=passive verify\n";
+    @Configuration
+    @Override
+    public Option[] config() {
+        Option[] parentOptions = super.config();
+        Option[] propertiesOptions = getPropertiesOptions();
+        Option[] otherOptions = getOtherOptions();
+        Option[] options = new Option[parentOptions.length + propertiesOptions.length + otherOptions.length];
+        System.arraycopy(parentOptions, 0, options, 0, parentOptions.length);
+        System.arraycopy(propertiesOptions, 0, options, parentOptions.length, propertiesOptions.length);
+        System.arraycopy(otherOptions, 0, options, parentOptions.length + propertiesOptions.length,
+                otherOptions.length);
+        return options;
+    }
+
+    private Option[] getOtherOptions() {
+        return new Option[] {
+                wrappedBundle(
+                        mavenBundle("org.opendaylight.ovsdb", "utils.mdsal-openflow")
+                                .version(asInProject())
+                                .type("jar")),
+                wrappedBundle(
+                        mavenBundle("org.opendaylight.ovsdb", "utils.config")
+                                .version(asInProject())
+                                .type("jar")),
+                configureConsole().startLocalConsole(),
+                vmOption("-javaagent:../jars/org.jacoco.agent.jar=destfile=../../jacoco-it.exec"),
+                keepRuntimeFolder()
+        };
+    }
+
+    public Option[] getPropertiesOptions() {
+        return new Option[] {
+                propagateSystemProperties(NetvirtITConstants.SERVER_IPADDRESS,
+                        NetvirtITConstants.SERVER_PORT, NetvirtITConstants.CONNECTION_TYPE,
+                        NetvirtITConstants.CONTROLLER_IPADDRESS),
+        };
     }
 
     @Override
@@ -193,32 +179,34 @@ public class NetvirtIT extends AbstractMdsalTestBase {
                 editConfigurationFilePut(NetvirtITConstants.ORG_OPS4J_PAX_LOGGING_CFG,
                         "log4j.logger.org.opendaylight.ovsdb",
                         LogLevelOption.LogLevel.TRACE.name()),
-                editConfigurationFilePut(NetvirtITConstants.ORG_OPS4J_PAX_LOGGING_CFG,
-                        "log4j.logger.org.opendaylight.ovsdb.lib",
+                editConfigurationFilePut(ORG_OPS4J_PAX_LOGGING_CFG,
+                        logConfiguration(NetvirtIT.class),
                         LogLevelOption.LogLevel.INFO.name()),
+                //editConfigurationFilePut(NetvirtITConstants.ORG_OPS4J_PAX_LOGGING_CFG,
+                //        "log4j.logger.org.opendaylight.ovsdb.lib",
+                //        LogLevelOption.LogLevel.INFO.name()),
                 super.getLoggingOption());
     }
 
-    private Option[] getPropertiesOptions() {
-        Properties props = new Properties(System.getProperties());
-        String addressStr = props.getProperty(NetvirtITConstants.SERVER_IPADDRESS,
-                NetvirtITConstants.DEFAULT_SERVER_IPADDRESS);
-        String portStr = props.getProperty(NetvirtITConstants.SERVER_PORT,
-                NetvirtITConstants.DEFAULT_SERVER_PORT);
-        String connectionType = props.getProperty(NetvirtITConstants.CONNECTION_TYPE,
-                NetvirtITConstants.CONNECTION_TYPE_ACTIVE);
-
-        LOG.info("getPropertiesOptions: Using the following properties: mode= {}, ip:port= {}:{}",
-                connectionType, addressStr, portStr);
+    protected String usage() {
+        return "Integration Test needs a valid connection configuration as follows :\n"
+                + "active connection : mvn -Dovsdbserver.ipaddress=x.x.x.x -Dovsdbserver.port=yyyy verify\n"
+                + "passive connection : mvn -Dovsdbserver.connection=passive verify\n";
+    }
 
-        return new Option[] {
-                editConfigurationFilePut(NetvirtITConstants.CUSTOM_PROPERTIES,
-                        NetvirtITConstants.SERVER_IPADDRESS, addressStr),
-                editConfigurationFilePut(NetvirtITConstants.CUSTOM_PROPERTIES,
-                        NetvirtITConstants.SERVER_PORT, portStr),
-                editConfigurationFilePut(NetvirtITConstants.CUSTOM_PROPERTIES,
-                        NetvirtITConstants.CONNECTION_TYPE, connectionType),
-        };
+    private void getProperties() {
+        Properties props = System.getProperties();
+        addressStr = props.getProperty(NetvirtITConstants.SERVER_IPADDRESS);
+        portStr = props.getProperty(NetvirtITConstants.SERVER_PORT, NetvirtITConstants.DEFAULT_SERVER_PORT);
+        connectionType = props.getProperty(NetvirtITConstants.CONNECTION_TYPE, "active");
+        controllerStr = props.getProperty(NetvirtITConstants.CONTROLLER_IPADDRESS);
+        LOG.info("setUp: Using the following properties: mode= {}, ip:port= {}:{}, controller ip: {}",
+                connectionType, addressStr, portStr, controllerStr);
+        if (connectionType.equalsIgnoreCase(NetvirtITConstants.CONNECTION_TYPE_ACTIVE)) {
+            if (addressStr == null) {
+                fail(usage());
+            }
+        }
     }
 
     @Before
@@ -235,40 +223,75 @@ public class NetvirtIT extends AbstractMdsalTestBase {
             e.printStackTrace();
         }
 
-        addressStr = bundleContext.getProperty(NetvirtITConstants.SERVER_IPADDRESS);
-        portStr = bundleContext.getProperty(NetvirtITConstants.SERVER_PORT);
-        connectionType = bundleContext.getProperty(NetvirtITConstants.CONNECTION_TYPE);
+        getProperties();
 
-        LOG.info("setUp: Using the following properties: mode= {}, ip:port= {}:{}",
-                connectionType, addressStr, portStr);
         if (connectionType.equalsIgnoreCase(NetvirtITConstants.CONNECTION_TYPE_ACTIVE)) {
             if (addressStr == null) {
                 fail(usage());
             }
         }
 
-        isBundleReady(bundleContext, NETVIRT);
-        isBundleReady(bundleContext, NETVIRTPROVIDERS);
-
-        //dataBroker = getSession().getSALService(DataBroker.class);
-        //Thread.sleep(3000);
-        //dataBroker = OvsdbInventoryServiceImpl.getDataBroker();
-        for (int i=0; i<20; i++) {
-            southbound = (Southbound) ServiceHelper.getGlobalInstance(Southbound.class, this);
-            if (southbound != null) {
-                dataBroker = southbound.getDatabroker();
-                if (dataBroker != null) {
-                    break;
+        dataBroker = getDatabroker(getProviderContext());
+        mdsalUtils = new MdsalUtils(dataBroker);
+        assertNotNull("mdsalUtils should not be null", mdsalUtils);
+        assertTrue("Did not find " + NETVIRT_TOPOLOGY_ID, getNetvirtTopology());
+        southbound = (Southbound) ServiceHelper.getGlobalInstance(Southbound.class, this);
+        assertNotNull("southbound should not be null", southbound);
+        setup.set(true);
+    }
+
+    private BindingAwareBroker.ProviderContext getProviderContext() {
+        BindingAwareBroker.ProviderContext providerContext = null;
+        for (int i=0; i < 60; i++) {
+            providerContext = getSession();
+            if (providerContext != null) {
+                break;
+            } else {
+                try {
+                    Thread.sleep(1000);
+                } catch (InterruptedException e) {
+                    e.printStackTrace();
                 }
             }
-            LOG.warn("NetvirtIT: dataBroker is null");
-            Thread.sleep(5000);
         }
-        Assert.assertNotNull("dataBroker should not be null", dataBroker);
-        Thread.sleep(5000);
-
-        mdsalUtils = new MdsalUtils(dataBroker);
-        setup.set(true);
+        assertNotNull("providercontext should not be null", providerContext);
+        /* One more second to let the provider finish initialization */
+        try {
+            Thread.sleep(1000);
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+        return providerContext;
+    }
+
+    private DataBroker getDatabroker(BindingAwareBroker.ProviderContext providerContext) {
+        DataBroker dataBroker = providerContext.getSALService(DataBroker.class);
+        assertNotNull("dataBroker should not be null", dataBroker);
+        return dataBroker;
+    }
+
+    private Boolean getNetvirtTopology() {
+        LOG.info("getNetvirtTopology: looking for {}...", NETVIRT_TOPOLOGY_ID);
+        Boolean found = false;
+        final TopologyId topologyId = new TopologyId(new Uri(NETVIRT_TOPOLOGY_ID));
+        InstanceIdentifier<Topology> path =
+                InstanceIdentifier.create(NetworkTopology.class).child(Topology.class, new TopologyKey(topologyId));
+        for (int i = 0; i < 60; i++) {
+            Topology topology = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, path);
+            if (topology != null) {
+                LOG.info("getNetvirtTopology: found {}...", NETVIRT_TOPOLOGY_ID);
+                found = true;
+                break;
+            } else {
+                LOG.info("getNetvirtTopology: still looking ({})...", i);
+                try {
+                    Thread.sleep(1000);
+                } catch (InterruptedException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+        return found;
     }
 
     /**
@@ -277,6 +300,7 @@ public class NetvirtIT extends AbstractMdsalTestBase {
      *
      * @throws InterruptedException
      */
+    @Ignore
     @Test
     public void testPassiveNode() throws InterruptedException {
         if (connectionType.equalsIgnoreCase(NetvirtITConstants.CONNECTION_TYPE_PASSIVE)) {
@@ -347,51 +371,136 @@ public class NetvirtIT extends AbstractMdsalTestBase {
         return true;
     }
 
+    private String getControllerIPAddress() {
+        String addressString = ConfigProperties.getProperty(this.getClass(), "ovsdb.controller.address");
+        if (addressString != null) {
+            try {
+                if (InetAddress.getByName(addressString) != null) {
+                    return addressString;
+                }
+            } catch (UnknownHostException e) {
+                LOG.error("Host {} is invalid", addressString);
+            }
+        }
+
+        addressString = ConfigProperties.getProperty(this.getClass(), "of.address");
+        if (addressString != null) {
+            try {
+                if (InetAddress.getByName(addressString) != null) {
+                    return addressString;
+                }
+            } catch (UnknownHostException e) {
+                LOG.error("Host {} is invalid", addressString);
+            }
+        }
+
+        return null;
+    }
+
+    private short getControllerOFPort() {
+        short openFlowPort = Constants.OPENFLOW_PORT;
+        String portString = ConfigProperties.getProperty(this.getClass(), "of.listenPort");
+        if (portString != null) {
+            try {
+                openFlowPort = Short.parseShort(portString);
+            } catch (NumberFormatException e) {
+                LOG.warn("Invalid port:{}, use default({})", portString,
+                        openFlowPort);
+            }
+        }
+        return openFlowPort;
+    }
+
+    private List<String> getControllersFromOvsdbNode(Node node) {
+        List<String> controllersStr = new ArrayList<>();
+
+        String controllerIpStr = getControllerIPAddress();
+        if (controllerIpStr != null) {
+            // If codepath makes it here, the ip address to be used was explicitly provided.
+            // Being so, also fetch openflowPort provided via ConfigProperties.
+            controllersStr.add(Constants.OPENFLOW_CONNECTION_PROTOCOL
+                    + ":" + controllerIpStr + ":" + getControllerOFPort());
+        } else {
+            // Check if ovsdb node has manager entries
+            OvsdbNodeAugmentation ovsdbNodeAugmentation = southbound.extractOvsdbNode(node);
+            if (ovsdbNodeAugmentation != null) {
+                List<ManagerEntry> managerEntries = ovsdbNodeAugmentation.getManagerEntry();
+                if (managerEntries != null && !managerEntries.isEmpty()) {
+                    for (ManagerEntry managerEntry : managerEntries) {
+                        if (managerEntry == null || managerEntry.getTarget() == null) {
+                            continue;
+                        }
+                        String[] tokens = managerEntry.getTarget().getValue().split(":");
+                        if (tokens.length == 3 && tokens[0].equalsIgnoreCase("tcp")) {
+                            controllersStr.add(Constants.OPENFLOW_CONNECTION_PROTOCOL
+                                    + ":" + tokens[1] + ":" + getControllerOFPort());
+                        } else if (tokens[0].equalsIgnoreCase("ptcp")) {
+                            ConnectionInfo connectionInfo = ovsdbNodeAugmentation.getConnectionInfo();
+                            if (connectionInfo != null && connectionInfo.getLocalIp() != null) {
+                                controllerIpStr = new String(connectionInfo.getLocalIp().getValue());
+                                controllersStr.add(Constants.OPENFLOW_CONNECTION_PROTOCOL
+                                        + ":" + controllerIpStr + ":" + Constants.OPENFLOW_PORT);
+                            } else {
+                                LOG.warn("Ovsdb Node does not contain connection info: {}", node);
+                            }
+                        } else {
+                            LOG.trace("Skipping manager entry {} for node {}",
+                                    managerEntry.getTarget(), node.getNodeId().getValue());
+                        }
+                    }
+                } else {
+                    LOG.warn("Ovsdb Node does not contain manager entries : {}", node);
+                }
+            }
+        }
+
+        if (controllersStr.isEmpty()) {
+            // Neither user provided ip nor ovsdb node has manager entries. Lets use local machine ip address.
+            LOG.debug("Use local machine ip address as a OpenFlow Controller ip address");
+            controllerIpStr = getLocalControllerHostIpAddress();
+            if (controllerIpStr != null) {
+                controllersStr.add(Constants.OPENFLOW_CONNECTION_PROTOCOL
+                        + ":" + controllerIpStr + ":" + Constants.OPENFLOW_PORT);
+            }
+        }
+
+        if (controllersStr.isEmpty()) {
+            LOG.warn("Failed to determine OpenFlow controller ip address");
+        } else if (LOG.isDebugEnabled()) {
+            controllerIpStr = "";
+            for (String currControllerIpStr : controllersStr) {
+                controllerIpStr += " " + currControllerIpStr;
+            }
+            LOG.debug("Found {} OpenFlow Controller(s) :{}", controllersStr.size(), controllerIpStr);
+        }
+
+        return controllersStr;
+    }
+
     private String getLocalControllerHostIpAddress() {
         String ipaddress = null;
         try{
-            for (Enumeration<NetworkInterface> ifaces = NetworkInterface.getNetworkInterfaces();
-                 ifaces.hasMoreElements();) {
+            for (Enumeration<NetworkInterface> ifaces = NetworkInterface.getNetworkInterfaces();ifaces.hasMoreElements();){
                 NetworkInterface iface = ifaces.nextElement();
 
                 for (Enumeration<InetAddress> inetAddrs = iface.getInetAddresses(); inetAddrs.hasMoreElements();) {
                     InetAddress inetAddr = inetAddrs.nextElement();
-                    if (!inetAddr.isLoopbackAddress()) {
-                        if (inetAddr.isSiteLocalAddress()) {
-                            ipaddress = inetAddr.getHostAddress();
-                            break;
-                        }
+                    if (!inetAddr.isLoopbackAddress() && inetAddr.isSiteLocalAddress()) {
+                        ipaddress = inetAddr.getHostAddress();
+                        break;
                     }
                 }
             }
         }catch (Exception e){
-            LOG.warn("Exception while fetching local host ip address ",e);
+            LOG.warn("Exception while fetching local host ip address ", e);
         }
         return ipaddress;
     }
 
     private String getControllerTarget(Node ovsdbNode) {
-        String target = null;
-        String ipAddr = null;
-        OvsdbNodeAugmentation ovsdbNodeAugmentation = ovsdbNode.getAugmentation(OvsdbNodeAugmentation.class);
-        ConnectionInfo connectionInfo = ovsdbNodeAugmentation.getConnectionInfo();
-        LOG.info("connectionInfo: {}", connectionInfo);
-        if (connectionInfo != null && connectionInfo.getLocalIp() != null) {
-            ipAddr = new String(connectionInfo.getLocalIp().getValue());
-        }
-        if (ipAddr == null) {
-            ipAddr = getLocalControllerHostIpAddress();
-        }
-
-        if (ipAddr != null) {
-            target = NetvirtITConstants.OPENFLOW_CONNECTION_PROTOCOL + ":"
-                    + ipAddr + ":" + NetvirtITConstants.DEFAULT_OPENFLOW_PORT;
-        }
-
-        return target;
+        return getControllersFromOvsdbNode(ovsdbNode).get(0);
     }
 
-    //@Ignore//
     @Test
     public void testAddDeleteOvsdbNode() throws InterruptedException {
         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
@@ -638,31 +747,6 @@ public class NetvirtIT extends AbstractMdsalTestBase {
             bridge.getBridgeName());
     }
 
-    /**
-     * isBundleReady is used to check if the requested bundle is Active
-     */
-    public void isBundleReady(BundleContext bundleContext, String bundleName) throws InterruptedException {
-        boolean ready = false;
-
-        while (!ready) {
-            int state = Bundle.UNINSTALLED;
-            Bundle[] bundles = bundleContext.getBundles();
-            for (Bundle element : bundles) {
-                if (element.getSymbolicName().equals(bundleName)) {
-                    state = element.getState();
-                    LOG.info(">>>>> bundle is ready {}", bundleName);
-                    break;
-                }
-            }
-            if (state != Bundle.ACTIVE) {
-                LOG.info(">>>>> bundle not ready {}", bundleName);
-                Thread.sleep(5000);
-            } else {
-                ready = true;
-            }
-        }
-    }
-
     private void netVirtAddPort(ConnectionInfo connectionInfo) throws InterruptedException {
         OvsdbBridgeAugmentation bridge = getBridge(connectionInfo, NetvirtITConstants.INTEGRATION_BRIDGE_NAME);
         Assert.assertNotNull(bridge);
@@ -689,21 +773,22 @@ public class NetvirtIT extends AbstractMdsalTestBase {
      * </pre>
      * @throws InterruptedException
      */
-    // TODO add verification of flows
-    //@Ignore //
+    @Ignore
     @Test
     public void testNetVirt() throws InterruptedException {
         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
         Node ovsdbNode = connectOvsdbNode(connectionInfo);
 
-        Thread.sleep(10000);
+        Thread.sleep(30000);
         // 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);
+        assertNotEquals("datapathId was not found", datapathId, 0);
         org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder nodeBuilder =
                 FlowUtils.createNodeBuilder(datapathId);
 
@@ -735,6 +820,7 @@ public class NetvirtIT extends AbstractMdsalTestBase {
         Thread.sleep(60000);
     }
 
+    @Ignore
     @Test
     public void testReadOvsdbTopologyNodes() throws InterruptedException {
         Thread.sleep(10000);
index e1dc6ad6928e87b11820f860abda2ddd9eb07182..4fea5264b6a2c99a7619c2611aa9d335468fe65c 100644 (file)
@@ -19,6 +19,7 @@ public final class NetvirtITConstants {
     public static final String CUSTOM_PROPERTIES = "etc/custom.properties";
     public static final String SERVER_IPADDRESS = "ovsdbserver.ipaddress";
     public static final String SERVER_PORT = "ovsdbserver.port";
+    public static final String CONTROLLER_IPADDRESS = "ovsdb.controller.address";
     public static final String SERVER_EXTRAS = "ovsdbserver.extras";
     public static final String CONNECTION_TYPE = "ovsdbserver.connection";
     public static final String CONNECTION_TYPE_ACTIVE = "active";
index 03b19a8bbd10e6b9cadc54fecb6fe16774dbc0e1..7c7f43493c0dfd691cb1b74459d6b0b2fa34ddc2 100644 (file)
@@ -154,12 +154,10 @@ public class SouthboundMapper {
     public static String createDatapathType(OvsdbBridgeAugmentation mdsalbridge) {
         String datapathtype = SouthboundConstants.DATAPATH_TYPE_MAP.get(DatapathTypeSystem.class);
 
-        if (mdsalbridge.getDatapathType() != null) {
-            if (SouthboundConstants.DATAPATH_TYPE_MAP.get(mdsalbridge.getDatapathType()) != null) {
-                datapathtype = SouthboundConstants.DATAPATH_TYPE_MAP.get(mdsalbridge.getDatapathType());
-            } else {
-                throw new IllegalArgumentException("Unknown datapath type "
-                        + SouthboundConstants.DATAPATH_TYPE_MAP.get(mdsalbridge.getDatapathType()));
+        if (mdsalbridge.getDatapathType() != null && !mdsalbridge.getDatapathType().equals(DatapathTypeBase.class)) {
+            datapathtype = SouthboundConstants.DATAPATH_TYPE_MAP.get(mdsalbridge.getDatapathType());
+            if (datapathtype == null) {
+                throw new IllegalArgumentException("Unknown datapath type " + mdsalbridge.getDatapathType().getName());
             }
         }
         return datapathtype;
index 5de7118017f750fe19df1da89a6eef515998ca86..350f9cf478e18d8c3543449ca71d3adf8cffbbc4 100644 (file)
@@ -83,6 +83,13 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA
              * http://docs.openstack.org/api/openstack-network/2.0/content/security_groups.html
              *
              */
+
+            if (portSecurityRule == null ||
+                    portSecurityRule.getSecurityRuleEthertype() == null ||
+                    portSecurityRule.getSecurityRuleDirection() == null) {
+                continue;
+            }
+
             if ("IPv4".equals(portSecurityRule.getSecurityRuleEthertype())
                     && portSecurityRule.getSecurityRuleDirection().equals("egress")) {
                 LOG.debug("programPortSecurityGroup: Acl Rule matching IPv4 and ingress is: {} ", portSecurityRule);
@@ -149,13 +156,51 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA
                                 Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
                   break;
               default:
-                  LOG.error("programPortSecurityRule: Protocol not supported", portSecurityRule);
+                  LOG.info("programPortSecurityAcl: Protocol is not TCP/UDP/ICMP but other " +
+                          "protocol = ", portSecurityRule.getSecurityRuleProtocol());
+                  egressOtherProtocolAclHandler(dpid, segmentationId, attachedMac,
+                                      portSecurityRule, ipaddress, write,
+                                      Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
                   break;
             }
         }
 
     }
 
+    private void egressOtherProtocolAclHandler(Long dpidLong, String segmentationId, String srcMac,
+         NeutronSecurityRule portSecurityRule, String dstAddress,
+         boolean write, Integer protoPortMatchPriority) {
+
+         MatchBuilder matchBuilder = new MatchBuilder();
+         String flowId = "Egress_Other_" + segmentationId + "_" + srcMac + "_";
+         matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,srcMac,null);
+
+         short proto = 0;
+         try {
+             Integer protocol = new Integer(portSecurityRule.getSecurityRuleProtocol());
+             proto = protocol.shortValue();
+             flowId = flowId + proto;
+         } catch (NumberFormatException e) {
+             LOG.error("Protocol vlaue conversion failure", e);
+         }
+         matchBuilder = MatchUtils.createIpProtocolMatch(matchBuilder, proto);
+
+         if (null != dstAddress) {
+             flowId = flowId + dstAddress;
+             matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,null,
+                                                         MatchUtils.iPv4PrefixFromIPv4Address(dstAddress));
+
+         } else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) {
+             flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix();
+             matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder, null,new Ipv4Prefix(portSecurityRule
+                                                                        .getSecurityRuleRemoteIpPrefix()));
+         }
+         flowId = flowId + "_Permit";
+         String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
+         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
+         syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false);
+ }
+
     @Override
     public void programFixedSecurityGroup(Long dpid, String segmentationId, String attachedMac,
                                         long localPort, List<Neutron_IPs> srcAddressList,
@@ -224,7 +269,7 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA
             if (portSecurityRule.getSecurityRulePortMin().equals(PORT_RANGE_MIN)
                     && portSecurityRule.getSecurityRulePortMax().equals(PORT_RANGE_MAX)) {
                 flowId = flowId + portSecurityRule.getSecurityRulePortMin() + "_"
-                    + portSecurityRule.getSecurityRulePortMax() + "_";
+                            + portSecurityRule.getSecurityRulePortMax() + "_";
                 matchBuilder = MatchUtils.addLayer4Match(matchBuilder, MatchUtils.TCP_SHORT, 0, 0);
             }
             /*TODO TCP PortRange Match*/
@@ -234,13 +279,12 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA
         if (null != dstAddress) {
             flowId = flowId + dstAddress;
             matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,null,
-                                                        MatchUtils.iPv4PrefixFromIPv4Address(dstAddress));
+                                      MatchUtils.iPv4PrefixFromIPv4Address(dstAddress));
 
         } else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) {
             flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix();
             matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,null,
-                                                        new Ipv4Prefix(portSecurityRule
-                                                                       .getSecurityRuleRemoteIpPrefix()));
+                                      new Ipv4Prefix(portSecurityRule.getSecurityRuleRemoteIpPrefix()));
         }
         flowId = flowId + "_Permit";
         String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
@@ -264,14 +308,23 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA
     private void egressAclIcmp(Long dpidLong, String segmentationId, String srcMac,
                                NeutronSecurityRule portSecurityRule, String dstAddress,
                                boolean write, Integer protoPortMatchPriority) {
+
         MatchBuilder matchBuilder = new MatchBuilder();
-        String flowId = "Egress_ICMP_" + segmentationId + "_" + srcMac + "_"
-                    + portSecurityRule.getSecurityRulePortMin().shortValue() + "_"
-                    + portSecurityRule.getSecurityRulePortMax().shortValue() + "_";
+        String flowId = "Egress_ICMP_" + segmentationId + "_" + srcMac + "_";
         matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,srcMac,null);
-        matchBuilder = MatchUtils.createICMPv4Match(matchBuilder,
-                                                    portSecurityRule.getSecurityRulePortMin().shortValue(),
-                                                    portSecurityRule.getSecurityRulePortMax().shortValue());
+        /*Custom ICMP Match */
+        if (portSecurityRule.getSecurityRulePortMin() != null &&
+                             portSecurityRule.getSecurityRulePortMax() != null) {
+            flowId = flowId + portSecurityRule.getSecurityRulePortMin().shortValue() + "_"
+                    + portSecurityRule.getSecurityRulePortMax().shortValue() + "_";
+            matchBuilder = MatchUtils.createICMPv4Match(matchBuilder,
+                    portSecurityRule.getSecurityRulePortMin().shortValue(),
+                    portSecurityRule.getSecurityRulePortMax().shortValue());
+        } else {
+            /* All ICMP Match */ // We are getting from neutron NULL for both min and max
+            flowId = flowId + "all" + "_" ;
+            matchBuilder = MatchUtils.createICMPv4Match(matchBuilder, MatchUtils.ALL_ICMP, MatchUtils.ALL_ICMP);
+        }
         if (null != dstAddress) {
             flowId = flowId + dstAddress;
             matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,null,
index 581eb9d69ba91b3e987f145bfe6a0040689cff79..d100f4e6daf96205aeae722195e0f07623a382e6 100644 (file)
@@ -85,6 +85,12 @@ public class IngressAclService extends AbstractServiceInstance implements Ingres
              *
              */
 
+            if (portSecurityRule == null ||
+                    portSecurityRule.getSecurityRuleEthertype() == null ||
+                    portSecurityRule.getSecurityRuleDirection() == null) {
+                continue;
+            }
+
             if ("IPv4".equals(portSecurityRule.getSecurityRuleEthertype())
                     && "ingress".equals(portSecurityRule.getSecurityRuleDirection())) {
                 LOG.debug("programPortSecurityGroup: Rule matching IPv4 and ingress is: {} ", portSecurityRule);
@@ -114,9 +120,6 @@ public class IngressAclService extends AbstractServiceInstance implements Ingres
                     securityGroupCacheManger.portRemoved(securityGroup.getSecurityGroupUUID(), portUuid);
                 }
             }
-
-
-
         }
     }
 
@@ -149,12 +152,46 @@ public class IngressAclService extends AbstractServiceInstance implements Ingres
                                  write, Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
                   break;
               default:
-                  LOG.error("programPortSecurityRule: Protocol not supported", portSecurityRule);
+                  LOG.info("programPortSecurityAcl: Protocol is not TCP/UDP/ICMP but other " +
+                          "protocol = ", portSecurityRule.getSecurityRuleProtocol());
+                  ingressOtherProtocolAclHandler(dpid, segmentationId, attachedMac, portSecurityRule,
+                              null, write, Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
                   break;
             }
         }
     }
 
+    private void ingressOtherProtocolAclHandler(Long dpidLong, String segmentationId, String dstMac,
+          NeutronSecurityRule portSecurityRule, String srcAddress,
+          boolean write, Integer protoPortMatchPriority) {
+
+          MatchBuilder matchBuilder = new MatchBuilder();
+          String flowId = "Ingress_Other_" + segmentationId + "_" + dstMac + "_";
+          matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,null,dstMac);
+          short proto = 0;
+          try {
+              Integer protocol = new Integer(portSecurityRule.getSecurityRuleProtocol());
+              proto = protocol.shortValue();
+              flowId = flowId + proto;
+          } catch (NumberFormatException e) {
+              LOG.error("Protocol vlaue conversion failure", e);
+          }
+          matchBuilder = MatchUtils.createIpProtocolMatch(matchBuilder, proto);
+          if (null != srcAddress) {
+              flowId = flowId + srcAddress;
+              matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,
+                                        MatchUtils.iPv4PrefixFromIPv4Address(srcAddress), null);
+          } else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) {
+              flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix();
+              matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,
+                                        new Ipv4Prefix(portSecurityRule.getSecurityRuleRemoteIpPrefix()),null);
+          }
+          String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
+          NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
+          flowId = flowId + "_Permit";
+          syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false);
+    }
+
     @Override
     public void programFixedSecurityGroup(Long dpid, String segmentationId, String dhcpMacAddress,
                                         long localPort, boolean isLastPortinSubnet,
@@ -311,14 +348,22 @@ public class IngressAclService extends AbstractServiceInstance implements Ingres
                                 boolean write, Integer protoPortMatchPriority) {
 
         MatchBuilder matchBuilder = new MatchBuilder();
-        FlowBuilder flowBuilder = new FlowBuilder();
-        String flowId = "Ingress_ICMP_" + segmentationId + "_" + dstMac + "_"
-                + portSecurityRule.getSecurityRulePortMin().shortValue() + "_"
-                + portSecurityRule.getSecurityRulePortMax().shortValue() + "_";
+        String flowId = "Ingress_ICMP_" + segmentationId + "_" + dstMac + "_";
         matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,null,dstMac);
-        matchBuilder = MatchUtils.createICMPv4Match(matchBuilder,
-                                                    portSecurityRule.getSecurityRulePortMin().shortValue(),
-                                                    portSecurityRule.getSecurityRulePortMax().shortValue());
+
+        /* Custom ICMP Match */
+        if (portSecurityRule.getSecurityRulePortMin() != null &&
+                portSecurityRule.getSecurityRulePortMax() != null) {
+            flowId = flowId + portSecurityRule.getSecurityRulePortMin().shortValue() + "_"
+                    + portSecurityRule.getSecurityRulePortMax().shortValue() + "_";
+            matchBuilder = MatchUtils.createICMPv4Match(matchBuilder,
+                    portSecurityRule.getSecurityRulePortMin().shortValue(),
+                    portSecurityRule.getSecurityRulePortMax().shortValue());
+        } else {
+            /* All ICMP Match */
+            flowId = flowId + "all" + "_";
+            matchBuilder = MatchUtils.createICMPv4Match(matchBuilder,MatchUtils.ALL_ICMP, MatchUtils.ALL_ICMP);
+        }
         if (null != srcAddress) {
             flowId = flowId + srcAddress;
             matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,
index ce2eec801263f3741e6ac00b4a885a34c6c8f6ab..0eeddf214344e46c86fc57b2ca7d3df9488168bc 100644 (file)
@@ -9,6 +9,8 @@
 package org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.services;
 
 import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 
 import org.opendaylight.ovsdb.openstack.netvirt.api.L2ForwardingProvider;
@@ -16,6 +18,7 @@ import org.opendaylight.ovsdb.openstack.netvirt.providers.ConfigInterface;
 import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.AbstractServiceInstance;
 import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.Service;
 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.Uri;
@@ -30,11 +33,11 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.Fl
 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.Instructions;
 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.instruction.ApplyActionsCase;
 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.ApplyActions;
 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.flow.types.rev131026.instruction.list.Instruction;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
@@ -42,14 +45,11 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instru
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxRegCaseBuilder;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceReference;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.collect.Lists;
-
 public class L2ForwardingService extends AbstractServiceInstance implements ConfigInterface, L2ForwardingProvider {
     private static final Logger LOG = LoggerFactory.getLogger(L2ForwardingService.class);
     public L2ForwardingService() {
@@ -72,50 +72,35 @@ public class L2ForwardingService extends AbstractServiceInstance implements Conf
 
         String nodeName = OPENFLOW + dpidLong;
 
-        MatchBuilder matchBuilder = new MatchBuilder();
         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
         FlowBuilder flowBuilder = new FlowBuilder();
 
         // Create the OF Match using MatchBuilder
-        flowBuilder.setMatch(MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
-        flowBuilder.setMatch(MatchUtils.createDestEthMatch(matchBuilder, new MacAddress(attachedMac), null).build());
+        MatchBuilder matchBuilder = new MatchBuilder();
+        MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId));
+        MatchUtils.createDestEthMatch(matchBuilder, new MacAddress(attachedMac), null);
+        flowBuilder.setMatch(matchBuilder.build());
 
-        String flowId = "UcastOut_"+segmentationId+"_"+localPort+"_"+attachedMac;
         // Add Flow Attributes
-        flowBuilder.setId(new FlowId(flowId));
-        FlowKey key = new FlowKey(new FlowId(flowId));
-        flowBuilder.setStrict(true);
-        flowBuilder.setBarrier(false);
-        flowBuilder.setTableId(getTable());
-        flowBuilder.setKey(key);
-        flowBuilder.setFlowName(flowId);
-        flowBuilder.setHardTimeout(0);
-        flowBuilder.setIdleTimeout(0);
+        String flowName = "UcastOut_" + segmentationId + "_" + localPort + "_" + attachedMac;
+        FlowUtils.initFlowBuilder(flowBuilder, flowName, getTable());
 
         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.createOutputPortInstructions(ib, dpidLong, localPort);
-            ib.setOrder(0);
-            ib.setKey(new InstructionKey(0));
-            instructions.add(ib.build());
-
-            // Add InstructionBuilder to the Instruction(s)Builder List
-            isb.setInstruction(instructions);
+            Instruction setOutputPortInstruction =
+                    InstructionUtils.createOutputPortInstructions(new InstructionBuilder(), dpidLong, localPort)
+                            .setOrder(0)
+                            .setKey(new InstructionKey(0))
+                            .build();
 
             // Add InstructionsBuilder to FlowBuilder
-            flowBuilder.setInstructions(isb.build());
+            InstructionUtils.setFlowBuilderInstruction(flowBuilder, setOutputPortInstruction);
             writeFlow(flowBuilder, nodeBuilder);
         } else {
             removeFlow(flowBuilder, nodeBuilder);
         }
     }
+
     /*
      * (Table:2) Local VLAN unicast
      * Match: VLAN ID and dMAC
@@ -129,54 +114,36 @@ public class L2ForwardingService extends AbstractServiceInstance implements Conf
 
         String nodeName = OPENFLOW + dpidLong;
 
-        MatchBuilder matchBuilder = new MatchBuilder();
         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
         FlowBuilder flowBuilder = new FlowBuilder();
 
         // Create the OF Match using MatchBuilder
-        flowBuilder.setMatch(
-                MatchUtils.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId)), true).build());
-        flowBuilder.setMatch(MatchUtils.createDestEthMatch(matchBuilder, new MacAddress(attachedMac), null).build());
+        MatchBuilder matchBuilder = new MatchBuilder();
+        MatchUtils.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId)), true);
+        MatchUtils.createDestEthMatch(matchBuilder, new MacAddress(attachedMac), null);
+        flowBuilder.setMatch(matchBuilder.build());
 
-        String flowId = "VlanUcastOut_"+segmentationId+"_"+localPort+"_"+attachedMac;
         // Add Flow Attributes
-        flowBuilder.setId(new FlowId(flowId));
-        FlowKey key = new FlowKey(new FlowId(flowId));
-        flowBuilder.setStrict(true);
-        flowBuilder.setBarrier(false);
-        flowBuilder.setTableId(getTable());
-        flowBuilder.setKey(key);
-        flowBuilder.setFlowName(flowId);
-        flowBuilder.setHardTimeout(0);
-        flowBuilder.setIdleTimeout(0);
+        String flowName = "VlanUcastOut_" + segmentationId + "_" + localPort + "_" + attachedMac;
+        FlowUtils.initFlowBuilder(flowBuilder, flowName, getTable());
 
         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();
-            List<Instruction> instructions_tmp = Lists.newArrayList();
-
             /* Strip vlan and store to tmp instruction space*/
-            InstructionUtils.createPopVlanInstructions(ib);
-            ib.setOrder(0);
-            ib.setKey(new InstructionKey(0));
-            instructions_tmp.add(ib.build());
+            Instruction stripVlanInstruction = InstructionUtils.createPopVlanInstructions(new InstructionBuilder())
+                    .setOrder(0)
+                    .setKey(new InstructionKey(0))
+                    .build();
 
             // Set the Output Port/Iface
-            ib = new InstructionBuilder();
-            InstructionUtils.addOutputPortInstructions(ib, dpidLong, localPort, instructions_tmp);
-            ib.setOrder(1);
-            ib.setKey(new InstructionKey(0));
-            instructions.add(ib.build());
-
-            // Add InstructionBuilder to the Instruction(s)Builder List
-            isb.setInstruction(instructions);
+            Instruction setOutputPortInstruction =
+                    InstructionUtils.addOutputPortInstructions(new InstructionBuilder(), dpidLong, localPort,
+                            Collections.singletonList(stripVlanInstruction))
+                            .setOrder(1)
+                            .setKey(new InstructionKey(0))
+                            .build();
 
             // Add InstructionsBuilder to FlowBuilder
-            flowBuilder.setInstructions(isb.build());
+            InstructionUtils.setFlowBuilderInstruction(flowBuilder, setOutputPortInstruction);
             writeFlow(flowBuilder, nodeBuilder);
         } else {
             removeFlow(flowBuilder, nodeBuilder);
@@ -184,33 +151,6 @@ public class L2ForwardingService extends AbstractServiceInstance implements Conf
     }
 
 
-    /**
-     * Utility function used by the flooding logic to allow a flow to be resubmitted
-     * to the local port flooding rule, after being outputed to all available tunnel
-     * or VLAN egress ports.
-     */
-    private void appendResubmitLocalFlood(InstructionBuilder ib) {
-
-        //Update the ApplyActions instructions
-        ApplyActionsCase aac = (ApplyActionsCase) ib.getInstruction();
-        List<Action> actionList = aac.getApplyActions().getAction();
-
-        int index = actionList.size();
-        ActionBuilder ab = new ActionBuilder();
-        ab.setAction(ActionUtils.nxLoadRegAction(new DstNxRegCaseBuilder().setNxReg(ClassifierService.REG_FIELD).build(),
-                BigInteger.valueOf(ClassifierService.REG_VALUE_FROM_REMOTE)));
-        ab.setOrder(index);
-        ab.setKey(new ActionKey(index));
-        actionList.add(ab.build());
-
-        index++;
-        ab = new ActionBuilder();
-        ab.setAction(ActionUtils.nxResubmitAction(null, this.getTable()));
-        ab.setOrder(index);
-        ab.setKey(new ActionKey(index));
-        actionList.add(ab.build());
-    }
-
     /*
      * (Table:2) Local Broadcast Flood
      * Match: Tunnel ID and dMAC (::::FF:FF)
@@ -223,61 +163,45 @@ public class L2ForwardingService extends AbstractServiceInstance implements Conf
 
         String nodeName = OPENFLOW + dpidLong;
 
-        MatchBuilder matchBuilder = new MatchBuilder();
         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
         FlowBuilder flowBuilder = new FlowBuilder();
 
         // Create the OF Match using MatchBuilder
-        MatchUtils.addNxRegMatch(matchBuilder, new MatchUtils.RegMatch(ClassifierService.REG_FIELD, ClassifierService.REG_VALUE_FROM_REMOTE));
-        flowBuilder.setMatch(MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
-        flowBuilder.setMatch(MatchUtils.createDestEthMatch(matchBuilder, new MacAddress("01:00:00:00:00:00"),
-                new MacAddress("01:00:00:00:00:00")).build());
+        MatchBuilder matchBuilder = new MatchBuilder();
+        MatchUtils.addNxRegMatch(matchBuilder,
+                new MatchUtils.RegMatch(ClassifierService.REG_FIELD, ClassifierService.REG_VALUE_FROM_REMOTE));
+        MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId));
+        MatchUtils.createDestEthMatch(matchBuilder, new MacAddress("01:00:00:00:00:00"),
+                new MacAddress("01:00:00:00:00:00"));
+        flowBuilder.setMatch(matchBuilder.build());
 
-        String flowId = "BcastOut_"+segmentationId;
         // Add Flow Attributes
-        flowBuilder.setId(new FlowId(flowId));
-        FlowKey key = new FlowKey(new FlowId(flowId));
-        flowBuilder.setStrict(true);
-        flowBuilder.setBarrier(false);
-        flowBuilder.setTableId(getTable());
-        flowBuilder.setKey(key);
-        flowBuilder.setPriority(16384);
-        flowBuilder.setFlowName(flowId);
-        flowBuilder.setHardTimeout(0);
-        flowBuilder.setIdleTimeout(0);
+        String flowName = "BcastOut_" + segmentationId;
+        FlowUtils.initFlowBuilder(flowBuilder, flowName, getTable())
+                .setPriority(16384);
+
         Flow flow = this.getFlow(flowBuilder, nodeBuilder);
-        // Instantiate the Builders for the OF Actions and Instructions
-        InstructionBuilder ib = new InstructionBuilder();
-        InstructionsBuilder isb = new InstructionsBuilder();
-        List<Instruction> instructions = Lists.newArrayList();
-        List<Instruction> existingInstructions = null;
-        if (flow != null) {
-            Instructions ins = flow.getInstructions();
-            if (ins != null) {
-                existingInstructions = ins.getInstruction();
-            }
-        }
+
+        // Retrieve the existing instructions
+        List<Instruction> existingInstructions = InstructionUtils.extractExistingInstructions(flow);
 
         if (write) {
             // Create output port list
-            createOutputPortInstructions(ib, dpidLong, localPort, existingInstructions);
-            ib.setOrder(0);
-            ib.setKey(new InstructionKey(0));
+            Instruction outputPortInstruction =
+                    createOutputPortInstructions(new InstructionBuilder(), dpidLong, localPort, existingInstructions)
+                            .setOrder(0)
+                            .setKey(new InstructionKey(0))
+                            .build();
 
-            /* Alternative method to address Bug 2004 is to make a call
-             * here to appendResubmitLocalFlood(ib) so that we send the
-             * flow back to the local flood rule.
-             */
-            instructions.add(ib.build());
-
-            // Add InstructionBuilder to the Instruction(s)Builder List
-            isb.setInstruction(instructions);
+            /* Alternative method to address Bug 2004 is to use appendResubmitLocalFlood(ib) so that we send the
+             * flow back to the local flood rule. (See git history.) */
 
             // Add InstructionsBuilder to FlowBuilder
-            flowBuilder.setInstructions(isb.build());
+            InstructionUtils.setFlowBuilderInstruction(flowBuilder, outputPortInstruction);
 
             writeFlow(flowBuilder, nodeBuilder);
         } else {
+            InstructionBuilder ib = new InstructionBuilder();
             boolean flowRemove = InstructionUtils.removeOutputPortFromInstructions(ib, dpidLong, localPort,
                     existingInstructions);
             if (flowRemove) {
@@ -285,15 +209,14 @@ public class L2ForwardingService extends AbstractServiceInstance implements Conf
                 removeFlow(flowBuilder, nodeBuilder);
             } else {
                 /* Install instruction with new output port list*/
-                ib.setOrder(0);
-                ib.setKey(new InstructionKey(0));
-                instructions.add(ib.build());
-
-                // Add InstructionBuilder to the Instruction(s)Builder List
-                isb.setInstruction(instructions);
+                Instruction outputPortInstruction = ib
+                        .setOrder(0)
+                        .setKey(new InstructionKey(0))
+                        .build();
 
                 // Add InstructionsBuilder to FlowBuilder
-                flowBuilder.setInstructions(isb.build());
+                InstructionUtils.setFlowBuilderInstruction(flowBuilder, outputPortInstruction);
+
                 writeFlow(flowBuilder, nodeBuilder);
             }
         }
@@ -313,78 +236,69 @@ public class L2ForwardingService extends AbstractServiceInstance implements Conf
 
         String nodeName = OPENFLOW + dpidLong;
 
-        MatchBuilder matchBuilder = new MatchBuilder();
         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
         FlowBuilder flowBuilder = new FlowBuilder();
 
         // Create the OF Match using MatchBuilder
-        flowBuilder.setMatch(
-                MatchUtils.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId)), true).build());
-        flowBuilder.setMatch(MatchUtils.createDestEthMatch(matchBuilder, new MacAddress("01:00:00:00:00:00"),
-                new MacAddress("01:00:00:00:00:00")).build());
+        MatchBuilder matchBuilder = new MatchBuilder();
+        MatchUtils.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId)), true);
+        MatchUtils.createDestEthMatch(matchBuilder, new MacAddress("01:00:00:00:00:00"),
+                new MacAddress("01:00:00:00:00:00"));
+        flowBuilder.setMatch(matchBuilder.build());
 
-        String flowId = "VlanBcastOut_"+segmentationId+"_"+ethPort;
         // Add Flow Attributes
-        flowBuilder.setId(new FlowId(flowId));
-        FlowKey key = new FlowKey(new FlowId(flowId));
-        flowBuilder.setStrict(true);
-        flowBuilder.setBarrier(false);
-        flowBuilder.setTableId(getTable());
-        flowBuilder.setKey(key);
-        flowBuilder.setPriority(16384);
-        flowBuilder.setFlowName(flowId);
-        flowBuilder.setHardTimeout(0);
-        flowBuilder.setIdleTimeout(0);
+        String flowName = "VlanBcastOut_" + segmentationId + "_" + ethPort;
+        FlowUtils.initFlowBuilder(flowBuilder, flowName, getTable())
+                .setPriority(16384);
         Flow flow = this.getFlow(flowBuilder, nodeBuilder);
-        // Instantiate the Builders for the OF Actions and Instructions
-        List<Instruction> existingInstructions = null;
-        if (flow != null) {
-            Instructions ins = flow.getInstructions();
-            if (ins != null) {
-                existingInstructions = ins.getInstruction();
-            }
-        }
 
-        List<Instruction> instructions = Lists.newArrayList();
-        InstructionBuilder ib = new InstructionBuilder();
-        List<Action> actionList;
+        // Retrieve the existing instructions
+        List<Instruction> existingInstructions = InstructionUtils.extractExistingInstructions(flow);
+
         if (write) {
-            if (existingInstructions == null) {
+            List<Action> actionList;
+            if (existingInstructions == null || existingInstructions.isEmpty()) {
                 /* First time called there should be no instructions.
                  * We can simply add the output:ethPort first, followed by
                  * popVlan and then the local port. The next calls will append
                  * the rest of the local ports.
                  */
-                ActionBuilder ab = new ActionBuilder();
-                actionList = Lists.newArrayList();
-
-                ab.setAction(ActionUtils.outputAction(new NodeConnectorId(nodeName + ":" + ethPort)));
-                ab.setOrder(0);
-                ab.setKey(new ActionKey(0));
-                actionList.add(ab.build());
-
-                ab.setAction(ActionUtils.popVlanAction());
-                ab.setOrder(1);
-                ab.setKey(new ActionKey(1));
-                actionList.add(ab.build());
-
-                ab.setAction(ActionUtils.outputAction(new NodeConnectorId(nodeName + ":" + localPort)));
-                ab.setOrder(2);
-                ab.setKey(new ActionKey(2));
-                actionList.add(ab.build());
+                actionList = new ArrayList<>();
+
+                actionList.add(
+                        new ActionBuilder()
+                                .setAction(ActionUtils.outputAction(new NodeConnectorId(nodeName + ":" + ethPort)))
+                                .setOrder(0)
+                                .setKey(new ActionKey(0))
+                                .build());
+
+                actionList.add(
+                        new ActionBuilder()
+                                .setAction(ActionUtils.popVlanAction())
+                                .setOrder(1)
+                                .setKey(new ActionKey(1))
+                                .build());
+
+                actionList.add(
+                        new ActionBuilder()
+                                .setAction(ActionUtils.outputAction(new NodeConnectorId(nodeName + ":" + localPort)))
+                                .setOrder(2)
+                                .setKey(new ActionKey(2))
+                                .build());
             } else {
                 /* Subsequent calls require appending any new local ports for this tenant. */
                 Instruction in = existingInstructions.get(0);
                 actionList = (((ApplyActionsCase) in.getInstruction()).getApplyActions().getAction());
 
                 NodeConnectorId ncid = new NodeConnectorId(nodeName + ":" + localPort);
+                final Uri nodeConnectorUri = new Uri(ncid);
                 boolean addNew = true;
 
                 /* Check if the port is already in the output list */
                 for (Action action : actionList) {
                     if (action.getAction() instanceof OutputActionCase) {
                         OutputActionCase opAction = (OutputActionCase) action.getAction();
-                        if (opAction.getOutputAction().getOutputNodeConnector().equals(new Uri(ncid))) {
+                        if (opAction.getOutputAction().getOutputNodeConnector().equals(nodeConnectorUri)) {
                             addNew = false;
                             break;
                         }
@@ -392,32 +306,29 @@ public class L2ForwardingService extends AbstractServiceInstance implements Conf
                 }
 
                 if (addNew) {
-                    ActionBuilder ab = new ActionBuilder();
-
-                    ab.setAction(ActionUtils.outputAction(new NodeConnectorId(nodeName + ":" + localPort)));
-                    ab.setOrder(actionList.size());
-                    ab.setKey(new ActionKey(actionList.size()));
-                    actionList.add(ab.build());
+                    actionList.add(
+                            new ActionBuilder()
+                                    .setAction(
+                                            ActionUtils.outputAction(new NodeConnectorId(nodeName + ":" + localPort)))
+                                    .setOrder(actionList.size())
+                                    .setKey(new ActionKey(actionList.size()))
+                                    .build());
                 }
             }
 
-            ApplyActionsBuilder aab = new ApplyActionsBuilder();
-            aab.setAction(actionList);
-            ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
-            ib.setOrder(0);
-            ib.setKey(new InstructionKey(0));
-            instructions.add(ib.build());
-
-            // Add InstructionBuilder to the Instruction(s)Builder List
-            InstructionsBuilder isb = new InstructionsBuilder();
-            isb.setInstruction(instructions);
+            ApplyActions applyActions = new ApplyActionsBuilder().setAction(actionList).build();
+            Instruction applyActionsInstruction =
+                    new InstructionBuilder()
+                            .setInstruction(new ApplyActionsCaseBuilder().setApplyActions(applyActions).build())
+                            .setOrder(0)
+                            .setKey(new InstructionKey(0))
+                            .build();
 
             // Add InstructionsBuilder to FlowBuilder
-            flowBuilder.setInstructions(isb.build());
+            InstructionUtils.setFlowBuilderInstruction(flowBuilder, applyActionsInstruction);
             writeFlow(flowBuilder, nodeBuilder);
         } else {
-            //boolean flowRemove = removeOutputPortFromGroup(nodeBuilder, ib, dpidLong,
-            //                     localPort, existingInstructions);
+            InstructionBuilder ib = new InstructionBuilder();
             boolean flowRemove = removeOutputPortFromInstructions(ib, dpidLong, localPort, ethPort,
                     existingInstructions);
             if (flowRemove) {
@@ -425,16 +336,13 @@ public class L2ForwardingService extends AbstractServiceInstance implements Conf
                 removeFlow(flowBuilder, nodeBuilder);
             } else {
                 /* Install instruction with new output port list*/
-                ib.setOrder(0);
-                ib.setKey(new InstructionKey(0));
-                instructions.add(ib.build());
-
-                // Add InstructionBuilder to the Instruction(s)Builder List
-                InstructionsBuilder isb = new InstructionsBuilder();
-                isb.setInstruction(instructions);
+                Instruction outputPortInstruction = ib
+                        .setOrder(0)
+                        .setKey(new InstructionKey(0))
+                        .build();
 
                 // Add InstructionsBuilder to FlowBuilder
-                flowBuilder.setInstructions(isb.build());
+                InstructionUtils.setFlowBuilderInstruction(flowBuilder, outputPortInstruction);
                 writeFlow(flowBuilder, nodeBuilder);
             }
         }
@@ -442,43 +350,44 @@ public class L2ForwardingService extends AbstractServiceInstance implements Conf
 
     private boolean removeOutputPortFromInstructions(InstructionBuilder ib, Long dpidLong, Long localPort,
                                                      Long ethPort, List<Instruction> instructions) {
-        List<Action> actionList = Lists.newArrayList();
+        List<Action> actionList = new ArrayList<>();
         boolean removeFlow = true;
 
-        if (instructions != null) {
+        if (instructions != null && !instructions.isEmpty()) {
             Instruction in = instructions.get(0);
             List<Action> oldActionList = (((ApplyActionsCase) in.getInstruction()).getApplyActions().getAction());
             NodeConnectorId ncid = new NodeConnectorId(OPENFLOW + dpidLong + ":" + localPort);
+            final Uri localNodeConnectorUri = new Uri(ncid);
             NodeConnectorId ncidEth = new NodeConnectorId(OPENFLOW + dpidLong + ":" + ethPort);
+            final Uri ethNodeConnectorUri = new Uri(ncidEth);
 
             // Remove the port from the output list
-            ActionBuilder ab = new ActionBuilder();
             int index = 2;
-            //for (ListIterator<Action> it = oldActionList.listIterator(oldActionList.size()); it.hasPrevious();) {
-            //    Action action = it.previous();
             for (Action action : oldActionList) {
                 if (action.getAction() instanceof OutputActionCase) {
                     OutputActionCase opAction = (OutputActionCase) action.getAction();
-                    if (opAction.getOutputAction().getOutputNodeConnector().equals(new Uri(ncidEth))) {
+                    if (opAction.getOutputAction().getOutputNodeConnector().equals(ethNodeConnectorUri)) {
                         actionList.add(action);
-                    } else if (!opAction.getOutputAction().getOutputNodeConnector().equals(new Uri(ncid))) {
-                        ab.setAction(action.getAction());
-                        ab.setOrder(index);
-                        ab.setKey(new ActionKey(index));
-                        actionList.add(ab.build());
+                    } else if (!opAction.getOutputAction().getOutputNodeConnector().equals(localNodeConnectorUri)) {
+                        actionList.add(
+                                new ActionBuilder()
+                                        .setAction(action.getAction())
+                                        .setOrder(index)
+                                        .setKey(new ActionKey(index))
+                                        .build());
                         index++;
                     }
                 } else {
                     actionList.add(action);
                 }
             }
-            ApplyActionsBuilder aab = new ApplyActionsBuilder();
-            aab.setAction(actionList);
-            ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
+            ApplyActions applyActions = new ApplyActionsBuilder().setAction(actionList).build();
+            ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(applyActions).build());
         }
 
         if (actionList.size() > 2) {
             // Add InstructionBuilder to the Instruction(s)Builder List
+            // TODO This doesn't actually do anything
             InstructionsBuilder isb = new InstructionsBuilder();
             isb.setInstruction(instructions);
             removeFlow = false;
@@ -499,46 +408,28 @@ public class L2ForwardingService extends AbstractServiceInstance implements Conf
 
         String nodeName = OPENFLOW + dpidLong;
 
-        MatchBuilder matchBuilder = new MatchBuilder();
         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
         FlowBuilder flowBuilder = new FlowBuilder();
 
         // Create Match(es) and Set them in the FlowBuilder Object
-        flowBuilder.setMatch(MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
+        flowBuilder.setMatch(
+                MatchUtils.createTunnelIDMatch(new MatchBuilder(), new BigInteger(segmentationId)).build());
 
         if (write) {
-            // Create the OF Actions and Instructions
-            InstructionBuilder ib = new InstructionBuilder();
-            InstructionsBuilder isb = new InstructionsBuilder();
-
-            // Instructions List Stores Individual Instructions
-            List<Instruction> instructions = Lists.newArrayList();
-
             // Call the InstructionBuilder Methods Containing Actions
-            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);
+            Instruction dropInstruction = InstructionUtils.createDropInstructions(new InstructionBuilder())
+                    .setOrder(0)
+                    .setKey(new InstructionKey(0))
+                    .build();
 
             // Add InstructionsBuilder to FlowBuilder
-            flowBuilder.setInstructions(isb.build());
+            InstructionUtils.setFlowBuilderInstruction(flowBuilder, dropInstruction);
         }
 
-        String flowId = "LocalTableMiss_"+segmentationId;
         // Add Flow Attributes
-        flowBuilder.setId(new FlowId(flowId));
-        FlowKey key = new FlowKey(new FlowId(flowId));
-        flowBuilder.setStrict(true);
-        flowBuilder.setBarrier(false);
-        flowBuilder.setTableId(getTable());
-        flowBuilder.setKey(key);
-        flowBuilder.setPriority(8192);
-        flowBuilder.setFlowName(flowId);
-        flowBuilder.setHardTimeout(0);
-        flowBuilder.setIdleTimeout(0);
+        String flowName = "LocalTableMiss_" + segmentationId;
+        FlowUtils.initFlowBuilder(flowBuilder, flowName, getTable())
+                .setPriority(8192);
         if (write) {
             writeFlow(flowBuilder, nodeBuilder);
         } else {
@@ -558,47 +449,29 @@ public class L2ForwardingService extends AbstractServiceInstance implements Conf
 
         String nodeName = OPENFLOW + dpidLong;
 
-        MatchBuilder matchBuilder = new MatchBuilder();
         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
         FlowBuilder flowBuilder = new FlowBuilder();
 
         // Create Match(es) and Set them in the FlowBuilder Object
         flowBuilder.setMatch(
-                MatchUtils.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId)), true).build());
+                MatchUtils.createVlanIdMatch(new MatchBuilder(), new VlanId(Integer.valueOf(segmentationId)),
+                        true).build());
 
         if (write) {
-            // Create the OF Actions and Instructions
-            InstructionBuilder ib = new InstructionBuilder();
-            InstructionsBuilder isb = new InstructionsBuilder();
-
-            // Instructions List Stores Individual Instructions
-            List<Instruction> instructions = Lists.newArrayList();
-
             // Call the InstructionBuilder Methods Containing Actions
-            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);
+            Instruction dropInstruction = InstructionUtils.createDropInstructions(new InstructionBuilder())
+                    .setOrder(0)
+                    .setKey(new InstructionKey(0))
+                    .build();
 
             // Add InstructionsBuilder to FlowBuilder
-            flowBuilder.setInstructions(isb.build());
+            InstructionUtils.setFlowBuilderInstruction(flowBuilder, dropInstruction);
         }
 
-        String flowId = "LocalTableMiss_"+segmentationId;
         // Add Flow Attributes
-        flowBuilder.setId(new FlowId(flowId));
-        FlowKey key = new FlowKey(new FlowId(flowId));
-        flowBuilder.setStrict(true);
-        flowBuilder.setBarrier(false);
-        flowBuilder.setTableId(getTable());
-        flowBuilder.setKey(key);
-        flowBuilder.setPriority(8192);
-        flowBuilder.setFlowName(flowId);
-        flowBuilder.setHardTimeout(0);
-        flowBuilder.setIdleTimeout(0);
+        String flowName = "LocalTableMiss_" + segmentationId;
+        FlowUtils.initFlowBuilder(flowBuilder, flowName, getTable())
+                .setPriority(8192);
         if (write) {
             writeFlow(flowBuilder, nodeBuilder);
         } else {
@@ -620,45 +493,29 @@ public class L2ForwardingService extends AbstractServiceInstance implements Conf
 
         String nodeName = OPENFLOW + dpidLong;
 
-        MatchBuilder matchBuilder = new MatchBuilder();
         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
         FlowBuilder flowBuilder = new FlowBuilder();
 
         // Create the OF Match using MatchBuilder
-        flowBuilder.setMatch(MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
-        flowBuilder.setMatch(MatchUtils.createDestEthMatch(matchBuilder, new MacAddress(attachedMac), null).build());
+        MatchBuilder matchBuilder = new MatchBuilder();
+        MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId));
+        MatchUtils.createDestEthMatch(matchBuilder, new MacAddress(attachedMac), null);
+        flowBuilder.setMatch(matchBuilder.build());
 
-        String flowId = "TunnelOut_"+segmentationId+"_"+OFPortOut+"_"+attachedMac;
         // Add Flow Attributes
-        flowBuilder.setId(new FlowId(flowId));
-        FlowKey key = new FlowKey(new FlowId(flowId));
-        flowBuilder.setStrict(true);
-        flowBuilder.setBarrier(false);
-        flowBuilder.setTableId(getTable());
-        flowBuilder.setKey(key);
-        flowBuilder.setFlowName(flowId);
-        flowBuilder.setHardTimeout(0);
-        flowBuilder.setIdleTimeout(0);
+        String flowName = "TunnelOut_" + segmentationId + "_" + OFPortOut + "_" + attachedMac;
+        FlowUtils.initFlowBuilder(flowBuilder, flowName, getTable());
 
         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.createOutputPortInstructions(ib, dpidLong, OFPortOut);
-            ib.setOrder(0);
-            ib.setKey(new InstructionKey(1));
-            instructions.add(ib.build());
-
-            // Add InstructionBuilder to the Instruction(s)Builder List
-            isb.setInstruction(instructions);
+            Instruction outputPortInstruction =
+                    InstructionUtils.createOutputPortInstructions(new InstructionBuilder(), dpidLong, OFPortOut)
+                            .setOrder(0)
+                            .setKey(new InstructionKey(1))
+                            .build();
 
             // Add InstructionsBuilder to FlowBuilder
-            flowBuilder.setInstructions(isb.build());
+            InstructionUtils.setFlowBuilderInstruction(flowBuilder, outputPortInstruction);
 
             writeFlow(flowBuilder, nodeBuilder);
         } else {
@@ -679,44 +536,29 @@ public class L2ForwardingService extends AbstractServiceInstance implements Conf
 
         String nodeName = OPENFLOW + dpidLong;
 
-        MatchBuilder matchBuilder = new MatchBuilder();
         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
         FlowBuilder flowBuilder = new FlowBuilder();
 
         // Create the OF Match using MatchBuilder
-        flowBuilder.setMatch(
-                MatchUtils.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId)), true).build());
-        flowBuilder.setMatch(MatchUtils.createDestEthMatch(matchBuilder, new MacAddress(attachedMac), null).build());
+        MatchBuilder matchBuilder = new MatchBuilder();
+        MatchUtils.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId)), true);
+        MatchUtils.createDestEthMatch(matchBuilder, new MacAddress(attachedMac), null);
+        flowBuilder.setMatch(matchBuilder.build());
 
-        String flowId = "VlanOut_"+segmentationId+"_"+ethPort+"_"+attachedMac;
         // Add Flow Attributes
-        flowBuilder.setId(new FlowId(flowId));
-        FlowKey key = new FlowKey(new FlowId(flowId));
-        flowBuilder.setStrict(true);
-        flowBuilder.setBarrier(false);
-        flowBuilder.setTableId(getTable());
-        flowBuilder.setKey(key);
-        flowBuilder.setFlowName(flowId);
-        flowBuilder.setHardTimeout(0);
-        flowBuilder.setIdleTimeout(0);
+        String flowName = "VlanOut_" + segmentationId + "_" + ethPort + "_" + attachedMac;
+        FlowUtils.initFlowBuilder(flowBuilder, flowName, getTable());
 
         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();
-            InstructionUtils.createOutputPortInstructions(ib, dpidLong, ethPort);
-            ib.setOrder(0);
-            ib.setKey(new InstructionKey(1));
-            instructions.add(ib.build());
-
-            // Add InstructionBuilder to the Instruction(s)Builder List
-            isb.setInstruction(instructions);
+            Instruction outputPortInstruction =
+                    InstructionUtils.createOutputPortInstructions(new InstructionBuilder(), dpidLong, ethPort)
+                            .setOrder(0)
+                            .setKey(new InstructionKey(1))
+                            .build();
 
             // Add InstructionsBuilder to FlowBuilder
-            flowBuilder.setInstructions(isb.build());
+            InstructionUtils.setFlowBuilderInstruction(flowBuilder, outputPortInstruction);
 
             writeFlow(flowBuilder, nodeBuilder);
         } else {
@@ -736,59 +578,51 @@ public class L2ForwardingService extends AbstractServiceInstance implements Conf
 
         String nodeName = OPENFLOW + dpidLong;
 
-        MatchBuilder matchBuilder = new MatchBuilder();
         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
         FlowBuilder flowBuilder = new FlowBuilder();
 
         // Create the OF Match using MatchBuilder
+        MatchBuilder matchBuilder = new MatchBuilder();
         // Match TunnelID
-        MatchUtils.addNxRegMatch(matchBuilder, new MatchUtils.RegMatch(ClassifierService.REG_FIELD, ClassifierService.REG_VALUE_FROM_LOCAL));
-        flowBuilder.setMatch(MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
+        MatchUtils.addNxRegMatch(matchBuilder,
+                new MatchUtils.RegMatch(ClassifierService.REG_FIELD, ClassifierService.REG_VALUE_FROM_LOCAL));
+        MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId));
         // Match DMAC
-        flowBuilder.setMatch(MatchUtils.createDestEthMatch(matchBuilder, new MacAddress("01:00:00:00:00:00"),
-                new MacAddress("01:00:00:00:00:00")).build());
+        MatchUtils.createDestEthMatch(matchBuilder, new MacAddress("01:00:00:00:00:00"),
+                new MacAddress("01:00:00:00:00:00"));
+        flowBuilder.setMatch(matchBuilder.build());
 
-        String flowId = "TunnelFloodOut_"+segmentationId;
         // Add Flow Attributes
-        flowBuilder.setId(new FlowId(flowId));
-        FlowKey key = new FlowKey(new FlowId(flowId));
-        flowBuilder.setBarrier(true);
-        flowBuilder.setTableId(getTable());
-        flowBuilder.setKey(key);
-        flowBuilder.setPriority(16383);  // FIXME: change it back to 16384 once bug 3005 is fixed.
-        flowBuilder.setFlowName(flowId);
-        flowBuilder.setHardTimeout(0);
-        flowBuilder.setIdleTimeout(0);
+        String flowName = "TunnelFloodOut_" + segmentationId;
+        final FlowId flowId = new FlowId(flowName);
+        flowBuilder
+                .setId(flowId)
+                .setBarrier(true)
+                .setTableId(getTable())
+                .setKey(new FlowKey(flowId))
+                .setPriority(16383)  // FIXME: change it back to 16384 once bug 3005 is fixed.
+                .setFlowName(flowName)
+                .setHardTimeout(0)
+                .setIdleTimeout(0);
 
         Flow flow = this.getFlow(flowBuilder, nodeBuilder);
         // Instantiate the Builders for the OF Actions and Instructions
-        InstructionBuilder ib = new InstructionBuilder();
-        InstructionsBuilder isb = new InstructionsBuilder();
-        List<Instruction> instructions = Lists.newArrayList();
-        List<Instruction> existingInstructions = null;
-        if (flow != null) {
-            Instructions ins = flow.getInstructions();
-            if (ins != null) {
-                existingInstructions = ins.getInstruction();
-            }
-        }
+        List<Instruction> existingInstructions = InstructionUtils.extractExistingInstructions(flow);
 
         if (write) {
             // Set the Output Port/Iface
-            //createOutputGroupInstructions(nodeBuilder, ib, dpidLong, OFPortOut, existingInstructions);
-            createOutputPortInstructions(ib, dpidLong, OFPortOut, existingInstructions);
-            ib.setOrder(0);
-            ib.setKey(new InstructionKey(0));
-            instructions.add(ib.build());
-
-            // Add InstructionBuilder to the Instruction(s)Builder List
-            isb.setInstruction(instructions);
+            Instruction outputPortInstruction =
+                    createOutputPortInstructions(new InstructionBuilder(), dpidLong, OFPortOut, existingInstructions)
+                            .setOrder(0)
+                            .setKey(new InstructionKey(0))
+                            .build();
 
             // Add InstructionsBuilder to FlowBuilder
-            flowBuilder.setInstructions(isb.build());
+            InstructionUtils.setFlowBuilderInstruction(flowBuilder, outputPortInstruction);
 
             writeFlow(flowBuilder, nodeBuilder);
         } else {
+            InstructionBuilder ib = new InstructionBuilder();
             /* remove port from action list */
             boolean flowRemove = InstructionUtils.removeOutputPortFromInstructions(ib, dpidLong,
                     OFPortOut, existingInstructions);
@@ -797,15 +631,13 @@ public class L2ForwardingService extends AbstractServiceInstance implements Conf
                 removeFlow(flowBuilder, nodeBuilder);
             } else {
                 /* Install instruction with new output port list*/
-                ib.setOrder(0);
-                ib.setKey(new InstructionKey(0));
-                instructions.add(ib.build());
-
-                // Add InstructionBuilder to the Instruction(s)Builder List
-                isb.setInstruction(instructions);
+                Instruction instruction = ib
+                        .setOrder(0)
+                        .setKey(new InstructionKey(0))
+                        .build();
 
                 // Add InstructionsBuilder to FlowBuilder
-                flowBuilder.setInstructions(isb.build());
+                InstructionUtils.setFlowBuilderInstruction(flowBuilder, instruction);
                 writeFlow(flowBuilder, nodeBuilder);
             }
         }
@@ -824,50 +656,44 @@ public class L2ForwardingService extends AbstractServiceInstance implements Conf
 
         String nodeName = OPENFLOW + dpidLong;
 
-        MatchBuilder matchBuilder = new MatchBuilder();
         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
         FlowBuilder flowBuilder = new FlowBuilder();
 
         // Create the OF Match using MatchBuilder
+        MatchBuilder matchBuilder = new MatchBuilder();
         // Match Vlan ID
-        flowBuilder.setMatch(
-                MatchUtils.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId)), true).build());
+        MatchUtils.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId)), true);
         // Match DMAC
-        flowBuilder.setMatch(MatchUtils.createDestEthMatch(matchBuilder, new MacAddress("01:00:00:00:00:00"),
-                new MacAddress("01:00:00:00:00:00")).build());
+        MatchUtils.createDestEthMatch(matchBuilder, new MacAddress("01:00:00:00:00:00"),
+                new MacAddress("01:00:00:00:00:00"));
+        flowBuilder.setMatch(matchBuilder.build());
 
-        String flowId = "VlanFloodOut_"+segmentationId+"_"+ethPort;
         // Add Flow Attributes
-        flowBuilder.setId(new FlowId(flowId));
-        FlowKey key = new FlowKey(new FlowId(flowId));
-        flowBuilder.setBarrier(true);
-        flowBuilder.setTableId(getTable());
-        flowBuilder.setKey(key);
-        flowBuilder.setPriority(16384);
-        flowBuilder.setFlowName(flowId);
-        flowBuilder.setHardTimeout(0);
-        flowBuilder.setIdleTimeout(0);
+        String flowName = "VlanFloodOut_" + segmentationId + "_" + ethPort;
+        final FlowId flowId = new FlowId(flowName);
+        flowBuilder
+                .setId(flowId)
+                .setBarrier(true)
+                .setTableId(getTable())
+                .setKey(new FlowKey(flowId))
+                .setPriority(16384)
+                .setFlowName(flowName)
+                .setHardTimeout(0)
+                .setIdleTimeout(0);
 
         //ToDo: Is there something to be done with result of the call to getFlow?
-
         Flow flow = this.getFlow(flowBuilder, nodeBuilder);
-        // Instantiate the Builders for the OF Actions and Instructions
-        InstructionBuilder ib = new InstructionBuilder();
-        InstructionsBuilder isb = new InstructionsBuilder();
-        List<Instruction> instructions = Lists.newArrayList();
 
         if (write) {
             // Set the Output Port/Iface
-            InstructionUtils.createOutputPortInstructions(ib, dpidLong, ethPort);
-            ib.setOrder(0);
-            ib.setKey(new InstructionKey(0));
-            instructions.add(ib.build());
-
-            // Add InstructionBuilder to the Instruction(s)Builder List
-            isb.setInstruction(instructions);
+            Instruction outputPortInstruction =
+                    InstructionUtils.createOutputPortInstructions(new InstructionBuilder(), dpidLong, ethPort)
+                            .setOrder(0)
+                            .setKey(new InstructionKey(0))
+                            .build();
 
             // Add InstructionsBuilder to FlowBuilder
-            flowBuilder.setInstructions(isb.build());
+            InstructionUtils.setFlowBuilderInstruction(flowBuilder, outputPortInstruction);
 
             writeFlow(flowBuilder, nodeBuilder);
         } else {
@@ -886,45 +712,28 @@ public class L2ForwardingService extends AbstractServiceInstance implements Conf
 
         String nodeName = OPENFLOW + dpidLong;
 
-        MatchBuilder matchBuilder = new MatchBuilder();
         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
         FlowBuilder flowBuilder = new FlowBuilder();
 
         // Create Match(es) and Set them in the FlowBuilder Object
-        flowBuilder.setMatch(MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
+        flowBuilder.setMatch(
+                MatchUtils.createTunnelIDMatch(new MatchBuilder(), new BigInteger(segmentationId)).build());
 
         if (write) {
-            // Create the OF Actions and Instructions
-            InstructionsBuilder isb = new InstructionsBuilder();
-
-            // Instructions List Stores Individual Instructions
-            List<Instruction> instructions = Lists.newArrayList();
-
             // Call the InstructionBuilder Methods Containing Actions
-            InstructionBuilder ib = this.getMutablePipelineInstructionBuilder();
-            ib.setOrder(0);
-            ib.setKey(new InstructionKey(0));
-            instructions.add(ib.build());
-
-            // Add InstructionBuilder to the Instruction(s)Builder List
-            isb.setInstruction(instructions);
+            Instruction mutablePipelineInstruction = getMutablePipelineInstructionBuilder()
+                    .setOrder(0)
+                    .setKey(new InstructionKey(0))
+                    .build();
 
             // Add InstructionsBuilder to FlowBuilder
-            flowBuilder.setInstructions(isb.build());
+            InstructionUtils.setFlowBuilderInstruction(flowBuilder, mutablePipelineInstruction);
         }
 
-        String flowId = "TunnelMiss_"+segmentationId;
         // Add Flow Attributes
-        flowBuilder.setId(new FlowId(flowId));
-        FlowKey key = new FlowKey(new FlowId(flowId));
-        flowBuilder.setStrict(true);
-        flowBuilder.setBarrier(false);
-        flowBuilder.setTableId(getTable());
-        flowBuilder.setKey(key);
-        flowBuilder.setPriority(8192);
-        flowBuilder.setFlowName(flowId);
-        flowBuilder.setHardTimeout(0);
-        flowBuilder.setIdleTimeout(0);
+        String flowName = "TunnelMiss_" + segmentationId;
+        FlowUtils.initFlowBuilder(flowBuilder, flowName, getTable())
+                .setPriority(8192);
         if (write) {
             writeFlow(flowBuilder, nodeBuilder);
         } else {
@@ -945,47 +754,30 @@ public class L2ForwardingService extends AbstractServiceInstance implements Conf
 
         String nodeName = OPENFLOW + dpidLong;
 
-        MatchBuilder matchBuilder = new MatchBuilder();
         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
         FlowBuilder flowBuilder = new FlowBuilder();
 
         // Create Match(es) and Set them in the FlowBuilder Object
         flowBuilder.setMatch(
-                MatchUtils.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId)), true).build());
+                MatchUtils.createVlanIdMatch(new MatchBuilder(), new VlanId(Integer.valueOf(segmentationId)),
+                        true).build());
 
         if (write) {
-            // Create 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.createOutputPortInstructions(ib, dpidLong, ethPort);
-            ib.setOrder(0);
-            ib.setKey(new InstructionKey(1));
-            instructions.add(ib.build());
-
-            // Add InstructionBuilder to the Instruction(s)Builder List
-            isb.setInstruction(instructions);
+            Instruction outputPortInstruction =
+                    InstructionUtils.createOutputPortInstructions(new InstructionBuilder(), dpidLong, ethPort)
+                            .setOrder(0)
+                            .setKey(new InstructionKey(1))
+                            .build();
 
             // Add InstructionsBuilder to FlowBuilder
-            flowBuilder.setInstructions(isb.build());
+            InstructionUtils.setFlowBuilderInstruction(flowBuilder, outputPortInstruction);
         }
 
-        String flowId = "VlanMiss_"+segmentationId;
         // Add Flow Attributes
-        flowBuilder.setId(new FlowId(flowId));
-        FlowKey key = new FlowKey(new FlowId(flowId));
-        flowBuilder.setStrict(true);
-        flowBuilder.setBarrier(false);
-        flowBuilder.setTableId(getTable());
-        flowBuilder.setKey(key);
-        flowBuilder.setPriority(8192);
-        flowBuilder.setFlowName(flowId);
-        flowBuilder.setHardTimeout(0);
-        flowBuilder.setIdleTimeout(0);
+        String flowName = "VlanMiss_" + segmentationId;
+        FlowUtils.initFlowBuilder(flowBuilder, flowName, getTable())
+                .setPriority(8192);
         if (write) {
             writeFlow(flowBuilder, nodeBuilder);
         } else {
@@ -1007,7 +799,7 @@ public class L2ForwardingService extends AbstractServiceInstance implements Conf
         NodeConnectorId ncid = new NodeConnectorId(OPENFLOW + dpidLong + ":" + port);
         LOG.debug("createOutputPortInstructions() Node Connector ID is - Type=openflow: DPID={} port={} existingInstructions={}", dpidLong, port, instructions);
 
-        List<Action> actionList = Lists.newArrayList();
+        List<Action> actionList = new ArrayList<>();
         ActionBuilder ab = new ActionBuilder();
 
         List<Action> existingActions;
index f1654266de348eb4871d83069cd761787adf0617..c21b60fa0bbde363e34bdfde92fe71e68db7dfed 100644 (file)
@@ -266,6 +266,43 @@ public class EgressAclServiceTest {
         verify(commitFuture, times(1)).get();
     }
 */
+    /**
+     * Test method {@link EgressAclService#programPortSecurityGroup(java.lang.Long, java.lang.String,
+     * java.lang.String, long, org.opendaylight.ovsdb.openstack.netvirt.translator.NeutronSecurityGroup,
+     * java.lang.String, boolean)} when portSecurityRule is incomplete
+     */
+    @Test
+    public void testProgramPortSecurityGroupWithIncompleteRule() throws Exception {
+        NeutronSecurityRule portSecurityRule1 = mock(NeutronSecurityRule.class);
+        when(portSecurityRule1.getSecurityRuleEthertype()).thenReturn("IPv4");
+        when(portSecurityRule1.getSecurityRuleDirection()).thenReturn("not_egress");  // other direction
+
+        NeutronSecurityRule portSecurityRule2 = mock(NeutronSecurityRule.class);
+        when(portSecurityRule2.getSecurityRuleEthertype()).thenReturn(null);
+        when(portSecurityRule2.getSecurityRuleDirection()).thenReturn("egress");
+
+        NeutronSecurityRule portSecurityRule3 = mock(NeutronSecurityRule.class);
+        when(portSecurityRule3.getSecurityRuleEthertype()).thenReturn("IPv4");
+        when(portSecurityRule3.getSecurityRuleDirection()).thenReturn(null);
+
+        NeutronSecurityRule portSecurityRule4 = mock(NeutronSecurityRule.class);
+        when(portSecurityRule4.getSecurityRuleEthertype()).thenReturn(null);
+        when(portSecurityRule4.getSecurityRuleDirection()).thenReturn(null);
+
+        List<NeutronSecurityRule> portSecurityList = new ArrayList<>();
+        portSecurityList.add(null);
+        portSecurityList.add(portSecurityRule1);
+        portSecurityList.add(portSecurityRule2);
+        portSecurityList.add(portSecurityRule3);
+        portSecurityList.add(portSecurityRule4);
+
+        NeutronSecurityGroup localSecurityGroup = mock(NeutronSecurityGroup.class);
+        when(localSecurityGroup.getSecurityRules()).thenReturn(portSecurityList);
+
+        egressAclServiceSpy.programPortSecurityGroup(DP_ID_LONG, SEGMENT_ID, MAC_ADDRESS, LOCAL_PORT,
+                localSecurityGroup, PORT_UUID, true);
+    }
+
     /**
      * Test method {@link EgressAclService#egressACLDefaultTcpDrop(Long, String, String, int, boolean)}
      */
index f617990b578ac755d0f23340f66071723ad9d5d6..e2b41f68bcdb995d3d02cb121a023a36e94802af 100644 (file)
@@ -269,6 +269,43 @@ public class IngressAclServiceTest {
         verify(commitFuture, times(1)).get();
     }
 */
+    /**
+     * Test method {@link EgressAclService#programPortSecurityGroup(java.lang.Long, java.lang.String,
+     * java.lang.String, long, org.opendaylight.ovsdb.openstack.netvirt.translator.NeutronSecurityGroup,
+     * java.lang.String, boolean)} when portSecurityRule is incomplete
+     */
+    @Test
+    public void testProgramPortSecurityGroupWithIncompleteRule() throws Exception {
+        NeutronSecurityRule portSecurityRule1 = mock(NeutronSecurityRule.class);
+        when(portSecurityRule1.getSecurityRuleEthertype()).thenReturn("IPv4");
+        when(portSecurityRule1.getSecurityRuleDirection()).thenReturn("not_ingress");  // other direction
+
+        NeutronSecurityRule portSecurityRule2 = mock(NeutronSecurityRule.class);
+        when(portSecurityRule2.getSecurityRuleEthertype()).thenReturn(null);
+        when(portSecurityRule2.getSecurityRuleDirection()).thenReturn("ingress");
+
+        NeutronSecurityRule portSecurityRule3 = mock(NeutronSecurityRule.class);
+        when(portSecurityRule3.getSecurityRuleEthertype()).thenReturn("IPv4");
+        when(portSecurityRule3.getSecurityRuleDirection()).thenReturn(null);
+
+        NeutronSecurityRule portSecurityRule4 = mock(NeutronSecurityRule.class);
+        when(portSecurityRule4.getSecurityRuleEthertype()).thenReturn(null);
+        when(portSecurityRule4.getSecurityRuleDirection()).thenReturn(null);
+
+        List<NeutronSecurityRule> portSecurityList = new ArrayList<>();
+        portSecurityList.add(null);
+        portSecurityList.add(portSecurityRule1);
+        portSecurityList.add(portSecurityRule2);
+        portSecurityList.add(portSecurityRule3);
+        portSecurityList.add(portSecurityRule4);
+
+        NeutronSecurityGroup localSecurityGroup = mock(NeutronSecurityGroup.class);
+        when(localSecurityGroup.getSecurityRules()).thenReturn(portSecurityList);
+
+        ingressAclServiceSpy.programPortSecurityGroup(
+                Long.valueOf(1554), "2", MAC_ADDRESS, 124, localSecurityGroup, PORT_UUID, false);
+    }
+
     /**
      *  Test IPv4 add test case.
      */
index c01db2bc0c15d7b4ddbef284e30952252a5cc1c6..75049d0d0e309d3f466bae15a6b5206749848ece 100644 (file)
@@ -57,11 +57,8 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
             <Export-Package>
               org.opendaylight.yang.gen.v1.*,
               org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.acl.rev150105,
-              org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.acl.rev150105.*,
               org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105,
-              org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.*,
               org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.rev150105,
-              org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.rev150105.*
             </Export-Package>
           </instructions>
         </configuration>
index 31d1e1d867e9b727f259cb1daab7ae3e9269056e..44fa5a1847ce303d084f01e108f6af4c3ee190fb 100644 (file)
@@ -10,7 +10,6 @@ module netvirt-sfc-acl {
         description "Initial revision of netvirt extensions to ietf-acl model";
     }
 
-    // TODO: Add choice for Neutron and add fields there instead of at the root of matches
   //augment "/ietf-acl:access-lists/ietf-acl:access-list/ietf-acl:access-list-entries/ietf-acl:access-list-entry/ietf-acl:matches" {
     augment "/ietf-acl:access-lists/ietf-acl:acl/ietf-acl:access-list-entries/ietf-acl:ace/ietf-acl:matches" {
         description "Neutron network uuid";
@@ -20,11 +19,16 @@ module netvirt-sfc-acl {
         }
     }
 
-    // TODO: Add choice for Neutron and add fields there instead of at the root of matches
     augment "/ietf-acl:access-lists/ietf-acl:acl/ietf-acl:access-list-entries/ietf-acl:ace/ietf-acl:actions" {
-        description "Redirect traffic to SFC identified by SFC Path ID";
+        description "Redirect traffic to SFC identified by either SFC, SFP or RSP";
         ext:augment-identifier "redirect-to-sfc";
-        leaf redirect-sfc {
+        leaf sfc-name {
+            type string;
+        }
+        leaf sfp-name {
+            type string;
+        }
+        leaf rsp-name {
             type string;
         }
     }
index ba405df726bf5fa56275456d900688f4c5268b6d..684d59a55fb868a9aad0b34cb11d748f57a384a3 100644 (file)
@@ -130,22 +130,6 @@ and is available at http://www.eclipse.org/legal/epl-v10.html INTERNAL
       <type>xml</type>
       <scope>runtime</scope>
     </dependency>
-    <dependency>
-      <groupId>org.opendaylight.sfc</groupId>
-      <artifactId>features-sfc-ovs</artifactId>
-      <version>${sfc.version}</version>
-      <classifier>features</classifier>
-      <type>xml</type>
-      <scope>runtime</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.opendaylight.sfc</groupId>
-      <artifactId>features-sfcofl2</artifactId>
-      <version>${sfc.version}</version>
-      <classifier>features</classifier>
-      <type>xml</type>
-      <scope>runtime</scope>
-    </dependency>
     <dependency>
       <groupId>${project.groupId}</groupId>
       <artifactId>openstack.net-virt-sfc-impl</artifactId>
index dc73264661f7aed2efd1d5d082424ad56bfe96fb..cce550aa05e70bcfb09a3bffd79598a66e19c802 100644 (file)
@@ -10,21 +10,19 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
 <features name="odl-ovsdb-sfc-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.2.0"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0">
-  <repository>mvn:org.opendaylight.controller/features-mdsal/${mdsal.version}/xml/features</repository>
-  <repository>mvn:org.opendaylight.dlux/features-dlux/${dlux.version}/xml/features</repository>
-  <repository>mvn:org.opendaylight.mdsal.model/features-mdsal-model/${mdsal.model.version}/xml/features</repository>
-  <repository>mvn:org.opendaylight.netconf/features-restconf/${restconf.version}/xml/features</repository>
-  <repository>mvn:org.opendaylight.openflowplugin/features-openflowplugin/${openflowplugin.version}/xml/features</repository>
-  <repository>mvn:org.opendaylight.openflowplugin/features-openflowplugin-extension/${openflowplugin.version}/xml/features</repository>
-  <repository>mvn:org.opendaylight.ovsdb/features-ovsdb/${project.version}/xml/features</repository>
-  <repository>mvn:org.opendaylight.ovsdb/southbound-features/${project.version}/xml/features</repository>
-  <repository>mvn:org.opendaylight.sfc/features-sfc/${sfc.version}/xml/features</repository>
-  <!--<repository>mvn:org.opendaylight.sfc/features-sfc-ovs/${sfc.version}/xml/features</repository>-->
-  <repository>mvn:org.opendaylight.sfc/features-sfcofl2/${sfc.version}/xml/features</repository>
-  <repository>mvn:org.opendaylight.yangtools/features-yangtools/${yangtools.version}/xml/features</repository>
+  <repository>mvn:org.opendaylight.controller/features-mdsal/{{VERSION}}/xml/features</repository>
+  <repository>mvn:org.opendaylight.dlux/features-dlux/{{VERSION}}/xml/features</repository>
+  <repository>mvn:org.opendaylight.mdsal.model/features-mdsal-model/{{VERSION}}/xml/features</repository>
+  <repository>mvn:org.opendaylight.netconf/features-restconf/{{VERSION}}/xml/features</repository>
+  <repository>mvn:org.opendaylight.openflowplugin/features-openflowplugin/{{VERSION}}/xml/features</repository>
+  <repository>mvn:org.opendaylight.openflowplugin/features-openflowplugin-extension/{{VERSION}}/xml/features</repository>
+  <repository>mvn:org.opendaylight.ovsdb/features-ovsdb/{{VERSION}}/xml/features</repository>
+  <repository>mvn:org.opendaylight.ovsdb/southbound-features/{{VERSION}}/xml/features</repository>
+  <repository>mvn:org.opendaylight.sfc/features-sfc/{{VERSION}}/xml/features</repository>
+  <repository>mvn:org.opendaylight.yangtools/features-yangtools/{{VERSION}}/xml/features</repository>
   <feature name='odl-ovsdb-sfc-api' version='${project.version}' description='OpenDaylight :: ovsdb-sfc :: api'>
     <feature version='${mdsal.model.version}'>odl-mdsal-models</feature>
-    <bundle>mvn:org.opendaylight.ovsdb/openstack.net-virt-sfc-api/${project.version}</bundle>
+    <bundle>mvn:org.opendaylight.ovsdb/openstack.net-virt-sfc-api/{{VERSION}}</bundle>
   </feature>
   <feature name='odl-ovsdb-sfc' version='${project.version}' description='OpenDaylight :: ovsdb-sfc'>
     <feature version='${mdsal.version}'>odl-mdsal-broker</feature>
@@ -36,10 +34,10 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
     <feature version='${sfc.version}'>odl-sfc-provider</feature>
     <feature version='${sfc.version}'>odl-sfcofl2</feature>
     <feature version='${project.version}'>odl-ovsdb-sfc-api</feature>
-    <bundle>mvn:org.opendaylight.ovsdb/utils.mdsal-utils/${project.version}</bundle>
-    <bundle>mvn:org.opendaylight.ovsdb/utils.servicehelper/${project.version}</bundle>
-    <bundle>mvn:org.opendaylight.ovsdb/openstack.net-virt-sfc-impl/${project.version}</bundle>
-    <configfile finalname="${configfile.directory}/openstack.net-virt-sfc.xml">mvn:org.opendaylight.ovsdb/openstack.net-virt-sfc-impl/${project.version}/xml/config</configfile>
+    <bundle>mvn:org.opendaylight.ovsdb/utils.mdsal-utils/{{VERSION}}</bundle>
+    <bundle>mvn:org.opendaylight.ovsdb/utils.servicehelper/{{VERSION}}</bundle>
+    <bundle>mvn:org.opendaylight.ovsdb/openstack.net-virt-sfc-impl/{{VERSION}}</bundle>
+    <configfile finalname="${configfile.directory}/openstack.net-virt-sfc.xml">mvn:org.opendaylight.ovsdb/openstack.net-virt-sfc-impl/{{VERSION}}/xml/config</configfile>
   </feature>
   <feature name='odl-ovsdb-sfc-rest' version='${project.version}' description='OpenDaylight :: ovsdb-sfc :: REST'>
     <feature version="${project.version}">odl-ovsdb-sfc</feature>
index 9dd3154362cc4931297cf5646899143e490bb89a..0f8b724bd82a9b68cf191587670c64fafdd27370 100644 (file)
@@ -12,8 +12,8 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
   xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0">
   <repository>mvn:org.opendaylight.ovsdb/openstack.net-virt-sfc-features/1.2.1-SNAPSHOT/xml/features</repository>
   <feature name='odl-ovsdb-sfc-test' version='${project.version}' description='OpenDaylight :: ovsdb-sfc-test'>
-    <bundle>mvn:org.opendaylight.ovsdb/utils.mdsal-utils/${project.version}</bundle>
-    <bundle>mvn:org.opendaylight.ovsdb/utils.southbound-utils/${project.version}</bundle>
+    <bundle>mvn:org.opendaylight.ovsdb/utils.mdsal-utils/{{VERSION}}</bundle>
+    <bundle>mvn:org.opendaylight.ovsdb/utils.southbound-utils/{{VERSION}}</bundle>
     <feature version='${project.version}'>odl-ovsdb-sfc-ui</feature>
   </feature>
 </features>
index 21cdee3e26f5c434e1b77584853e5ef735b07d79..27c3ab73097acb581025a68ff1aa9b0227f6262c 100644 (file)
@@ -178,6 +178,11 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
       <version>${sonar-jacoco-listeners.version}</version>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.mdsal.model</groupId>
+      <artifactId>iana-if-type-2014-05-08</artifactId>
+      <version>2014.05.08.8-SNAPSHOT</version>
+    </dependency>
   </dependencies>
 
   <build>
index 806e7c6387afdb8c5d44b9b5ee05c0de52d9d365..008339eda43e0822c9b72ad87ec6c68ab592b9d5 100644 (file)
@@ -21,8 +21,11 @@ public interface ISfcClassifierService {
     void programEgressClassifier1(long dataPathId, long vxGpeOfPort, long nsp, short nsi,
                                   int tunnelOfPort, int tunnelId, short gotoTableId, boolean write);
 
-    void programEgressClassifier2(long dataPathId, long vxGpeOfPort, long nsp, short nsi,
-                                  int tunnelOfPort, int tunnelId, boolean write);
+    void programEgressClassifier(long dataPathId, long vxGpeOfPort, long nsp, short nsi,
+                                 long sfOfPort, int tunnelId, boolean write);
+
+    void programEgressClassifierBypass(long dataPathId, long vxGpeOfPort, long nsp, short nsi,
+                                       long sfOfPort, int tunnelId, boolean write);
 
     void program_sfEgress(long dataPathId, int dstPort, boolean write);
 
index 3983fa125086fbdd98c4f64d927ef8d2f026bf91..40b8172393e41608418dae976913283d6b736b11 100644 (file)
@@ -20,10 +20,12 @@ import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev1407
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.ServiceFunctions;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.service.functions.ServiceFunction;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.service.functions.ServiceFunctionKey;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.ServiceFunctionForwarder;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.ServiceFunctionPaths;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.service.function.paths.ServiceFunctionPath;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sl.rev140701.data.plane.locator.locator.type.Ip;
 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.inet.types.rev100924.PortNumber;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.Classifiers;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
@@ -55,6 +57,10 @@ public class SfcUtils {
                 .child(ServiceFunction.class, new ServiceFunctionKey(SfName.getDefaultInstance(sfName))).build();
     }
 
+    public RenderedServicePath getRsp(String rspName) {
+        return mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, getRspId(rspName));
+    }
+
     public RenderedServicePath getRspforSfp(String sfpName) {
         RenderedServicePath rspFound = null;
         RenderedServicePaths rsps = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, this.getRspsId());
@@ -83,7 +89,7 @@ public class SfcUtils {
         return sfpFound;
     }
 
-    public IpAddress getSfIp(String sfname) {
+    public IpAddress getSfIpAddress(String sfname) {
         ServiceFunction serviceFunction =
                 SfcProviderServiceFunctionAPI.readServiceFunction(SfName.getDefaultInstance(sfname));
 
@@ -92,10 +98,10 @@ public class SfcUtils {
             return null;
         }
 
-        return getSfIp(serviceFunction);
+        return getSfIpAddress(serviceFunction);
     }
 
-    public IpAddress getSfIp(ServiceFunction serviceFunction) {
+    public IpAddress getSfIpAddress(ServiceFunction serviceFunction) {
         if (serviceFunction == null) {
             LOG.info("getSfIp: Servicefunction is null");
             return null;
@@ -105,6 +111,25 @@ public class SfcUtils {
         return ipLocator.getIp();
     }
 
+    public PortNumber getSfPort(ServiceFunction serviceFunction) {
+        if (serviceFunction == null) {
+            LOG.info("getSfIp: Servicefunction is null");
+            return null;
+        }
+
+        Ip ipLocator = (Ip) serviceFunction.getSfDataPlaneLocator().get(0).getLocatorType();
+        return ipLocator.getPort();
+    }
+
+    public Ip getSfIp(ServiceFunction serviceFunction) {
+        if (serviceFunction == null) {
+            LOG.info("getSfIp: Servicefunction is null");
+            return null;
+        }
+
+        return (Ip)serviceFunction.getSfDataPlaneLocator().get(0).getLocatorType();
+    }
+
     public String getSfDplName(ServiceFunction serviceFunction) {
         String sfDplName = null;
         if (serviceFunction == null) {
@@ -115,4 +140,13 @@ public class SfcUtils {
         sfDplName = serviceFunction.getSfDataPlaneLocator().get(0).getName().getValue();
         return sfDplName;
     }
+
+    public Ip getSffIp(ServiceFunctionForwarder serviceFunctionForwarder) {
+        if (serviceFunctionForwarder == null) {
+            LOG.info("getSfIp: ServicefunctionForwarder is null");
+            return null;
+        }
+
+        return (Ip)serviceFunctionForwarder.getSffDataPlaneLocator().get(0).getDataPlaneLocator().getLocatorType();
+    }
 }
index 7cfcf6c96edc5ecce118f7fd5f7a310a045a0c0f..77ec178f65f50b943b8b98c53a8c5e1d588e3c64 100644 (file)
@@ -154,59 +154,16 @@ public class NetvirtSfcStandaloneOF13Provider implements INetvirtSfcOF13Provider
             return;
         }
 
-        RedirectToSfc sfcRedirect = entry.getActions().getAugmentation(RedirectToSfc.class);
-        LOG.debug("Processing ACL entry = {} sfcRedirect = {}", entry.getRuleName(), sfcRedirect);
-        if (sfcRedirect == null) {
-            LOG.warn("processAClEntry: sfcRedirect is null");
-            return;
-        }
-
-        String sfcName = sfcRedirect.getRedirectSfc();
-        LOG.debug("Processing Redirect to SFC = {}", sfcRedirect.getRedirectSfc());
-        ServiceFunctionPath sfp = getSfp(sfcName);
-        if (sfp == null || sfp.getName() == null) {
-            LOG.warn("There is no configured SFP with sfcName = {}; so skip installing the ACL entry!!", sfcName);
-            return;
-        }
-
-        LOG.debug("Processing Redirect to SFC = {}, SFP = {}", sfcRedirect.getRedirectSfc(), sfp);
-        // If RSP doesn't exist, create an RSP.
-        String sfpName = sfp.getName().getValue();
-        RenderedServicePath rsp = getRspforSfp(sfpName);
-        String rspName = sfp.getName().getValue() + "_rsp";
+        RenderedServicePath rsp = getRenderedServicePath(entry);
         if (rsp == null) {
-            LOG.info("No configured RSP corresponding to SFP = {}, Creating new RSP = {}", sfpName, rspName);
-            CreateRenderedPathInput rspInput = new CreateRenderedPathInputBuilder()
-                    .setParentServiceFunctionPath(sfpName)
-                    .setName(rspName)
-                    .setSymmetric(sfp.isSymmetric())
-                    .build();
-            rsp = SfcProviderRenderedPathAPI.createRenderedServicePathAndState(sfp, rspInput);
-            if (rsp == null) {
-                LOG.warn("failed to add RSP");
-                return;
-            }
-
-            // If SFP is symmetric, create RSP in the reverse direction.
-            if (sfp.isSymmetric()) {
-                LOG.info("SFP = {} is symmetric, installing RSP in the reverse direction!!", sfpName);
-                String rspNameRev = rspName + "-Reverse";
-                RenderedServicePath rspReverse = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL,
-                                                             this.getRspId(rspNameRev));
-                if (rspReverse == null) {
-                    rspReverse = SfcProviderRenderedPathAPI.createSymmetricRenderedServicePathAndState(rsp);
-                    if (rspReverse == null) {
-                        LOG.warn("failed to add reverse RSP");
-                        return;
-                    }
-                }
-            }
+            LOG.warn("Failed to get renderedServicePatch for entry: {}", entry);
+            return;
         }
 
         LOG.info("processAclEntry: RSP: {}", rsp);
         List<RenderedServicePathHop> pathHopList = rsp.getRenderedServicePathHop();
         if (pathHopList.isEmpty()) {
-            LOG.warn("Service Path = {} has empty hops!!", sfpName);
+            LOG.warn("Service Path = {} has empty hops!!", rsp.getName());
             return;
         }
 
@@ -235,10 +192,10 @@ public class NetvirtSfcStandaloneOF13Provider implements INetvirtSfcOF13Provider
                 // Find the first Hop within an RSP.
                 // The classifier flow needs to send all matched traffic to this first hop SFF.
                 RenderedServicePathFirstHop firstRspHop = SfcProviderRenderedPathAPI
-                        .readRenderedServicePathFirstHop(new RspName(rspName));
+                        .readRenderedServicePathFirstHop(new RspName(rsp.getName()));
 
                 LOG.debug("First Hop IPAddress = {}, Port = {}", firstRspHop.getIp().getIpv4Address().getValue(),
-                        firstRspHop.getPort().getValue().intValue());
+                        firstRspHop.getPort().getValue());
 
                 NshUtils nshHeader = new NshUtils();
                 // C1 is the normal overlay dest ip and c2 is the vnid
@@ -299,6 +256,81 @@ public class NetvirtSfcStandaloneOF13Provider implements INetvirtSfcOF13Provider
         }
     }
 
+    private RenderedServicePath getRenderedServicePath (Ace entry) {
+        RenderedServicePath rsp = null;
+        RedirectToSfc sfcRedirect = entry.getActions().getAugmentation(RedirectToSfc.class);
+        LOG.debug("Processing ACL entry = {} sfcRedirect = {}", entry.getRuleName(), sfcRedirect);
+        if (sfcRedirect == null) {
+            LOG.warn("processAClEntry: sfcRedirect is null");
+            return null;
+        }
+
+        if (sfcRedirect.getRspName() != null) {
+            rsp = getRenderedServicePathFromRsp(sfcRedirect.getRspName());
+        } else if (sfcRedirect.getSfpName() != null) {
+            LOG.warn("getRenderedServicePath: sfp not handled yet");
+        } else {
+            rsp = getRenderedServicePathFromSfc(entry);
+        }
+        LOG.info("getRenderedServicePath: rsp: {}", rsp);
+        return rsp;
+    }
+
+    private RenderedServicePath getRenderedServicePathFromRsp(String rspName) {
+        return null;//getRsp(rspName);
+    }
+
+    private RenderedServicePath getRenderedServicePathFromSfc (Ace entry) {
+        RedirectToSfc sfcRedirect = entry.getActions().getAugmentation(RedirectToSfc.class);
+        LOG.debug("Processing ACL entry = {} sfcRedirect = {}", entry.getRuleName(), sfcRedirect);
+        if (sfcRedirect == null) {
+            LOG.warn("processAClEntry: sfcRedirect is null");
+            return null;
+        }
+
+        String sfcName = sfcRedirect.getSfcName();
+        ServiceFunctionPath sfp = getSfp(sfcName);
+        if (sfp == null || sfp.getName() == null) {
+            LOG.warn("There is no configured SFP with sfcName = {}; so skip installing the ACL entry!!", sfcName);
+            return null;
+        }
+
+        LOG.debug("Processing Redirect to SFC = {}, SFP = {}", sfcName, sfp);
+        // If RSP doesn't exist, create an RSP.
+        String sfpName = sfp.getName().getValue();
+        RenderedServicePath rsp = getRspforSfp(sfpName);
+        String rspName = sfp.getName().getValue() + "_rsp";
+        if (rsp == null) {
+            LOG.info("No configured RSP corresponding to SFP = {}, Creating new RSP = {}", sfpName, rspName);
+            CreateRenderedPathInput rspInput = new CreateRenderedPathInputBuilder()
+                    .setParentServiceFunctionPath(sfpName)
+                    .setName(rspName)
+                    .setSymmetric(sfp.isSymmetric())
+                    .build();
+            rsp = SfcProviderRenderedPathAPI.createRenderedServicePathAndState(sfp, rspInput);
+            if (rsp == null) {
+                LOG.warn("failed to add RSP");
+                return null;
+            }
+
+            // If SFP is symmetric, create RSP in the reverse direction.
+            if (sfp.isSymmetric()) {
+                LOG.info("SFP = {} is symmetric, installing RSP in the reverse direction!!", sfpName);
+                String rspNameRev = rspName + "-Reverse";
+                RenderedServicePath rspReverse = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL,
+                        getRspId(rspNameRev));
+                if (rspReverse == null) {
+                    rspReverse = SfcProviderRenderedPathAPI.createSymmetricRenderedServicePathAndState(rsp);
+                    if (rspReverse == null) {
+                        LOG.warn("failed to add reverse RSP");
+                        return null;
+                    }
+                }
+            }
+        }
+        return rsp;
+    }
+
     private void handleLocalEgressPort(long dataPathId, String s, long localOfPort, short writeTable,
                                        short gotoTable, boolean write) {
 
index 7ebdd6dfcd1b095490e0141d22d44c38852f6e25..f725c24297291aefbacd94356a4cabdf0f293e3d 100644 (file)
@@ -55,7 +55,12 @@ public class SfcClassifierService extends AbstractServiceInstance implements Con
     }
 
     @Override
-    public void programEgressClassifier2(long dataPathId, long vxGpeOfPort, long nsp, short nsi, int tunnelOfPort, int tunnelId, boolean write) {
+    public void programEgressClassifier(long dataPathId, long vxGpeOfPort, long nsp, short nsi, long sfOfPort, int tunnelId, boolean write) {
+
+    }
+
+    @Override
+    public void programEgressClassifierBypass(long dataPathId, long vxGpeOfPort, long nsp, short nsi, long sfOfPort, int tunnelId, boolean write) {
 
     }
 
index 4d13ddb7e58a5f33b2851f4588ef43c79a9e7070..a69e801281e0794ac6c4e2f4502c8594e168e377 100644 (file)
@@ -14,24 +14,27 @@ 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.api.Constants;
 import org.opendaylight.ovsdb.openstack.netvirt.api.NodeCacheManager;
+import org.opendaylight.ovsdb.openstack.netvirt.api.OvsdbTables;
 import org.opendaylight.ovsdb.openstack.netvirt.api.Southbound;
 import org.opendaylight.ovsdb.openstack.netvirt.sfc.INetvirtSfcOF13Provider;
 import org.opendaylight.ovsdb.openstack.netvirt.sfc.ISfcClassifierService;
 import org.opendaylight.ovsdb.openstack.netvirt.sfc.NshUtils;
 import org.opendaylight.ovsdb.openstack.netvirt.sfc.SfcUtils;
-import org.opendaylight.ovsdb.openstack.netvirt.sfc.workaround.services.SfcClassifierService;
 import org.opendaylight.ovsdb.southbound.SouthboundConstants;
 import org.opendaylight.ovsdb.utils.mdsal.utils.MdsalUtils;
 import org.opendaylight.ovsdb.utils.servicehelper.ServiceHelper;
 import org.opendaylight.sfc.provider.api.SfcProviderRenderedPathAPI;
+import org.opendaylight.sfc.provider.api.SfcProviderServiceForwarderAPI;
 import org.opendaylight.sfc.provider.api.SfcProviderServiceFunctionAPI;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SfName;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sl.rev140701.data.plane.locator.locator.type.Ip;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.CreateRenderedPathInput;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.CreateRenderedPathInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.path.first.hop.info.RenderedServicePathFirstHop;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.paths.RenderedServicePath;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.paths.rendered.service.path.RenderedServicePathHop;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.service.functions.ServiceFunction;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.ServiceFunctionForwarder;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.service.function.paths.ServiceFunctionPath;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.Acl;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.access.list.entries.Ace;
@@ -45,6 +48,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.classifiers.classifier.bridges.Bridge;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.classifiers.classifier.sffs.Sff;
 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.OvsdbNodeAugmentation;
 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.port._interface.attributes.Options;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
@@ -66,6 +70,7 @@ public class NetvirtSfcWorkaroundOF13Provider implements INetvirtSfcOF13Provider
     private static final String VXGPE = "vxgpe";
     private static final String TUNNEL_DST = "192.168.120.31";
     private static final String TUNNEL_VNID = "10";
+    public static final String TUNNEL_ENDPOINT_KEY = "local_ip";
 
     public NetvirtSfcWorkaroundOF13Provider(final DataBroker dataBroker, MdsalUtils mdsalUtils, SfcUtils sfcUtils) {
         Preconditions.checkNotNull(dataBroker, "Input dataBroker cannot be NULL!");
@@ -134,7 +139,7 @@ public class NetvirtSfcWorkaroundOF13Provider implements INetvirtSfcOF13Provider
         handleRenderedServicePath(rsp, entry);
     }
 
-    private void handleRenderedServicePath(RenderedServicePath rsp, Ace entry) {
+    private void handleRenderedServicePathOld(RenderedServicePath rsp, Ace entry) {
         LOG.info("handleRenderedServicePath: RSP: {}", rsp);
 
         Matches matches = entry.getMatches();
@@ -180,7 +185,7 @@ public class NetvirtSfcWorkaroundOF13Provider implements INetvirtSfcOF13Provider
             LOG.info("handleRenderedServicePath: firstRspHop: {}", firstRspHop);
             LOG.debug("handleRenderedServicePath: First Hop IPAddress = {}, Port = {}",
                     firstRspHop.getIp().getIpv4Address().getValue(),
-                    firstRspHop.getPort().getValue().intValue());
+                    firstRspHop.getPort().getValue());
 
             NshUtils nshHeader = new NshUtils();
             nshHeader.setNshMetaC1(NshUtils.convertIpAddressToLong(new Ipv4Address(TUNNEL_DST)));
@@ -201,7 +206,7 @@ public class NetvirtSfcWorkaroundOF13Provider implements INetvirtSfcOF13Provider
             nshHeader.setNshNsi(firstHop.getServiceIndex());
             // workaround: bypass sff and got directly to sf
             //nshHeader.setNshTunIpDst(firstRspHop.getIp().getIpv4Address());
-            IpAddress sfIpAddress = sfcUtils.getSfIp(serviceFunction);
+            IpAddress sfIpAddress = sfcUtils.getSfIpAddress(serviceFunction);
             String sfDplName = sfcUtils.getSfDplName(serviceFunction);
             //sfcUtils.getSfIp(firstHop.getServiceFunctionName().getValue());
             nshHeader.setNshTunIpDst(sfIpAddress.getIpv4Address());
@@ -212,7 +217,6 @@ public class NetvirtSfcWorkaroundOF13Provider implements INetvirtSfcOF13Provider
                     nshHeader, vxGpeOfPort, true);
 
             sfcClassifierService.program_sfEgress(dataPathId, GPE_PORT, true);
-            //not needed if ip route and arp can be added to stack
             long sfOfPort = getSfPort(bridgeNode, sfDplName);
 
             String sfMac = getMacFromExternalIds(bridgeNode, sfDplName);
@@ -225,16 +229,180 @@ public class NetvirtSfcWorkaroundOF13Provider implements INetvirtSfcOF13Provider
             }
 
             short lastServiceindex = (short)((lastHop.getServiceIndex()).intValue() - 1);
-            sfcClassifierService.programEgressClassifier1(dataPathId, vxGpeOfPort, rsp.getPathId(),
-                    lastServiceindex, (int)sfOfPort, 0, (short)0, true);
-            sfcClassifierService.programEgressClassifier2(dataPathId, vxGpeOfPort, rsp.getPathId(),
-                    lastServiceindex, (int)sfOfPort, 0, true);
+            sfcClassifierService.programEgressClassifier(dataPathId, vxGpeOfPort, rsp.getPathId(),
+                    lastServiceindex, sfOfPort, 0, true);
+            sfcClassifierService.programEgressClassifierBypass(dataPathId, vxGpeOfPort, rsp.getPathId(),
+                    lastServiceindex, sfOfPort, 0, true);
 
             sfcClassifierService.programSfcTable(dataPathId, vxGpeOfPort, SFC_TABLE, true);
         }
     }
 
+    private void handleRenderedServicePath(RenderedServicePath rsp, Ace entry) {
+        LOG.info("handleRenderedServicePath: RSP: {}", rsp);
+
+        Matches matches = entry.getMatches();
+        if (matches == null) {
+            LOG.warn("processAclEntry: matches not found");
+            return;
+        }
+
+        List<RenderedServicePathHop> pathHopList = rsp.getRenderedServicePathHop();
+        if (pathHopList.isEmpty()) {
+            LOG.warn("handleRenderedServicePath: RSP {} has empty hops!!", rsp.getName());
+            return;
+        }
+        LOG.info("handleRenderedServicePath: pathHopList: {}", pathHopList);
+
+        RenderedServicePathFirstHop firstRspHop = SfcProviderRenderedPathAPI
+                .readRenderedServicePathFirstHop(rsp.getName());
+        LOG.info("handleRenderedServicePath: firstRspHop: {}", firstRspHop);
+
+        RenderedServicePathHop firstHop = pathHopList.get(0);
+        RenderedServicePathHop lastHop = pathHopList.get(pathHopList.size()-1);
+
+        final List<Node> bridgeNodes = nodeCacheManager.getBridgeNodes();
+        if (bridgeNodes == null || bridgeNodes.isEmpty()) {
+            LOG.warn("handleRenderedServicePath: There are no bridges to process");
+            return;
+        }
+        for (RenderedServicePathHop hop : pathHopList) {
+            for (Node bridgeNode : bridgeNodes) {
+                // ignore bridges other than br-int
+                OvsdbBridgeAugmentation ovsdbBridgeAugmentation = southbound.getBridge(bridgeNode, "br-int");
+                if (ovsdbBridgeAugmentation == null) {
+                    continue;
+                }
+                long vxGpeOfPort = getOFPort(bridgeNode, VXGPE);
+                if (vxGpeOfPort == 0L) {
+                    LOG.warn("programAclEntry: Could not identify gpe vtep {} -> OF ({}) on {}",
+                            VXGPE, vxGpeOfPort, bridgeNode);
+                    continue;
+                }
+                long dataPathId = southbound.getDataPathId(bridgeNode);
+                if (dataPathId == 0L) {
+                    LOG.warn("programAclEntry: Could not identify datapathId on {}", bridgeNode);
+                    continue;
+                }
+
+                ServiceFunction serviceFunction =
+                        SfcProviderServiceFunctionAPI.readServiceFunction(firstHop.getServiceFunctionName());
+                if (serviceFunction == null) {
+                    LOG.warn("programAclEntry: Could not identify ServiceFunction {} on {}",
+                            firstHop.getServiceFunctionName().getValue(), bridgeNode);
+                    continue;
+                }
+                ServiceFunctionForwarder serviceFunctionForwarder =
+                        SfcProviderServiceForwarderAPI
+                                .readServiceFunctionForwarder(hop.getServiceFunctionForwarder());
+                if (serviceFunctionForwarder == null) {
+                    LOG.warn("programAclEntry: Could not identify ServiceFunctionForwarder {} on {}",
+                            firstHop.getServiceFunctionName().getValue(), bridgeNode);
+                    continue;
+                }
+
+                handleSf(bridgeNode, serviceFunction);
+                handleSff(bridgeNode, serviceFunctionForwarder, serviceFunction, hop, firstHop, lastHop,
+                        entry.getRuleName(), matches, vxGpeOfPort, rsp);
+                if (firstHop == lastHop) {
+                    handleSff(bridgeNode, serviceFunctionForwarder, serviceFunction, hop, null, lastHop,
+                            entry.getRuleName(), matches, vxGpeOfPort, rsp);
+                }
+            }
+        }
+    }
+
+    private void handleSff(Node bridgeNode, ServiceFunctionForwarder serviceFunctionForwarder,
+                           ServiceFunction serviceFunction,
+                           RenderedServicePathHop hop,
+                           RenderedServicePathHop firstHop,
+                           RenderedServicePathHop lastHop,
+                           String ruleName, Matches matches,
+                           long vxGpeOfPort, RenderedServicePath rsp) {
+        long dataPathId = southbound.getDataPathId(bridgeNode);
+
+        if (hop == firstHop) {
+            LOG.info("handleSff: first hop processing {} - {}",
+                    bridgeNode.getNodeId(), serviceFunctionForwarder.getName());
+            NshUtils nshHeader = new NshUtils();
+            nshHeader.setNshNsp(rsp.getPathId());
+            nshHeader.setNshNsi(firstHop.getServiceIndex());
+            if (isSffOnBridge(bridgeNode, serviceFunctionForwarder)) {
+                LOG.info("handleSff: sff and bridge are the same: {} - {}, skipping first sff",
+                        bridgeNode.getNodeId(), serviceFunctionForwarder.getName());
+                Ip ip = sfcUtils.getSfIp(serviceFunction);
+                nshHeader.setNshTunIpDst(ip.getIp().getIpv4Address());
+                nshHeader.setNshTunUdpPort(ip.getPort());
+            } else {
+                LOG.info("handleSff: sff and bridge are not the same: {} - {}, sending to first sff",
+                        bridgeNode.getNodeId(), serviceFunctionForwarder.getName());
+                Ip ip = sfcUtils.getSffIp(serviceFunctionForwarder);
+                nshHeader.setNshTunIpDst(ip.getIp().getIpv4Address());
+                nshHeader.setNshTunUdpPort(ip.getPort());
+            }
+            sfcClassifierService.programIngressClassifier(dataPathId, ruleName, matches,
+                    nshHeader, vxGpeOfPort, true);
+        } else if (hop == lastHop) {
+            LOG.info("handleSff: last hop processing {} - {}",
+                    bridgeNode.getNodeId(), serviceFunctionForwarder.getName());
+            short lastServiceindex = (short)((lastHop.getServiceIndex()).intValue() - 1);
+            String sfDplName = sfcUtils.getSfDplName(serviceFunction);
+            long sfOfPort = getSfPort(bridgeNode, sfDplName);
+            sfcClassifierService.programEgressClassifier(dataPathId, vxGpeOfPort, rsp.getPathId(),
+                    lastServiceindex, sfOfPort, 0, true);
+            sfcClassifierService.programEgressClassifierBypass(dataPathId, vxGpeOfPort, rsp.getPathId(),
+                    lastServiceindex, sfOfPort, 0, true);
+        } else {
+            // add typical sff flows
+        }
+
+        sfcClassifierService.programSfcTable(dataPathId, vxGpeOfPort, SFC_TABLE, true);
+    }
+
+    void handleSf(Node bridgeNode, ServiceFunction serviceFunction) {
+        if (isSfOnBridge(bridgeNode, serviceFunction)) {
+            LOG.info("handleSf: sf and bridge are on the same node: {} - {}, adding workaround and arp",
+                    bridgeNode.getNodeId(), serviceFunction.getName());
+            long dataPathId = southbound.getDataPathId(bridgeNode);
+            Ip ip = sfcUtils.getSfIp(serviceFunction);
+            String sfIpAddr = String.valueOf(ip.getIp().getValue());
+            int sfIpPort = ip.getPort().getValue(); //GPE_PORT
+            String sfDplName = sfcUtils.getSfDplName(serviceFunction);
+            long sfOfPort = getSfPort(bridgeNode, sfDplName);
+            String sfMac = getMacFromExternalIds(bridgeNode, sfDplName);
+            if (sfMac == null) {
+                LOG.warn("handleSff: could not find mac for {} on {}", sfDplName, bridgeNode);
+                return;
+            }
+            //should be sffdplport, but they should all be the same 6633/4790
+            sfcClassifierService.program_sfEgress(dataPathId, sfIpPort, true);
+            sfcClassifierService.program_sfIngress(dataPathId, sfIpPort, sfOfPort, sfIpAddr, sfDplName, true);
+            sfcClassifierService.programStaticArpEntry(dataPathId, 0L, sfMac, sfIpAddr, true);
+        }
+    }
+
+    private boolean isSffOnBridge(Node bridgeNode, ServiceFunctionForwarder serviceFunctionForwarder) {
+        String local_ip = "";
+        Ip ip = sfcUtils.getSffIp(serviceFunctionForwarder);
+        Node ovsdbNode = southbound.readOvsdbNode(bridgeNode);
+        if (ovsdbNode != null) {
+            OvsdbNodeAugmentation ovsdbNodeAugmentation = ovsdbNode.getAugmentation(OvsdbNodeAugmentation.class);
+            if (ovsdbNodeAugmentation != null && ovsdbNodeAugmentation.getOpenvswitchOtherConfigs() != null) {
+                southbound.getOtherConfig(ovsdbNode, OvsdbTables.OPENVSWITCH, TUNNEL_ENDPOINT_KEY);
+            }
+
+        }
+        return local_ip.equals(String.valueOf(ip.getIp().getValue()));
+    }
+
+    private boolean isSfOnBridge(Node bridgeNode, ServiceFunction serviceFunction) {
+        String sfDplName = sfcUtils.getSfDplName(serviceFunction);
+        long sfOfPort = getSfPort(bridgeNode, sfDplName);
+        return sfOfPort != 0L;
+    }
+
     private RenderedServicePath getRenderedServicePath (Ace entry) {
+        RenderedServicePath rsp = null;
         RedirectToSfc sfcRedirect = entry.getActions().getAugmentation(RedirectToSfc.class);
         LOG.debug("Processing ACL entry = {} sfcRedirect = {}", entry.getRuleName(), sfcRedirect);
         if (sfcRedirect == null) {
@@ -242,14 +410,37 @@ public class NetvirtSfcWorkaroundOF13Provider implements INetvirtSfcOF13Provider
             return null;
         }
 
-        String sfcName = sfcRedirect.getRedirectSfc();
+        if (sfcRedirect.getRspName() != null) {
+            rsp = getRenderedServicePathFromRsp(sfcRedirect.getRspName());
+        } else if (sfcRedirect.getSfpName() != null) {
+            LOG.warn("getRenderedServicePath: sfp not handled yet");
+        } else {
+            rsp = getRenderedServicePathFromSfc(entry);
+        }
+        LOG.info("getRenderedServicePath: rsp: {}", rsp);
+        return rsp;
+    }
+
+    private RenderedServicePath getRenderedServicePathFromRsp(String rspName) {
+        return sfcUtils.getRsp(rspName);
+    }
+
+    private RenderedServicePath getRenderedServicePathFromSfc (Ace entry) {
+        RedirectToSfc sfcRedirect = entry.getActions().getAugmentation(RedirectToSfc.class);
+        LOG.debug("Processing ACL entry = {} sfcRedirect = {}", entry.getRuleName(), sfcRedirect);
+        if (sfcRedirect == null) {
+            LOG.warn("processAClEntry: sfcRedirect is null");
+            return null;
+        }
+
+        String sfcName = sfcRedirect.getSfcName();
         ServiceFunctionPath sfp = sfcUtils.getSfp(sfcName);
         if (sfp == null || sfp.getName() == null) {
             LOG.warn("There is no configured SFP with sfcName = {}; so skip installing the ACL entry!!", sfcName);
             return null;
         }
 
-        LOG.debug("Processing Redirect to SFC = {}, SFP = {}", sfcRedirect.getRedirectSfc(), sfp);
+        LOG.debug("Processing Redirect to SFC = {}, SFP = {}", sfcName, sfp);
         // If RSP doesn't exist, create an RSP.
         String sfpName = sfp.getName().getValue();
         RenderedServicePath rsp = sfcUtils.getRspforSfp(sfpName);
@@ -293,7 +484,8 @@ public class NetvirtSfcWorkaroundOF13Provider implements INetvirtSfcOF13Provider
         List<OvsdbTerminationPointAugmentation> ovsdbTerminationPointAugmentations =
                 southbound.getTerminationPointsOfBridge(bridgeNode);
         if (!ovsdbTerminationPointAugmentations.isEmpty()) {
-            for (OvsdbTerminationPointAugmentation terminationPointAugmentation : ovsdbTerminationPointAugmentations) {
+            for (OvsdbTerminationPointAugmentation terminationPointAugmentation :
+                    ovsdbTerminationPointAugmentations) {
                 if (terminationPointAugmentation.getInterfaceType() ==
                         SouthboundConstants.OVSDB_INTERFACE_TYPE_MAP.get(NETWORK_TYPE_VXLAN)) {
                     if (!terminationPointAugmentation.getName().equals(vxGpePortName)) {
@@ -314,7 +506,8 @@ public class NetvirtSfcWorkaroundOF13Provider implements INetvirtSfcOF13Provider
 
     private long getOFPort(Node bridgeNode, String portName) {
         long ofPort = 0L;
-        OvsdbTerminationPointAugmentation port = southbound.extractTerminationPointAugmentation(bridgeNode, portName);
+        OvsdbTerminationPointAugmentation port =
+                southbound.extractTerminationPointAugmentation(bridgeNode, portName);
         if (port != null) {
             ofPort = southbound.getOFPort(port);
         }
@@ -360,7 +553,7 @@ public class NetvirtSfcWorkaroundOF13Provider implements INetvirtSfcOF13Provider
 
     private String getMacFromExternalIds(Node bridgeNode, String portName) {
         String mac = null;
-        OvsdbTerminationPointAugmentation port = southbound.extractTerminationPointAugmentation(bridgeNode, portName);
+        OvsdbTerminationPointAugmentation port = southbound.getTerminationPointOfBridge(bridgeNode, portName);
         LOG.info("getMac: portName: {}, bridgeNode: {},,, port: {}", portName, bridgeNode, port);
         if (port != null && port.getInterfaceExternalIds() != null) {
             mac = southbound.getInterfaceExternalIdsValue(port, Constants.EXTERNAL_ID_VM_MAC);
index c597e5eb22d815f1364f22ef6ed3d2f45688269e..947dcec1f3d8211f94d7796df07e0985a468745f 100644 (file)
@@ -45,6 +45,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instru
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
 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.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxRegCaseBuilder;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceReference;
 import org.slf4j.Logger;
@@ -54,14 +55,26 @@ public class SfcClassifierService extends AbstractServiceInstance implements Con
     private static final Logger LOG = LoggerFactory.getLogger(SfcClassifierService.class);
     private static final short TABLE_0 = 0;
     private static final short UDP_SHORT = 17;
-    private static int cookieCounter = 0;
-    private static final int FLOW_INGRESSCLASS = 1;
-    private static final int FLOW_SFINGRESS = 2;
-    private static final int FLOW_SFEGRESS = 3;
-    private static final int FLOW_SFARP = 4;
-    private static final int FLOW_EGRESSCLASS1 = 5;
-    private static final int FLOW_EGRESSCLASS2 = 6;
-    private static final int FLOW_SFCTABLE = 7;
+    static int cookieIndex = 0;
+
+    private enum FlowID {
+        FLOW_INGRESSCLASS(1), FLOW_SFINGRESS(2), FLOW_SFEGRESS(3), FLOW_SFARP(4),
+        FLOW_EGRESSCLASSUNUSED(5), FLOW_EGRESSCLASS(6), FLOW_EGRESSCLASSBYPASS(7), FLOW_SFCTABLE(8);
+
+        private int value;
+        FlowID(int value) {
+            this.value = value;
+        }
+
+    }
+
+    //private AtomicLong flowCookieInc = new AtomicLong(0x1L);
+    private BigInteger getCookie(FlowID flowID) {
+        String cookieString = new String().format("1110%02d%010d", flowID.value, cookieIndex++);
+                //new String().format("1100%02d00%04d", flowID.value, flowCookieInc.getAndIncrement());
+                // "1100%02000000d%04d"
+        return new BigInteger(cookieString, 16);
+    }
 
     public SfcClassifierService(Service service) {
         super(service);
@@ -79,11 +92,6 @@ public class SfcClassifierService extends AbstractServiceInstance implements Con
     @Override
     public void setDependencies(Object impl) {}
 
-    private BigInteger getCookie(int index) {
-        String indexString = new String().format("%02d0000000000%04d", index, cookieCounter++);
-        return new BigInteger(indexString, 16);
-    }
-
     @Override
     public void programIngressClassifier(long dataPathId, String ruleName, Matches matches,
                                          NshUtils nshHeader, long vxGpeOfPort, boolean write) {
@@ -91,10 +99,11 @@ public class SfcClassifierService extends AbstractServiceInstance implements Con
         FlowBuilder flowBuilder = new FlowBuilder();
 
         MatchBuilder matchBuilder = buildMatch(matches);
-        //flowBuilder.setMatch(matchBuilder.build());
-        flowBuilder.setMatch(MatchUtils.addNxRegMatch(
-                matchBuilder,
-                new MatchUtils.RegMatch(FlowUtils.REG_FIELD, FlowUtils.REG_VALUE_FROM_LOCAL)).build());
+        MatchUtils.addNxRegMatch(matchBuilder,
+                MatchUtils.RegMatch.of(FlowUtils.REG_FIELD, FlowUtils.REG_VALUE_FROM_LOCAL));
+        MatchUtils.addNxRegMatch(matchBuilder,
+                MatchUtils.RegMatch.of(FlowUtils.REG_FIELD, FlowUtils.REG_VALUE_FROM_LOCAL));
+        flowBuilder.setMatch(matchBuilder.build());
 
         String flowId = "sfcIngressClass_" + ruleName;// + "_" + nshHeader.getNshNsp();
         flowBuilder.setId(new FlowId(flowId));
@@ -105,8 +114,7 @@ public class SfcClassifierService extends AbstractServiceInstance implements Con
         flowBuilder.setFlowName(flowId);
         flowBuilder.setHardTimeout(0);
         flowBuilder.setIdleTimeout(0);
-        flowBuilder.setCookie(new FlowCookie(getCookie(FLOW_INGRESSCLASS)));
-        flowBuilder.setCookieMask(new FlowCookie(getCookie(FLOW_INGRESSCLASS)));
+        flowBuilder.setCookie(new FlowCookie(getCookie(FlowID.FLOW_INGRESSCLASS)));
 
         if (write) {
             ActionBuilder ab = new ActionBuilder();
@@ -149,7 +157,8 @@ public class SfcClassifierService extends AbstractServiceInstance implements Con
         FlowBuilder flowBuilder = new FlowBuilder();
 
         MatchBuilder matchBuilder = new MatchBuilder();
-        flowBuilder.setMatch(MatchUtils.createInPortMatch(matchBuilder, dataPathId, vxGpeOfPort).build());
+        MatchUtils.createInPortMatch(matchBuilder, dataPathId, vxGpeOfPort);
+        flowBuilder.setMatch(matchBuilder.build());
 
         String flowId = "sfcTable_" + vxGpeOfPort;
         flowBuilder.setId(new FlowId(flowId));
@@ -161,8 +170,8 @@ public class SfcClassifierService extends AbstractServiceInstance implements Con
         flowBuilder.setHardTimeout(0);
         flowBuilder.setIdleTimeout(0);
         flowBuilder.setPriority(1000);
-        flowBuilder.setCookie(new FlowCookie(getCookie(FLOW_SFCTABLE)));
-        flowBuilder.setCookieMask(new FlowCookie(getCookie(FLOW_SFCTABLE)));
+        flowBuilder.setCookie(new FlowCookie(getCookie(FlowID.FLOW_SFCTABLE)));
+        flowBuilder.setCookieMask(new FlowCookie(getCookie(FlowID.FLOW_SFCTABLE)));
 
         if (write) {
             InstructionsBuilder isb = new InstructionsBuilder();
@@ -190,7 +199,8 @@ public class SfcClassifierService extends AbstractServiceInstance implements Con
         MatchBuilder matchBuilder = new MatchBuilder();
         MatchUtils.createInPortMatch(matchBuilder, dataPathId, vxGpeOfPort);
         MatchUtils.addNxNspMatch(matchBuilder, nsp);
-        flowBuilder.setMatch(MatchUtils.addNxNsiMatch(matchBuilder, nsi).build());
+        MatchUtils.addNxNsiMatch(matchBuilder, nsi);
+        flowBuilder.setMatch(matchBuilder.build());
 
         String flowId = "sfcEgressClass1_" + vxGpeOfPort;
         flowBuilder.setId(new FlowId(flowId));
@@ -201,8 +211,8 @@ public class SfcClassifierService extends AbstractServiceInstance implements Con
         flowBuilder.setFlowName(flowId);
         flowBuilder.setHardTimeout(0);
         flowBuilder.setIdleTimeout(0);
-        flowBuilder.setCookie(new FlowCookie(getCookie(FLOW_EGRESSCLASS1)));
-        flowBuilder.setCookieMask(new FlowCookie(getCookie(FLOW_EGRESSCLASS1)));
+        flowBuilder.setCookie(new FlowCookie(getCookie(FlowID.FLOW_EGRESSCLASSUNUSED)));
+        flowBuilder.setCookieMask(new FlowCookie(getCookie(FlowID.FLOW_EGRESSCLASSUNUSED)));
 
         if (write) {
             InstructionsBuilder isb = new InstructionsBuilder();
@@ -238,31 +248,29 @@ public class SfcClassifierService extends AbstractServiceInstance implements Con
         }
     }
 
-    // add 3: same match, add in_port sf, priority=40k, move c2 to tun_id, reg0-1, nsp=0,nsi=0
     @Override
-    public void programEgressClassifier2(long dataPathId, long vxGpeOfPort, long nsp, short nsi,
-                                         int tunnelOfPort, int tunnelId, boolean write) {
+    public void programEgressClassifier(long dataPathId, long vxGpeOfPort, long nsp, short nsi,
+                                        long sfOfPort, int tunnelId, boolean write) {
         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dataPathId);
         FlowBuilder flowBuilder = new FlowBuilder();
 
         MatchBuilder matchBuilder = new MatchBuilder();
         MatchUtils.createInPortMatch(matchBuilder, dataPathId, vxGpeOfPort);
-        MatchUtils.addNxRegMatch(matchBuilder,
-                new MatchUtils.RegMatch(FlowUtils.REG_FIELD, FlowUtils.REG_VALUE_FROM_LOCAL)).build();
         MatchUtils.addNxNspMatch(matchBuilder, nsp);
-        flowBuilder.setMatch(MatchUtils.addNxNsiMatch(matchBuilder, nsi).build());
+        MatchUtils.addNxNsiMatch(matchBuilder, nsi);
+        flowBuilder.setMatch(matchBuilder.build());
 
-        String flowId = "sfcEgressClass2_" + vxGpeOfPort;
+        String flowId = "sfcEgressClass_" + nsp + "_" + + nsi + "_"  + vxGpeOfPort;
         flowBuilder.setId(new FlowId(flowId));
         FlowKey key = new FlowKey(new FlowId(flowId));
         flowBuilder.setBarrier(true);
-        flowBuilder.setTableId(getTable());
+        flowBuilder.setTableId(TABLE_0);
         flowBuilder.setKey(key);
         flowBuilder.setFlowName(flowId);
         flowBuilder.setHardTimeout(0);
         flowBuilder.setIdleTimeout(0);
-        flowBuilder.setCookie(new FlowCookie(getCookie(FLOW_EGRESSCLASS2)));
-        flowBuilder.setCookieMask(new FlowCookie(getCookie(FLOW_EGRESSCLASS2)));
+        flowBuilder.setCookie(new FlowCookie(getCookie(FlowID.FLOW_EGRESSCLASS)));
+        flowBuilder.setCookieMask(new FlowCookie(getCookie(FlowID.FLOW_EGRESSCLASS)));
 
         if (write) {
             InstructionsBuilder isb = new InstructionsBuilder();
@@ -271,13 +279,19 @@ public class SfcClassifierService extends AbstractServiceInstance implements Con
 
             ActionBuilder ab = new ActionBuilder();
 
-            // don't do this, need it to match on the resubmit side and get past table 10 so it isn't reclassified
-            //ab.setAction(ActionUtils.nxSetNspAction((long)(0)));
-            //ab.setOrder(0);
-            //ab.setKey(new ActionKey(0));
-            //actionList.add(ab.build());
+            ab.setAction(
+                    ActionUtils.nxLoadRegAction(new DstNxRegCaseBuilder().setNxReg(FlowUtils.REG_FIELD).build(),
+                    BigInteger.valueOf(FlowUtils.REG_VALUE_FROM_LOCAL)));
+            ab.setOrder(actionList.size());
+            ab.setKey(new ActionKey(actionList.size()));
+            actionList.add(ab.build());
+
+            ab.setAction(ActionUtils.nxMoveNshc2ToTunId());
+            ab.setOrder(actionList.size());
+            ab.setKey(new ActionKey(actionList.size()));
+            actionList.add(ab.build());
 
-            ab.setAction(ActionUtils.nxResubmitAction(tunnelOfPort, TABLE_0));
+            ab.setAction(ActionUtils.nxResubmitAction((int)sfOfPort, TABLE_0));
             ab.setOrder(actionList.size());
             ab.setKey(new ActionKey(actionList.size()));
             actionList.add(ab.build());
@@ -294,7 +308,51 @@ public class SfcClassifierService extends AbstractServiceInstance implements Con
             isb.setInstruction(instructions);
             flowBuilder.setInstructions(isb.build());
             writeFlow(flowBuilder, nodeBuilder);
+        } else {
+            removeFlow(flowBuilder, nodeBuilder);
+        }
+    }
+
+    @Override
+    public void programEgressClassifierBypass(long dataPathId, long vxGpeOfPort, long nsp, short nsi,
+                                              long sfOfPort, int tunnelId, boolean write) {
+        NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dataPathId);
+        FlowBuilder flowBuilder = new FlowBuilder();
+
+        MatchBuilder matchBuilder = new MatchBuilder();
+        MatchUtils.createInPortMatch(matchBuilder, dataPathId, sfOfPort);
+        MatchUtils.addNxRegMatch(matchBuilder,
+                MatchUtils.RegMatch.of(FlowUtils.REG_FIELD, FlowUtils.REG_VALUE_FROM_LOCAL));
+        MatchUtils.addNxNspMatch(matchBuilder, nsp);
+        MatchUtils.addNxNsiMatch(matchBuilder, nsi);
+        flowBuilder.setMatch(matchBuilder.build());
+
+        String flowId = "sfcEgressClassBypass_" + nsp + "_" + + nsi + "_"  + sfOfPort;
+        flowBuilder.setId(new FlowId(flowId));
+        FlowKey key = new FlowKey(new FlowId(flowId));
+        flowBuilder.setBarrier(true);
+        flowBuilder.setTableId(TABLE_0);
+        flowBuilder.setKey(key);
+        flowBuilder.setFlowName(flowId);
+        flowBuilder.setHardTimeout(0);
+        flowBuilder.setIdleTimeout(0);
+        flowBuilder.setCookie(new FlowCookie(getCookie(FlowID.FLOW_EGRESSCLASSBYPASS)));
+        flowBuilder.setCookieMask(new FlowCookie(getCookie(FlowID.FLOW_EGRESSCLASSBYPASS)));
+        flowBuilder.setPriority(40000); //Needs to be above default priority of 32768
+
+        if (write) {
+            InstructionsBuilder isb = new InstructionsBuilder();
+            List<Instruction> instructions = Lists.newArrayList();
+
+            InstructionBuilder ib;
+            ib = this.getMutablePipelineInstructionBuilder();
+            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);
         }
@@ -309,8 +367,9 @@ public class SfcClassifierService extends AbstractServiceInstance implements Con
         MatchBuilder matchBuilder = new MatchBuilder();
         MatchUtils.createIpProtocolMatch(matchBuilder, UDP_SHORT);
         MatchUtils.addLayer4Match(matchBuilder, UDP_SHORT, 0, dstPort);
-        flowBuilder.setMatch(MatchUtils.addNxRegMatch(
-                matchBuilder, new MatchUtils.RegMatch(FlowUtils.REG_FIELD, FlowUtils.REG_VALUE_FROM_LOCAL)).build());
+        MatchUtils.addNxRegMatch(matchBuilder,
+                MatchUtils.RegMatch.of(FlowUtils.REG_FIELD, FlowUtils.REG_VALUE_FROM_LOCAL));
+        flowBuilder.setMatch(matchBuilder.build());
 
         String flowId = "sfEgress_" + dstPort;
         flowBuilder.setId(new FlowId(flowId));
@@ -321,8 +380,8 @@ public class SfcClassifierService extends AbstractServiceInstance implements Con
         flowBuilder.setFlowName(flowId);
         flowBuilder.setHardTimeout(0);
         flowBuilder.setIdleTimeout(0);
-        flowBuilder.setCookie(new FlowCookie(getCookie(FLOW_SFEGRESS)));
-        flowBuilder.setCookieMask(new FlowCookie(getCookie(FLOW_SFEGRESS)));
+        flowBuilder.setCookie(new FlowCookie(getCookie(FlowID.FLOW_SFEGRESS)));
+        flowBuilder.setCookieMask(new FlowCookie(getCookie(FlowID.FLOW_SFEGRESS)));
 
         if (write) {
             InstructionBuilder ib = new InstructionBuilder();
@@ -352,7 +411,8 @@ public class SfcClassifierService extends AbstractServiceInstance implements Con
         MatchUtils.createIpProtocolMatch(matchBuilder, UDP_SHORT);
         Ipv4Prefix ipCidr = MatchUtils.iPv4PrefixFromIPv4Address(ipAddress);
         MatchUtils.createDstL3IPv4Match(matchBuilder, new Ipv4Prefix(ipCidr));
-        flowBuilder.setMatch(MatchUtils.addLayer4Match(matchBuilder, UDP_SHORT, 0, dstPort).build());
+        MatchUtils.addLayer4Match(matchBuilder, UDP_SHORT, 0, dstPort);
+        flowBuilder.setMatch(matchBuilder.build());
 
         String flowId = "sfIngress_" + dstPort + "_" + ipAddress;
         flowBuilder.setId(new FlowId(flowId));
@@ -363,8 +423,8 @@ public class SfcClassifierService extends AbstractServiceInstance implements Con
         flowBuilder.setFlowName(flowId);
         flowBuilder.setHardTimeout(0);
         flowBuilder.setIdleTimeout(0);
-        flowBuilder.setCookie(new FlowCookie(getCookie(FLOW_SFINGRESS)));
-        flowBuilder.setCookieMask(new FlowCookie(getCookie(FLOW_SFINGRESS)));
+        flowBuilder.setCookie(new FlowCookie(getCookie(FlowID.FLOW_SFINGRESS)));
+        flowBuilder.setCookieMask(new FlowCookie(getCookie(FlowID.FLOW_SFINGRESS)));
 
         if (write) {
             InstructionBuilder ib = new InstructionBuilder();
@@ -393,6 +453,7 @@ public class SfcClassifierService extends AbstractServiceInstance implements Con
         MacAddress macAddress = new MacAddress(macAddressStr);
 
         MatchBuilder matchBuilder = new MatchBuilder();
+        MatchUtils.createInPortReservedMatch(matchBuilder, dataPathId, OutputPortValues.LOCAL.toString());
         MatchUtils.createEtherTypeMatch(matchBuilder, new EtherType(Constants.ARP_ETHERTYPE));
         MatchUtils.createArpDstIpv4Match(matchBuilder, MatchUtils.iPv4PrefixFromIPv4Address(ipAddress));
         flowBuilder.setMatch(matchBuilder.build());
@@ -407,8 +468,8 @@ public class SfcClassifierService extends AbstractServiceInstance implements Con
         flowBuilder.setFlowName(flowId);
         flowBuilder.setHardTimeout(0);
         flowBuilder.setIdleTimeout(0);
-        flowBuilder.setCookie(new FlowCookie(getCookie(FLOW_SFARP)));
-        flowBuilder.setCookieMask(new FlowCookie(getCookie(FLOW_SFARP)));
+        flowBuilder.setCookie(new FlowCookie(getCookie(FlowID.FLOW_SFARP)));
+        flowBuilder.setCookieMask(new FlowCookie(getCookie(FlowID.FLOW_SFARP)));
 
         if (write == true) {
             InstructionBuilder ib = new InstructionBuilder();
@@ -431,7 +492,7 @@ public class SfcClassifierService extends AbstractServiceInstance implements Con
             actionList.add(ab.build());
 
             // Set ARP OP
-            ab.setAction(ActionUtils.nxLoadArpOpAction(BigInteger.valueOf(0x02L)));
+            ab.setAction(ActionUtils.nxLoadArpOpAction(BigInteger.valueOf(FlowUtils.ARP_OP_REPLY)));
             ab.setOrder(2);
             ab.setKey(new ActionKey(2));
             actionList.add(ab.build());
index b11229488209acc704c7c528d2351760161da569..08a1f0069560fc98dc0c3f1d555de973ea8876bb 100644 (file)
@@ -160,8 +160,8 @@ public class NetvirtSfcIT extends AbstractMdsalTestBase {
     private static final String SF2IP = "10.2.1.2";
     private static final String SF1DPLNAME = "sf1";
     private static final String SF2DPLNAME = "sf2";
-    private static final String SFF1IP = "127.0.0.1";
-    private static final String SFF2IP = "127.0.0.1";
+    private static final String SFF1IP = "127.0.0.1"; //"192.168.1.129"
+    private static final String SFF2IP = "192.168.1.129";//"127.0.0.1";
     private static final String SFF1NAME = "SFF1";
     private static final String SFF2NAME = "SFF2";
     private static final String SFFDPL1NAME = "vxgpe";
index 76734d11d1258405af7ac15aa9e6192eb869a38f..7657f2eee31f6ee07089e16679a761ba7d4d3544 100644 (file)
@@ -46,7 +46,7 @@ public class AclUtils extends AbstractUtils {
     }
 
     public ActionsBuilder actionsBuilder(ActionsBuilder actionsBuilder, String sfcName) {
-        RedirectToSfcBuilder redirectToSfcBuilder = new RedirectToSfcBuilder().setRedirectSfc(sfcName);
+        RedirectToSfcBuilder redirectToSfcBuilder = new RedirectToSfcBuilder().setSfcName(sfcName);
 
         return actionsBuilder.addAugmentation(RedirectToSfc.class, redirectToSfcBuilder.build());
     }
index 87fc3e0c2f47f2caa8745fd9a49ef7e7c72d6410..28cc30f9b02d50a094a03508c8a0e087e0db6dd6 100644 (file)
@@ -58,6 +58,7 @@ public class MdsalHelper {
     public static final String OVSDB_URI_PREFIX = "ovsdb";
     public static final String BRIDGE_URI_PREFIX = "bridge";
     public static final String TP_URI_PREFIX = "termination-point";
+    public static final String DISABLE_IN_BAND = "disable-in-band";
 
     public static final ImmutableBiMap<Class<? extends OvsdbBridgeProtocolBase>,String> OVSDB_PROTOCOL_MAP
             = new ImmutableBiMap.Builder<Class<? extends OvsdbBridgeProtocolBase>,String>()
index 209e292b0aa49dd2ca75fa9ad06d3f82db0415fc..88a9ebc073f14198d13633c1ee3d096644c1bca8 100644 (file)
@@ -16,6 +16,7 @@ import org.opendaylight.ovsdb.openstack.netvirt.translator.NeutronNetwork;
 import org.opendaylight.ovsdb.openstack.netvirt.translator.NeutronPort;
 import org.opendaylight.ovsdb.openstack.netvirt.translator.NeutronRouter;
 import org.opendaylight.ovsdb.openstack.netvirt.translator.NeutronRouter_Interface;
+import org.opendaylight.ovsdb.openstack.netvirt.translator.NeutronSecurityRule;
 import org.opendaylight.ovsdb.openstack.netvirt.translator.NeutronSubnet;
 import org.opendaylight.ovsdb.openstack.netvirt.api.Action;
 
@@ -30,6 +31,7 @@ public class NorthboundEvent extends AbstractEvent {
     private NeutronLoadBalancer loadBalancer;
     private NeutronLoadBalancerPool loadBalancerPool;
     private NeutronLoadBalancerPoolMember loadBalancerPoolMember;
+    private NeutronSecurityRule neutronSecurityRule;
 
     NorthboundEvent(NeutronPort port, Action action) {
         super(HandlerType.NEUTRON_PORT, action);
@@ -77,6 +79,11 @@ public class NorthboundEvent extends AbstractEvent {
         this.loadBalancerPoolMember = loadBalancerPoolMember;
     }
 
+    NorthboundEvent(NeutronSecurityRule neutronSecurityRule, Action action) {
+        super(HandlerType.NEUTRON_PORT_SECURITY, action);
+        this.neutronSecurityRule = neutronSecurityRule;
+    }
+
     public NeutronPort getPort() {
         return port;
     }
@@ -104,6 +111,9 @@ public class NorthboundEvent extends AbstractEvent {
     public NeutronLoadBalancerPoolMember getLoadBalancerPoolMember() {
         return loadBalancerPoolMember;
     }
+    public NeutronSecurityRule getNeutronSecurityRule() {
+        return neutronSecurityRule;
+    }
 
     @Override
     public String toString() {
@@ -118,6 +128,7 @@ public class NorthboundEvent extends AbstractEvent {
                + ", loadBalancer=" + loadBalancer
                + ", loadBalancerPool=" + loadBalancerPool
                + ", loadBalancerPoolMember=" + loadBalancerPoolMember
+               + ", neutronsecurityRule=" + neutronSecurityRule
                + "]";
     }
 
@@ -131,6 +142,7 @@ public class NorthboundEvent extends AbstractEvent {
         result = prime * result + ((routerInterface == null) ? 0 : routerInterface.hashCode());
         result = prime * result + ((neutronFloatingIP == null) ? 0 : neutronFloatingIP.hashCode());
         result = prime * result + ((neutronNetwork == null) ? 0 : neutronNetwork.hashCode());
+        result = prime * result + ((neutronSecurityRule == null) ? 0 : neutronSecurityRule.hashCode());
         return result;
     }
 
@@ -212,6 +224,13 @@ public class NorthboundEvent extends AbstractEvent {
         } else if (!loadBalancerPoolMember.equals(other.loadBalancerPoolMember)) {
             return false;
         }
+        if (neutronSecurityRule == null) {
+            if (other.neutronSecurityRule != null) {
+                return false;
+            }
+        } else if (!neutronSecurityRule.equals(other.neutronSecurityRule)) {
+            return false;
+        }
         return true;
     }
 }
index e6568000a947c14e8433c990d6355035a76c0bf5..646693cd263950310ad51f608b252d49f9366816 100644 (file)
@@ -9,12 +9,19 @@
 package org.opendaylight.ovsdb.openstack.netvirt;
 
 import java.net.HttpURLConnection;
+import java.util.ArrayList;
+import java.util.List;
 
+import org.opendaylight.ovsdb.openstack.netvirt.translator.NeutronPort;
 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.openstack.netvirt.translator.crud.INeutronPortCRUD;
 import org.opendaylight.ovsdb.openstack.netvirt.translator.iaware.INeutronSecurityGroupAware;
 import org.opendaylight.ovsdb.openstack.netvirt.translator.iaware.INeutronSecurityRuleAware;
+import org.opendaylight.ovsdb.openstack.netvirt.api.Action;
 import org.opendaylight.ovsdb.openstack.netvirt.api.EventDispatcher;
+import org.opendaylight.ovsdb.openstack.netvirt.api.SecurityServicesManager;
 import org.opendaylight.ovsdb.utils.servicehelper.ServiceHelper;
 import org.osgi.framework.ServiceReference;
 import org.slf4j.Logger;
@@ -27,6 +34,8 @@ public class PortSecurityHandler extends AbstractHandler
         implements INeutronSecurityGroupAware, INeutronSecurityRuleAware, ConfigInterface {
 
     private static final Logger LOG = LoggerFactory.getLogger(PortSecurityHandler.class);
+    private volatile INeutronPortCRUD neutronPortCache;
+    private volatile SecurityServicesManager securityServicesManager;
 
     @Override
     public int canCreateNeutronSecurityGroup(NeutronSecurityGroup neutronSecurityGroup) {
@@ -80,10 +89,7 @@ public class PortSecurityHandler extends AbstractHandler
 
     @Override
     public void neutronSecurityRuleCreated(NeutronSecurityRule neutronSecurityRule) {
-        int result = canCreateNeutronSecurityRule(neutronSecurityRule);
-        if (result != HttpURLConnection.HTTP_CREATED) {
-            LOG.debug("Neutron Security Group creation failed {} ", result);
-        }
+        enqueueEvent(new NorthboundEvent(neutronSecurityRule, Action.ADD));
     }
 
     @Override
@@ -103,10 +109,7 @@ public class PortSecurityHandler extends AbstractHandler
 
     @Override
     public void neutronSecurityRuleDeleted(NeutronSecurityRule neutronSecurityRule) {
-        int result = canDeleteNeutronSecurityRule(neutronSecurityRule);
-        if  (result != HttpURLConnection.HTTP_OK) {
-            LOG.error(" delete Neutron Security Rule validation failed for result - {} ", result);
-        }
+        enqueueEvent(new NorthboundEvent(neutronSecurityRule, Action.DELETE));
     }
 
     /**
@@ -123,19 +126,71 @@ public class PortSecurityHandler extends AbstractHandler
         }
         NorthboundEvent ev = (NorthboundEvent) abstractEvent;
         switch (ev.getAction()) {
-            // TODO: add handling of events here, once callbacks do something
-            //       other than logging.
+            case ADD:
+                processNeutronSecurityRuleAdded(ev.getNeutronSecurityRule());
+                break;
+            case DELETE:
+                processNeutronSecurityRuleDeleted(ev.getNeutronSecurityRule());
+                break;
             default:
                 LOG.warn("Unable to process event action {}", ev.getAction());
                 break;
         }
     }
 
+    private void processNeutronSecurityRuleAdded(NeutronSecurityRule neutronSecurityRule) {
+        List<NeutronPort> portList = getPortWithSecurityGroup(neutronSecurityRule.getSecurityRuleGroupID());
+        for (NeutronPort port:portList) {
+            syncSecurityGroup(neutronSecurityRule,port,neutronSecurityRule.getSecurityRuleGroupID(),true);
+        }
+    }
+
+    private void processNeutronSecurityRuleDeleted(NeutronSecurityRule neutronSecurityRule) {
+        List<NeutronPort> portList = getPortWithSecurityGroup(neutronSecurityRule.getSecurityRuleGroupID());
+        for (NeutronPort port:portList) {
+            syncSecurityGroup(neutronSecurityRule,port,neutronSecurityRule.getSecurityRuleGroupID(),false);
+        }
+    }
+
+    private void syncSecurityGroup(NeutronSecurityRule  securityRule,NeutronPort port,
+                                   String neutronSecurityGroupId,boolean write) {
+
+        if (null != securityRule.getSecurityRemoteGroupID()) {
+            List<Neutron_IPs> vmIpList  = securityServicesManager
+                    .getVmListForSecurityGroup(port.getID(), neutronSecurityGroupId);
+            for (Neutron_IPs vmIp :vmIpList ) {
+                securityServicesManager.syncSecurityRule(port, securityRule, vmIp, write);
+            }
+        } else {
+            securityServicesManager.syncSecurityRule(port, securityRule, null, write);
+        }
+    }
+
+    private List<NeutronPort> getPortWithSecurityGroup(String securityGroupUuid) {
+
+        List<NeutronPort> neutronPortList = neutronPortCache.getAllPorts();
+        List<NeutronPort> neutronPortInSG = new ArrayList<NeutronPort>();
+        for (NeutronPort neutronPort:neutronPortList) {
+            List<NeutronSecurityGroup> securityGroupList = neutronPort.getSecurityGroups();
+            for (NeutronSecurityGroup neutronSecurityGroup:securityGroupList) {
+                if (neutronSecurityGroup.getID().equals(securityGroupUuid)) {
+                    neutronPortInSG.add(neutronPort);
+                    break;
+                }
+            }
+        }
+        return neutronPortInSG;
+    }
+
     @Override
     public void setDependencies(ServiceReference serviceReference) {
         eventDispatcher =
                 (EventDispatcher) ServiceHelper.getGlobalInstance(EventDispatcher.class, this);
         eventDispatcher.eventHandlerAdded(serviceReference, this);
+        neutronPortCache =
+                (INeutronPortCRUD) ServiceHelper.getGlobalInstance(INeutronPortCRUD.class, this);
+        securityServicesManager =
+                (SecurityServicesManager) ServiceHelper.getGlobalInstance(SecurityServicesManager.class, this);
     }
 
     @Override
index d58075cad0b467c11026db1a72dc67673212c52f..0d1b52cf75fa30772805efe3a6a7632dd1eda0aa 100644 (file)
@@ -117,4 +117,14 @@ public interface BridgeConfigurationManager {
      * @return a List in the format {eth1, eth2} given bridge_mappings=physnet1:eth1,physnet2:eth2
      */
     List<String> getAllPhysicalInterfaceNames(Node node);
+
+   /*
+     * Return br-ex interface configured in the bridge_mappings.
+     * Return null if br-ex is not configured in bridge_mappings.
+     * @param node the {@link Node} to query
+     * @param externalNetwork
+     * @return the interface as a string like eth3 given bridge_mappings=br-ex:eth3
+   */
+     String getExternalInterfaceName (Node node, String externalNetwork);
+
 }
index e58021f93b29a8e2f59c1b23b602a0a44cac67af..3ea4608014c0466a82ca6467caf80e3abc31611b 100644 (file)
@@ -200,6 +200,34 @@ public class BridgeConfigurationManagerImpl implements BridgeConfigurationManage
         return isCreated;
     }
 
+
+
+    @Override
+    public String getExternalInterfaceName (Node node, String extNetwork) {
+        String phyIf = null;
+        String providerMaps = southbound.getOtherConfig(node, OvsdbTables.OPENVSWITCH,
+                configurationService.getProviderMappingsKey());
+        if (providerMaps != null) {
+            for (String map : providerMaps.split(",")) {
+                String[] pair = map.split(":");
+                if (pair[0].equals(extNetwork)) {
+                    phyIf = pair[1];
+                    break;
+                }
+            }
+        }
+        if (phyIf == null) {
+            LOG.error("External interface not found for Node: {}, Network {}",
+                    node, extNetwork);
+        }
+        else {
+            LOG.info("External interface found for Node: {}, Network {} is {}",node,extNetwork,phyIf);
+        }
+        return phyIf;
+    }
+
+
+
     @Override
     public String getPhysicalInterfaceName (Node node, String physicalNetwork) {
         String phyIf = null;
@@ -378,8 +406,15 @@ public class BridgeConfigurationManagerImpl implements BridgeConfigurationManage
                 LOG.error("Add Port {} to Bridge {} failed", portNameExt, brExt);
                 return false;
             }
+            String extNetName = getExternalInterfaceName(extBridgeNode, brExt);
+            if ( extNetName != null) {
+                if (!addPortToBridge(extBridgeNode, brExt, extNetName)) {
+                    LOG.error("Add External Port {} to Bridge {} failed", extNetName, brExt);
+                    return false;
+                }
+            LOG.info("Add External Port {} to Ext Bridge {} success", extNetName, brExt);
+            }
         }
-
         /* For vlan network types add physical port to br-int. */
         if (network.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VLAN)) {
             String phyNetName = this.getPhysicalInterfaceName(bridgeNode, network.getProviderPhysicalNetwork());
@@ -389,7 +424,7 @@ public class BridgeConfigurationManagerImpl implements BridgeConfigurationManage
             }
         }
 
-        LOG.debug("createBridges: node: {}, status: success", bridgeNode);
+        LOG.info("createBridges: node: {}, status: success", bridgeNode);
         return true;
     }
 
index 60388974f223e4af40a731c5a9f140e4b09eca8f..530fee8311bd319ee5330b4774251e32f312e3b6 100644 (file)
@@ -22,6 +22,7 @@ import org.opendaylight.ovsdb.openstack.netvirt.translator.iaware.impl.NeutronFl
 import org.opendaylight.ovsdb.openstack.netvirt.translator.iaware.impl.NeutronNetworkChangeListener;
 import org.opendaylight.ovsdb.openstack.netvirt.translator.iaware.impl.NeutronPortChangeListener;
 import org.opendaylight.ovsdb.openstack.netvirt.translator.iaware.impl.NeutronRouterChangeListener;
+import org.opendaylight.ovsdb.openstack.netvirt.translator.iaware.impl.NeutronSecurityRuleDataChangeListener;
 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;
@@ -104,6 +105,7 @@ public class OvsdbInventoryServiceImpl implements ConfigInterface, OvsdbInventor
         new NeutronFloatingIPChangeListener(db);
         new NeutronLoadBalancerPoolChangeListener(db);
         new NeutronLoadBalancerPoolMemberChangeListener(db);
+        new NeutronSecurityRuleDataChangeListener(db);
     }
 
 }
index 2ea54897d85d5eb0169b6299b855fc643e474415..38eeaecbdab60b1cf01d9e76dbf35d85703f1943 100644 (file)
@@ -33,6 +33,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.re
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentationBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeExternalIds;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeOtherConfigs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeOtherConfigsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeOtherConfigsKey;
 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.bridge.attributes.ControllerEntryBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ProtocolEntry;
@@ -197,6 +199,13 @@ public class SouthboundImpl implements Southbound {
             ovsdbBridgeAugmentationBuilder.setProtocolEntry(createMdsalProtocols());
             ovsdbBridgeAugmentationBuilder.setFailMode(
                     MdsalHelper.OVSDB_FAIL_MODE_MAP.inverse().get("secure"));
+            BridgeOtherConfigsBuilder bridgeOtherConfigsBuilder = new BridgeOtherConfigsBuilder();
+            bridgeOtherConfigsBuilder.setBridgeOtherConfigKey(MdsalHelper.DISABLE_IN_BAND);
+            bridgeOtherConfigsBuilder.setBridgeOtherConfigValue("true");
+            bridgeOtherConfigsBuilder.setBridgeOtherConfigKey(MdsalHelper.DISABLE_IN_BAND);
+            List<BridgeOtherConfigs> bridgeOtherConfigsList = new ArrayList<>();
+            bridgeOtherConfigsList.add(bridgeOtherConfigsBuilder.build());
+            ovsdbBridgeAugmentationBuilder.setBridgeOtherConfigs(bridgeOtherConfigsList);
             setManagedByForBridge(ovsdbBridgeAugmentationBuilder, ovsdbNode.getKey());
             if (isOvsdbNodeDpdk(ovsdbNode)) {
                 ovsdbBridgeAugmentationBuilder.setDatapathType(DatapathTypeNetdev.class);
index 488b32d885f46d7dcdb5b5f9d4f644db0f579be1..6f09a7fa5ca840755923dbbb51e7581d0500b27d 100644 (file)
@@ -23,10 +23,10 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.EthertypeV4;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.EthertypeV6;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.ProtocolBase;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.ProtocolHttp;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.ProtocolHttps;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.ProtocolIcmp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.ProtocolIcmpV6;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.ProtocolTcp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.ProtocolUdp;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.security.rules.attributes.SecurityRules;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.security.rules.attributes.security.rules.SecurityRule;
@@ -43,20 +43,20 @@ public class NeutronSecurityRuleDataChangeListener implements DataChangeListener
     private static final Logger LOG = LoggerFactory.getLogger(NeutronSecurityRuleDataChangeListener.class);
 
     private static final ImmutableBiMap<Class<? extends DirectionBase>, String> DIRECTION_MAP
-            = new ImmutableBiMap.Builder<Class<? extends DirectionBase>, String>()
-            .put(DirectionEgress.class, "egress")
-            .put(DirectionIngress.class, "ingress").build();
-    private static final ImmutableBiMap<Class<? extends ProtocolBase>, String> PROTOCOL_MAP
-            = new ImmutableBiMap.Builder<Class<? extends ProtocolBase>, String>()
-            .put(ProtocolHttp.class, "HTTP")
-            .put(ProtocolHttps.class, "HTTPS")
-            .put(ProtocolIcmp.class, "ICMP")
-            .put(ProtocolTcp.class, "TCP")
+        = new ImmutableBiMap.Builder<Class<? extends DirectionBase>, String>()
+        .put(DirectionEgress.class, "egress")
+        .put(DirectionIngress.class, "ingress").build();
+    private static final ImmutableBiMap<Class<? extends ProtocolBase>,String> PROTOCOL_MAP
+            = new ImmutableBiMap.Builder<Class<? extends ProtocolBase>,String>()
+            .put(ProtocolIcmp.class,"icmp")
+            .put(ProtocolTcp.class,"tcp")
+            .put(ProtocolUdp.class,"udp")
+            .put(ProtocolIcmpV6.class,"icmpv6")
             .build();
-    private static final ImmutableBiMap<Class<? extends EthertypeBase>, String> ETHERTYPE_MAP
-            = new ImmutableBiMap.Builder<Class<? extends EthertypeBase>, String>()
-            .put(EthertypeV4.class, "v4")
-            .put(EthertypeV6.class, "v6")
+    private static final ImmutableBiMap<Class<? extends EthertypeBase>,String> ETHERTYPE_MAP
+            = new ImmutableBiMap.Builder<Class<? extends EthertypeBase>,String>()
+            .put(EthertypeV4.class,"IPv4")
+            .put(EthertypeV6.class,"IPv6")
             .build();
 
     private ListenerRegistration<DataChangeListener> registration;
index b00c7a50291e5b185b63524f53d311eb84514b21..660aad36146458a2498a363ee203e5e33890c34f 100644 (file)
@@ -21,6 +21,7 @@ import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.InjectMocks;
+import org.mockito.Mock;
 import org.mockito.Mockito;
 import org.opendaylight.ovsdb.openstack.netvirt.translator.NeutronSecurityGroup;
 import org.opendaylight.ovsdb.openstack.netvirt.translator.NeutronSecurityRule;
@@ -40,6 +41,7 @@ public class PortSecurityHandlerTest {
 
     @InjectMocks private PortSecurityHandler portSecurityHandler;
     private PortSecurityHandler posrtSecurityHandlerSpy;
+    @Mock EventDispatcher eventDispatcher;
 
     @Before
     public void setUp() {
@@ -72,7 +74,7 @@ public class PortSecurityHandlerTest {
         assertEquals("Error, did not return the correct HTTP flag", HttpURLConnection.HTTP_CREATED, portSecurityHandler.canCreateNeutronSecurityRule(mock(NeutronSecurityRule.class)));
 
         posrtSecurityHandlerSpy.neutronSecurityRuleCreated(any(NeutronSecurityRule.class));
-        verify(posrtSecurityHandlerSpy, times(1)).canCreateNeutronSecurityRule(any(NeutronSecurityRule.class));
+        verify(posrtSecurityHandlerSpy, times(1)).enqueueEvent(any(AbstractEvent.class));
     }
 
     @Test
@@ -85,7 +87,7 @@ public class PortSecurityHandlerTest {
         assertEquals("Error, did not return the correct HTTP flag", HttpURLConnection.HTTP_OK, portSecurityHandler.canDeleteNeutronSecurityRule(mock(NeutronSecurityRule.class)));
 
         posrtSecurityHandlerSpy.neutronSecurityRuleDeleted(any(NeutronSecurityRule.class));
-        verify(posrtSecurityHandlerSpy, times(1)).canDeleteNeutronSecurityRule(any(NeutronSecurityRule.class));
+        verify(posrtSecurityHandlerSpy, times(1)).enqueueEvent(any(AbstractEvent.class));
    }
 
     @Test
diff --git a/resources/commons/Ovsdb-HwvtepSouthbound-Collection.json.postman_collection b/resources/commons/Ovsdb-HwvtepSouthbound-Collection.json.postman_collection
new file mode 100755 (executable)
index 0000000..7c98745
--- /dev/null
@@ -0,0 +1,222 @@
+{
+    "id":"19f6b1a8-4d54-62f8-6bd6-f52e0b6e40b8",
+    "name":"Ovsdb HwvtepSouthbound",
+    "timestamp":1424977469540,
+    "order":[
+        "e9ff6957-4dc2-9257-c0c6-21560bfd5de2",
+        "ee151670-85a0-30ec-b22b-5defe7b66e0b",
+        "6de1ede7-817c-ccbb-3df9-ef510bdaf583",
+        "6e7c88e4-485d-ab9f-4c3a-cc235e022905",
+        "92ee7422-5b08-6d63-2b95-961ec0e18ffa",
+        "e92ac963-daaf-0899-c3e8-a00d897be0e2",
+        "9bc22ca7-049c-af51-7c12-6bf71044b2ec",
+        "f6d300f7-380a-d090-0d4a-2b2ddefe5104",
+        "f9f71d74-a49d-b190-d929-b6772ce0ba73",
+        "18032e93-3bc5-9976-4525-fe1e77e98207",
+        "22354294-1d01-cebf-180c-d609747be9bc",
+        "c8e8f3fd-3bfb-aafa-e3ec-a671a942f426",
+        "d362ddc4-1c5f-67d5-e354-c2a8d2ba9d79",
+        "538c71b3-e3e6-f01b-cc4c-d2b686686aa8"
+    ],
+    "owner":0,
+    "sharedWithTeam":false,
+    "synced":false,
+    "subscribed":false,
+    "hasRequests":true,
+    "requests":[
+        {
+            "collectionId":"19f6b1a8-4d54-62f8-6bd6-f52e0b6e40b8",
+            "id":"18032e93-3bc5-9976-4525-fe1e77e98207",
+            "name":"Delete Specific Config Logical Switch",
+            "description":"This restconf request delete specific logical switch from the config data store.",
+            "url":"http://{{controllerHost}}:8181/restconf/config/network-topology:network-topology/topology/hwvtep:1/node/hwvtep:%2F%2F{{hwvtepNodeIp}}:6640%2Flogicalswitch%2Fls0",
+            "method":"DELETE",
+            "headers":"Authorization: Basic YWRtaW46YWRtaW4=\n",
+            "data":[],
+            "dataMode":"params",
+            "timestamp":0,
+            "version":2,
+            "time":1447335528744
+        },
+        {
+            "collectionId":"19f6b1a8-4d54-62f8-6bd6-f52e0b6e40b8",
+            "id":"22354294-1d01-cebf-180c-d609747be9bc",
+            "name":"Get All Operational Topology",
+            "description":"This restconf request will fetch the operational topology. Operational topology details are fetch by hwvtepsouthbound plugin from all the connected hwvtep node.",
+            "url":"http://{{controllerHost}}:8181/restconf/operational/network-topology:network-topology/",
+            "method":"GET",
+            "headers":"Authorization: Basic YWRtaW46YWRtaW4=\n",
+            "data":[],
+            "dataMode":"params",
+            "timestamp":0,
+            "version":2
+        },
+        {
+            "collectionId":"19f6b1a8-4d54-62f8-6bd6-f52e0b6e40b8",
+            "id":"538c71b3-e3e6-f01b-cc4c-d2b686686aa8",
+            "name":"Get Specific Operational Logical Switch",
+            "description":"This restconf request fetch the operational for specific Logical Switch",
+            "url":"http://{{controllerHost}}:8181/restconf/operational/network-topology:network-topology/topology/hwvtep:1/node/hwvtep:%2F%2F{{hwvtepNodeIp}}:6640%2logicalswitch%2ls0",
+            "method":"GET",
+            "headers":"Authorization: Basic YWRtaW46YWRtaW4=\n",
+            "data":"{\n  \"network-topology:node\": [\n        {\n            \"node-id\": \"hwvtep://{{hwvtepNodeIp}}:6640/logicalswitch/ls0\",\n            \"hwvtep-node-description\": \"\",\n            \"hwvtep-node-name\": \"ls0\",\n            \"tunnel-key\": \"10000\"\n        }\n    ]\n}",
+            "dataMode":"raw",
+            "timestamp":0,
+            "version":2,
+            "time":1447335701900
+        },
+        {
+            "collectionId":"19f6b1a8-4d54-62f8-6bd6-f52e0b6e40b8",
+            "id":"6de1ede7-817c-ccbb-3df9-ef510bdaf583",
+            "name":"Create Specific Config HwvtepNode",
+            "description":"Fire this Restconf request if you want to initiate the connection to hwvtep node from controller. It assumes that hwvtep node is listening for tcp connection in passive mode.",
+            "url":"http://{{controllerHost}}:8181/restconf/config/network-topology:network-topology/topology/hwvtep:1/",
+            "method":"POST",
+            "headers":"Authorization: Basic YWRtaW46YWRtaW4=\nContent-Type: application/json\n",
+            "data":"{\n  \"network-topology:node\": [\n        {\n            \"node-id\": \"hwvtep://{{hwvtepNodeIp}}:6640\",\n            \"connection-info\": {\n              \"hwvtep:remote-port\": 6640,\n              \"hwvtep:remote-ip\": \"{{hwvtepNodeIp}}\"\n            }\n        }\n    ]\n}",
+            "dataMode":"raw",
+            "timestamp":0,
+            "version":2,
+            "time":1447334840814
+        },
+        {
+            "collectionId":"19f6b1a8-4d54-62f8-6bd6-f52e0b6e40b8",
+            "id":"6e7c88e4-485d-ab9f-4c3a-cc235e022905",
+            "name":"Update Specific Config HwvtepNode",
+            "description":"Fire this Restconf request if you want to update the connection to Hwvtep node from controller.",
+            "url":"http://{{controllerHost}}:8181/restconf/config/network-topology:network-topology/topology/hwvtep:1/node/hwvtep:%2F%2F{{hwvtepNodeIp}}:6640",
+            "method":"PUT",
+            "headers":"Authorization: Basic YWRtaW46YWRtaW4=\nContent-Type: application/json\n",
+            "data":"{\n  \"network-topology:node\": [\n        {\n            \"node-id\": \"hwvtep://{{hwvtepNodeIp}}:6640\",\n            \"connection-info\": {\n              \"hwvtep:remote-port\": 6640,\n              \"hwvtep:remote-ip\": \"{{hwvtepNodeIp}}\"\n            }\n        }\n    ]\n}",
+            "dataMode":"raw",
+            "timestamp":0,
+            "version":2,
+            "time":1447334483164
+        },
+        {
+            "collectionId":"19f6b1a8-4d54-62f8-6bd6-f52e0b6e40b8",
+            "id":"92ee7422-5b08-6d63-2b95-961ec0e18ffa",
+            "name":"Get Specific Config HwvtepNode",
+            "description":"This restconf request fetch the configration for specific hwvtep node.",
+            "url":"http://{{controllerHost}}:8181/restconf/config/network-topology:network-topology/topology/hwvtep:1/node/hwvtep:%2F%2F{{hwvtepNodeIp}}:6640",
+            "method":"GET",
+            "headers":"Authorization: Basic YWRtaW46YWRtaW4=\n",
+            "data":"{\n  \"network-topology:node\": [\n        {\n            \"node-id\": \"hwvtep://{{hwvtepNodeIp}}:6640\",\n            \"connection-info\": {\n              \"hwvtep:remote-port\": 6640,\n              \"hwvtep:remote-ip\": \"{{hwvtepNodeIp}}\"\n            }\n        }\n    ]\n}",
+            "dataMode":"raw",
+            "timestamp":0,
+            "version":2,
+            "time":1447334914971
+        },
+        {
+            "collectionId":"19f6b1a8-4d54-62f8-6bd6-f52e0b6e40b8",
+            "id":"9bc22ca7-049c-af51-7c12-6bf71044b2ec",
+            "name":"Create Specific Config Logical Switch",
+            "description":"Fire this Restconf request if you want to create a logical switch.",
+            "url":"http://{{controllerHost}}:8181/restconf/config/network-topology:network-topology/topology/hwvtep:1/",
+            "method":"POST",
+            "headers":"Authorization: Basic YWRtaW46YWRtaW4=\nContent-Type: application/json\n",
+            "data":"{\n  \"network-topology:node\": [\n        {\n            \"node-id\": \"hwvtep://{{hwvtepNodeIp}}:6640/logicalswitch/ls0\",\n            \"hwvtep-node-description\": \"\",\n            \"hwvtep-node-name\": \"ls0\",\n            \"tunnel-key\": \"10000\",\n            \"managed-by\": \"/network-topology:network-topology/network-topology:topology[network-topology:topology-id='hwvtep:1']/network-topology:node[network-topology:node-id='hwvtep://{{hwvtepNodeIp}}:6640']\"             \n        }\n    ]\n}",
+            "dataMode":"raw",
+            "timestamp":0,
+            "version":2,
+            "time":1447340822378
+        },
+        {
+            "collectionId":"19f6b1a8-4d54-62f8-6bd6-f52e0b6e40b8",
+            "id":"c8e8f3fd-3bfb-aafa-e3ec-a671a942f426",
+            "name":"Get Operational Hwvtep Topology",
+            "description":"",
+            "url":"http://{{controllerHost}}:8181/restconf/operational/network-topology:network-topology/topology/hwvtep:1/",
+            "method":"GET",
+            "headers":"Authorization: Basic YWRtaW46YWRtaW4=\n",
+            "data":"{\n  \"network-topology:node\": [\n        {\n            \"node-id\": \"hwvtep://{{hwvtepNodeIp}}:6640\",\n            \"connection-info\": {\n              \"hwvtep:remote-port\": 6640,\n              \"hwvtep:remote-ip\": \"{{hwvtepNodeIp}}\"\n            }\n        }\n    ]\n}",
+            "dataMode":"raw",
+            "timestamp":0,
+            "version":2,
+            "time":1447335830695
+        },
+        {
+            "collectionId":"19f6b1a8-4d54-62f8-6bd6-f52e0b6e40b8",
+            "id":"d362ddc4-1c5f-67d5-e354-c2a8d2ba9d79",
+            "name":"Get Specific Operational HwvtepNode",
+            "description":"This restconf request fetch the operational for specific HwvtepNode",
+            "url":"http://{{controllerHost}}:8181/restconf/operational/network-topology:network-topology/topology/hwvtep:1/node/hwvtep:%2F%2F{{hwvtepNodeIp}}:6640",
+            "method":"GET",
+            "headers":"Authorization: Basic YWRtaW46YWRtaW4=\n",
+            "data":"{\n  \"network-topology:node\": [\n        {\n            \"node-id\": \"hwvtep://{{hwvtepNodeIp}}:6640/logicalswitch/ls0\",\n            \"hwvtep-node-description\": \"\",\n            \"hwvtep-node-name\": \"ls0\",\n            \"tunnel-key\": \"10000\"\n        }\n    ]\n}",
+            "dataMode":"raw",
+            "timestamp":0,
+            "version":2,
+            "time":1447335686540
+        },
+        {
+            "collectionId":"19f6b1a8-4d54-62f8-6bd6-f52e0b6e40b8",
+            "id":"e92ac963-daaf-0899-c3e8-a00d897be0e2",
+            "name":"Delete Specific Config HwvtepNode",
+            "description":"This restconf request delete any node (ovsdb node or bridge node) from the config data store. You can use the same request to delete the ovsdb node by using the following URI: http://localhost:8080/restconf/config/network-topology:network-topology/topology/ovsdb:1/node/ovsdb:%2F%2F10.10.10.10:22222",
+            "url":"http://{{controllerHost}}:8181/restconf/config/network-topology:network-topology/topology/hwvtep:1/node/hwvtep:%2F%2F{{hwvtepNodeIp}}:6640",
+            "method":"DELETE",
+            "headers":"Authorization: Basic YWRtaW46YWRtaW4=\n",
+            "data":[],
+            "dataMode":"params",
+            "timestamp":0,
+            "version":2
+        },
+        {
+            "collectionId":"19f6b1a8-4d54-62f8-6bd6-f52e0b6e40b8",
+            "id":"e9ff6957-4dc2-9257-c0c6-21560bfd5de2",
+            "name":"Get All Config Topology",
+            "description":"Fetch all the config topology from configuration data store.",
+            "url":"http://{{controllerHost}}:8181/restconf/config/network-topology:network-topology/",
+            "method":"GET",
+            "headers":"Authorization: Basic YWRtaW46YWRtaW4=\n",
+            "data":"{\n  \"network-topology:node\": [\n        {\n            \"node-id\": \"hwvtep://{{hwvtepNodeIp}}:6640\",\n            \"connection-info\": {\n              \"hwvtep:remote-port\": 6640,\n              \"hwvtep:remote-ip\": \"{{hwvtepNodeIp}}\"\n            }\n        }\n    ]\n}",
+            "dataMode":"raw",
+            "timestamp":0,
+            "version":2,
+            "time":1447311894927
+        },
+        {
+            "collectionId":"19f6b1a8-4d54-62f8-6bd6-f52e0b6e40b8",
+            "id":"ee151670-85a0-30ec-b22b-5defe7b66e0b",
+            "name":"Get Config  Hwvtep Topology",
+            "description":"Fetch the config hwvtep topology from configuration data store.",
+            "url":"http://{{controllerHost}}:8181/restconf/config/network-topology:network-topology/hwvtep:1/",
+            "method":"GET",
+            "headers":"Authorization: Basic YWRtaW46YWRtaW4=\n",
+            "data":"{\n  \"network-topology:node\": [\n        {\n            \"node-id\": \"hwvtep://{{hwvtepNodeIp}}:6640\",\n            \"connection-info\": {\n              \"hwvtep:remote-port\": 6640,\n              \"hwvtep:remote-ip\": \"{{hwvtepNodeIp}}\"\n            }\n        }\n    ]\n}",
+            "dataMode":"raw",
+            "timestamp":0,
+            "version":2,
+            "time":1447335823182
+        },
+        {
+            "collectionId":"19f6b1a8-4d54-62f8-6bd6-f52e0b6e40b8",
+            "id":"f6d300f7-380a-d090-0d4a-2b2ddefe5104",
+            "name":"Create Specific Config Logical Switch",
+            "description":"Fire this request if you want to update specific logical switch.",
+            "url":"http://{{controllerHost}}:8181/restconf/config/network-topology:network-topology/topology/hwvtep:1/node/hwvtep:%2F%2F{{hwvtepNodeIp}}:6640%2Flogicalswitch%2Fls0",
+            "method":"PUT",
+            "headers":"Authorization: Basic YWRtaW46YWRtaW4=\nContent-Type: application/json\n",
+            "data":"{\n  \"network-topology:node\": [\n        {\n            \"node-id\": \"hwvtep://{{hwvtepNodeIp}}:6640/logicalswitch/ls0\",\n            \"hwvtep-node-description\": \"\",\n            \"hwvtep-node-name\": \"ls0\",\n            \"tunnel-key\": \"10000\",\n            \"managed-by\": \"/network-topology:network-topology/network-topology:topology[network-topology:topology-id='hwvtep:1']/network-topology:node[network-topology:node-id='hwvtep://{{hwvtepNodeIp}}:6640']\"             \n        }\n    ]\n}",
+            "dataMode":"raw",
+            "timestamp":0,
+            "version":2,
+            "time":1447340847211
+        },
+        {
+            "collectionId":"19f6b1a8-4d54-62f8-6bd6-f52e0b6e40b8",
+            "id":"f9f71d74-a49d-b190-d929-b6772ce0ba73",
+            "name":"Get Specific Config Logical Switch",
+            "description":"This restconf request fetch configuration for specific logical switch.",
+            "url":"http://{{controllerHost}}:8181/restconf/config/network-topology:network-topology/topology/hwvtep:1/node/hwvtep:%2F%2F{{hwvtepNodeIp}}:6640%2Flogicalswitch%2Fls0",
+            "method":"GET",
+            "headers":"Authorization: Basic YWRtaW46YWRtaW4=\n",
+            "data":"{\n  \"network-topology:node\": [\n        {\n            \"node-id\": \"hwvtep://{{hwvtepNodeIp}}:6640/logicalswitch/ls0\",\n            \"hwvtep-node-description\": \"\",\n            \"hwvtep-node-name\": \"ls0\",\n            \"tunnel-key\": \"10000\"\n        }\n    ]\n}",
+            "dataMode":"raw",
+            "timestamp":0,
+            "version":2,
+            "time":1447335408595
+        }
+    ]
+}
index 25cf72cccfcd29a3282a6e2e0d7d567127c018c9..0cad7271a01ba6b95242b5232038e55125f7d4bb 100644 (file)
@@ -14,13 +14,13 @@ Contents
 - showOvsdbMdsal.py : Dumps mdsal related info from running ODL that is related to ovsdb and netvirt. Use 'showOvsdbMdsal.py -h' for usage
 
 - ODL-Clustering.json.postman_collection : Collection contains Restconf request to fetch clustering service related data to check the state of 3 node cluster and inventory/topology shards.
-       - Please import and load 3-Node-Cluster-Setup-Environment-Variables.postman_environment file, because Restconf request present in this collection depends on the variable defined in this collection.
+    - Please import and load 3-Node-Cluster-Setup-Environment-Variables.postman_environment file, because Restconf request present in this collection depends on the variable defined in this collection.
 
 - Ovsdb-Southbound-Collection-for-Single-Node-Cluster.json.postman_collection : Collection contains Restconf request for doing CRUD operations (connection, bridge, termination point) on southbound plugin running in standalone controller.
-       - Please import and load Single-Node-Cluster-Setup-Environment-Variables.postman_environment file, because Restconf request present in this collection depends on the variable defined in this collection.
+    - Please import and load Single-Node-Cluster-Setup-Environment-Variables.postman_environment file, because Restconf request present in this collection depends on the variable defined in this collection.
 
-- Ovsdb-Southbound-Collection-for-3-Node-Cluster.json.postman_collection : 
-       - Please import and load 3-Node-Cluster-Setup-Environment-Variables.postman_environment file, because Restconf request present in this collection depends on the variable defined in this collection.
+- Ovsdb-Southbound-Collection-for-3-Node-Cluster.json.postman_collection :
+    - Please import and load 3-Node-Cluster-Setup-Environment-Variables.postman_environment file, because Restconf request present in this collection depends on the variable defined in this collection.
 
 
 - Single-Node-Cluster-Setup-Environment-Variables.postman_environment : Postman environment file that defines variables for Restconf request for southbound plugin running in Single controller instance
@@ -28,3 +28,5 @@ Contents
 - 3-Node-Cluster-Setup-Environment-Variables.postman_environment : Postman environment file that defines variables for Restconf request for southbound plugin running in 3 node cluster environment
 
 - NetvirtSfc.json.postman_collection : Collection of REST-APIs to interact with Netvirt-Sfc.
+
+- Ovsdb-HwvtepSouthbound-Collection.json.postman_collection : Collection contains Restconf request for doing CRUD operations (hwvtep global node, physical switch, logical switch, physical locator, and physical port) on hwvtepsouthbound plugin running in standalone controller.
index c11a620a5ee6d2e23eaea3c940fe4af3e4fdbb96..74fea32479bf269bc184ff771c0d5a82cb35227b 100644 (file)
@@ -19,7 +19,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.ta
 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.OutputPortValues;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
@@ -39,6 +38,9 @@ public class FlowUtils {
     public final static long REG_VALUE_FROM_LOCAL = 0x1L;
     public final static long REG_VALUE_FROM_REMOTE = 0x2L;
     public static final Class<? extends NxmNxReg> REG_FIELD = NxmNxReg0.class;
+    public static final int ARP_OP_REQUEST = 0x1;
+    public static final int ARP_OP_REPLY = 0x2;
+
 
     public static String getNodeName(long dpidLong) {
         return OPENFLOW + ":" + dpidLong;
@@ -98,17 +100,31 @@ public class FlowUtils {
         FlowBuilder flowBuilder = new FlowBuilder();
         flowBuilder.setMatch(new MatchBuilder().build());
 
-        String flowId = "DEFAULT_PIPELINE_FLOW_" + table;
-        flowBuilder.setId(new FlowId(flowId));
-        FlowKey key = new FlowKey(new FlowId(flowId));
-        flowBuilder.setStrict(true);
-        flowBuilder.setBarrier(false);
-        flowBuilder.setTableId(table);
-        flowBuilder.setKey(key);
-        flowBuilder.setFlowName(flowId);
-        flowBuilder.setHardTimeout(0);
-        flowBuilder.setIdleTimeout(0);
-        flowBuilder.setPriority(0);
+        String flowName = "DEFAULT_PIPELINE_FLOW_" + table;
+        return initFlowBuilder(flowBuilder, flowName, table)
+                .setPriority(0);
+    }
+
+    /**
+     * Sets up common defaults for the given flow builder: a flow identifier and key based on the given flow name,
+     * strict, no barrier, the given table identifier, no hard timeout and no idle timeout.
+     *
+     * @param flowBuilder The flow builder.
+     * @param flowName The flow name.
+     * @param table The table.
+     * @return The flow builder.
+     */
+    public static FlowBuilder initFlowBuilder(FlowBuilder flowBuilder, String flowName, short table) {
+        final FlowId flowId = new FlowId(flowName);
+        flowBuilder
+                .setId(flowId)
+                .setStrict(true)
+                .setBarrier(false)
+                .setTableId(table)
+                .setKey(new FlowKey(flowId))
+                .setFlowName(flowName)
+                .setHardTimeout(0)
+                .setIdleTimeout(0);
         return flowBuilder;
     }
 }
index 1bfde3e21f20e8897f2354d8d9b03d8843a626ba..4c59d45c555d382d70361647de70c6ff9620d4c6 100644 (file)
@@ -43,6 +43,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.acti
 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.action.types.rev131112.address.address.Ipv4Builder;
+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.types.rev131026.OutputPortValues;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
@@ -73,6 +75,7 @@ import org.slf4j.LoggerFactory;
 
 import java.math.BigInteger;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 
 public class InstructionUtils {
@@ -113,7 +116,7 @@ public class InstructionUtils {
     }
 
     /**
-     * Create LOCAL Reserved Port Instruction
+     * Create NORMAL Reserved Port Instruction (packet_in)
      *
      * @param nodeName Uri Prefix, containing nodeConnectorType and dpId (aka NodeId)
      * @param ib Map InstructionBuilder without any instructions
@@ -145,7 +148,7 @@ public class InstructionUtils {
     }
 
     /**
-     * Create NORMAL Reserved Port Instruction (packet_in)
+     * Create LOCAL Reserved Port Instruction
      *
      * @param ib Map InstructionBuilder without any instructions
      * @param dpidLong Long the datapath ID of a switch/node
@@ -1094,6 +1097,37 @@ public class InstructionUtils {
         return getInstructions(applyActionIns(dropAction()));
     }
 
+    /**
+     * Extracts the existing instructions (if any) from the flow.
+     *
+     * @param flow The flow.
+     * @return The instructions in the flow (empty if none).
+     */
+    public static List<Instruction> extractExistingInstructions(Flow flow) {
+        if (flow != null) {
+            Instructions ins = flow.getInstructions();
+            if (ins != null) {
+                return ins.getInstruction();
+            }
+        }
+        return Collections.emptyList();
+    }
+
+    /**
+     * Configures the flow builder to have the single given instruction.
+     *
+     * @param flowBuilder The flow builder.
+     * @param instruction The instruction.
+     * @return The flow builder.
+     */
+    public static FlowBuilder setFlowBuilderInstruction(FlowBuilder flowBuilder, Instruction instruction) {
+        flowBuilder.setInstructions(
+                new InstructionsBuilder()
+                        .setInstruction(Collections.singletonList(instruction))
+                        .build());
+        return flowBuilder;
+    }
+
     /**
      * Get a list of Instructions containing Nicira extensions that can have
      * additional OF/OXM instructions added to the returned Instruction list
index ef0960ffe15fdc30bc7495c59dd29b3d1f400757..930a1d507b8f25a70e7aee8f517819346630e24f 100644 (file)
@@ -81,6 +81,7 @@ public class MatchUtils {
     public static final String UDP = "udp";
     private static final int TCP_SYN = 0x0002;
     public static final String ICMP = "icmp";
+    public static final short ALL_ICMP = -1;
 
     /**
      * Create Ingress Port Match dpidLong, inPort
@@ -100,6 +101,17 @@ public class MatchUtils {
         return matchBuilder;
     }
 
+    public static MatchBuilder createInPortReservedMatch(MatchBuilder matchBuilder, Long dpidLong, String inPort) {
+
+        NodeConnectorId ncid = new NodeConnectorId("openflow:" + dpidLong + ":" + inPort);
+        LOG.debug("createInPortResrevedMatch() Node Connector ID is - Type=openflow: DPID={} inPort={} ",
+                dpidLong, inPort);
+        matchBuilder.setInPort(NodeConnectorId.getDefaultInstance(ncid.getValue()));
+        matchBuilder.setInPort(ncid);
+
+        return matchBuilder;
+    }
+
     /**
      * Create EtherType Match
      *
@@ -208,8 +220,10 @@ public class MatchUtils {
 
         // Build the ICMPv4 Match
         Icmpv4MatchBuilder icmpv4match = new Icmpv4MatchBuilder();
-        icmpv4match.setIcmpv4Type(type);
-        icmpv4match.setIcmpv4Code(code);
+        if (type != ALL_ICMP || code != ALL_ICMP) {
+            icmpv4match.setIcmpv4Type(type);
+            icmpv4match.setIcmpv4Code(code);
+        }
         matchBuilder.setIcmpv4Match(icmpv4match.build());
 
         return matchBuilder;
@@ -244,7 +258,8 @@ public class MatchUtils {
      */
     public static MatchBuilder createArpDstIpv4Match(MatchBuilder matchBuilder, Ipv4Prefix dstip) {
         ArpMatchBuilder arpDstMatch = new ArpMatchBuilder();
-        arpDstMatch.setArpTargetTransportAddress(dstip);
+        arpDstMatch.setArpTargetTransportAddress(dstip)
+                .setArpOp(FlowUtils.ARP_OP_REQUEST);
         matchBuilder.setLayer3Match(arpDstMatch.build());
 
         return matchBuilder;