OVSDB Neutron & OpenFlow 1.3 integration 70/4470/1
authorMadhu Venugopal <mavenugo@gmail.com>
Tue, 21 Jan 2014 05:24:24 +0000 (21:24 -0800)
committerMadhu Venugopal <mavenugo@gmail.com>
Tue, 21 Jan 2014 05:24:24 +0000 (21:24 -0800)
This commit brings in a major portion of OVSDB Neutron & Openflow1.3 integration pieces & is
built on top of Brent's OF1.3 work.

Change-Id: Ic0edef2d52175aad873759513d20f42efc8dc23c
Signed-off-by: Madhu Venugopal <mavenugo@gmail.com>
neutron/src/main/java/org/opendaylight/ovsdb/neutron/InternalNetworkManager.java
neutron/src/main/java/org/opendaylight/ovsdb/neutron/PortHandler.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/OF10ProviderManager.java
neutron/src/main/java/org/opendaylight/ovsdb/neutron/provider/OF13ProviderManager.java
neutron/src/main/java/org/opendaylight/ovsdb/neutron/provider/ProviderNetworkManager.java

index b11ada9353fb2b8fafa3c249b9bce947d2a6edab..5122344a2975282b0f87f6466c61bec95f23772c 100644 (file)
@@ -137,8 +137,8 @@ public class InternalNetworkManager {
         OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
 
         String bridgeUUID = this.getInternalBridgeUUID(node, bridgeName);
+        Bridge bridge = new Bridge();
         if (bridgeUUID == null) {
-            Bridge bridge = new Bridge();
             bridge.setName(bridgeName);
             if (!ProviderNetworkManager.getManager().hasPerTenantTunneling()) {
                 OvsDBSet<String> protocols = new OvsDBSet<String>();
@@ -152,6 +152,11 @@ public class InternalNetworkManager {
             Port port = new Port();
             port.setName(bridgeName);
             ovsdbTable.insertRow(node, Port.NAME.getName(), bridgeUUID, port);
+        } else if (!ProviderNetworkManager.getManager().hasPerTenantTunneling()) {
+            OvsDBSet<String> protocols = new OvsDBSet<String>();
+            protocols.add("OpenFlow13");
+            bridge.setProtocols(protocols);
+            ovsdbTable.updateRow(node, Bridge.NAME.getName(), null, bridgeUUID, bridge);
         }
 
         IConnectionServiceInternal connectionService = (IConnectionServiceInternal)ServiceHelper.getGlobalInstance(IConnectionServiceInternal.class, this);
index 538912e21bbf7674150bdeb093c2ecb9b7a70e3b..dc558716053aa46303cfe49ba40186d449f0bfb7 100644 (file)
@@ -65,7 +65,7 @@ public class PortHandler extends BaseHandler
          * The Tunnel Creation logic is completely owned by the Southbound handler at this point.
 
         NeutronNetwork network = this.neutronNetworkCache.getNetwork(port.getNetworkUUID());
-        ProviderNetworkManager.getManager().createTunnels(network.getProviderNetworkType(),
+        ProviderNetworkManager.getManager().handleInterfaceUpdate(network.getProviderNetworkType(),
                                                           network.getProviderSegmentationID());
          */
         logger.debug(" Port-ADD successful for tenant-id - {}," +
index 23fe8f9aae77710a110f4bf93b077ca234636705..d9b20c6f897173c63265471bb1a0acf66fd4fec0 100644 (file)
@@ -164,14 +164,16 @@ public class SouthboundHandler extends BaseHandler implements OVSDBInventoryList
             Interface intf = (Interface)row;
             NeutronNetwork network = TenantNetworkManager.getManager().getTenantNetworkForInterface(intf);
             if (network != null && !network.getRouterExternal()) {
-                int vlan = TenantNetworkManager.getManager().networkCreated(network.getID());
-                logger.trace("Neutron Network {} Created with Internal Vlan : {}", network.toString(), vlan);
+                if (ProviderNetworkManager.getManager().hasPerTenantTunneling()) {
+                    int vlan = TenantNetworkManager.getManager().networkCreated(network.getID());
+                    logger.trace("Neutron Network {} Created with Internal Vlan : {}", network.toString(), vlan);
 
-                String portUUID = this.getPortIdForInterface(node, uuid, intf);
-                if (portUUID != null) {
-                    TenantNetworkManager.getManager().programTenantNetworkInternalVlan(node, portUUID, network);
+                    String portUUID = this.getPortIdForInterface(node, uuid, intf);
+                    if (portUUID != null) {
+                        TenantNetworkManager.getManager().programTenantNetworkInternalVlan(node, portUUID, network);
+                    }
                 }
-                this.createTunnels(node, uuid, intf);
+                this.handleInterfaceUpdate(node, uuid, intf);
             }
         } else if (Port.NAME.getName().equalsIgnoreCase(tableName)) {
             logger.debug("{} Added / Updated {} , {}, {}", tableName, node, uuid, row);
@@ -197,7 +199,7 @@ public class SouthboundHandler extends BaseHandler implements OVSDBInventoryList
                 if (interfaces != null) {
                     for (String intfUUID : interfaces.keySet()) {
                         Interface intf = (Interface) interfaces.get(intfUUID);
-                        createTunnels(node, intfUUID, intf);
+                        this.handleInterfaceUpdate(node, intfUUID, intf);
                     }
                 }
             } catch (Exception e) {
@@ -206,14 +208,14 @@ public class SouthboundHandler extends BaseHandler implements OVSDBInventoryList
         }
     }
 
-    private void createTunnels (Node node, String uuid, Interface intf) {
+    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);
         if (network != null) {
-            ProviderNetworkManager.getManager().createTunnels(network.getProviderNetworkType(),
+            ProviderNetworkManager.getManager().handleInterfaceUpdate(network.getProviderNetworkType(),
                     network.getProviderSegmentationID(), node, intf);
         }
     }
index 10f8e24847c2d4f16abab15d5312ba87c7531d2d..2cc0f94fb8f2a6b6393ebc757c751fa556eb2daf 100644 (file)
@@ -36,6 +36,7 @@ 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.neutron.provider.ProviderNetworkManager;
 import org.opendaylight.ovsdb.plugin.OVSDBConfigService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -116,10 +117,12 @@ public class TenantNetworkManager {
             logger.debug("Tenant Network not found with Segmenation-id {}",segmentationId);
             return false;
         }
-        int internalVlan = this.getInternalVlan(networkId);
-        if (internalVlan == 0) {
-            logger.debug("No InternalVlan provisioned for Tenant Network {}",networkId);
-            return false;
+        if (ProviderNetworkManager.getManager().hasPerTenantTunneling()) {
+            int internalVlan = this.getInternalVlan(networkId);
+            if (internalVlan == 0) {
+                logger.debug("No InternalVlan provisioned for Tenant Network {}",networkId);
+                return false;
+            }
         }
         OVSDBConfigService ovsdbTable = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
         try {
index dc2d339a331fdd4dc70e7a017558d9f904f7fb03..016d2aeb6d99d20fee92275ae8c22fe5adcf5f59 100644 (file)
@@ -289,7 +289,7 @@ class OF10ProviderManager extends ProviderNetworkManager {
     }
 
     @Override
-    public Status createTunnels(String tunnelType, String tunnelKey, Node srcNode, Interface intf) {
+    public Status handleInterfaceUpdate(String tunnelType, String tunnelKey, Node srcNode, Interface intf) {
         Status status = getTunnelReadinessStatus(srcNode, tunnelKey);
         if (!status.isSuccess()) return status;
 
@@ -422,11 +422,11 @@ class OF10ProviderManager extends ProviderNetworkManager {
     }
 
     @Override
-    public Status createTunnels(String tunnelType, String tunnelKey) {
+    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.createTunnels(tunnelType, tunnelKey, srcNode, null);
+            this.handleInterfaceUpdate(tunnelType, tunnelKey, srcNode, null);
         }
         return new Status(StatusCode.SUCCESS);
     }
index 10ae0dd05538e1c3fed5e2a56af0ca192766cc98..03dea2c47893a2c4c4ebd1bb8b500b6800aa629e 100644 (file)
 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 org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.UdpMatchBuilder;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 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.sal.binding.api.data.DataBrokerService;
@@ -25,13 +25,23 @@ 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.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.AdminConfigManager;
 import org.opendaylight.ovsdb.neutron.IMDSALConsumer;
+import org.opendaylight.ovsdb.neutron.InternalNetworkManager;
+import org.opendaylight.ovsdb.neutron.TenantNetworkManager;
+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;
@@ -45,21 +55,46 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.acti
 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.output.action._case.OutputActionBuilder;
 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.action.strip.vlan.action._case.StripVlanAction;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.strip.vlan.action._case.StripVlanActionBuilder;
+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.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.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.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;
@@ -67,32 +102,14 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026
 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.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
-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.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.common.RpcResult;
-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.FlowCapableNode;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
-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.ethernet.match.fields.EthernetTypeBuilder;
-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.list.Action;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 
 /**
  *
@@ -100,20 +117,316 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.ta
 class OF13ProviderManager extends ProviderNetworkManager {
     private static final Logger logger = LoggerFactory.getLogger(OF13ProviderManager.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;
 
     @Override
     public boolean hasPerTenantTunneling() {
         return false;
     }
 
+    private Status getTunnelReadinessStatus (Node node, String tunnelKey) {
+        InetAddress srcTunnelEndPoint = AdminConfigManager.getManager().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().isInternalNetworkNeutronReady(node)) {
+            logger.error(node+" is not Overlay ready");
+            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);
+        }
+        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 Status addTunnelPort (Node node, String tunnelType, InetAddress src, InetAddress dst) {
+        try {
+            String bridgeUUID = null;
+            String tunnelBridgeName = AdminConfigManager.getManager().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());
+            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);
+        }
+    }
+
+    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 (10)
+         */
+
+         writeTunnelIn(dpid, TABLE_0_DEFAULT_INGRESS, TABLE_2_LOCAL_FORWARD, segmentationId, tunnelOFPort);
+
+         /*
+         * Table(0) Rule #3
+         * ----------------
+         * Match: VM sMac and Local Ingress Port
+         * Action:Action: Set Tunnel ID and GOTO Local Table (5)
+         */
+
+         writeLocalInPort(dpid, TABLE_0_DEFAULT_INGRESS, TABLE_1_ISOLATE_TENANT, segmentationId, localPort, attachedMac);
+
+        /*
+         * Table(0) Rule #4
+         * ----------------
+         * Match: Drop any remaining Ingress Local VM Packets
+         * Action: Drop w/ a low priority
+         */
+
+         writeDropSrcIface(dpid, localPort);
+    }
+
+    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
+         */
+
+        writeTunnelOut(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD, segmentationId, tunnelOFPort, attachedMac);
+
+        /*
+         * 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
+         */
+
+        writeTunnelFloodOut(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD, segmentationId, tunnelOFPort);
+
+        /*
+         * 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
+         */
+
+         writeLocalUcastOut(dpid, TABLE_2_LOCAL_FORWARD, segmentationId, localPort, attachedMac);
+
+        /*
+         * 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
+         */
+
+         writeLocalBcastOut(dpid, TABLE_2_LOCAL_FORWARD, segmentationId, localPort);
+    }
+
+    private void programFloodEgressTunnelBridgeRules(Long dpid, String segmentationId) {
+        /*
+         * 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
+         */
+
+         writeTunnelMiss(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD, segmentationId);
+
+        /*
+         * 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
+         */
+
+         writeLocalTableMiss(dpid, TABLE_2_LOCAL_FORWARD, segmentationId);
+    }
+
+    private void programTunnelRules (String tunnelType, String segmentationId, InetAddress dst, Node node,
+            Interface intf, boolean local) {
+        try {
+
+            String bridgeName = AdminConfigManager.getManager().getIntegrationBridgeName();
+            String brIntId = this.getInternalBridgeUUID(node, bridgeName);
+            if (brIntId == null) {
+                logger.error("Unable to spot Bridge Identifier for {} in {}", bridgeName, node);
+                return;
+            }
+
+            OVSDBConfigService ovsdbTable = (OVSDBConfigService) ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
+            Bridge bridge = (Bridge) ovsdbTable.getRow(node, Bridge.NAME.getName(), brIntId);
+            Set<String> dpids = bridge.getDatapath_id();
+            if (dpids == null || dpids.size() == 0) return;
+            Long dpid = Long.valueOf(HexEncode.stringToLong((String) dpids.toArray()[0]));
+
+            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(TenantNetworkManager.EXTERNAL_ID_VM_MAC);
+            if (attachedMac == null) {
+                logger.error("No AttachedMac seen in {}", intf);
+                return;
+            }
+
+            Map<String, org.opendaylight.ovsdb.lib.table.internal.Table<?>> intfs = ovsdbTable.getRows(node, Interface.NAME.getName());
+            if (intfs != null) {
+                for (org.opendaylight.ovsdb.lib.table.internal.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);
+                        }
+                        programLocalIngressTunnelBridgeRules(node, dpid, segmentationId, attachedMac, tunnelOFPort, localPort);
+                        programFloodEgressTunnelBridgeRules(dpid, segmentationId);
+                        return;
+                    }
+                }
+            }
+        } catch (Exception e) {
+            logger.error("", e);
+        }
+    }
+
     @Override
-    public Status createTunnels(String tunnelType, String tunnelKey, Node source, Interface intf) {
-        // TODO Auto-generated method stub
-        return null;
+    public Status handleInterfaceUpdate(String tunnelType, String tunnelKey, Node srcNode, Interface intf) {
+        Status status = getTunnelReadinessStatus(srcNode, tunnelKey);
+        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, tunnelKey);
+            if (!status.isSuccess()) continue;
+            InetAddress src = AdminConfigManager.getManager().getTunnelEndPoint(srcNode);
+            InetAddress dst = AdminConfigManager.getManager().getTunnelEndPoint(dstNode);
+            status = addTunnelPort(srcNode, tunnelType, src, dst);
+            if (status.isSuccess()) {
+                this.programTunnelRules(tunnelType, tunnelKey, dst, srcNode, intf, true);
+            }
+            addTunnelPort(dstNode, tunnelType, dst, src);
+            if (status.isSuccess()) {
+                this.programTunnelRules(tunnelType, tunnelKey, src, dstNode, intf, false);
+            }
+        }
+        return new Status(StatusCode.SUCCESS);
     }
 
     @Override
-    public Status createTunnels(String tunnelType, String tunnelKey) {
+    public Status handleInterfaceUpdate(String tunnelType, String tunnelKey) {
         // TODO Auto-generated method stub
         return null;
     }
@@ -133,7 +446,7 @@ class OF13ProviderManager extends ProviderNetworkManager {
             // TODO : 3 second sleep hack is to make sure the OF connection is established.
             // Correct fix is to check the MD-SAL inventory before proceeding and listen
             // to Inventory update for processing.
-            Thread.sleep(5000);
+            Thread.sleep(3000);
         } catch (Exception e) {
             e.printStackTrace();
         }
@@ -148,13 +461,522 @@ class OF13ProviderManager extends ProviderNetworkManager {
             Bridge bridge = (Bridge) ovsdbTable.getRow(node, Bridge.NAME.getName(), brIntId);
             Set<String> dpids = bridge.getDatapath_id();
             if (dpids == null || dpids.size() == 0) return;
-            Long dpidLong = Long.valueOf(HexEncode.stringToLong((String) dpids.toArray()[0]));
+            Long dpid = Long.valueOf(HexEncode.stringToLong((String) dpids.toArray()[0]));
+
+            /*
+             * Table(0) Rule #1
+             * ----------------
+             * Match: LLDP (0x88CCL)
+             * Action: Packet_In to Controller Reserved Port
+             */
 
+             writeLLDPRule(dpid);
         } catch (Exception e) {
-            logger.error("Failed to initialize Flow Rules for " + node.toString(), e);
+            logger.error("Failed to initialize Flow Rules for " + node.toString()+ " Bridge "+bridgeName, e);
         }
     }
 
+    /*
+    * 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);
+        instructions.add(ib.build());
+
+        // Add InstructionBuilder to the Instruction(s)Builder List
+        isb.setInstruction(instructions);
+
+        // Add InstructionsBuilder to FlowBuilder
+        flowBuilder.setInstructions(isb.build());
+
+        flowBuilder.setId(new FlowId("10"));
+        FlowKey key = new FlowKey(new FlowId(String.valueOf((long) 110)));
+        flowBuilder.setBarrier(true);
+        flowBuilder.setTableId((short) 0);
+        flowBuilder.setKey(key);
+        flowBuilder.setFlowName("LLDP_" + nodeName);
+        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 writeTunnelIn(Long dpidLong, Short writeTable, Short goToTableId, String segmentationId,  Long ofPort) {
+
+        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());
+
+        // 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);
+        instructions.add(ib.build());
+
+        // Add InstructionBuilder to the Instruction(s)Builder List
+        isb.setInstruction(instructions);
+
+        // Add InstructionsBuilder to FlowBuilder
+        flowBuilder.setInstructions(isb.build());
+
+        // Add Flow Attributes
+        flowBuilder.setId(new FlowId("20"));
+        FlowKey key = new FlowKey(new FlowId(String.valueOf((long) 120)));
+        flowBuilder.setBarrier(false);
+        flowBuilder.setTableId(writeTable);
+        flowBuilder.setKey(key);
+        flowBuilder.setFlowName("TUNIN_" + nodeName);
+        flowBuilder.setHardTimeout(0);
+        flowBuilder.setIdleTimeout(0);
+        writeFlow(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 writeLocalInPort(Long dpidLong, Short writeTable, Short goToTableId, String segmentationId, Long inPort, String attachedMac) {
+
+        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());
+
+        // 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);
+        instructions.add(ib.build());
+        // TODO Broken SetTunID
+        createSetTunnelIdInstructions(ib, new BigInteger(segmentationId));
+        instructions.add(ib.build());
+
+        // Add InstructionBuilder to the Instruction(s)Builder List
+        isb.setInstruction(instructions);
+
+        // Add InstructionsBuilder to FlowBuilder
+        flowBuilder.setInstructions(isb.build());
+
+        // Add Flow Attributes
+        flowBuilder.setId(new FlowId("30"));
+        FlowKey key = new FlowKey(new FlowId(String.valueOf((long) 130)));
+        flowBuilder.setBarrier(false);
+        flowBuilder.setTableId(writeTable);
+        flowBuilder.setKey(key);
+        flowBuilder.setFlowName("LOCALSMAC_" + nodeName);
+        flowBuilder.setHardTimeout(0);
+        flowBuilder.setIdleTimeout(0);
+        writeFlow(flowBuilder, nodeBuilder);
+    }
+
+    /*
+     * (Table:0) Drop frames sourced 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 writeDropSrcIface(Long dpidLong, Long inPort) {
+
+        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());
+
+        // 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);
+        instructions.add(ib.build());
+
+        // Add InstructionBuilder to the Instruction(s)Builder List
+        isb.setInstruction(instructions);
+
+        // Add InstructionsBuilder to FlowBuilder
+        flowBuilder.setInstructions(isb.build());
+
+        // Add Flow Attributes
+        flowBuilder.setId(new FlowId("40"));
+        FlowKey key = new FlowKey(new FlowId(String.valueOf((long) 140)));
+        flowBuilder.setBarrier(false);
+        flowBuilder.setTableId((short) 0);
+        flowBuilder.setKey(key);
+        flowBuilder.setFlowName("LOCALDROP_" + nodeName);
+        flowBuilder.setPriority(8192);
+        flowBuilder.setHardTimeout(0);
+        flowBuilder.setIdleTimeout(0);
+        writeFlow(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 writeTunnelOut(Long dpidLong, Short writeTable, Short goToTableId, String segmentationId , Long OFPortOut, String attachedMac) {
+
+        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());
+
+        // 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);
+        instructions.add(ib.build());
+        // Set the Output Port/Iface
+        createOutputPortInstructions(ib, dpidLong, OFPortOut);
+        instructions.add(ib.build());
+
+        // Add InstructionBuilder to the Instruction(s)Builder List
+        isb.setInstruction(instructions);
+
+        // Add InstructionsBuilder to FlowBuilder
+        flowBuilder.setInstructions(isb.build());
+
+        // Add Flow Attributes
+        flowBuilder.setId(new FlowId("50"));
+        FlowKey key = new FlowKey(new FlowId(String.valueOf((long) 150)));
+        flowBuilder.setBarrier(false);
+        flowBuilder.setTableId(writeTable);
+        flowBuilder.setKey(key);
+        flowBuilder.setFlowName("TUNOUT_" + nodeName);
+        flowBuilder.setHardTimeout(0);
+        flowBuilder.setIdleTimeout(0);
+        writeFlow(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 writeTunnelFloodOut(Long dpidLong, Short writeTable, Short localTable, String segmentationId,  Long OFPortOut) {
+
+        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
+        byte[] mask = new byte[] { (byte) 1, 0, 0, 0, 0, 0 };
+        flowBuilder.setMatch(createDestEthMatch(matchBuilder, new MacAddress("01:00:00:00:00:00"), mask).build());
+
+        // 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 Instuction
+        createGotoTableInstructions(ib, localTable);
+        instructions.add(ib.build());
+        // Set the Output Port/Iface
+        createOutputPortInstructions(ib, dpidLong, OFPortOut);
+        instructions.add(ib.build());
+
+        // Add InstructionBuilder to the Instruction(s)Builder List
+        isb.setInstruction(instructions);
+
+        // Add InstructionsBuilder to FlowBuilder
+        flowBuilder.setInstructions(isb.build());
+
+        // Add Flow Attributes
+        flowBuilder.setId(new FlowId("60"));
+        FlowKey key = new FlowKey(new FlowId(String.valueOf((long) 160)));
+        flowBuilder.setBarrier(true);
+        flowBuilder.setTableId(writeTable);
+        flowBuilder.setKey(key);
+        flowBuilder.setPriority(16384);
+        flowBuilder.setFlowName("TUNFLOODOUT_" + nodeName);
+        flowBuilder.setHardTimeout(0);
+        flowBuilder.setIdleTimeout(0);
+        writeFlow(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 writeTunnelMiss(Long dpidLong, Short writeTable, Short goToTableId, String segmentationId) {
+
+        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());
+
+        // 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);
+        instructions.add(ib.build());
+
+        // Add InstructionBuilder to the Instruction(s)Builder List
+        isb.setInstruction(instructions);
+
+        // Add InstructionsBuilder to FlowBuilder
+        flowBuilder.setInstructions(isb.build());
+
+        // Add Flow Attributes
+        flowBuilder.setId(new FlowId("70"));
+        FlowKey key = new FlowKey(new FlowId(String.valueOf((long) 170)));
+        flowBuilder.setBarrier(false);
+        flowBuilder.setTableId(writeTable);
+        flowBuilder.setKey(key);
+        flowBuilder.setPriority(8192);
+        flowBuilder.setFlowName("TUNMISS_" + nodeName);
+        flowBuilder.setHardTimeout(0);
+        flowBuilder.setIdleTimeout(0);
+        writeFlow(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 writeLocalUcastOut(Long dpidLong, Short writeTable, String segmentationId, Long localPort, String attachedMac) {
+
+        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());
+
+        // 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);
+        instructions.add(ib.build());
+
+        // Add InstructionBuilder to the Instruction(s)Builder List
+        isb.setInstruction(instructions);
+
+        // Add InstructionsBuilder to FlowBuilder
+        flowBuilder.setInstructions(isb.build());
+
+        // Add Flow Attributes
+        flowBuilder.setId(new FlowId("80"));
+        FlowKey key = new FlowKey(new FlowId(String.valueOf((long) 180)));
+        flowBuilder.setBarrier(false);
+        flowBuilder.setTableId(writeTable);
+        flowBuilder.setKey(key);
+        flowBuilder.setFlowName("LOCALHOSTUCAST_" + nodeName);
+        flowBuilder.setHardTimeout(0);
+        flowBuilder.setIdleTimeout(0);
+        writeFlow(flowBuilder, nodeBuilder);
+    }
+
+    /*
+     * (Table:1) 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 writeLocalBcastOut(Long dpidLong, Short writeTable, String segmentationId, Long localPort) {
+
+        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());
+        byte[] mask = new byte[] { (byte) 1, 0, 0, 0, 0, 0 };
+        flowBuilder.setMatch(createDestEthMatch(matchBuilder, new MacAddress("01:00:00:00:00:00"), mask).build());
+
+        // 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>();
+
+        // Broken OutPort TODO: localPort needs to be a list of Ports)
+        createOutputPortInstructions(ib, dpidLong, localPort);
+        instructions.add(ib.build());
+
+        // Add InstructionBuilder to the Instruction(s)Builder List
+        isb.setInstruction(instructions);
+
+        // Add InstructionsBuilder to FlowBuilder
+        flowBuilder.setInstructions(isb.build());
+
+        // Add Flow Attributes
+        flowBuilder.setId(new FlowId("90"));
+        FlowKey key = new FlowKey(new FlowId(String.valueOf((long) 190)));
+        flowBuilder.setBarrier(false);
+        flowBuilder.setTableId(writeTable);
+        flowBuilder.setKey(key);
+        flowBuilder.setPriority(16384);
+        flowBuilder.setFlowName("LOCALHOSTBCAST_" + nodeName);
+        flowBuilder.setHardTimeout(0);
+        flowBuilder.setIdleTimeout(0);
+        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 writeLocalTableMiss(Long dpidLong, Short writeTable, String segmentationId) {
+
+        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());
+
+        // 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);
+        instructions.add(ib.build());
+
+        // Add InstructionBuilder to the Instruction(s)Builder List
+        isb.setInstruction(instructions);
+
+        // Add InstructionsBuilder to FlowBuilder
+        flowBuilder.setInstructions(isb.build());
+
+        // Add Flow Attributes
+        flowBuilder.setId(new FlowId("100"));
+        FlowKey key = new FlowKey(new FlowId(String.valueOf((long) 200)));
+        flowBuilder.setBarrier(false);
+        flowBuilder.setTableId(writeTable);
+        flowBuilder.setKey(key);
+        flowBuilder.setPriority(8192);
+        flowBuilder.setFlowName("TUNMISS_" + nodeName);
+        flowBuilder.setHardTimeout(0);
+        flowBuilder.setIdleTimeout(0);
+        writeFlow(flowBuilder, nodeBuilder);
+    }
+
     private void writeFlow(FlowBuilder flowBuilder, NodeBuilder nodeBuilder) {
         IMDSALConsumer mdsalConsumer = (IMDSALConsumer) ServiceHelper.getInstance(IMDSALConsumer.class, "default", this);
         if (mdsalConsumer == null) {
@@ -268,11 +1090,14 @@ class OF13ProviderManager extends ProviderNetworkManager {
      * @return matchBuilder Map MatchBuilder Object with a match
      */
 
-    protected static MatchBuilder createDestEthMatch(MatchBuilder matchBuilder, MacAddress dMacAddr) {
+    protected static MatchBuilder createDestEthMatch(MatchBuilder matchBuilder, MacAddress dMacAddr, byte[] 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());
 
index df5e50a06d7ecd9971fa664803f182a7dba2ee73..c38a027e52b90ca714732ae750c5ed0c9c7171d4 100644 (file)
@@ -54,8 +54,8 @@ public abstract class ProviderNetworkManager {
     }
 
     public abstract boolean hasPerTenantTunneling();
-    public abstract Status createTunnels(String tunnelType, String tunnelKey);
-    public abstract Status createTunnels(String tunnelType, String tunnelKey, Node source, Interface intf);
+    public abstract Status handleInterfaceUpdate(String tunnelType, String tunnelKey);
+    public abstract Status handleInterfaceUpdate(String tunnelType, String tunnelKey, Node source, Interface intf);
     /*
      * Initialize the Flow rules given the OVSDB node.
      * This method provides a set of common functionalities to initialize the Flow rules of an OVSDB node