diff --git a/src/main/java/net/floodlightcontroller/core/internal/OFSwitchImplBase.java b/src/main/java/net/floodlightcontroller/core/internal/OFSwitchImplBase.java
index 442dd68..094eef0 100644
--- a/src/main/java/net/floodlightcontroller/core/internal/OFSwitchImplBase.java
+++ b/src/main/java/net/floodlightcontroller/core/internal/OFSwitchImplBase.java
@@ -750,8 +750,8 @@
                 }
 
                 if (log.isDebugEnabled()) {
-                    log.debug("Handling OFPortStatus: {} for {}",
-                            reason, ps);
+                    log.debug("Handling OFPortStatus: {} for {} in sw {}",
+                            reason, ps, getStringId());
                 }
 
                 if (reason == OFPortReason.DELETE)
diff --git a/src/main/java/net/onrc/onos/core/drivermanager/OFSwitchImplCPqD13.java b/src/main/java/net/onrc/onos/core/drivermanager/OFSwitchImplCPqD13.java
index 0931eca..ad84268 100644
--- a/src/main/java/net/onrc/onos/core/drivermanager/OFSwitchImplCPqD13.java
+++ b/src/main/java/net/onrc/onos/core/drivermanager/OFSwitchImplCPqD13.java
@@ -87,7 +87,6 @@
 import org.projectfloodlight.openflow.types.TableId;
 import org.projectfloodlight.openflow.types.TransportPort;
 import org.projectfloodlight.openflow.types.U32;
-import org.projectfloodlight.openflow.types.U64;
 import org.projectfloodlight.openflow.util.HexString;
 
 import com.google.common.collect.Sets;
@@ -99,7 +98,6 @@
  * None
  */
 public class OFSwitchImplCPqD13 extends OFSwitchImplBase implements IOF13Switch {
-    private static final int VLAN_ID_OFFSET = 16;
     private AtomicBoolean driverHandshakeComplete;
     private AtomicBoolean haltStateMachine;
     private OFFactory factory;
@@ -123,15 +121,11 @@
     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 PRIORITY_MULTIPLIER = (short) 2046;
     private static final short MIN_PRIORITY = 0x0;
-    private static final U64 METADATA_MASK = U64.of(Long.MAX_VALUE << 1 | 0x1);
-
-    ConcurrentHashMap<Integer, OFGroup> l2groups;
 
     private long barrierXidToWaitFor = -1;
     private DriverState driverState;
@@ -147,7 +141,6 @@
         haltStateMachine = new AtomicBoolean(false);
         driverState = DriverState.INIT;
         driverHandshakeComplete = new AtomicBoolean(false);
-        l2groups = new ConcurrentHashMap<Integer, OFGroup>();
         setSwitchDescription(desc);
         neighbors = new ConcurrentHashMap<Dpid, Set<PortNumber>>();
         ecmpGroups = new ConcurrentHashMap<NeighborSet, EcmpInfo>();
@@ -186,7 +179,6 @@
         }
     }
 
-
     @Override
     public boolean isDriverHandshakeComplete() {
         if (!startDriverHandshakeCalled)
@@ -228,8 +220,9 @@
 
     protected void nextDriverState() throws IOException {
         DriverState currentState = driverState;
-        if (haltStateMachine.get())
+        if (haltStateMachine.get()) {
             return;
+        }
         switch (currentState) {
         case INIT:
             driverState = DriverState.SET_TABLE_MISS_ENTRIES;
@@ -602,10 +595,9 @@
     }
 
     private void setNeighbors(List<LinkConfig> linkConfigList) {
-        List<PortNumber> portlist = new ArrayList<PortNumber>();
         for (LinkConfig lg : linkConfigList) {
             if (!lg.getType().equals(NetworkConfigManager.PKT_LINK)) {
-                return;
+                continue;
             }
             PktLinkConfig plg = (PktLinkConfig) lg;
             if (plg.getDpid1() == getId()) {
@@ -1137,27 +1129,10 @@
     }
 
     // *****************************
-    // Old Hardcoded Stuff
+    // Unused
     // *****************************
 
-    private void configureSwitch() throws IOException {
-        // setAsyncConfig();
-        // getTableFeatures();
-        sendGroupFeaturesRequest();
-        setL2Groups();
-        sendHandshakeBarrier();
-        setL3Groups();
-        setL25Groups();
-        // setEcmpGroup();
-        sendGroupDescRequest();
-        populateTableVlan();
-        populateTableTMac();
-        populateIpTable();
-        populateMplsTable();
-        populateTableMissEntry(TABLE_ACL, false, false, false, -1);
-        sendHandshakeBarrier();
-    }
-
+    @SuppressWarnings("unused")
     private void setAsyncConfig() throws IOException {
         List<OFMessage> msglist = new ArrayList<OFMessage>(3);
         OFMessage setAC = null;
@@ -1198,6 +1173,7 @@
         write(msglist);
     }
 
+    @SuppressWarnings("unused")
     private void decodeAsyncGetReply(OFAsyncGetReply rep) {
         long frm = rep.getFlowRemovedMaskEqualMaster();
         long frs = rep.getFlowRemovedMaskSlave();
@@ -1214,6 +1190,7 @@
 
     }
 
+    @SuppressWarnings("unused")
     private void getTableFeatures() throws IOException {
         OFMessage gtf = factory.buildTableFeaturesStatsRequest()
                 .setXid(getNextTransactionId())
@@ -1221,6 +1198,7 @@
         write(gtf, null);
     }
 
+    @SuppressWarnings("unused")
     private void sendGroupFeaturesRequest() throws IOException {
         OFMessage gfr = factory.buildGroupFeaturesStatsRequest()
                 .setXid(getNextTransactionId())
@@ -1228,684 +1206,8 @@
         write(gfr, null);
     }
 
-
-    /*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());
-        write(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;
-    }
-
-
-    // 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() == 0x1 && portnum == 7) { // 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);
-        }
-        write(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);
-            }
-        }
-        write(msglist);
-        log.debug("Creating {} MPLS groups in sw {}", msglist.size(), getStringId());
-    }
-
-
     private void processGroupFeatures(OFGroupFeaturesStatsReply gfsr) {
         log.info("Sw: {} Group Features {}", getStringId(), gfsr);
     }
 
-
-
-    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() == 0x2) {
-        }
-        if (getId() == 0x3) {
-            subnetIps.add("7.7.7.0");
-        }
-        return subnetIps;
-    }
-
-    private 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.1.1", 1, "00:00:00:00:01:01")); // Just for Test - SSH
-            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() == 0x2) {
-        }
-        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);
-        }
-        write(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((short) 0xfff0)
-                    .setBufferId(OFBufferId.NO_BUFFER)
-                    .setIdleTimeout(0)
-                    .setHardTimeout(0)
-                    .setXid(getNextTransactionId())
-                    .build();
-            msglist.add(myIpEntry);
-        }
-        write(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();
-
-            List<OFAction> writeActions = new ArrayList<OFAction>();
-            writeActions.add(pushlabel);
-            writeActions.add(copyTtlOut);
-            writeActions.add(setlabelid);
-            // 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();
-
-            if (getId() == 0x1) {
-                OFAction group47 = factory.actions().buildGroup()
-                        .setGroup(OFGroup.of(47)).build();
-                writeActions.add(group47);
-            } else {
-                writeActions.add(outg); // group will decr mpls-ttl, set
-                                        // mac-sa/da,
-                                    // vlan
-            }
-
-            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);
-
-            // 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_META)).build();*/
-            /*instructions.add(applyInstr);
-            instructions.add(writeMeta);*/
-
-            instructions.add(gotoInstr);
-            int priority = -1;
-            if (routerNextHopIps.get(i).mask.equals("255.255.255.255"))
-                priority = MAX_PRIORITY;
-            else
-                priority = (short) 0xfff0;
-            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); */
-
-        }
-        write(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);
-        }
-        write(msglist);
-        log.debug("Adding {} next-hop-host-rules in sw {}", msglist.size(), getStringId());
-    }
-
-    private 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 copyttlin = factory.actions().copyTtlIn();
-            OFAction sendTo = null;
-            if (lfibEntries.get(i).portnum == OFPort.CONTROLLER.getPortNumber()) {
-                sendTo = factory.actions().output(OFPort.CONTROLLER,
-                        OFPCML_NO_BUFFER);
-            } else {
-                // after popping send to L3 intf, not MPLS intf
-                sendTo = factory.actions().group(OFGroup.of(
-                        0x20000000 | lfibEntries.get(i).portnum));
-            }
-            List<OFAction> writeActions = new ArrayList<OFAction>();
-            writeActions.add(copyttlin);
-            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);
-        }
-        write(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);
-
-    }
-
-
 }
