diff --git a/drivers/src/main/java/org/onosproject/driver/handshaker/OFSwitchImplCPqD13.java b/drivers/src/main/java/org/onosproject/driver/handshaker/OFSwitchImplCPqD13.java
new file mode 100644
index 0000000..1c9e66a
--- /dev/null
+++ b/drivers/src/main/java/org/onosproject/driver/handshaker/OFSwitchImplCPqD13.java
@@ -0,0 +1,1189 @@
+/*
+ * 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.driver.handshaker;
+
+import org.onosproject.openflow.controller.RoleState;
+import org.onosproject.openflow.controller.driver.AbstractOpenFlowSwitch;
+import org.onosproject.openflow.controller.driver.SwitchDriverSubHandshakeAlreadyStarted;
+import org.onosproject.openflow.controller.driver.SwitchDriverSubHandshakeCompleted;
+import org.onosproject.openflow.controller.driver.SwitchDriverSubHandshakeNotStarted;
+import org.projectfloodlight.openflow.protocol.OFAsyncGetReply;
+import org.projectfloodlight.openflow.protocol.OFBarrierRequest;
+import org.projectfloodlight.openflow.protocol.OFBucket;
+import org.projectfloodlight.openflow.protocol.OFFactory;
+import org.projectfloodlight.openflow.protocol.OFGroupDescStatsReply;
+import org.projectfloodlight.openflow.protocol.OFGroupFeaturesStatsReply;
+import org.projectfloodlight.openflow.protocol.OFGroupType;
+import org.projectfloodlight.openflow.protocol.OFMatchV3;
+import org.projectfloodlight.openflow.protocol.OFMessage;
+import org.projectfloodlight.openflow.protocol.OFOxmList;
+import org.projectfloodlight.openflow.protocol.OFPortDesc;
+import org.projectfloodlight.openflow.protocol.OFStatsReply;
+import org.projectfloodlight.openflow.protocol.action.OFAction;
+import org.projectfloodlight.openflow.protocol.instruction.OFInstruction;
+import org.projectfloodlight.openflow.protocol.oxm.OFOxmEthDst;
+import org.projectfloodlight.openflow.protocol.oxm.OFOxmEthSrc;
+import org.projectfloodlight.openflow.protocol.oxm.OFOxmEthType;
+import org.projectfloodlight.openflow.protocol.oxm.OFOxmInPort;
+import org.projectfloodlight.openflow.protocol.oxm.OFOxmIpv4DstMasked;
+import org.projectfloodlight.openflow.protocol.oxm.OFOxmMetadataMasked;
+import org.projectfloodlight.openflow.protocol.oxm.OFOxmMplsLabel;
+import org.projectfloodlight.openflow.protocol.oxm.OFOxmVlanVid;
+import org.projectfloodlight.openflow.types.EthType;
+import org.projectfloodlight.openflow.types.IPv4Address;
+import org.projectfloodlight.openflow.types.MacAddress;
+import org.projectfloodlight.openflow.types.OFBufferId;
+import org.projectfloodlight.openflow.types.OFGroup;
+import org.projectfloodlight.openflow.types.OFMetadata;
+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.util.HexString;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * OFDescriptionStatistics Vendor (Manufacturer Desc.): Stanford University,
+ * Ericsson Research and CPqD Research. Make (Hardware Desc.) : OpenFlow 1.3
+ * Reference Userspace Switch Model (Datapath Desc.) : None Software : Serial :
+ * None
+ */
+public class OFSwitchImplCPqD13 extends AbstractOpenFlowSwitch {
+
+    private static final int VLAN_ID_OFFSET = 16;
+    private final AtomicBoolean driverHandshakeComplete = new AtomicBoolean(false);
+    private OFFactory factory;
+    private static final int OFPCML_NO_BUFFER = 0xffff;
+    // Configuration of asynch messages to controller. We need different
+    // asynch messages depending on role-equal or role-master.
+    // We don't want to get anything if we are slave.
+    private static final long SET_FLOW_REMOVED_MASK_MASTER = 0xf;
+    private static final long SET_PACKET_IN_MASK_MASTER = 0x7;
+    private static final long SET_PORT_STATUS_MASK_MASTER = 0x7;
+    private static final long SET_FLOW_REMOVED_MASK_EQUAL = 0x0;
+    private static final long SET_PACKET_IN_MASK_EQUAL = 0x0;
+    private static final long SET_PORT_STATUS_MASK_EQUAL = 0x7;
+    private static final long SET_ALL_SLAVE = 0x0;
+
+    private static final long TEST_FLOW_REMOVED_MASK = 0xf;
+    private static final long TEST_PACKET_IN_MASK = 0x7;
+    private static final long TEST_PORT_STATUS_MASK = 0x7;
+    private long barrierXidToWaitFor = -1;
+
+    private static final int TABLE_VLAN = 0;
+    private static final int TABLE_TMAC = 1;
+    private static final int TABLE_IPV4_UNICAST = 2;
+    private static final int TABLE_MPLS = 3;
+    private static final int TABLE_META = 4;
+    private static final int TABLE_ACL = 5;
+
+    private static final short MAX_PRIORITY = (short) 0xffff;
+    private static final short SLASH_24_PRIORITY = (short) 0xfff0;
+    private static final short MIN_PRIORITY = 0x0;
+    private static final U64 METADATA_MASK = U64.of(Long.MAX_VALUE << 1 | 0x1);
+
+    private final Map<Integer, OFGroup> l2groups = new ConcurrentHashMap<>();
+
+
+    @Override
+    public void startDriverHandshake() {
+        log.debug("Starting driver handshake for sw {}", getStringId());
+        if (startDriverHandshakeCalled) {
+            throw new SwitchDriverSubHandshakeAlreadyStarted();
+        }
+        startDriverHandshakeCalled = true;
+        factory = this.factory();
+
+        sendBarrier(true);
+    }
+
+    @Override
+    public boolean isDriverHandshakeComplete() {
+        if (!startDriverHandshakeCalled) {
+            throw new SwitchDriverSubHandshakeNotStarted();
+        }
+        return driverHandshakeComplete.get();
+    }
+
+    @Override
+    public void processDriverHandshakeMessage(OFMessage m) {
+        if (!startDriverHandshakeCalled) {
+            throw new SwitchDriverSubHandshakeNotStarted();
+        }
+        if (driverHandshakeComplete.get()) {
+            throw new SwitchDriverSubHandshakeCompleted(m);
+        }
+
+        switch (m.getType()) {
+        case BARRIER_REPLY:
+            if (m.getXid() == barrierXidToWaitFor) {
+                driverHandshakeComplete.set(true);
+            }
+            break;
+
+        case ERROR:
+            log.error("Switch {} Error {}", getStringId(), m);
+            break;
+
+        case GET_ASYNC_REPLY:
+            OFAsyncGetReply asrep = (OFAsyncGetReply) m;
+            decodeAsyncGetReply(asrep);
+            break;
+        case STATS_REPLY:
+            processStatsReply((OFStatsReply) m);
+            break;
+        case PACKET_IN:
+        case PORT_STATUS:
+        case QUEUE_GET_CONFIG_REPLY:
+        case ROLE_REPLY:
+        case FEATURES_REPLY:
+        case FLOW_REMOVED:
+            break;
+
+        default:
+            log.debug("Received message {} during switch-driver subhandshake "
+                    + "from switch {} ... Ignoring message", m, getStringId());
+
+        }
+    }
+
+    private void configureSwitch() throws IOException {
+        // setAsyncConfig();
+        // getTableFeatures();
+        sendGroupFeaturesRequest();
+        setL2Groups();
+        sendBarrier(false);
+        setL3Groups();
+        setL25Groups();
+        sendGroupDescRequest();
+        populateTableVlan();
+        populateTableTMac();
+        populateIpTable();
+        populateMplsTable();
+        populateTableMissEntry(TABLE_ACL, false, false, false, -1);
+        sendBarrier(true);
+    }
+
+    private void setAsyncConfig() throws IOException {
+        List<OFMessage> msglist = new ArrayList<OFMessage>(3);
+        OFMessage setAC = null;
+
+        if (role == RoleState.MASTER) {
+            setAC = factory.buildAsyncSet()
+                    .setFlowRemovedMaskEqualMaster(SET_FLOW_REMOVED_MASK_MASTER)
+                    .setPacketInMaskEqualMaster(SET_PACKET_IN_MASK_MASTER)
+                    .setPortStatusMaskEqualMaster(SET_PORT_STATUS_MASK_MASTER)
+                    .setFlowRemovedMaskSlave(SET_ALL_SLAVE)
+                    .setPacketInMaskSlave(SET_ALL_SLAVE)
+                    .setPortStatusMaskSlave(SET_ALL_SLAVE)
+                    .setXid(getNextTransactionId())
+                    .build();
+        } else if (role == RoleState.EQUAL) {
+            setAC = factory.buildAsyncSet()
+                    .setFlowRemovedMaskEqualMaster(SET_FLOW_REMOVED_MASK_EQUAL)
+                    .setPacketInMaskEqualMaster(SET_PACKET_IN_MASK_EQUAL)
+                    .setPortStatusMaskEqualMaster(SET_PORT_STATUS_MASK_EQUAL)
+                    .setFlowRemovedMaskSlave(SET_ALL_SLAVE)
+                    .setPacketInMaskSlave(SET_ALL_SLAVE)
+                    .setPortStatusMaskSlave(SET_ALL_SLAVE)
+                    .setXid(getNextTransactionId())
+                    .build();
+        }
+        msglist.add(setAC);
+
+        OFMessage br = factory.buildBarrierRequest()
+                .setXid(getNextTransactionId())
+                .build();
+        msglist.add(br);
+
+        OFMessage getAC = factory.buildAsyncGetRequest()
+                .setXid(getNextTransactionId())
+                .build();
+        msglist.add(getAC);
+
+        sendMsg(msglist);
+    }
+
+    private void decodeAsyncGetReply(OFAsyncGetReply rep) {
+        long frm = rep.getFlowRemovedMaskEqualMaster();
+        //long frs = rep.getFlowRemovedMaskSlave();
+        long pim = rep.getPacketInMaskEqualMaster();
+        //long pis = rep.getPacketInMaskSlave();
+        long psm = rep.getPortStatusMaskEqualMaster();
+        //long pss = rep.getPortStatusMaskSlave();
+
+        if (role == RoleState.MASTER || role == RoleState.EQUAL) { // should separate
+            log.info("FRM:{}", HexString.toHexString((frm & TEST_FLOW_REMOVED_MASK)));
+            log.info("PIM:{}", HexString.toHexString((pim & TEST_PACKET_IN_MASK)));
+            log.info("PSM:{}", HexString.toHexString((psm & TEST_PORT_STATUS_MASK)));
+        }
+
+    }
+
+    private void getTableFeatures() throws IOException {
+        OFMessage gtf = factory.buildTableFeaturesStatsRequest()
+                .setXid(getNextTransactionId())
+                .build();
+        sendMsg(gtf);
+    }
+
+    private void sendGroupFeaturesRequest() throws IOException {
+        OFMessage gfr = factory.buildGroupFeaturesStatsRequest()
+                .setXid(getNextTransactionId())
+                .build();
+        sendMsg(gfr);
+    }
+
+    private void sendGroupDescRequest() throws IOException {
+        OFMessage gdr = factory.buildGroupDescStatsRequest()
+                .setXid(getNextTransactionId())
+                .build();
+        sendMsg(gdr);
+    }
+
+    /*Create L2 interface groups for all physical ports
+     Naming convention followed is the same as OF-DPA spec
+     eg. port 1 with allowed vlan 10, is enveloped in group with id,
+         0x0 00a 0001, where the uppermost 4 bits identify an L2 interface,
+         the next 12 bits identify the vlan-id, and the lowermost 16 bits
+         identify the port number.*/
+    private void setL2Groups() throws IOException {
+        List<OFMessage> msglist = new ArrayList<OFMessage>();
+        for (OFPortDesc p : getPorts()) {
+            int pnum = p.getPortNo().getPortNumber();
+            int portVlan = getVlanConfig(pnum);
+            if (U32.of(pnum).compareTo(U32.of(OFPort.MAX.getPortNumber())) < 1) {
+                OFGroup gl2 = OFGroup.of(pnum | (portVlan << VLAN_ID_OFFSET));
+                OFAction out = factory.actions().buildOutput()
+                        .setPort(p.getPortNo()).build();
+                OFAction popVlan = factory.actions().popVlan();
+                List<OFAction> actions = new ArrayList<OFAction>();
+                actions.add(popVlan);
+                actions.add(out);
+                OFBucket bucket = factory.buildBucket()
+                        .setActions(actions).build();
+                List<OFBucket> buckets = Collections.singletonList(bucket);
+                OFMessage gmAdd = factory.buildGroupAdd()
+                        .setGroup(gl2)
+                        .setBuckets(buckets)
+                        .setGroupType(OFGroupType.INDIRECT)
+                        .setXid(getNextTransactionId())
+                        .build();
+                msglist.add(gmAdd);
+                l2groups.put(pnum, gl2);
+            }
+        }
+        log.debug("Creating {} L2 groups in sw {}", msglist.size(), getStringId());
+        sendMsg(msglist);
+    }
+
+    private int getVlanConfig(int portnum) {
+        int portVlan = 10 * portnum;
+        if ((getId() == 0x1 && portnum == 6) ||
+                (getId() == 0x2) ||
+                (getId() == 0x3 && portnum == 2)) {
+            portVlan = 192; // 0xc0
+        }
+        return portVlan;
+    }
+
+    private MacAddress getRouterMacAddr() {
+        if (getId() == 0x3) {
+            return MacAddress.of("00:00:07:07:07:80"); // router mac
+        }
+        if (getId() == 0x1) {
+            return MacAddress.of("00:00:01:01:01:80");
+        }
+        // switch 0x2
+        return MacAddress.of("00:00:02:02:02:80");
+    }
+
+    // only for ports connected to other routers
+    private OFAction getDestAction(int portnum) {
+        OFAction setDA = null;
+        MacAddress dAddr = null;
+        if (getId() == 0x1 && portnum == 6) { // connected to switch 2
+            dAddr = MacAddress.of("00:00:02:02:02:80");
+        }
+        if (getId() == 0x2) {
+            if (portnum == 1) { // connected to sw 1
+                dAddr = MacAddress.of("00:00:01:01:01:80");
+            } else if (portnum == 2) { // connected to sw 3
+                dAddr = MacAddress.of("00:00:07:07:07:80");
+            }
+        }
+        if (getId() == 0x3) {
+            if (portnum == 2) { // connected to switch 2
+                dAddr = MacAddress.of("00:00:02:02:02:80");
+            }
+        }
+
+        if (dAddr != null) {
+            OFOxmEthDst dstAddr = factory.oxms().ethDst(dAddr);
+            setDA = factory.actions().buildSetField()
+                    .setField(dstAddr).build();
+        }
+        return setDA;
+    }
+
+    /*
+     * L3 groups are created for all router ports and they all point to corresponding
+     * L2 groups. Only the ports that connect to other routers will have the
+     * DA set.
+     */
+    private void setL3Groups() throws IOException {
+        List<OFMessage> msglist = new ArrayList<OFMessage>();
+        for (OFGroup gl2 : l2groups.values()) {
+            int gnum = gl2.getGroupNumber();
+            int portnum = gnum & 0x0000ffff;
+            int vlanid = ((gnum & 0x0fff0000) >> VLAN_ID_OFFSET);
+            MacAddress sAddr = getRouterMacAddr();
+
+            OFGroup gl3 = OFGroup.of(0x20000000 | portnum);
+            OFAction group = factory.actions().buildGroup()
+                    .setGroup(gl2).build();
+            OFOxmEthSrc srcAddr = factory.oxms().ethSrc(sAddr);
+            OFAction setSA = factory.actions().buildSetField()
+                    .setField(srcAddr).build();
+            OFOxmVlanVid vid = factory.oxms().vlanVid(OFVlanVidMatch.ofVlan(vlanid));
+            OFAction setVlan = factory.actions().buildSetField()
+                    .setField(vid).build();
+            OFAction decTtl = factory.actions().decNwTtl();
+
+            List<OFAction> actions = new ArrayList<OFAction>();
+            actions.add(decTtl); // decrement the IP TTL/do-checksum/check TTL
+            // and MTU
+            actions.add(setVlan); // set the vlan-id of the exit-port (and
+            // l2group)
+            actions.add(setSA); // set this routers mac address
+            // make L3Unicast group setDA for known (configured) ports
+            // that connect to other routers
+            OFAction setDA = getDestAction(portnum);
+            if (setDA != null) {
+                actions.add(setDA);
+            }
+            actions.add(group);
+
+            OFBucket bucket = factory.buildBucket()
+                    .setActions(actions).build();
+            List<OFBucket> buckets = Collections.singletonList(bucket);
+            OFMessage gmAdd = factory.buildGroupAdd()
+                    .setGroup(gl3)
+                    .setBuckets(buckets)
+                    .setGroupType(OFGroupType.INDIRECT)
+                    .setXid(getNextTransactionId())
+                    .build();
+            msglist.add(gmAdd);
+        }
+        sendMsg(msglist);
+        log.debug("Creating {} L3 groups in sw {}", msglist.size(), getStringId());
+    }
+
+    /*
+     * L2.5 or mpls-unicast groups are only created for those router ports
+     * connected to other router ports. They differ from the corresponding
+     * L3-unicast group only by the fact that they decrement the MPLS TTL
+     * instead of the IP ttl
+     */
+    private void setL25Groups() throws IOException {
+        List<OFMessage> msglist = new ArrayList<OFMessage>();
+        for (OFGroup gl2 : l2groups.values()) {
+            int gnum = gl2.getGroupNumber();
+            int portnum = gnum & 0x0000ffff;
+            int vlanid = ((gnum & 0x0fff0000) >> VLAN_ID_OFFSET);
+            MacAddress sAddr = getRouterMacAddr();
+            OFAction setDA = getDestAction(portnum);
+            // setDA will only be non-null for ports connected to routers
+            if (setDA != null) {
+                OFGroup gl3 = OFGroup.of(0xa0000000 | portnum); // different id
+                // for mpls
+                // group
+                OFAction group = factory.actions().buildGroup()
+                        .setGroup(gl2).build();
+                OFOxmEthSrc srcAddr = factory.oxms().ethSrc(sAddr);
+                OFAction setSA = factory.actions().buildSetField()
+                        .setField(srcAddr).build();
+                OFOxmVlanVid vid = factory.oxms().vlanVid(OFVlanVidMatch.ofVlan(vlanid));
+                OFAction setVlan = factory.actions().buildSetField()
+                        .setField(vid).build();
+                OFAction decMplsTtl = factory.actions().decMplsTtl();
+                List<OFAction> actions = new ArrayList<OFAction>();
+                actions.add(decMplsTtl); // decrement the MPLS
+                // TTL/do-checksum/check TTL and MTU
+                actions.add(setVlan); // set the vlan-id of the exit-port (and
+                // l2group)
+                actions.add(setSA); // set this routers mac address
+                actions.add(setDA);
+                actions.add(group);
+                OFBucket bucket = factory.buildBucket()
+                        .setActions(actions).build();
+                List<OFBucket> buckets = Collections.singletonList(bucket);
+                OFMessage gmAdd = factory.buildGroupAdd()
+                        .setGroup(gl3)
+                        .setBuckets(buckets)
+                        .setGroupType(OFGroupType.INDIRECT)
+                        .setXid(getNextTransactionId())
+                        .build();
+                msglist.add(gmAdd);
+            }
+        }
+        sendMsg(msglist);
+        log.debug("Creating {} MPLS groups in sw {}", msglist.size(), getStringId());
+    }
+
+    /* Using ECMP groups
+     *
+     * OFGroup group47 = OFGroup.of(47);
+        OFAction outgroup1 = factory.actions()
+                        .buildGroup()
+                        .setGroup(group61)
+                        .build();
+        OFBucket buc47_1 = factory.buildBucket()
+                        .setWeight(1)
+                        .setActions(Collections.singletonList(outgroup1))
+                        .build();
+        OFAction outgroup2 = factory.actions()
+                        .buildGroup()
+                        .setGroup(group62)
+                        .build();
+        OFBucket buc47_2 = factory.buildBucket()
+                        .setWeight(1)
+                        .setActions(Collections.singletonList(outgroup2))
+                        .build();
+        List<OFBucket> buckets47 = new ArrayList<OFBucket>();
+        buckets47.add(buc47_1);
+        buckets47.add(buc47_2);
+        OFMessage gmS12 = factory.buildGroupAdd()
+                        .setGroup(group47)
+                        .setBuckets(buckets47)
+                        .setGroupType(OFGroupType.SELECT)
+                        .setXid(getNextTransactionId())
+                        .build();
+        write(gmS12, null);     */
+
+    private void processStatsReply(OFStatsReply sr) {
+        switch (sr.getStatsType()) {
+        case AGGREGATE:
+            break;
+        case DESC:
+            break;
+        case EXPERIMENTER:
+            break;
+        case FLOW:
+            break;
+        case GROUP_DESC:
+            processGroupDesc((OFGroupDescStatsReply) sr);
+            break;
+        case GROUP_FEATURES:
+            processGroupFeatures((OFGroupFeaturesStatsReply) sr);
+            break;
+        case METER_CONFIG:
+            break;
+        case METER_FEATURES:
+            break;
+        case PORT_DESC:
+            break;
+        case TABLE_FEATURES:
+            break;
+        default:
+            break;
+
+        }
+    }
+
+    private void processGroupFeatures(OFGroupFeaturesStatsReply gfsr) {
+        log.info("Sw: {} Group Features {}", getStringId(), gfsr);
+    }
+
+    private void processGroupDesc(OFGroupDescStatsReply gdsr) {
+        log.info("Sw: {} Group Desc {}", getStringId(), gdsr);
+    }
+
+    private void populateTableVlan() throws IOException {
+        // for all incoming ports assign configured port-vlans
+        // currently assign portnum*10 -> vlanid to access ports
+        // and vlan 192 to router to router ports
+        List<OFMessage> msglist = new ArrayList<OFMessage>();
+        for (OFPortDesc p : getPorts()) {
+            int pnum = p.getPortNo().getPortNumber();
+            if (U32.of(pnum).compareTo(U32.of(OFPort.MAX.getPortNumber())) < 1) {
+                int vlanid = getVlanConfig(pnum);
+                OFOxmInPort oxp = factory.oxms().inPort(p.getPortNo());
+                OFOxmVlanVid oxv = factory.oxms()
+                        .vlanVid(OFVlanVidMatch.UNTAGGED);
+                OFOxmList oxmList = OFOxmList.of(oxp, oxv);
+                OFMatchV3 match = factory.buildMatchV3()
+                        .setOxmList(oxmList).build();
+                OFOxmVlanVid vidToSet = factory.oxms()
+                        .vlanVid(OFVlanVidMatch.ofVlan(vlanid));
+                OFAction pushVlan = factory.actions().pushVlan(EthType.VLAN_FRAME);
+                OFAction setVlan = factory.actions().setField(vidToSet);
+                List<OFAction> actionlist = new ArrayList<OFAction>();
+                actionlist.add(pushVlan);
+                actionlist.add(setVlan);
+                OFInstruction appAction = factory.instructions().buildApplyActions()
+                        .setActions(actionlist).build();
+                OFInstruction gotoTbl = factory.instructions().buildGotoTable()
+                        .setTableId(TableId.of(TABLE_TMAC)).build();
+                List<OFInstruction> instructions = new ArrayList<OFInstruction>();
+                instructions.add(appAction);
+                instructions.add(gotoTbl);
+                OFMessage flowEntry = factory.buildFlowAdd()
+                        .setTableId(TableId.of(TABLE_VLAN))
+                        .setMatch(match)
+                        .setInstructions(instructions)
+                        .setPriority(1000) // does not matter - all rules
+                        // exclusive
+                        .setBufferId(OFBufferId.NO_BUFFER)
+                        .setIdleTimeout(0)
+                        .setHardTimeout(0)
+                        .setXid(getNextTransactionId())
+                        .build();
+                msglist.add(flowEntry);
+            }
+        }
+        // table-vlan has no table-miss entry, and so packets that miss are
+        // essentially dropped
+        sendMsg(msglist);
+        log.debug("Adding {} vlan-rules in sw {}", msglist.size(), getStringId());
+    }
+
+    private void populateTableTMac() throws IOException {
+        // match for ip packets
+        OFOxmEthType oxe = factory.oxms().ethType(EthType.IPv4);
+        OFOxmList oxmListIp = OFOxmList.of(oxe);
+        OFMatchV3 matchIp = factory.buildMatchV3()
+                .setOxmList(oxmListIp).build();
+        OFInstruction gotoTblIp = factory.instructions().buildGotoTable()
+                .setTableId(TableId.of(TABLE_IPV4_UNICAST)).build();
+        List<OFInstruction> instructionsIp = Collections.singletonList(gotoTblIp);
+        OFMessage ipEntry = factory.buildFlowAdd()
+                .setTableId(TableId.of(TABLE_TMAC))
+                .setMatch(matchIp)
+                .setInstructions(instructionsIp)
+                .setPriority(1000) // strict priority required lower than
+                // multicastMac
+                .setBufferId(OFBufferId.NO_BUFFER)
+                .setIdleTimeout(0)
+                .setHardTimeout(0)
+                .setXid(getNextTransactionId())
+                .build();
+
+        // match for mpls packets
+        OFOxmEthType oxmpls = factory.oxms().ethType(EthType.MPLS_UNICAST);
+        OFOxmList oxmListMpls = OFOxmList.of(oxmpls);
+        OFMatchV3 matchMpls = factory.buildMatchV3()
+                .setOxmList(oxmListMpls).build();
+        OFInstruction gotoTblMpls = factory.instructions().buildGotoTable()
+                .setTableId(TableId.of(TABLE_MPLS)).build();
+        List<OFInstruction> instructionsMpls = Collections.singletonList(gotoTblMpls);
+        OFMessage mplsEntry = factory.buildFlowAdd()
+                .setTableId(TableId.of(TABLE_TMAC))
+                .setMatch(matchMpls)
+                .setInstructions(instructionsMpls)
+                .setPriority(1001) // strict priority required lower than
+                // multicastMac
+                .setBufferId(OFBufferId.NO_BUFFER)
+                .setIdleTimeout(0)
+                .setHardTimeout(0)
+                .setXid(getNextTransactionId())
+                .build();
+
+        // match for everything else to send to controller. Essentially
+        // the table miss flow entry
+        populateTableMissEntry(TABLE_TMAC, true, false, false, -1);
+        log.debug("Adding termination-mac-rules in sw {}", getStringId());
+        List<OFMessage> msglist = new ArrayList<OFMessage>(2);
+        msglist.add(ipEntry);
+        msglist.add(mplsEntry);
+        sendMsg(msglist);
+    }
+
+    private List<String> getMyIps() { // send to controller
+        List<String> myIps = new ArrayList<String>();
+        if (getId() == 0x1) {
+            myIps.add("10.0.2.128");
+            myIps.add("10.0.3.128");
+            myIps.add("10.0.1.128");
+            myIps.add("192.168.0.1");
+        }
+        if (getId() == 0x2) {
+            myIps.add("192.168.0.2");
+        }
+        if (getId() == 0x3) {
+            myIps.add("192.168.0.3");
+            myIps.add("7.7.7.128");
+        }
+        return myIps;
+    }
+
+    private List<String> getMySubnetIps() { // send to controller
+        List<String> subnetIps = new ArrayList<String>();
+        if (getId() == 0x1) {
+            subnetIps.add("10.0.2.0");
+            subnetIps.add("10.0.3.0");
+            subnetIps.add("10.0.1.0");
+        }
+
+        if (getId() == 0x3) {
+            subnetIps.add("7.7.7.0");
+        }
+        return subnetIps;
+    }
+    private static class RouteEntry {
+        String prefix;
+        String mask;
+        int nextHopPort;
+        String dstMac;
+        int label;
+
+        public RouteEntry(String prefix, String mask, int nextHopPort, int label) {
+            this.prefix = prefix;
+            this.mask = mask;
+            this.nextHopPort = nextHopPort;
+            this.label = label;
+        }
+
+        public RouteEntry(String prefix, int nextHopPort, String dstMac) {
+            this.prefix = prefix;
+            this.nextHopPort = nextHopPort;
+            this.dstMac = dstMac;
+        }
+    }
+
+    // send out of mpls-group where the next-hop mac-da is already set
+    private List<RouteEntry> getRouterNextHopIps() {
+        List<RouteEntry> routerNextHopIps = new ArrayList<RouteEntry>();
+        if (getId() == 0x1) {
+            routerNextHopIps
+            .add(new RouteEntry("192.168.0.2", "255.255.255.255", 6, 102));
+            routerNextHopIps
+            .add(new RouteEntry("192.168.0.3", "255.255.255.255", 6, 103));
+            routerNextHopIps.add(new RouteEntry("7.7.7.0", "255.255.255.0", 6, 103));
+        }
+        //if (getId() == 0x2) {
+        /* These are required for normal IP routing without labels.
+            routerNextHopIps.add(new RouteEntry("192.168.0.1","255.255.255.255",1));
+            routerNextHopIps.add(new RouteEntry("192.168.0.3","255.255.255.255",2));
+            routerNextHopIps.add(new RouteEntry("10.0.1.0","255.255.255.0",1));
+            routerNextHopIps.add(new RouteEntry("10.0.2.0","255.255.255.0",1));
+            routerNextHopIps.add(new RouteEntry("10.0.3.0","255.255.255.0",1));
+            routerNextHopIps.add(new RouteEntry("7.7.7.0","255.255.255.0",2));*/
+        //}
+        if (getId() == 0x3) {
+            routerNextHopIps
+            .add(new RouteEntry("192.168.0.2", "255.255.255.255", 2, 102));
+            routerNextHopIps
+            .add(new RouteEntry("192.168.0.1", "255.255.255.255", 2, 101));
+            routerNextHopIps.add(new RouteEntry("10.0.1.0", "255.255.255.0", 2, 101));
+            routerNextHopIps.add(new RouteEntry("10.0.2.0", "255.255.255.0", 2, 101));
+            routerNextHopIps.add(new RouteEntry("10.0.3.0", "255.255.255.0", 2, 101));
+        }
+        return routerNextHopIps;
+    }
+
+    // known host mac-addr, setDA/send out of l3group
+    private List<RouteEntry> getHostNextHopIps() {
+        List<RouteEntry> hostNextHopIps = new ArrayList<RouteEntry>();
+        if (getId() == 0x1) {
+            hostNextHopIps.add(new RouteEntry("10.0.2.1", 4, "00:00:00:00:02:01"));
+            hostNextHopIps.add(new RouteEntry("10.0.3.1", 5, "00:00:00:00:03:01"));
+        }
+        if (getId() == 0x3) {
+            hostNextHopIps.add(new RouteEntry("7.7.7.7", 1, "00:00:07:07:07:07"));
+        }
+        return hostNextHopIps;
+    }
+
+    private void populateIpTable() throws IOException {
+        populateMyIps();
+        populateMySubnets();
+        populateRoutes();
+        populateHostRoutes();
+
+        // match for everything else to send to ACL table. Essentially
+        // the table miss flow entry
+        populateTableMissEntry(TABLE_IPV4_UNICAST, false, true,
+                true, TABLE_ACL);
+    }
+
+    private void populateMyIps() throws IOException {
+        List<OFMessage> msglist = new ArrayList<OFMessage>();
+        // first all my ip's as exact-matches
+        // write-action instruction to send to controller
+        List<String> myIps = getMyIps();
+        for (int i = 0; i < myIps.size(); i++) {
+            OFOxmEthType ethTypeIp = factory.oxms()
+                    .ethType(EthType.IPv4);
+            OFOxmIpv4DstMasked ipPrefix = factory.oxms()
+                    .ipv4DstMasked(IPv4Address.of(myIps.get(i)), IPv4Address.NO_MASK);
+            OFOxmList oxmListSlash32 = OFOxmList.of(ethTypeIp, ipPrefix);
+            OFMatchV3 match = factory.buildMatchV3()
+                    .setOxmList(oxmListSlash32).build();
+            OFAction outc = factory.actions().buildOutput()
+                    .setPort(OFPort.CONTROLLER).setMaxLen(OFPCML_NO_BUFFER)
+                    .build();
+            OFInstruction writeInstr = factory.instructions().buildWriteActions()
+                    .setActions(Collections.singletonList(outc)).build();
+            OFInstruction gotoInstr = factory.instructions().buildGotoTable()
+                    .setTableId(TableId.of(TABLE_ACL)).build();
+            List<OFInstruction> instructions = new ArrayList<OFInstruction>();
+            instructions.add(writeInstr);
+            instructions.add(gotoInstr);
+            OFMessage myIpEntry = factory.buildFlowAdd()
+                    .setTableId(TableId.of(TABLE_IPV4_UNICAST))
+                    .setMatch(match)
+                    .setInstructions(instructions)
+                    .setPriority(MAX_PRIORITY) // highest priority for exact
+                    // match
+                    .setBufferId(OFBufferId.NO_BUFFER)
+                    .setIdleTimeout(0)
+                    .setHardTimeout(0)
+                    .setXid(getNextTransactionId())
+                    .build();
+            msglist.add(myIpEntry);
+        }
+        sendMsg(msglist);
+        log.debug("Adding {} my-ip-rules in sw {}", msglist.size(), getStringId());
+    }
+
+    private void populateMySubnets() throws IOException {
+        List<OFMessage> msglist = new ArrayList<OFMessage>();
+        // next prefix-based subnet-IP's configured on my interfaces
+        // need to ARP for exact-IP, so write-action instruction to send to
+        // controller
+        // this has different mask and priority than earlier case
+        List<String> subnetIps = getMySubnetIps();
+        for (int i = 0; i < subnetIps.size(); i++) {
+            OFOxmEthType ethTypeIp = factory.oxms()
+                    .ethType(EthType.IPv4);
+            OFOxmIpv4DstMasked ipPrefix = factory.oxms().ipv4DstMasked(
+                    IPv4Address.of(subnetIps.get(i)),
+                    IPv4Address.of(0xffffff00)); // '/24' mask
+            OFOxmList oxmListSlash24 = OFOxmList.of(ethTypeIp, ipPrefix);
+            OFMatchV3 match = factory.buildMatchV3()
+                    .setOxmList(oxmListSlash24).build();
+            OFAction outc = factory.actions().buildOutput()
+                    .setPort(OFPort.CONTROLLER).setMaxLen(OFPCML_NO_BUFFER)
+                    .build();
+            OFInstruction writeInstr = factory.instructions().buildWriteActions()
+                    .setActions(Collections.singletonList(outc)).build();
+            OFInstruction gotoInstr = factory.instructions().buildGotoTable()
+                    .setTableId(TableId.of(TABLE_ACL)).build();
+            List<OFInstruction> instructions = new ArrayList<OFInstruction>();
+            instructions.add(writeInstr);
+            instructions.add(gotoInstr);
+            OFMessage myIpEntry = factory.buildFlowAdd()
+                    .setTableId(TableId.of(TABLE_IPV4_UNICAST))
+                    .setMatch(match)
+                    .setInstructions(instructions)
+                    .setPriority(SLASH_24_PRIORITY)
+                    .setBufferId(OFBufferId.NO_BUFFER)
+                    .setIdleTimeout(0)
+                    .setHardTimeout(0)
+                    .setXid(getNextTransactionId())
+                    .build();
+            msglist.add(myIpEntry);
+        }
+        sendMsg(msglist);
+        log.debug("Adding {} subnet-ip-rules in sw {}", msglist.size(), getStringId());
+        msglist.clear();
+    }
+
+    private void populateRoutes() throws IOException {
+        List<OFMessage> msglist = new ArrayList<OFMessage>();
+        // addresses where I know the next-hop's mac-address because it is a
+        // router port - so I have an L3 interface to it (and an MPLS interface)
+        List<RouteEntry> routerNextHopIps = getRouterNextHopIps();
+        for (int i = 0; i < routerNextHopIps.size(); i++) {
+            OFOxmEthType ethTypeIp = factory.oxms()
+                    .ethType(EthType.IPv4);
+            OFOxmIpv4DstMasked ipPrefix = factory.oxms()
+                    .ipv4DstMasked(
+                            IPv4Address.of(routerNextHopIps.get(i).prefix),
+                            IPv4Address.of(routerNextHopIps.get(i).mask)
+                            );
+            OFOxmList oxmListSlash32 = OFOxmList.of(ethTypeIp, ipPrefix);
+            OFMatchV3 match = factory.buildMatchV3()
+                    .setOxmList(oxmListSlash32).build();
+            OFAction outg = factory.actions().buildGroup()
+                    .setGroup(OFGroup.of(0xa0000000 | // mpls group id
+                            routerNextHopIps.get(i).nextHopPort))
+                            .build();
+            // lots of actions before forwarding to mpls group, and
+            // unfortunately
+            // they need to be apply-actions
+
+            OFAction pushlabel = factory.actions().pushMpls(EthType.MPLS_UNICAST);
+            OFOxmMplsLabel l = factory.oxms()
+                    .mplsLabel(U32.of(routerNextHopIps.get(i).label));
+            OFAction setlabelid = factory.actions().buildSetField()
+                    .setField(l).build();
+            OFAction copyTtlOut = factory.actions().copyTtlOut();
+            // OFAction setBos =
+            // factory.actions().buildSetField().setField(bos).build();
+
+            /*
+            writeActions.add(pushlabel);  // need to be apply actions so can be
+            writeActions.add(copyTtlOut); // matched in pseudo-table
+            //writeActions.add(setlabelid); // bad support in cpqd
+            //writeActions.add(setBos); no support in loxigen
+             */
+
+            List<OFAction> applyActions = new ArrayList<OFAction>();
+            applyActions.add(pushlabel);
+            applyActions.add(copyTtlOut);
+            OFInstruction applyInstr = factory.instructions().buildApplyActions()
+                    .setActions(applyActions).build();
+            List<OFAction> writeActions = new ArrayList<OFAction>();
+            writeActions.add(outg); // group will decr mpls-ttl, set mac-sa/da,
+            // vlan
+            OFInstruction writeInstr = factory.instructions().buildWriteActions()
+                    .setActions(writeActions).build();
+
+            // necessary to match in pseudo-table to overcome cpqd 1.3 flaw
+            OFInstruction writeMeta = factory.instructions().buildWriteMetadata()
+                    .setMetadata(U64.of(routerNextHopIps.get(i).label))
+                    .setMetadataMask(METADATA_MASK).build();
+            /*OFInstruction gotoInstr = factory.instructions().buildGotoTable()
+                        .setTableId(TableId.of(TABLE_ACL)).build();*/
+            OFInstruction gotoInstr = factory.instructions().buildGotoTable()
+                    .setTableId(TableId.of(TABLE_META)).build();
+            List<OFInstruction> instructions = new ArrayList<OFInstruction>();
+            instructions.add(applyInstr);
+            // instructions.add(writeInstr);// cannot write here - causes switch
+            // to crash
+            instructions.add(writeMeta);
+            instructions.add(gotoInstr);
+
+            int priority = -1;
+            if (routerNextHopIps.get(i).mask.equals("255.255.255.255")) {
+                priority = MAX_PRIORITY;
+            } else {
+                priority = SLASH_24_PRIORITY;
+            }
+            OFMessage myIpEntry = factory.buildFlowAdd()
+                    .setTableId(TableId.of(TABLE_IPV4_UNICAST))
+                    .setMatch(match)
+                    .setInstructions(instructions)
+                    .setPriority(priority)
+                    .setBufferId(OFBufferId.NO_BUFFER)
+                    .setIdleTimeout(0)
+                    .setHardTimeout(0)
+                    .setXid(getNextTransactionId())
+                    .build();
+            msglist.add(myIpEntry);
+
+            // need to also handle psuedo-table entries to match-metadata and
+            // set mpls
+            // label-id
+            OFOxmEthType ethTypeMpls = factory.oxms()
+                    .ethType(EthType.MPLS_UNICAST);
+            OFOxmMetadataMasked meta = factory.oxms()
+                    .metadataMasked(
+                            OFMetadata.ofRaw(routerNextHopIps.get(i).label),
+                            OFMetadata.NO_MASK);
+            OFOxmList oxmListMeta = OFOxmList.of(ethTypeMpls, meta);
+            OFMatchV3 matchMeta = factory.buildMatchV3()
+                    .setOxmList(oxmListMeta).build();
+            List<OFAction> writeActions2 = new ArrayList<OFAction>();
+            writeActions2.add(setlabelid);
+            OFAction outg2 = factory.actions().buildGroup()
+                    .setGroup(OFGroup.of(routerNextHopIps.get(i).nextHopPort |
+                            (192 << VLAN_ID_OFFSET)))
+                            .build();
+            writeActions2.add(outg2);
+            OFInstruction writeInstr2 = factory.instructions().buildWriteActions()
+                    .setActions(writeActions2).build();
+            OFInstruction gotoInstr2 = factory.instructions().buildGotoTable()
+                    .setTableId(TableId.of(TABLE_ACL)).build();
+            List<OFInstruction> instructions2 = new ArrayList<OFInstruction>();
+            // unfortunately have to apply this action too
+            OFInstruction applyInstr2 = factory.instructions().buildApplyActions()
+                    .setActions(writeActions2).build();
+            instructions2.add(applyInstr2);
+            // instructions2.add(writeInstr2);
+            // instructions2.add(gotoInstr2);
+
+            /*OFMatchV3 match3 = factory.buildMatchV3()
+                        .setOxmList(OFOxmList.of(meta)).build();
+            OFInstruction clearInstruction = factory.instructions().clearActions();
+            List<OFInstruction> instructions3 = new ArrayList<OFInstruction>();
+            OFAction outc = factory.actions().buildOutput()
+                        .setPort(OFPort.CONTROLLER).setMaxLen(OFPCML_NO_BUFFER)
+                        .build();
+            OFInstruction writec = factory.instructions()
+                        .writeActions(Collections.singletonList(outc));
+            instructions3.add(clearInstruction);
+            instructions3.add(writec);
+            instructions3.add(gotoInstr2); */
+            OFMessage myMetaEntry = factory.buildFlowAdd()
+                    .setTableId(TableId.of(TABLE_META))
+                    .setMatch(matchMeta)
+                    .setInstructions(instructions2)
+                    .setPriority(MAX_PRIORITY)
+                    .setBufferId(OFBufferId.NO_BUFFER)
+                    .setIdleTimeout(0)
+                    .setHardTimeout(0)
+                    .setXid(getNextTransactionId())
+                    .build();
+            msglist.add(myMetaEntry);
+
+        }
+        sendMsg(msglist);
+        log.debug("Adding {} next-hop-router-rules in sw {}", msglist.size(),
+                getStringId());
+
+        // add a table-miss entry to table 4 for debugging - leave it out
+        // unclear packet state - causes switch to crash
+        // populateTableMissEntry(TABLE_META, false, true,
+        // true, TABLE_ACL);
+    }
+
+    private void populateHostRoutes() throws IOException {
+        List<OFMessage> msglist = new ArrayList<OFMessage>();
+        // addresses where I know the next hop's mac-address and I can set the
+        // destination mac in the match-instruction.write-action
+        // either I sent out arp-request or I got an arp-request from this host
+        List<RouteEntry> hostNextHopIps = getHostNextHopIps();
+        for (int i = 0; i < hostNextHopIps.size(); i++) {
+            OFOxmEthType ethTypeIp = factory.oxms()
+                    .ethType(EthType.IPv4);
+            OFOxmIpv4DstMasked ipPrefix = factory.oxms()
+                    .ipv4DstMasked(
+                            IPv4Address.of(hostNextHopIps.get(i).prefix),
+                            IPv4Address.NO_MASK); // host addr should be /32
+            OFOxmList oxmListSlash32 = OFOxmList.of(ethTypeIp, ipPrefix);
+            OFMatchV3 match = factory.buildMatchV3()
+                    .setOxmList(oxmListSlash32).build();
+            OFAction setDmac = null, outg = null;
+            OFOxmEthDst dmac = factory.oxms()
+                    .ethDst(MacAddress.of(hostNextHopIps.get(i).dstMac));
+            setDmac = factory.actions().buildSetField()
+                    .setField(dmac).build();
+            outg = factory.actions().buildGroup()
+                    .setGroup(OFGroup.of(0x20000000 | hostNextHopIps.get(i).nextHopPort)) // l3group
+                    // id
+                    .build();
+            List<OFAction> writeActions = new ArrayList<OFAction>();
+            writeActions.add(setDmac);
+            writeActions.add(outg);
+            OFInstruction writeInstr = factory.instructions().buildWriteActions()
+                    .setActions(writeActions).build();
+            OFInstruction gotoInstr = factory.instructions().buildGotoTable()
+                    .setTableId(TableId.of(TABLE_ACL)).build();
+            List<OFInstruction> instructions = new ArrayList<OFInstruction>();
+            instructions.add(writeInstr);
+            instructions.add(gotoInstr);
+            OFMessage myIpEntry = factory.buildFlowAdd()
+                    .setTableId(TableId.of(TABLE_IPV4_UNICAST))
+                    .setMatch(match)
+                    .setInstructions(instructions)
+                    .setPriority(MAX_PRIORITY) // highest priority for exact
+                    // match
+                    .setBufferId(OFBufferId.NO_BUFFER)
+                    .setIdleTimeout(0)
+                    .setHardTimeout(0)
+                    .setXid(getNextTransactionId())
+                    .build();
+            msglist.add(myIpEntry);
+        }
+        sendMsg(msglist);
+        log.debug("Adding {} next-hop-host-rules in sw {}", msglist.size(), getStringId());
+    }
+
+    private static class MplsEntry {
+        int labelid;
+        int portnum;
+
+        public MplsEntry(int labelid, int portnum) {
+            this.labelid = labelid;
+            this.portnum = portnum;
+        }
+    }
+
+    private List<MplsEntry> getMplsEntries() {
+        List<MplsEntry> myLabels = new ArrayList<MplsEntry>();
+        if (getId() == 0x1) {
+            myLabels.add(new MplsEntry(101, OFPort.CONTROLLER.getPortNumber()));
+            myLabels.add(new MplsEntry(103, 6));
+        }
+        if (getId() == 0x2) {
+            myLabels.add(new MplsEntry(103, 2));
+            myLabels.add(new MplsEntry(102, OFPort.CONTROLLER.getPortNumber()));
+            myLabels.add(new MplsEntry(101, 1));
+        }
+        if (getId() == 0x3) {
+            myLabels.add(new MplsEntry(103, OFPort.CONTROLLER.getPortNumber()));
+            myLabels.add(new MplsEntry(101, 2));
+        }
+        return myLabels;
+    }
+
+    private void populateMplsTable() throws IOException {
+        List<OFMessage> msglist = new ArrayList<OFMessage>();
+        List<MplsEntry> lfibEntries = getMplsEntries();
+        for (int i = 0; i < lfibEntries.size(); i++) {
+            OFOxmEthType ethTypeMpls = factory.oxms()
+                    .ethType(EthType.MPLS_UNICAST);
+            OFOxmMplsLabel labelid = factory.oxms()
+                    .mplsLabel(U32.of(lfibEntries.get(i).labelid));
+            OFOxmList oxmList = OFOxmList.of(ethTypeMpls, labelid);
+            OFMatchV3 matchlabel = factory.buildMatchV3()
+                    .setOxmList(oxmList).build();
+            OFAction poplabel = factory.actions().popMpls(EthType.IPv4);
+            OFAction sendTo = null;
+            if (lfibEntries.get(i).portnum == OFPort.CONTROLLER.getPortNumber()) {
+                sendTo = factory.actions().output(OFPort.CONTROLLER,
+                        OFPCML_NO_BUFFER);
+            } else {
+                sendTo = factory.actions().group(OFGroup.of(
+                        0xa0000000 | lfibEntries.get(i).portnum));
+            }
+            List<OFAction> writeActions = new ArrayList<OFAction>();
+            writeActions.add(poplabel);
+            writeActions.add(sendTo);
+            OFInstruction writeInstr = factory.instructions().buildWriteActions()
+                    .setActions(writeActions).build();
+            OFInstruction gotoInstr = factory.instructions().buildGotoTable()
+                    .setTableId(TableId.of(TABLE_ACL)).build();
+            List<OFInstruction> instructions = new ArrayList<OFInstruction>();
+            instructions.add(writeInstr);
+            instructions.add(gotoInstr);
+            OFMessage myMplsEntry = factory.buildFlowAdd()
+                    .setTableId(TableId.of(TABLE_MPLS))
+                    .setMatch(matchlabel)
+                    .setInstructions(instructions)
+                    .setPriority(MAX_PRIORITY) // exact match and exclusive
+                    .setBufferId(OFBufferId.NO_BUFFER)
+                    .setIdleTimeout(0)
+                    .setHardTimeout(0)
+                    .setXid(getNextTransactionId())
+                    .build();
+            msglist.add(myMplsEntry);
+        }
+        sendMsg(msglist);
+        log.debug("Adding {} mpls-forwarding-rules in sw {}", msglist.size(),
+                getStringId());
+
+        // match for everything else to send to ACL table. Essentially
+        // the table miss flow entry
+        populateTableMissEntry(TABLE_MPLS, false, true,
+                true, TABLE_ACL);
+
+    }
+
+    /**
+     * By default if none of the booleans in the call are set, then the
+     * table-miss entry is added with no instructions, which means that pipeline
+     * execution will stop, and the action set associated with the packet will
+     * be executed.
+     *
+     * @param tableToAdd
+     * @param toControllerNow as an APPLY_ACTION instruction
+     * @param toControllerWrite as a WRITE_ACITION instruction
+     * @param toTable as a GOTO_TABLE instruction
+     * @param tableToSend
+     * @throws java.io.IOException
+     */
+    @SuppressWarnings("unchecked")
+    private void populateTableMissEntry(int tableToAdd, boolean toControllerNow,
+            boolean toControllerWrite,
+            boolean toTable, int tableToSend) {
+        OFOxmList oxmList = OFOxmList.EMPTY;
+        OFMatchV3 match = factory.buildMatchV3()
+                .setOxmList(oxmList)
+                .build();
+        OFAction outc = factory.actions()
+                .buildOutput()
+                .setPort(OFPort.CONTROLLER)
+                .setMaxLen(OFPCML_NO_BUFFER)
+                .build();
+        List<OFInstruction> instructions = new ArrayList<OFInstruction>();
+        if (toControllerNow) {
+            // table-miss instruction to send to controller immediately
+            OFInstruction instr = factory.instructions()
+                    .buildApplyActions()
+                    .setActions(Collections.singletonList(outc))
+                    .build();
+            instructions.add(instr);
+        }
+
+        if (toControllerWrite) {
+            // table-miss instruction to write-action to send to controller
+            // this will be executed whenever the action-set gets executed
+            OFInstruction instr = factory.instructions()
+                    .buildWriteActions()
+                    .setActions(Collections.singletonList(outc))
+                    .build();
+            instructions.add(instr);
+        }
+
+        if (toTable) {
+            // table-miss instruction to goto-table x
+            OFInstruction instr = factory.instructions()
+                    .gotoTable(TableId.of(tableToSend));
+            instructions.add(instr);
+        }
+
+        if (!toControllerNow && !toControllerWrite && !toTable) {
+            // table-miss has no instruction - at which point action-set will be
+            // executed - if there is an action to output/group in the action
+            // set
+            // the packet will be sent there, otherwise it will be dropped.
+            instructions = Collections.EMPTY_LIST;
+        }
+
+        OFMessage tableMissEntry = factory.buildFlowAdd()
+                .setTableId(TableId.of(tableToAdd))
+                .setMatch(match) // match everything
+                .setInstructions(instructions)
+                .setPriority(MIN_PRIORITY)
+                .setBufferId(OFBufferId.NO_BUFFER)
+                .setIdleTimeout(0)
+                .setHardTimeout(0)
+                .setXid(getNextTransactionId())
+                .build();
+
+        sendMsg(tableMissEntry);
+    }
+
+    private void sendBarrier(boolean finalBarrier) {
+        int xid = getNextTransactionId();
+        if (finalBarrier) {
+            barrierXidToWaitFor = xid;
+        }
+        OFBarrierRequest br = factory
+                .buildBarrierRequest()
+                .setXid(xid)
+                .build();
+
+        sendMsg(br);
+    }
+
+    @Override
+    public Boolean supportNxRole() {
+        return false;
+    }
+}
