support for corsa pipeline. EXPERIMENTAL.

Change-Id: Ic3db0a7a18f11c41c8a84f25a249dfb63109da97
diff --git a/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficTreatment.java b/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficTreatment.java
index 37dcd06..de5c328 100644
--- a/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficTreatment.java
+++ b/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficTreatment.java
@@ -249,6 +249,11 @@
         }
 
         @Override
+        public TrafficTreatment.Builder transition(FlowRule.Type type) {
+            return add(Instructions.transition(type));
+        }
+
+        @Override
         public TrafficTreatment build() {
 
             //If we are dropping should we just return an empty list?
diff --git a/core/api/src/main/java/org/onosproject/net/flow/FlowRule.java b/core/api/src/main/java/org/onosproject/net/flow/FlowRule.java
index b03f620..462875a 100644
--- a/core/api/src/main/java/org/onosproject/net/flow/FlowRule.java
+++ b/core/api/src/main/java/org/onosproject/net/flow/FlowRule.java
@@ -40,7 +40,19 @@
         /* Used in flow entry for MPLS table */
         MPLS,
         /* Used in flow entry for ACL table */
-        ACL
+        ACL,
+
+        /* VLAN-to-MPLS table */
+        VLAN_MPLS,
+
+        /* VLAN table */
+        VLAN,
+
+        /* L2 table */
+        ETHER,
+
+        /* Class of Service table */
+        COS,
     }
 
     //TODO: build cookie value
diff --git a/core/api/src/main/java/org/onosproject/net/flow/TrafficTreatment.java b/core/api/src/main/java/org/onosproject/net/flow/TrafficTreatment.java
index bfb8f2e..e890e62 100644
--- a/core/api/src/main/java/org/onosproject/net/flow/TrafficTreatment.java
+++ b/core/api/src/main/java/org/onosproject/net/flow/TrafficTreatment.java
@@ -195,6 +195,15 @@
          */
         public Builder group(GroupId groupId);
 
+
+        /**
+         * Sets the next table type to transition to.
+         *
+         * @param type the table type
+         * @return a treatement builder
+         */
+        public Builder transition(FlowRule.Type type);
+
         /**
          * Builds an immutable traffic treatment descriptor.
          *
diff --git a/core/api/src/main/java/org/onosproject/net/flow/instructions/Instruction.java b/core/api/src/main/java/org/onosproject/net/flow/instructions/Instruction.java
index 6f2162f..807aaf8 100644
--- a/core/api/src/main/java/org/onosproject/net/flow/instructions/Instruction.java
+++ b/core/api/src/main/java/org/onosproject/net/flow/instructions/Instruction.java
@@ -50,6 +50,11 @@
         L2MODIFICATION,
 
         /**
+         * Signifies that the traffic should be passed to another table.
+         */
+        TABLE,
+
+        /**
          * Signifies that the traffic should be modified in L3 way.
          */
         L3MODIFICATION
diff --git a/core/api/src/main/java/org/onosproject/net/flow/instructions/Instructions.java b/core/api/src/main/java/org/onosproject/net/flow/instructions/Instructions.java
index 09ec536..246d21a 100644
--- a/core/api/src/main/java/org/onosproject/net/flow/instructions/Instructions.java
+++ b/core/api/src/main/java/org/onosproject/net/flow/instructions/Instructions.java
@@ -23,6 +23,7 @@
 
 import org.onosproject.core.GroupId;
 import org.onosproject.net.PortNumber;
+import org.onosproject.net.flow.FlowRule;
 import org.onosproject.net.flow.instructions.L0ModificationInstruction.L0SubType;
 import org.onosproject.net.flow.instructions.L0ModificationInstruction.ModLambdaInstruction;
 import org.onosproject.net.flow.instructions.L2ModificationInstruction.L2SubType;
@@ -254,6 +255,11 @@
         return new PushHeaderInstructions(L2SubType.MPLS_POP, etherType);
     }
 
+    public static Instruction transition(FlowRule.Type type) {
+        checkNotNull(type, "Table type cannot be null");
+        return new TableTypeTransition(type);
+    }
+
     /*
      *  Drop instructions
      */
@@ -352,6 +358,7 @@
         public Type type() {
             return Type.GROUP;
         }
+
         @Override
         public String toString() {
             return toStringHelper(type().toString())
@@ -377,6 +384,49 @@
         }
     }
 
+    // FIXME: Temporary support for this. This should probably become it's own
+    // type like other instructions.
+    public static class TableTypeTransition implements Instruction {
+        private final FlowRule.Type tableType;
+
+        public TableTypeTransition(FlowRule.Type type) {
+            this.tableType = type;
+        }
+
+        @Override
+        public Type type() {
+            return Type.TABLE;
+        }
+
+        public FlowRule.Type tableType() {
+            return this.tableType;
+        }
+
+        @Override
+        public String toString() {
+            return toStringHelper(type().toString())
+                    .add("group ID", this.tableType).toString();
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(type(), tableType);
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj) {
+                return true;
+            }
+            if (obj instanceof TableTypeTransition) {
+                TableTypeTransition that = (TableTypeTransition) obj;
+                return Objects.equals(tableType, that.tableType);
+
+            }
+            return false;
+        }
+
+    }
 }
 
 
diff --git a/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowSwitch.java b/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowSwitch.java
index f020a1a..a400b8e 100644
--- a/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowSwitch.java
+++ b/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowSwitch.java
@@ -32,6 +32,18 @@
      * It is used only for multi-table support switch.
      */
     public static enum TableType {
+        /* VLAN-to-MPLS table */
+        VLAN_MPLS,
+
+        /* VLAN table */
+        VLAN,
+
+        /* L2 table */
+        ETHER,
+
+        /* Class of Service table */
+        COS,
+
         /* IP table */
         IP,
         /* MPLS table */
@@ -40,6 +52,8 @@
         ACL,
         /* Single table */
         NONE,
+
+
     }
 
     /**
diff --git a/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/AbstractOpenFlowSwitch.java b/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/AbstractOpenFlowSwitch.java
index 6235c5c..555c37d 100644
--- a/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/AbstractOpenFlowSwitch.java
+++ b/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/AbstractOpenFlowSwitch.java
@@ -406,4 +406,6 @@
         return false;
     }
 
+
+
 }
diff --git a/openflow/drivers/src/main/java/org/onosproject/openflow/drivers/OFCorsaSwitchDriver.java b/openflow/drivers/src/main/java/org/onosproject/openflow/drivers/OFCorsaSwitchDriver.java
new file mode 100644
index 0000000..f07725f
--- /dev/null
+++ b/openflow/drivers/src/main/java/org/onosproject/openflow/drivers/OFCorsaSwitchDriver.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.openflow.drivers;
+
+import com.google.common.collect.Lists;
+import org.onosproject.openflow.controller.Dpid;
+import org.onosproject.openflow.controller.RoleState;
+import org.onosproject.openflow.controller.driver.AbstractOpenFlowSwitch;
+import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
+import org.projectfloodlight.openflow.protocol.OFFlowMod;
+import org.projectfloodlight.openflow.protocol.OFMessage;
+import org.projectfloodlight.openflow.protocol.OFType;
+import org.projectfloodlight.openflow.protocol.instruction.OFInstruction;
+import org.projectfloodlight.openflow.protocol.instruction.OFInstructionGotoTable;
+import org.projectfloodlight.openflow.types.TableId;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Corsa switch driver for BGP Router deployment.
+ */
+public class OFCorsaSwitchDriver extends AbstractOpenFlowSwitch {
+
+    private static final int VLAN_MPLS_TABLE = 1;
+    private static final int VLAN_TABLE = 2;
+    private static final int MPLS_TABLE = 3;
+    private static final int ETHER_TABLE = 4;
+    private static final int COS_MAP_TABLE = 5;
+    private static final int FIB_TABLE = 6;
+    private static final int LOCAL_TABLE = 9;
+
+
+
+    OFCorsaSwitchDriver(Dpid dpid, OFDescStatsReply desc) {
+        super(dpid);
+
+        setSwitchDescription(desc);
+    }
+
+    @Override
+    public void write(OFMessage msg) {
+        this.write(Collections.singletonList(msg));
+    }
+
+    @Override
+    public void write(List<OFMessage> msgs) {
+        if (role == RoleState.MASTER) {
+            channel.write(msgs);
+        }
+
+    }
+
+    @Override
+    public void sendMsg(OFMessage msg, TableType type) {
+        if (msg.getType() == OFType.FLOW_MOD) {
+            OFFlowMod flowMod = (OFFlowMod) msg;
+            OFFlowMod.Builder builder = flowMod.createBuilder();
+            List<OFInstruction> instructions = builder.getInstructions();
+            List<OFInstruction> newInstructions = Lists.newArrayList();
+            for (OFInstruction i : instructions) {
+                if (i instanceof OFInstructionGotoTable) {
+                    OFInstructionGotoTable gotoTable = (OFInstructionGotoTable) i;
+                    TableType tid = TableType.values()[gotoTable.getTableId().getValue()];
+                    switch (tid) {
+                        case VLAN_MPLS:
+                            newInstructions.add(
+                                    gotoTable.createBuilder()
+                                            .setTableId(TableId.of(VLAN_MPLS_TABLE)).build());
+                            break;
+                        case VLAN:
+                            newInstructions.add(
+                                    gotoTable.createBuilder()
+                                            .setTableId(TableId.of(VLAN_TABLE)).build());
+                            break;
+                        case ETHER:
+                            newInstructions.add(
+                                    gotoTable.createBuilder()
+                                            .setTableId(TableId.of(ETHER_TABLE)).build());
+                            break;
+                        case COS:
+                            newInstructions.add(
+                                    gotoTable.createBuilder()
+                                            .setTableId(TableId.of(COS_MAP_TABLE)).build());
+                            break;
+                        case IP:
+                            newInstructions.add(
+                                    gotoTable.createBuilder()
+                                            .setTableId(TableId.of(FIB_TABLE)).build());
+                            break;
+                        case MPLS:
+                            newInstructions.add(
+                                    gotoTable.createBuilder()
+                                            .setTableId(TableId.of(MPLS_TABLE)).build());
+                            break;
+                        case ACL:
+                            newInstructions.add(
+                                    gotoTable.createBuilder()
+                                            .setTableId(TableId.of(LOCAL_TABLE)).build());
+                            break;
+                        case NONE:
+                            newInstructions.add(
+                                    gotoTable.createBuilder()
+                                            .setTableId(TableId.of(0)).build());
+                            break;
+                        default:
+                            log.warn("Unknown table type: {}", tid);
+                    }
+
+                } else {
+                    newInstructions.add(i);
+                }
+            }
+            switch (type) {
+                case VLAN_MPLS:
+                    builder.setTableId(TableId.of(VLAN_MPLS_TABLE));
+                    break;
+                case VLAN:
+                    builder.setTableId(TableId.of(VLAN_TABLE));
+                    break;
+                case ETHER:
+                    builder.setTableId(TableId.of(ETHER_TABLE));
+                    break;
+                case COS:
+                    builder.setTableId(TableId.of(COS_MAP_TABLE));
+                    break;
+                case IP:
+                    builder.setTableId(TableId.of(FIB_TABLE));
+                    break;
+                case MPLS:
+                    builder.setTableId(TableId.of(MPLS_TABLE));
+                    break;
+                case ACL:
+                    builder.setTableId(TableId.of(LOCAL_TABLE));
+                    break;
+                case NONE:
+                    builder.setTableId(TableId.of(0));
+                    break;
+                default:
+                    log.warn("Unknown table type: {}", type);
+            }
+            this.write(builder.build());
+        } else {
+            this.write(msg);
+        }
+    }
+
+    @Override
+    public Boolean supportNxRole() {
+        return false;
+    }
+
+    @Override
+    public void startDriverHandshake() {}
+
+    @Override
+    public boolean isDriverHandshakeComplete() {
+        return true;
+    }
+
+    @Override
+    public void processDriverHandshakeMessage(OFMessage m) {}
+}
diff --git a/openflow/drivers/src/main/java/org/onosproject/openflow/drivers/OFOpticalSwitchImplLINC13.java b/openflow/drivers/src/main/java/org/onosproject/openflow/drivers/OFOpticalSwitchImplLINC13.java
index 75f2726..5663c48 100644
--- a/openflow/drivers/src/main/java/org/onosproject/openflow/drivers/OFOpticalSwitchImplLINC13.java
+++ b/openflow/drivers/src/main/java/org/onosproject/openflow/drivers/OFOpticalSwitchImplLINC13.java
@@ -87,7 +87,7 @@
 
     @Override
     public void processDriverHandshakeMessage(OFMessage m) {
-         if (!startDriverHandshakeCalled) {
+        if (!startDriverHandshakeCalled) {
             throw new SwitchDriverSubHandshakeNotStarted();
         }
         if (driverHandshakeComplete.get()) {
diff --git a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilder.java b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilder.java
index 490a157..ff4ae57 100644
--- a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilder.java
+++ b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilder.java
@@ -25,10 +25,6 @@
 import org.onosproject.net.flow.criteria.Criteria;
 import org.onosproject.net.flow.criteria.Criteria.EthCriterion;
 import org.onosproject.net.flow.criteria.Criteria.EthTypeCriterion;
-import org.onosproject.net.flow.criteria.Criteria.IcmpCodeCriterion;
-import org.onosproject.net.flow.criteria.Criteria.IcmpTypeCriterion;
-import org.onosproject.net.flow.criteria.Criteria.Icmpv6CodeCriterion;
-import org.onosproject.net.flow.criteria.Criteria.Icmpv6TypeCriterion;
 import org.onosproject.net.flow.criteria.Criteria.IPCriterion;
 import org.onosproject.net.flow.criteria.Criteria.IPDscpCriterion;
 import org.onosproject.net.flow.criteria.Criteria.IPEcnCriterion;
@@ -36,6 +32,10 @@
 import org.onosproject.net.flow.criteria.Criteria.IPv6FlowLabelCriterion;
 import org.onosproject.net.flow.criteria.Criteria.IPv6NDLinkLayerAddressCriterion;
 import org.onosproject.net.flow.criteria.Criteria.IPv6NDTargetAddressCriterion;
+import org.onosproject.net.flow.criteria.Criteria.IcmpCodeCriterion;
+import org.onosproject.net.flow.criteria.Criteria.IcmpTypeCriterion;
+import org.onosproject.net.flow.criteria.Criteria.Icmpv6CodeCriterion;
+import org.onosproject.net.flow.criteria.Criteria.Icmpv6TypeCriterion;
 import org.onosproject.net.flow.criteria.Criteria.LambdaCriterion;
 import org.onosproject.net.flow.criteria.Criteria.MetadataCriterion;
 import org.onosproject.net.flow.criteria.Criteria.PortCriterion;
@@ -99,7 +99,8 @@
      * @return the new flow mod builder
      */
     public static FlowModBuilder builder(FlowRule flowRule,
-                                         OFFactory factory, Optional<Long> xid) {
+                                         OFFactory factory,
+                                         Optional<Long> xid) {
         switch (factory.getVersion()) {
         case OF_10:
             return new FlowModBuilderVer10(flowRule, factory, xid);
diff --git a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer13.java b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer13.java
index 88ec845..e77096e 100644
--- a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer13.java
+++ b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer13.java
@@ -21,8 +21,9 @@
 import org.onosproject.net.flow.FlowRule;
 import org.onosproject.net.flow.TrafficTreatment;
 import org.onosproject.net.flow.instructions.Instruction;
-import org.onosproject.net.flow.instructions.Instructions.OutputInstruction;
+import org.onosproject.net.flow.instructions.Instructions;
 import org.onosproject.net.flow.instructions.Instructions.GroupInstruction;
+import org.onosproject.net.flow.instructions.Instructions.OutputInstruction;
 import org.onosproject.net.flow.instructions.L0ModificationInstruction;
 import org.onosproject.net.flow.instructions.L0ModificationInstruction.ModLambdaInstruction;
 import org.onosproject.net.flow.instructions.L2ModificationInstruction;
@@ -34,6 +35,7 @@
 import org.onosproject.net.flow.instructions.L3ModificationInstruction;
 import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModIPInstruction;
 import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModIPv6FlowLabelInstruction;
+import org.onosproject.openflow.controller.OpenFlowSwitch;
 import org.projectfloodlight.openflow.protocol.OFFactory;
 import org.projectfloodlight.openflow.protocol.OFFlowAdd;
 import org.projectfloodlight.openflow.protocol.OFFlowDelete;
@@ -42,6 +44,7 @@
 import org.projectfloodlight.openflow.protocol.action.OFAction;
 import org.projectfloodlight.openflow.protocol.action.OFActionGroup;
 import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
+import org.projectfloodlight.openflow.protocol.instruction.OFInstruction;
 import org.projectfloodlight.openflow.protocol.match.Match;
 import org.projectfloodlight.openflow.protocol.oxm.OFOxm;
 import org.projectfloodlight.openflow.types.CircuitSignalID;
@@ -54,6 +57,7 @@
 import org.projectfloodlight.openflow.types.OFGroup;
 import org.projectfloodlight.openflow.types.OFPort;
 import org.projectfloodlight.openflow.types.OFVlanVidMatch;
+import org.projectfloodlight.openflow.types.TableId;
 import org.projectfloodlight.openflow.types.U32;
 import org.projectfloodlight.openflow.types.U64;
 import org.projectfloodlight.openflow.types.VlanPcp;
@@ -92,7 +96,7 @@
     public OFFlowAdd buildFlowAdd() {
         Match match = buildMatch();
         List<OFAction> actions = buildActions();
-
+        List<OFInstruction> instructions = buildInstructions();
         // FIXME had to revert back to using apply-actions instead of
         // write-actions because LINC-OE apparently doesn't support
         // write-actions. I would prefer to change this back in the future
@@ -109,7 +113,7 @@
                 .setCookie(U64.of(cookie))
                 .setBufferId(OFBufferId.NO_BUFFER)
                 .setActions(actions)
-                //.setInstructions(Collections.singletonList(writeActions))
+                .setInstructions(instructions)
                 .setMatch(match)
                 .setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM))
                 .setPriority(flowRule().priority())
@@ -122,6 +126,7 @@
     public OFFlowMod buildFlowMod() {
         Match match = buildMatch();
         List<OFAction> actions = buildActions();
+        List<OFInstruction> instructions = buildInstructions();
         //OFInstruction writeActions =
                 //factory().instructions().writeActions(actions);
 
@@ -133,7 +138,7 @@
                 .setCookie(U64.of(cookie))
                 .setBufferId(OFBufferId.NO_BUFFER)
                 .setActions(actions)
-                //.setInstructions(Collections.singletonList(writeActions))
+                .setInstructions(instructions)
                 .setMatch(match)
                 .setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM))
                 .setPriority(flowRule().priority())
@@ -145,7 +150,6 @@
     @Override
     public OFFlowDelete buildFlowDel() {
         Match match = buildMatch();
-        List<OFAction> actions = buildActions();
 
         long cookie = flowRule().id().value();
 
@@ -161,6 +165,24 @@
         return fm;
     }
 
+
+    private List<OFInstruction> buildInstructions() {
+        List<OFInstruction> instructions = new LinkedList<>();
+        if (treatment == null) {
+            return instructions;
+        }
+        for (Instruction i : treatment.instructions()) {
+            switch (i.type()) {
+                case TABLE:
+                    instructions.add(buildTableGoto(((Instructions.TableTypeTransition) i)));
+                    break;
+                default:
+                    break;
+            }
+        }
+        return instructions;
+    }
+
     private List<OFAction> buildActions() {
         List<OFAction> actions = new LinkedList<>();
         if (treatment == null) {
@@ -168,41 +190,73 @@
         }
         for (Instruction i : treatment.instructions()) {
             switch (i.type()) {
-            case DROP:
-                log.warn("Saw drop action; assigning drop action");
-                return new LinkedList<>();
-            case L0MODIFICATION:
-                actions.add(buildL0Modification(i));
-                break;
-            case L2MODIFICATION:
-                actions.add(buildL2Modification(i));
-                break;
-            case L3MODIFICATION:
-                actions.add(buildL3Modification(i));
-                break;
-            case OUTPUT:
-                OutputInstruction out = (OutputInstruction) i;
-                OFActionOutput.Builder action = factory().actions().buildOutput()
-                        .setPort(OFPort.of((int) out.port().toLong()));
-                if (out.port().equals(PortNumber.CONTROLLER)) {
-                    action.setMaxLen(OFPCML_NO_BUFFER);
-                }
-                actions.add(action.build());
-                break;
-            case GROUP:
-                GroupInstruction group = (GroupInstruction) i;
-                OFActionGroup.Builder groupBuilder = factory().actions().buildGroup()
-                        .setGroup(OFGroup.of(group.groupId().id()));
-                actions.add(groupBuilder.build());
-                break;
-            default:
-                log.warn("Instruction type {} not yet implemented.", i.type());
+                case DROP:
+                    log.warn("Saw drop action; assigning drop action");
+                    return new LinkedList<>();
+                case L0MODIFICATION:
+                    actions.add(buildL0Modification(i));
+                    break;
+                case L2MODIFICATION:
+                    actions.add(buildL2Modification(i));
+                    break;
+                case L3MODIFICATION:
+                    actions.add(buildL3Modification(i));
+                    break;
+                case OUTPUT:
+                    OutputInstruction out = (OutputInstruction) i;
+                    OFActionOutput.Builder action = factory().actions().buildOutput()
+                            .setPort(OFPort.of((int) out.port().toLong()));
+                    if (out.port().equals(PortNumber.CONTROLLER)) {
+                        action.setMaxLen(OFPCML_NO_BUFFER);
+                    }
+                    actions.add(action.build());
+                    break;
+                case GROUP:
+                    GroupInstruction group = (GroupInstruction) i;
+                    OFActionGroup.Builder groupBuilder = factory().actions().buildGroup()
+                            .setGroup(OFGroup.of(group.groupId().id()));
+                    actions.add(groupBuilder.build());
+                    break;
+                default:
+                    log.warn("Instruction type {} not yet implemented.", i.type());
             }
         }
 
         return actions;
     }
 
+    private OFInstruction buildTableGoto(Instructions.TableTypeTransition i) {
+        OFInstruction instruction = factory().instructions().gotoTable(
+                TableId.of(getTableType(i.tableType()).ordinal()));
+        return instruction;
+    }
+
+    // FIXME: this has to go as well perhaps when we implement the SelectorService.
+    private OpenFlowSwitch.TableType getTableType(FlowRule.Type type) {
+        switch (type) {
+
+            case DEFAULT:
+                return OpenFlowSwitch.TableType.NONE;
+            case IP:
+                return OpenFlowSwitch.TableType.IP;
+            case MPLS:
+                return OpenFlowSwitch.TableType.MPLS;
+            case ACL:
+                return OpenFlowSwitch.TableType.ACL;
+            case VLAN_MPLS:
+                return OpenFlowSwitch.TableType.VLAN_MPLS;
+            case VLAN:
+                return OpenFlowSwitch.TableType.VLAN;
+            case ETHER:
+                return OpenFlowSwitch.TableType.ETHER;
+            case COS:
+                return OpenFlowSwitch.TableType.COS;
+            default:
+                return OpenFlowSwitch.TableType.NONE;
+        }
+    }
+
+
     private OFAction buildL0Modification(Instruction i) {
         L0ModificationInstruction l0m = (L0ModificationInstruction) i;
         switch (l0m.subtype()) {
diff --git a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/OpenFlowRuleProvider.java b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/OpenFlowRuleProvider.java
index d6fbaf9..56ced3d 100644
--- a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/OpenFlowRuleProvider.java
+++ b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/OpenFlowRuleProvider.java
@@ -159,8 +159,10 @@
             sw.sendMsg(FlowModBuilder.builder(flowRule, sw.factory(),
                     Optional.empty()).buildFlowAdd());
         } else {
+            OpenFlowSwitch.TableType type = getTableType(flowRule.type());
             sw.sendMsg(FlowModBuilder.builder(flowRule, sw.factory(),
-                    Optional.empty()).buildFlowAdd(), getTableType(flowRule.type()));
+                                              Optional.empty()).buildFlowAdd(),
+                                              type);
         }
     }
 
@@ -230,12 +232,23 @@
 
     private OpenFlowSwitch.TableType getTableType(FlowRule.Type type) {
         switch (type) {
+
+            case DEFAULT:
+                return OpenFlowSwitch.TableType.NONE;
             case IP:
                 return OpenFlowSwitch.TableType.IP;
             case MPLS:
                 return OpenFlowSwitch.TableType.MPLS;
             case ACL:
                 return OpenFlowSwitch.TableType.ACL;
+            case VLAN_MPLS:
+                return OpenFlowSwitch.TableType.VLAN_MPLS;
+            case VLAN:
+                return OpenFlowSwitch.TableType.VLAN;
+            case ETHER:
+                return OpenFlowSwitch.TableType.ETHER;
+            case COS:
+                return OpenFlowSwitch.TableType.COS;
             default:
                 return OpenFlowSwitch.TableType.NONE;
         }