Merge remote-tracking branch 'origin/master' into merge-branch
authorMadhu Venugopal <mavenugo@gmail.com>
Mon, 16 Jun 2014 23:07:37 +0000 (16:07 -0700)
committerMadhu Venugopal <mavenugo@gmail.com>
Tue, 17 Jun 2014 00:34:41 +0000 (17:34 -0700)
Signed-off-by: Madhu Venugopal <mavenugo@gmail.com>
Conflicts:
.gitignore
distribution/opendaylight/pom.xml
neutron/pom.xml
neutron/src/main/java/org/opendaylight/ovsdb/neutron/InternalNetworkManager.java
neutron/src/main/java/org/opendaylight/ovsdb/neutron/SouthboundHandler.java
neutron/src/main/java/org/opendaylight/ovsdb/neutron/TenantNetworkManager.java
neutron/src/main/java/org/opendaylight/ovsdb/neutron/provider/OF10Provider.java
neutron/src/main/java/org/opendaylight/ovsdb/neutron/provider/OF13ProviderManager.java
neutron/src/main/java/org/opendaylight/ovsdb/neutron/provider/ProviderNetworkManager.java
northbound/pom.xml
ovsdb/pom.xml
ovsdb/src/test/java/org/opendaylight/ovsdb/lib/message/OVSDBNettyFactoryIT.java
ovsdb/src/test/java/org/opendaylight/ovsdb/plugin/OvsdbTestDeletePortIT.java
plugin/src/main/java/org/opendaylight/ovsdb/plugin/ConfigurationService.java
plugin/src/test/java/org/opendaylight/ovsdb/plugin/OvsdbTestBase.java

Change-Id: Ib84968636e29a86a2308c112f251e7b5fd0ab0dc
Signed-off-by: Madhu Venugopal <mavenugo@gmail.com>
29 files changed:
1  2 
commons/parent/pom.xml
distribution/opendaylight/pom.xml
neutron/pom.xml
neutron/src/main/java/org/opendaylight/ovsdb/neutron/AdminConfigManager.java
neutron/src/main/java/org/opendaylight/ovsdb/neutron/InternalNetworkManager.java
neutron/src/main/java/org/opendaylight/ovsdb/neutron/NetworkHandler.java
neutron/src/main/java/org/opendaylight/ovsdb/neutron/NodeConfiguration.java
neutron/src/main/java/org/opendaylight/ovsdb/neutron/PortHandler.java
neutron/src/main/java/org/opendaylight/ovsdb/neutron/SouthboundEvent.java
neutron/src/main/java/org/opendaylight/ovsdb/neutron/SouthboundHandler.java
neutron/src/main/java/org/opendaylight/ovsdb/neutron/TenantNetworkManager.java
neutron/src/main/java/org/opendaylight/ovsdb/neutron/provider/OF10Provider.java
neutron/src/main/java/org/opendaylight/ovsdb/neutron/provider/OF13Provider.java
neutron/src/test/java/org/opendaylight/ovsdb/neutron/AdminConfigManagerTest.java
northbound/src/main/java/org/opendaylight/ovsdb/northbound/OVSDBRow.java
plugin/src/main/java/org/opendaylight/ovsdb/plugin/ConfigurationService.java
plugin/src/main/java/org/opendaylight/ovsdb/plugin/ConnectionService.java
plugin/src/main/java/org/opendaylight/ovsdb/plugin/InventoryService.java
plugin/src/main/java/org/opendaylight/ovsdb/plugin/OVSDBInventoryListener.java
plugin/src/test/java/org/opendaylight/ovsdb/plugin/OvsdbTestAddBridgeIT.java
plugin/src/test/java/org/opendaylight/ovsdb/plugin/OvsdbTestAddPortIT.java
plugin/src/test/java/org/opendaylight/ovsdb/plugin/OvsdbTestAddTunnelIT.java
plugin/src/test/java/org/opendaylight/ovsdb/plugin/OvsdbTestAddVlanIT.java
plugin/src/test/java/org/opendaylight/ovsdb/plugin/OvsdbTestBase.java
plugin/src/test/java/org/opendaylight/ovsdb/plugin/OvsdbTestBridgeConfigIT.java
plugin/src/test/java/org/opendaylight/ovsdb/plugin/OvsdbTestDeletePortIT.java
plugin/src/test/java/org/opendaylight/ovsdb/plugin/OvsdbTestGetBridgeDomainsIT.java
plugin/src/test/java/org/opendaylight/ovsdb/plugin/OvsdbTestSetManagerIT.java
plugin/src/test/java/org/opendaylight/ovsdb/plugin/OvsdbTestSetOFControllerIT.java

diff --combined commons/parent/pom.xml
index a752b6e7e7f641205ceb1685eaec7431b0f71e10,25a6b4d16126cb053236c54081a5c714071fc348..853afb8227d64e13f10e1cb335f9983815bb80ba
@@@ -7,8 -7,8 +7,8 @@@
      <version>1.4.2-SNAPSHOT</version>
    </parent>
    <groupId>org.opendaylight.ovsdb</groupId>
 -  <artifactId>commons.ovsdb</artifactId>
 -  <version>1.0.1-SNAPSHOT</version>
 +  <artifactId>ovsdb_commons</artifactId>
 +  <version>1.1.0-SNAPSHOT</version>
    <packaging>pom</packaging>
    <prerequisites>
      <maven>3.0</maven>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
  
+   <dependencyManagement>
+     <dependencies>
+       <dependency>
+         <groupId>org.opendaylight.ovsdb</groupId>
+         <artifactId>ovsdb</artifactId>
+         <version>0.5.1-SNAPSHOT</version>
+       </dependency>
+     </dependencies>
+   </dependencyManagement>
    <build>
      <pluginManagement>
        <plugins>
index da9a9a48adcf10f38728af0453bf836c23cbc8b7,04dd37a7b0543420cef754dd71e49d1dae418556..d81f9b21e12102d37463958b1cc47edcad9dfd0d
@@@ -7,8 -7,8 +7,8 @@@ see https://git.opendaylight.org/gerrit
    <modelVersion>4.0.0</modelVersion>
    <parent>
      <groupId>org.opendaylight.ovsdb</groupId>
 -    <artifactId>commons.ovsdb</artifactId>
 -    <version>1.0.1-SNAPSHOT</version>
 +    <artifactId>ovsdb_commons</artifactId>
 +    <version>1.1.0-SNAPSHOT</version>
      <relativePath>../../commons/parent/</relativePath>
    </parent>
  
    <packaging>pom</packaging>
    <name>ovsdb Distribution</name>
    <dependencies>
+     <dependency>
+       <groupId>org.opendaylight.openflowjava</groupId>
+       <artifactId>openflow-protocol-api</artifactId>
+       <version>0.5-SNAPSHOT</version>
+     </dependency>
+     <!-- openflowjava -->
+     <dependency>
+       <groupId>org.opendaylight.openflowjava</groupId>
+       <artifactId>openflow-protocol-impl</artifactId>
+       <version>0.5-SNAPSHOT</version>
+     </dependency>
+     <dependency>
+       <groupId>org.opendaylight.openflowjava</groupId>
+       <artifactId>openflow-protocol-spi</artifactId>
+       <version>0.5-SNAPSHOT</version>
+     </dependency>
+     <!-- openflowplugin -->
+     <dependency>
+       <groupId>org.opendaylight.openflowplugin</groupId>
+       <artifactId>openflowplugin</artifactId>
+       <version>0.0.3-SNAPSHOT</version>
+     </dependency>
+     <dependency>
+       <groupId>org.opendaylight.openflowplugin</groupId>
+       <artifactId>openflowplugin-controller-config</artifactId>
+       <version>0.0.3-SNAPSHOT</version>
+     </dependency>
      <dependency>
        <groupId>org.opendaylight.ovsdb</groupId>
 -      <artifactId>ovsdb</artifactId>
 -      <version>0.5.1-SNAPSHOT</version>
 +      <artifactId>ovsdb_library</artifactId>
 +      <version>1.0.0-SNAPSHOT</version>
      </dependency>
      <dependency>
        <groupId>org.opendaylight.ovsdb</groupId>
 -      <artifactId>ovsdb.neutron</artifactId>
 +      <artifactId>ovsdb_neutron</artifactId>
-       <version>0.6.0-SNAPSHOT</version>
+       <version>0.7.0-SNAPSHOT</version>
      </dependency>
      <dependency>
        <groupId>org.opendaylight.ovsdb</groupId>
 -      <artifactId>ovsdb.northbound</artifactId>
 -      <version>0.5.1-SNAPSHOT</version>
 +      <artifactId>ovsdb_northbound</artifactId>
 +      <version>0.6.0-SNAPSHOT</version>
 +    </dependency>
 +    <dependency>
 +      <groupId>org.opendaylight.ovsdb</groupId>
 +      <artifactId>ovsdb_plugin</artifactId>
 +      <version>1.0.0-SNAPSHOT</version>
      </dependency>
      <dependency>
        <groupId>org.opendaylight.controller</groupId>
                <ignorePermissions>false</ignorePermissions>
              </configuration>
            </execution>
+           <execution>
+             <id>unpack-provided-configs</id>
+             <goals>
+               <goal>unpack-dependencies</goal>
+             </goals>
+             <phase>generate-resources</phase>
+             <configuration>
+               <outputDirectory>${project.build.directory}/provided-configs</outputDirectory>
+               <includeArtifactIds>openflowplugin-controller-config</includeArtifactIds>
+               <includes>**\/*.xml</includes>
+               <excludeTransitive>true</excludeTransitive>
+               <ignorePermissions>false</ignorePermissions>
+             </configuration>
+           </execution>
          </executions>
        </plugin>
      </plugins>
diff --combined neutron/pom.xml
index 2716c442ef258038e6180e98e09dafd3a386b857,77d9c8cf26defb74b91db46025488b5d48e48724..b7f51c3168725ab5a8aad34c18fe810c424e8827
@@@ -3,13 -3,13 +3,13 @@@
    <modelVersion>4.0.0</modelVersion>
    <parent>
      <groupId>org.opendaylight.ovsdb</groupId>
 -    <artifactId>commons.ovsdb</artifactId>
 -    <version>1.0.1-SNAPSHOT</version>
 +    <artifactId>ovsdb_commons</artifactId>
 +    <version>1.1.0-SNAPSHOT</version>
      <relativePath>../commons/parent</relativePath>
    </parent>
  
 -  <artifactId>ovsdb.neutron</artifactId>
 +  <artifactId>ovsdb_neutron</artifactId>
-   <version>0.6.0-SNAPSHOT</version>
+   <version>0.7.0-SNAPSHOT</version>
    <packaging>bundle</packaging>
  
    <properties>
      </dependency>
      <dependency>
        <groupId>org.opendaylight.ovsdb</groupId>
 -      <artifactId>ovsdb</artifactId>
 -      <version>0.5.1-SNAPSHOT</version>
 +      <artifactId>ovsdb_library</artifactId>
 +      <version>1.0.0-SNAPSHOT</version>
 +    </dependency>
 +    <dependency>
 +      <groupId>org.opendaylight.ovsdb</groupId>
 +      <artifactId>ovsdb_plugin</artifactId>
 +      <version>1.0.0-SNAPSHOT</version>
      </dependency>
      <dependency>
        <groupId>org.opendaylight.yangtools</groupId>
                org.opendaylight.ovsdb.plugin,
                org.opendaylight.ovsdb.lib.notation,
                org.opendaylight.ovsdb.lib.table,
 -              org.opendaylight.ovsdb.lib.table.internal,
                org.opendaylight.controller.sal.binding.api,
                org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819,
                org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes,
            </instructions>
          </configuration>
        </plugin>
      </plugins>
    </build>
  
index a251d675b165c3b22fe3dd7b031642e825b7bcfb,cc108fe1e55a211efe4da49c696d90b77685bed5..9df091ed9dac28cc8deafebfb9e4560b8248bed6
@@@ -5,65 -5,69 +5,69 @@@
   * terms of the Eclipse Public License v1.0 which accompanies this distribution,
   * and is available at http://www.eclipse.org/legal/epl-v10.html
   *
-  * Authors : Madhu Venugopal, Brent Salisbury
+  * Authors : Madhu Venugopal, Brent Salisbury, Sam Hague
   */
  package org.opendaylight.ovsdb.neutron;
  
  import java.net.InetAddress;
+ import java.util.ArrayList;
+ import java.util.List;
  import java.util.Map;
  
  import org.opendaylight.controller.sal.core.Node;
  import org.opendaylight.controller.sal.utils.ServiceHelper;
  import org.opendaylight.ovsdb.lib.table.Open_vSwitch;
 -import org.opendaylight.ovsdb.lib.table.internal.Table;
 +import org.opendaylight.ovsdb.lib.table.Table;
  import org.opendaylight.ovsdb.plugin.OVSDBConfigService;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  
- public class AdminConfigManager {
+ public class AdminConfigManager implements IAdminConfigManager{
      static final Logger logger = LoggerFactory.getLogger(AdminConfigManager.class);
  
      private String integrationBridgeName;
-     private String tunnelBridgeName;
+     private String networkBridgeName;
      private String externalBridgeName;
      private String tunnelEndpointConfigName;
      private String patchToIntegration;
-     private String patchToTunnel;
+     private String patchToNetwork;
+     private String providerMappingsConfigName;
+     private String providerMappings;
  
      // Refer to /etc/quantum/plugins/openvswitch/ovs_quantum_plugin.ini
      private static String DEFAULT_TUNNEL_ENDPOINT_CONFIG_STRING = "local_ip";
      private static String DEFAULT_INTEGRATION_BRIDGENAME = "br-int";
-     private static String DEFAULT_TUNNEL_BRIDGENAME = "br-tun";
+     private static String DEFAULT_NETWORK_BRIDGENAME = "br-net";
      private static String DEFAULT_EXTERNAL_BRIDGENAME = "br-ex";
      private static String DEFAULT_PATCH_TO_INTEGRATION = "patch-int";
-     private static String DEFAULT_PATCH_TO_TUNNEL = "patch-tun";
+     private static String DEFAULT_PATCH_TO_NETWORK = "patch-net";
      private static String CONFIG_TUNNEL_ENDPOINT_CONFIG = "tunnel_endpoint_config_string";
      private static String CONFIG_INTEGRATION_BRIDGENAME = "integration_bridge";
-     private static String CONFIG_TUNNEL_BRIDGENAME = "tunnel_bridge";
+     private static String CONFIG_NETWORK_BRIDGENAME = "network_bridge";
      private static String CONFIG_EXTERNAL_BRIDGENAME = "external_bridge";
      private static String CONFIG_PATCH_TO_INTEGRATION = "patch-int";
-     private static String CONFIG_PATCH_TO_TUNNEL = "patch-tun";
+     private static String CONFIG_PATCH_TO_NETWORK = "patch-net";
+     private static String DEFAULT_PROVIDER_MAPPINGS_CONFIG_STRING = "provider_mappings";
+     private static String CONFIG_PROVIDER_MAPPINGS_CONFIG = "provider_mappings_config_string";
+     private static String CONFIG_PROVIDER_MAPPINGS = "provider_mappings";
  
-     private static AdminConfigManager adminConfiguration = new AdminConfigManager();
-     private AdminConfigManager() {
+     public AdminConfigManager() {
          tunnelEndpointConfigName = System.getProperty(CONFIG_TUNNEL_ENDPOINT_CONFIG);
          integrationBridgeName = System.getProperty(CONFIG_INTEGRATION_BRIDGENAME);
-         tunnelBridgeName = System.getProperty(CONFIG_TUNNEL_BRIDGENAME);
+         networkBridgeName = System.getProperty(CONFIG_NETWORK_BRIDGENAME);
          externalBridgeName = System.getProperty(CONFIG_EXTERNAL_BRIDGENAME);
          patchToIntegration = System.getProperty(CONFIG_PATCH_TO_INTEGRATION);
-         patchToTunnel = System.getProperty(CONFIG_PATCH_TO_TUNNEL);
+         patchToNetwork = System.getProperty(CONFIG_PATCH_TO_NETWORK);
+         providerMappingsConfigName = System.getProperty(CONFIG_PROVIDER_MAPPINGS_CONFIG);
+         providerMappings = System.getProperty(CONFIG_PROVIDER_MAPPINGS);
  
          if (tunnelEndpointConfigName == null) tunnelEndpointConfigName = DEFAULT_TUNNEL_ENDPOINT_CONFIG_STRING;
          if (integrationBridgeName == null) integrationBridgeName = DEFAULT_INTEGRATION_BRIDGENAME;
-         if (tunnelBridgeName == null) tunnelBridgeName = DEFAULT_TUNNEL_BRIDGENAME;
+         if (networkBridgeName == null) networkBridgeName = DEFAULT_NETWORK_BRIDGENAME;
          if (externalBridgeName == null) externalBridgeName = DEFAULT_EXTERNAL_BRIDGENAME;
          if (patchToIntegration == null) patchToIntegration = DEFAULT_PATCH_TO_INTEGRATION;
-         if (patchToTunnel == null) patchToTunnel = DEFAULT_PATCH_TO_TUNNEL;
-     }
-     public static AdminConfigManager getManager() {
-         return adminConfiguration;
+         if (patchToNetwork == null) patchToNetwork  = DEFAULT_PATCH_TO_NETWORK;
+         if (providerMappingsConfigName == null) providerMappingsConfigName = DEFAULT_PROVIDER_MAPPINGS_CONFIG_STRING;
      }
  
      public String getIntegrationBridgeName() {
          this.integrationBridgeName = integrationBridgeName;
      }
  
-     public String getTunnelBridgeName() {
-         return tunnelBridgeName;
-     }
+     public String getNetworkBridgeName() { return networkBridgeName; }
  
-     public void setTunnelBridgeName(String tunnelBridgeName) {
-         this.tunnelBridgeName = tunnelBridgeName;
+     public void setNetworkBridgeName(String networkBridgeName) {
+         this.networkBridgeName = networkBridgeName;
      }
  
      public String getExternalBridgeName() {
          this.patchToIntegration = patchToIntegration;
      }
  
-     public String getPatchToTunnel() {
-         return patchToTunnel;
-     }
+     public String getPatchToNetwork() { return patchToNetwork; }
  
-     public void setPatchToTunnel(String patchToTunnel) {
-         this.patchToTunnel = patchToTunnel;
+     public void setPatchToNetwork(String patchToNetwork) {
+         this.patchToNetwork = patchToNetwork;
      }
  
      public InetAddress getTunnelEndPoint(Node node) {
          return address;
      }
  
+     /*
+      * Return the physical interface mapped to the given neutron physical network.
+      * Provider mappings will be of the following format:
+      * provider_mappings=physnet1:eth1[,physnet2:eth2]
+      */
+       public String getPhysicalInterfaceName (Node node, String physicalNetwork) {
+           String phyIf = null;
+           OVSDBConfigService ovsdbConfig = (OVSDBConfigService) ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
+           try {
+             Map<String, Table<?>> ovsTable = ovsdbConfig.getRows(node, Open_vSwitch.NAME.getName());
+             if (ovsTable == null) {
+                 logger.error("Open_vSwitch table is null for Node {} ", node);
+                 return null;
+             }
+             // Loop through all the Open_vSwitch rows looking for the first occurrence of other_config.
+             // The specification does not restrict the number of rows so we choose the first we find.
+             for (Table<?> row : ovsTable.values()) {
+                 String providerMaps;
+                 Open_vSwitch ovsRow = (Open_vSwitch) row;
+                 Map<String, String> configs = ovsRow.getOther_config();
+                 if (configs == null) {
+                     logger.debug("Open_vSwitch table is null for Node {} ", node);
+                     continue;
+                 }
+                 providerMaps = configs.get(providerMappingsConfigName);
+                 if (providerMaps == null) {
+                     providerMaps = providerMappings;
+                 }
+                 if (providerMaps != null) {
+                     for (String map : providerMaps.split(",")) {
+                         String[] pair = map.split(":");
+                         if (pair[0].equals(physicalNetwork)) {
+                             phyIf = pair[1];
+                             break;
+                         }
+                     }
+                 }
+                 if (phyIf != null) {
+                     break;
+                 }
+             }
+         } catch (Exception e) {
+             logger.error("Unable to find physical interface for Node: {}, Network {}",
+                     node, physicalNetwork, e);
+         }
+         if (phyIf == null) {
+             logger.error("Physical interface not found for Node: {}, Network {}",
+                     node, physicalNetwork);
+         }
+         return phyIf;
+     }
+     /* Return all physical interfaces configure in bridge mapping
+      * Bridge mappings will be of the following format:
+      * bridge_mappings=physnet1:eth1,physnet2:eth2
+      * Method will return list = {eth1, eth2}
+      */
+     public List<String> getAllPhysicalInterfaceNames(Node node) {
+         List<String> phyIfName = new ArrayList<String>();
+         try {
+             OVSDBConfigService ovsdbConfig = (OVSDBConfigService) ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
+             Map<String, Table<?>> ovsTable = ovsdbConfig.getRows(node, Open_vSwitch.NAME.getName());
+             if (ovsTable == null) {
+                 logger.error("Open_vSwitch table is null for Node {} ", node);
+                 return null;
+             }
+             // While there is only one entry in the HashMap, we can't access it by index...
+             for (Table<?> row : ovsTable.values()) {
+                 String bridgeMaps;
+                 Open_vSwitch ovsRow = (Open_vSwitch) row;
+                 Map<String, String> configs = ovsRow.getOther_config();
+                 if (configs == null) {
+                     logger.debug("Open_vSwitch table is null for Node {} ", node);
+                     continue;
+                 }
+                 bridgeMaps = configs.get(providerMappingsConfigName);
+                 if (bridgeMaps == null) {
+                     bridgeMaps = providerMappings;
+                 }
+                 if (bridgeMaps != null) {
+                     for (String map : bridgeMaps.split(",")) {
+                         String[] pair = map.split(":");
+                         phyIfName.add(pair[1]);
+                     }
+                 }
+             }
+         } catch (Exception e) {
+             logger.error("Unable to find physical interface for Node: {}",
+                     node, e);
+         }
+         logger.debug("Physical interface for Node: {}, If: {}",
+                 node, phyIfName);
+         return phyIfName;
+     }
      public boolean isInterested (String tableName) {
          return tableName.equalsIgnoreCase(Open_vSwitch.NAME.getName());
      }
index 53dff68c75dca192d686587e434104a6b8de7d60,5ff7c18f5e3e52e2bbbdf5341c53e4c011c8f042..dbfd0da99024180ca099e05818a60f06b73aa22f
@@@ -5,12 -5,13 +5,13 @@@
   * terms of the Eclipse Public License v1.0 which accompanies this distribution,
   * and is available at http://www.eclipse.org/legal/epl-v10.html
   *
-  * Authors : Madhu Venugopal, Brent Salisbury
+  * Authors : Madhu Venugopal, Brent Salisbury, Sam Hague
   */
  package org.opendaylight.ovsdb.neutron;
  
  import java.util.Map;
  
+ import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork;
  import org.opendaylight.controller.sal.core.Node;
  import org.opendaylight.controller.sal.utils.ServiceHelper;
  import org.opendaylight.controller.sal.utils.Status;
@@@ -21,8 -22,8 +22,8 @@@ import org.opendaylight.ovsdb.lib.notat
  import org.opendaylight.ovsdb.lib.table.Bridge;
  import org.opendaylight.ovsdb.lib.table.Interface;
  import org.opendaylight.ovsdb.lib.table.Port;
 -import org.opendaylight.ovsdb.lib.table.internal.Table;
 +import org.opendaylight.ovsdb.lib.table.Table;
- import org.opendaylight.ovsdb.neutron.provider.ProviderNetworkManager;
+ import org.opendaylight.ovsdb.neutron.provider.IProviderNetworkManager;
  import org.opendaylight.ovsdb.plugin.IConnectionServiceInternal;
  import org.opendaylight.ovsdb.plugin.OVSDBConfigService;
  import org.opendaylight.ovsdb.plugin.StatusWithUuid;
@@@ -30,24 -31,23 +31,23 @@@ import org.slf4j.Logger
  import org.slf4j.LoggerFactory;
  
  /**
-  * OpenStack Neutron with the OpenVswitch data plan relies on a typical OVS bridge configurations that
+  * OpenStack Neutron with the OpenvSwitch data plan relies on a typical OVS bridge configurations that
   * consists of br-int (Integration Bridge), br-tun (Tunnel bridge), br-ex (External bridge).
   *
   * In DevStack like setups, the br-tun is not automatically created on the controller nodes.
-  * Hence this class attempts to bring all the nodes to be elibible for OpenStack operations.
+  * Hence this class attempts to bring all the nodes to be eligible for OpenStack operations.
   *
   */
- public class InternalNetworkManager {
+ public class InternalNetworkManager implements IInternalNetworkManager {
      static final Logger logger = LoggerFactory.getLogger(InternalNetworkManager.class);
      private static final int LLDP_PRIORITY = 1000;
      private static final int NORMAL_PRIORITY = 0;
  
-     private static InternalNetworkManager internalNetwork = new InternalNetworkManager();
-     private InternalNetworkManager() {
-     }
+     // The implementation for each of these services is resolved by the OSGi Service Manager
+     private volatile IAdminConfigManager adminConfigManager;
+     private volatile IProviderNetworkManager providerNetworkManager;
  
-     public static InternalNetworkManager getManager() {
-         return internalNetwork;
+     public InternalNetworkManager() {
      }
  
      public String getInternalBridgeUUID (Node node, String bridgeName) {
          return null;
      }
  
+     public Bridge getInternalBridge (Node node, String bridgeName) {
+         try {
+             OVSDBConfigService ovsdbTable = (OVSDBConfigService) ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
+             Map<String, Table<?>> bridgeTable = ovsdbTable.getRows(node, Bridge.NAME.getName());
+             if (bridgeTable != null) {
+                 for (String key : bridgeTable.keySet()) {
+                     Bridge bridge = (Bridge) bridgeTable.get(key);
+                     if (bridge.getName().equals(bridgeName)) {
+                         return bridge;
+                     }
+                 }
+             }
+         } catch (Exception e) {
+             logger.error("Error getting Bridge Identifier for {} / {}", node, bridgeName, e);
+         }
+         return null;
+     }
      public boolean isInternalNetworkNeutronReady(Node node) {
-         if (this.getInternalBridgeUUID(node, AdminConfigManager.getManager().getIntegrationBridgeName()) != null) {
+         if (this.getInternalBridgeUUID(node, adminConfigManager.getIntegrationBridgeName()) != null) {
              return true;
          } else {
              return false;
          if (!this.isInternalNetworkNeutronReady(node)) {
              return false;
          }
-         if (this.getInternalBridgeUUID(node, AdminConfigManager.getManager().getTunnelBridgeName()) != null) {
+         if (this.getInternalBridgeUUID(node, adminConfigManager.getNetworkBridgeName()) != null) {
              return true;
          } else {
              return false;
          }
      }
  
+     public boolean isPortOnBridge (Node node, Bridge bridge, String portName) {
+         OVSDBConfigService ovsdbTable = (OVSDBConfigService) ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
+         for (UUID portsUUID : bridge.getPorts()) {
+             try {
+                 Port port = (Port) ovsdbTable.getRow(node, Port.NAME.getName(), portsUUID.toString());
+                 if ((port != null) && port.getName().equalsIgnoreCase(portName)) {
+                     return true;
+                 }
+             } catch (Exception e) {
+                 logger.error("Error getting port {} for bridge domain {}/{}", portsUUID, node, bridge.getName(), e);
+             }
+         }
+         return false;
+     }
+     public boolean isNetworkPatchCreated (Node node, Bridge intBridge, Bridge netBridge) {
+         boolean isPatchCreated = false;
+         String portName = adminConfigManager.getPatchToNetwork();
+         if (isPortOnBridge(node, intBridge, portName)) {
+             portName = adminConfigManager.getPatchToIntegration();
+             if (isPortOnBridge(node, netBridge, portName)) {
+                 isPatchCreated = true;
+             }
+         }
+         return isPatchCreated;
+     }
+     /* Determine if internal network is ready for tunnel network types.
+      * - OF 1.0 requires br-int, br-net and a patch connecting them.
+      * - OF 1.3 requires br-int.
+      */
+     public boolean isInternalNetworkTunnelReady (Node node) {
+         /* Is br-int created? */
+         Bridge intBridge = this.getInternalBridge(node, adminConfigManager.getIntegrationBridgeName());
+         if (intBridge == null) {
+             return false;
+         }
+         if (providerNetworkManager == null) {
+             logger.error("Provider Network Manager is not available");
+             return false;
+         }
+         if (providerNetworkManager.getProvider().hasPerTenantTunneling()) {
+             /* Is br-net created? */
+             Bridge netBridge = this.getInternalBridge(node, adminConfigManager.getNetworkBridgeName());
+             if (netBridge == null) {
+                 return false;
+             }
+             if (!isNetworkPatchCreated(node, intBridge, netBridge)) {
+                 return false;
+             }
+         }
+         return true;
+     }
+     /* Determine if internal network is ready for vlan network types.
+      * - OF 1.0 requires br-int, br-net, a patch connecting them and
+      * physical device added to br-net.
+      * - OF 1.3 requires br-int and physical device added to br-int.
+      */
+     public boolean isInternalNetworkVlanReady (Node node, NeutronNetwork network) {
+         /* is br-int created */
+         Bridge intBridge = this.getInternalBridge(node, adminConfigManager.getIntegrationBridgeName());
+         if (intBridge == null) {
+             logger.trace("shague isInternalNetworkVlanReady: node: {}, br-int missing", node);
+             return false;
+         }
+         if (providerNetworkManager == null) {
+             logger.error("Provider Network Manager is not available");
+             return false;
+         }
+         if (providerNetworkManager.getProvider().hasPerTenantTunneling()) {
+             /* is br-net created? */
+             Bridge netBridge = this.getInternalBridge(node, adminConfigManager.getNetworkBridgeName());
+             if (netBridge == null) {
+                 logger.trace("shague isInternalNetworkVlanReady: node: {}, br-net missing", node);
+                 return false;
+             }
+             if (!isNetworkPatchCreated(node, intBridge, netBridge)) {
+                 logger.trace("shague isInternalNetworkVlanReady: node: {}, patch missing", node);
+                 return false;
+             }
+             /* Check if physical device is added to br-net. */
+             String phyNetName = adminConfigManager.getPhysicalInterfaceName(node, network.getProviderPhysicalNetwork());
+             if (isPortOnBridge(node, netBridge, phyNetName)) {
+                 return true;
+             }
+         } else {
+             /* Check if physical device is added to br-int. */
+             String phyNetName = adminConfigManager.getPhysicalInterfaceName(node, network.getProviderPhysicalNetwork());
+             if (isPortOnBridge(node, intBridge, phyNetName)) {
+                 return true;
+             }
+         }
+         logger.trace("shague isInternalNetworkVlanReady: node: {}, eth missing", node);
+         return false;
+     }
+     /*
+      * Create the integration bridge.
+      *
+        Bridge br-int
+             Port br-int
+                 Interface br-int
+                     type: internal
+      */
+     public void createIntegrationBridge (Node node) throws Exception {
+         String brInt = adminConfigManager.getIntegrationBridgeName();
+         Status status = this.addInternalBridge(node, brInt, null, null);
+         if (!status.isSuccess()) {
+             logger.debug("Integration Bridge Creation Status: {}", status);
+         }
+     }
      /*
-      * Lets create these if not already present :
+      * Create complete network for all network types and OpenFlow versions.
       *
+        OF 1.0 vlan:
         Bridge br-int
-             Port patch-tun
-                 Interface patch-tun
+             Port patch-net
+                 Interface patch-net
                      type: patch
                      options: {peer=patch-int}
              Port br-int
                  Interface br-int
                      type: internal
-       Bridge br-tun
+        Bridge br-net
+             Port "eth1"
+                 Interface "eth1"
              Port patch-int
                  Interface patch-int
                      type: patch
-                     options: {peer=patch-tun}
-             Port br-tun
-                 Interface br-tun
+                     options: {peer=patch-net}
+             Port br-net
+                 Interface br-net
                      type: internal
-      */
-     public void createInternalNetworkForOverlay(Node node) throws Exception {
-         String brTun = AdminConfigManager.getManager().getTunnelBridgeName();
-         String brInt = AdminConfigManager.getManager().getIntegrationBridgeName();
-         String patchInt = AdminConfigManager.getManager().getPatchToIntegration();
-         String patchTun = AdminConfigManager.getManager().getPatchToTunnel();
  
-         Status status = this.addInternalBridge(node, brInt, patchTun, patchInt);
-         if (!status.isSuccess()) logger.debug("Integration Bridge Creation Status : "+status.toString());
-         if (ProviderNetworkManager.getManager().hasPerTenantTunneling()) {
-             status = this.addInternalBridge(node, brTun, patchInt, patchTun);
-             if (!status.isSuccess()) logger.debug("Tunnel Bridge Creation Status : "+status.toString());
-         }
-     }
+        OF 1.0 tunnel:
+        Bridge br-int
+             Port patch-net
+                 Interface patch-net
+                     type: patch
+                     options: {peer=patch-int}
+             Port br-int
+                 Interface br-int
+                     type: internal
+        Bridge "br-net"
+             Port patch-int
+                 Interface patch-int
+                     type: patch
+                     options: {peer=patch-net}
+             Port br-net
+                 Interface br-net
+                     type: internal
  
-     /*
-      * Lets create these if not already present :
-      *
+        OF 1.3 vlan:
+        Bridge br-int
+             Port "eth1"
+                 Interface "eth1"
+             Port br-int
+                 Interface br-int
+                     type: internal
+        OF 1.3 tunnel:
         Bridge br-int
              Port br-int
                  Interface br-int
                      type: internal
       */
-     public void createInternalNetworkForNeutron(Node node) throws Exception {
-         String brInt = AdminConfigManager.getManager().getIntegrationBridgeName();
+     public boolean createNetNetwork (Node node, NeutronNetwork network) throws Exception {
+         Status status;
  
-         Status status = this.addInternalBridge(node, brInt, null, null);
-         if (!status.isSuccess()) logger.debug("Integration Bridge Creation Status : "+status.toString());
-     }
+         logger.debug("createNetNetwork: node: {}, network type: {}", node, network.getProviderNetworkType());
  
-     private Status addInternalBridge (Node node, String bridgeName, String localPathName, String remotePatchName) throws Exception {
-         OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
+         if (providerNetworkManager == null) {
+             logger.error("Provider Network Manager is not available");
+             return false;
+         }
+         if (providerNetworkManager.getProvider().hasPerTenantTunneling()) { /* indicates OF 1.0 */
+             String brInt = adminConfigManager.getIntegrationBridgeName();
+             String brNet = adminConfigManager.getNetworkBridgeName();
+             String patchNet = adminConfigManager.getPatchToNetwork();
+             String patchInt = adminConfigManager.getPatchToIntegration();
  
-         String bridgeUUID = this.getInternalBridgeUUID(node, bridgeName);
-         Bridge bridge = new Bridge();
-         OvsDBSet<String> failMode = new OvsDBSet<String>();
-         failMode.add("secure");
-         bridge.setFail_mode(failMode);
+             status = this.addInternalBridge(node, brInt, patchNet, patchInt);
+             if (!status.isSuccess()) {
+                 logger.debug("{} Bridge Creation Status: {}", brInt, status);
+                 return false;
+             }
+             status = this.addInternalBridge(node, brNet, patchInt, patchNet);
+             if (!status.isSuccess()) {
+                 logger.debug("{} Bridge Creation Status: {}", brNet, status);
+                 return false;
+             }
  
-         OvsDBSet<String> protocols = new OvsDBSet<String>();
-         if (!ProviderNetworkManager.getManager().hasPerTenantTunneling()) {
-             protocols.add("OpenFlow13");
+             /* For vlan network types add physical port to br-net. */
+             if (network.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VLAN)) {
+                 String phyNetName = adminConfigManager.getPhysicalInterfaceName(node, network.getProviderPhysicalNetwork());
+                 status = addPortToBridge(node, brNet, phyNetName);
+                 if (!status.isSuccess()) {
+                     logger.debug("Add Port {} to Bridge {} Status: {}", phyNetName, brNet, status);
+                     return false;
+                 }
+             }
          } else {
-             protocols.add("OpenFlow10");
+             String brInt = adminConfigManager.getIntegrationBridgeName();
+             status = this.addInternalBridge(node, brInt, null, null);
+             if (!status.isSuccess()) {
+                 logger.debug("{} Bridge Creation Status: {}", brInt, status);
+                 return false;
+             }
+             /* For vlan network types add physical port to br-int. */
+             if (network.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VLAN)) {
+                 String phyNetName = adminConfigManager.getPhysicalInterfaceName(node, network.getProviderPhysicalNetwork());
+                 status = addPortToBridge(node, brInt, phyNetName);
+                 if (!status.isSuccess()) {
+                     logger.debug("Add Port {} to Bridge {} Status: {}", phyNetName, brInt, status);
+                     return false;
+                 }
+             }
          }
-         bridge.setProtocols(protocols);
  
+         logger.debug("createNetNetwork: node: {}, status: success", node);
+         return true;
+     }
+     private Status addPortToBridge (Node node, String bridgeName, String portName) throws Exception {
+         logger.debug("addPortToBridge: Adding port: {} to Bridge {}, Node {}", portName, bridgeName, node);
+         OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
+         String bridgeUUID = this.getInternalBridgeUUID(node, bridgeName);
          if (bridgeUUID == null) {
-             bridge.setName(bridgeName);
+             logger.error("addPortToBridge: Could not find Bridge {} in Node {}", bridgeName, node);
+             return new Status(StatusCode.NOTFOUND, "Could not find "+bridgeName+" in "+node);
+         }
  
-             StatusWithUuid statusWithUuid = ovsdbTable.insertRow(node, Bridge.NAME.getName(), null, bridge);
-             if (!statusWithUuid.isSuccess()) return statusWithUuid;
-             bridgeUUID = statusWithUuid.getUuid().toString();
-             Port port = new Port();
-             port.setName(bridgeName);
-             Status status = ovsdbTable.insertRow(node, Port.NAME.getName(), bridgeUUID, port);
-             logger.debug("addInternalBridge : Inserting Bridge {} with protocols {} and status {}", bridgeUUID, protocols, status);
+         /* Check if the port already exists. */
+         Bridge bridge = (Bridge)ovsdbTable.getRow(node, Bridge.NAME.getName(), bridgeUUID);
+         if (bridge != null) {
+             if (isPortOnBridge(node, bridge, portName)) {
+                 logger.debug("addPortToBridge: Port {} already in Bridge {}, Node {}", portName, bridgeName, node);
+                 return new Status(StatusCode.SUCCESS);
+             }
          } else {
-             Status status = ovsdbTable.updateRow(node, Bridge.NAME.getName(), null, bridgeUUID, bridge);
-             logger.debug("addInternalBridge : Updating Bridge {} with protocols {} and status {}", bridgeUUID, protocols, status);
+             logger.error("addPortToBridge: Could not find Port {} in Bridge {}, Node {}", portName, bridgeName, node);
+             return new Status(StatusCode.NOTFOUND, "Could not find "+portName+" in "+bridgeName);
          }
  
-         IConnectionServiceInternal connectionService = (IConnectionServiceInternal)ServiceHelper.getGlobalInstance(IConnectionServiceInternal.class, this);
-         connectionService.setOFController(node, bridgeUUID);
+         Port port = new Port();
+         port.setName(portName);
+         StatusWithUuid statusWithUuid = ovsdbTable.insertRow(node, Port.NAME.getName(), bridgeUUID, port);
+         if (!statusWithUuid.isSuccess()) {
+             logger.error("addPortToBridge: Failed to add Port {} in Bridge {}, Node {}", portName, bridgeName, node);
+             return statusWithUuid;
+         }
  
-         if (localPathName != null && remotePatchName != null && ProviderNetworkManager.getManager().hasPerTenantTunneling()) {
-             return addPatchPort(node, bridgeUUID, localPathName, remotePatchName);
+         String portUUID = statusWithUuid.getUuid().toString();
+         String interfaceUUID = null;
+         int timeout = 6;
+         while ((interfaceUUID == null) && (timeout > 0)) {
+             port = (Port)ovsdbTable.getRow(node, Port.NAME.getName(), portUUID);
+             OvsDBSet<UUID> interfaces = port.getInterfaces();
+             if (interfaces == null || interfaces.size() == 0) {
+                 // Wait for the OVSDB update to sync up the Local cache.
+                 Thread.sleep(500);
+                 timeout--;
+                 continue;
+             }
+             interfaceUUID = interfaces.toArray()[0].toString();
+             Interface intf = (Interface)ovsdbTable.getRow(node, Interface.NAME.getName(), interfaceUUID);
+             if (intf == null) {
+                 interfaceUUID = null;
+             }
          }
+         if (interfaceUUID == null) {
+             logger.error("addPortToBridge: Cannot identify Interface for port {}/{}", portName, portUUID);
+             return new Status(StatusCode.INTERNALERROR);
+         }
          return new Status(StatusCode.SUCCESS);
      }
  
-     private Status addPatchPort (Node node, String bridgeUUID, String portName, String patchName) throws Exception {
+     private Status addPatchPort (Node node, String bridgeUUID, String portName, String peerPortName) throws Exception {
          OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
  
+         logger.debug("addPatchPort: node: {}, bridgeUUID: {}, port: {}, peer: {}",
+                 node, bridgeUUID, portName, peerPortName);
+         /* Check if the port already exists. */
+         Bridge bridge = (Bridge)ovsdbTable.getRow(node, Bridge.NAME.getName(), bridgeUUID);
+         if (bridge != null) {
+             if (isPortOnBridge(node, bridge, portName)) {
+                 logger.debug("addPatchPort: Port {} already in Bridge, Node {}", portName, node);
+                 return new Status(StatusCode.SUCCESS);
+             }
+         } else {
+             logger.error("addPatchPort: Could not find Port {} in Bridge, Node {}", portName, node);
+             return new Status(StatusCode.NOTFOUND, "Could not find "+portName+" in Bridge");
+         }
          Port patchPort = new Port();
          patchPort.setName(portName);
          // Create patch port and interface
              return new Status(StatusCode.INTERNALERROR);
          }
  
-         Interface tunInterface = new Interface();
-         tunInterface.setType("patch");
+         Interface intf = new Interface();
+         intf.setType("patch");
          OvsDBMap<String, String> options = new OvsDBMap<String, String>();
-         options.put("peer", patchName);
-         tunInterface.setOptions(options);
-         return ovsdbTable.updateRow(node, Interface.NAME.getName(), patchPortUUID, interfaceUUID, tunInterface);
+         options.put("peer", peerPortName);
+         intf.setOptions(options);
+         return ovsdbTable.updateRow(node, Interface.NAME.getName(), patchPortUUID, interfaceUUID, intf);
+     }
+     private Status addInternalBridge (Node node, String bridgeName, String localPatchName, String remotePatchName) throws Exception {
+         OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
+         String bridgeUUID = this.getInternalBridgeUUID(node, bridgeName);
+         Bridge bridge = new Bridge();
+         OvsDBSet<String> failMode = new OvsDBSet<String>();
+         failMode.add("secure");
+         bridge.setFail_mode(failMode);
+         OvsDBSet<String> protocols = new OvsDBSet<String>();
+         if (providerNetworkManager == null) {
+             logger.error("Provider Network Manager is not available");
+             return new Status(StatusCode.INTERNALERROR);
+         }
+         if (!providerNetworkManager.getProvider().hasPerTenantTunneling()) {
+             protocols.add("OpenFlow13");
+         } else {
+             protocols.add("OpenFlow10");
+         }
+         bridge.setProtocols(protocols);
+         if (bridgeUUID == null) {
+             bridge.setName(bridgeName);
+             StatusWithUuid statusWithUuid = ovsdbTable.insertRow(node, Bridge.NAME.getName(), null, bridge);
+             if (!statusWithUuid.isSuccess()) return statusWithUuid;
+             bridgeUUID = statusWithUuid.getUuid().toString();
+             Port port = new Port();
+             port.setName(bridgeName);
+             Status status = ovsdbTable.insertRow(node, Port.NAME.getName(), bridgeUUID, port);
+             logger.debug("addInternalBridge: Inserting Bridge {} {} with protocols {} and status {}",
+                     bridgeName, bridgeUUID, protocols, status);
+         } else {
+             Status status = ovsdbTable.updateRow(node, Bridge.NAME.getName(), null, bridgeUUID, bridge);
+             logger.debug("addInternalBridge: Updating Bridge {} {} with protocols {} and status {}",
+                     bridgeName, bridgeUUID, protocols, status);
+         }
+         IConnectionServiceInternal connectionService = (IConnectionServiceInternal)ServiceHelper.getGlobalInstance(IConnectionServiceInternal.class, this);
+         connectionService.setOFController(node, bridgeUUID);
+         if (localPatchName != null && remotePatchName != null && providerNetworkManager.getProvider().hasPerTenantTunneling()) {
+             return addPatchPort(node, bridgeUUID, localPatchName, remotePatchName);
+         }
+         return new Status(StatusCode.SUCCESS);
      }
  
      public void prepareInternalNetwork(Node node) {
          try {
-             this.createInternalNetworkForOverlay(node);
+             this.createIntegrationBridge(node);
          } catch (Exception e) {
              logger.error("Error creating internal network "+node.toString(), e);
+             return;
+         }
+         if (providerNetworkManager == null) {
+             logger.error("Error creating internal network. Provider Network Manager unavailable");
+             return;
+         }
+         providerNetworkManager.getProvider().initializeFlowRules(node);
+     }
+     /*
+      * Check if the full network setup is available. If not, create it.
+      */
+     public boolean checkAndCreateNetwork (Node node, NeutronNetwork network) {
+         boolean isCreated = false;
+         if (network.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VLAN)) {
+             if (!this.isInternalNetworkVlanReady(node, network)) {
+                 try {
+                     isCreated = this.createNetNetwork(node, network);
+                 } catch (Exception e) {
+                     logger.error("Error creating internal net network ", node, e);
+                 }
+             } else {
+                 isCreated = true;
+             }
+         } else if (network.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VXLAN) ||
+                 network.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_GRE)) {
+             if (!this.isInternalNetworkTunnelReady(node)) {
+                 try {
+                     isCreated = this.createNetNetwork(node, network);
+                 } catch (Exception e) {
+                     logger.error("Error creating internal net network ", node, e);
+                 }
+             } else {
+                 isCreated = true;
+             }
          }
-         ProviderNetworkManager.getManager().initializeFlowRules(node);
+         return isCreated;
      }
  }
index 62880477910e7cbee24ae8056a756961159b66f5,80cf8139ad5c57263d8bd5df0f7e0ab03f4168c2..dc0a6575ad5a2f37eb7781871f86a7dd68ffe81b
@@@ -5,14 -5,24 +5,24 @@@
   * terms of the Eclipse Public License v1.0 which accompanies this distribution,
   * and is available at http://www.eclipse.org/legal/epl-v10.html
   *
-  * Authors : Madhu Venugopal, Brent Salisbury
+  * Authors : Madhu Venugopal, Brent Salisbury, Hsin-Yi Shen
   */
  package org.opendaylight.ovsdb.neutron;
  
  import java.net.HttpURLConnection;
+ import java.util.ArrayList;
+ import java.util.List;
+ import java.util.concurrent.ConcurrentMap;
  
  import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkAware;
+ import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;
  import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork;
 -import org.opendaylight.ovsdb.lib.table.internal.Table;
+ import org.opendaylight.controller.sal.core.Node;
+ import org.opendaylight.controller.sal.utils.ServiceHelper;
+ import org.opendaylight.ovsdb.lib.table.Interface;
++import org.opendaylight.ovsdb.lib.table.Table;
+ import org.opendaylight.ovsdb.plugin.IConnectionServiceInternal;
+ import org.opendaylight.ovsdb.plugin.OVSDBInventoryListener;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  
   */
  public class NetworkHandler extends BaseHandler
                              implements INeutronNetworkAware {
+     public static final String NETWORK_TYPE_VXLAN = "vxlan";
+     public static final String NETWORK_TYPE_GRE = "gre";
+     public static final String NETWORK_TYPE_VLAN = "vlan";
      /**
       * Logger instance.
       */
      static final Logger logger = LoggerFactory.getLogger(NetworkHandler.class);
  
+     // The implementation for each of these services is resolved by the OSGi Service Manager
+     private volatile ITenantNetworkManager tenantNetworkManager;
+     private volatile IAdminConfigManager adminConfigManager;
      /**
       * Invoked when a network creation is requested
       * to indicate if the specified network can be created.
@@@ -51,7 -70,7 +70,7 @@@
      @Override
      public void neutronNetworkCreated(NeutronNetwork network) {
          int result = HttpURLConnection.HTTP_BAD_REQUEST;
+         logger.trace("neutronNetworkCreated: network: {}", network);
          result = canCreateNetwork(network);
          if (result != HttpURLConnection.HTTP_CREATED) {
              logger.debug("Network creation failed {} ", result);
@@@ -73,6 -92,7 +92,7 @@@
      @Override
      public int canUpdateNetwork(NeutronNetwork delta,
                                  NeutronNetwork original) {
+         logger.trace("canUpdateNetwork: network delta {} --- original {}", delta, original);
          return HttpURLConnection.HTTP_OK;
      }
  
       */
      @Override
      public void neutronNetworkUpdated(NeutronNetwork network) {
+         logger.trace("neutronNetworkUpdated: network: {}", network);
          return;
      }
  
      public void neutronNetworkDeleted(NeutronNetwork network) {
  
          int result = canDeleteNetwork(network);
+         logger.trace("canDeleteNetwork: network: {}", network);
          if  (result != HttpURLConnection.HTTP_OK) {
              logger.error(" deleteNetwork validation failed for result - {} ",
                      result);
              return;
          }
-         TenantNetworkManager.getManager().networkDeleted(network.getID());
+         /* Is this the last Neutron tenant network */
+         INeutronNetworkCRUD neutronNetworkService = (INeutronNetworkCRUD)ServiceHelper.getGlobalInstance(INeutronNetworkCRUD.class, this);
+         List <NeutronNetwork> networks = new ArrayList<NeutronNetwork>();
+         if (neutronNetworkService != null) {
+             networks = neutronNetworkService.getAllNetworks();
+             OVSDBInventoryListener inventoryListener = (OVSDBInventoryListener)ServiceHelper.getGlobalInstance(OVSDBInventoryListener.class, this);
+             if (networks.isEmpty()) {
+                 logger.trace("neutronNetworkDeleted: last tenant network, delete tunnel ports...");
+                 IConnectionServiceInternal connectionService = (IConnectionServiceInternal)
+                                         ServiceHelper.getGlobalInstance(IConnectionServiceInternal.class, this);
+                 List<Node> nodes = connectionService.getNodes();
+                 for (Node node : nodes) {
+                     List<String> phyIfName = adminConfigManager.getAllPhysicalInterfaceNames(node);
+                     try {
+                         ConcurrentMap<String, Table<?>> interfaces = this.ovsdbConfigService.getRows(node, Interface.NAME.getName());
+                         if (interfaces != null) {
+                             for (String intfUUID : interfaces.keySet()) {
+                                 Interface intf = (Interface) interfaces.get(intfUUID);
+                                 String intfType = intf.getType();
+                                 if (intfType.equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VXLAN) || intfType.equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_GRE)) {
+                                     /* delete tunnel ports on this node */
+                                     logger.trace("Delete tunnel intf {}", intf);
+                                     inventoryListener.rowRemoved(node, Interface.NAME.getName(), intfUUID,
+                                             intf, null);
+                                 } else if (!phyIfName.isEmpty() && phyIfName.contains(intf.getName())) {
+                                     logger.trace("Delete physical intf {}", intf);
+                                     inventoryListener.rowRemoved(node, Interface.NAME.getName(), intfUUID,
+                                             intf, null);
+                                 }
+                             }
+                         }
+                     } catch (Exception e) {
+                         logger.error("Exception during handlingNeutron network delete");
+                     }
+                 }
+             }
+         }
+         tenantNetworkManager.networkDeleted(network.getID());
      }
  }
index 115b891e82eec0cd10e2fb3e4602c5cf92123e41,ae9914384e20d8392a5d33a22d1a1f46f223f1a8..0e03bf6db3defc98788888fceb5e87566bfc20ee
@@@ -22,7 -22,7 +22,7 @@@ import org.opendaylight.controller.sal.
  import org.opendaylight.ovsdb.lib.notation.UUID;
  import org.opendaylight.ovsdb.lib.table.Interface;
  import org.opendaylight.ovsdb.lib.table.Port;
 -import org.opendaylight.ovsdb.lib.table.internal.Table;
 +import org.opendaylight.ovsdb.lib.table.Table;
  import org.opendaylight.ovsdb.plugin.OVSDBConfigService;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
@@@ -32,18 -32,18 +32,18 @@@ public class NodeConfiguration 
      private static final int MAX_VLAN = 4096;
      private java.util.Queue<Integer> internalVlans = new LinkedList<>();
      private ConcurrentMap<String, Integer> tenantVlanMap = new ConcurrentHashMap<>();
+     private ITenantNetworkManager tenantNetworkManager;
  
-     public NodeConfiguration(Node node) {
+     public NodeConfiguration(Node node, ITenantNetworkManager tenantNetworkManager) {
          for (int i = 1; i < MAX_VLAN ; i++) {
              internalVlans.add(i);
          }
+         setTenantNetworkManager(tenantNetworkManager);
          initializeNodeConfiguration(node);
      }
  
  
      private void initializeNodeConfiguration(Node node) {
          int vlan = 0;
          String networkId = new String();
          OVSDBConfigService ovsdbTable = (OVSDBConfigService) ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
@@@ -66,7 -66,7 +66,7 @@@
                      vlan = tags[0].intValue();
                  }
                  else {
-                    logger.debug("This port has more {} interfaces", tags.length);
+                    logger.debug("This port ({}) has {} tags", port.getName(), tags.length);
                     continue;
                  }
  
@@@ -78,7 -78,7 +78,7 @@@
                          continue;
                      }
  
-                     networkId = TenantNetworkManager.getManager().getTenantNetworkForInterface(iface).getNetworkUUID();
+                     networkId = tenantNetworkManager.getTenantNetworkForInterface(iface).getNetworkUUID();
  
                      if (networkId != null) break;
                  }
@@@ -88,6 -88,8 +88,8 @@@
                      this.internalVlanInUse(vlan);
                      this.tenantVlanMap.put(networkId, vlan);
  
+                 } else {
+                     logger.debug("Node: {} initialized without a vlan", node);
                  }
              }
          }
          }
      }
  
+     /*
+      * Return the currently mapped internal vlan or get the next
+      * free internal vlan from the available pool and map it to the networkId.
+      */
      public int assignInternalVlan (String networkId) {
          Integer mappedVlan = tenantVlanMap.get(networkId);
          if (mappedVlan != null) return mappedVlan;
          return mappedVlan;
      }
  
+     /*
+      * Return the mapped internal vlan to the available pool.
+      */
      public int reclaimInternalVlan (String networkId) {
          Integer mappedVlan = tenantVlanMap.get(networkId);
          if (mappedVlan != null) {
          return 0;
      }
  
+     /*
+      * Remove the internal vlan from the available pool.
+      */
      public void internalVlanInUse (int vlan) {
          internalVlans.remove(vlan);
      }
  
+     /*
+      * Return a vlan from the mapped pool keyed by the networkId.
+      */
      public int getInternalVlan (String networkId) {
          Integer vlan = tenantVlanMap.get(networkId);
          if (vlan == null) return 0;
          return vlan.intValue();
      }
  
+     public void setTenantNetworkManager(ITenantNetworkManager tenantNetworkManager) {
+         this.tenantNetworkManager = tenantNetworkManager;
+     }
  }
index d30d01f0a6a62e31ac67dd640e80bf5717d8c7cd,ec21561547ad6960f0f056616646210dc8823dcf..128b53bfffc3870e10a1b5571d4a8347f8905a1b
  package org.opendaylight.ovsdb.neutron;
  
  import java.net.HttpURLConnection;
+ import java.util.List;
+ import java.util.Map;
+ import java.util.concurrent.ConcurrentMap;
  
+ import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;
  import org.opendaylight.controller.networkconfig.neutron.INeutronPortAware;
+ import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork;
  import org.opendaylight.controller.networkconfig.neutron.NeutronPort;
 -import org.opendaylight.ovsdb.lib.table.internal.Table;
+ import org.opendaylight.controller.sal.core.Node;
+ import org.opendaylight.controller.sal.utils.ServiceHelper;
+ import org.opendaylight.ovsdb.lib.table.Interface;
++import org.opendaylight.ovsdb.lib.table.Table;
+ import org.opendaylight.ovsdb.plugin.IConnectionServiceInternal;
+ import org.opendaylight.ovsdb.plugin.OVSDBInventoryListener;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  
@@@ -118,9 -129,43 +129,43 @@@ public class PortHandler extends BaseHa
              return;
          }
  
+         IConnectionServiceInternal connectionService = (IConnectionServiceInternal)ServiceHelper.getGlobalInstance(IConnectionServiceInternal.class, this);
+         INeutronNetworkCRUD neutronNetworkService = (INeutronNetworkCRUD)ServiceHelper.getGlobalInstance(INeutronNetworkCRUD.class, this);
+         NeutronNetwork neutronNetwork = neutronNetworkService.getNetwork(port.getNetworkUUID());
+         OVSDBInventoryListener inventoryListener = (OVSDBInventoryListener)ServiceHelper.getGlobalInstance(OVSDBInventoryListener.class, this);
+         List<Node> nodes = connectionService.getNodes();
+         for (Node node : nodes) {
+             try {
+                 ConcurrentMap<String, Table<?>> interfaces = this.ovsdbConfigService.getRows(node, Interface.NAME.getName());
+                 if (interfaces != null) {
+                     for (String intfUUID : interfaces.keySet()) {
+                         Interface intf = (Interface) interfaces.get(intfUUID);
+                         Map<String, String> externalIds = intf.getExternal_ids();
+                         if (externalIds == null) {
+                             logger.trace("No external_ids seen in {}", intf);
+                             continue;
+                         }
+                         /* Compare Neutron port uuid */
+                         String neutronPortId = externalIds.get(TenantNetworkManager.EXTERNAL_ID_INTERFACE_ID);
+                         if (neutronPortId == null) {
+                             continue;
+                         }
+                         if (neutronPortId.equalsIgnoreCase(port.getPortUUID())) {
+                             logger.trace("neutronPortDeleted: Delete interface {}", intf.getName());
+                             inventoryListener.rowRemoved(node, Interface.NAME.getName(), intfUUID,
+                                                          intf, neutronNetwork);
+                             break;
+                         }
+                     }
+                 }
+             } catch (Exception e) {
+                 logger.error("Exception during handlingNeutron network delete");
+             }
+         }
          logger.debug(" PORT delete successful for tenant-id - {}, " +
                       " network-id - {}, port-id - {}",
                       port.getTenantID(), port.getNetworkUUID(),
                       port.getID());
      }
  }
index 5c5028f049338cda6220e270344bf1e8b1e8eefc,70e69c81432d588aec4e7ced72a0acec546572d8..8204d91d20e09cbf74d5049b5b7160bf2637711f
@@@ -10,7 -10,7 +10,7 @@@
  package org.opendaylight.ovsdb.neutron;
  
  import org.opendaylight.controller.sal.core.Node;
 -import org.opendaylight.ovsdb.lib.table.internal.Table;
 +import org.opendaylight.ovsdb.lib.table.Table;
  
  public class SouthboundEvent {
      public enum Type { NODE, ROW };
@@@ -21,6 -21,7 +21,7 @@@
      private String tableName;
      private String uuid;
      private Table<?> row;
+     private Object context;
      public SouthboundEvent(Node node, Action action) {
          super();
          this.type = Type.NODE;
          this.uuid = uuid;
          this.row = row;
      }
+     public SouthboundEvent(Node node, String tableName, String uuid, Table<?> row, Object context, Action action) {
+         super();
+         this.type = Type.ROW;
+         this.action = action;
+         this.node = node;
+         this.tableName = tableName;
+         this.uuid = uuid;
+         this.row = row;
+         this.context = context;
+     }
      public Type getType() {
          return type;
      }
      public Table<?> getRow() {
          return row;
      }
+     public Object getContext() {
+         return context;
+     }
      @Override
      public String toString() {
          return "SouthboundEvent [type=" + type + ", action=" + action + ", node=" + node + ", tableName=" + tableName
-                 + ", uuid=" + uuid + ", row=" + row + "]";
+                 + ", uuid=" + uuid + ", row=" + row + ", context=" + context.toString() + "]";
      }
      @Override
      public int hashCode() {
index 8d6b830bab2022f0a2282374185b4983e65d3ab2,5d114870328873ce273ba5b6bc412f7acda247d4..5238e5069409fd2cbf101b7495954a57fbb9e90d
@@@ -5,7 -5,7 +5,7 @@@
   * terms of the Eclipse Public License v1.0 which accompanies this distribution,
   * and is available at http://www.eclipse.org/legal/epl-v10.html
   *
-  * Authors : Madhu Venugopal, Brent Salisbury
+  * Authors : Madhu Venugopal, Brent Salisbury, Sam Hague, Dave Tucker
   */
  package org.opendaylight.ovsdb.neutron;
  
@@@ -29,8 -29,8 +29,8 @@@ import org.opendaylight.ovsdb.lib.notat
  import org.opendaylight.ovsdb.lib.table.Interface;
  import org.opendaylight.ovsdb.lib.table.Open_vSwitch;
  import org.opendaylight.ovsdb.lib.table.Port;
 -import org.opendaylight.ovsdb.lib.table.internal.Table;
 +import org.opendaylight.ovsdb.lib.table.Table;
- import org.opendaylight.ovsdb.neutron.provider.ProviderNetworkManager;
+ import org.opendaylight.ovsdb.neutron.provider.IProviderNetworkManager;
  import org.opendaylight.ovsdb.plugin.OVSDBInventoryListener;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
@@@ -42,6 -42,12 +42,12 @@@ public class SouthboundHandler extends 
      private BlockingQueue<SouthboundEvent> events;
      List<Node> nodeCache;
  
+     // The implementation for each of these services is resolved by the OSGi Service Manager
+     private volatile IAdminConfigManager adminConfigManager;
+     private volatile IInternalNetworkManager internalNetworkManager;
+     private volatile ITenantNetworkManager tenantNetworkManager;
+     private volatile IProviderNetworkManager providerNetworkManager;
      void init() {
          eventHandler = Executors.newSingleThreadExecutor();
          this.events = new LinkedBlockingQueue<SouthboundEvent>();
@@@ -70,7 -76,8 +76,8 @@@
                          break;
                      case ROW:
                          try {
-                             processRowUpdate(ev.getNode(), ev.getTableName(), ev.getUuid(), ev.getRow(), ev.getAction());
+                             processRowUpdate(ev.getNode(), ev.getTableName(), ev.getUuid(), ev.getRow(),
+                                              ev.getContext(),ev.getAction());
                          } catch (Exception e) {
                              logger.error("Exception caught in ProcessRowUpdate for node " + ev.getNode(), e);
                          }
  
      @Override
      public void rowUpdated(Node node, String tableName, String uuid, Table<?> oldRow, Table<?> newRow) {
-         if (this.isUpdateOfInterest(oldRow, newRow)) {
+         if (this.isUpdateOfInterest(node, oldRow, newRow)) {
              this.enqueueEvent(new SouthboundEvent(node, tableName, uuid, newRow, SouthboundEvent.Action.UPDATE));
          }
      }
       * (Especially stats update are fast and furious).
       */
  
-     private boolean isUpdateOfInterest(Table<?> oldRow, Table<?> newRow) {
+     private boolean isUpdateOfInterest(Node node, Table<?> oldRow, Table<?> newRow) {
          if (oldRow == null) return true;
          if (newRow.getTableName().equals(Interface.NAME)) {
              // We are NOT interested in Stats only updates
              if (oldIntf.getName() == null && oldIntf.getExternal_ids() == null && oldIntf.getMac() == null &&
                  oldIntf.getOfport() == null && oldIntf.getOptions() == null && oldIntf.getOther_config() == null &&
                  oldIntf.getType() == null) {
-                 logger.trace("IGNORING Interface Update : "+newRow.toString());
+                 logger.trace("IGNORING Interface Update: node {}, row: {}", node, newRow);
                  return false;
              }
          } else if (newRow.getTableName().equals(Port.NAME)) {
              Port oldPort = (Port)oldRow;
              if (oldPort.getName() == null && oldPort.getExternal_ids() == null && oldPort.getMac() == null &&
                  oldPort.getInterfaces() == null && oldPort.getTag() == null && oldPort.getTrunks() == null) {
-                 logger.trace("IGNORING Port Update : "+newRow.toString());
+                 logger.trace("IGNORING Port Update: node {}, row: {}", node, newRow);
+                 return false;
+             }
+         } else if (newRow.getTableName().equals(Open_vSwitch.NAME)) {
+             Open_vSwitch oldOpenvSwitch = (Open_vSwitch) oldRow;
+             if (oldOpenvSwitch.getOther_config()== null) {
+                 /* we are only interested in other_config field change */
                  return false;
              }
          }
          return true;
      }
  
      @Override
-     public void rowRemoved(Node node, String tableName, String uuid, Table<?> row) {
-         this.enqueueEvent(new SouthboundEvent(node, tableName, uuid, row, SouthboundEvent.Action.DELETE));
+     public void rowRemoved(Node node, String tableName, String uuid, Table<?> row, Object context) {
+         this.enqueueEvent(new SouthboundEvent(node, tableName, uuid, row, context, SouthboundEvent.Action.DELETE));
      }
  
      private void enqueueEvent (SouthboundEvent event) {
          } catch (InterruptedException e) {
              logger.error("Thread was interrupted while trying to enqueue event ", e);
          }
      }
  
      public void processNodeUpdate(Node node, SouthboundEvent.Action action) {
          if (action == SouthboundEvent.Action.DELETE) return;
          logger.trace("Process Node added {}", node);
-         InternalNetworkManager.getManager().prepareInternalNetwork(node);
+         internalNetworkManager.prepareInternalNetwork(node);
      }
  
      private void processRowUpdate(Node node, String tableName, String uuid, Table<?> row,
-                                   SouthboundEvent.Action action) {
+                                   Object context, SouthboundEvent.Action action) {
          if (action == SouthboundEvent.Action.DELETE) {
              if (Interface.NAME.getName().equalsIgnoreCase(tableName)) {
+                 logger.debug("processRowUpdate: {} Deleted node: {}, uuid: {}, row: {}", tableName, node, uuid, row);
                  Interface deletedIntf = (Interface)row;
-                 NeutronNetwork network = TenantNetworkManager.getManager().getTenantNetworkForInterface(deletedIntf);
-                 if (network != null && !network.getRouterExternal()) {
+                 NeutronNetwork network = null;
+                 if (context == null) {
+                     network = tenantNetworkManager.getTenantNetworkForInterface(deletedIntf);
+                 } else {
+                     network = (NeutronNetwork)context;
+                 }
+                 List<String> phyIfName = adminConfigManager.getAllPhysicalInterfaceNames(node);
+                 logger.info("Delete interface " + deletedIntf.getName());
+                 if (deletedIntf.getType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VXLAN) ||
+                     deletedIntf.getType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_GRE) ||
+                     phyIfName.contains(deletedIntf.getName())) {
+                     /* delete tunnel interfaces or physical interfaces */
+                     this.handleInterfaceDelete(node, uuid, deletedIntf, false, null);
+                 } else if (network != null && !network.getRouterExternal()) {
                      try {
                          ConcurrentMap<String, Table<?>> interfaces = this.ovsdbConfigService.getRows(node, Interface.NAME.getName());
                          if (interfaces != null) {
                              for (String intfUUID : interfaces.keySet()) {
                                  if (intfUUID.equals(uuid)) continue;
                                  Interface intf = (Interface) interfaces.get(intfUUID);
-                                 NeutronNetwork neutronNetwork = TenantNetworkManager.getManager().getTenantNetworkForInterface(intf);
+                                 NeutronNetwork neutronNetwork = tenantNetworkManager.getTenantNetworkForInterface(intf);
                                  if (neutronNetwork != null && neutronNetwork.equals(network)) isLastInstanceOnNode = false;
                              }
-                             this.handleInterfaceDelete(node, uuid, deletedIntf, isLastInstanceOnNode);
+                             this.handleInterfaceDelete(node, uuid, deletedIntf, isLastInstanceOnNode, network);
                          }
                      } catch (Exception e) {
                          logger.error("Error fetching Interface Rows for node " + node, e);
              }
          }
          else if (Interface.NAME.getName().equalsIgnoreCase(tableName)) {
-             logger.debug("{} Added / Updated {} , {}, {}", tableName, node, uuid, row);
+             logger.debug("processRowUpdate: {} Added / Updated node: {}, uuid: {}, row: {}", tableName, node, uuid, row);
              Interface intf = (Interface)row;
-             NeutronNetwork network = TenantNetworkManager.getManager().getTenantNetworkForInterface(intf);
+             NeutronNetwork network = tenantNetworkManager.getTenantNetworkForInterface(intf);
              if (network != null && !network.getRouterExternal()) {
-                 if (ProviderNetworkManager.getManager().hasPerTenantTunneling()) {
-                     int vlan = TenantNetworkManager.getManager().networkCreated(node, network.getID());
-                     logger.trace("Neutron Network {} Created with Internal Vlan : {}", network.toString(), vlan);
+                 if (providerNetworkManager.getProvider().hasPerTenantTunneling()) {
+                     int vlan = tenantNetworkManager.networkCreated(node, network.getID());
+                     logger.trace("Neutron Network {}:{} Created with Internal Vlan: {}", network.getNetworkUUID(), network.getNetworkName(), vlan);
  
                      String portUUID = this.getPortIdForInterface(node, uuid, intf);
                      if (portUUID != null) {
-                         TenantNetworkManager.getManager().programTenantNetworkInternalVlan(node, portUUID, network);
+                         tenantNetworkManager.programTenantNetworkInternalVlan(node, portUUID, network);
                      }
                  }
                  this.handleInterfaceUpdate(node, uuid, intf);
              }
          } else if (Port.NAME.getName().equalsIgnoreCase(tableName)) {
-             logger.debug("{} Added / Updated {} , {}, {}", tableName, node, uuid, row);
+             logger.debug("processRowUpdate: {} Added / Updated node: {}, uuid: {}, row: {}", tableName, node, uuid, row);
              Port port = (Port)row;
              Set<UUID> interfaceUUIDs = port.getInterfaces();
              for (UUID intfUUID : interfaceUUIDs) {
                  logger.trace("Scanning interface "+intfUUID);
                  try {
                      Interface intf = (Interface)this.ovsdbConfigService.getRow(node, Interface.NAME.getName(), intfUUID.toString());
-                     NeutronNetwork network = TenantNetworkManager.getManager().getTenantNetworkForInterface(intf);
+                     NeutronNetwork network = tenantNetworkManager.getTenantNetworkForInterface(intf);
                      if (network != null && !network.getRouterExternal()) {
-                         TenantNetworkManager.getManager().programTenantNetworkInternalVlan(node, uuid, network);
+                         tenantNetworkManager.programTenantNetworkInternalVlan(node, uuid, network);
+                     } else {
+                         logger.trace("ignore update because there is not a neutron network.");
                      }
                  } catch (Exception e) {
                      logger.error("Failed to process row update", e);
                  }
              }
          } else if (Open_vSwitch.NAME.getName().equalsIgnoreCase(tableName)) {
-             logger.debug("{} Added / Updated {} , {}, {}", tableName, node, uuid, row);
+             logger.debug("processRowUpdate: {} Added / Updated node: {}, uuid: {}, row: {}", tableName, node, uuid, row);
              try {
                  ConcurrentMap<String, Table<?>> interfaces = this.ovsdbConfigService.getRows(node, Interface.NAME.getName());
                  if (interfaces != null) {
      }
  
      private void handleInterfaceUpdate (Node node, String uuid, Interface intf) {
-         if (AdminConfigManager.getManager().getTunnelEndPoint(node) == null) {
-             logger.error("Tunnel end-point configuration missing. Please configure it in Open_vSwitch Table");
-             return;
-         }
-         NeutronNetwork network = TenantNetworkManager.getManager().getTenantNetworkForInterface(intf);
+         logger.debug("handleInterfaceUpdate: node: {}, uuid: {}", node, uuid);
+         NeutronNetwork network = tenantNetworkManager.getTenantNetworkForInterface(intf);
          if (network != null) {
-             ProviderNetworkManager.getManager().handleInterfaceUpdate(network.getProviderNetworkType(),
-                     network.getProviderSegmentationID(), node, intf);
+             if (internalNetworkManager.checkAndCreateNetwork(node, network)) {
+                 providerNetworkManager.getProvider().handleInterfaceUpdate(network, node, intf);
+             }
          }
      }
-     private void handleInterfaceDelete (Node node, String uuid, Interface intf, boolean isLastInstanceOnNode) {
-         if (AdminConfigManager.getManager().getTunnelEndPoint(node) == null) {
-             logger.error("Tunnel end-point configuration missing. Please configure it in Open_vSwitch Table");
-             return;
-         }
-         NeutronNetwork network = TenantNetworkManager.getManager().getTenantNetworkForInterface(intf);
-         if (network != null) {
-             if (isLastInstanceOnNode) {
-                 TenantNetworkManager.getManager().reclaimTennantNetworkInternalVlan(node, uuid, network);
+     private void handleInterfaceDelete (Node node, String uuid, Interface intf, boolean isLastInstanceOnNode,
+                                         NeutronNetwork network) {
+         logger.debug("handleInterfaceDelete: node: {}, uuid: {}, isLastInstanceOnNode: {}, interface: {}",
+                 node, uuid, isLastInstanceOnNode, intf);
+         List<String> phyIfName = adminConfigManager.getAllPhysicalInterfaceNames(node);
+         if (intf.getType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VXLAN) ||
+             intf.getType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_GRE) ||
+             phyIfName.contains(intf.getName())) {
+             /* delete tunnel or physical interfaces */
+             providerNetworkManager.getProvider().handleInterfaceDelete(intf.getType(), null, node, intf, isLastInstanceOnNode);
+         } else if (network != null) {
+             if (!network.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VLAN)) { /* vlan doesn't need a tunnel endpoint */
+                 if (adminConfigManager.getTunnelEndPoint(node) == null) {
+                     logger.error("Tunnel end-point configuration missing. Please configure it in Open_vSwitch Table");
+                     return;
+                 }
+             }
+             if (isLastInstanceOnNode & providerNetworkManager.getProvider().hasPerTenantTunneling()) {
+                 tenantNetworkManager.reclaimTenantNetworkInternalVlan(node, uuid, network);
              }
-             ProviderNetworkManager.getManager().handleInterfaceDelete(network.getProviderNetworkType(),
-                     network.getProviderSegmentationID(), node, intf, isLastInstanceOnNode);
+             providerNetworkManager.getProvider().handleInterfaceDelete(network.getProviderNetworkType(), network, node, intf, isLastInstanceOnNode);
          }
      }
  
                  logger.trace("Scanning Port {} to identify interface : {} ",port, uuid);
                  for (UUID intfUUID : interfaceUUIDs) {
                      if (intfUUID.toString().equalsIgnoreCase(uuid)) {
-                         logger.trace("Found Interafce {} -> {}", uuid, portUUID);
+                         logger.trace("Found Interface {} -> {}", uuid, portUUID);
                          return portUUID;
                      }
                  }
  
      @Override
      public void notifyNode(Node node, UpdateType type, Map<String, Property> propMap) {
-         logger.debug("Node {} update {} from Controller's inventory Service", node, type);
+         logger.debug("notifyNode: Node {} update {} from Controller's inventory Service", node, type);
  
          // Add the Node Type check back once the Consistency issue is resolved between MD-SAL and AD-SAL
          if (!type.equals(UpdateType.REMOVED) && !nodeCache.contains(node)) {
              nodeCache.add(node);
-             ProviderNetworkManager.getManager().initializeOFFlowRules(node);
+             providerNetworkManager.getProvider().initializeOFFlowRules(node);
          } else if (type.equals(UpdateType.REMOVED)){
              nodeCache.remove(node);
          }
index f77478a663fb7b434032f08fbd9b47e4f6bf148c,1d9337d7de4a7f972dd95f2fe351d0e725da8a80..c74796d9dbbe687ac736a5262283f3cadaad5258
@@@ -35,34 -35,28 +35,28 @@@ import org.opendaylight.ovsdb.lib.table
  import org.opendaylight.ovsdb.lib.table.Interface;
  import org.opendaylight.ovsdb.lib.table.Open_vSwitch;
  import org.opendaylight.ovsdb.lib.table.Port;
 -import org.opendaylight.ovsdb.lib.table.internal.Table;
 +import org.opendaylight.ovsdb.lib.table.Table;
- import org.opendaylight.ovsdb.neutron.provider.ProviderNetworkManager;
+ import org.opendaylight.ovsdb.neutron.provider.IProviderNetworkManager;
  import org.opendaylight.ovsdb.plugin.IConnectionServiceInternal;
  import org.opendaylight.ovsdb.plugin.OVSDBConfigService;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  
- public class TenantNetworkManager {
+ public class TenantNetworkManager implements ITenantNetworkManager {
      static final Logger logger = LoggerFactory.getLogger(TenantNetworkManager.class);
-     public static final String EXTERNAL_ID_VM_ID = "vm-id";
-     public static final String EXTERNAL_ID_INTERFACE_ID = "iface-id";
-     public static final String EXTERNAL_ID_VM_MAC = "attached-mac";
-     private static TenantNetworkManager tenantHelper = new TenantNetworkManager();
      private ConcurrentMap<String, NodeConfiguration> nodeConfigurationCache = new ConcurrentHashMap<>();
  
+     // The implementation for each of these services is resolved by the OSGi Service Manager
+     private volatile IProviderNetworkManager providerNetworkManager;
      private boolean enableContainer = false;
-     private TenantNetworkManager() {
+     public TenantNetworkManager() {
          String isTenantContainer = System.getProperty("TenantIsContainer");
          if (isTenantContainer != null && isTenantContainer.equalsIgnoreCase("true")) {
              enableContainer =  true;
          }
      }
  
-     public static TenantNetworkManager getManager() {
-         return tenantHelper;
-     }
      public int getInternalVlan(Node node, String networkId) {
          String nodeUuid = getNodeUUID(node);
          if (nodeUuid == null) {
@@@ -81,7 -75,7 +75,7 @@@
      }
  
      private NodeConfiguration addNodeConfigurationToCache(Node node) {
-         NodeConfiguration nodeConfiguration = new NodeConfiguration(node);
+         NodeConfiguration nodeConfiguration = new NodeConfiguration(node, this);
          String nodeUuid = getNodeUUID(node);
          if (nodeUuid == null) {
              logger.error("Cannot get Node UUID for Node {}", node);
@@@ -91,7 -85,7 +85,7 @@@
          return nodeConfigurationCache.get(nodeUuid);
      }
  
-     public void reclaimTennantNetworkInternalVlan(Node node, String portUUID, NeutronNetwork network) {
+     public void reclaimTenantNetworkInternalVlan(Node node, String portUUID, NeutronNetwork network) {
          String nodeUuid = getNodeUUID(node);
          if (nodeUuid == null) {
              logger.error("Unable to get UUID for Node {}", node);
              logger.debug("Tenant Network not found with Segmenation-id {}",segmentationId);
              return false;
          }
-         if (ProviderNetworkManager.getManager().hasPerTenantTunneling()) {
+         if (providerNetworkManager.getProvider().hasPerTenantTunneling()) {
              String nodeUuid = getNodeUUID(node);
              if (nodeUuid == null) {
                  logger.debug("Unable to get UUID for Node {}", node);
          config.setContainer(networkID);
          containerManager.removeContainer(config);
      }
  }
index 1093b34b9733e353500db8f7c8d265514ab83bfb,c506ae32f0de3588638871a95536464646063b02..a0cb62d685ccadaec8f8173d50627ee7bd5f114c
@@@ -5,7 -5,7 +5,7 @@@
   * terms of the Eclipse Public License v1.0 which accompanies this distribution,
   * and is available at http://www.eclipse.org/legal/epl-v10.html
   *
-  * Authors : Madhu Venugopal, Brent Salisbury
+  * Authors : Madhu Venugopal, Brent Salisbury, Sam Hague, Dave Tucker
   */
  package org.opendaylight.ovsdb.neutron.provider;
  
@@@ -18,6 -18,7 +18,7 @@@ import java.util.Set
  
  import org.opendaylight.controller.forwardingrulesmanager.FlowConfig;
  import org.opendaylight.controller.forwardingrulesmanager.IForwardingRulesManager;
+ import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork;
  import org.opendaylight.controller.sal.action.ActionType;
  import org.opendaylight.controller.sal.core.Node;
  import org.opendaylight.controller.sal.utils.EtherTypes;
@@@ -33,10 -34,11 +34,11 @@@ import org.opendaylight.ovsdb.lib.notat
  import org.opendaylight.ovsdb.lib.table.Bridge;
  import org.opendaylight.ovsdb.lib.table.Interface;
  import org.opendaylight.ovsdb.lib.table.Port;
 -import org.opendaylight.ovsdb.lib.table.internal.Table;
 +import org.opendaylight.ovsdb.lib.table.Table;
- import org.opendaylight.ovsdb.neutron.AdminConfigManager;
- import org.opendaylight.ovsdb.neutron.InternalNetworkManager;
- import org.opendaylight.ovsdb.neutron.TenantNetworkManager;
+ import org.opendaylight.ovsdb.neutron.NetworkHandler;
+ import org.opendaylight.ovsdb.neutron.IAdminConfigManager;
+ import org.opendaylight.ovsdb.neutron.IInternalNetworkManager;
+ import org.opendaylight.ovsdb.neutron.ITenantNetworkManager;
  import org.opendaylight.ovsdb.plugin.IConnectionServiceInternal;
  import org.opendaylight.ovsdb.plugin.OVSDBConfigService;
  import org.opendaylight.ovsdb.plugin.StatusWithUuid;
@@@ -44,11 -46,24 +46,24 @@@ import org.slf4j.Logger
  import org.slf4j.LoggerFactory;
  
  
class OF10ProviderManager extends ProviderNetworkManager {
-     private static final Logger logger = LoggerFactory.getLogger(OF10ProviderManager.class);
public class OF10Provider implements NetworkProvider {
+     private static final Logger logger = LoggerFactory.getLogger(OF10Provider.class);
      private static final int INGRESS_TUNNEL_FLOW_PRIORITY = 100;
      private static final int EGRESS_TUNNEL_FLOW_PRIORITY = 100;
-     private static final int FLOOD_TUNNEL_FLOW_PRIORITY = 1;
+     private static final int DROP_FLOW_PRIORITY = 10;
+     private static final int FLOOD_TUNNEL_FLOW_PRIORITY = 50;
+     private IAdminConfigManager adminConfigManager;
+     private IInternalNetworkManager internalNetworkManager;
+     private ITenantNetworkManager tenantNetworkManager;
+     public OF10Provider(IAdminConfigManager adminConfigManager,
+                         IInternalNetworkManager internalNetworkManager,
+                         ITenantNetworkManager tenantNetworkManager) {
+         this.adminConfigManager = adminConfigManager;
+         this.internalNetworkManager = internalNetworkManager;
+         this.tenantNetworkManager = tenantNetworkManager;
+     }
  
      @Override
      public boolean hasPerTenantTunneling() {
      }
  
      private Status getTunnelReadinessStatus (Node node, String tunnelKey) {
-         InetAddress srcTunnelEndPoint = AdminConfigManager.getManager().getTunnelEndPoint(node);
+         InetAddress srcTunnelEndPoint = adminConfigManager.getTunnelEndPoint(node);
          if (srcTunnelEndPoint == null) {
              logger.error("Tunnel Endpoint not configured for Node {}", node);
              return new Status(StatusCode.NOTFOUND, "Tunnel Endpoint not configured for "+ node);
          }
  
-         if (!InternalNetworkManager.getManager().isInternalNetworkOverlayReady(node)) {
+         if (!internalNetworkManager.isInternalNetworkOverlayReady(node)) {
              logger.warn("{} is not Overlay ready. It might be an OpenStack Controller Node", node);
              return new Status(StatusCode.NOTACCEPTABLE, node+" is not Overlay ready");
          }
  
-         if (!TenantNetworkManager.getManager().isTenantNetworkPresentInNode(node, tunnelKey)) {
-             logger.debug(node+" has no VM corresponding to segment "+ tunnelKey);
-             return new Status(StatusCode.NOTACCEPTABLE, node+" has no VM corresponding to segment "+ tunnelKey);
+         if (!tenantNetworkManager.isTenantNetworkPresentInNode(node, tunnelKey)) {
+             logger.debug(node+" has no network corresponding to segment "+ tunnelKey);
+             return new Status(StatusCode.NOTACCEPTABLE, node+" has no network corresponding to segment "+ tunnelKey);
+         }
+         return new Status(StatusCode.SUCCESS);
+     }
+     private Status getVlanReadinessStatus (Node node, String segmentationId) {
+         if (!internalNetworkManager.isInternalNetworkOverlayReady(node)) {
+             logger.warn("{} is not Overlay ready. It might be an OpenStack Controller Node", node);
+             return new Status(StatusCode.NOTACCEPTABLE, node+" is not Overlay ready");
+         }
+         if (!tenantNetworkManager.isTenantNetworkPresentInNode(node, segmentationId)) {
+             logger.debug(node+" has no network corresponding to segment "+ segmentationId);
+             return new Status(StatusCode.NOTACCEPTABLE, node+" has no network corresponding to segment "+ segmentationId);
          }
          return new Status(StatusCode.SUCCESS);
      }
       * and rewrite the Corresponding internal Vlan and pass it on to br-int via the patch port.
       */
      private void programLocalIngressTunnelBridgeRules(Node node, int tunnelOFPort, int internalVlan, int patchPort) {
-         String brIntId = InternalNetworkManager.getManager().getInternalBridgeUUID(node, AdminConfigManager.getManager().getTunnelBridgeName());
-         if (brIntId == null) {
+         String brNetId = internalNetworkManager.getInternalBridgeUUID(node, adminConfigManager.getNetworkBridgeName());
+         if (brNetId == null) {
              logger.error("Failed to initialize Flow Rules for {}", node);
              return;
          }
          try {
              OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
-             Bridge bridge = (Bridge) ovsdbTable.getRow(node, Bridge.NAME.getName(), brIntId);
+             Bridge bridge = (Bridge) ovsdbTable.getRow(node, Bridge.NAME.getName(), brNetId);
              Set<String> dpids = bridge.getDatapath_id();
              if (dpids == null || dpids.size() ==  0) return;
              Long dpidLong = Long.valueOf(HexEncode.stringToLong((String)dpids.toArray()[0]));
      }
  
      private void removeLocalIngressTunnelBridgeRules(Node node, int tunnelOFPort, int internalVlan, int patchPort) {
-         String brIntId = InternalNetworkManager.getManager().getInternalBridgeUUID(node, AdminConfigManager.getManager().getTunnelBridgeName());
-         if (brIntId == null) {
+         String brNetId = internalNetworkManager.getInternalBridgeUUID(node, adminConfigManager.getNetworkBridgeName());
+         if (brNetId == null) {
              logger.error("Failed to remove Flow Rules for {}", node);
              return;
          }
          try {
              OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
-             Bridge bridge = (Bridge) ovsdbTable.getRow(node, Bridge.NAME.getName(), brIntId);
+             Bridge bridge = (Bridge) ovsdbTable.getRow(node, Bridge.NAME.getName(), brNetId);
              Set<String> dpids = bridge.getDatapath_id();
              if (dpids == null || dpids.size() ==  0) return;
              Long dpidLong = Long.valueOf(HexEncode.stringToLong((String)dpids.toArray()[0]));
       */
      private void programRemoteEgressTunnelBridgeRules(Node node, int patchPort, String attachedMac,
              int internalVlan, int tunnelOFPort) {
-         String brIntId = InternalNetworkManager.getManager().getInternalBridgeUUID(node, AdminConfigManager.getManager().getTunnelBridgeName());
-         if (brIntId == null) {
+         String brNetId = internalNetworkManager.getInternalBridgeUUID(node, adminConfigManager.getNetworkBridgeName());
+         if (brNetId == null) {
              logger.error("Failed to initialize Flow Rules for {}", node);
              return;
          }
          try {
              OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
-             Bridge bridge = (Bridge) ovsdbTable.getRow(node, Bridge.NAME.getName(), brIntId);
+             Bridge bridge = (Bridge) ovsdbTable.getRow(node, Bridge.NAME.getName(), brNetId);
              Set<String> dpids = bridge.getDatapath_id();
              if (dpids == null || dpids.size() ==  0) return;
              Long dpidLong = Long.valueOf(HexEncode.stringToLong((String)dpids.toArray()[0]));
  
      private void removeRemoteEgressTunnelBridgeRules(Node node, int patchPort, String attachedMac,
              int internalVlan, int tunnelOFPort) {
-         String brIntId = InternalNetworkManager.getManager().getInternalBridgeUUID(node, AdminConfigManager.getManager().getTunnelBridgeName());
-         if (brIntId == null) {
+         String brNetId = internalNetworkManager.getInternalBridgeUUID(node, adminConfigManager.getNetworkBridgeName());
+         if (brNetId == null) {
              logger.error("Failed to initialize Flow Rules for {}", node);
              return;
          }
          try {
              OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
-             Bridge bridge = (Bridge) ovsdbTable.getRow(node, Bridge.NAME.getName(), brIntId);
+             Bridge bridge = (Bridge) ovsdbTable.getRow(node, Bridge.NAME.getName(), brNetId);
              Set<String> dpids = bridge.getDatapath_id();
              if (dpids == null || dpids.size() ==  0) return;
              Long dpidLong = Long.valueOf(HexEncode.stringToLong((String)dpids.toArray()[0]));
       * Also perform the Strip-Vlan action.
       */
      private void programFloodEgressTunnelBridgeRules(Node node, int patchPort, int internalVlan, int tunnelOFPort) {
-         String brIntId = InternalNetworkManager.getManager().getInternalBridgeUUID(node, AdminConfigManager.getManager().getTunnelBridgeName());
-         if (brIntId == null) {
+         String brNetId = internalNetworkManager.getInternalBridgeUUID(node, adminConfigManager.getNetworkBridgeName());
+         if (brNetId == null) {
              logger.error("Failed to initialize Flow Rules for {}", node);
              return;
          }
          try {
              OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
-             Bridge bridge = (Bridge) ovsdbTable.getRow(node, Bridge.NAME.getName(), brIntId);
+             Bridge bridge = (Bridge) ovsdbTable.getRow(node, Bridge.NAME.getName(), brNetId);
              Set<String> dpids = bridge.getDatapath_id();
              if (dpids == null || dpids.size() ==  0) return;
              Long dpidLong = Long.valueOf(HexEncode.stringToLong((String)dpids.toArray()[0]));
      }
  
      private void removeFloodEgressTunnelBridgeRules(Node node, int patchPort, int internalVlan, int tunnelOFPort) {
-         String brIntId = InternalNetworkManager.getManager().getInternalBridgeUUID(node, AdminConfigManager.getManager().getTunnelBridgeName());
-         if (brIntId == null) {
+         String brNetId = internalNetworkManager.getInternalBridgeUUID(node, adminConfigManager.getNetworkBridgeName());
+         if (brNetId == null) {
              logger.error("Failed to remove Flow Rules for {}", node);
              return;
          }
          try {
              OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
-             Bridge bridge = (Bridge) ovsdbTable.getRow(node, Bridge.NAME.getName(), brIntId);
+             Bridge bridge = (Bridge) ovsdbTable.getRow(node, Bridge.NAME.getName(), brNetId);
              Set<String> dpids = bridge.getDatapath_id();
              if (dpids == null || dpids.size() ==  0) return;
              Long dpidLong = Long.valueOf(HexEncode.stringToLong((String)dpids.toArray()[0]));
  
      private void programTunnelRules (String tunnelType, String segmentationId, InetAddress dst, Node node,
                                       Interface intf, boolean local) {
-         String networkId = TenantNetworkManager.getManager().getNetworkIdForSegmentationId(segmentationId);
+         String networkId = tenantNetworkManager.getNetworkIdForSegmentationId(segmentationId);
          if (networkId == null) {
-             logger.debug("Tenant Network not found with Segmenation-id {}",segmentationId);
+             logger.debug("Tenant Network not found with Segmentation-id {}", segmentationId);
              return;
          }
-         int internalVlan = TenantNetworkManager.getManager().getInternalVlan(node, networkId);
+         int internalVlan = tenantNetworkManager.getInternalVlan(node, networkId);
          if (internalVlan == 0) {
              logger.debug("No InternalVlan provisioned for Tenant Network {}",networkId);
              return;
              return;
          }
  
-         String attachedMac = externalIds.get(TenantNetworkManager.EXTERNAL_ID_VM_MAC);
+         String attachedMac = externalIds.get(ITenantNetworkManager.EXTERNAL_ID_VM_MAC);
          if (attachedMac == null) {
              logger.error("No AttachedMac seen in {}", intf);
              return;
          }
-         String patchInt = AdminConfigManager.getManager().getPatchToIntegration();
+         String patchInt = adminConfigManager.getPatchToIntegration();
  
          int patchOFPort = -1;
          try {
  
      private void removeTunnelRules (String tunnelType, String segmentationId, InetAddress dst, Node node,
              Interface intf, boolean local) {
-         String networkId = TenantNetworkManager.getManager().getNetworkIdForSegmentationId(segmentationId);
+         String networkId = tenantNetworkManager.getNetworkIdForSegmentationId(segmentationId);
          if (networkId == null) {
-             logger.debug("Tenant Network not found with Segmenation-id {}",segmentationId);
+             logger.debug("Tenant Network not found with Segmentation-id {}",segmentationId);
              return;
          }
-         int internalVlan = TenantNetworkManager.getManager().getInternalVlan(node,networkId);
+         int internalVlan = tenantNetworkManager.getInternalVlan(node,networkId);
          if (internalVlan == 0) {
              logger.debug("No InternalVlan provisioned for Tenant Network {}",networkId);
              return;
              return;
          }
  
-         String attachedMac = externalIds.get(TenantNetworkManager.EXTERNAL_ID_VM_MAC);
+         String attachedMac = externalIds.get(ITenantNetworkManager.EXTERNAL_ID_VM_MAC);
          if (attachedMac == null) {
              logger.error("No AttachedMac seen in {}", intf);
              return;
          }
-         String patchInt = AdminConfigManager.getManager().getPatchToIntegration();
+         String patchInt = adminConfigManager.getPatchToIntegration();
  
          int patchOFPort = -1;
          try {
          }
      }
  
+     private String getIntModVlanFlowName (int inOFPort, String fromVlan, String toVlan) {
+         return "int_mod_"+inOFPort+"_"+fromVlan+"_"+toVlan;
+     }
+     private String getIntDropFlowName (int inOFPort) {
+         return "int_drop_"+inOFPort;
+     }
+     private String getNetModVlanFlowName (int inOFPort, String fromVlan, String toVlan) {
+         return "net_mod_"+inOFPort+"_"+fromVlan+"_"+toVlan;
+     }
+     private String getNetDropFlowName (int inOFPort) {
+         return "net_drop_"+inOFPort;
+     }
+     private String getNetFwdFlowName (int inOFPort, int outOFPort, String vlan) {
+         return "net_fwd_"+vlan+"_"+inOFPort+"_"+outOFPort;
+     }
+     private void deleteRule (Node node, Node ofNode, String flowName) {
+         logger.debug("deleteRule: node: {} / {}, flowName: {}", node, ofNode, flowName);
+         try {
+             this.deleteStaticFlow(ofNode, flowName);
+         } catch (Exception e) {
+             logger.error("deleteRule: Failed to delete Flow Rule for {} / {}", node, ofNode, e);
+         }
+     }
+     /* in_port=p actions=drop */
+     private void programDropRule (Node node, Node ofNode, int inOFPort, String flowName) {
+         logger.debug("programDropRule: node: {} / {}, inOfPort: {}, flowName: {}",
+                 node, ofNode, inOFPort, flowName);
+         try {
+             FlowConfig flow = new FlowConfig();
+             flow.setName(flowName);
+             flow.setNode(ofNode);
+             flow.setInstallInHw(true);
+             flow.setPriority(DROP_FLOW_PRIORITY+"");
+             flow.setIngressPort(inOFPort+"");
+             List<String> actions = new ArrayList<String>();
+             actions.add(ActionType.DROP+"");
+             flow.setActions(actions);
+             Status status = this.addStaticFlow(ofNode, flow);
+             logger.debug("programDropRule: Flow Programming Status {} for Flow {} on {} / {}",
+                     status, flow, node, ofNode);
+         } catch (Exception e) {
+             logger.error("programDropRule: Failed to initialize Flow Rules for {} / {}", node, ofNode, e);
+         }
+     }
+     /* in_port=p2,dl_vlan=v actions=mod_vlan_vid,[NORMAL|output:p2] */
+     private void programModVlanRule (Node node, Node ofNode, int inOFPort, int outOFPort, String fromVlan,
+                                      String toVlan, String flowName) {
+         logger.debug("programModVlanRule: node: {} / {}, inOfPort: {}, fromVlan: {}, toVlan: {}, flowName: {}",
+                 node, ofNode, inOFPort, fromVlan, toVlan, flowName);
+         try {
+             FlowConfig flow = new FlowConfig();
+             flow.setName(flowName);
+             flow.setNode(ofNode);
+             flow.setInstallInHw(true);
+             flow.setPriority(INGRESS_TUNNEL_FLOW_PRIORITY+"");
+             flow.setIngressPort(inOFPort+"");
+             flow.setVlanId(fromVlan);
+             List<String> actions = new ArrayList<String>();
+             actions.add(ActionType.SET_VLAN_ID+"="+toVlan);
+             if (outOFPort == -1) {
+                 actions.add(ActionType.HW_PATH.toString());
+             } else {
+                 actions.add(ActionType.OUTPUT.toString()+"="+outOFPort);
+             }
+             flow.setActions(actions);
+             Status status = this.addStaticFlow(ofNode, flow);
+             logger.debug("programModVlanRule: Flow Programming Status {} for Flow {} on {} / {}",
+                     status, flow, node, ofNode);
+         } catch (Exception e) {
+             logger.error("programModVlanRule: Failed to initialize Flow Rule for {} / {}", node, ofNode, e);
+         }
+     }
+     /* in_port=p1,dl_vlan=v actions=output:p2 */
+     private void programForwardRule (Node node, Node ofNode, int inOFPort, int outOFPort, String vlan, String flowName) {
+         logger.debug("programModVlanRule: node: {} / {}, inOfPort: {}, outOFPort: {}, flowName: {}",
+                 node, ofNode, inOFPort, outOFPort, flowName);
+         try {
+             FlowConfig flow = new FlowConfig();
+             flow.setName(flowName);
+             flow.setNode(ofNode);
+             flow.setInstallInHw(true);
+             flow.setPriority(EGRESS_TUNNEL_FLOW_PRIORITY + "");
+             flow.setIngressPort(inOFPort + "");
+             flow.setVlanId(vlan);
+             List<String> actions = new ArrayList<String>();
+             actions.add(ActionType.OUTPUT.toString()+"="+outOFPort);
+             flow.setActions(actions);
+             Status status = this.addStaticFlow(ofNode, flow);
+             logger.debug("programForwardRule: Flow Programming Status {} for Flow {} on {} / {}",
+                     status, flow, node, ofNode);
+         } catch (Exception e) {
+             logger.error("programForwardRule: Failed to initialize Flow Rules for {} / {}", node, ofNode, e);
+         }
+     }
+     public int getOFPort (Node node, String portName) {
+         int ofPort = -1;
+         try {
+             OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
+             Map<String, Table<?>> intfs = ovsdbTable.getRows(node, Interface.NAME.getName());
+             if (intfs != null) {
+                 for (Table<?> row : intfs.values()) {
+                     Interface intf = (Interface)row;
+                     if (intf.getName().equalsIgnoreCase(portName)) {
+                         Set<BigInteger> of_ports = intf.getOfport();
+                         if (of_ports == null || of_ports.size() <= 0) {
+                             logger.error("Could not identify patch port {} on {}", portName, node);
+                             continue;
+                         }
+                         ofPort = Long.valueOf(((BigInteger)of_ports.toArray()[0]).longValue()).intValue();
+                         logger.debug("Identified port {} -> OF ({}) on {}", portName, ofPort, node);
+                         break;
+                     }
+                 }
+             }
+         } catch (Exception e) {
+             logger.error("", e);
+         }
+         return ofPort;
+     }
+     /*
+      * Transient class to return all the vlan network data needed for flow programming.
+      */
+     public class vlanNet {
+         public int patchIntOfPort;
+         public int patchNetOfPort;
+         public int physicalOfPort;
+         public int internalVlan;
+         public vlanNet (NeutronNetwork network, Node node, Interface intf) {
+             patchIntOfPort = -1;
+             patchNetOfPort = -1;
+             physicalOfPort = -1;
+             internalVlan = 0;
+             initializeVlanNet(network, node, intf);
+         }
+         public boolean isValid () {
+             if ((patchIntOfPort != -1) && (patchNetOfPort != -1) && (physicalOfPort != -1) && (internalVlan != -1)) {
+                 return true;
+             } else {
+                 return false;
+             }
+         }
+         public int getPatchIntOfPort () {
+             return patchIntOfPort;
+         }
+         public int getPatchNetOfPort () {
+             return patchNetOfPort;
+         }
+         public int getphysicalOfPort () {
+             return physicalOfPort;
+         }
+         public int getInternalVlan () {
+             return internalVlan;
+         }
+         public void initializeVlanNet (NeutronNetwork network, Node node, Interface intf) {
+             internalVlan = tenantNetworkManager.getInternalVlan(node, network.getNetworkUUID());
+             if (internalVlan == 0) {
+                 logger.debug("No InternalVlan provisioned for Tenant Network {}", network.getNetworkUUID());
+                 return;
+             }
+             /* Get ofports for patch ports and physical interface. */
+             String patchToNetworkName = adminConfigManager.getPatchToNetwork();
+             String patchToIntegrationName = adminConfigManager.getPatchToIntegration();
+             String physNetName = adminConfigManager.getPhysicalInterfaceName(node, network.getProviderPhysicalNetwork());
+             patchIntOfPort = getOFPort(node, patchToNetworkName);
+             if (patchIntOfPort == -1) {
+                 logger.error("Cannot identify {} interface on {}", patchToNetworkName, node);
+                 return;
+             }
+             patchNetOfPort = getOFPort(node, patchToIntegrationName);
+             if (patchNetOfPort == -1) {
+                 logger.error("Cannot identify {} interface on {}", patchToIntegrationName, node);
+                 return;
+             }
+             physicalOfPort = getOFPort(node, physNetName);
+             if (physicalOfPort == -1) {
+                 logger.error("Cannot identify {} interface on {}", physNetName, node);
+                 return;
+             }
+         }
+     }
+     private Node getOFNode (Node node, String bridgeName) {
+         String brUUID = internalNetworkManager.getInternalBridgeUUID(node, bridgeName);
+         if (brUUID == null) {
+             logger.error("getOFNode: Unable to find {} UUID on node {}", bridgeName, node);
+             return null;
+         }
+         try {
+             OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
+             Bridge bridge = (Bridge) ovsdbTable.getRow(node, Bridge.NAME.getName(), brUUID);
+             Set<String> dpids = bridge.getDatapath_id();
+             if (dpids == null || dpids.size() ==  0) {
+                 return null;
+             }
+             Long dpidLong = Long.valueOf(HexEncode.stringToLong((String)dpids.toArray()[0]));
+             Node ofNode = new Node(Node.NodeIDType.OPENFLOW, dpidLong);
+             return ofNode;
+         } catch (Exception e) {
+             logger.error("deleteRule: Failed to delete Flow Rule for {}", node, e);
+         }
+         return null;
+     }
+     /*
+      * Vlan isolation uses a patch port between br-int and br-net. Anything received on one end of
+      * the patch is piped to the other end of the patch so the incoming packets from the network would
+      * arrive untouched at the patch port on br-int.
+      *
+      * Program OF1.0 Flow rules on br-net in the ingress direction from the network
+      * and egress direction towards the network.
+      * The logic is to simply match on the incoming patch OF-Port and internal vlan,
+      * rewrite the internal vlan to the external vlan and forward out the physical port.
+      * There is also a flow to match the externally tagged packets from the physical port
+      * rewrite the external tag to the internal tag and forward to the patch port.
+      *
+      * priority=100,in_port=1,dl_vlan=1 actions=mod_vlan_vid:2001,output:2
+      * priority=100,in_port=2,dl_vlan=2001 actions=mod_vlan_vid:1actions=output:1
+      */
+     private void programVlanRules (NeutronNetwork network, Node node, Interface intf) {
+         vlanNet vlanNet = new vlanNet(network, node, intf);
+         if (vlanNet.isValid()) {
+             String netBrName = adminConfigManager.getNetworkBridgeName();
+             String intModVlanFlowName = getIntModVlanFlowName(vlanNet.getPatchNetOfPort(), network.getProviderSegmentationID(), vlanNet.getInternalVlan()+"");
+             String netModVlanFlowName = getNetModVlanFlowName(vlanNet.getPatchNetOfPort(), vlanNet.getInternalVlan()+"", network.getProviderSegmentationID());
+             Node netOFNode = getOFNode(node, netBrName);
+             if (netOFNode == null) {
+                 logger.error("Unable to find {} ofNode, Failed to initialize Flow Rules for {}", netBrName, node);
+                 return;
+             }
+             /* Program flows on br-net */
+             deleteRule(node, netOFNode, "NORMAL");
+             programModVlanRule(node, netOFNode, vlanNet.getPatchNetOfPort(), vlanNet.getphysicalOfPort(),
+                     vlanNet.getInternalVlan()+"", network.getProviderSegmentationID(), intModVlanFlowName);
+             programModVlanRule(node, netOFNode, vlanNet.getphysicalOfPort(), vlanNet.getPatchNetOfPort(),
+                     network.getProviderSegmentationID(), vlanNet.getInternalVlan()+"", netModVlanFlowName);
+         }
+     }
+     private void removeVlanRules (NeutronNetwork network, Node node, Interface intf) {
+         vlanNet vlanNet = new vlanNet(network, node, intf);
+         if (vlanNet.isValid()) {
+             String netBrName = adminConfigManager.getNetworkBridgeName();
+             String intModVlanFlowName = getIntModVlanFlowName(vlanNet.getPatchNetOfPort(), network.getProviderSegmentationID(), vlanNet.getInternalVlan()+"");
+             String netModVlanFlowName = getNetModVlanFlowName(vlanNet.getPatchNetOfPort(), vlanNet.getInternalVlan()+"", network.getProviderSegmentationID());
+             Node netOFNode = getOFNode(node, netBrName);
+             if (netOFNode == null) {
+                 logger.error("Unable to find {} ofNode, Failed to initialize Flow Rules for {}", netBrName, node);
+                 return;
+             }
+             deleteRule(node, netOFNode, intModVlanFlowName);
+             deleteRule(node, netOFNode, netModVlanFlowName);
+         }
+     }
      @Override
-     public Status handleInterfaceUpdate(String tunnelType, String tunnelKey, Node srcNode, Interface intf) {
-         Status status = getTunnelReadinessStatus(srcNode, tunnelKey);
-         if (!status.isSuccess()) return status;
+     public Status handleInterfaceUpdate(NeutronNetwork network, Node srcNode, Interface intf) {
+         logger.debug("handleInterfaceUpdate: networkType: {}, segmentationId: {}, srcNode: {}, intf: {}",
+                      network.getProviderNetworkType(), network.getProviderSegmentationID(), srcNode, intf.getName());
  
-         IConnectionServiceInternal connectionService = (IConnectionServiceInternal)ServiceHelper.getGlobalInstance(IConnectionServiceInternal.class, this);
-         List<Node> nodes = connectionService.getNodes();
-         nodes.remove(srcNode);
-         for (Node dstNode : nodes) {
-             status = getTunnelReadinessStatus(dstNode, tunnelKey);
-             if (!status.isSuccess()) continue;
-             InetAddress src = AdminConfigManager.getManager().getTunnelEndPoint(srcNode);
-             InetAddress dst = AdminConfigManager.getManager().getTunnelEndPoint(dstNode);
-             status = addTunnelPort(srcNode, tunnelType, src, dst, tunnelKey);
-             if (status.isSuccess()) {
-                 this.programTunnelRules(tunnelType, tunnelKey, dst, srcNode, intf, true);
+         if (network.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VLAN)) {
+             Status status = getVlanReadinessStatus(srcNode, network.getProviderSegmentationID());
+             if (!status.isSuccess()) {
+                 return status;
+             } else {
+                 this.programVlanRules(network, srcNode, intf);
+                 return new Status(StatusCode.SUCCESS);
              }
-             addTunnelPort(dstNode, tunnelType, dst, src, tunnelKey);
-             if (status.isSuccess()) {
-                 this.programTunnelRules(tunnelType, tunnelKey, src, dstNode, intf, false);
+         } else if (network.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VXLAN) ||
+                    network.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_GRE)) {
+             Status status = getTunnelReadinessStatus(srcNode, network.getProviderSegmentationID());
+             if (!status.isSuccess()) return status;
+             IConnectionServiceInternal connectionService = (IConnectionServiceInternal)ServiceHelper.getGlobalInstance(IConnectionServiceInternal.class, this);
+             List<Node> nodes = connectionService.getNodes();
+             nodes.remove(srcNode);
+             for (Node dstNode : nodes) {
+                 status = getTunnelReadinessStatus(dstNode, network.getProviderSegmentationID());
+                 if (!status.isSuccess()) continue;
+                 InetAddress src = adminConfigManager.getTunnelEndPoint(srcNode);
+                 InetAddress dst = adminConfigManager.getTunnelEndPoint(dstNode);
+                 status = addTunnelPort(srcNode, network.getProviderNetworkType(), src, dst, network.getProviderSegmentationID());
+                 if (status.isSuccess()) {
+                     this.programTunnelRules(network.getProviderNetworkType(), network.getProviderSegmentationID(), dst, srcNode, intf, true);
+                 }
+                 addTunnelPort(dstNode, network.getProviderNetworkType(), dst, src, network.getProviderSegmentationID());
+                 if (status.isSuccess()) {
+                     this.programTunnelRules(network.getProviderNetworkType(), network.getProviderSegmentationID(), src, dstNode, intf, false);
+                 }
              }
+             return new Status(StatusCode.SUCCESS);
+         } else {
+             return new Status(StatusCode.BADREQUEST);
          }
-         return new Status(StatusCode.SUCCESS);
      }
  
      @Override
-     public Status handleInterfaceDelete(String tunnelType, String tunnelKey, Node srcNode, Interface intf, boolean isLastInstanceOnNode) {
+     public Status handleInterfaceDelete(String tunnelType, NeutronNetwork network, Node srcNode, Interface intf, boolean isLastInstanceOnNode) {
          Status status = new Status(StatusCode.SUCCESS);
+         logger.debug("handleInterfaceDelete: srcNode: {}, networkType: {}, intf: {}, type: {}, isLast: {}",
+                 srcNode, (network != null) ? network.getProviderNetworkType() : "",
+                 intf.getName(), intf.getType(), isLastInstanceOnNode);
  
-         IConnectionServiceInternal connectionService = (IConnectionServiceInternal)ServiceHelper.getGlobalInstance(IConnectionServiceInternal.class, this);
-         List<Node> nodes = connectionService.getNodes();
-         nodes.remove(srcNode);
-         for (Node dstNode : nodes) {
-             InetAddress src = AdminConfigManager.getManager().getTunnelEndPoint(srcNode);
-             InetAddress dst = AdminConfigManager.getManager().getTunnelEndPoint(dstNode);
-             this.removeTunnelRules(tunnelType, tunnelKey, dst, srcNode, intf, true);
+         List<String> phyIfName = adminConfigManager.getAllPhysicalInterfaceNames(srcNode);
+         if ((network != null) && network.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VLAN)) {
              if (isLastInstanceOnNode) {
-                 status = deleteTunnelPort(srcNode, tunnelType, src, dst, tunnelKey);
+                 this.removeVlanRules(network, srcNode, intf);
              }
-             this.removeTunnelRules(tunnelType, tunnelKey, src, dstNode, intf, false);
-             if (status.isSuccess() && isLastInstanceOnNode) {
-                 deleteTunnelPort(dstNode, tunnelType, dst, src, tunnelKey);
+         } else if (intf.getType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VXLAN) || intf.getType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_GRE)) {
+             /* Delete tunnel port */
+             try {
+                 OvsDBMap<String, String> options = intf.getOptions();
+                 InetAddress src = InetAddress.getByName(options.get("local_ip"));
+                 InetAddress dst = InetAddress.getByName(options.get("remote_ip"));
+                 String key = options.get("key");
+                 status = deleteTunnelPort(srcNode, intf.getType(), src, dst, key);
+             } catch (Exception e) {
+                 logger.error(e.getMessage(), e);
+             }
+         } else if (phyIfName.contains(intf.getName())) {
+             deletePhysicalPort(srcNode, intf.getName());
+         } else {
+             /* delete all other interfaces */
+             IConnectionServiceInternal connectionService = (IConnectionServiceInternal)ServiceHelper.getGlobalInstance(IConnectionServiceInternal.class, this);
+             List<Node> nodes = connectionService.getNodes();
+             nodes.remove(srcNode);
+             for (Node dstNode : nodes) {
+                 InetAddress src = adminConfigManager.getTunnelEndPoint(srcNode);
+                 InetAddress dst = adminConfigManager.getTunnelEndPoint(dstNode);
+                 this.removeTunnelRules(network.getProviderNetworkType(), network.getProviderSegmentationID(), dst, srcNode, intf, true);
+                 if (isLastInstanceOnNode) {
+                     status = deleteTunnelPort(srcNode, network.getProviderNetworkType(), src, dst, network.getProviderSegmentationID());
+                 }
+                 this.removeTunnelRules(network.getProviderNetworkType(), network.getProviderSegmentationID(), src, dstNode, intf, false);
+                 if (status.isSuccess() && isLastInstanceOnNode) {
+                     deleteTunnelPort(dstNode, network.getProviderNetworkType(), dst, src, network.getProviderSegmentationID());
+                 }
              }
          }
          return status;
          return false;
      }
  
-     private String getTunnelPortUuid(Node node, String tunnelName, String bridgeUUID) throws Exception {
+     private String getPortUuid(Node node, String portName, String bridgeUUID) throws Exception {
          OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
          Bridge bridge = (Bridge)ovsdbTable.getRow(node, Bridge.NAME.getName(), bridgeUUID);
          if (bridge != null) {
              Set<UUID> ports = bridge.getPorts();
              for (UUID portUUID : ports) {
                  Port port = (Port)ovsdbTable.getRow(node, Port.NAME.getName(), portUUID.toString());
-                 if (port != null && port.getName().equalsIgnoreCase(tunnelName)) return portUUID.toString();
+                 if (port != null && port.getName().equalsIgnoreCase(portName)) return portUUID.toString();
              }
          }
          return null;
      private Status addTunnelPort (Node node, String tunnelType, InetAddress src, InetAddress dst, String key) {
          try {
              String bridgeUUID = null;
-             String tunnelBridgeName = AdminConfigManager.getManager().getTunnelBridgeName();
+             String tunnelBridgeName = adminConfigManager.getNetworkBridgeName();
              OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
              Map<String, Table<?>> bridgeTable = ovsdbTable.getRows(node, Bridge.NAME.getName());
              if (bridgeTable != null) {
          }
      }
  
-     private Status deleteTunnelPort (Node node, String tunnelType, InetAddress src, InetAddress dst, String key) {
+     private Status deletePort(Node node, String bridgeName, String portName) {
          try {
              String bridgeUUID = null;
-             String tunnelBridgeName = AdminConfigManager.getManager().getTunnelBridgeName();
              OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
              Map<String, Table<?>> bridgeTable = ovsdbTable.getRows(node, Bridge.NAME.getName());
              if (bridgeTable != null) {
                  for (String uuid : bridgeTable.keySet()) {
                      Bridge bridge = (Bridge)bridgeTable.get(uuid);
-                     if (bridge.getName().equals(tunnelBridgeName)) {
+                     if (bridge.getName().equals(bridgeName)) {
                          bridgeUUID = uuid;
                          break;
                      }
                  }
              }
              if (bridgeUUID == null) {
-                 logger.debug("Could not find Bridge {} in {}", tunnelBridgeName, node);
+                 logger.debug("Could not find Bridge {} in {}", bridgeName, node);
                  return new Status(StatusCode.SUCCESS);
              }
-             String portName = getTunnelName(tunnelType, key, dst);
-             String tunnelPortUUID = this.getTunnelPortUuid(node, portName, bridgeUUID);
-             Status status = ovsdbTable.deleteRow(node, Port.NAME.getName(), tunnelPortUUID);
-             if (!status.isSuccess()) {
-                 logger.error("Failed to delete Tunnel port {} in {} status : {}", portName, bridgeUUID, status);
-                 return status;
+             String portUUID = this.getPortUuid(node, portName, bridgeUUID);
+             Status status = new Status(StatusCode.SUCCESS);
+             if (portUUID != null) {
+                 status = ovsdbTable.deleteRow(node, Port.NAME.getName(), portUUID);
+                 if (!status.isSuccess()) {
+                     logger.error("Failed to delete port {} in {} status : {}", portName, bridgeUUID, status);
+                     return status;
+                 }
+                 logger.debug("Port {} delete status : {}", portName, status);
              }
-             logger.debug("Tunnel {} delete status : {}", portName, status);
              return status;
          } catch (Exception e) {
              logger.error("Exception in deleteTunnelPort", e);
          }
      }
  
+     private Status deleteTunnelPort (Node node, String tunnelType, InetAddress src, InetAddress dst, String key) {
+         String tunnelBridgeName = adminConfigManager.getNetworkBridgeName();
+         String portName = getTunnelName(tunnelType, key, dst);
+         Status status = deletePort(node, tunnelBridgeName, portName);
+         return status;
+     }
+     private Status deletePhysicalPort(Node node, String phyIntfName) {
+         String netBridgeName = adminConfigManager.getNetworkBridgeName();
+         Status status = deletePort(node, netBridgeName, phyIntfName);
+         return status;
+     }
      @Override
      public Status handleInterfaceUpdate(String tunnelType, String tunnelKey) {
          IConnectionServiceInternal connectionService = (IConnectionServiceInternal)ServiceHelper.getGlobalInstance(IConnectionServiceInternal.class, this);
          List<Node> nodes = connectionService.getNodes();
          for (Node srcNode : nodes) {
-             this.handleInterfaceUpdate(tunnelType, tunnelKey, srcNode, null);
+             this.handleInterfaceUpdate(null, srcNode, null);
          }
          return new Status(StatusCode.SUCCESS);
      }
  
      @Override
      public void initializeFlowRules(Node node) {
-         this.initializeFlowRules(node, AdminConfigManager.getManager().getIntegrationBridgeName());
-         this.initializeFlowRules(node, AdminConfigManager.getManager().getTunnelBridgeName());
-         this.initializeFlowRules(node, AdminConfigManager.getManager().getExternalBridgeName());
+         this.initializeFlowRules(node, adminConfigManager.getIntegrationBridgeName());
+         this.initializeFlowRules(node, adminConfigManager.getExternalBridgeName());
      }
  
      private void initializeFlowRules(Node node, String bridgeName) {
          String brIntId = this.getInternalBridgeUUID(node, bridgeName);
          if (brIntId == null) {
-             if (bridgeName == AdminConfigManager.getManager().getExternalBridgeName()){
+             if (bridgeName == adminConfigManager.getExternalBridgeName()){
                  logger.debug("Failed to initialize Flow Rules for bridge {} on node {}. Is the Neutron L3 agent running on this node?");
              }
              else {
          IForwardingRulesManager frm = (IForwardingRulesManager) ServiceHelper.getInstance(
                  IForwardingRulesManager.class, "default", this);
          if (frm.getStaticFlow(flowName, ofNode) == null) {
-             logger.debug("Flow doese not exist {} on {}. Skipping deletion.", flowName, ofNode);
+             logger.debug("Flow does not exist {} on {}. Skipping deletion.", flowName, ofNode);
              return new Status(StatusCode.SUCCESS);
          }
          return frm.removeStaticFlow(flowName,ofNode);
-     }}
+     }
+     private String getInternalBridgeUUID (Node node, String bridgeName) {
+         try {
+             OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
+             Map<String, Table<?>> bridgeTable = ovsdbTable.getRows(node, Bridge.NAME.getName());
+             if (bridgeTable == null) return null;
+             for (String key : bridgeTable.keySet()) {
+                 Bridge bridge = (Bridge)bridgeTable.get(key);
+                 if (bridge.getName().equals(bridgeName)) return key;
+             }
+         } catch (Exception e) {
+             logger.error("Error getting Bridge Identifier for {} / {}", node, bridgeName, e);
+         }
+         return null;
+     }
+ }
index 0000000000000000000000000000000000000000,542128a4317c76c057f7be39e559c7a7a94a058f..c6cd2591055ec9ccf2ef5d447de5c6c39739930c
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,4078 +1,4078 @@@
 -            Map<String, org.opendaylight.ovsdb.lib.table.internal.Table<?>> bridgeTable = ovsdbTable.getRows(node, Bridge.NAME.getName());
+ /**
+  * Copyright (C) 2013 Red Hat, Inc.
+  *
+  * This program and the accompanying materials are made available under the
+  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+  * and is available at http://www.eclipse.org/legal/epl-v10.html
+  *
+  * Authors : Madhu Venugopal, Brent Salisbury, Dave Tucker
+  */
+ package org.opendaylight.ovsdb.neutron.provider;
+ import java.math.BigInteger;
+ import java.net.InetAddress;
+ import java.util.ArrayList;
+ import java.util.List;
+ import java.util.Map;
+ import java.util.Set;
+ import java.util.concurrent.ExecutionException;
+ import java.util.concurrent.Future;
+ import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+ import org.opendaylight.controller.md.sal.common.api.data.DataModification;
+ import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork;
+ import org.opendaylight.controller.sal.binding.api.data.DataBrokerService;
+ import org.opendaylight.controller.sal.core.Node;
+ import org.opendaylight.controller.sal.utils.HexEncode;
+ import org.opendaylight.controller.sal.utils.ServiceHelper;
+ import org.opendaylight.controller.sal.utils.Status;
+ import org.opendaylight.controller.sal.utils.StatusCode;
+ import org.opendaylight.controller.switchmanager.ISwitchManager;
+ import org.opendaylight.ovsdb.lib.notation.OvsDBMap;
+ import org.opendaylight.ovsdb.lib.notation.OvsDBSet;
+ import org.opendaylight.ovsdb.lib.notation.UUID;
+ import org.opendaylight.ovsdb.lib.table.Bridge;
+ import org.opendaylight.ovsdb.lib.table.Interface;
+ import org.opendaylight.ovsdb.lib.table.Port;
+ import org.opendaylight.ovsdb.neutron.IAdminConfigManager;
+ import org.opendaylight.ovsdb.neutron.IInternalNetworkManager;
+ import org.opendaylight.ovsdb.neutron.IMDSALConsumer;
+ import org.opendaylight.ovsdb.neutron.NetworkHandler;
+ import org.opendaylight.ovsdb.neutron.ITenantNetworkManager;
+ import org.opendaylight.ovsdb.plugin.IConnectionServiceInternal;
+ import org.opendaylight.ovsdb.plugin.OVSDBConfigService;
+ import org.opendaylight.ovsdb.plugin.StatusWithUuid;
+ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
+ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
+ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
+ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.DecNwTtlCaseBuilder;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.DropActionCaseBuilder;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.GroupActionCase;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.GroupActionCaseBuilder;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionCase;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionCaseBuilder;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PopVlanActionCase;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PopVlanActionCaseBuilder;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetFieldCaseBuilder;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNwDstActionCaseBuilder;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNwSrcActionCaseBuilder;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanIdActionCaseBuilder;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushVlanActionCaseBuilder;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.dec.nw.ttl._case.DecNwTtl;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.dec.nw.ttl._case.DecNwTtlBuilder;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.drop.action._case.DropAction;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.drop.action._case.DropActionBuilder;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.group.action._case.GroupActionBuilder;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.output.action._case.OutputActionBuilder;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.push.vlan.action._case.PushVlanActionBuilder;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.pop.vlan.action._case.PopVlanActionBuilder;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.field._case.SetFieldBuilder;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.nw.dst.action._case.SetNwDstActionBuilder;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.nw.src.action._case.SetNwSrcActionBuilder;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.vlan.id.action._case.SetVlanIdActionBuilder;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionKey;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.address.Ipv4Builder;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
+ 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.GoToTableCaseBuilder;
+ 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.instruction.go.to.table._case.GoToTableBuilder;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.BucketId;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupId;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.BucketsBuilder;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.Bucket;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.BucketBuilder;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.BucketKey;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupBuilder;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupKey;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.Buckets;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.EtherType;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.arp.match.fields.ArpSourceHardwareAddressBuilder;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.arp.match.fields.ArpTargetHardwareAddressBuilder;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetDestinationBuilder;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetSourceBuilder;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetTypeBuilder;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatchBuilder;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Icmpv4MatchBuilder;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.IpMatchBuilder;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.TunnelBuilder;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatchBuilder;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.ArpMatchBuilder;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchBuilder;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.TcpMatchBuilder;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.UdpMatchBuilder;
+ import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.vlan.match.fields.VlanIdBuilder;
+ import org.opendaylight.yangtools.yang.binding.DataObject;
+ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+ import org.opendaylight.yangtools.yang.common.RpcResult;
+ import org.slf4j.Logger;
+ import org.slf4j.LoggerFactory;
+ /**
+  *
+  */
+ public class OF13Provider implements NetworkProvider {
+     private static final Logger logger = LoggerFactory.getLogger(OF13Provider.class);
+     private DataBrokerService dataBrokerService;
+     private static final short TABLE_0_DEFAULT_INGRESS = 0;
+     private static final short TABLE_1_ISOLATE_TENANT = 10;
+     private static final short TABLE_2_LOCAL_FORWARD = 20;
+     private static Long groupId = 1L;
+     private IAdminConfigManager adminConfigManager;
+     private IInternalNetworkManager internalNetworkManager;
+     private ITenantNetworkManager tenantNetworkManager;
+     public OF13Provider(IAdminConfigManager adminConfigManager,
+                         IInternalNetworkManager internalNetworkManager,
+                         ITenantNetworkManager tenantNetworkManager) {
+         this.adminConfigManager = adminConfigManager;
+         this.internalNetworkManager = internalNetworkManager;
+         this.tenantNetworkManager = tenantNetworkManager;
+     }
+     @Override
+     public boolean hasPerTenantTunneling() {
+         return false;
+     }
+     private Status getTunnelReadinessStatus (Node node, String tunnelKey) {
+         InetAddress srcTunnelEndPoint = adminConfigManager.getTunnelEndPoint(node);
+         if (srcTunnelEndPoint == null) {
+             logger.error("Tunnel Endpoint not configured for Node {}", node);
+             return new Status(StatusCode.NOTFOUND, "Tunnel Endpoint not configured for "+ node);
+         }
+         if (!internalNetworkManager.isInternalNetworkNeutronReady(node)) {
+             logger.error(node+" is not Overlay ready");
+             return new Status(StatusCode.NOTACCEPTABLE, node+" is not Overlay ready");
+         }
+         if (!tenantNetworkManager.isTenantNetworkPresentInNode(node, tunnelKey)) {
+             logger.debug(node+" has no VM corresponding to segment "+ tunnelKey);
+             return new Status(StatusCode.NOTACCEPTABLE, node+" has no VM corresponding to segment "+ tunnelKey);
+         }
+         return new Status(StatusCode.SUCCESS);
+     }
+     private String getTunnelName(String tunnelType, InetAddress dst) {
+         return tunnelType+"-"+dst.getHostAddress();
+     }
+     private boolean isTunnelPresent(Node node, String tunnelName, String bridgeUUID) throws Exception {
+         OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
+         Bridge bridge = (Bridge)ovsdbTable.getRow(node, Bridge.NAME.getName(), bridgeUUID);
+         if (bridge != null) {
+             Set<UUID> ports = bridge.getPorts();
+             for (UUID portUUID : ports) {
+                 Port port = (Port)ovsdbTable.getRow(node, Port.NAME.getName(), portUUID.toString());
+                 if (port != null && port.getName().equalsIgnoreCase(tunnelName)) return true;
+             }
+         }
+         return false;
+     }
+     private String getPortUuid(Node node, String name, String bridgeUUID) throws Exception {
+         OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
+         Bridge bridge = (Bridge)ovsdbTable.getRow(node, Bridge.NAME.getName(), bridgeUUID);
+         if (bridge != null) {
+             Set<UUID> ports = bridge.getPorts();
+             for (UUID portUUID : ports) {
+                 Port port = (Port)ovsdbTable.getRow(node, Port.NAME.getName(), portUUID.toString());
+                 if (port != null && port.getName().equalsIgnoreCase(name)) return portUUID.toString();
+             }
+         }
+         return null;
+     }
+     private Status addTunnelPort (Node node, String tunnelType, InetAddress src, InetAddress dst) {
+         try {
+             String bridgeUUID = null;
+             String tunnelBridgeName = adminConfigManager.getIntegrationBridgeName();
+             OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
 -            Map<String, org.opendaylight.ovsdb.lib.table.internal.Table<?>> bridgeTable = ovsdbTable.getRows(node, Bridge.NAME.getName());
++            Map<String, org.opendaylight.ovsdb.lib.table.Table<?>> bridgeTable = ovsdbTable.getRows(node, Bridge.NAME.getName());
+             if (bridgeTable != null) {
+                 for (String uuid : bridgeTable.keySet()) {
+                     Bridge bridge = (Bridge)bridgeTable.get(uuid);
+                     if (bridge.getName().equals(tunnelBridgeName)) {
+                         bridgeUUID = uuid;
+                         break;
+                     }
+                 }
+             }
+             if (bridgeUUID == null) {
+                 logger.error("Could not find Bridge {} in {}", tunnelBridgeName, node);
+                 return new Status(StatusCode.NOTFOUND, "Could not find "+tunnelBridgeName+" in "+node);
+             }
+             String portName = getTunnelName(tunnelType, dst);
+             if (this.isTunnelPresent(node, portName, bridgeUUID)) {
+                 logger.trace("Tunnel {} is present in {} of {}", portName, tunnelBridgeName, node);
+                 return new Status(StatusCode.SUCCESS);
+             }
+             Port tunnelPort = new Port();
+             tunnelPort.setName(portName);
+             StatusWithUuid statusWithUuid = ovsdbTable.insertRow(node, Port.NAME.getName(), bridgeUUID, tunnelPort);
+             if (!statusWithUuid.isSuccess()) {
+                 logger.error("Failed to insert Tunnel port {} in {}", portName, bridgeUUID);
+                 return statusWithUuid;
+             }
+             String tunnelPortUUID = statusWithUuid.getUuid().toString();
+             String interfaceUUID = null;
+             int timeout = 6;
+             while ((interfaceUUID == null) && (timeout > 0)) {
+                 tunnelPort = (Port)ovsdbTable.getRow(node, Port.NAME.getName(), tunnelPortUUID);
+                 OvsDBSet<UUID> interfaces = tunnelPort.getInterfaces();
+                 if (interfaces == null || interfaces.size() == 0) {
+                     // Wait for the OVSDB update to sync up the Local cache.
+                     Thread.sleep(500);
+                     timeout--;
+                     continue;
+                 }
+                 interfaceUUID = interfaces.toArray()[0].toString();
+                 Interface intf = (Interface)ovsdbTable.getRow(node, Interface.NAME.getName(), interfaceUUID);
+                 if (intf == null) interfaceUUID = null;
+             }
+             if (interfaceUUID == null) {
+                 logger.error("Cannot identify Tunnel Interface for port {}/{}", portName, tunnelPortUUID);
+                 return new Status(StatusCode.INTERNALERROR);
+             }
+             Interface tunInterface = new Interface();
+             tunInterface.setType(tunnelType);
+             OvsDBMap<String, String> options = new OvsDBMap<String, String>();
+             options.put("key", "flow");
+             options.put("local_ip", src.getHostAddress());
+             options.put("remote_ip", dst.getHostAddress());
+             tunInterface.setOptions(options);
+             Status status = ovsdbTable.updateRow(node, Interface.NAME.getName(), tunnelPortUUID, interfaceUUID, tunInterface);
+             logger.debug("Tunnel {} add status : {}", tunInterface, status);
+             return status;
+         } catch (Exception e) {
+             logger.error("Exception in addTunnelPort", e);
+             return new Status(StatusCode.INTERNALERROR);
+         }
+     }
+     /* delete port from ovsdb port table */
+     private Status deletePort(Node node, String bridgeName, String portName) {
+         try {
+             String bridgeUUID = null;
+             OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
 -            Map<String, org.opendaylight.ovsdb.lib.table.internal.Table<?>> intfs = ovsdbTable.getRows(node, Interface.NAME.getName());
++            Map<String, org.opendaylight.ovsdb.lib.table.Table<?>> bridgeTable = ovsdbTable.getRows(node, Bridge.NAME.getName());
+             if (bridgeTable != null) {
+                 for (String uuid : bridgeTable.keySet()) {
+                     Bridge bridge = (Bridge)bridgeTable.get(uuid);
+                     if (bridge.getName().equals(bridgeName)) {
+                         bridgeUUID = uuid;
+                         break;
+                     }
+                 }
+             }
+             if (bridgeUUID == null) {
+                 logger.debug("Could not find Bridge {} in {}", bridgeName, node);
+                 return new Status(StatusCode.SUCCESS);
+             }
+             String portUUID = this.getPortUuid(node, portName, bridgeUUID);
+             Status status = new Status(StatusCode.SUCCESS);
+             if (portUUID != null) {
+                status = ovsdbTable.deleteRow(node, Port.NAME.getName(), portUUID);
+                if (!status.isSuccess()) {
+                    logger.error("Failed to delete port {} in {} status : {}", portName, bridgeUUID,
+                                 status);
+                    return status;
+                }
+                logger.debug("Port {} delete status : {}", portName, status);
+             }
+             return status;
+         } catch (Exception e) {
+             logger.error("Exception in deletePort", e);
+             return new Status(StatusCode.INTERNALERROR);
+         }
+     }
+     private Status deleteTunnelPort(Node node, String tunnelType, InetAddress src, InetAddress dst) {
+         String tunnelBridgeName = adminConfigManager.getIntegrationBridgeName();
+         String portName = getTunnelName(tunnelType, dst);
+         Status status = deletePort(node, tunnelBridgeName, portName);
+         return status;
+     }
+     private Status deletePhysicalPort(Node node, String phyIntfName) {
+         String intBridgeName = adminConfigManager.getIntegrationBridgeName();
+         Status status = deletePort(node, intBridgeName, phyIntfName);
+         return status;
+     }
+     private void programLocalBridgeRules(Node node, Long dpid, String segmentationId, String attachedMac, long localPort) {
+          /*
+          * Table(0) Rule #3
+          * ----------------
+          * Match: VM sMac and Local Ingress Port
+          * Action:Action: Set Tunnel ID and GOTO Local Table (5)
+          */
+          handleLocalInPort(dpid, TABLE_0_DEFAULT_INGRESS, TABLE_1_ISOLATE_TENANT, segmentationId, localPort, attachedMac, true);
+         /*
+          * Table(0) Rule #4
+          * ----------------
+          * Match: Drop any remaining Ingress Local VM Packets
+          * Action: Drop w/ a low priority
+          */
+          handleDropSrcIface(dpid, localPort, true);
+          /*
+           * Table(2) Rule #1
+           * ----------------
+           * Match: Match TunID and Destination DL/dMAC Addr
+           * Action: Output Port
+           * table=2,tun_id=0x5,dl_dst=00:00:00:00:00:01 actions=output:2
+           */
+          handleLocalUcastOut(dpid, TABLE_2_LOCAL_FORWARD, segmentationId, localPort, attachedMac, true);
+          /*
+           * Table(2) Rule #2
+           * ----------------
+           * Match: Tunnel ID and dMAC (::::FF:FF)
+           * table=2,priority=16384,tun_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
+           * actions=output:2,3,4,5
+           */
+           handleLocalBcastOut(dpid, TABLE_2_LOCAL_FORWARD, segmentationId, localPort, true);
+           /*
+            * TODO : Optimize the following 2 writes to be restricted only for the very first port known in a segment.
+            */
+           /*
+            * Table(1) Rule #3
+            * ----------------
+            * Match:  Any remaining Ingress Local VM Packets
+            * Action: Drop w/ a low priority
+            * -------------------------------------------
+            * table=1,priority=8192,tun_id=0x5 actions=goto_table:2
+            */
+            handleTunnelMiss(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD, segmentationId, true);
+           /*
+            * Table(2) Rule #3
+            * ----------------
+            * Match: Any Remaining Flows w/a TunID
+            * Action: Drop w/ a low priority
+            * table=2,priority=8192,tun_id=0x5 actions=drop
+            */
+            handleLocalTableMiss(dpid, TABLE_2_LOCAL_FORWARD, segmentationId, true);
+     }
+     private void removeLocalBridgeRules(Node node, Long dpid, String segmentationId, String attachedMac, long localPort) {
+         /*
+          * Table(0) Rule #3
+          * ----------------
+          * Match: VM sMac and Local Ingress Port
+          * Action:Action: Set Tunnel ID and GOTO Local Table (5)
+          */
+          handleLocalInPort(dpid, TABLE_0_DEFAULT_INGRESS, TABLE_1_ISOLATE_TENANT, segmentationId, localPort, attachedMac, false);
+         /*
+          * Table(0) Rule #4
+          * ----------------
+          * Match: Drop any remaining Ingress Local VM Packets
+          * Action: Drop w/ a low priority
+          */
+          handleDropSrcIface(dpid, localPort, false);
+          /*
+           * Table(2) Rule #1
+           * ----------------
+           * Match: Match TunID and Destination DL/dMAC Addr
+           * Action: Output Port
+           * table=2,tun_id=0x5,dl_dst=00:00:00:00:00:01 actions=output:2
+           */
+          handleLocalUcastOut(dpid, TABLE_2_LOCAL_FORWARD, segmentationId, localPort, attachedMac, false);
+          /*
+           * Table(2) Rule #2
+           * ----------------
+           * Match: Tunnel ID and dMAC (::::FF:FF)
+           * table=2,priority=16384,tun_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
+           * actions=output:2,3,4,5
+           */
+           handleLocalBcastOut(dpid, TABLE_2_LOCAL_FORWARD, segmentationId, localPort, false);
+     }
+     private void programLocalIngressTunnelBridgeRules(Node node, Long dpid, String segmentationId, String attachedMac, long tunnelOFPort, long localPort) {
+         /*
+          * Table(0) Rule #2
+          * ----------------
+          * Match: Ingress Port, Tunnel ID
+          * Action: GOTO Local Table (20)
+          */
+          handleTunnelIn(dpid, TABLE_0_DEFAULT_INGRESS, TABLE_2_LOCAL_FORWARD, segmentationId, tunnelOFPort, true);
+          /*
+           * Table(1) Rule #2
+           * ----------------
+           * Match: Match Tunnel ID and L2 ::::FF:FF Flooding
+           * Action: Flood to selected destination TEPs
+           * -------------------------------------------
+           * table=1,priority=16384,tun_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
+           * actions=output:10,output:11,goto_table:2
+           */
+          handleTunnelFloodOut(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD, segmentationId, tunnelOFPort, true);
+     }
+     private void programRemoteEgressTunnelBridgeRules(Node node, Long dpid, String segmentationId, String attachedMac, long tunnelOFPort, long localPort) {
+         /*
+          * Table(1) Rule #1
+          * ----------------
+          * Match: Drop any remaining Ingress Local VM Packets
+          * Action: Drop w/ a low priority
+          * -------------------------------------------
+          * table=1,tun_id=0x5,dl_dst=00:00:00:00:00:08 \
+          * actions=output:11,goto_table:2
+          */
+         handleTunnelOut(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD, segmentationId, tunnelOFPort, attachedMac, true);
+     }
+     private void removeRemoteEgressTunnelBridgeRules(Node node, Long dpid, String segmentationId, String attachedMac, long tunnelOFPort, long localPort) {
+         /*
+          * Table(1) Rule #1
+          * ----------------
+          * Match: Drop any remaining Ingress Local VM Packets
+          * Action: Drop w/ a low priority
+          * -------------------------------------------
+          * table=1,tun_id=0x5,dl_dst=00:00:00:00:00:08 \
+          * actions=output:11,goto_table:2
+          */
+         handleTunnelOut(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD, segmentationId, tunnelOFPort, attachedMac, false);
+     }
+     /* Remove tunnel rules if last node in this tenant network */
+     private void removePerTunnelRules(Node node, Long dpid, String segmentationId, long tunnelOFPort) {
+         /*
+          * TODO : Optimize the following 2 writes to be restricted only for the very first port known in a segment.
+          */
+         /*
+          * Table(1) Rule #3
+          * ----------------
+          * Match:  Any remaining Ingress Local VM Packets
+          * Action: Drop w/ a low priority
+          * -------------------------------------------
+          * table=1,priority=8192,tun_id=0x5 actions=goto_table:2
+          */
+         handleTunnelMiss(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD, segmentationId, false);
+         /*
+          * Table(2) Rule #3
+          * ----------------
+          * Match: Any Remaining Flows w/a TunID
+          * Action: Drop w/ a low priority
+          * table=2,priority=8192,tun_id=0x5 actions=drop
+          */
+         handleLocalTableMiss(dpid, TABLE_2_LOCAL_FORWARD, segmentationId, false);
+         /*
+          * Table(0) Rule #2
+          * ----------------
+          * Match: Ingress Port, Tunnel ID
+          * Action: GOTO Local Table (10)
+          */
+         handleTunnelIn(dpid, TABLE_0_DEFAULT_INGRESS, TABLE_2_LOCAL_FORWARD, segmentationId, tunnelOFPort, false);
+          /*
+           * Table(1) Rule #2
+           * ----------------
+           * Match: Match Tunnel ID and L2 ::::FF:FF Flooding
+           * Action: Flood to selected destination TEPs
+           * -------------------------------------------
+           * table=1,priority=16384,tun_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
+           * actions=output:10,output:11,goto_table:2
+           */
+         handleTunnelFloodOut(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD, segmentationId, tunnelOFPort, false);
+     }
+     private void programLocalVlanRules(Node node, Long dpid, String segmentationId, String attachedMac, long localPort) {
+         /*
+          * Table(0) Rule #1
+          * ----------------
+          * Match: VM sMac and Local Ingress Port
+          * Action: Set VLAN ID and GOTO Local Table 1
+          */
+         handleLocalInPortSetVlan(dpid, TABLE_0_DEFAULT_INGRESS,
+                 TABLE_1_ISOLATE_TENANT, segmentationId, localPort,
+                 attachedMac, true);
+         /*
+          * Table(0) Rule #3
+          * ----------------
+          * Match: Drop any remaining Ingress Local VM Packets
+          * Action: Drop w/ a low priority
+          */
+         handleDropSrcIface(dpid, localPort, true);
+         /*
+          * Table(2) Rule #1
+          * ----------------
+          * Match: Match VLAN ID and Destination DL/dMAC Addr
+          * Action: strip vlan, output to local port
+          * Example: table=2,vlan_id=0x5,dl_dst=00:00:00:00:00:01 actions= strip vlan, output:2
+          */
+         handleLocalVlanUcastOut(dpid, TABLE_2_LOCAL_FORWARD, segmentationId,
+                 localPort, attachedMac, true);
+         /*
+          * Table(2) Rule #2
+          * ----------------
+          * Match: VLAN ID and dMAC (::::FF:FF)
+          * Action: strip vlan, output to all local ports in this vlan
+          * Example: table=2,priority=16384,vlan_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
+          * actions= strip_vlan, output:2,3,4,5
+          */
+         handleLocalVlanBcastOut(dpid, TABLE_2_LOCAL_FORWARD, segmentationId,
+                 localPort, true);
+          /*
+           * Table(2) Rule #3
+           * ----------------
+           * Match: Any Remaining Flows w/a VLAN ID
+           * Action: Drop w/ a low priority
+           * Example: table=2,priority=8192,vlan_id=0x5 actions=drop
+           */
+           handleLocalVlanTableMiss(dpid, TABLE_2_LOCAL_FORWARD, segmentationId,
+                                    true);
+    }
+     private void removeLocalVlanRules(Node node, Long dpid,
+                                       String segmentationId, String attachedMac,
+                                       long localPort) {
+         /*
+          * Table(0) Rule #1
+          * ----------------
+          * Match: VM sMac and Local Ingress Port
+          * Action: Set VLAN ID and GOTO Local Table 1
+          */
+         handleLocalInPortSetVlan(dpid, TABLE_0_DEFAULT_INGRESS,
+                 TABLE_1_ISOLATE_TENANT, segmentationId, localPort,
+                 attachedMac, false);
+         /*
+          * Table(0) Rule #3
+          * ----------------
+          * Match: Drop any remaining Ingress Local VM Packets
+          * Action: Drop w/ a low priority
+          */
+         handleDropSrcIface(dpid, localPort, false);
+         /*
+          * Table(2) Rule #1
+          * ----------------
+          * Match: Match VLAN ID and Destination DL/dMAC Addr
+          * Action: strip vlan, output to local port
+          * Example: table=2,vlan_id=0x5,dl_dst=00:00:00:00:00:01 actions= strip vlan, output:2
+          */
+         handleLocalVlanUcastOut(dpid, TABLE_2_LOCAL_FORWARD, segmentationId,
+                 localPort, attachedMac, false);
+         /*
+          * Table(2) Rule #2
+          * ----------------
+          * Match: VLAN ID and dMAC (::::FF:FF)
+          * Action: strip vlan, output to all local ports in this vlan
+          * Example: table=2,priority=16384,vlan_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
+          * actions= strip_vlan, output:2,3,4,5
+          */
+         handleLocalVlanBcastOut(dpid, TABLE_2_LOCAL_FORWARD, segmentationId,
+                 localPort, false);
+    }
+    private void programLocalIngressVlanRules(Node node, Long dpid, String segmentationId, String attachedMac, long ethPort) {
+        /*
+         * Table(0) Rule #2
+         * ----------------
+         * Match: Ingress port = physical interface, Vlan ID
+         * Action: GOTO Local Table 2
+         */
+        handleVlanIn(dpid, TABLE_0_DEFAULT_INGRESS, TABLE_2_LOCAL_FORWARD,
+                     segmentationId, ethPort, true);
+         /*
+          * Table(1) Rule #2
+          * ----------------
+          * Match: Match VLAN ID and L2 ::::FF:FF Flooding
+          * Action: Flood to local and remote VLAN members
+          * -------------------------------------------
+          * Example: table=1,priority=16384,vlan_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
+          * actions=output:10 (eth port),goto_table:2
+          */
+         handleVlanFloodOut(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD,
+                            segmentationId, ethPort, true);
+    }
+    private void programRemoteEgressVlanRules(Node node, Long dpid, String segmentationId, String attachedMac, long ethPort) {
+        /*
+         * Table(1) Rule #1
+         * ----------------
+         * Match: Destination MAC is local VM MAC and vlan id
+         * Action: go to table 2
+         * -------------------------------------------
+         * Example: table=1,vlan_id=0x5,dl_dst=00:00:00:00:00:08 \
+         * actions=goto_table:2
+         */
+        handleVlanOut(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD,
+                      segmentationId, ethPort, attachedMac, true);
+        /*
+         * Table(1) Rule #3
+         * ----------------
+         * Match:  VLAN ID
+         * Action: Go to table 2
+         * -------------------------------------------
+         * Example: table=1,priority=8192,vlan_id=0x5 actions=output:1,goto_table:2
+         */
+        handleVlanMiss(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD,
+                       segmentationId, ethPort, true);
+    }
+    private void removeRemoteEgressVlanRules(Node node, Long dpid, String segmentationId, String attachedMac, long ethPort) {
+        /*
+         * Table(1) Rule #1
+         * ----------------
+         * Match: Destination MAC is local VM MAC and vlan id
+         * Action: go to table 2
+         * -------------------------------------------
+         * Example: table=1,vlan_id=0x5,dl_dst=00:00:00:00:00:08 \
+         * actions=goto_table:2
+         */
+        handleVlanOut(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD,
+                      segmentationId, ethPort, attachedMac, false);
+    }
+    private void removePerVlanRules(Node node, Long dpid, String segmentationId, long ethPort) {
+        /*
+         * Table(2) Rule #3
+         * ----------------
+         * Match: Any Remaining Flows w/a VLAN ID
+         * Action: Drop w/ a low priority
+         * Example: table=2,priority=8192,vlan_id=0x5 actions=drop
+         */
+         handleLocalVlanTableMiss(dpid, TABLE_2_LOCAL_FORWARD, segmentationId,
+                                  false);
+         /*
+          * Table(0) Rule #2
+          * ----------------
+          * Match: Ingress port = physical interface, Vlan ID
+          * Action: GOTO Local Table 2
+          */
+         handleVlanIn(dpid, TABLE_0_DEFAULT_INGRESS, TABLE_2_LOCAL_FORWARD,
+                      segmentationId, ethPort, false);
+          /*
+           * Table(1) Rule #2
+           * ----------------
+           * Match: Match VLAN ID and L2 ::::FF:FF Flooding
+           * Action: Flood to local and remote VLAN members
+           * -------------------------------------------
+           * Example: table=1,priority=16384,vlan_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
+           * actions=output:10 (eth port),goto_table:2
+           */
+          handleVlanFloodOut(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD,
+                             segmentationId, ethPort, false);
+          /*
+           * Table(1) Rule #3
+           * ----------------
+           * Match:  VLAN ID
+           * Action: Go to table 2
+           * -------------------------------------------
+           * Example: table=1,priority=8192,vlan_id=0x5 actions=output:1,goto_table:2
+           */
+          handleVlanMiss(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD,
+                         segmentationId, ethPort, false);
+    }
+     private Long getDpid (Node node, String bridgeUuid) {
+         try {
+             OVSDBConfigService ovsdbTable = (OVSDBConfigService) ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
+             Bridge bridge = (Bridge) ovsdbTable.getRow(node, Bridge.NAME.getName(), bridgeUuid);
+             Set<String> dpids = bridge.getDatapath_id();
+             if (dpids == null || dpids.size() == 0) return 0L;
+             return Long.valueOf(HexEncode.stringToLong((String) dpids.toArray()[0]));
+         } catch (Exception e) {
+             logger.error("Error finding Bridge's OF DPID", e);
+             return 0L;
+         }
+     }
+     private Long getIntegrationBridgeOFDPID (Node node) {
+         try {
+             String bridgeName = adminConfigManager.getIntegrationBridgeName();
+             String brIntId = this.getInternalBridgeUUID(node, bridgeName);
+             if (brIntId == null) {
+                 logger.error("Unable to spot Bridge Identifier for {} in {}", bridgeName, node);
+                 return 0L;
+             }
+             return getDpid(node, brIntId);
+         } catch (Exception e) {
+             logger.error("Error finding Integration Bridge's OF DPID", e);
+             return 0L;
+         }
+     }
+     private Long getExternalBridgeDpid (Node node) {
+         try {
+             String bridgeName = adminConfigManager.getExternalBridgeName();
+             String brUuid = this.getInternalBridgeUUID(node, bridgeName);
+             if (brUuid == null) {
+                 logger.error("Unable to spot Bridge Identifier for {} in {}", bridgeName, node);
+                 return 0L;
+             }
+             return getDpid(node, brUuid);
+         } catch (Exception e) {
+             logger.error("Error finding External Bridge's OF DPID", e);
+             return 0L;
+         }
+     }
+     private void programLocalRules (String networkType, String segmentationId, Node node, Interface intf) {
+         try {
+             Long dpid = this.getIntegrationBridgeOFDPID(node);
+             if (dpid == 0L) {
+                 logger.debug("Openflow Datapath-ID not set for the integration bridge in {}", node);
+                 return;
+             }
+             Set<BigInteger> of_ports = intf.getOfport();
+             if (of_ports == null || of_ports.size() <= 0) {
+                 logger.error("Could NOT Identify OF value for port {} on {}", intf.getName(), node);
+                 return;
+             }
+             long localPort = ((BigInteger)of_ports.toArray()[0]).longValue();
+             Map<String, String> externalIds = intf.getExternal_ids();
+             if (externalIds == null) {
+                 logger.error("No external_ids seen in {}", intf);
+                 return;
+             }
+             String attachedMac = externalIds.get(ITenantNetworkManager.EXTERNAL_ID_VM_MAC);
+             if (attachedMac == null) {
+                 logger.error("No AttachedMac seen in {}", intf);
+                 return;
+             }
+             /* Program local rules based on network type */
+             if (networkType.equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VLAN)) {
+                 logger.debug("Program local vlan rules for interface {}", intf.getName());
+                 programLocalVlanRules(node, dpid, segmentationId, attachedMac, localPort);
+             } else if (networkType.equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_GRE) ||
+                        networkType.equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VXLAN)) {
+                 logger.debug("Program local bridge rules for interface {}", intf.getName());
+                 programLocalBridgeRules(node, dpid, segmentationId, attachedMac, localPort);
+             }
+         } catch (Exception e) {
+             logger.error("Exception in programming Local Rules for "+intf+" on "+node, e);
+         }
+     }
+     private void removeLocalRules (String networkType, String segmentationId, Node node, Interface intf) {
+         try {
+             Long dpid = this.getIntegrationBridgeOFDPID(node);
+             if (dpid == 0L) {
+                 logger.debug("Openflow Datapath-ID not set for the integration bridge in {}", node);
+                 return;
+             }
+             Set<BigInteger> of_ports = intf.getOfport();
+             if (of_ports == null || of_ports.size() <= 0) {
+                 logger.error("Could NOT Identify OF value for port {} on {}", intf.getName(), node);
+                 return;
+             }
+             long localPort = ((BigInteger)of_ports.toArray()[0]).longValue();
+             Map<String, String> externalIds = intf.getExternal_ids();
+             if (externalIds == null) {
+                 logger.error("No external_ids seen in {}", intf);
+                 return;
+             }
+             String attachedMac = externalIds.get(ITenantNetworkManager.EXTERNAL_ID_VM_MAC);
+             if (attachedMac == null) {
+                 logger.error("No AttachedMac seen in {}", intf);
+                 return;
+             }
+             /* Program local rules based on network type */
+             if (networkType.equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VLAN)) {
+                 logger.debug("Remove local vlan rules for interface {}", intf.getName());
+                 removeLocalVlanRules(node, dpid, segmentationId, attachedMac, localPort);
+             } else if (networkType.equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_GRE) ||
+                        networkType.equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VXLAN)) {
+                 logger.debug("Remove local bridge rules for interface {}", intf.getName());
+                 removeLocalBridgeRules(node, dpid, segmentationId, attachedMac, localPort);
+             }
+         } catch (Exception e) {
+             logger.error("Exception in removing Local Rules for "+intf+" on "+node, e);
+         }
+     }
+     private void programTunnelRules (String tunnelType, String segmentationId, InetAddress dst, Node node,
+             Interface intf, boolean local) {
+         try {
+             Long dpid = this.getIntegrationBridgeOFDPID(node);
+             if (dpid == 0L) {
+                 logger.debug("Openflow Datapath-ID not set for the integration bridge in {}", node);
+                 return;
+             }
+             OVSDBConfigService ovsdbTable = (OVSDBConfigService) ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
+             Set<BigInteger> of_ports = intf.getOfport();
+             if (of_ports == null || of_ports.size() <= 0) {
+                 logger.error("Could NOT Identify OF value for port {} on {}", intf.getName(), node);
+                 return;
+             }
+             long localPort = ((BigInteger)of_ports.toArray()[0]).longValue();
+             Map<String, String> externalIds = intf.getExternal_ids();
+             if (externalIds == null) {
+                 logger.error("No external_ids seen in {}", intf);
+                 return;
+             }
+             String attachedMac = externalIds.get(ITenantNetworkManager.EXTERNAL_ID_VM_MAC);
+             if (attachedMac == null) {
+                 logger.error("No AttachedMac seen in {}", intf);
+                 return;
+             }
 -                for (org.opendaylight.ovsdb.lib.table.internal.Table<?> row : intfs.values()) {
++            Map<String, org.opendaylight.ovsdb.lib.table.Table<?>> intfs = ovsdbTable.getRows(node, Interface.NAME.getName());
+             if (intfs != null) {
 -            Map<String, org.opendaylight.ovsdb.lib.table.internal.Table<?>> intfs = ovsdbTable.getRows(node, Interface.NAME.getName());
++                for (org.opendaylight.ovsdb.lib.table.Table<?> row : intfs.values()) {
+                     Interface tunIntf = (Interface)row;
+                     if (tunIntf.getName().equals(this.getTunnelName(tunnelType, dst))) {
+                         of_ports = tunIntf.getOfport();
+                         if (of_ports == null || of_ports.size() <= 0) {
+                             logger.error("Could NOT Identify Tunnel port {} on {}", tunIntf.getName(), node);
+                             continue;
+                         }
+                         long tunnelOFPort = ((BigInteger)of_ports.toArray()[0]).longValue();
+                         if (tunnelOFPort == -1) {
+                             logger.error("Could NOT Identify Tunnel port {} -> OF ({}) on {}", tunIntf.getName(), tunnelOFPort, node);
+                             return;
+                         }
+                         logger.debug("Identified Tunnel port {} -> OF ({}) on {}", tunIntf.getName(), tunnelOFPort, node);
+                         if (!local) {
+                             programRemoteEgressTunnelBridgeRules(node, dpid, segmentationId, attachedMac, tunnelOFPort, localPort);
+                         }
+                         logger.trace("program local ingress tunnel rules: node" + node.getNodeIDString() + " intf " + intf.getName());
+                         if (local) {
+                             programLocalIngressTunnelBridgeRules(node, dpid, segmentationId, attachedMac, tunnelOFPort, localPort);
+                         }
+                         return;
+                     }
+                 }
+             }
+         } catch (Exception e) {
+             logger.error("", e);
+         }
+     }
+     private void removeTunnelRules (String tunnelType, String segmentationId, InetAddress dst, Node node,
+             Interface intf, boolean local, boolean isLastInstanceOnNode) {
+         try {
+             Long dpid = this.getIntegrationBridgeOFDPID(node);
+             if (dpid == 0L) {
+                 logger.debug("Openflow Datapath-ID not set for the integration bridge in {}", node);
+                 return;
+             }
+             OVSDBConfigService ovsdbTable = (OVSDBConfigService) ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
+             Set<BigInteger> of_ports = intf.getOfport();
+             if (of_ports == null || of_ports.size() <= 0) {
+                 logger.error("Could NOT Identify OF value for port {} on {}", intf.getName(), node);
+                 return;
+             }
+             long localPort = ((BigInteger)of_ports.toArray()[0]).longValue();
+             Map<String, String> externalIds = intf.getExternal_ids();
+             if (externalIds == null) {
+                 logger.error("No external_ids seen in {}", intf);
+                 return;
+             }
+             String attachedMac = externalIds.get(ITenantNetworkManager.EXTERNAL_ID_VM_MAC);
+             if (attachedMac == null) {
+                 logger.error("No AttachedMac seen in {}", intf);
+                 return;
+             }
 -                for (org.opendaylight.ovsdb.lib.table.internal.Table<?> row : intfs.values()) {
++            Map<String, org.opendaylight.ovsdb.lib.table.Table<?>> intfs = ovsdbTable.getRows(node, Interface.NAME.getName());
+             if (intfs != null) {
 -            Map<String, org.opendaylight.ovsdb.lib.table.internal.Table<?>> intfs = ovsdbTable.getRows(node, Interface.NAME.getName());
++                for (org.opendaylight.ovsdb.lib.table.Table<?> row : intfs.values()) {
+                     Interface tunIntf = (Interface)row;
+                     if (tunIntf.getName().equals(this.getTunnelName(tunnelType, dst))) {
+                         of_ports = tunIntf.getOfport();
+                         if (of_ports == null || of_ports.size() <= 0) {
+                             logger.error("Could NOT Identify Tunnel port {} on {}", tunIntf.getName(), node);
+                             continue;
+                         }
+                         long tunnelOFPort = ((BigInteger)of_ports.toArray()[0]).longValue();
+                         if (tunnelOFPort == -1) {
+                             logger.error("Could NOT Identify Tunnel port {} -> OF ({}) on {}", tunIntf.getName(), tunnelOFPort, node);
+                             return;
+                         }
+                         logger.debug("Identified Tunnel port {} -> OF ({}) on {}", tunIntf.getName(), tunnelOFPort, node);
+                         if (!local) {
+                             removeRemoteEgressTunnelBridgeRules(node, dpid, segmentationId, attachedMac, tunnelOFPort, localPort);
+                         }
+                         if (local && isLastInstanceOnNode) {
+                             removePerTunnelRules(node, dpid, segmentationId, tunnelOFPort);
+                         }
+                         return;
+                     }
+                 }
+             }
+         } catch (Exception e) {
+             logger.error("", e);
+         }
+     }
+     private void programVlanRules (NeutronNetwork network, Node node, Interface intf) {
+         logger.debug("Program vlan rules for interface {}", intf.getName());
+         try {
+             Long dpid = this.getIntegrationBridgeOFDPID(node);
+             if (dpid == 0L) {
+                 logger.debug("Openflow Datapath-ID not set for the integration bridge in {}", node);
+                 return;
+             }
+             OVSDBConfigService ovsdbTable = (OVSDBConfigService) ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
+             Set<BigInteger> of_ports = intf.getOfport();
+             int timeout = 6;
+             while ((of_ports == null) && (timeout > 0)) {
+                 of_ports = intf.getOfport();
+                 if (of_ports == null || of_ports.size() <= 0) {
+                     // Wait for the OVSDB update to sync up the Local cache.
+                     Thread.sleep(500);
+                     timeout--;
+                     continue;
+                 }
+             }
+             if (of_ports == null || of_ports.size() <= 0) {
+                 logger.error("Could NOT Identify OF value for port {} on {}", intf.getName(), node);
+                 return;
+             }
+             Map<String, String> externalIds = intf.getExternal_ids();
+             if (externalIds == null) {
+                 logger.error("No external_ids seen in {}", intf);
+                 return;
+             }
+             String attachedMac = externalIds.get(tenantNetworkManager.EXTERNAL_ID_VM_MAC);
+             if (attachedMac == null) {
+                 logger.error("No AttachedMac seen in {}", intf);
+                 return;
+             }
 -                for (org.opendaylight.ovsdb.lib.table.internal.Table<?> row : intfs.values()) {
++            Map<String, org.opendaylight.ovsdb.lib.table.Table<?>> intfs = ovsdbTable.getRows(node, Interface.NAME.getName());
+             if (intfs != null) {
 -            Map<String, org.opendaylight.ovsdb.lib.table.internal.Table<?>> intfs = ovsdbTable.getRows(node, Interface.NAME.getName());
++                for (org.opendaylight.ovsdb.lib.table.Table<?> row : intfs.values()) {
+                     Interface ethIntf = (Interface)row;
+                     if (ethIntf.getName().equalsIgnoreCase(adminConfigManager.getPhysicalInterfaceName(node, network.getProviderPhysicalNetwork()))) {
+                         of_ports = ethIntf.getOfport();
+                         timeout = 6;
+                         while ((of_ports == null) && (timeout > 0)) {
+                             of_ports = ethIntf.getOfport();
+                             if (of_ports == null || of_ports.size() <= 0) {
+                                 // Wait for the OVSDB update to sync up the Local cache.
+                                 Thread.sleep(500);
+                                 timeout--;
+                                 continue;
+                             }
+                         }
+                         if (of_ports == null || of_ports.size() <= 0) {
+                             logger.error("Could NOT Identify eth port {} on {}", ethIntf.getName(), node);
+                             continue;
+                         }
+                         long ethOFPort = ((BigInteger)of_ports.toArray()[0]).longValue();
+                         if (ethOFPort == -1) {
+                             logger.error("Could NOT Identify eth port {} -> OF ({}) on {}", ethIntf.getName(), ethOFPort, node);
+                             throw new Exception("port number < 0");
+                         }
+                         logger.debug("Identified eth port {} -> OF ({}) on {}", ethIntf.getName(), ethOFPort, node);
+                         programRemoteEgressVlanRules(node, dpid, network.getProviderSegmentationID(), attachedMac, ethOFPort);
+                         programLocalIngressVlanRules(node, dpid, network.getProviderSegmentationID(), attachedMac, ethOFPort);
+                         return;
+                     }
+                 }
+             }
+         } catch (Exception e) {
+             logger.error("", e);
+         }
+     }
+     private void removeVlanRules (NeutronNetwork network, Node node,
+                       Interface intf, boolean isLastInstanceOnNode) {
+         logger.debug("Remove vlan rules for interface {}", intf.getName());
+         try {
+             Long dpid = this.getIntegrationBridgeOFDPID(node);
+             if (dpid == 0L) {
+                 logger.debug("Openflow Datapath-ID not set for the integration bridge in {}", node);
+                 return;
+             }
+             OVSDBConfigService ovsdbTable = (OVSDBConfigService) ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
+             Set<BigInteger> of_ports = intf.getOfport();
+             if (of_ports == null || of_ports.size() <= 0) {
+                 logger.error("Could NOT Identify OF value for port {} on {}", intf.getName(), node);
+                 return;
+             }
+             Map<String, String> externalIds = intf.getExternal_ids();
+             if (externalIds == null) {
+                 logger.error("No external_ids seen in {}", intf);
+                 return;
+             }
+             String attachedMac = externalIds.get(tenantNetworkManager.EXTERNAL_ID_VM_MAC);
+             if (attachedMac == null) {
+                 logger.error("No AttachedMac seen in {}", intf);
+                 return;
+             }
 -                for (org.opendaylight.ovsdb.lib.table.internal.Table<?> row : intfs.values()) {
++            Map<String, org.opendaylight.ovsdb.lib.table.Table<?>> intfs = ovsdbTable.getRows(node, Interface.NAME.getName());
+             if (intfs != null) {
 -            Map<String, org.opendaylight.ovsdb.lib.table.internal.Table<?>> intfs = ovsdbTable.getRows(node, Interface.NAME.getName());
++                for (org.opendaylight.ovsdb.lib.table.Table<?> row : intfs.values()) {
+                     Interface ethIntf = (Interface)row;
+                     if (ethIntf.getName().equalsIgnoreCase(adminConfigManager.getPhysicalInterfaceName(node,
+                                                                    network.getProviderPhysicalNetwork()))) {
+                         of_ports = ethIntf.getOfport();
+                         if (of_ports == null || of_ports.size() <= 0) {
+                             logger.error("Could NOT Identify eth port {} on {}", ethIntf.getName(), node);
+                             continue;
+                         }
+                         long ethOFPort = ((BigInteger)of_ports.toArray()[0]).longValue();
+                         if (ethOFPort == -1) {
+                             logger.error("Could NOT Identify eth port {} -> OF ({}) on {}", ethIntf.getName(), ethOFPort, node);
+                             throw new Exception("port number < 0");
+                         }
+                         logger.debug("Identified eth port {} -> OF ({}) on {}", ethIntf.getName(), ethOFPort, node);
+                         removeRemoteEgressVlanRules(node, dpid, network.getProviderSegmentationID(), attachedMac, ethOFPort);
+                         if (isLastInstanceOnNode) {
+                             removePerVlanRules(node, dpid, network.getProviderSegmentationID(), ethOFPort);
+                         }
+                         return;
+                     }
+                 }
+             }
+         } catch (Exception e) {
+             logger.error("", e);
+         }
+     }
+     @Override
+     public Status handleInterfaceUpdate(NeutronNetwork network, Node srcNode, Interface intf) {
+         ISwitchManager switchManager = (ISwitchManager) ServiceHelper.getInstance(ISwitchManager.class, "default", this);
+         if (switchManager == null) {
+             logger.error("Unable to identify SwitchManager");
+         } else {
+             Long dpid = this.getIntegrationBridgeOFDPID(srcNode);
+             if (dpid == 0L) {
+                 logger.debug("Openflow Datapath-ID not set for the integration bridge in {}", srcNode);
+                 return new Status(StatusCode.NOTFOUND);
+             }
+             Set<Node> ofNodes = switchManager.getNodes();
+             boolean ofNodeFound = false;
+             if (ofNodes != null) {
+                 for (Node ofNode : ofNodes) {
+                     if (ofNode.toString().contains(dpid+"")) {
+                         logger.debug("Identified the Openflow node via toString {}", ofNode);
+                         ofNodeFound = true;
+                         break;
+                     }
+                 }
+             } else {
+                 logger.error("Unable to find any Node from SwitchManager");
+             }
+             if (!ofNodeFound) {
+                 logger.error("Unable to find OF Node for {} with update {} on node {}", dpid, intf, srcNode);
+                 return new Status(StatusCode.NOTFOUND);
+             }
+         }
+         IConnectionServiceInternal connectionService = (IConnectionServiceInternal)ServiceHelper.getGlobalInstance(IConnectionServiceInternal.class, this);
+         List<Node> nodes = connectionService.getNodes();
+         nodes.remove(srcNode);
+         this.programLocalRules(network.getProviderNetworkType(), network.getProviderSegmentationID(), srcNode, intf);
+         if (network.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VLAN)) {
+             this.programVlanRules(network, srcNode, intf);
+         } else if (network.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_GRE)
+                    || network.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VXLAN)){
+             for (Node dstNode : nodes) {
+                 InetAddress src = adminConfigManager.getTunnelEndPoint(srcNode);
+                 InetAddress dst = adminConfigManager.getTunnelEndPoint(dstNode);
+                 Status status = addTunnelPort(srcNode, network.getProviderNetworkType(), src, dst);
+                 if (status.isSuccess()) {
+                     this.programTunnelRules(network.getProviderNetworkType(), network.getProviderSegmentationID(), dst, srcNode, intf, true);
+                 }
+                 addTunnelPort(dstNode, network.getProviderNetworkType(), dst, src);
+                 if (status.isSuccess()) {
+                     this.programTunnelRules(network.getProviderNetworkType(), network.getProviderSegmentationID(), src, dstNode, intf, false);
+                 }
+             }
+         }
+         return new Status(StatusCode.SUCCESS);
+     }
+     private Status triggerInterfaceUpdates(Node node) {
+         try {
+             OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
 -                for (org.opendaylight.ovsdb.lib.table.internal.Table<?> row : intfs.values()) {
++            Map<String, org.opendaylight.ovsdb.lib.table.Table<?>> intfs = ovsdbTable.getRows(node, Interface.NAME.getName());
+             if (intfs != null) {
 -            Map<String, org.opendaylight.ovsdb.lib.table.internal.Table<?>> bridgeTable = ovsdbTable.getRows(node, Bridge.NAME.getName());
++                for (org.opendaylight.ovsdb.lib.table.Table<?> row : intfs.values()) {
+                     Interface intf = (Interface)row;
+                     NeutronNetwork network = tenantNetworkManager.getTenantNetworkForInterface(intf);
+                     logger.debug("Trigger Interface update for {}", intf);
+                     if (network != null) {
+                         this.handleInterfaceUpdate(network, node, intf);
+                     }
+                 }
+             }
+         } catch (Exception e) {
+             logger.error("Error Triggering the lost interface updates for "+ node, e);
+             return new Status(StatusCode.INTERNALERROR, e.getLocalizedMessage());
+         }
+         return new Status(StatusCode.SUCCESS);
+     }
+     @Override
+     public Status handleInterfaceUpdate(String tunnelType, String tunnelKey) {
+         // TODO Auto-generated method stub
+         return null;
+     }
+     @Override
+     public Status handleInterfaceDelete(String tunnelType, NeutronNetwork network, Node srcNode, Interface intf,
+             boolean isLastInstanceOnNode) {
+         Status status = new Status(StatusCode.SUCCESS);
+         IConnectionServiceInternal connectionService = (IConnectionServiceInternal)ServiceHelper.getGlobalInstance(IConnectionServiceInternal.class, this);
+         List<Node> nodes = connectionService.getNodes();
+         nodes.remove(srcNode);
+         logger.info("Delete intf " + intf.getName() + " isLastInstanceOnNode " + isLastInstanceOnNode);
+         List<String> phyIfName = adminConfigManager.getAllPhysicalInterfaceNames(srcNode);
+         if (intf.getType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VXLAN)
+             || intf.getType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_GRE)) {
+             /* Delete tunnel port */
+             try {
+                 OvsDBMap<String, String> options = intf.getOptions();
+                 InetAddress src = InetAddress.getByName(options.get("local_ip"));
+                 InetAddress dst = InetAddress.getByName(options.get("remote_ip"));
+                 status = deleteTunnelPort(srcNode, intf.getType(), src, dst);
+             } catch (Exception e) {
+                 logger.error(e.getMessage(), e);
+             }
+         } else if (phyIfName.contains(intf.getName())) {
+             deletePhysicalPort(srcNode, intf.getName());
+         } else {
+             /* delete all other interfaces */
+             this.removeLocalRules(network.getProviderNetworkType(), network.getProviderSegmentationID(),
+                     srcNode, intf);
+             if (network.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VLAN)) {
+                 this.removeVlanRules(network, srcNode,
+                                  intf, isLastInstanceOnNode);
+             } else if (network.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_GRE)
+                    || network.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VXLAN)) {
+                 for (Node dstNode : nodes) {
+                     InetAddress src = adminConfigManager.getTunnelEndPoint(srcNode);
+                     InetAddress dst = adminConfigManager.getTunnelEndPoint(dstNode);
+                     logger.info("Remove tunnel rules for interface " + intf.getName() + " on srcNode" + srcNode.getNodeIDString());
+                     this.removeTunnelRules(tunnelType, network.getProviderSegmentationID(),
+                                            dst, srcNode, intf, true, isLastInstanceOnNode);
+                     logger.info("Remove tunnel rules for interface " + intf.getName() + " on dstNode" + dstNode.getNodeIDString());
+                     this.removeTunnelRules(tunnelType, network.getProviderSegmentationID(),
+                                            src, dstNode, intf, false, isLastInstanceOnNode);
+                 }
+             }
+         }
+         return status;
+     }
+     @Override
+     public void initializeFlowRules(Node node) {
+         this.initializeFlowRules(node, adminConfigManager.getIntegrationBridgeName());
+         this.initializeFlowRules(node, adminConfigManager.getExternalBridgeName());
+         this.triggerInterfaceUpdates(node);
+     }
+     /**
+      * @param node
+      * @param bridgeName
+      */
+     private void initializeFlowRules(Node node, String bridgeName) {
+         String bridgeUuid = this.getInternalBridgeUUID(node, bridgeName);
+         if (bridgeUuid == null) {
+             return;
+         }
+         Long dpid = getDpid(node, bridgeUuid);
+         if (dpid == 0L) {
+             logger.debug("Openflow Datapath-ID not set for the integration bridge in {}", node);
+             return;
+         }
+         /*
+          * Table(0) Rule #1
+          * ----------------
+          * Match: LLDP (0x88CCL)
+          * Action: Packet_In to Controller Reserved Port
+          */
+          writeLLDPRule(dpid);
+          if (bridgeName == adminConfigManager.getExternalBridgeName()) {
+              writeNormalRule(dpid);
+          }
+     }
+     /*
+     * Create an LLDP Flow Rule to encapsulate into
+     * a packet_in that is sent to the controller
+     * for topology handling.
+     * Match: Ethertype 0x88CCL
+     * Action: Punt to Controller in a Packet_In msg
+     */
+     private void writeLLDPRule(Long dpidLong) {
+         String nodeName = "openflow:" + dpidLong;
+         EtherType etherType = new EtherType(0x88CCL);
+         MatchBuilder matchBuilder = new MatchBuilder();
+         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
+         FlowBuilder flowBuilder = new FlowBuilder();
+         // Create Match(es) and Set them in the FlowBuilder Object
+         flowBuilder.setMatch(createEtherTypeMatch(matchBuilder, etherType).build());
+         // Create the OF Actions and Instructions
+         InstructionBuilder ib = new InstructionBuilder();
+         InstructionsBuilder isb = new InstructionsBuilder();
+         // Instructions List Stores Individual Instructions
+         List<Instruction> instructions = new ArrayList<Instruction>();
+         // Call the InstructionBuilder Methods Containing Actions
+         createSendToControllerInstructions(ib);
+         ib.setOrder(0);
+         ib.setKey(new InstructionKey(0));
+         instructions.add(ib.build());
+         // Add InstructionBuilder to the Instruction(s)Builder List
+         isb.setInstruction(instructions);
+         // Add InstructionsBuilder to FlowBuilder
+         flowBuilder.setInstructions(isb.build());
+         String flowId = "LLDP";
+         flowBuilder.setId(new FlowId(flowId));
+         FlowKey key = new FlowKey(new FlowId(flowId));
+         flowBuilder.setBarrier(true);
+         flowBuilder.setTableId((short) 0);
+         flowBuilder.setKey(key);
+         flowBuilder.setFlowName(flowId);
+         flowBuilder.setHardTimeout(0);
+         flowBuilder.setIdleTimeout(0);
+         writeFlow(flowBuilder, nodeBuilder);
+     }
+     /*
+     * Create a NORMAL Table Miss Flow Rule
+     * Match: any
+     * Action: forward to NORMAL pipeline
+     */
+     private void writeNormalRule(Long dpidLong) {
+         String nodeName = "openflow:" + dpidLong;
+         MatchBuilder matchBuilder = new MatchBuilder();
+         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
+         FlowBuilder flowBuilder = new FlowBuilder();
+         // Create the OF Actions and Instructions
+         InstructionBuilder ib = new InstructionBuilder();
+         InstructionsBuilder isb = new InstructionsBuilder();
+         // Instructions List Stores Individual Instructions
+         List<Instruction> instructions = new ArrayList<Instruction>();
+         // Call the InstructionBuilder Methods Containing Actions
+         createNormalInstructions(ib);
+         ib.setOrder(0);
+         ib.setKey(new InstructionKey(0));
+         instructions.add(ib.build());
+         // Add InstructionBuilder to the Instruction(s)Builder List
+         isb.setInstruction(instructions);
+         // Add InstructionsBuilder to FlowBuilder
+         flowBuilder.setInstructions(isb.build());
+         String flowId = "NORMAL";
+         flowBuilder.setId(new FlowId(flowId));
+         FlowKey key = new FlowKey(new FlowId(flowId));
+         flowBuilder.setMatch(matchBuilder.build());
+         flowBuilder.setPriority(0);
+         flowBuilder.setBarrier(true);
+         flowBuilder.setTableId((short) 0);
+         flowBuilder.setKey(key);
+         flowBuilder.setFlowName(flowId);
+         flowBuilder.setHardTimeout(0);
+         flowBuilder.setIdleTimeout(0);
+         writeFlow(flowBuilder, nodeBuilder);
+     }
+     /*
+      * (Table:0) Ingress Tunnel Traffic
+      * Match: OpenFlow InPort and Tunnel ID
+      * Action: GOTO Local Table (10)
+      * table=0,tun_id=0x5,in_port=10, actions=goto_table:2
+      */
+     private void handleTunnelIn(Long dpidLong, Short writeTable,
+                                 Short goToTableId, String segmentationId,
+                                 Long ofPort, boolean write) {
+         String nodeName = "openflow:" + dpidLong;
+         BigInteger tunnelId = new BigInteger(segmentationId);
+         MatchBuilder matchBuilder = new MatchBuilder();
+         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
+         FlowBuilder flowBuilder = new FlowBuilder();
+         // Create Match(es) and Set them in the FlowBuilder Object
+         flowBuilder.setMatch(createTunnelIDMatch(matchBuilder, tunnelId).build());
+         flowBuilder.setMatch(createInPortMatch(matchBuilder, dpidLong, ofPort).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 = new ArrayList<Instruction>();
+             // Call the InstructionBuilder Methods Containing Actions
+             createGotoTableInstructions(ib, goToTableId);
+             ib.setOrder(0);
+             ib.setKey(new InstructionKey(0));
+             instructions.add(ib.build());
+             // Add InstructionBuilder to the Instruction(s)Builder List
+             isb.setInstruction(instructions);
+             // Add InstructionsBuilder to FlowBuilder
+             flowBuilder.setInstructions(isb.build());
+         }
+         String flowId = "TunnelIn_"+segmentationId+"_"+ofPort;
+         // Add Flow Attributes
+         flowBuilder.setId(new FlowId(flowId));
+         FlowKey key = new FlowKey(new FlowId(flowId));
+         flowBuilder.setStrict(true);
+         flowBuilder.setBarrier(false);
+         flowBuilder.setTableId(writeTable);
+         flowBuilder.setKey(key);
+         flowBuilder.setFlowName(flowId);
+         flowBuilder.setHardTimeout(0);
+         flowBuilder.setIdleTimeout(0);
+         if (write) {
+             writeFlow(flowBuilder, nodeBuilder);
+         } else {
+             removeFlow(flowBuilder, nodeBuilder);
+         }
+     }
+     /*
+      * (Table:0) Ingress VLAN Traffic
+      * Match: OpenFlow InPort and vlan ID
+      * Action: GOTO Local Table (20)
+      * table=0,vlan_id=0x5,in_port=10, actions=goto_table:2
+      */
+     private void handleVlanIn(Long dpidLong, Short writeTable, Short goToTableId,
+                       String segmentationId,  Long ethPort, boolean write) {
+         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(createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId))).build());
+         flowBuilder.setMatch(createInPortMatch(matchBuilder, dpidLong, ethPort).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 = new ArrayList<Instruction>();
+             // Call the InstructionBuilder Methods Containing Actions
+             createGotoTableInstructions(ib, goToTableId);
+             ib.setOrder(0);
+             ib.setKey(new InstructionKey(0));
+             instructions.add(ib.build());
+             // Add InstructionBuilder to the Instruction(s)Builder List
+             isb.setInstruction(instructions);
+             // Add InstructionsBuilder to FlowBuilder
+             flowBuilder.setInstructions(isb.build());
+         }
+         String flowId = "VlanIn_"+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(writeTable);
+         flowBuilder.setKey(key);
+         flowBuilder.setFlowName(flowId);
+         flowBuilder.setHardTimeout(0);
+         flowBuilder.setIdleTimeout(0);
+         if (write) {
+             writeFlow(flowBuilder, nodeBuilder);
+         } else {
+             removeFlow(flowBuilder, nodeBuilder);
+         }
+     }
+    /*
+     * (Table:0) Egress VM Traffic Towards TEP
+     * Match: Destination Ethernet Addr and OpenFlow InPort
+     * Instruction: Set TunnelID and GOTO Table Tunnel Table (n)
+     * table=0,in_port=2,dl_src=00:00:00:00:00:01 \
+     * actions=set_field:5->tun_id,goto_table=1"
+     */
+     private void handleLocalInPort(Long dpidLong, Short writeTable, Short goToTableId,
+                            String segmentationId, Long inPort, String attachedMac,
+                            boolean write) {
+         String nodeName = "openflow:" + dpidLong;
+         MatchBuilder matchBuilder = new MatchBuilder();
+         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
+         FlowBuilder flowBuilder = new FlowBuilder();
+         // Create the OF Match using MatchBuilder
+         flowBuilder.setMatch(createEthSrcMatch(matchBuilder, new MacAddress(attachedMac)).build());
+         // TODO Broken In_Port Match
+         flowBuilder.setMatch(createInPortMatch(matchBuilder, dpidLong, inPort).build());
+         String flowId = "LocalMac_"+segmentationId+"_"+inPort+"_"+attachedMac;
+         // Add Flow Attributes
+         flowBuilder.setId(new FlowId(flowId));
+         FlowKey key = new FlowKey(new FlowId(flowId));
+         flowBuilder.setStrict(true);
+         flowBuilder.setBarrier(false);
+         flowBuilder.setTableId(writeTable);
+         flowBuilder.setKey(key);
+         flowBuilder.setFlowName(flowId);
+         flowBuilder.setHardTimeout(0);
+         flowBuilder.setIdleTimeout(0);
+         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 = new ArrayList<Instruction>();
+             // GOTO Instuctions Need to be added first to the List
+             createGotoTableInstructions(ib, goToTableId);
+             ib.setOrder(0);
+             ib.setKey(new InstructionKey(0));
+             instructions.add(ib.build());
+             // TODO Broken SetTunID
+             createSetTunnelIdInstructions(ib, new BigInteger(segmentationId));
+             ib.setOrder(1);
+             ib.setKey(new InstructionKey(1));
+             instructions.add(ib.build());
+             // Add InstructionBuilder to the Instruction(s)Builder List
+             isb.setInstruction(instructions);
+             // Add InstructionsBuilder to FlowBuilder
+             flowBuilder.setInstructions(isb.build());
+             writeFlow(flowBuilder, nodeBuilder);
+         } else {
+             removeFlow(flowBuilder, nodeBuilder);
+         }
+     }
+     /*
+      * (Table:0) Egress VM Traffic Towards TEP
+      * Match: Source Ethernet Addr and OpenFlow InPort
+      * Instruction: Set VLANID and GOTO Table Egress (n)
+      * table=0,in_port=2,dl_src=00:00:00:00:00:01 \
+      * actions=push_vlan, set_field:5->vlan_id,goto_table=1"
+      */
+      private void handleLocalInPortSetVlan(Long dpidLong, Short writeTable,
+                                   Short goToTableId, String segmentationId,
+                                   Long inPort, String attachedMac,
+                                   boolean write) {
+          String nodeName = "openflow:" + dpidLong;
+          MatchBuilder matchBuilder = new MatchBuilder();
+          NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
+          FlowBuilder flowBuilder = new FlowBuilder();
+          // Create the OF Match using MatchBuilder
+          flowBuilder.setMatch(createEthSrcMatch(matchBuilder, new MacAddress(attachedMac)).build());
+          // TODO Broken In_Port Match
+          flowBuilder.setMatch(createInPortMatch(matchBuilder, dpidLong, inPort).build());
+          String flowId = "LocalMac_"+segmentationId+"_"+inPort+"_"+attachedMac;
+          // Add Flow Attributes
+          flowBuilder.setId(new FlowId(flowId));
+          FlowKey key = new FlowKey(new FlowId(flowId));
+          flowBuilder.setStrict(true);
+          flowBuilder.setBarrier(false);
+          flowBuilder.setTableId(writeTable);
+          flowBuilder.setKey(key);
+          flowBuilder.setFlowName(flowId);
+          flowBuilder.setHardTimeout(0);
+          flowBuilder.setIdleTimeout(0);
+          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 = new ArrayList<Instruction>();
+              // GOTO Instructions Need to be added first to the List
+              createGotoTableInstructions(ib, goToTableId);
+              ib.setOrder(0);
+              ib.setKey(new InstructionKey(0));
+              instructions.add(ib.build());
+              // Set VLAN ID Instruction
+              createSetVlanInstructions(ib, new VlanId(Integer.valueOf(segmentationId)));
+              ib.setOrder(1);
+              ib.setKey(new InstructionKey(1));
+              instructions.add(ib.build());
+              // Add InstructionBuilder to the Instruction(s)Builder List
+              isb.setInstruction(instructions);
+              // Add InstructionsBuilder to FlowBuilder
+              flowBuilder.setInstructions(isb.build());
+              writeFlow(flowBuilder, nodeBuilder);
+          } else {
+              removeFlow(flowBuilder, nodeBuilder);
+          }
+      }
+     /*
+      * (Table:0) Drop frames source from a VM that do not
+      * match the associated MAC address of the local VM.
+      * Match: Low priority anything not matching the VM SMAC
+      * Instruction: Drop
+      * table=0,priority=16384,in_port=1 actions=drop"
+      */
+     private void handleDropSrcIface(Long dpidLong, Long inPort, boolean write) {
+         String nodeName = "openflow:" + dpidLong;
+         MatchBuilder matchBuilder = new MatchBuilder();
+         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
+         FlowBuilder flowBuilder = new FlowBuilder();
+         // Create the OF Match using MatchBuilder
+         flowBuilder.setMatch(createInPortMatch(matchBuilder, dpidLong, inPort).build());
+         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 = new ArrayList<Instruction>();
+             // Call the InstructionBuilder Methods Containing Actions
+             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);
+             // Add InstructionsBuilder to FlowBuilder
+             flowBuilder.setInstructions(isb.build());
+         }
+         String flowId = "DropFilter_"+inPort;
+         // Add Flow Attributes
+         flowBuilder.setId(new FlowId(flowId));
+         FlowKey key = new FlowKey(new FlowId(flowId));
+         flowBuilder.setStrict(true);
+         flowBuilder.setBarrier(false);
+         flowBuilder.setTableId((short) 0);
+         flowBuilder.setKey(key);
+         flowBuilder.setFlowName(flowId);
+         flowBuilder.setPriority(8192);
+         flowBuilder.setHardTimeout(0);
+         flowBuilder.setIdleTimeout(0);
+         if (write) {
+             writeFlow(flowBuilder, nodeBuilder);
+         } else {
+             removeFlow(flowBuilder, nodeBuilder);
+         }
+     }
+    /*
+     * (Table:1) Egress Tunnel Traffic
+     * Match: Destination Ethernet Addr and Local InPort
+     * Instruction: Set TunnelID and GOTO Table Tunnel Table (n)
+     * table=1,tun_id=0x5,dl_dst=00:00:00:00:00:08 \
+     * actions=output:10,goto_table:2"
+     */
+     private void handleTunnelOut(Long dpidLong, Short writeTable,
+                          Short goToTableId, String segmentationId,
+                          Long OFPortOut, String attachedMac,
+                          boolean write) {
+         String nodeName = "openflow:" + dpidLong;
+         MatchBuilder matchBuilder = new MatchBuilder();
+         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
+         FlowBuilder flowBuilder = new FlowBuilder();
+         // Create the OF Match using MatchBuilder
+         flowBuilder.setMatch(createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
+         flowBuilder.setMatch(createDestEthMatch(matchBuilder, new MacAddress(attachedMac), null).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(writeTable);
+         flowBuilder.setKey(key);
+         flowBuilder.setFlowName(flowId);
+         flowBuilder.setHardTimeout(0);
+         flowBuilder.setIdleTimeout(0);
+         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 = new ArrayList<Instruction>();
+             // GOTO Instuctions
+             createGotoTableInstructions(ib, goToTableId);
+             ib.setOrder(0);
+             ib.setKey(new InstructionKey(0));
+             instructions.add(ib.build());
+             // Set the Output Port/Iface
+             createOutputPortInstructions(ib, dpidLong, OFPortOut);
+             ib.setOrder(1);
+             ib.setKey(new InstructionKey(1));
+             instructions.add(ib.build());
+             // Add InstructionBuilder to the Instruction(s)Builder List
+             isb.setInstruction(instructions);
+             // Add InstructionsBuilder to FlowBuilder
+             flowBuilder.setInstructions(isb.build());
+             writeFlow(flowBuilder, nodeBuilder);
+         } else {
+             removeFlow(flowBuilder, nodeBuilder);
+         }
+     }
+     /*
+      * (Table:1) Egress VLAN Traffic
+      * Match: Destination Ethernet Addr and VLAN id
+      * Instruction: GOTO Table Table 2
+      * table=1,vlan_id=0x5,dl_dst=00:00:00:00:00:08 \
+      * actions= goto_table:2"
+      */
+      private void handleVlanOut(Long dpidLong, Short writeTable,
+                         Short goToTableId, String segmentationId,
+                         Long ethPort, String attachedMac, boolean write) {
+          String nodeName = "openflow:" + dpidLong;
+          MatchBuilder matchBuilder = new MatchBuilder();
+          NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
+          FlowBuilder flowBuilder = new FlowBuilder();
+          // Create the OF Match using MatchBuilder
+          flowBuilder.setMatch(createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId))).build());
+          flowBuilder.setMatch(createDestEthMatch(matchBuilder, new MacAddress(attachedMac), null).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(writeTable);
+          flowBuilder.setKey(key);
+          flowBuilder.setFlowName(flowId);
+          flowBuilder.setHardTimeout(0);
+          flowBuilder.setIdleTimeout(0);
+          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 = new ArrayList<Instruction>();
+              // GOTO Instuctions
+              createGotoTableInstructions(ib, goToTableId);
+              ib.setOrder(0);
+              ib.setKey(new InstructionKey(0));
+              instructions.add(ib.build());
+              // Add InstructionBuilder to the Instruction(s)Builder List
+              isb.setInstruction(instructions);
+              // Add InstructionsBuilder to FlowBuilder
+              flowBuilder.setInstructions(isb.build());
+              writeFlow(flowBuilder, nodeBuilder);
+          } else {
+              removeFlow(flowBuilder, nodeBuilder);
+          }
+      }
+        /*
+     * (Table:1) Egress Tunnel Traffic
+     * Match: Destination Ethernet Addr and Local InPort
+     * Instruction: Set TunnelID and GOTO Table Tunnel Table (n)
+     * table=1,priority=16384,tun_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
+     * actions=output:10,output:11,goto_table:2
+     */
+     private void handleTunnelFloodOut(Long dpidLong, Short writeTable,
+                              Short localTable, String segmentationId,
+                              Long OFPortOut, boolean write) {
+         String nodeName = "openflow:" + dpidLong;
+         MatchBuilder matchBuilder = new MatchBuilder();
+         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
+         FlowBuilder flowBuilder = new FlowBuilder();
+         // Create the OF Match using MatchBuilder
+         // Match TunnelID
+         flowBuilder.setMatch(createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
+         // Match DMAC
+         flowBuilder.setMatch(createDestEthMatch(matchBuilder, new MacAddress("01:00:00:00:00:00"), new MacAddress("01:00:00:00:00:00")).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(writeTable);
+         flowBuilder.setKey(key);
+         flowBuilder.setPriority(16384);
+         flowBuilder.setFlowName(flowId);
+         flowBuilder.setHardTimeout(0);
+         flowBuilder.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 = new ArrayList<Instruction>();
+         List<Instruction> existingInstructions = null;
+         if (flow != null) {
+             Instructions ins = flow.getInstructions();
+             if (ins != null) {
+                 existingInstructions = ins.getInstruction();
+             }
+         }
+         if (write) {
+             // GOTO Instruction
+             createGotoTableInstructions(ib, localTable);
+             ib.setOrder(0);
+             ib.setKey(new InstructionKey(0));
+             instructions.add(ib.build());
+             // Set the Output Port/Iface
+             //createOutputGroupInstructions(nodeBuilder, ib, dpidLong, OFPortOut, existingInstructions);
+             createOutputPortInstructions(ib, dpidLong, OFPortOut, existingInstructions);
+             ib.setOrder(1);
+             ib.setKey(new InstructionKey(1));
+             instructions.add(ib.build());
+             // Add InstructionBuilder to the Instruction(s)Builder List
+             isb.setInstruction(instructions);
+             // Add InstructionsBuilder to FlowBuilder
+             flowBuilder.setInstructions(isb.build());
+             writeFlow(flowBuilder, nodeBuilder);
+         } else {
+             /* remove port from action list */
+             boolean flowRemove = removeOutputPortFromInstructions(ib, dpidLong,
+                                    OFPortOut, existingInstructions);
+             if (flowRemove) {
+                 /* if all port are removed, remove the flow too. */
+                 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);
+                 // Add InstructionsBuilder to FlowBuilder
+                 flowBuilder.setInstructions(isb.build());
+             }
+         }
+     }
+     /*
+      * (Table:1) Egress VLAN Traffic
+      * Match: Destination Ethernet Addr and VLAN id
+      * Instruction: GOTO table 2 and Output port eth interface
+      * Example: table=1,priority=16384,vlan_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
+      * actions=output:eth1,goto_table:2
+      */
+      private void handleVlanFloodOut(Long dpidLong, Short writeTable,
+                            Short localTable, String segmentationId,
+                            Long ethPort, boolean write) {
+          String nodeName = "openflow:" + dpidLong;
+          MatchBuilder matchBuilder = new MatchBuilder();
+          NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
+          FlowBuilder flowBuilder = new FlowBuilder();
+          // Create the OF Match using MatchBuilder
+          // Match Vlan ID
+          flowBuilder.setMatch(createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId))).build());
+          // Match DMAC
+          flowBuilder.setMatch(createDestEthMatch(matchBuilder, new MacAddress("01:00:00:00:00:00"), new MacAddress("01:00:00:00:00:00")).build());
+          String flowId = "VlanFloodOut_"+segmentationId;
+          // Add Flow Attributes
+          flowBuilder.setId(new FlowId(flowId));
+          FlowKey key = new FlowKey(new FlowId(flowId));
+          flowBuilder.setBarrier(true);
+          flowBuilder.setTableId(writeTable);
+          flowBuilder.setKey(key);
+          flowBuilder.setPriority(16384);
+          flowBuilder.setFlowName(flowId);
+          flowBuilder.setHardTimeout(0);
+          flowBuilder.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 = new ArrayList<Instruction>();
+          if (write) {
+              // GOTO Instuction
+              createGotoTableInstructions(ib, localTable);
+              ib.setOrder(0);
+              ib.setKey(new InstructionKey(0));
+              instructions.add(ib.build());
+              // Set the Output Port/Iface
+              createOutputPortInstructions(ib, dpidLong, ethPort);
+              ib.setOrder(1);
+              ib.setKey(new InstructionKey(1));
+              instructions.add(ib.build());
+              // Add InstructionBuilder to the Instruction(s)Builder List
+              isb.setInstruction(instructions);
+              // Add InstructionsBuilder to FlowBuilder
+              flowBuilder.setInstructions(isb.build());
+              writeFlow(flowBuilder, nodeBuilder);
+          } else {
+              removeFlow(flowBuilder, nodeBuilder);
+          }
+      }
+    /*
+     * (Table:1) Table Drain w/ Catch All
+     * Match: Tunnel ID
+     * Action: GOTO Local Table (10)
+     * table=2,priority=8192,tun_id=0x5 actions=drop
+     */
+     private void handleTunnelMiss(Long dpidLong, Short writeTable,
+                           Short goToTableId, String segmentationId,
+                           boolean write) {
+         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(createTunnelIDMatch(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 = new ArrayList<Instruction>();
+             // Call the InstructionBuilder Methods Containing Actions
+             createGotoTableInstructions(ib, goToTableId);
+             ib.setOrder(0);
+             ib.setKey(new InstructionKey(0));
+             instructions.add(ib.build());
+             // Add InstructionBuilder to the Instruction(s)Builder List
+             isb.setInstruction(instructions);
+             // Add InstructionsBuilder to FlowBuilder
+             flowBuilder.setInstructions(isb.build());
+         }
+         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(writeTable);
+         flowBuilder.setKey(key);
+         flowBuilder.setPriority(8192);
+         flowBuilder.setFlowName(flowId);
+         flowBuilder.setHardTimeout(0);
+         flowBuilder.setIdleTimeout(0);
+         if (write) {
+             writeFlow(flowBuilder, nodeBuilder);
+         } else {
+             removeFlow(flowBuilder, nodeBuilder);
+         }
+     }
+     /*
+      * (Table:1) Table Drain w/ Catch All
+      * Match: Vlan ID
+      * Action: Output port eth interface
+      * table=1,priority=8192,vlan_id=0x5 actions= output port:eth1
+      */
+      private void handleVlanMiss(Long dpidLong, Short writeTable,
+                          Short goToTableId, String segmentationId,
+                          Long ethPort, boolean write) {
+          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(createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(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 = new ArrayList<Instruction>();
+              // Call the InstructionBuilder Methods Containing Actions
+              //createGotoTableInstructions(ib, goToTableId);
+              //ib.setOrder(0);
+              //ib.setKey(new InstructionKey(0));
+              //instructions.add(ib.build());
+              // Set the Output Port/Iface
+              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);
+              // Add InstructionsBuilder to FlowBuilder
+              flowBuilder.setInstructions(isb.build());
+          }
+          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(writeTable);
+          flowBuilder.setKey(key);
+          flowBuilder.setPriority(8192);
+          flowBuilder.setFlowName(flowId);
+          flowBuilder.setHardTimeout(0);
+          flowBuilder.setIdleTimeout(0);
+          if (write) {
+              writeFlow(flowBuilder, nodeBuilder);
+          } else {
+              removeFlow(flowBuilder, nodeBuilder);
+          }
+      }
+     /*
+      * (Table:1) Local Broadcast Flood
+      * Match: Tunnel ID and dMAC
+      * Action: Output Port
+      * table=2,tun_id=0x5,dl_dst=00:00:00:00:00:01 actions=output:2
+      */
+     private void handleLocalUcastOut(Long dpidLong, Short writeTable,
+                              String segmentationId, Long localPort,
+                              String attachedMac, boolean write) {
+         String nodeName = "openflow:" + dpidLong;
+         MatchBuilder matchBuilder = new MatchBuilder();
+         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
+         FlowBuilder flowBuilder = new FlowBuilder();
+         // Create the OF Match using MatchBuilder
+         flowBuilder.setMatch(createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
+         flowBuilder.setMatch(createDestEthMatch(matchBuilder, new MacAddress(attachedMac), null).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(writeTable);
+         flowBuilder.setKey(key);
+         flowBuilder.setFlowName(flowId);
+         flowBuilder.setHardTimeout(0);
+         flowBuilder.setIdleTimeout(0);
+         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 = new ArrayList<Instruction>();
+             // Set the Output Port/Iface
+             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);
+             // Add InstructionsBuilder to FlowBuilder
+             flowBuilder.setInstructions(isb.build());
+             writeFlow(flowBuilder, nodeBuilder);
+         } else {
+             removeFlow(flowBuilder, nodeBuilder);
+         }
+     }
+     /*
+      * (Table:2) Local VLAN unicast
+      * Match: VLAN ID and dMAC
+      * Action: Output Port
+      * table=2,vlan_id=0x5,dl_dst=00:00:00:00:00:01 actions=output:2
+      */
+     private void handleLocalVlanUcastOut(Long dpidLong, Short writeTable,
+                                  String segmentationId, Long localPort,
+                                  String attachedMac, boolean write) {
+         String nodeName = "openflow:" + dpidLong;
+         MatchBuilder matchBuilder = new MatchBuilder();
+         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
+         FlowBuilder flowBuilder = new FlowBuilder();
+         // Create the OF Match using MatchBuilder
+         flowBuilder.setMatch(createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId))).build());
+         flowBuilder.setMatch(createDestEthMatch(matchBuilder, new MacAddress(attachedMac), null).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(writeTable);
+         flowBuilder.setKey(key);
+         flowBuilder.setFlowName(flowId);
+         flowBuilder.setHardTimeout(0);
+         flowBuilder.setIdleTimeout(0);
+         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 = new ArrayList<Instruction>();
+             List<Instruction> instructions_tmp = new ArrayList<Instruction>();
+             /* Strip vlan and store to tmp instruction space*/
+             createPopVlanInstructions(ib);
+             ib.setOrder(0);
+             ib.setKey(new InstructionKey(0));
+             instructions_tmp.add(ib.build());
+             // Set the Output Port/Iface
+             ib = new InstructionBuilder();
+             addOutputPortInstructions(ib, dpidLong, localPort, instructions_tmp);
+             ib.setOrder(0);
+             ib.setKey(new InstructionKey(0));
+             instructions.add(ib.build());
+             // Add InstructionBuilder to the Instruction(s)Builder List
+             isb.setInstruction(instructions);
+             // Add InstructionsBuilder to FlowBuilder
+             flowBuilder.setInstructions(isb.build());
+             writeFlow(flowBuilder, nodeBuilder);
+         } else {
+             removeFlow(flowBuilder, nodeBuilder);
+         }
+     }
+     /*
+      * (Table:2) Local Broadcast Flood
+      * Match: Tunnel ID and dMAC (::::FF:FF)
+      * table=2,priority=16384,tun_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
+      * actions=output:2,3,4,5
+      */
+     private void handleLocalBcastOut(Long dpidLong, Short writeTable,
+                              String segmentationId, Long localPort,
+                              boolean write) {
+         String nodeName = "openflow:" + dpidLong;
+         MatchBuilder matchBuilder = new MatchBuilder();
+         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
+         FlowBuilder flowBuilder = new FlowBuilder();
+         // Create the OF Match using MatchBuilder
+         flowBuilder.setMatch(createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
+         flowBuilder.setMatch(createDestEthMatch(matchBuilder, new MacAddress("01:00:00:00:00:00"), new MacAddress("01:00:00:00:00:00")).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(writeTable);
+         flowBuilder.setKey(key);
+         flowBuilder.setPriority(16384);
+         flowBuilder.setFlowName(flowId);
+         flowBuilder.setHardTimeout(0);
+         flowBuilder.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 = new ArrayList<Instruction>();
+         List<Instruction> existingInstructions = null;
+         if (flow != null) {
+             Instructions ins = flow.getInstructions();
+             if (ins != null) {
+                 existingInstructions = ins.getInstruction();
+             }
+         }
+         if (write) {
+             // Create output port list
+             createOutputPortInstructions(ib, dpidLong, localPort, existingInstructions);
+             ib.setOrder(0);
+             ib.setKey(new InstructionKey(0));
+             instructions.add(ib.build());
+             // Add InstructionBuilder to the Instruction(s)Builder List
+             isb.setInstruction(instructions);
+             // Add InstructionsBuilder to FlowBuilder
+             flowBuilder.setInstructions(isb.build());
+             writeFlow(flowBuilder, nodeBuilder);
+         } else {
+             boolean flowRemove = removeOutputPortFromInstructions(ib, dpidLong, localPort,
+                                                                   existingInstructions);
+             if (flowRemove) {
+                 /* if all ports are removed, remove flow */
+                 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);
+                 // Add InstructionsBuilder to FlowBuilder
+                 flowBuilder.setInstructions(isb.build());
+                 writeFlow(flowBuilder, nodeBuilder);
+             }
+         }
+     }
+     /*
+      * (Table:2) Local VLAN Broadcast Flood
+      * Match: vlan ID and dMAC (::::FF:FF)
+      * table=2,priority=16384,vlan_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
+      * actions=strip_vlan, output:2,3,4,5
+      */
+     private void handleLocalVlanBcastOut(Long dpidLong, Short writeTable,
+                                  String segmentationId, Long localPort,
+                                  boolean write) {
+         String nodeName = "openflow:" + dpidLong;
+         MatchBuilder matchBuilder = new MatchBuilder();
+         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
+         FlowBuilder flowBuilder = new FlowBuilder();
+         // Create the OF Match using MatchBuilder
+         flowBuilder.setMatch(createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId))).build());
+         flowBuilder.setMatch(createDestEthMatch(matchBuilder, new MacAddress("01:00:00:00:00:00"), new MacAddress("01:00:00:00:00:00")).build());
+         String flowId = "VlanBcastOut_"+segmentationId;
+         // Add Flow Attributes
+         flowBuilder.setId(new FlowId(flowId));
+         FlowKey key = new FlowKey(new FlowId(flowId));
+         flowBuilder.setStrict(true);
+         flowBuilder.setBarrier(false);
+         flowBuilder.setTableId(writeTable);
+         flowBuilder.setKey(key);
+         flowBuilder.setPriority(16384);
+         flowBuilder.setFlowName(flowId);
+         flowBuilder.setHardTimeout(0);
+         flowBuilder.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 = new ArrayList<Instruction>();
+         List<Instruction> existingInstructions = null;
+         boolean add_pop_vlan = true;
+         if (flow != null) {
+             Instructions ins = flow.getInstructions();
+             if (ins != null) {
+                 existingInstructions = ins.getInstruction();
+             }
+         }
+         if (write) {
+             if (existingInstructions != null) {
+                 /* Check if pop vlan is already the first action in action list */
+                 List<Action> existingActions = null;
+                 for (Instruction in : existingInstructions) {
+                     if (in.getInstruction() instanceof ApplyActionsCase) {
+                         existingActions = (((ApplyActionsCase)
+                                 in.getInstruction()).getApplyActions().getAction());
+                         if (existingActions.get(0).getAction() instanceof PopVlanActionCase) {
+                             add_pop_vlan = false;
+                             break;
+                         }
+                     }
+                 }
+             } else {
+                 existingInstructions = new ArrayList<Instruction>();
+             }
+             if (add_pop_vlan) {
+                 /* pop vlan */
+                 createPopVlanInstructions(ib);
+                 ib.setOrder(0);
+                 ib.setKey(new InstructionKey(0));
+                 existingInstructions.add(ib.build());
+                 ib = new InstructionBuilder();
+             }
+             // Create port list
+             //createOutputGroupInstructions(nodeBuilder, ib, dpidLong, localPort, existingInstructions);
+             createOutputPortInstructions(ib, dpidLong, localPort, existingInstructions);
+             ib.setOrder(0);
+             ib.setKey(new InstructionKey(0));
+             instructions.add(ib.build());
+             // Add InstructionBuilder to the Instruction(s)Builder List
+             isb.setInstruction(instructions);
+             // Add InstructionsBuilder to FlowBuilder
+             flowBuilder.setInstructions(isb.build());
+             writeFlow(flowBuilder, nodeBuilder);
+         } else {
+             //boolean flowRemove = removeOutputPortFromGroup(nodeBuilder, ib, dpidLong,
+             //                     localPort, existingInstructions);
+             boolean flowRemove = removeOutputPortFromInstructions(ib, dpidLong,
+                                                     localPort, existingInstructions);
+             if (flowRemove) {
+                 /* if all ports are removed, remove flow */
+                 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);
+                 // Add InstructionsBuilder to FlowBuilder
+                 flowBuilder.setInstructions(isb.build());
+                 writeFlow(flowBuilder, nodeBuilder);
+             }
+         }
+     }
+     /*
+      * (Table:1) Local Table Miss
+      * Match: Any Remaining Flows w/a TunID
+      * Action: Drop w/ a low priority
+      * table=2,priority=8192,tun_id=0x5 actions=drop
+      */
+     private void handleLocalTableMiss(Long dpidLong, Short writeTable,
+                              String segmentationId, boolean write) {
+         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(createTunnelIDMatch(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 = new ArrayList<Instruction>();
+             // Call the InstructionBuilder Methods Containing Actions
+             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);
+             // Add InstructionsBuilder to FlowBuilder
+             flowBuilder.setInstructions(isb.build());
+         }
+         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(writeTable);
+         flowBuilder.setKey(key);
+         flowBuilder.setPriority(8192);
+         flowBuilder.setFlowName(flowId);
+         flowBuilder.setHardTimeout(0);
+         flowBuilder.setIdleTimeout(0);
+         if (write) {
+             writeFlow(flowBuilder, nodeBuilder);
+         } else {
+             removeFlow(flowBuilder, nodeBuilder);
+         }
+     }
+     /*
+      * (Table:1) Local Table Miss
+      * Match: Any Remaining Flows w/a VLAN ID
+      * Action: Drop w/ a low priority
+      * table=2,priority=8192,vlan_id=0x5 actions=drop
+      */
+     private void handleLocalVlanTableMiss(Long dpidLong, Short writeTable,
+                                   String segmentationId, boolean write) {
+         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(createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(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 = new ArrayList<Instruction>();
+             // Call the InstructionBuilder Methods Containing Actions
+             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);
+             // Add InstructionsBuilder to FlowBuilder
+             flowBuilder.setInstructions(isb.build());
+         }
+         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(writeTable);
+         flowBuilder.setKey(key);
+         flowBuilder.setPriority(8192);
+         flowBuilder.setFlowName(flowId);
+         flowBuilder.setHardTimeout(0);
+         flowBuilder.setIdleTimeout(0);
+         if (write) {
+             writeFlow(flowBuilder, nodeBuilder);
+         } else {
+             removeFlow(flowBuilder, nodeBuilder);
+         }
+     }
+     private Group getGroup(GroupBuilder groupBuilder, NodeBuilder nodeBuilder) {
+         IMDSALConsumer mdsalConsumer = (IMDSALConsumer) ServiceHelper.getInstance(IMDSALConsumer.class, "default", this);
+         if (mdsalConsumer == null) {
+             logger.error("ERROR finding MDSAL Service. Its possible that writeFlow is called too soon ?");
+             return null;
+         }
+         dataBrokerService = mdsalConsumer.getDataBrokerService();
+         if (dataBrokerService == null) {
+             logger.error("ERROR finding reference for DataBrokerService. Please check out the MD-SAL support on the Controller.");
+             return null;
+         }
+         InstanceIdentifier<Group> path1 = InstanceIdentifier.builder(Nodes.class).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory
+                 .rev130819.nodes.Node.class, nodeBuilder.getKey()).augmentation(FlowCapableNode.class).child(Group.class,
+                 new GroupKey(groupBuilder.getGroupId())).build();
+         return (Group)dataBrokerService.readConfigurationData(path1);
+     }
+     private Group writeGroup(GroupBuilder groupBuilder, NodeBuilder nodeBuilder) {
+         IMDSALConsumer mdsalConsumer = (IMDSALConsumer) ServiceHelper.getInstance(IMDSALConsumer.class, "default", this);
+         if (mdsalConsumer == null) {
+             logger.error("ERROR finding MDSAL Service. Its possible that writeFlow is called too soon ?");
+             return null;
+         }
+         dataBrokerService = mdsalConsumer.getDataBrokerService();
+         if (dataBrokerService == null) {
+             logger.error("ERROR finding reference for DataBrokerService. Please check out the MD-SAL support on the Controller.");
+             return null;
+         }
+         DataModification<InstanceIdentifier<?>, DataObject> modification = dataBrokerService.beginTransaction();
+         InstanceIdentifier<Group> path1 = InstanceIdentifier.builder(Nodes.class).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory
+                 .rev130819.nodes.Node.class, nodeBuilder.getKey()).augmentation(FlowCapableNode.class).child(Group.class,
+                 new GroupKey(groupBuilder.getGroupId())).build();
+         modification.putConfigurationData(nodeBuilderToInstanceId(nodeBuilder), nodeBuilder.build());
+         modification.putConfigurationData(path1, groupBuilder.build());
+         Future<RpcResult<TransactionStatus>> commitFuture = modification.commit();
+         try {
+             RpcResult<TransactionStatus> result = commitFuture.get();
+             TransactionStatus status = result.getResult();
+             logger.debug("Transaction Status "+status.toString()+" for Group "+groupBuilder.getGroupName());
+         } catch (InterruptedException e) {
+             logger.error(e.getMessage(), e);
+         } catch (ExecutionException e) {
+             logger.error(e.getMessage(), e);
+         }
+         return (Group)dataBrokerService.readConfigurationData(path1);
+     }
+     private Group removeGroup(GroupBuilder groupBuilder, NodeBuilder nodeBuilder) {
+         IMDSALConsumer mdsalConsumer = (IMDSALConsumer) ServiceHelper.getInstance(IMDSALConsumer.class, "default", this);
+         if (mdsalConsumer == null) {
+             logger.error("ERROR finding MDSAL Service. Its possible that writeFlow is called too soon ?");
+             return null;
+         }
+         dataBrokerService = mdsalConsumer.getDataBrokerService();
+         if (dataBrokerService == null) {
+             logger.error("ERROR finding reference for DataBrokerService. Please check out the MD-SAL support on the Controller.");
+             return null;
+         }
+         DataModification<InstanceIdentifier<?>, DataObject> modification = dataBrokerService.beginTransaction();
+         InstanceIdentifier<Group> path1 = InstanceIdentifier.builder(Nodes.class).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory
+                 .rev130819.nodes.Node.class, nodeBuilder.getKey()).augmentation(FlowCapableNode.class).child(Group.class,
+                 new GroupKey(groupBuilder.getGroupId())).build();
+         modification.removeConfigurationData(path1);
+         Future<RpcResult<TransactionStatus>> commitFuture = modification.commit();
+         try {
+             RpcResult<TransactionStatus> result = commitFuture.get();
+             TransactionStatus status = result.getResult();
+             logger.debug("Transaction Status "+status.toString()+" for Group "+groupBuilder.getGroupName());
+         } catch (InterruptedException e) {
+             logger.error(e.getMessage(), e);
+         } catch (ExecutionException e) {
+             logger.error(e.getMessage(), e);
+         }
+         return (Group)dataBrokerService.readConfigurationData(path1);
+     }
+     private Flow getFlow(FlowBuilder flowBuilder, NodeBuilder nodeBuilder) {
+         IMDSALConsumer mdsalConsumer = (IMDSALConsumer) ServiceHelper.getInstance(IMDSALConsumer.class, "default", this);
+         if (mdsalConsumer == null) {
+             logger.error("ERROR finding MDSAL Service. Its possible that writeFlow is called too soon ?");
+             return null;
+         }
+         dataBrokerService = mdsalConsumer.getDataBrokerService();
+         if (dataBrokerService == null) {
+             logger.error("ERROR finding reference for DataBrokerService. Please check out the MD-SAL support on the Controller.");
+             return null;
+         }
+         InstanceIdentifier<Flow> path1 = InstanceIdentifier.builder(Nodes.class).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory
+                 .rev130819.nodes.Node.class, nodeBuilder.getKey()).augmentation(FlowCapableNode.class).child(Table.class,
+                 new TableKey(flowBuilder.getTableId())).child(Flow.class, flowBuilder.getKey()).build();
+         return (Flow)dataBrokerService.readConfigurationData(path1);
+     }
+     private void writeFlow(FlowBuilder flowBuilder, NodeBuilder nodeBuilder) {
+         IMDSALConsumer mdsalConsumer = (IMDSALConsumer) ServiceHelper.getInstance(IMDSALConsumer.class, "default", this);
+         if (mdsalConsumer == null) {
+             logger.error("ERROR finding MDSAL Service. Its possible that writeFlow is called too soon ?");
+             return;
+         }
+         dataBrokerService = mdsalConsumer.getDataBrokerService();
+         if (dataBrokerService == null) {
+             logger.error("ERROR finding reference for DataBrokerService. Please check out the MD-SAL support on the Controller.");
+             return;
+         }
+         DataModification<InstanceIdentifier<?>, DataObject> modification = dataBrokerService.beginTransaction();
+         InstanceIdentifier<Flow> path1 = InstanceIdentifier.builder(Nodes.class).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory
+                 .rev130819.nodes.Node.class, nodeBuilder.getKey()).augmentation(FlowCapableNode.class).child(Table.class,
+                 new TableKey(flowBuilder.getTableId())).child(Flow.class, flowBuilder.getKey()).build();
+         //modification.putOperationalData(nodeBuilderToInstanceId(nodeBuilder), nodeBuilder.build());
+         //modification.putOperationalData(path1, flowBuilder.build());
+         modification.putConfigurationData(nodeBuilderToInstanceId(nodeBuilder), nodeBuilder.build());
+         modification.putConfigurationData(path1, flowBuilder.build());
+         Future<RpcResult<TransactionStatus>> commitFuture = modification.commit();
+         try {
+             RpcResult<TransactionStatus> result = commitFuture.get();
+             TransactionStatus status = result.getResult();
+             logger.debug("Transaction Status "+status.toString()+" for Flow "+flowBuilder.getFlowName());
+         } catch (InterruptedException e) {
+             logger.error(e.getMessage(), e);
+         } catch (ExecutionException e) {
+             logger.error(e.getMessage(), e);
+         }
+     }
+     private void removeFlow(FlowBuilder flowBuilder, NodeBuilder nodeBuilder) {
+         IMDSALConsumer mdsalConsumer = (IMDSALConsumer) ServiceHelper.getInstance(IMDSALConsumer.class, "default", this);
+         if (mdsalConsumer == null) {
+             logger.error("ERROR finding MDSAL Service.");
+             return;
+         }
+         dataBrokerService = mdsalConsumer.getDataBrokerService();
+         if (dataBrokerService == null) {
+             logger.error("ERROR finding reference for DataBrokerService. Please check out the MD-SAL support on the Controller.");
+             return;
+         }
+         DataModification<InstanceIdentifier<?>, DataObject> modification = dataBrokerService.beginTransaction();
+         InstanceIdentifier<Flow> path1 = InstanceIdentifier.builder(Nodes.class)
+                 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory
+                 .rev130819.nodes.Node.class, nodeBuilder.getKey())
+                 .augmentation(FlowCapableNode.class).child(Table.class,
+                 new TableKey(flowBuilder.getTableId())).child(Flow.class, flowBuilder.getKey()).build();
+         //modification.removeOperationalData(nodeBuilderToInstanceId(nodeBuilder));
+         //modification.removeOperationalData(path1);
+         //modification.removeConfigurationData(nodeBuilderToInstanceId(nodeBuilder));
+         modification.removeConfigurationData(path1);
+         Future<RpcResult<TransactionStatus>> commitFuture = modification.commit();
+         try {
+             RpcResult<TransactionStatus> result = commitFuture.get();
+             TransactionStatus status = result.getResult();
+             logger.debug("Transaction Status "+status.toString()+" for Flow "+flowBuilder.getFlowName());
+         } catch (InterruptedException e) {
+             logger.error(e.getMessage(), e);
+         } catch (ExecutionException e) {
+             logger.error(e.getMessage(), e);
+         }
+     }
+     /**
+      * Create Ingress Port Match dpidLong, inPort
+      *
+      * @param matchBuilder  Map matchBuilder MatchBuilder Object without a match
+      * @param dpidLong      Long the datapath ID of a switch/node
+      * @param inPort        Long ingress port on a switch
+      * @return matchBuilder Map MatchBuilder Object with a match
+      */
+     protected static MatchBuilder createInPortMatch(MatchBuilder matchBuilder, Long dpidLong, Long inPort) {
+         NodeConnectorId ncid = new NodeConnectorId("openflow:" + dpidLong + ":" + inPort);
+         logger.debug("createInPortMatch() Node Connector ID is - Type=openflow: DPID={} inPort={} ", dpidLong, inPort);
+         matchBuilder.setInPort(NodeConnectorId.getDefaultInstance(ncid.getValue()));
+         matchBuilder.setInPort(ncid);
+         return matchBuilder;
+     }
+     /**
+      * Create EtherType Match
+      *
+      * @param matchBuilder  Map matchBuilder MatchBuilder Object without a match
+      * @param etherType     Long EtherType
+      * @return matchBuilder Map MatchBuilder Object with a match
+      */
+     protected static MatchBuilder createEtherTypeMatch(MatchBuilder matchBuilder, EtherType etherType) {
+         EthernetMatchBuilder ethernetMatch = new EthernetMatchBuilder();
+         EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder();
+         ethTypeBuilder.setType(new EtherType(etherType));
+         ethernetMatch.setEthernetType(ethTypeBuilder.build());
+         matchBuilder.setEthernetMatch(ethernetMatch.build());
+         return matchBuilder;
+     }
+     /**
+      * Create Ethernet Source Match
+      *
+      * @param matchBuilder  MatchBuilder Object without a match yet
+      * @param sMacAddr      String representing a source MAC
+      * @return matchBuilder Map MatchBuilder Object with a match
+      */
+     protected static MatchBuilder createEthSrcMatch(MatchBuilder matchBuilder, MacAddress sMacAddr) {
+         EthernetMatchBuilder ethernetMatch = new EthernetMatchBuilder();
+         EthernetSourceBuilder ethSourceBuilder = new EthernetSourceBuilder();
+         ethSourceBuilder.setAddress(new MacAddress(sMacAddr));
+         ethernetMatch.setEthernetSource(ethSourceBuilder.build());
+         matchBuilder.setEthernetMatch(ethernetMatch.build());
+         return matchBuilder;
+     }
+     /**
+      * Create Ethernet Destination Match
+      *
+      * @param matchBuilder MatchBuilder Object without a match yet
+      * @param vlanId       Integer representing a VLAN ID Integer representing a VLAN ID
+      * @return matchBuilder Map MatchBuilder Object with a match
+      */
+     protected static MatchBuilder createVlanIdMatch(MatchBuilder matchBuilder, VlanId vlanId) {
+         VlanMatchBuilder vlanMatchBuilder = new VlanMatchBuilder();
+         VlanIdBuilder vlanIdBuilder = new VlanIdBuilder();
+         vlanIdBuilder.setVlanId(new VlanId(vlanId));
+         vlanIdBuilder.setVlanIdPresent(true);
+         vlanMatchBuilder.setVlanId(vlanIdBuilder.build());
+         matchBuilder.setVlanMatch(vlanMatchBuilder.build());
+         return matchBuilder;
+     }
+     /**
+      * Create Ethernet Destination Match
+      *
+      * @param matchBuilder  MatchBuilder Object without a match yet
+      * @param dMacAddr      String representing a destination MAC
+      * @return matchBuilder Map MatchBuilder Object with a match
+      */
+     protected static MatchBuilder createDestEthMatch(MatchBuilder matchBuilder, MacAddress dMacAddr, MacAddress mask) {
+         EthernetMatchBuilder ethernetMatch = new EthernetMatchBuilder();
+         EthernetDestinationBuilder ethDestinationBuilder = new EthernetDestinationBuilder();
+         ethDestinationBuilder.setAddress(new MacAddress(dMacAddr));
+         if (mask != null) {
+             ethDestinationBuilder.setMask(mask);
+         }
+         ethernetMatch.setEthernetDestination(ethDestinationBuilder.build());
+         matchBuilder.setEthernetMatch(ethernetMatch.build());
+         return matchBuilder;
+     }
+     /**
+      * Tunnel ID Match Builder
+      *
+      * @param matchBuilder  MatchBuilder Object without a match yet
+      * @param tunnelId      BigInteger representing a tunnel ID
+      * @return matchBuilder Map MatchBuilder Object with a match
+      */
+     protected static MatchBuilder createTunnelIDMatch(MatchBuilder matchBuilder, BigInteger tunnelId) {
+         TunnelBuilder tunnelBuilder = new TunnelBuilder();
+         tunnelBuilder.setTunnelId(tunnelId);
+         matchBuilder.setTunnel(tunnelBuilder.build());
+         return matchBuilder;
+     }
+     /**
+      * Match ICMP code and type
+      *
+      * @param matchBuilder  MatchBuilder Object without a match yet
+      * @param type          short representing an ICMP type
+      * @param code          short representing an ICMP code
+      * @return matchBuilder Map MatchBuilder Object with a match
+      */
+     protected static MatchBuilder createICMPv4Match(MatchBuilder matchBuilder, short type, short code) {
+         EthernetMatchBuilder eth = new EthernetMatchBuilder();
+         EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder();
+         ethTypeBuilder.setType(new EtherType(0x0800L));
+         eth.setEthernetType(ethTypeBuilder.build());
+         matchBuilder.setEthernetMatch(eth.build());
+         // Build the IPv4 Match requied per OVS Syntax
+         IpMatchBuilder ipmatch = new IpMatchBuilder();
+         ipmatch.setIpProtocol((short) 1);
+         matchBuilder.setIpMatch(ipmatch.build());
+         // Build the ICMPv4 Match
+         Icmpv4MatchBuilder icmpv4match = new Icmpv4MatchBuilder();
+         icmpv4match.setIcmpv4Type(type);
+         icmpv4match.setIcmpv4Code(code);
+         matchBuilder.setIcmpv4Match(icmpv4match.build());
+         return matchBuilder;
+     }
+     /**
+      * @param matchBuilder MatchBuilder Object without a match yet
+      * @param dstip        String containing an IPv4 prefix
+      * @return matchBuilder Map Object with a match
+      */
+     private static MatchBuilder createDstL3IPv4Match(MatchBuilder matchBuilder, Ipv4Prefix dstip) {
+         EthernetMatchBuilder eth = new EthernetMatchBuilder();
+         EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder();
+         ethTypeBuilder.setType(new EtherType(0x0800L));
+         eth.setEthernetType(ethTypeBuilder.build());
+         matchBuilder.setEthernetMatch(eth.build());
+         Ipv4MatchBuilder ipv4match = new Ipv4MatchBuilder();
+         ipv4match.setIpv4Destination(dstip);
+         matchBuilder.setLayer3Match(ipv4match.build());
+         return matchBuilder;
+     }
+     /**
+      * @param matchBuilder MatchBuilder Object without a match yet
+      * @param srcip        String containing an IPv4 prefix
+      * @return             matchBuilder Map Object with a match
+      */
+     private static MatchBuilder createSrcL3IPv4Match(MatchBuilder matchBuilder, Ipv4Prefix srcip) {
+         EthernetMatchBuilder eth = new EthernetMatchBuilder();
+         EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder();
+         ethTypeBuilder.setType(new EtherType(0x0800L));
+         eth.setEthernetType(ethTypeBuilder.build());
+         matchBuilder.setEthernetMatch(eth.build());
+         Ipv4MatchBuilder ipv4Match = new Ipv4MatchBuilder();
+         Ipv4MatchBuilder ipv4match = new Ipv4MatchBuilder();
+         ipv4match.setIpv4Source(srcip);
+         matchBuilder.setLayer3Match(ipv4match.build());
+         return matchBuilder;
+     }
+     /**
+      * Create Source TCP Port Match
+      *
+      * @param matchBuilder @param matchbuilder MatchBuilder Object without a match yet
+      * @param tcpport      Integer representing a source TCP port
+      * @return             matchBuilder Map MatchBuilder Object with a match
+      */
+     protected static MatchBuilder createSetSrcTcpMatch(MatchBuilder matchBuilder, PortNumber tcpport) {
+         EthernetMatchBuilder ethType = new EthernetMatchBuilder();
+         EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder();
+         ethTypeBuilder.setType(new EtherType(0x0800L));
+         ethType.setEthernetType(ethTypeBuilder.build());
+         matchBuilder.setEthernetMatch(ethType.build());
+         IpMatchBuilder ipmatch = new IpMatchBuilder();
+         ipmatch.setIpProtocol((short) 6);
+         matchBuilder.setIpMatch(ipmatch.build());
+         TcpMatchBuilder tcpmatch = new TcpMatchBuilder();
+         tcpmatch.setTcpSourcePort(tcpport);
+         matchBuilder.setLayer4Match(tcpmatch.build());
+         return matchBuilder;
+     }
+     /**
+      * Create Destination TCP Port Match
+      *
+      * @param matchBuilder MatchBuilder Object without a match yet
+      * @param tcpport      Integer representing a destination TCP port
+      * @return             matchBuilder Map MatchBuilder Object with a match
+      */
+     protected static MatchBuilder createSetDstTcpMatch(MatchBuilder matchBuilder, PortNumber tcpport) {
+         EthernetMatchBuilder ethType = new EthernetMatchBuilder();
+         EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder();
+         ethTypeBuilder.setType(new EtherType(0x0800L));
+         ethType.setEthernetType(ethTypeBuilder.build());
+         matchBuilder.setEthernetMatch(ethType.build());
+         IpMatchBuilder ipmatch = new IpMatchBuilder();
+         ipmatch.setIpProtocol((short) 6);
+         matchBuilder.setIpMatch(ipmatch.build());
+         PortNumber dstport = new PortNumber(tcpport);
+         TcpMatchBuilder tcpmatch = new TcpMatchBuilder();
+         tcpmatch.setTcpDestinationPort(tcpport);
+         matchBuilder.setLayer4Match(tcpmatch.build());
+         return matchBuilder;
+     }
+     /**
+      * Create Send to Controller Reserved Port Instruction (packet_in)
+      *
+      * @param ib Map InstructionBuilder without any instructions
+      * @return ib Map InstructionBuilder with instructions
+      */
+     protected static InstructionBuilder createSendToControllerInstructions(InstructionBuilder ib) {
+         List<Action> actionList = new ArrayList<Action>();
+         ActionBuilder ab = new ActionBuilder();
+         OutputActionBuilder output = new OutputActionBuilder();
+         output.setMaxLength(0xffff);
+         Uri value = new Uri("CONTROLLER");
+         output.setOutputNodeConnector(value);
+         ab.setAction(new OutputActionCaseBuilder().setOutputAction(output.build()).build());
+         ab.setOrder(0);
+         ab.setKey(new ActionKey(0));
+         actionList.add(ab.build());
+         // Create an Apply Action
+         ApplyActionsBuilder aab = new ApplyActionsBuilder();
+         aab.setAction(actionList);
+         // Wrap our Apply Action in an Instruction
+         ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
+         return ib;
+     }
+     /**
+      * Create NORMAL Reserved Port Instruction (packet_in)
+      *
+      * @param ib Map InstructionBuilder without any instructions
+      * @return ib Map InstructionBuilder with instructions
+      */
+     protected static InstructionBuilder createNormalInstructions(InstructionBuilder ib) {
+         List<Action> actionList = new ArrayList<Action>();
+         ActionBuilder ab = new ActionBuilder();
+         OutputActionBuilder output = new OutputActionBuilder();
+         Uri value = new Uri("NORMAL");
+         output.setOutputNodeConnector(value);
+         ab.setAction(new OutputActionCaseBuilder().setOutputAction(output.build()).build());
+         ab.setOrder(0);
+         ab.setKey(new ActionKey(0));
+         actionList.add(ab.build());
+         // Create an Apply Action
+         ApplyActionsBuilder aab = new ApplyActionsBuilder();
+         aab.setAction(actionList);
+         // Wrap our Apply Action in an Instruction
+         ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
+         return ib;
+     }
+     /**
+      * Create Output Port Instruction
+      *
+      * @param ib       Map InstructionBuilder without any instructions
+      * @param dpidLong Long the datapath ID of a switch/node
+      * @param port     Long representing a port on a switch/node
+      * @return ib InstructionBuilder Map with instructions
+      */
+     protected static InstructionBuilder createOutputPortInstructions(InstructionBuilder ib, Long dpidLong, Long port) {
+         NodeConnectorId ncid = new NodeConnectorId("openflow:" + dpidLong + ":" + port);
+         logger.debug("createOutputPortInstructions() Node Connector ID is - Type=openflow: DPID={} inPort={} ", dpidLong, port);
+         List<Action> actionList = new ArrayList<Action>();
+         ActionBuilder ab = new ActionBuilder();
+         OutputActionBuilder oab = new OutputActionBuilder();
+         oab.setOutputNodeConnector(ncid);
+         ab.setAction(new OutputActionCaseBuilder().setOutputAction(oab.build()).build());
+         ab.setOrder(0);
+         ab.setKey(new ActionKey(0));
+         actionList.add(ab.build());
+         // Create an Apply Action
+         ApplyActionsBuilder aab = new ApplyActionsBuilder();
+         aab.setAction(actionList);
+         ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
+         return ib;
+     }
+     /**
+      * Create Output Port Group Instruction
+      *
+      * @param ib       Map InstructionBuilder without any instructions
+      * @param dpidLong Long the datapath ID of a switch/node
+      * @param port     Long representing a port on a switch/node
+      * @return ib InstructionBuilder Map with instructions
+      */
+     protected InstructionBuilder createOutputPortInstructions(InstructionBuilder ib,
+                                                               Long dpidLong, Long port ,
+                                                               List<Instruction> instructions) {
+         NodeConnectorId ncid = new NodeConnectorId("openflow:" + dpidLong + ":" + port);
+         logger.debug("createOutputPortInstructions() Node Connector ID is - Type=openflow: DPID={} port={} existingInstructions={}", dpidLong, port, instructions);
+         List<Action> actionList = new ArrayList<Action>();
+         ActionBuilder ab = new ActionBuilder();
+         List<Action> existingActions = null;
+         if (instructions != null) {
+             for (Instruction in : instructions) {
+                 if (in.getInstruction() instanceof ApplyActionsCase) {
+                     existingActions = (((ApplyActionsCase) in.getInstruction()).getApplyActions().getAction());
+                     actionList.addAll(existingActions);
+                 }
+             }
+         }
+         /* Create output action for this port*/
+         OutputActionBuilder oab = new OutputActionBuilder();
+         oab.setOutputNodeConnector(ncid);
+         ab.setAction(new OutputActionCaseBuilder().setOutputAction(oab.build()).build());
+         boolean addNew = true;
+         /* Find the group action and get the group */
+         for (Action action : actionList) {
+             if (action.getAction() instanceof OutputActionCase) {
+                 OutputActionCase opAction = (OutputActionCase)action.getAction();
+                 /* If output port action already in the action list of one of the buckets, skip */
+                 if (opAction.getOutputAction().getOutputNodeConnector().equals(new Uri(ncid))) {
+                     addNew = false;
+                     break;
+                 }
+             }
+         }
+         if (addNew) {
+             ab.setOrder(actionList.size());
+             ab.setKey(new ActionKey(actionList.size()));
+             actionList.add(ab.build());
+         }
+         // Create an Apply Action
+         ApplyActionsBuilder aab = new ApplyActionsBuilder();
+         aab.setAction(actionList);
+         ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
+         logger.debug("createOutputPortInstructions() : applyAction {}", aab.build());
+         return ib;
+     }
+     /**
+      * Create Output Port Group Instruction
+      *
+      * @param ib       Map InstructionBuilder without any instructions
+      * @param dpidLong Long the datapath ID of a switch/node
+      * @param port     Long representing a port on a switch/node
+      * @return ib InstructionBuilder Map with instructions
+      */
+     protected InstructionBuilder createOutputGroupInstructions(NodeBuilder nodeBuilder,
+                                                                InstructionBuilder ib,
+                                                                Long dpidLong, Long port ,
+                                                                List<Instruction> instructions) {
+         NodeConnectorId ncid = new NodeConnectorId("openflow:" + dpidLong + ":" + port);
+         logger.debug("createOutputGroupInstructions() Node Connector ID is - Type=openflow: DPID={} port={} existingInstructions={}", dpidLong, port, instructions);
+         List<Action> actionList = new ArrayList<Action>();
+         ActionBuilder ab = new ActionBuilder();
+         List<Action> existingActions = null;
+         if (instructions != null) {
+             for (Instruction in : instructions) {
+                 if (in.getInstruction() instanceof ApplyActionsCase) {
+                     existingActions = (((ApplyActionsCase) in.getInstruction()).getApplyActions().getAction());
+                     actionList.addAll(existingActions);
+                 }
+             }
+         }
+         GroupBuilder groupBuilder = new GroupBuilder();
+         Group group = null;
+         /* Create output action for this port*/
+         OutputActionBuilder oab = new OutputActionBuilder();
+         oab.setOutputNodeConnector(ncid);
+         ab.setAction(new OutputActionCaseBuilder().setOutputAction(oab.build()).build());
+         logger.debug("createOutputGroupInstructions(): output action {}", ab.build());
+         boolean addNew = true;
+         boolean groupActionAdded = false;
+         /* Find the group action and get the group */
+         for (Action action : actionList) {
+             if (action.getAction() instanceof GroupActionCase) {
+                 groupActionAdded = true;
+                 GroupActionCase groupAction = (GroupActionCase) action.getAction();
+                 Long id = groupAction.getGroupAction().getGroupId();
+                 String groupName = groupAction.getGroupAction().getGroup();
+                 GroupKey key = new GroupKey(new GroupId(id));
+                 groupBuilder.setGroupId(new GroupId(id));
+                 groupBuilder.setGroupName(groupName);
+                 groupBuilder.setGroupType(GroupTypes.GroupAll);
+                 groupBuilder.setKey(key);
+                 group = getGroup(groupBuilder, nodeBuilder);
+                 logger.debug("createOutputGroupInstructions: group {}", group);
+                 break;
+             }
+         }
+         logger.debug("createOutputGroupInstructions: groupActionAdded {}", groupActionAdded);
+         if (groupActionAdded) {
+             /* modify the action bucket in group */
+             groupBuilder = new GroupBuilder(group);
+             Buckets buckets = groupBuilder.getBuckets();
+             for (Bucket bucket : buckets.getBucket()) {
+                 List<Action> bucketActions = bucket.getAction();
+                 logger.debug("createOutputGroupInstructions: bucketActions {}", bucketActions);
+                 for (Action action : bucketActions) {
+                     if (action.getAction() instanceof OutputActionCase) {
+                         OutputActionCase opAction = (OutputActionCase)action.getAction();
+                         /* If output port action already in the action list of one of the buckets, skip */
+                         if (opAction.getOutputAction().getOutputNodeConnector().equals(new Uri(ncid))) {
+                             addNew = false;
+                             break;
+                         }
+                     }
+                 }
+             }
+             logger.debug("createOutputGroupInstructions: addNew {}", addNew);
+             if (addNew) {
+                 /* the new output action is not in the bucket, add to bucket */
+                 if (!buckets.getBucket().isEmpty()) {
+                     Bucket bucket = buckets.getBucket().get(0);
+                     List<Action> bucketActionList = new ArrayList<Action>();
+                     bucketActionList.addAll(bucket.getAction());
+                     /* set order for new action and add to action list */
+                     ab.setOrder(bucketActionList.size());
+                     ab.setKey(new ActionKey(bucketActionList.size()));
+                     bucketActionList.add(ab.build());
+                     /* set bucket and buckets list. Reset groupBuilder with new buckets.*/
+                     BucketsBuilder bucketsBuilder = new BucketsBuilder();
+                     List<Bucket> bucketList = new ArrayList<Bucket>();
+                     BucketBuilder bucketBuilder = new BucketBuilder();
+                     bucketBuilder.setBucketId(new BucketId((long) 1));
+                     bucketBuilder.setKey(new BucketKey(new BucketId((long) 1)));
+                     bucketBuilder.setAction(bucketActionList);
+                     bucketList.add(bucketBuilder.build());
+                     bucketsBuilder.setBucket(bucketList);
+                     groupBuilder.setBuckets(bucketsBuilder.build());
+                     logger.debug("createOutputGroupInstructions: bucketList {}", bucketList);
+                 }
+             }
+         } else {
+             /* create group */
+             groupBuilder = new GroupBuilder();
+             groupBuilder.setGroupType(GroupTypes.GroupAll);
+             groupBuilder.setGroupId(new GroupId(groupId));
+             groupBuilder.setKey(new GroupKey(new GroupId(groupId)));
+             groupBuilder.setGroupName("Output port group" + groupId);
+             groupBuilder.setBarrier(false);
+             BucketsBuilder bucketBuilder = new BucketsBuilder();
+             List<Bucket> bucketList = new ArrayList<Bucket>();
+             BucketBuilder bucket = new BucketBuilder();
+             bucket.setBucketId(new BucketId((long) 1));
+             bucket.setKey(new BucketKey(new BucketId((long) 1)));
+             /* put output action to the bucket */
+             List<Action> bucketActionList = new ArrayList<Action>();
+             /* set order for new action and add to action list */
+             ab.setOrder(bucketActionList.size());
+             ab.setKey(new ActionKey(bucketActionList.size()));
+             bucketActionList.add(ab.build());
+             bucket.setAction(bucketActionList);
+             bucketList.add(bucket.build());
+             bucketBuilder.setBucket(bucketList);
+             groupBuilder.setBuckets(bucketBuilder.build());
+             /* Add new group action */
+             GroupActionBuilder groupActionB = new GroupActionBuilder();
+             groupActionB.setGroupId(groupId);
+             groupActionB.setGroup("Output port group" + groupId);
+             ab = new ActionBuilder();
+             ab.setAction(new GroupActionCaseBuilder().setGroupAction(groupActionB.build()).build());
+             ab.setOrder(actionList.size());
+             ab.setKey(new ActionKey(actionList.size()));
+             actionList.add(ab.build());
+             groupId++;
+         }
+         logger.debug("createOutputGroupInstructions: group {}", groupBuilder.build());
+         logger.debug("createOutputGroupInstructions: actionList {}", actionList);
+         if (addNew) {
+             /* rewrite the group to group table */
+             writeGroup(groupBuilder, nodeBuilder);
+         }
+         // Create an Apply Action
+         ApplyActionsBuilder aab = new ApplyActionsBuilder();
+         aab.setAction(actionList);
+         ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
+         return ib;
+     }
+     /**
+      * add Output Port action to Instruction action list.
+      * This is use for flow with single output port actions.
+      * Flow with mutiple output port actions should use createOutputPortInstructions() method.
+      *
+      * @param ib       Map InstructionBuilder without any instructions
+      * @param dpidLong Long the datapath ID of a switch/node
+      * @param port     Long representing a port on a switch/node
+      * @return ib InstructionBuilder Map with instructions
+      */
+     protected static InstructionBuilder addOutputPortInstructions(InstructionBuilder ib,
+                                                                      Long dpidLong, Long port ,
+                                                                      List<Instruction> instructions) {
+         NodeConnectorId ncid = new NodeConnectorId("openflow:" + dpidLong + ":" + port);
+         logger.debug("addOutputPortInstructions() Node Connector ID is - Type=openflow: DPID={} port={} existingInstructions={}", dpidLong, port, instructions);
+         List<Action> actionList = new ArrayList<Action>();
+         ActionBuilder ab = new ActionBuilder();
+         List<Action> existingActions = null;
+         if (instructions != null) {
+             for (Instruction in : instructions) {
+                 if (in.getInstruction() instanceof ApplyActionsCase) {
+                     existingActions = (((ApplyActionsCase) in.getInstruction()).getApplyActions().getAction());
+                     actionList.addAll(existingActions);
+                 }
+             }
+         }
+         /* Create output action for this port*/
+         OutputActionBuilder oab = new OutputActionBuilder();
+         oab.setOutputNodeConnector(ncid);
+         ab.setAction(new OutputActionCaseBuilder().setOutputAction(oab.build()).build());
+         ab.setOrder(actionList.size());
+         ab.setKey(new ActionKey(actionList.size()));
+         actionList.add(ab.build());
+         // Create an Apply Action
+         ApplyActionsBuilder aab = new ApplyActionsBuilder();
+         aab.setAction(actionList);
+         ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
+         return ib;
+     }
+     /**
+      * Remove Output Port from action list in group bucket
+      *
+      * @param ib       Map InstructionBuilder without any instructions
+      * @param dpidLong Long the datapath ID of a switch/node
+      * @param port     Long representing a port on a switch/node
+      * @return ib InstructionBuilder Map with instructions
+      */
+     protected boolean removeOutputPortFromGroup(NodeBuilder nodeBuilder, InstructionBuilder ib,
+                                 Long dpidLong, Long port , List<Instruction> instructions) {
+         NodeConnectorId ncid = new NodeConnectorId("openflow:" + dpidLong + ":" + port);
+         logger.debug("removeOutputPortFromGroup() Node Connector ID is - Type=openflow: DPID={} port={} existingInstructions={}", dpidLong, port, instructions);
+         List<Action> actionList = new ArrayList<Action>();
+         ActionBuilder ab;
+         List<Action> existingActions = null;
+         if (instructions != null) {
+             for (Instruction in : instructions) {
+                 if (in.getInstruction() instanceof ApplyActionsCase) {
+                     existingActions = (((ApplyActionsCase) in.getInstruction()).getApplyActions().getAction());
+                     actionList.addAll(existingActions);
+                     break;
+                 }
+             }
+         }
+         GroupBuilder groupBuilder = new GroupBuilder();
+         Group group = null;
+         boolean groupActionAdded = false;
+         /* Find the group action and get the group */
+         for (Action action : actionList) {
+             if (action.getAction() instanceof GroupActionCase) {
+                 groupActionAdded = true;
+                 GroupActionCase groupAction = (GroupActionCase) action.getAction();
+                 Long id = groupAction.getGroupAction().getGroupId();
+                 String groupName = groupAction.getGroupAction().getGroup();
+                 GroupKey key = new GroupKey(new GroupId(id));
+                 groupBuilder.setGroupId(new GroupId(id));
+                 groupBuilder.setGroupName(groupName);
+                 groupBuilder.setGroupType(GroupTypes.GroupAll);
+                 groupBuilder.setKey(key);
+                 group = getGroup(groupBuilder, nodeBuilder);
+                 break;
+             }
+         }
+         if (groupActionAdded) {
+             /* modify the action bucket in group */
+             groupBuilder = new GroupBuilder(group);
+             Buckets buckets = groupBuilder.getBuckets();
+             List<Action> bucketActions = new ArrayList<Action>();
+             for (Bucket bucket : buckets.getBucket()) {
+                 int index = 0;
+                 boolean isPortDeleted = false;
+                 bucketActions = bucket.getAction();
+                 for (Action action : bucketActions) {
+                     if (action.getAction() instanceof OutputActionCase) {
+                         OutputActionCase opAction = (OutputActionCase)action.getAction();
+                         if (opAction.getOutputAction().getOutputNodeConnector().equals(new Uri(ncid))) {
+                             /* Find the output port in action list and remove */
+                             index = bucketActions.indexOf(action);
+                             bucketActions.remove(action);
+                             isPortDeleted = true;
+                             break;
+                         }
+                     }
+                 }
+                 if (isPortDeleted && !bucketActions.isEmpty()) {
+                     for (int i = index; i< bucketActions.size(); i++) {
+                         Action action = bucketActions.get(i);
+                         if (action.getOrder() != i) {
+                             /* Shift the action order */
+                             ab = new ActionBuilder();
+                             ab.setAction(action.getAction());
+                             ab.setOrder(i);
+                             ab.setKey(new ActionKey(i));
+                             Action actionNewOrder = ab.build();
+                             bucketActions.remove(action);
+                             bucketActions.add(i, actionNewOrder);
+                         }
+                     }
+                 } else if (bucketActions.isEmpty()) {
+                     /* remove bucket with empty action list */
+                     buckets.getBucket().remove(bucket);
+                     break;
+                 }
+             }
+             if (!buckets.getBucket().isEmpty()) {
+                 /* rewrite the group to group table */
+                 /* set bucket and buckets list. Reset groupBuilder with new buckets.*/
+                 BucketsBuilder bucketsBuilder = new BucketsBuilder();
+                 List<Bucket> bucketList = new ArrayList<Bucket>();
+                 BucketBuilder bucketBuilder = new BucketBuilder();
+                 bucketBuilder.setBucketId(new BucketId((long) 1));
+                 bucketBuilder.setKey(new BucketKey(new BucketId((long) 1)));
+                 bucketBuilder.setAction(bucketActions);
+                 bucketList.add(bucketBuilder.build());
+                 bucketsBuilder.setBucket(bucketList);
+                 groupBuilder.setBuckets(bucketsBuilder.build());
+                 logger.debug("removeOutputPortFromGroup: bucketList {}", bucketList);
+                 writeGroup(groupBuilder, nodeBuilder);
+                 ApplyActionsBuilder aab = new ApplyActionsBuilder();
+                 aab.setAction(actionList);
+                 ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
+                 return false;
+             } else {
+                 /* remove group with empty bucket. return true to delete flow */
+                 removeGroup(groupBuilder, nodeBuilder);
+                 return true;
+             }
+         } else {
+             /* no group for port list. flow can be removed */
+             return true;
+         }
+     }
+     /**
+      * Remove Output Port from Instruction
+      *
+      * @param ib       Map InstructionBuilder without any instructions
+      * @param dpidLong Long the datapath ID of a switch/node
+      * @param port     Long representing a port on a switch/node
+      * @return ib InstructionBuilder Map with instructions
+      */
+     protected static boolean removeOutputPortFromInstructions(InstructionBuilder ib,
+                                 Long dpidLong, Long port , List<Instruction> instructions) {
+         NodeConnectorId ncid = new NodeConnectorId("openflow:" + dpidLong + ":" + port);
+         logger.debug("createOutputPortInstructions() Node Connector ID is - Type=openflow: DPID={} port={} existingInstructions={}", dpidLong, port, instructions);
+         List<Action> actionList = new ArrayList<Action>();
+         ActionBuilder ab;
+         List<Action> existingActions = null;
+         if (instructions != null) {
+             for (Instruction in : instructions) {
+                 if (in.getInstruction() instanceof ApplyActionsCase) {
+                     existingActions = (((ApplyActionsCase) in.getInstruction()).getApplyActions().getAction());
+                     actionList.addAll(existingActions);
+                     break;
+                 }
+             }
+         }
+         int numOutputPort = 0;
+         int index = 0;
+         boolean isPortDeleted = false;
+         for (Action action : actionList) {
+             if (action.getAction() instanceof OutputActionCase) {
+                 numOutputPort++;
+                 OutputActionCase opAction = (OutputActionCase)action.getAction();
+                 if (opAction.getOutputAction().getOutputNodeConnector().equals(new Uri(ncid))) {
+                     /* Find the output port in action list and remove */
+                     index = actionList.indexOf(action);
+                     actionList.remove(action);
+                     isPortDeleted = true;
+                     numOutputPort--;
+                     break;
+                 }
+             }
+         }
+         if (isPortDeleted) {
+             for (int i = index; i< actionList.size(); i++) {
+                 Action action = actionList.get(i);
+                 if (action.getOrder() != i) {
+                     /* Shift the action order */
+                     ab = new ActionBuilder();
+                     ab.setAction(action.getAction());
+                     ab.setOrder(i);
+                     ab.setKey(new ActionKey(i));
+                     Action actionNewOrder = ab.build();
+                     actionList.remove(action);
+                     actionList.add(i, actionNewOrder);
+                 }
+             }
+         }
+         /* Put new action list in Apply Action instruction */
+         if (numOutputPort > 0) {
+             ApplyActionsBuilder aab = new ApplyActionsBuilder();
+             aab.setAction(actionList);
+             ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
+             logger.debug("createOutputPortInstructions() : applyAction {}", aab.build());
+             return false;
+         } else {
+             /* if all output port are removed. Return true to indicate flow remove */
+             return true;
+         }
+     }
+     /**
+      * Create Set Vlan ID Instruction - This includes push vlan action, and set field -> vlan vid action
+      *
+      * @param ib     Map InstructionBuilder without any instructions
+      * @param vlanId Integer representing a VLAN ID Integer representing a VLAN ID
+      * @return ib Map InstructionBuilder with instructions
+      */
+     protected static InstructionBuilder createSetVlanInstructions(InstructionBuilder ib, VlanId vlanId) {
+         List<Action> actionList = new ArrayList<Action>();
+         ActionBuilder ab = new ActionBuilder();
+         /* First we push vlan header */
+         PushVlanActionBuilder vlan = new PushVlanActionBuilder();
+         vlan.setEthernetType(new Integer(0x8100));
+         ab.setAction(new PushVlanActionCaseBuilder().setPushVlanAction(vlan.build()).build());
+         ab.setOrder(0);
+         actionList.add(ab.build());
+         /* Then we set vlan id value as vlanId */
+         SetVlanIdActionBuilder vl = new SetVlanIdActionBuilder();
+         vl.setVlanId(vlanId);
+         ab = new ActionBuilder();
+         ab.setAction(new SetVlanIdActionCaseBuilder().setSetVlanIdAction(vl.build()).build());
+         ab.setOrder(1);
+         actionList.add(ab.build());
+         // Create an Apply Action
+         ApplyActionsBuilder aab = new ApplyActionsBuilder();
+         aab.setAction(actionList);
+         // Wrap our Apply Action in an Instruction
+         ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
+         return ib;
+     }
+     /**
+      * Create Pop Vlan Instruction - this remove vlan header
+      *
+      * @param ib Map InstructionBuilder without any instructions
+      * @return ib Map InstructionBuilder with instructions
+      */
+     protected static InstructionBuilder createPopVlanInstructions(InstructionBuilder ib) {
+         List<Action> actionList = new ArrayList<Action>();
+         ActionBuilder ab = new ActionBuilder();
+         PopVlanActionBuilder popVlanActionBuilder = new PopVlanActionBuilder();
+         ab.setAction(new PopVlanActionCaseBuilder().setPopVlanAction(popVlanActionBuilder.build()).build());
+         ab.setOrder(0);
+         actionList.add(ab.build());
+         // Create an Apply Action
+         ApplyActionsBuilder aab = new ApplyActionsBuilder();
+         aab.setAction(actionList);
+         // Wrap our Apply Action in an Instruction
+         ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
+         return ib;
+     }
+     /**
+      * Create Set IPv4 Source Instruction
+      *
+      * @param ib        Map InstructionBuilder without any instructions
+      * @param prefixsrc String containing an IPv4 prefix
+      * @return ib Map InstructionBuilder with instructions
+      */
+     protected static InstructionBuilder createNwSrcInstructions(InstructionBuilder ib, Ipv4Prefix prefixsrc) {
+         List<Action> actionList = new ArrayList<Action>();
+         ActionBuilder ab = new ActionBuilder();
+         SetNwSrcActionBuilder setNwsrcActionBuilder = new SetNwSrcActionBuilder();
+         Ipv4Builder ipsrc = new Ipv4Builder();
+         ipsrc.setIpv4Address(prefixsrc);
+         setNwsrcActionBuilder.setAddress(ipsrc.build());
+         ab.setAction(new SetNwSrcActionCaseBuilder().setSetNwSrcAction(setNwsrcActionBuilder.build()).build());
+         actionList.add(ab.build());
+         // Create an Apply Action
+         ApplyActionsBuilder aab = new ApplyActionsBuilder();
+         aab.setAction(actionList);
+         // Wrap our Apply Action in an Instruction
+         ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
+         return ib;
+     }
+     /**
+      * Create Set IPv4 Destination Instruction
+      *
+      * @param ib           Map InstructionBuilder without any instructions
+      * @param prefixdst    String containing an IPv4 prefix
+      * @return ib Map InstructionBuilder with instructions
+      */
+     protected static InstructionBuilder createNwDstInstructions(InstructionBuilder ib, Ipv4Prefix prefixdst) {
+         List<Action> actionList = new ArrayList<Action>();
+         ActionBuilder ab = new ActionBuilder();
+         SetNwDstActionBuilder setNwDstActionBuilder = new SetNwDstActionBuilder();
+         Ipv4Builder ipdst = new Ipv4Builder();
+         ipdst.setIpv4Address(prefixdst);
+         setNwDstActionBuilder.setAddress(ipdst.build());
+         ab.setAction(new SetNwDstActionCaseBuilder().setSetNwDstAction(setNwDstActionBuilder.build()).build());
+         actionList.add(ab.build());
+         // Create an Apply Action
+         ApplyActionsBuilder aab = new ApplyActionsBuilder();
+         aab.setAction(actionList);
+         // Wrap our Apply Action in an Instruction
+         ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
+         return ib;
+     }
+     /**
+      * Create Drop Instruction
+      *
+      * @param ib Map InstructionBuilder without any instructions
+      * @return ib Map InstructionBuilder with instructions
+      */
+     protected static InstructionBuilder createDropInstructions(InstructionBuilder ib) {
+         DropActionBuilder dab = new DropActionBuilder();
+         DropAction dropAction = dab.build();
+         ActionBuilder ab = new ActionBuilder();
+         ab.setAction(new DropActionCaseBuilder().setDropAction(dropAction).build());
+         ab.setOrder(0);
+         // Add our drop action to a list
+         List<Action> actionList = new ArrayList<Action>();
+         actionList.add(ab.build());
+         // Create an Apply Action
+         ApplyActionsBuilder aab = new ApplyActionsBuilder();
+         aab.setAction(actionList);
+         // Wrap our Apply Action in an Instruction
+         ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
+         return ib;
+     }
+     /**
+      * Create GOTO Table Instruction Builder
+      *
+      * @param ib      Map InstructionBuilder without any instructions
+      * @param tableId short representing a flow table ID short representing a flow table ID
+      * @return ib Map InstructionBuilder with instructions
+      */
+     protected static InstructionBuilder createGotoTableInstructions(InstructionBuilder ib, short tableId) {
+         GoToTableBuilder gttb = new GoToTableBuilder();
+         gttb.setTableId(tableId);
+         // Wrap our Apply Action in an InstructionBuilder
+         ib.setInstruction(new GoToTableCaseBuilder().setGoToTable(gttb.build()).build());
+         return ib;
+     }
+     /**
+      * Create Set Tunnel ID Instruction Builder
+      *
+      * @param ib       Map InstructionBuilder without any instructions
+      * @param tunnelId BigInteger representing a tunnel ID
+      * @return ib Map InstructionBuilder with instructions
+      */
+     protected static InstructionBuilder createSetTunnelIdInstructions(InstructionBuilder ib, BigInteger tunnelId) {
+         List<Action> actionList = new ArrayList<Action>();
+         ActionBuilder ab = new ActionBuilder();
+         SetFieldBuilder setFieldBuilder = new SetFieldBuilder();
+         // Build the Set Tunnel Field Action
+         TunnelBuilder tunnel = new TunnelBuilder();
+         tunnel.setTunnelId(tunnelId);
+         setFieldBuilder.setTunnel(tunnel.build());
+         ab.setAction(new SetFieldCaseBuilder().setSetField(setFieldBuilder.build()).build());
+         ab.setOrder(0);
+         actionList.add(ab.build());
+         ApplyActionsBuilder aab = new ApplyActionsBuilder();
+         aab.setAction(actionList);
+         // Wrap the Apply Action in an InstructionBuilder and return
+         ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
+         return ib;
+     }
+     /**
+      * Create Set Source TCP Port Instruction
+      *
+      * @param ib      Map InstructionBuilder without any instructions
+      * @param tcpport Integer representing a source TCP port
+      * @return ib Map InstructionBuilder with instructions
+      */
+     protected static InstructionBuilder createSetSrcTCPPort(InstructionBuilder ib, PortNumber tcpport) {
+         List<Action> actionList = new ArrayList<Action>();
+         ActionBuilder ab = new ActionBuilder();
+         SetFieldBuilder setFieldBuilder = new SetFieldBuilder();
+         // Build the Destination TCP Port
+         PortNumber tcpsrcport = new PortNumber(tcpport);
+         TcpMatchBuilder tcpmatch = new TcpMatchBuilder();
+         tcpmatch.setTcpSourcePort(tcpsrcport);
+         setFieldBuilder.setLayer4Match(tcpmatch.build());
+         ab.setAction(new SetFieldCaseBuilder().setSetField(setFieldBuilder.build()).build());
+         ab.setKey(new ActionKey(1));
+         actionList.add(ab.build());
+         ApplyActionsBuilder aab = new ApplyActionsBuilder();
+         aab.setAction(actionList);
+         ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
+         return ib;
+     }
+     /**
+      * Create Set Destination TCP Port Instruction
+      *
+      * @param ib      Map InstructionBuilder without any instructions
+      * @param tcpport Integer representing a source TCP port
+      * @return ib Map InstructionBuilder with instructions
+      */
+     protected static InstructionBuilder createSetDstTCPPort(InstructionBuilder ib, PortNumber tcpport) {
+         List<Action> actionList = new ArrayList<Action>();
+         ActionBuilder ab = new ActionBuilder();
+         SetFieldBuilder setFieldBuilder = new SetFieldBuilder();
+         // Build the Destination TCP Port
+         PortNumber tcpdstport = new PortNumber(tcpport);
+         TcpMatchBuilder tcpmatch = new TcpMatchBuilder();
+         tcpmatch.setTcpDestinationPort(tcpdstport);
+         setFieldBuilder.setLayer4Match(tcpmatch.build());
+         ab.setAction(new SetFieldCaseBuilder().setSetField(setFieldBuilder.build()).build());
+         ab.setKey(new ActionKey(1));
+         actionList.add(ab.build());
+         ApplyActionsBuilder aab = new ApplyActionsBuilder();
+         aab.setAction(actionList);
+         ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
+         return ib;
+     }
+     /**
+      * Create Set Source UDP Port Instruction
+      *
+      * @param ib      Map InstructionBuilder without any instructions
+      * @param udpport Integer representing a source UDP port
+      * @return ib Map InstructionBuilder with instructions
+      */
+     protected static InstructionBuilder createSetSrcUDPPort(InstructionBuilder ib, PortNumber udpport) {
+         List<Action> actionList = new ArrayList<Action>();
+         ActionBuilder ab = new ActionBuilder();
+         SetFieldBuilder setFieldBuilder = new SetFieldBuilder();
+         // Build the Destination TCP Port
+         PortNumber udpsrcport = new PortNumber(udpport);
+         UdpMatchBuilder udpmatch = new UdpMatchBuilder();
+         udpmatch.setUdpSourcePort(udpsrcport);
+         setFieldBuilder.setLayer4Match(udpmatch.build());
+         ab.setAction(new SetFieldCaseBuilder().setSetField(setFieldBuilder.build()).build());
+         ab.setKey(new ActionKey(1));
+         actionList.add(ab.build());
+         ApplyActionsBuilder aab = new ApplyActionsBuilder();
+         aab.setAction(actionList);
+         ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
+         return ib;
+     }
+     /**
+      * Create Set Destination UDP Port Instruction
+      *
+      * @param ib      Map InstructionBuilder without any instructions
+      * @param udpport Integer representing a destination UDP port
+      * @return ib Map InstructionBuilder with instructions
+      */
+     protected static InstructionBuilder createSetDstUDPPort(InstructionBuilder ib, PortNumber udpport) {
+         List<Action> actionList = new ArrayList<Action>();
+         ActionBuilder ab = new ActionBuilder();
+         SetFieldBuilder setFieldBuilder = new SetFieldBuilder();
+         // Build the Destination TCP Port
+         PortNumber udpdstport = new PortNumber(udpport);
+         UdpMatchBuilder udpmatch = new UdpMatchBuilder();
+         udpmatch.setUdpDestinationPort(udpdstport);
+         setFieldBuilder.setLayer4Match(udpmatch.build());
+         ab.setAction(new SetFieldCaseBuilder().setSetField(setFieldBuilder.build()).build());
+         ab.setKey(new ActionKey(1));
+         actionList.add(ab.build());
+         ApplyActionsBuilder aab = new ApplyActionsBuilder();
+         aab.setAction(actionList);
+         ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
+         return ib;
+     }
+     /**
+      * Create Set ICMP Code Instruction
+      *
+      * @param ib   Map InstructionBuilder without any instructions
+      * @param code short repesenting an ICMP code
+      * @return ib Map InstructionBuilder with instructions
+      */
+     private static InstructionBuilder createSetIcmpCodeInstruction(InstructionBuilder ib, short code) {
+         List<Action> actionList = new ArrayList<Action>();
+         ActionBuilder ab = new ActionBuilder();
+         SetFieldBuilder setFieldBuilder = new SetFieldBuilder();
+         Icmpv4MatchBuilder icmpv4match = new Icmpv4MatchBuilder();
+         // Build the ICMPv4 Code Match
+         icmpv4match.setIcmpv4Code(code);
+         setFieldBuilder.setIcmpv4Match(icmpv4match.build());
+         ab.setAction(new SetFieldCaseBuilder().setSetField(setFieldBuilder.build()).build());
+         ab.setKey(new ActionKey(0));
+         actionList.add(ab.build());
+         ApplyActionsBuilder aab = new ApplyActionsBuilder();
+         aab.setAction(actionList);
+         // Wrap our Apply Action in an Instruction
+         ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
+         return ib;
+     }
+     /**
+      * Create Set ICMP Code Instruction
+      *
+      * @param ib Map InstructionBuilder without any instructions
+      * @return ib Map InstructionBuilder with instructions
+      */
+     private static InstructionBuilder createSetIcmpTypeInstruction(InstructionBuilder ib, short type) {
+         List<Action> actionList = new ArrayList<Action>();
+         ActionBuilder ab = new ActionBuilder();
+         SetFieldBuilder setFieldBuilder = new SetFieldBuilder();
+         Icmpv4MatchBuilder icmpv4match = new Icmpv4MatchBuilder();
+         // Build the ICMPv4 Code Match
+         icmpv4match.setIcmpv4Code(type);
+         setFieldBuilder.setIcmpv4Match(icmpv4match.build());
+         ab.setAction(new SetFieldCaseBuilder().setSetField(setFieldBuilder.build()).build());
+         ab.setKey(new ActionKey(1));
+         actionList.add(ab.build());
+         ApplyActionsBuilder aab = new ApplyActionsBuilder();
+         aab.setAction(actionList);
+         // Wrap our Apply Action in an Instruction
+         ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
+         return ib;
+     }
+     /**
+      * Create Decrement TTL Instruction
+      *
+      * @param ib Map InstructionBuilder without any instructions
+      * @return ib Map InstructionBuilder with instructions
+      */
+     private static InstructionBuilder createDecNwTtlInstructions(InstructionBuilder ib) {
+         DecNwTtlBuilder decNwTtlBuilder = new DecNwTtlBuilder();
+         DecNwTtl decNwTtl = decNwTtlBuilder.build();
+         ActionBuilder ab = new ActionBuilder();
+         ab.setAction(new DecNwTtlCaseBuilder().setDecNwTtl(decNwTtl).build());
+         // Add our drop action to a list
+         List<Action> actionList = new ArrayList<Action>();
+         actionList.add(ab.build());
+         // Create an Apply Action
+         ApplyActionsBuilder aab = new ApplyActionsBuilder();
+         aab.setAction(actionList);
+         // Wrap our Apply Action in an Instruction
+         ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
+         return ib;
+     }
+     /**
+      * Set Src Arp MAC
+      */
+     private static InstructionBuilder createSrcArpMacInstructions(InstructionBuilder ib, MacAddress macsrc) {
+         List<Action> actionList = new ArrayList<Action>();
+         ActionBuilder ab = new ActionBuilder();
+         SetFieldBuilder setFieldBuilder = new SetFieldBuilder();
+         ArpMatchBuilder arpmatch = new ArpMatchBuilder();
+         ArpSourceHardwareAddressBuilder arpsrc = new ArpSourceHardwareAddressBuilder();
+         arpsrc.setAddress(macsrc);
+         arpmatch.setArpSourceHardwareAddress(arpsrc.build());
+         setFieldBuilder.setLayer3Match(arpmatch.build());
+         ab.setAction(new SetFieldCaseBuilder().setSetField(setFieldBuilder.build()).build());
+         ab.setKey(new ActionKey(0));
+         actionList.add(ab.build());
+         ApplyActionsBuilder aab = new ApplyActionsBuilder();
+         aab.setAction(actionList);
+         return ib;
+     }
+     /**
+      * Set Dst Arp MAC
+      */
+     private static InstructionBuilder createDstArpMacInstructions(InstructionBuilder ib, MacAddress macdst) {
+         List<Action> actionList = new ArrayList<Action>();
+         ActionBuilder ab = new ActionBuilder();
+         SetFieldBuilder setFieldBuilder = new SetFieldBuilder();
+         ArpMatchBuilder arpmatch = new ArpMatchBuilder();
+         ArpTargetHardwareAddressBuilder arpdst = new ArpTargetHardwareAddressBuilder();
+         arpdst.setAddress(macdst);
+         setFieldBuilder.setLayer3Match(arpmatch.build());
+         ab.setAction(new SetFieldCaseBuilder().setSetField(setFieldBuilder.build()).build());
+         ab.setKey(new ActionKey(0));
+         actionList.add(ab.build());
+         ApplyActionsBuilder aab = new ApplyActionsBuilder();
+         aab.setAction(actionList);
+         return ib;
+     }
+     /**
+      * Set Dst Arp IP
+      */
+     private static InstructionBuilder createDstArpIpInstructions(InstructionBuilder ib, Ipv4Prefix dstiparp) {
+         List<Action> actionList = new ArrayList<Action>();
+         ActionBuilder ab = new ActionBuilder();
+         SetFieldBuilder setFieldBuilder = new SetFieldBuilder();
+         ArpMatchBuilder arpmatch = new ArpMatchBuilder();
+         arpmatch.setArpTargetTransportAddress(dstiparp);
+         setFieldBuilder.setLayer3Match(arpmatch.build());
+         ab.setAction(new SetFieldCaseBuilder().setSetField(setFieldBuilder.build()).build());
+         ab.setKey(new ActionKey(0));
+         actionList.add(ab.build());
+         ApplyActionsBuilder aab = new ApplyActionsBuilder();
+         aab.setAction(actionList);
+         return ib;
+     }
+     /**
+      * Set Src Arp IP
+      */
+     private static InstructionBuilder createSrcArpIpInstructions(InstructionBuilder ib, Ipv4Prefix srciparp) {
+         List<Action> actionList = new ArrayList<Action>();
+         ActionBuilder ab = new ActionBuilder();
+         SetFieldBuilder setFieldBuilder = new SetFieldBuilder();
+         ArpMatchBuilder arpmatch = new ArpMatchBuilder();
+         arpmatch.setArpSourceTransportAddress(srciparp);
+         setFieldBuilder.setLayer3Match(arpmatch.build());
+         ab.setAction(new SetFieldCaseBuilder().setSetField(setFieldBuilder.build()).build());
+         ab.setKey(new ActionKey(0));
+         actionList.add(ab.build());
+         ApplyActionsBuilder aab = new ApplyActionsBuilder();
+         aab.setAction(actionList);
+         return ib;
+     }
+     @Override
+     public void initializeOFFlowRules(Node openflowNode) {
+         IConnectionServiceInternal connectionService = (IConnectionServiceInternal)ServiceHelper.getGlobalInstance(IConnectionServiceInternal.class, this);
+         List<Node> ovsNodes = connectionService.getNodes();
+         if (ovsNodes == null) return;
+         for (Node ovsNode : ovsNodes) {
+             Long brIntDpid = this.getIntegrationBridgeOFDPID(ovsNode);
+             Long brExDpid = this.getExternalBridgeDpid(ovsNode);
+             logger.debug("Compare openflowNode to OVS node {} vs {} and {}", openflowNode.getID(), brIntDpid, brExDpid);
+             String openflowID = openflowNode.getID().toString();
+             if (openflowID.contains(brExDpid.toString())) {
+                 this.initializeFlowRules(ovsNode, adminConfigManager.getExternalBridgeName());
+                 this.triggerInterfaceUpdates(ovsNode);
+             }
+             if (openflowID.contains(brIntDpid.toString())) {
+                 this.initializeFlowRules(ovsNode, adminConfigManager.getIntegrationBridgeName());
+                 this.triggerInterfaceUpdates(ovsNode);
+             }
+         }
+     }
+     private NodeBuilder createNodeBuilder(String nodeId) {
+         NodeBuilder builder = new NodeBuilder();
+         builder.setId(new NodeId(nodeId));
+         builder.setKey(new NodeKey(builder.getId()));
+         return builder;
+     }
+     private InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node> nodeBuilderToInstanceId(NodeBuilder
+                                                                                                                                              node) {
+         return InstanceIdentifier.builder(Nodes.class).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node.class,
+                 node.getKey()).toInstance();
+     }
+     private String getInternalBridgeUUID (Node node, String bridgeName) {
+         try {
+             OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
++            Map<String, org.opendaylight.ovsdb.lib.table.Table<?>> bridgeTable = ovsdbTable.getRows(node, Bridge.NAME.getName());
+             if (bridgeTable == null) return null;
+             for (String key : bridgeTable.keySet()) {
+                 Bridge bridge = (Bridge)bridgeTable.get(key);
+                 if (bridge.getName().equals(bridgeName)) return key;
+             }
+         } catch (Exception e) {
+             logger.error("Error getting Bridge Identifier for {} / {}", node, bridgeName, e);
+         }
+         return null;
+     }
+ }
index 7ef27dec559a6e2055ff5ee11b60d4dd3934faf6,5ac7a2d5a241bbaa44976c98c1caaec9c94372e8..6e3f6774fd07e6bd1cfe27d63b19302790445be1
@@@ -1,5 -1,5 +1,5 @@@
  /*******************************************************************************
-  * Copyright (c) 2013 Hewlett-Packard Development Company, L.P.
+  * Copyright (c) 2013 Hewlett-Packard Development Company, L.P. and others
   * All rights reserved. This program and the accompanying materials
   * are made available under the terms of the Eclipse Public License v1.0
   * which accompanies this distribution, and is available at
@@@ -7,11 -7,13 +7,13 @@@
   *
   * Contributors:
   *    Dave Tucker (HP) - Added unit tests for the AdminConfigManager class.
+  *    Sam Hague - Added unit tests for getPhysicalInterfaceName.
   *******************************************************************************/
  
  package org.opendaylight.ovsdb.neutron;
  
  import static org.junit.Assert.assertEquals;
+ import static org.junit.Assert.assertNull;
  import static org.mockito.Matchers.any;
  import static org.mockito.Matchers.anyObject;
  import static org.mockito.Matchers.anyString;
@@@ -23,13 -25,14 +25,14 @@@ import java.net.InetAddress
  import java.util.concurrent.ConcurrentHashMap;
  import java.util.concurrent.ConcurrentMap;
  
+ import org.junit.Before;
  import org.junit.Test;
  import org.junit.runner.RunWith;
  import org.opendaylight.controller.sal.core.Node;
  import org.opendaylight.controller.sal.utils.ServiceHelper;
  import org.opendaylight.ovsdb.lib.notation.OvsDBMap;
  import org.opendaylight.ovsdb.lib.table.Open_vSwitch;
 -import org.opendaylight.ovsdb.lib.table.internal.Table;
 +import org.opendaylight.ovsdb.lib.table.Table;
  import org.opendaylight.ovsdb.plugin.ConfigurationService;
  import org.opendaylight.ovsdb.plugin.OVSDBConfigService;
  import org.powermock.api.mockito.PowerMockito;
@@@ -40,6 -43,38 +43,38 @@@ import org.powermock.modules.junit4.Pow
  @PrepareForTest(ServiceHelper.class)
  public class AdminConfigManagerTest {
  
+     AdminConfigManager adminConfigManager;
+     private OVSDBConfigService ovsdbConfig;
+     private Node node;
+     private Open_vSwitch ovsTable;
+     private ConcurrentMap<String, Table<?>> ovsMap;
+     private OvsDBMap map;
+     private static String OPENVSWITCH = "Open_vSwitch";
+     private static String PROVIDER_MAPPINGS = "provider_mappings";
+     private static String PHYSNET1 = "physnet1";
+     private static String ETH1 = "eth1";
+     private static String PHYSNET2 = "physnet2";
+     private static String ETH2 = "eth2";
+     private static String PHYSNET3 = "physnet3";
+     private static String ETH3 = "eth3";
+     private static String LOCAL_IP = "local_ip";
+     private static String IPADDR = "10.10.10.10";
+     @Before
+     public void setUp(){
+         adminConfigManager = new AdminConfigManager();
+         node = mock(Node.class);
+         ovsdbConfig = mock(ConfigurationService.class);
+         PowerMockito.mockStatic(ServiceHelper.class);
+         when(ServiceHelper.getGlobalInstance(eq(OVSDBConfigService.class), anyObject())).thenReturn(ovsdbConfig);
+         ovsTable = new Open_vSwitch();
+         ovsMap = new ConcurrentHashMap<>();
+         map = new OvsDBMap();
+     }
      @Test
      public void testGetTunnelEndpoint() throws Exception {
          InetAddress testAddress = InetAddress.getByName("10.10.10.10");
          when(ServiceHelper.getGlobalInstance(eq(OVSDBConfigService.class), anyObject())).thenReturn(ovsdbConfig);
  
          // OVSDBConfigService is null
-         assertEquals(null, AdminConfigManager.getManager().getTunnelEndPoint(mockNode));
+         assertEquals(null, adminConfigManager.getTunnelEndPoint(mockNode));
  
          // Success...
-         assertEquals(testAddress, AdminConfigManager.getManager().getTunnelEndPoint(mockNode));
+         assertEquals(testAddress, adminConfigManager.getTunnelEndPoint(mockNode));
      }
  
      @Test
          when(ServiceHelper.getGlobalInstance(eq(OVSDBConfigService.class), anyObject())).thenReturn(ovsdbConfig);
  
          // Success...
-         assertEquals(testAddress, AdminConfigManager.getManager().getTunnelEndPoint(mockNode));
+         assertEquals(testAddress, adminConfigManager.getTunnelEndPoint(mockNode));
+     }
+     // Add key:value pairs to the map.
+     // Calling again with the same key will overwrite the current pair.
+     private void initMap (String key, String value) {
+         map.put(key, value);
+         ovsTable.setOther_config(map);
+         ovsMap.put(OPENVSWITCH, ovsTable);
+     }
+     @Test
+     public void testGetPhysicalInterfaceName () throws Exception {
+         when(ovsdbConfig.getRows(any(Node.class), anyString())).thenReturn(ovsMap);
+         // Check if match can be found with a single pair
+         initMap(PROVIDER_MAPPINGS, PHYSNET1 + ":" + ETH1);
+         assertEquals("Failed to find " + ETH1 + " in " + map.toString(),
+                 ETH1, adminConfigManager.getPhysicalInterfaceName(node, PHYSNET1));
+         // Check if match can be found with different pairs
+         initMap(PROVIDER_MAPPINGS, PHYSNET1 + ":" + ETH1 + "," + PHYSNET2 + ":" + ETH2);
+         assertEquals("Failed to find " + ETH2 + " in " + map.toString(),
+                 ETH2, adminConfigManager.getPhysicalInterfaceName(node, PHYSNET2));
+         // Check if match can be found with duplicate pairs
+         initMap(PROVIDER_MAPPINGS, PHYSNET1 + ":" + ETH1 + "," + PHYSNET2 + ":" + ETH2 + "," + PHYSNET2 + ":" + ETH2);
+         assertEquals("Failed to find " + ETH2 + " in " + map.toString(),
+                 ETH2, adminConfigManager.getPhysicalInterfaceName(node, PHYSNET2));
+         // Check if match can be found with multiple pairs and extra other_config
+         initMap(LOCAL_IP, IPADDR);
+         assertEquals("Failed to find " + ETH2 + " in " + map.toString(),
+                 ETH2, adminConfigManager.getPhysicalInterfaceName(node, PHYSNET2));
+     }
+     @Test
+     public void testGetPhysicalInterfaceNameNegative () throws Exception {
+         when(ovsdbConfig.getRows(any(Node.class), anyString())).thenReturn(null)
+                 .thenReturn(ovsMap);
+         // Add a null row, an empty row and a good row to the table
+         Open_vSwitch nullRow = new Open_vSwitch();
+         Open_vSwitch emptyRow = new Open_vSwitch();
+         OvsDBMap emptyProviderMap = new OvsDBMap();
+         emptyRow.setOther_config(emptyProviderMap);
+         ovsMap.put("0", nullRow);
+         ovsMap.put("1", emptyRow);
+         initMap(PROVIDER_MAPPINGS, PHYSNET1 + ":" + ETH1);
+         // Check if no rows/no table is handled
+         assertEquals("Failed to return null when ovsdb table is null",
+                 null, adminConfigManager.getTunnelEndPoint(node));
+         // Check if the null and empty rows are ignored
+         System.out.println("map = " + map.toString());
+         System.out.println("ovsMap = " + ovsMap.toString());
+         assertEquals("Failed to find " + ETH1 + " in " + map.toString(),
+                 ETH1, adminConfigManager.getPhysicalInterfaceName(node, PHYSNET1));
+         // Should not be able to find match
+         initMap(PROVIDER_MAPPINGS, PHYSNET1 + ":" + ETH1 + "," + PHYSNET2 + ":" + ETH2);
+         assertNull("Found " + ETH3 + " in " + map.toString(),
+                 adminConfigManager.getPhysicalInterfaceName(node, PHYSNET3));
+         // Should not be able to find match with mal-formed values
+         initMap(PROVIDER_MAPPINGS, PHYSNET1 + "-" + ETH1);
+         assertNull("Found " + ETH1 + " in " + map.toString(),
+                 adminConfigManager.getPhysicalInterfaceName(node, PHYSNET1));
      }
  }
index 86567364aaa181e64c6c5bd1698585d377c01175,9f5ab18980c651405a8687a102316624f7b1b904..fc2624ec40b305a48613caeb22e41e3d53d31e95
@@@ -12,6 -12,7 +12,7 @@@ package org.opendaylight.ovsdb.northbou
  import org.opendaylight.ovsdb.lib.table.Bridge;
  import org.opendaylight.ovsdb.lib.table.Capability;
  import org.opendaylight.ovsdb.lib.table.Controller;
+ import org.opendaylight.ovsdb.lib.table.IPFIX;
  import org.opendaylight.ovsdb.lib.table.Interface;
  import org.opendaylight.ovsdb.lib.table.Manager;
  import org.opendaylight.ovsdb.lib.table.Mirror;
@@@ -22,7 -23,7 +23,7 @@@ import org.opendaylight.ovsdb.lib.table
  import org.opendaylight.ovsdb.lib.table.Queue;
  import org.opendaylight.ovsdb.lib.table.SFlow;
  import org.opendaylight.ovsdb.lib.table.SSL;
 -import org.opendaylight.ovsdb.lib.table.internal.Table;
 +import org.opendaylight.ovsdb.lib.table.Table;
  
  import com.fasterxml.jackson.annotation.JsonSubTypes;
  import com.fasterxml.jackson.annotation.JsonTypeInfo;
@@@ -59,7 -60,8 +60,8 @@@ public class OVSDBRow 
          @JsonSubTypes.Type(value=Qos.class, name="QoS"),
          @JsonSubTypes.Type(value=Queue.class, name="Queue"),
          @JsonSubTypes.Type(value=SFlow.class, name="sFlow"),
-         @JsonSubTypes.Type(value=SSL.class, name="SSL")
+         @JsonSubTypes.Type(value=SSL.class, name="SSL"),
+         @JsonSubTypes.Type(value=IPFIX.class, name="IPFIX")
          })
      Table row;
  
index fdaed3af3624db3ab224bda317ee03028f455678,5b68bd13b1d2a36a4ce7819e7676b85982ff7fd9..b9d9c7d8993b08ed26863d35cec39c36d0837ac0
@@@ -32,6 -32,12 +32,12 @@@ import org.opendaylight.controller.sal.
  import org.opendaylight.ovsdb.lib.database.OVSInstance;
  import org.opendaylight.ovsdb.lib.database.OvsdbType;
  import org.opendaylight.ovsdb.lib.message.TransactBuilder;
 -import org.opendaylight.ovsdb.lib.message.operations.DeleteOperation;
 -import org.opendaylight.ovsdb.lib.message.operations.InsertOperation;
 -import org.opendaylight.ovsdb.lib.message.operations.MutateOperation;
 -import org.opendaylight.ovsdb.lib.message.operations.Operation;
 -import org.opendaylight.ovsdb.lib.message.operations.OperationResult;
 -import org.opendaylight.ovsdb.lib.message.operations.UpdateOperation;
++import org.opendaylight.ovsdb.lib.operations.DeleteOperation;
++import org.opendaylight.ovsdb.lib.operations.InsertOperation;
++import org.opendaylight.ovsdb.lib.operations.MutateOperation;
++import org.opendaylight.ovsdb.lib.operations.Operation;
++import org.opendaylight.ovsdb.lib.operations.OperationResult;
++import org.opendaylight.ovsdb.lib.operations.UpdateOperation;
  import org.opendaylight.ovsdb.lib.notation.Condition;
  import org.opendaylight.ovsdb.lib.notation.Function;
  import org.opendaylight.ovsdb.lib.notation.Mutation;
@@@ -39,14 -45,9 +45,9 @@@ import org.opendaylight.ovsdb.lib.notat
  import org.opendaylight.ovsdb.lib.notation.OvsDBMap;
  import org.opendaylight.ovsdb.lib.notation.OvsDBSet;
  import org.opendaylight.ovsdb.lib.notation.UUID;
- import org.opendaylight.ovsdb.lib.operations.DeleteOperation;
- import org.opendaylight.ovsdb.lib.operations.InsertOperation;
- import org.opendaylight.ovsdb.lib.operations.MutateOperation;
- import org.opendaylight.ovsdb.lib.operations.Operation;
- import org.opendaylight.ovsdb.lib.operations.OperationResult;
- import org.opendaylight.ovsdb.lib.operations.UpdateOperation;
  import org.opendaylight.ovsdb.lib.table.Bridge;
  import org.opendaylight.ovsdb.lib.table.Controller;
+ import org.opendaylight.ovsdb.lib.table.IPFIX;
  import org.opendaylight.ovsdb.lib.table.Interface;
  import org.opendaylight.ovsdb.lib.table.Manager;
  import org.opendaylight.ovsdb.lib.table.Mirror;
@@@ -57,7 -58,7 +58,7 @@@ import org.opendaylight.ovsdb.lib.table
  import org.opendaylight.ovsdb.lib.table.Queue;
  import org.opendaylight.ovsdb.lib.table.SFlow;
  import org.opendaylight.ovsdb.lib.table.SSL;
 -import org.opendaylight.ovsdb.lib.table.internal.Table;
 +import org.opendaylight.ovsdb.lib.table.Table;
  import org.osgi.framework.BundleContext;
  import org.osgi.framework.FrameworkUtil;
  import org.slf4j.Logger;
@@@ -266,7 -267,7 +267,7 @@@ public class ConfigurationService imple
       * Create a Port Attached to a Bridge
       * Ex. ovs-vsctl add-port br0 vif0
       * @param node Node serving this configuration service
-      * @param bridgeDomainIdentifier String representation of a Bridge Domain
+      * @param bridgeIdentifier String representation of a Bridge Domain
       * @param portIdentifier String representation of a user defined Port Name
       */
      @Override
       * Implements the OVS Connection for Managers
       *
       * @param node Node serving this configuration service
-      * @param managerip with IP and connection types
+      * @param managerip String Representing IP and connection types
       */
      @SuppressWarnings("unchecked")
      public boolean setManager(Node node, String managerip) {
              if (connection != null) {
                  String newmanager = "new_manager";
  
 -                OVSInstance instance = OVSInstance.monitorOVS(connection);
 +                OVSInstance instance = OVSInstance.monitorOVS();
  
                  Map ovsoutter = new LinkedHashMap();
                  Map ovsinner = new LinkedHashMap();
          else if (row.getTableName().getName().equalsIgnoreCase("sFlow")) {
              statusWithUUID = insertSflowRow(node, parent_uuid, (SFlow)row);
          }
+         else if (row.getTableName().getName().equalsIgnoreCase("IPFIX")) {
+             statusWithUUID = insertIpFixRow(node, parent_uuid, (IPFIX) row);
+         }
          else if (row.getTableName().getName().equalsIgnoreCase("SSL")) {
              statusWithUUID = insertSSLRow(node, parent_uuid, (SSL)row);
          }
          else if (tableName.equalsIgnoreCase("sFlow")) {
              return deleteSflowRow(node, uuid);
          }
+         else if (tableName.equalsIgnoreCase("IPFIX")) {
+             return deleteIpFixRow(node, uuid);
+         }
          else if (tableName.equalsIgnoreCase("SSL")) {
              return deleteSSLRow(node, uuid);
          }
          return new StatusWithUuid(StatusCode.INTERNALERROR);
      }
  
+         private StatusWithUuid insertIpFixRow(Node node, String parent_uuid, IPFIX row) {
+         String insertErrorMsg = "ipfix";
+         String rowName=row.NAME.getName();
+         try{
+             Map<String, Table<?>> brTable = inventoryServiceInternal.getTableCache(node, Bridge.NAME.getName());
+             if (brTable == null ||  brTable.get(parent_uuid) == null) {
+                 return new StatusWithUuid(StatusCode.NOTFOUND, "Bridge with UUID "+parent_uuid+" Not found");
+             }
+             if (parent_uuid == null) {
+                 return new StatusWithUuid(StatusCode.BADREQUEST, "Require parent Bridge UUID.");
+             }
+             UUID uuid = new UUID(parent_uuid);
+             String newIpFix = "new_ipfix";
+             Operation addBridgeRequest = null;
+             UUID ipfixUuid = new UUID(newIpFix);
+             Mutation ipfixMutation = new Mutation("ipfix", Mutator.INSERT, ipfixUuid);
+             List<Mutation> mutations = new ArrayList<Mutation>();
+             mutations.add(ipfixMutation);
+             Condition condition = new Condition("_uuid", Function.EQUALS, uuid);
+             List<Condition> where = new ArrayList<Condition>();
+             where.add(condition);
+             addBridgeRequest = new MutateOperation(Bridge.NAME.getName(), where, mutations);
+             InsertOperation addIpFixRequest = new InsertOperation(IPFIX.NAME.getName(), newIpFix, row);
+             TransactBuilder transaction = new TransactBuilder();
+             transaction.addOperations(
+                     new ArrayList<Operation>(Arrays.asList(addIpFixRequest,addBridgeRequest)));
+             int ipfixInsertIndex = transaction.getRequests().indexOf(addIpFixRequest);
+             return _insertTableRow(node,transaction,ipfixInsertIndex,insertErrorMsg,rowName);
+         } catch (Exception e) {
+             logger.error("Error in insertInterfaceRow(): ",e);
+         }
+         return new StatusWithUuid(StatusCode.INTERNALERROR);
+     }
      private StatusWithUuid insertSflowRow(Node node, String parent_uuid, SFlow row) {
  
          String insertErrorMsg = "sFlow";
          return _deleteTableRow(node,uuid,parentTableName,childTableName,parentColumn);
      }
  
+     private Status deleteIpFixRow(Node node, String uuid) {
+         // Set up variables for generic _deleteTableRow()
+         String parentTableName=Bridge.NAME.getName();
+         String childTableName=IPFIX.NAME.getName();
+         String parentColumn = "ipfix";
+         return _deleteTableRow(node,uuid,parentTableName,childTableName,parentColumn);
+     }
      private Status deleteQueueRow(Node node, String uuid) {
          // Set up variables for _deleteRootTableRow()
          // This doesn't do a mutate on parent, but simply deletes row
index a18592a2f48137ed95e03e5ebabcd4935baff279,ad7f71a5a24009099a9fc5830c03156a37ed04fa..534a94605cdcb393544991a12c664a83fd019616
@@@ -54,14 -54,14 +54,14 @@@ import org.opendaylight.ovsdb.lib.jsonr
  import org.opendaylight.ovsdb.lib.jsonrpc.JsonRpcServiceBinderHandler;
  import org.opendaylight.ovsdb.lib.message.MonitorRequestBuilder;
  import org.opendaylight.ovsdb.lib.message.OvsdbRPC;
 -import org.opendaylight.ovsdb.lib.message.TableUpdates;
 +import org.opendaylight.ovsdb.lib.message.temp.TableUpdates;
  import org.opendaylight.ovsdb.lib.message.UpdateNotification;
  import org.opendaylight.ovsdb.lib.notation.OvsDBSet;
  import org.opendaylight.ovsdb.lib.table.Bridge;
  import org.opendaylight.ovsdb.lib.table.Controller;
  import org.opendaylight.ovsdb.lib.table.Open_vSwitch;
 -import org.opendaylight.ovsdb.lib.table.internal.Table;
 -import org.opendaylight.ovsdb.lib.table.internal.Tables;
 +import org.opendaylight.ovsdb.lib.table.Table;
 +import org.opendaylight.ovsdb.lib.table.Tables;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  
@@@ -256,7 -256,7 +256,7 @@@ public class ConnectionService implemen
  
          JsonRpcEndpoint factory = new JsonRpcEndpoint(objectMapper, channel);
          JsonRpcServiceBinderHandler binderHandler = new JsonRpcServiceBinderHandler(factory);
 -        binderHandler.setNode(node);
 +        binderHandler.setContext(node);
          channel.pipeline().addLast(binderHandler);
  
          OvsdbRPC ovsdb = factory.getClient(node, OvsdbRPC.class);
          inventoryServiceInternal.addNode(connection.getNode(), props);
  
          List<String> dbNames = Arrays.asList(Open_vSwitch.NAME.getName());
-         ListenableFuture<DatabaseSchema> dbSchemaF = null;//todo : fix it up to new structue : connection.getRpc().get_schema(dbNames);
 -        ListenableFuture<DatabaseSchema> dbSchemaF = connection.getRpc().get_schema(dbNames);
++        ListenableFuture<DatabaseSchema> dbSchemaF = null;//TODO : fix it up to new structue : connection.getRpc().get_schema(dbNames);
          DatabaseSchema databaseSchema = dbSchemaF.get();
          inventoryServiceInternal.updateDatabaseSchema(connection.getNode(), databaseSchema);
  
 -        MonitorRequestBuilder monitorReq = new MonitorRequestBuilder();
 +        MonitorRequestBuilder monitorReq = null; //ashwin(not sure if we need) : new MonitorRequestBuilder();
          for (Table<?> table : Tables.getTables()) {
              if (databaseSchema.getTables().keySet().contains(table.getTableName().getName())) {
 -                monitorReq.monitor(table);
 +                //ashwin(not sure if we need) monitorReq.monitor(table);
              } else {
                  logger.debug("We know about table {} but it is not in the schema of {}", table.getTableName().getName(), connection.getNode().getNodeIDString());
              }
          }
  
-         ListenableFuture<TableUpdates> monResponse = null; //ashwin(not sure if we need)connection.getRpc().monitor(monitorReq);
 -        ListenableFuture<TableUpdates> monResponse = connection.getRpc().monitor(monitorReq);
++        ListenableFuture<TableUpdates> monResponse = null; //TODO : ashwin(not sure if we need)connection.getRpc().monitor(monitorReq);
          TableUpdates updates = monResponse.get();
          if (updates.getError() != null) {
              logger.error("Error configuring monitor, error : {}, details : {}",
      }
  
      @Override
 -    public void update(Node node, UpdateNotification updateNotification) {
 +    public void update(Object context, UpdateNotification updateNotification) {
          if (updateNotification == null) return;
 -        inventoryServiceInternal.processTableUpdates(node, updateNotification.getUpdate());
 +        inventoryServiceInternal.processTableUpdates((Node)context, updateNotification.getUpdate());
      }
  
      @Override
 -    public void locked(Node node, List<String> ids) {
 +    public void locked(Object context, List<String> ids) {
          // TODO Auto-generated method stub
      }
  
      @Override
 -    public void stolen(Node node, List<String> ids) {
 +    public void stolen(Object context, List<String> ids) {
          // TODO Auto-generated method stub
      }
--
  }
index b987efc111207d818b3245127dab4b680f6cc7c1,a1bac127bc6ef6cf3ff19530f56d85584dbe0348..28ae17b68b4f4b4c3659f471e1dc45ed3cad5a4a
@@@ -33,12 -33,12 +33,12 @@@ import org.opendaylight.controller.sal.
  import org.opendaylight.controller.sal.utils.HexEncode;
  import org.opendaylight.controller.sal.utils.ServiceHelper;
  import org.opendaylight.ovsdb.lib.database.DatabaseSchema;
 -import org.opendaylight.ovsdb.lib.message.TableUpdate;
 -import org.opendaylight.ovsdb.lib.message.TableUpdate.Row;
 -import org.opendaylight.ovsdb.lib.message.TableUpdates;
 +import org.opendaylight.ovsdb.lib.message.temp.TableUpdate;
 +import org.opendaylight.ovsdb.lib.message.temp.TableUpdate.Row;
 +import org.opendaylight.ovsdb.lib.message.temp.TableUpdates;
  import org.opendaylight.ovsdb.lib.notation.OvsDBSet;
  import org.opendaylight.ovsdb.lib.table.Bridge;
 -import org.opendaylight.ovsdb.lib.table.internal.Table;
 +import org.opendaylight.ovsdb.lib.table.Table;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  
@@@ -199,7 -199,7 +199,7 @@@ public class InventoryService implement
                      }
                  } else if (oldRow != null) {
                      if (inventoryListener != null) {
-                         inventoryListener.rowRemoved(n, name.getName(), uuid, oldRow);
+                         inventoryListener.rowRemoved(n, name.getName(), uuid, oldRow, null);
                      }
                      db.removeRow(name.getName(), uuid);
                  }
index 822da35ba606a7519a6891625ce81f6939c50d34,e0bdc1e4c135399d3a0cc3927d988a8e3e9edcb5..87c6ead0466f236c025ce7dce22511bacd07a9f0
  package org.opendaylight.ovsdb.plugin;
  
  import org.opendaylight.controller.sal.core.Node;
 -import org.opendaylight.ovsdb.lib.table.internal.Table;
 +import org.opendaylight.ovsdb.lib.table.Table;
  
  public interface OVSDBInventoryListener {
      public void nodeAdded(Node node);
      public void nodeRemoved(Node node);
      public void rowAdded(Node node, String tableName, String uuid, Table<?> row);
      public void rowUpdated(Node node, String tableName, String uuid, Table<?> old, Table<?> row);
-     public void rowRemoved(Node node, String tableName, String uuid, Table<?> row);
+     public void rowRemoved(Node node, String tableName, String uuid, Table<?> row, Object context);
  }
index f58b19b41df6d4c62546f24f29ea0d9441486123,53540804d766a195c82d9f54497b873dd892b984..53540804d766a195c82d9f54497b873dd892b984
@@@ -33,7 -33,7 +33,7 @@@ public class OvsdbTestAddBridgeIT exten
           */\r
          ConfigurationService configurationService = new ConfigurationService();\r
          configurationService.setConnectionServiceInternal(connectionService);\r
-         configurationService.createBridgeDomain(node, "JUNIT_BRIDGE_TEST", null);\r
+         configurationService.createBridgeDomain(node, BRIDGE_NAME, null);\r
      }\r
  \r
  }\r
index adafe4c5c9a452b0449cbc2a675b281aa601550d,c9f089946a63a430337d29633e6a315d93c69315..c9f089946a63a430337d29633e6a315d93c69315
@@@ -43,6 -43,6 +43,6 @@@ public class OvsdbTestAddPortIT extend
           */
          ConfigurationService configurationService = new ConfigurationService();
          configurationService.setConnectionServiceInternal(connectionService);
-         configurationService.addPort(node, "JUNIT_BRIDGE_TEST", "Jvif0", null);
+         configurationService.addPort(node, BRIDGE_NAME, PORT_NAME, null);
      }
  }
index 0c38f31cc5c1d0d09bf59c9f71936afef194be58,32029ba8ad21c4ccd58b7805a4d0ba69a8f5ea4c..32029ba8ad21c4ccd58b7805a4d0ba69a8f5ea4c
@@@ -41,7 -41,7 +41,7 @@@ public class OvsdbTestAddTunnelIT exten
  
          Encapsulation encap = Encapsulation.VXLAN;
          String tunencap = encap.toString();
-         String tunnelendpoint = "192.168.100.100";
+         String tunnelendpoint = FAKE_IP;
  
          /**
           * Create an Encapsulated Tunnel Interface and destination Tunnel Endpoint
@@@ -62,7 -62,7 +62,7 @@@
          configs.put(ConfigConstants.TUNNEL_TYPE, tunencap);
          configs.put(ConfigConstants.DEST_IP, tunnelendpoint);
  
-         configurationService.addPort(node, "JUNIT_BRIDGE_TEST", "Jtunnel0", configs);
+         configurationService.addPort(node, BRIDGE_NAME, TUNNEL_PORT_NAME, configs);
  
      }
  }
index ee66acde9278b4e47661c51deec83acd7480468f,496a976796eb4aa19bfdf76dbf71feefa3ad8d62..496a976796eb4aa19bfdf76dbf71feefa3ad8d62
@@@ -44,6 -44,6 +44,6 @@@ public class OvsdbTestAddVlanIT extend
          Map<ConfigConstants, Object> configs = new HashMap<ConfigConstants, Object>();
          configs.put(ConfigConstants.TYPE, "VLAN");
          configs.put(ConfigConstants.VLAN, vlanid+"");
-         configurationService.addPort(node, "JUNIT_BRIDGE_TEST", "Jtagvif0", configs);
+         configurationService.addPort(node, BRIDGE_NAME, TAGGED_PORT_NAME, configs);
      }
  }
index 18d929a6ce0941ae28a04fc7191e677e7730b4e8,3bdbefbcc300cba31d031f2af516c0aaeafdd29c..e9644dbcd81683422c10408f2e1559be3dd31bca
  package org.opendaylight.ovsdb.plugin;
  
  import java.io.IOException;
 -import java.io.InputStream;
  import java.util.HashMap;
  import java.util.Map;
  import java.util.Properties;
  
 +import junit.framework.Assert;
 +
  import org.opendaylight.controller.sal.connection.ConnectionConstants;
  import org.opendaylight.controller.sal.core.Node;
  import org.opendaylight.controller.sal.core.NodeConnector;
  
  public abstract class OvsdbTestBase {
      private final static String identifier = "TEST";
+     protected final static String BRIDGE_NAME = "JUNIT_TEST_BRIDGE";
+     protected final static String PORT_NAME = "eth0";
+     protected final static String TAGGED_PORT_NAME = "eth1";
+     protected final static String TUNNEL_PORT_NAME = "vxlan0";
+     protected final static String FAKE_IP = "192.168.254.254";
 +    private final static String SERVER_IPADDRESS = "ovsdbserver.ipaddress";
 +    private final static String SERVER_PORT = "ovsdbserver.port";
 +    private final static String DEFAULT_SERVER_PORT = "6640";
  
      public Properties loadProperties() throws IOException {
 -        InputStream is = this
 -                .getClass()
 -                .getClassLoader()
 -                .getResourceAsStream(
 -                        "org/opendaylight/ovsdb/lib/message/integration-test.properties");
 -        if (is == null) {
 -            throw new IOException("Unable to load integration-test.properties");
 -        }
 -        Properties props = new Properties();
 -        props.load(is);
 -
 +        Properties props = new Properties(System.getProperties());
          return props;
      }
  
      public class TestObjects {
          public final ConnectionService connectionService;
+         public final InventoryService inventoryService;
          public final Node node;
  
-         public TestObjects(ConnectionService connectionService, Node node) {
+         public TestObjects(ConnectionService connectionService, Node node, InventoryService inventoryService) {
              this.connectionService = connectionService;
+             this.inventoryService = inventoryService;
              this.node = node;
          }
      }
  
      public TestObjects getTestConnection() throws IOException {
 +        Properties props = loadProperties();
 +        String address = props.getProperty(SERVER_IPADDRESS);
 +        String port = props.getProperty(SERVER_PORT, DEFAULT_SERVER_PORT);
 +
 +        if (address == null) {
 +            Assert.fail("Usage : mvn -Pintegrationtest -Dovsdbserver.ipaddress=x.x.x.x -Dovsdbserver.port=yyyy verify");
 +        }
 +
          Node.NodeIDType.registerIDType("OVS", String.class);
          NodeConnector.NodeConnectorIDType.registerIDType("OVS", String.class,
                  "OVS");
 +        InventoryService inventoryService = new InventoryService();
 +        inventoryService.init();
  
          ConnectionService connectionService = new ConnectionService();
          connectionService.init();
-         connectionService.setInventoryServiceInternal(inventoryService);
+         InventoryService inventory = new InventoryService();
+         inventory.init();
+         connectionService.setInventoryServiceInternal(inventory);
          Map<ConnectionConstants, String> params = new HashMap<ConnectionConstants, String>();
 -        Properties props = loadProperties();
 -        params.put(ConnectionConstants.ADDRESS,
 -                props.getProperty("ovsdbserver.ipaddress"));
 -        params.put(ConnectionConstants.PORT,
 -                props.getProperty("ovsdbserver.port", "6640"));
 +
 +        params.put(ConnectionConstants.ADDRESS, address);
 +        params.put(ConnectionConstants.PORT, port);
  
          Node node = connectionService.connect(identifier, params);
          if (node == null) {
-             throw new IOException("Failed to connecto to ovsdb server");
+             throw new IOException("Failed to connect to the ovsdb server");
          }
-         return new TestObjects(connectionService, node);
+         return new TestObjects(connectionService, node, inventory);
      }
  
  }
index bc0eb13603871d7bbb81de9f1eac673608393a1d,d8891f91e65307ff7b0354b2e68cc36f957bfbe1..d8891f91e65307ff7b0354b2e68cc36f957bfbe1
@@@ -31,13 -31,13 +31,13 @@@ public class OvsdbTestBridgeConfigIT ex
          Map<ConfigConstants, Object> configs = new HashMap<ConfigConstants, Object>();
  
          Map<String, String> exterIDPairs = new HashMap<String, String>();
-         exterIDPairs.put("bridge-foo", "bri-bar");
+         exterIDPairs.put("br-foo", "br-bar");
          //Will accept multiple array pairs. Pairs must be arrays not maps.
          configs.put(ConfigConstants.CUSTOM, exterIDPairs);
  
          ConfigurationService configurationService = new ConfigurationService();
          configurationService.setConnectionServiceInternal(connectionService);
-         configurationService.addBridgeDomainConfig(node, "br0", configs);
+         configurationService.addBridgeDomainConfig(node, BRIDGE_NAME, configs);
      }
  
  }
index d83432b6fa254a8004faad2fc00c464af6ad9285,c52d60751fe9176259e287d6fdf418aee1ba600a..3fd246d3134e535f4a05d10d2c868499163ee569
@@@ -9,6 -9,10 +9,6 @@@
   */
  package org.opendaylight.ovsdb.plugin;
  
 -import java.io.IOException;
 -import java.util.Properties;
 -
 -import org.junit.Before;
  import org.junit.Test;
  import org.opendaylight.controller.sal.core.Node;
  import org.slf4j.Logger;
@@@ -18,21 -22,22 +18,21 @@@ public class OvsdbTestDeletePortIT exte
      private static final Logger logger = LoggerFactory
              .getLogger(OvsdbTestAddPortIT.class);
  
 -    private Properties props;
 -
 -    @Before
 -    public void loadProps() throws IOException {
 -        props = loadProperties();
 -    }
 -
      @Test
      public void deletePort() throws Throwable{
          TestObjects testObjects = getTestConnection();
          ConnectionService connectionService = testObjects.connectionService;
          Node node = testObjects.node;
  
 -
 +        /**
 +         * Deletes an existing port from an existing bridge
 +         * Ex. ovs-vsctl del-port ovsbr0 tap0
 +         * @param node Node serving this configuration service
 +         * @param bridgeDomainIdentifier String representation of a Bridge Domain
 +         * @param portIdentifier String representation of a user defined Port Name
 +         */
          ConfigurationService configurationService = new ConfigurationService();
          configurationService.setConnectionServiceInternal(connectionService);
-         configurationService.deletePort(node, "ovsbr0", "tap2");
+         configurationService.deletePort(node, BRIDGE_NAME, PORT_NAME);
      }
  }
index de1e370ff198d5ec25fd960f680fdf789ba62c5c,0d78f847bf88359877210d553a18184b9234a7d0..0d78f847bf88359877210d553a18184b9234a7d0
@@@ -9,8 -9,11 +9,11 @@@
   */
  package org.opendaylight.ovsdb.plugin;
  
+ import java.io.IOException;
  import java.util.List;
+ import java.util.Properties;
  
+ import org.junit.Before;
  import org.junit.Test;
  import org.opendaylight.controller.sal.core.Node;
  import org.slf4j.Logger;
@@@ -20,11 -23,19 +23,19 @@@ public class OvsdbTestGetBridgeDomainsI
      private static final Logger logger = LoggerFactory
              .getLogger(OvsdbTestGetBridgeDomainsIT.class);
  
+     private Properties props;
+     @Before
+     public void loadProps() throws IOException {
+         props = loadProperties();
+     }
      @Test
      public void getBridgeDomains() throws Throwable{
  
          TestObjects testObjects = getTestConnection();
          ConnectionService connectionService = testObjects.connectionService;
+         InventoryService inventoryService = testObjects.inventoryService;
          Node node = testObjects.node;
  
          /**
@@@ -35,7 -46,7 +46,7 @@@
           */
          ConfigurationService configurationService = new ConfigurationService();
          configurationService.setConnectionServiceInternal(connectionService);
+         configurationService.setInventoryServiceInternal(inventoryService);
          List<String> ls = configurationService.getBridgeDomains(node);
-         System.out.println(ls);
      }
  }
index cdff94ef81daeb41d253e0c85048b6197fb4fedd,4dba778569926ce76bb022db9e2584ceafc56765..4dba778569926ce76bb022db9e2584ceafc56765
@@@ -24,6 -24,13 +24,13 @@@ public class OvsdbTestSetManagerIT exte
          ConnectionService connectionService = testObjects.connectionService;\r
          Node node = testObjects.node;\r
  \r
\r
+         String port = "6634";\r
+         String host = FAKE_IP;\r
+         String connectionType = "ptcp";\r
\r
+         String manager = connectionType + ":" + host + ":" + port;\r
\r
          /**\r
           * Implements the OVS Connection for Managers\r
           *\r
@@@ -33,7 -40,7 +40,7 @@@
           */\r
          ConfigurationService configurationService = new ConfigurationService();\r
          configurationService.setConnectionServiceInternal(connectionService);\r
-         configurationService.setManager(node, "ptcp:6634:172.16.58.128");\r
+         configurationService.setManager(node, manager);\r
      }\r
  \r
  }\r
index 763414d53c5a6683cb81a50f46a45d66c6c160bb,e7d9737cd8882637790091d2ea806e7c2362ba6c..e7d9737cd8882637790091d2ea806e7c2362ba6c
@@@ -33,7 -33,7 +33,7 @@@ public class OvsdbTestSetOFControllerI
          configs.put(ConfigConstants.CUSTOM, "6633");
          ConfigurationService configurationService = new ConfigurationService();
          configurationService.setConnectionServiceInternal(connectionService);
-         configurationService.setBridgeOFController(node, "br0");
+         configurationService.setBridgeOFController(node, BRIDGE_NAME);
  
      }
  }