Fixing a ClassCastException issue with an incorect Row to TypedClass cast introduced...
[ovsdb.git] / neutron / src / main / java / org / opendaylight / ovsdb / neutron / provider / OF13Provider.java
index b656513dd747d8b774e129f4041f08c88870f8ce..0b1d4c1dda419f3f25deadec60fafddeb5238e03 100644 (file)
@@ -12,6 +12,7 @@ package org.opendaylight.ovsdb.neutron.provider;
 import java.math.BigInteger;
 import java.net.InetAddress;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -28,44 +29,48 @@ 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.Row;
 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.neutron.NetworkHandler;
 import org.opendaylight.ovsdb.plugin.IConnectionServiceInternal;
 import org.opendaylight.ovsdb.plugin.OVSDBConfigService;
 import org.opendaylight.ovsdb.plugin.StatusWithUuid;
+import org.opendaylight.ovsdb.schema.openvswitch.Bridge;
+import org.opendaylight.ovsdb.schema.openvswitch.Interface;
+import org.opendaylight.ovsdb.schema.openvswitch.Port;
 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.PushVlanActionCaseBuilder;
 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.StripVlanActionCaseBuilder;
 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.pop.vlan.action._case.PopVlanActionBuilder;
+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.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;
@@ -88,6 +93,17 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instru
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.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.Buckets;
+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.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;
@@ -126,6 +142,7 @@ public class OF13Provider implements NetworkProvider {
     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;
@@ -169,11 +186,13 @@ public class OF13Provider implements NetworkProvider {
 
     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);
+        Row bridgeRow = ovsdbTable.getRow(node, ovsdbTable.getTableName(node, Bridge.class), bridgeUUID);
+        Bridge bridge = ovsdbTable.getTypedRow(node, Bridge.class, bridgeRow);
         if (bridge != null) {
-            Set<UUID> ports = bridge.getPorts();
+            Set<UUID> ports = bridge.getPortsColumn().getData();
             for (UUID portUUID : ports) {
-                Port port = (Port)ovsdbTable.getRow(node, Port.NAME.getName(), portUUID.toString());
+                Row portRow = ovsdbTable.getRow(node, ovsdbTable.getTableName(node, Port.class), portUUID.toString());
+                Port port = ovsdbTable.getTypedRow(node, Port.class, portRow);
                 if (port != null && port.getName().equalsIgnoreCase(tunnelName)) return true;
             }
         }
@@ -182,11 +201,13 @@ public class OF13Provider implements NetworkProvider {
 
     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);
+        Row bridgeRow = ovsdbTable.getRow(node, ovsdbTable.getTableName(node, Bridge.class), bridgeUUID);
+        Bridge bridge = ovsdbTable.getTypedRow(node, Bridge.class, bridgeRow);
         if (bridge != null) {
-            Set<UUID> ports = bridge.getPorts();
+            Set<UUID> ports = bridge.getPortsColumn().getData();
             for (UUID portUUID : ports) {
-                Port port = (Port)ovsdbTable.getRow(node, Port.NAME.getName(), portUUID.toString());
+                Row portRow = ovsdbTable.getRow(node, ovsdbTable.getTableName(node, Port.class), portUUID.toString());
+                Port port = ovsdbTable.getTypedRow(node, Port.class, portRow);
                 if (port != null && port.getName().equalsIgnoreCase(name)) return portUUID.toString();
             }
         }
@@ -198,10 +219,10 @@ public class OF13Provider implements NetworkProvider {
             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, Row> bridgeTable = ovsdbTable.getRows(node, ovsdbTable.getTableName(node, Bridge.class));
             if (bridgeTable != null) {
                 for (String uuid : bridgeTable.keySet()) {
-                    Bridge bridge = (Bridge)bridgeTable.get(uuid);
+                    Bridge bridge = ovsdbTable.getTypedRow(node,Bridge.class, bridgeTable.get(uuid));
                     if (bridge.getName().equals(tunnelBridgeName)) {
                         bridgeUUID = uuid;
                         break;
@@ -219,9 +240,9 @@ public class OF13Provider implements NetworkProvider {
                 return new Status(StatusCode.SUCCESS);
             }
 
-            Port tunnelPort = new Port();
+            Port tunnelPort = ovsdbTable.createTypedRow(node, Port.class);
             tunnelPort.setName(portName);
-            StatusWithUuid statusWithUuid = ovsdbTable.insertRow(node, Port.NAME.getName(), bridgeUUID, tunnelPort);
+            StatusWithUuid statusWithUuid = ovsdbTable.insertRow(node, ovsdbTable.getTableName(node, Port.class), bridgeUUID, tunnelPort.getRow());
             if (!statusWithUuid.isSuccess()) {
                 logger.error("Failed to insert Tunnel port {} in {}", portName, bridgeUUID);
                 return statusWithUuid;
@@ -231,8 +252,9 @@ public class OF13Provider implements NetworkProvider {
             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();
+                Row portRow = ovsdbTable.getRow(node, ovsdbTable.getTableName(node, Port.class), tunnelPortUUID);
+                tunnelPort = ovsdbTable.getTypedRow(node, Port.class, portRow);
+                Set<UUID> interfaces = tunnelPort.getInterfacesColumn().getData();
                 if (interfaces == null || interfaces.size() == 0) {
                     // Wait for the OVSDB update to sync up the Local cache.
                     Thread.sleep(500);
@@ -240,7 +262,7 @@ public class OF13Provider implements NetworkProvider {
                     continue;
                 }
                 interfaceUUID = interfaces.toArray()[0].toString();
-                Interface intf = (Interface)ovsdbTable.getRow(node, Interface.NAME.getName(), interfaceUUID);
+                Interface intf = (Interface)ovsdbTable.getRow(node, ovsdbTable.getTableName(node, Interface.class), interfaceUUID);
                 if (intf == null) interfaceUUID = null;
             }
 
@@ -249,14 +271,14 @@ public class OF13Provider implements NetworkProvider {
                 return new Status(StatusCode.INTERNALERROR);
             }
 
-            Interface tunInterface = new Interface();
+            Interface tunInterface = ovsdbTable.createTypedRow(node, Interface.class);
             tunInterface.setType(tunnelType);
-            OvsDBMap<String, String> options = new OvsDBMap<String, String>();
+            Map<String, String> options = new HashMap<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);
+            Status status = ovsdbTable.updateRow(node, ovsdbTable.getTableName(node, Interface.class), tunnelPortUUID, interfaceUUID, tunInterface.getRow());
             logger.debug("Tunnel {} add status : {}", tunInterface, status);
             return status;
         } catch (Exception e) {
@@ -270,10 +292,10 @@ public class OF13Provider implements NetworkProvider {
         try {
             String bridgeUUID = null;
             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, Row> bridgeTable = ovsdbTable.getRows(node, ovsdbTable.getTableName(node, Bridge.class));
             if (bridgeTable != null) {
                 for (String uuid : bridgeTable.keySet()) {
-                    Bridge bridge = (Bridge)bridgeTable.get(uuid);
+                    Bridge bridge = ovsdbTable.getTypedRow(node, Bridge.class, bridgeTable.get(uuid));
                     if (bridge.getName().equals(bridgeName)) {
                         bridgeUUID = uuid;
                         break;
@@ -288,7 +310,7 @@ public class OF13Provider implements NetworkProvider {
             String portUUID = this.getPortUuid(node, portName, bridgeUUID);
             Status status = new Status(StatusCode.SUCCESS);
             if (portUUID != null) {
-               status = ovsdbTable.deleteRow(node, Port.NAME.getName(), portUUID);
+               status = ovsdbTable.deleteRow(node, ovsdbTable.getTableName(node, Port.class), portUUID);
                if (!status.isSuccess()) {
                    logger.error("Failed to delete port {} in {} status : {}", portName, bridgeUUID,
                                 status);
@@ -310,6 +332,12 @@ public class OF13Provider implements NetworkProvider {
         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
@@ -376,42 +404,42 @@ public class OF13Provider implements NetworkProvider {
 
     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)
-         **/
+         * 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);
+         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
-         **/
+         * Table(0) Rule #4
+         * ----------------
+         * Match: Drop any remaining Ingress Local VM Packets
+         * Action: Drop w/ a low priority
+         */
 
-        handleDropSrcIface(dpid, localPort, false);
+         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
-         **/
+         /*
+          * 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);
+         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
-         **/
+         /*
+          * 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);
+          handleLocalBcastOut(dpid, TABLE_2_LOCAL_FORWARD, segmentationId, localPort, false);
     }
 
     private void programLocalIngressTunnelBridgeRules(Node node, Long dpid, String segmentationId, String attachedMac, long tunnelOFPort, long localPort) {
@@ -454,64 +482,295 @@ public class OF13Provider implements NetworkProvider {
 
     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
-         **/
+         * 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);
+        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.
-         **/
+         * 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
-         **/
+         * 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
-         **/
+         * 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, Tunnel ID
-        ** Action: GOTO Local Table (10)
-        **/
+        * 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);
+   }
 
-       handleTunnelIn(dpid, TABLE_0_DEFAULT_INGRESS, TABLE_2_LOCAL_FORWARD, segmentationId, tunnelOFPort, false);
+   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 #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
-        **/
+        * 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
+          */
 
-       handleTunnelFloodOut(dpid, TABLE_1_ISOLATE_TENANT, TABLE_2_LOCAL_FORWARD, segmentationId, tunnelOFPort, false);
+         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);
+            Row bridgeRow =  ovsdbTable.getRow(node, ovsdbTable.getTableName(node, Bridge.class), bridgeUuid);
+            Bridge bridge = ovsdbTable.getTypedRow(node, Bridge.class, bridgeRow);
+            Set<String> dpids = bridge.getDatapathIdColumn().getData();
+            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) {
@@ -523,17 +782,30 @@ public class OF13Provider implements NetworkProvider {
                 return 0L;
             }
 
-            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 0L;
-            return Long.valueOf(HexEncode.stringToLong((String) dpids.toArray()[0]));
+            return getDpid(node, brIntId);
         } catch (Exception e) {
             logger.error("Error finding Integration Bridge's OF DPID", e);
             return 0L;
         }
     }
-    private void programLocalRules (String tunnelType, String segmentationId, Node node, Interface intf) {
+
+    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) {
@@ -541,14 +813,14 @@ public class OF13Provider implements NetworkProvider {
                 return;
             }
 
-            Set<BigInteger> of_ports = intf.getOfport();
+            Set<Integer> of_ports = intf.getOpenFlowPortColumn().getData();
             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();
+            long localPort = ((Integer)of_ports.toArray()[0]).longValue();
 
-            Map<String, String> externalIds = intf.getExternal_ids();
+            Map<String, String> externalIds = intf.getExternalIdsColumn().getData();
             if (externalIds == null) {
                 logger.error("No external_ids seen in {}", intf);
                 return;
@@ -560,7 +832,15 @@ public class OF13Provider implements NetworkProvider {
                 return;
             }
 
-            programLocalBridgeRules(node, dpid, segmentationId, attachedMac, localPort);
+            /* 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);
         }
@@ -574,14 +854,14 @@ public class OF13Provider implements NetworkProvider {
                 return;
             }
 
-            Set<BigInteger> of_ports = intf.getOfport();
+            Set<Integer> of_ports = intf.getOpenFlowPortColumn().getData();
             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();
+            long localPort = ((Integer)of_ports.toArray()[0]).longValue();
 
-            Map<String, String> externalIds = intf.getExternal_ids();
+            Map<String, String> externalIds = intf.getExternalIdsColumn().getData();
             if (externalIds == null) {
                 logger.error("No external_ids seen in {}", intf);
                 return;
@@ -594,8 +874,11 @@ public class OF13Provider implements NetworkProvider {
             }
 
             /* Program local rules based on network type */
-            if (networkType.equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_GRE) ||
-              networkType.equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VXLAN)) {
+            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);
             }
@@ -604,7 +887,6 @@ public class OF13Provider implements NetworkProvider {
         }
     }
 
-
     private void programTunnelRules (String tunnelType, String segmentationId, InetAddress dst, Node node,
             Interface intf, boolean local) {
         try {
@@ -616,14 +898,14 @@ public class OF13Provider implements NetworkProvider {
             }
             OVSDBConfigService ovsdbTable = (OVSDBConfigService) ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
 
-            Set<BigInteger> of_ports = intf.getOfport();
+            Set<Integer> of_ports = intf.getOpenFlowPortColumn().getData();
             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();
+            long localPort = ((Integer)of_ports.toArray()[0]).longValue();
 
-            Map<String, String> externalIds = intf.getExternal_ids();
+            Map<String, String> externalIds = intf.getExternalIdsColumn().getData();
             if (externalIds == null) {
                 logger.error("No external_ids seen in {}", intf);
                 return;
@@ -635,17 +917,17 @@ public class OF13Provider implements NetworkProvider {
                 return;
             }
 
-            Map<String, org.opendaylight.ovsdb.lib.table.internal.Table<?>> intfs = ovsdbTable.getRows(node, Interface.NAME.getName());
+            Map<String, Row> intfs = ovsdbTable.getRows(node, ovsdbTable.getTableName(node, Interface.class));
             if (intfs != null) {
-                for (org.opendaylight.ovsdb.lib.table.internal.Table<?> row : intfs.values()) {
-                    Interface tunIntf = (Interface)row;
+                for (Row row : intfs.values()) {
+                    Interface tunIntf = ovsdbTable.getTypedRow(node, Interface.class, row);
                     if (tunIntf.getName().equals(this.getTunnelName(tunnelType, dst))) {
-                        of_ports = tunIntf.getOfport();
+                        of_ports = tunIntf.getOpenFlowPortColumn().getData();
                         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();
+                        long tunnelOFPort = ((Integer)of_ports.toArray()[0]).longValue();
 
                         if (tunnelOFPort == -1) {
                             logger.error("Could NOT Identify Tunnel port {} -> OF ({}) on {}", tunIntf.getName(), tunnelOFPort, node);
@@ -680,14 +962,14 @@ public class OF13Provider implements NetworkProvider {
             }
             OVSDBConfigService ovsdbTable = (OVSDBConfigService) ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
 
-            Set<BigInteger> of_ports = intf.getOfport();
+            Set<Integer> of_ports = intf.getOpenFlowPortColumn().getData();
             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();
+            Map<String, String> externalIds = intf.getExternalIdsColumn().getData();
             if (externalIds == null) {
                 logger.error("No external_ids seen in {}", intf);
                 return;
@@ -699,12 +981,12 @@ public class OF13Provider implements NetworkProvider {
                 return;
             }
 
-            Map<String, org.opendaylight.ovsdb.lib.table.internal.Table<?>> intfs = ovsdbTable.getRows(node, Interface.NAME.getName());
+            Map<String, Row> intfs = ovsdbTable.getRows(node, ovsdbTable.getTableName(node, Interface.class));
             if (intfs != null) {
-                for (org.opendaylight.ovsdb.lib.table.internal.Table<?> row : intfs.values()) {
-                    Interface tunIntf = (Interface)row;
+                for (Row row : intfs.values()) {
+                    Interface tunIntf = ovsdbTable.getTypedRow(node, Interface.class, row);
                     if (tunIntf.getName().equals(this.getTunnelName(tunnelType, dst))) {
-                        of_ports = tunIntf.getOfport();
+                        of_ports = tunIntf.getOpenFlowPortColumn().getData();
                         if (of_ports == null || of_ports.size() <= 0) {
                             logger.error("Could NOT Identify Tunnel port {} on {}", tunIntf.getName(), node);
                             continue;
@@ -732,76 +1014,224 @@ public class OF13Provider implements NetworkProvider {
         }
     }
 
-    @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);
+    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 {}", srcNode);
-                return new Status(StatusCode.NOTFOUND);
+                logger.debug("Openflow Datapath-ID not set for the integration bridge in {}", node);
+                return;
             }
-            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;
-                    }
+            OVSDBConfigService ovsdbTable = (OVSDBConfigService) ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
+
+            Set<Integer> of_ports = intf.getOpenFlowPortColumn().getData();
+            int timeout = 6;
+            while ((of_ports == null) && (timeout > 0)) {
+                of_ports = intf.getOpenFlowPortColumn().getData();
+                if (of_ports == null || of_ports.size() <= 0) {
+                    // Wait for the OVSDB update to sync up the Local cache.
+                    Thread.sleep(500);
+                    timeout--;
+                    continue;
                 }
-            } 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);
+            if (of_ports == null || of_ports.size() <= 0) {
+                logger.error("Could NOT Identify OF value for port {} on {}", intf.getName(), node);
+                return;
             }
-        }
-
-        IConnectionServiceInternal connectionService = (IConnectionServiceInternal)ServiceHelper.getGlobalInstance(IConnectionServiceInternal.class, this);
-        List<Node> nodes = connectionService.getNodes();
-        nodes.remove(srcNode);
-        this.programLocalRules(network.getProviderNetworkType(), network.getProviderSegmentationID(), srcNode, intf);
 
-        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);
+            Map<String, String> externalIds = intf.getExternalIdsColumn().getData();
+            if (externalIds == null) {
+                logger.error("No external_ids seen in {}", intf);
+                return;
             }
-        }
 
-        return new Status(StatusCode.SUCCESS);
-    }
+            String attachedMac = externalIds.get(tenantNetworkManager.EXTERNAL_ID_VM_MAC);
+            if (attachedMac == null) {
+                logger.error("No AttachedMac seen in {}", intf);
+                return;
+            }
 
-    private Status triggerInterfaceUpdates(Node node) {
-        try {
-            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, Row> intfs = ovsdbTable.getRows(node, ovsdbTable.getTableName(node, Interface.class));
             if (intfs != null) {
-                for (org.opendaylight.ovsdb.lib.table.internal.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);
+                for (Row row : intfs.values()) {
+                    Interface ethIntf = ovsdbTable.getTypedRow(node, Interface.class, row);
+                    if (ethIntf.getName().equalsIgnoreCase(adminConfigManager.getPhysicalInterfaceName(node, network.getProviderPhysicalNetwork()))) {
+                        of_ports = ethIntf.getOpenFlowPortColumn().getData();
+                        timeout = 6;
+                        while ((of_ports == null) && (timeout > 0)) {
+                            of_ports = ethIntf.getOpenFlowPortColumn().getData();
+                            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("Error Triggering the lost interface updates for "+ node, e);
-            return new Status(StatusCode.INTERNALERROR, e.getLocalizedMessage());
+            logger.error("", e);
         }
-        return new Status(StatusCode.SUCCESS);
+    }
+
+    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<Integer> of_ports = intf.getOpenFlowPortColumn().getData();
+            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.getExternalIdsColumn().getData();
+            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, Row> intfs = ovsdbTable.getRows(node, ovsdbTable.getTableName(node, Interface.class));
+            if (intfs != null) {
+                for (Row row : intfs.values()) {
+                    Interface ethIntf = ovsdbTable.getTypedRow(node, Interface.class, row);
+                    if (ethIntf.getName().equalsIgnoreCase(adminConfigManager.getPhysicalInterfaceName(node,
+                                                                   network.getProviderPhysicalNetwork()))) {
+                        of_ports = ethIntf.getOpenFlowPortColumn().getData();
+                        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);
+            Map<String, Row> intfs = ovsdbTable.getRows(node, ovsdbTable.getTableName(node, Interface.class));
+            if (intfs != null) {
+                for (Row row : intfs.values()) {
+                    Interface intf = ovsdbTable.getTypedRow(node, Interface.class, 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) {
@@ -818,23 +1248,31 @@ public class OF13Provider implements NetworkProvider {
         nodes.remove(srcNode);
 
         logger.info("Delete intf " + intf.getName() + " isLastInstanceOnNode " + isLastInstanceOnNode);
-        if (intf.getType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VXLAN) || intf.getType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_GRE)) {
-        /* Delete tunnel port */
+        List<String> phyIfName = adminConfigManager.getAllPhysicalInterfaceNames(srcNode);
+        if (intf.getTypeColumn().getData().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VXLAN)
+            || intf.getTypeColumn().getData().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_GRE)) {
+            /* Delete tunnel port */
             try {
-                OvsDBMap<String, String> options = intf.getOptions();
+                Map<String, String> options = intf.getOptionsColumn().getData();
                 InetAddress src = InetAddress.getByName(options.get("local_ip"));
                 InetAddress dst = InetAddress.getByName(options.get("remote_ip"));
-                status = deleteTunnelPort(srcNode, intf.getType(), src, dst);
+                status = deleteTunnelPort(srcNode, intf.getTypeColumn().getData(), 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(tunnelType, network.getProviderSegmentationID(),
-                                  srcNode, intf);
+            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)) {
 
-            if (tunnelType.equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_GRE)
-                 || tunnelType.equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VXLAN)) {
                 for (Node dstNode : nodes) {
                     InetAddress src = adminConfigManager.getTunnelEndPoint(srcNode);
                     InetAddress dst = adminConfigManager.getTunnelEndPoint(dstNode);
@@ -853,6 +1291,7 @@ public class OF13Provider implements NetworkProvider {
     @Override
     public void initializeFlowRules(Node node) {
         this.initializeFlowRules(node, adminConfigManager.getIntegrationBridgeName());
+        this.initializeFlowRules(node, adminConfigManager.getExternalBridgeName());
         this.triggerInterfaceUpdates(node);
     }
 
@@ -861,7 +1300,13 @@ public class OF13Provider implements NetworkProvider {
      * @param bridgeName
      */
     private void initializeFlowRules(Node node, String bridgeName) {
-        Long dpid = this.getIntegrationBridgeOFDPID(node);
+        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;
@@ -875,6 +1320,9 @@ public class OF13Provider implements NetworkProvider {
          */
 
          writeLLDPRule(dpid);
+         if (bridgeName == adminConfigManager.getExternalBridgeName()) {
+             writeNormalRule(dpid);
+         }
     }
 
     /*
@@ -928,6 +1376,53 @@ public class OF13Provider implements NetworkProvider {
         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
@@ -935,8 +1430,9 @@ public class OF13Provider implements NetworkProvider {
      * 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) {
+    private void handleTunnelIn(Long dpidLong, Short writeTable,
+                                Short goToTableId, String segmentationId,
+                                Long ofPort, boolean write) {
 
         String nodeName = "openflow:" + dpidLong;
 
@@ -989,6 +1485,65 @@ public class OF13Provider implements NetworkProvider {
         }
     }
 
+    /*
+     * (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
@@ -998,7 +1553,8 @@ public class OF13Provider implements NetworkProvider {
     */
 
     private void handleLocalInPort(Long dpidLong, Short writeTable, Short goToTableId,
-                                   String segmentationId, Long inPort, String attachedMac, boolean write) {
+                           String segmentationId, Long inPort, String attachedMac,
+                           boolean write) {
 
         String nodeName = "openflow:" + dpidLong;
 
@@ -1055,7 +1611,74 @@ public class OF13Provider implements NetworkProvider {
     }
 
     /*
-     * (Table:0) Drop frames sourced from a VM that do not
+     * (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
@@ -1120,9 +1743,10 @@ public class OF13Provider implements NetworkProvider {
     * 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) {
+    private void handleTunnelOut(Long dpidLong, Short writeTable,
+                         Short goToTableId, String segmentationId,
+                         Long OFPortOut, String attachedMac,
+                         boolean write) {
 
         String nodeName = "openflow:" + dpidLong;
 
@@ -1177,6 +1801,66 @@ public class OF13Provider implements NetworkProvider {
         }
     }
 
+    /*
+     * (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
@@ -1185,8 +1869,9 @@ public class OF13Provider implements NetworkProvider {
     * actions=output:10,output:11,goto_table:2
     */
 
-    private void handleTunnelFloodOut(Long dpidLong, Short writeTable, Short localTable,
-                                      String segmentationId,  Long OFPortOut, boolean write) {
+    private void handleTunnelFloodOut(Long dpidLong, Short writeTable,
+                             Short localTable, String segmentationId,
+                             Long OFPortOut, boolean write) {
 
         String nodeName = "openflow:" + dpidLong;
 
@@ -1227,12 +1912,13 @@ public class OF13Provider implements NetworkProvider {
         }
 
         if (write) {
-            // GOTO Instuction
+            // 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));
@@ -1247,7 +1933,8 @@ public class OF13Provider implements NetworkProvider {
             writeFlow(flowBuilder, nodeBuilder);
         } else {
             /* remove port from action list */
-            boolean flowRemove = removeOutputPortFromInstructions(ib, dpidLong,OFPortOut, existingInstructions);
+            boolean flowRemove = removeOutputPortFromInstructions(ib, dpidLong,
+                                   OFPortOut, existingInstructions);
             if (flowRemove) {
                 /* if all port are removed, remove the flow too. */
                 removeFlow(flowBuilder, nodeBuilder);
@@ -1266,6 +1953,72 @@ public class OF13Provider implements NetworkProvider {
         }
     }
 
+    /*
+     * (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
@@ -1273,7 +2026,9 @@ public class OF13Provider implements NetworkProvider {
     * table=2,priority=8192,tun_id=0x5 actions=drop
     */
 
-    private void handleTunnelMiss(Long dpidLong, Short writeTable, Short goToTableId, String segmentationId, boolean write) {
+    private void handleTunnelMiss(Long dpidLong, Short writeTable,
+                          Short goToTableId, String segmentationId,
+                          boolean write) {
 
         String nodeName = "openflow:" + dpidLong;
 
@@ -1324,6 +2079,72 @@ public class OF13Provider implements NetworkProvider {
         }
     }
 
+
+    /*
+     * (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
@@ -1331,8 +2152,9 @@ public class OF13Provider implements NetworkProvider {
      * 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) {
+    private void handleLocalUcastOut(Long dpidLong, Short writeTable,
+                             String segmentationId, Long localPort,
+                             String attachedMac, boolean write) {
 
         String nodeName = "openflow:" + dpidLong;
 
@@ -1382,14 +2204,81 @@ public class OF13Provider implements NetworkProvider {
     }
 
     /*
-     * (Table:1) Local Broadcast Flood
+     * (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) {
+    private void handleLocalBcastOut(Long dpidLong, Short writeTable,
+                             String segmentationId, Long localPort,
+                             boolean write) {
 
         String nodeName = "openflow:" + dpidLong;
 
@@ -1441,24 +2330,136 @@ public class OF13Provider implements NetworkProvider {
 
             writeFlow(flowBuilder, nodeBuilder);
         } else {
-            boolean flowRemove = removeOutputPortFromInstructions(ib, dpidLong,
-                                       localPort, existingInstructions);
+            boolean flowRemove = removeOutputPortFromInstructions(ib, dpidLong, localPort,
+                                                                  existingInstructions);
             if (flowRemove) {
-                   /* if all ports are removed, remove flow */
-                 removeFlow(flowBuilder, nodeBuilder);
-               } else {
+                /* 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());
+                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());
+                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());
 
-                   writeFlow(flowBuilder, nodeBuilder);
+                // Add InstructionBuilder to the Instruction(s)Builder List
+                isb.setInstruction(instructions);
+
+                // Add InstructionsBuilder to FlowBuilder
+                flowBuilder.setInstructions(isb.build());
+                writeFlow(flowBuilder, nodeBuilder);
             }
         }
     }
@@ -1467,11 +2468,70 @@ public class OF13Provider implements NetworkProvider {
      * (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
+     * 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 handleLocalTableMiss(Long dpidLong, Short writeTable, String segmentationId,
-                                      boolean write) {
+    private void handleLocalVlanTableMiss(Long dpidLong, Short writeTable,
+                                  String segmentationId, boolean write) {
 
         String nodeName = "openflow:" + dpidLong;
 
@@ -1480,7 +2540,7 @@ public class OF13Provider implements NetworkProvider {
         FlowBuilder flowBuilder = new FlowBuilder();
 
         // Create Match(es) and Set them in the FlowBuilder Object
-        flowBuilder.setMatch(createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
+        flowBuilder.setMatch(createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId))).build());
 
         if (write) {
             // Create the OF Actions and Instructions
@@ -1522,6 +2582,90 @@ public class OF13Provider implements NetworkProvider {
         }
     }
 
+    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) {
@@ -1559,8 +2703,8 @@ public class OF13Provider implements NetworkProvider {
         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.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();
@@ -1585,7 +2729,7 @@ public class OF13Provider implements NetworkProvider {
         dataBrokerService = mdsalConsumer.getDataBrokerService();
 
         if (dataBrokerService == null) {
-            logger.error("ERROR finding reference for DataBrokerService. Please check out the MD-SALsupport on the Controller.");
+            logger.error("ERROR finding reference for DataBrokerService. Please check out the MD-SAL support on the Controller.");
             return;
         }
         DataModification<InstanceIdentifier<?>, DataObject> modification = dataBrokerService.beginTransaction();
@@ -1595,7 +2739,7 @@ public class OF13Provider implements NetworkProvider {
                 .augmentation(FlowCapableNode.class).child(Table.class,
                 new TableKey(flowBuilder.getTableId())).child(Flow.class, flowBuilder.getKey()).build();
         //modification.removeOperationalData(nodeBuilderToInstanceId(nodeBuilder));
-        modification.removeOperationalData(path1);
+        //modification.removeOperationalData(path1);
         //modification.removeConfigurationData(nodeBuilderToInstanceId(nodeBuilder));
         modification.removeConfigurationData(path1);
         Future<RpcResult<TransactionStatus>> commitFuture = modification.commit();
@@ -1673,10 +2817,10 @@ public class OF13Provider implements NetworkProvider {
      */
 
     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());
 
@@ -1863,7 +3007,7 @@ public class OF13Provider implements NetworkProvider {
         ActionBuilder ab = new ActionBuilder();
 
         OutputActionBuilder output = new OutputActionBuilder();
-        output.setMaxLength(56);
+        output.setMaxLength(0xffff);
         Uri value = new Uri("CONTROLLER");
         output.setOutputNodeConnector(value);
         ab.setAction(new OutputActionCaseBuilder().setOutputAction(output.build()).build());
@@ -1881,6 +3025,36 @@ public class OF13Provider implements NetworkProvider {
         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
      *
@@ -1913,15 +3087,16 @@ public class OF13Provider implements NetworkProvider {
     }
 
     /**
-     * Create Output Port Instruction
+     * 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 static InstructionBuilder createOutputPortInstructions(InstructionBuilder ib, Long dpidLong, Long port , List<Instruction> 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);
 
@@ -1937,24 +3112,184 @@ public class OF13Provider implements NetworkProvider {
                 }
             }
         }
-
+        /* Create output action for this port*/
         OutputActionBuilder oab = new OutputActionBuilder();
         oab.setOutputNodeConnector(ncid);
         ab.setAction(new OutputActionCaseBuilder().setOutputAction(oab.build()).build());
-        ab.setOrder(0);
-        ab.setKey(new ActionKey(0));
-        Action newAction = ab.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) actionList.add(newAction);
+        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();
@@ -1965,21 +3300,187 @@ public class OF13Provider implements NetworkProvider {
     }
 
     /**
-    * 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
-    */
+     * 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) {
+                                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();
+        ActionBuilder ab;
 
         List<Action> existingActions = null;
         if (instructions != null) {
@@ -1993,24 +3494,45 @@ public class OF13Provider implements NetworkProvider {
         }
 
         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 */
@@ -2019,7 +3541,7 @@ public class OF13Provider implements NetworkProvider {
     }
 
     /**
-     * Create Set Vlan ID Instruction
+     * 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
@@ -2030,9 +3552,19 @@ public class OF13Provider implements NetworkProvider {
         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();
@@ -2045,20 +3577,19 @@ public class OF13Provider implements NetworkProvider {
     }
 
     /**
-     * Create Set IPv4 Destination Instruction
+     * Create Pop Vlan Instruction - this remove vlan header
      *
      * @param ib Map InstructionBuilder without any instructions
      * @return ib Map InstructionBuilder with instructions
      */
-    protected static InstructionBuilder createStripVlanInstructions(InstructionBuilder ib) {
+    protected static InstructionBuilder createPopVlanInstructions(InstructionBuilder ib) {
 
-        StripVlanActionBuilder stripVlanActionBuilder = new StripVlanActionBuilder();
-        StripVlanAction vlanAction = stripVlanActionBuilder.build();
+        List<Action> actionList = new ArrayList<Action>();
         ActionBuilder ab = new ActionBuilder();
-        ab.setAction(new StripVlanActionCaseBuilder().setStripVlanAction(vlanAction).build());
 
-        // Add our drop action to a list
-        List<Action> actionList = new ArrayList<Action>();
+        PopVlanActionBuilder popVlanActionBuilder = new PopVlanActionBuilder();
+        ab.setAction(new PopVlanActionCaseBuilder().setPopVlanAction(popVlanActionBuilder.build()).build());
+        ab.setOrder(0);
         actionList.add(ab.build());
 
         // Create an Apply Action
@@ -2141,6 +3672,7 @@ public class OF13Provider implements NetworkProvider {
         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>();
@@ -2192,6 +3724,7 @@ public class OF13Provider implements NetworkProvider {
         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();
@@ -2506,10 +4039,15 @@ public class OF13Provider implements NetworkProvider {
         List<Node> ovsNodes = connectionService.getNodes();
         if (ovsNodes == null) return;
         for (Node ovsNode : ovsNodes) {
-            Long dpid = this.getIntegrationBridgeOFDPID(ovsNode);
-            logger.debug("Compare openflowNode to OVS br-int node {} vs {}", openflowNode.getID(), dpid);
-            String openflowID = ""+openflowNode.getID();
-            if (openflowID.contains(""+dpid)) {
+            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);
             }
@@ -2532,10 +4070,10 @@ public class OF13Provider implements NetworkProvider {
     private String getInternalBridgeUUID (Node node, String bridgeName) {
         try {
             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, Row> bridgeTable = ovsdbTable.getRows(node, ovsdbTable.getTableName(node, Bridge.class));
             if (bridgeTable == null) return null;
             for (String key : bridgeTable.keySet()) {
-                Bridge bridge = (Bridge)bridgeTable.get(key);
+                Bridge bridge = ovsdbTable.getTypedRow(node, Bridge.class, bridgeTable.get(key));
                 if (bridge.getName().equals(bridgeName)) return key;
             }
         } catch (Exception e) {