Knocking off OFSwitchImplCPqD13 java file as all the logic is moved to OFSwitchImplSpringOpenTTP and this file is no more required
diff --git a/src/main/java/net/onrc/onos/core/drivermanager/OFSwitchImplCPqD13.java b/src/main/java/net/onrc/onos/core/drivermanager/OFSwitchImplCPqD13.java
deleted file mode 100644
index a93a730..0000000
--- a/src/main/java/net/onrc/onos/core/drivermanager/OFSwitchImplCPqD13.java
+++ /dev/null
@@ -1,2165 +0,0 @@
-package net.onrc.onos.core.drivermanager;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import net.floodlightcontroller.core.IFloodlightProviderService.Role;
-import net.floodlightcontroller.core.IOF13Switch;
-import net.floodlightcontroller.core.IOFSwitch;
-import net.floodlightcontroller.core.SwitchDriverSubHandshakeAlreadyStarted;
-import net.floodlightcontroller.core.SwitchDriverSubHandshakeCompleted;
-import net.floodlightcontroller.core.SwitchDriverSubHandshakeNotStarted;
-import net.floodlightcontroller.core.internal.OFSwitchImplBase;
-import net.floodlightcontroller.util.MACAddress;
-import net.floodlightcontroller.util.OrderedCollection;
-import net.onrc.onos.core.configmanager.INetworkConfigService;
-import net.onrc.onos.core.configmanager.INetworkConfigService.NetworkConfigState;
-import net.onrc.onos.core.configmanager.INetworkConfigService.SwitchConfigStatus;
-import net.onrc.onos.core.configmanager.NetworkConfig.LinkConfig;
-import net.onrc.onos.core.configmanager.NetworkConfig.SwitchConfig;
-import net.onrc.onos.core.configmanager.NetworkConfigManager;
-import net.onrc.onos.core.configmanager.PktLinkConfig;
-import net.onrc.onos.core.configmanager.SegmentRouterConfig;
-import net.onrc.onos.core.configmanager.SegmentRouterConfig.AdjacencySid;
-import net.onrc.onos.core.matchaction.MatchAction;
-import net.onrc.onos.core.matchaction.MatchActionOperationEntry;
-import net.onrc.onos.core.matchaction.MatchActionOperations;
-import net.onrc.onos.core.matchaction.MatchActionOperations.Operator;
-import net.onrc.onos.core.matchaction.action.Action;
-import net.onrc.onos.core.matchaction.action.CopyTtlInAction;
-import net.onrc.onos.core.matchaction.action.CopyTtlOutAction;
-import net.onrc.onos.core.matchaction.action.DecMplsTtlAction;
-import net.onrc.onos.core.matchaction.action.DecNwTtlAction;
-import net.onrc.onos.core.matchaction.action.GroupAction;
-import net.onrc.onos.core.matchaction.action.ModifyDstMacAction;
-import net.onrc.onos.core.matchaction.action.ModifySrcMacAction;
-import net.onrc.onos.core.matchaction.action.OutputAction;
-import net.onrc.onos.core.matchaction.action.PopMplsAction;
-import net.onrc.onos.core.matchaction.action.PushMplsAction;
-import net.onrc.onos.core.matchaction.action.SetDAAction;
-import net.onrc.onos.core.matchaction.action.SetMplsBosAction;
-import net.onrc.onos.core.matchaction.action.SetMplsIdAction;
-import net.onrc.onos.core.matchaction.action.SetSAAction;
-import net.onrc.onos.core.matchaction.match.Ipv4Match;
-import net.onrc.onos.core.matchaction.match.Match;
-import net.onrc.onos.core.matchaction.match.MplsMatch;
-import net.onrc.onos.core.matchaction.match.PacketMatch;
-import net.onrc.onos.core.util.Dpid;
-import net.onrc.onos.core.util.IPv4Net;
-import net.onrc.onos.core.util.PortNumber;
-
-import org.codehaus.jackson.map.ObjectMapper;
-import org.projectfloodlight.openflow.protocol.OFAsyncGetReply;
-import org.projectfloodlight.openflow.protocol.OFBarrierRequest;
-import org.projectfloodlight.openflow.protocol.OFBucket;
-import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
-import org.projectfloodlight.openflow.protocol.OFErrorMsg;
-import org.projectfloodlight.openflow.protocol.OFFactory;
-import org.projectfloodlight.openflow.protocol.OFFlowMod;
-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.OFPortStatus;
-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.match.Match.Builder;
-import org.projectfloodlight.openflow.protocol.match.MatchField;
-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.OFOxmMplsBos;
-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.IpProtocol;
-import org.projectfloodlight.openflow.types.MacAddress;
-import org.projectfloodlight.openflow.types.OFBooleanValue;
-import org.projectfloodlight.openflow.types.OFBufferId;
-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.TransportPort;
-import org.projectfloodlight.openflow.types.U32;
-import org.projectfloodlight.openflow.util.HexString;
-
-/**
- * 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 OFSwitchImplBase implements IOF13Switch {
-    private AtomicBoolean driverHandshakeComplete;
-    private AtomicBoolean haltStateMachine;
-    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 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_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 long barrierXidToWaitFor = -1;
-    private DriverState driverState;
-    private final boolean usePipeline13;
-    private SegmentRouterConfig srConfig;
-    private ConcurrentMap<Dpid, Set<PortNumber>> neighbors;
-    private ConcurrentMap<PortNumber, Dpid> portToNeighbors;
-    private List<Integer> segmentIds;
-    private boolean isEdgeRouter;
-    private ConcurrentMap<NeighborSet, EcmpInfo> ecmpGroups;
-    private ConcurrentMap<Integer, EcmpInfo> userDefinedGroups;
-    private ConcurrentMap<PortNumber, ArrayList<NeighborSet>> portNeighborSetMap;
-    private AtomicInteger groupid;
-    private Map<String, String> publishAttributes;
-
-    public OFSwitchImplCPqD13(OFDescStatsReply desc, boolean usePipeline13) {
-        super();
-        haltStateMachine = new AtomicBoolean(false);
-        driverState = DriverState.INIT;
-        driverHandshakeComplete = new AtomicBoolean(false);
-        setSwitchDescription(desc);
-        neighbors = new ConcurrentHashMap<Dpid, Set<PortNumber>>();
-        portToNeighbors = new ConcurrentHashMap<PortNumber, Dpid>();
-        ecmpGroups = new ConcurrentHashMap<NeighborSet, EcmpInfo>();
-        userDefinedGroups = new ConcurrentHashMap<Integer, EcmpInfo>();
-        portNeighborSetMap =
-                new ConcurrentHashMap<PortNumber, ArrayList<NeighborSet>>();
-        segmentIds = new ArrayList<Integer>();
-        isEdgeRouter = false;
-        groupid = new AtomicInteger(0);
-        this.usePipeline13 = usePipeline13;
-    }
-
-    // *****************************
-    // OFSwitchImplBase
-    // *****************************
-
-
-    /* (non-Javadoc)
-     * @see java.lang.Object#toString()
-     */
-    @Override
-    public String toString() {
-        return "OFSwitchImplCPqD13 [" + ((channel != null)
-                ? channel.getRemoteAddress() : "?")
-                + " DPID[" + ((stringId != null) ? stringId : "?") + "]]";
-    }
-
-    @Override
-    public void startDriverHandshake() throws IOException {
-        log.debug("Starting driver handshake for sw {}", getStringId());
-        if (startDriverHandshakeCalled) {
-            throw new SwitchDriverSubHandshakeAlreadyStarted();
-        }
-        startDriverHandshakeCalled = true;
-        factory = getFactory();
-        if (!usePipeline13) {
-            // Send packet-in to controller if a packet misses the first table
-            populateTableMissEntry(0, true, false, false, 0);
-            driverHandshakeComplete.set(true);
-        } else {
-            nextDriverState();
-        }
-    }
-
-    @Override
-    public boolean isDriverHandshakeComplete() {
-        if (!startDriverHandshakeCalled)
-            throw new SwitchDriverSubHandshakeNotStarted();
-        return driverHandshakeComplete.get();
-    }
-
-    @Override
-    public void processDriverHandshakeMessage(OFMessage m) {
-        if (!startDriverHandshakeCalled)
-            throw new SwitchDriverSubHandshakeNotStarted();
-        if (isDriverHandshakeComplete())
-            throw new SwitchDriverSubHandshakeCompleted(m);
-        try {
-            processOFMessage(this, m);
-        } catch (IOException e) {
-            log.error("Error generated when processing OFMessage", e.getCause());
-        }
-    }
-
-    @Override
-    public String getSwitchDriverState() {
-        return driverState.toString();
-    }
-
-    public void removePortFromGroups(PortNumber port) {
-        log.debug("removePortFromGroups: Remove port {} from Switch {}",
-                port, getStringId());
-        ArrayList<NeighborSet> portNSSet = portNeighborSetMap.get(port);
-        if (portNSSet == null)
-        {
-            /* No Groups are created with this port yet */
-            log.warn("removePortFromGroups: No groups exist with Switch {} port {}",
-                            getStringId(), port);
-            return;
-        }
-        log.debug("removePortFromGroups: Neighborsets that the port {} is part"
-                + "of on Switch {} are {}",
-                port, getStringId(), portNSSet);
-
-        for (NeighborSet ns : portNSSet) {
-            /* Delete the first matched bucket */
-            EcmpInfo portEcmpInfo = ecmpGroups.get(ns);
-            Iterator<BucketInfo> it = portEcmpInfo.buckets.iterator();
-            log.debug("removePortFromGroups: Group {} on Switch {} has {} buckets",
-                    portEcmpInfo.groupId, getStringId(),
-                    portEcmpInfo.buckets.size());
-            while (it.hasNext()) {
-                BucketInfo bucket = it.next();
-                if (bucket.outport.equals(port)) {
-                    it.remove();
-                }
-            }
-            log.debug("removePortFromGroups: Modifying Group on Switch {} "
-                    + "and Neighborset {} with {}",
-                    getStringId(), ns, portEcmpInfo);
-            modifyEcmpGroup(portEcmpInfo);
-        }
-        /* Don't delete the entry from portNeighborSetMap because
-          * when the port is up again this info is needed
-          */
-        return;
-    }
-
-    public void addPortToGroups(PortNumber port) {
-        log.debug("addPortToGroups: Add port {} to Switch {}",
-                port, getStringId());
-        ArrayList<NeighborSet> portNSSet = portNeighborSetMap.get(port);
-        if (portNSSet == null) {
-            /* Unknown Port  */
-            log.warn("addPortToGroups: Switch {} port {} is unknown",
-                            getStringId(), port);
-            return;
-        }
-        log.debug("addPortToGroups: Neighborsets that the port {} is part"
-                + "of on Switch {} are {}",
-                port, getStringId(), portNSSet);
-
-        Dpid neighborDpid = portToNeighbors.get(port);
-        for (NeighborSet ns : portNSSet) {
-            EcmpInfo portEcmpInfo = ecmpGroups.get(ns);
-            /* Find if this port is already part of any bucket
-             * in this group
-             * NOTE: This is needed because in some cases
-             * (such as for configured network nodes), both driver and
-             * application detect the network elements and creates the
-             * buckets in the same group. This check is to avoid
-             * duplicate bucket creation in such scenarios
-             */
-            List<BucketInfo> buckets = portEcmpInfo.buckets;
-            if (buckets == null) {
-                buckets = new ArrayList<BucketInfo>();
-                portEcmpInfo.buckets = buckets;
-            } else {
-                Iterator<BucketInfo> it = buckets.iterator();
-                boolean matchingBucketExist = false;
-                while (it.hasNext()) {
-                    BucketInfo bucket = it.next();
-                    if (bucket.outport.equals(port)) {
-                        matchingBucketExist = true;
-                        break;
-                    }
-                }
-                if (matchingBucketExist) {
-                    log.warn("addPortToGroups: On Switch {} duplicate "
-                            + "portAdd is called for port {} with buckets {}",
-                            getStringId(), port, buckets);
-                    continue;
-                }
-            }
-            BucketInfo b = new BucketInfo(neighborDpid,
-                    MacAddress.of(srConfig.getRouterMac()),
-                    getNeighborRouterMacAddress(neighborDpid),
-                    port,
-                    ns.getEdgeLabel(), true, -1);
-            buckets.add(b);
-            log.debug("addPortToGroups: Modifying Group on Switch {} "
-                    + "and Neighborset {} with {}",
-                    getStringId(), ns, portEcmpInfo);
-            modifyEcmpGroup(portEcmpInfo);
-        }
-        return;
-    }
-
-    @Override
-    public OrderedCollection<PortChangeEvent> processOFPortStatus(OFPortStatus ps) {
-        OrderedCollection<PortChangeEvent> events = super.processOFPortStatus(ps);
-        for (PortChangeEvent e : events) {
-            switch (e.type) {
-            case DELETE:
-            case DOWN:
-                log.debug("processOFPortStatus: sw {} Port {} DOWN",
-                        getStringId(), e.port.getPortNo().getPortNumber());
-                removePortFromGroups(PortNumber.uint32(
-                        e.port.getPortNo().getPortNumber()));
-                break;
-            case UP:
-                log.debug("processOFPortStatus: sw {} Port {} UP",
-                        getStringId(), e.port.getPortNo().getPortNumber());
-                addPortToGroups(PortNumber.uint32(
-                        e.port.getPortNo().getPortNumber()));
-            }
-        }
-        return events;
-    }
-
-    // *****************************
-    // Driver handshake state-machine
-    // *****************************
-
-    enum DriverState {
-        INIT,
-        SET_TABLE_MISS_ENTRIES,
-        SET_TABLE_VLAN_TMAC,
-        SET_GROUPS,
-        VERIFY_GROUPS,
-        SET_ADJACENCY_LABELS,
-        EXIT
-    }
-
-    protected void nextDriverState() throws IOException {
-        DriverState currentState = driverState;
-        if (haltStateMachine.get()) {
-            return;
-        }
-        switch (currentState) {
-        case INIT:
-            driverState = DriverState.SET_TABLE_MISS_ENTRIES;
-            setTableMissEntries();
-            sendHandshakeBarrier();
-            break;
-        case SET_TABLE_MISS_ENTRIES:
-            driverState = DriverState.SET_TABLE_VLAN_TMAC;
-            getNetworkConfig();
-            populateTableVlan();
-            populateTableTMac();
-            sendHandshakeBarrier();
-            break;
-        case SET_TABLE_VLAN_TMAC:
-            driverState = DriverState.SET_GROUPS;
-            createGroups();
-            sendHandshakeBarrier();
-            break;
-        case SET_GROUPS:
-            driverState = DriverState.VERIFY_GROUPS;
-            verifyGroups();
-            break;
-        case VERIFY_GROUPS:
-            driverState = DriverState.SET_ADJACENCY_LABELS;
-            assignAdjacencyLabels();
-            break;
-        case SET_ADJACENCY_LABELS:
-            driverState = DriverState.EXIT;
-            driverHandshakeComplete.set(true);
-            break;
-        case EXIT:
-        default:
-            driverState = DriverState.EXIT;
-            log.error("Driver handshake has exited for sw: {}", getStringId());
-        }
-    }
-
-    void processOFMessage(IOFSwitch sw, OFMessage m) throws IOException {
-        switch (m.getType()) {
-        case BARRIER_REPLY:
-            processBarrierReply(m);
-            break;
-
-        case ERROR:
-            processErrorMessage(m);
-            break;
-
-        case GET_ASYNC_REPLY:
-            OFAsyncGetReply asrep = (OFAsyncGetReply) m;
-            decodeAsyncGetReply(asrep);
-            break;
-
-        case PACKET_IN:
-            // not ready to handle packet-ins
-            break;
-
-        case QUEUE_GET_CONFIG_REPLY:
-            // not doing queue config yet
-            break;
-
-        case STATS_REPLY:
-            processStatsReply((OFStatsReply) m);
-            break;
-
-        case ROLE_REPLY: // channelHandler should handle this
-        case PORT_STATUS: // channelHandler should handle this
-        case FEATURES_REPLY: // don't care
-        case FLOW_REMOVED: // don't care
-        default:
-            log.debug("Received message {} during switch-driver subhandshake "
-                    + "from switch {} ... Ignoring message", m, sw.getStringId());
-        }
-    }
-
-    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 processErrorMessage(OFMessage m) {
-        log.error("Switch {} Error {} in DriverState", getStringId(),
-                (OFErrorMsg) m, driverState);
-    }
-
-    private void processBarrierReply(OFMessage m) throws IOException {
-        if (m.getXid() == barrierXidToWaitFor) {
-            // Driver state-machine progresses to the next state.
-            // If Barrier messages is not received, then eventually
-            // the ChannelHandler state machine will timeout, and the switch
-            // will be disconnected.
-            nextDriverState();
-        } else {
-            log.error("Received incorrect barrier-message xid {} (expected: {}) in "
-                    + "switch-driver state {} for switch {}", m, barrierXidToWaitFor,
-                    driverState, getStringId());
-        }
-    }
-
-    private void processGroupDesc(OFGroupDescStatsReply gdsr) {
-        log.info("Sw: {} Group Desc {}", getStringId(), gdsr);
-        // TODO -- actually do verification
-        try {
-            nextDriverState();
-        } catch (IOException e) {
-            // TODO Auto-generated catch block
-            e.printStackTrace();
-        }
-    }
-
-    // *****************************
-    // Utility methods
-    // *****************************
-
-    void setTableMissEntries() throws IOException {
-        // set all table-miss-entries
-        populateTableMissEntry(TABLE_VLAN, true, false, false, -1);
-        populateTableMissEntry(TABLE_TMAC, true, false, false, -1);
-        populateTableMissEntry(TABLE_IPv4_UNICAST, false, true, true,
-                TABLE_ACL);
-        populateTableMissEntry(TABLE_MPLS, false, true, true,
-                TABLE_ACL);
-        populateTableMissEntry(TABLE_ACL, false, false, false, -1);
-    }
-
-    private void sendHandshakeBarrier() throws IOException {
-        long xid = getNextTransactionId();
-        barrierXidToWaitFor = xid;
-        OFBarrierRequest br = getFactory()
-                .buildBarrierRequest()
-                .setXid(xid)
-                .build();
-        write(br, null);
-    }
-
-    /**
-     * Adds a table-miss-entry to a pipeline table.
-     * <p>
-     * The table-miss-entry can be added with 'write-actions' or
-     * 'apply-actions'. It can also add a 'goto-table' instruction. 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 if a packet hits the
-     * table-miss-entry, pipeline execution will stop, and the action set
-     * associated with the packet will be executed.
-     *
-     * @param tableToAdd the table to where the table-miss-entry will be added
-     * @param toControllerNow as an APPLY_ACTION instruction
-     * @param toControllerWrite as a WRITE_ACTION instruction
-     * @param toTable as a GOTO_TABLE instruction
-     * @param tableToSend the table to send as per the GOTO_TABLE instruction it
-     *        needs to be set if 'toTable' is true. Ignored of 'toTable' is
-     *        false.
-     * @throws IOException
-     */
-    @SuppressWarnings("unchecked")
-    private void populateTableMissEntry(int tableToAdd, boolean toControllerNow,
-            boolean toControllerWrite,
-            boolean toTable, int tableToSend) throws IOException {
-        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 = (List<OFInstruction>) 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();
-        write(tableMissEntry, null);
-    }
-
-    private void getNetworkConfig() {
-        INetworkConfigService ncs = floodlightProvider.getNetworkConfigService();
-        SwitchConfigStatus scs = ncs.checkSwitchConfig(new Dpid(getId()));
-        if (scs.getConfigState() == NetworkConfigState.ACCEPT_ADD) {
-            srConfig = (SegmentRouterConfig) scs.getSwitchConfig();
-            isEdgeRouter = srConfig.isEdgeRouter();
-        } else {
-            log.error("Switch not configured as Segment-Router");
-        }
-
-        List<LinkConfig> linkConfigList = ncs.getConfiguredAllowedLinks();
-        setNeighbors(linkConfigList);
-
-        if (isEdgeRouter) {
-            List<SwitchConfig> switchList = ncs.getConfiguredAllowedSwitches();
-            getAllNodeSegmentIds(switchList);
-        }
-    }
-
-    private void populateTableVlan() throws IOException {
-        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) {
-                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();
-
-                // TODO: match on vlan-tagged packets for vlans configured on
-                // subnet ports and strip-vlan
-
-                // Do not need to add vlans
-                /*int vlanid = getVlanConfig(pnum);
-                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);
-            }
-        }
-        write(msglist);
-        log.debug("Adding {} port/vlan-rules in sw {}", msglist.size(), getStringId());
-    }
-
-    private void populateTableTMac() throws IOException {
-        // match for router-mac and ip-packets
-        OFOxmEthType oxe = factory.oxms().ethType(EthType.IPv4);
-        OFOxmEthDst dmac = factory.oxms().ethDst(getRouterMacAddr());
-        OFOxmList oxmListIp = OFOxmList.of(dmac, 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 router-mac and mpls packets
-        OFOxmEthType oxmpls = factory.oxms().ethType(EthType.MPLS_UNICAST);
-        OFOxmList oxmListMpls = OFOxmList.of(dmac, 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();
-
-        log.debug("Adding termination-mac-rules in sw {}", getStringId());
-        List<OFMessage> msglist = new ArrayList<OFMessage>(2);
-        msglist.add(ipEntry);
-        msglist.add(mplsEntry);
-        write(msglist);
-    }
-
-    private MacAddress getRouterMacAddr() {
-        if (srConfig != null) {
-            return MacAddress.of(srConfig.getRouterMac());
-        } else {
-            // return a dummy mac address - it will not be used
-            return MacAddress.of("00:00:00:00:00:00");
-        }
-    }
-
-    private boolean isEdgeRouter(Dpid ndpid) {
-        INetworkConfigService ncs = floodlightProvider.getNetworkConfigService();
-        SwitchConfigStatus scs = ncs.checkSwitchConfig(ndpid);
-        if (scs.getConfigState() == NetworkConfigState.ACCEPT_ADD) {
-            return ((SegmentRouterConfig) scs.getSwitchConfig()).isEdgeRouter();
-        } else {
-            // TODO: return false if router not allowed
-            return false;
-        }
-    }
-
-    private MacAddress getNeighborRouterMacAddress(Dpid ndpid) {
-        INetworkConfigService ncs = floodlightProvider.getNetworkConfigService();
-        SwitchConfigStatus scs = ncs.checkSwitchConfig(ndpid);
-        if (scs.getConfigState() == NetworkConfigState.ACCEPT_ADD) {
-            return MacAddress.of(((SegmentRouterConfig) scs.getSwitchConfig())
-                    .getRouterMac());
-        } else {
-            // return a dummy mac address - it will not be used
-            return MacAddress.of("00:00:00:00:00:00");
-        }
-    }
-
-    private void setNeighbors(List<LinkConfig> linkConfigList) {
-        for (LinkConfig lg : linkConfigList) {
-            if (!lg.getType().equals(NetworkConfigManager.PKT_LINK)) {
-                continue;
-            }
-            PktLinkConfig plg = (PktLinkConfig) lg;
-            if (plg.getDpid1() == getId()) {
-                addNeighborAtPort(new Dpid(plg.getDpid2()),
-                        PortNumber.uint32(plg.getPort1()));
-            } else if (plg.getDpid2() == getId()) {
-                addNeighborAtPort(new Dpid(plg.getDpid1()),
-                        PortNumber.uint32(plg.getPort2()));
-            }
-        }
-    }
-
-    private void addNeighborAtPort(Dpid neighborDpid, PortNumber portToNeighbor) {
-        /* Update NeighborToPort database */
-        if (neighbors.get(neighborDpid) != null) {
-            neighbors.get(neighborDpid).add(portToNeighbor);
-        } else {
-            Set<PortNumber> ports = new HashSet<PortNumber>();
-            ports.add(portToNeighbor);
-            neighbors.put(neighborDpid, ports);
-        }
-
-        /* Update portToNeighbors database */
-        if (portToNeighbors.get(portToNeighbor) == null)
-            portToNeighbors.put(portToNeighbor, neighborDpid);
-    }
-
-    private void getAllNodeSegmentIds(List<SwitchConfig> switchList) {
-        for (SwitchConfig sc : switchList) {
-            /* TODO: Do we need to check if the SwitchConfig is of
-             * type SegmentRouter?
-             */
-            if (sc.getDpid() == getId()) {
-                continue;
-            }
-            segmentIds.add(((SegmentRouterConfig) sc).getNodeSid());
-        }
-        log.debug("getAllNodeSegmentIds: at sw {} are {}",
-                getStringId(), segmentIds);
-    }
-
-    private boolean isSegmentIdSameAsNodeSegmentId(Dpid dpid, int sId) {
-        INetworkConfigService ncs = floodlightProvider.getNetworkConfigService();
-        SwitchConfigStatus scs = ncs.checkSwitchConfig(dpid);
-        if (scs.getConfigState() == NetworkConfigState.ACCEPT_ADD) {
-            return (((SegmentRouterConfig) scs.getSwitchConfig()).
-                    getNodeSid() == sId);
-        } else {
-            // TODO: return false if router not allowed
-            return false;
-        }
-    }
-
-    private Set<Set<Dpid>> getAllNeighborSets(Set<Dpid> neighbors) {
-        List<Dpid> list = new ArrayList<Dpid>(neighbors);
-        Set<Set<Dpid>> sets = new HashSet<Set<Dpid>>();
-        /* get the number of elements in the neighbors */
-        int elements = list.size();
-        /* the number of members of a power set is 2^n
-         * including the empty set
-         */
-        int powerElements = (1 << elements);
-
-        /* run a binary counter for the number of power elements */
-        for (long i = 1; i < powerElements; i++) {
-            Set<Dpid> dpidSubSet = new HashSet<Dpid>();
-            for (int j = 0; j < elements; j++) {
-                if ((i >> j) % 2 == 1) {
-                    dpidSubSet.add(list.get(j));
-                }
-            }
-            /* NOTE: Avoid any pairings of edge routers only
-             * at a backbone router */
-            boolean avoidEdgeRouterPairing = true;
-            if ((!isEdgeRouter) && (dpidSubSet.size() > 1)) {
-                for (Dpid dpid : dpidSubSet) {
-                    if (!isEdgeRouter(dpid)) {
-                        avoidEdgeRouterPairing = false;
-                        break;
-                    }
-                }
-            }
-            else
-                avoidEdgeRouterPairing = false;
-
-            if (!avoidEdgeRouterPairing)
-                sets.add(dpidSubSet);
-        }
-        return sets;
-    }
-
-    private void createGroupForANeighborSet(NeighborSet ns, int groupId) {
-        List<BucketInfo> buckets = new ArrayList<BucketInfo>();
-        for (Dpid d : ns.getDpids()) {
-            for (PortNumber sp : neighbors.get(d)) {
-                BucketInfo b = new BucketInfo(d,
-                        MacAddress.of(srConfig.getRouterMac()),
-                        getNeighborRouterMacAddress(d), sp,
-                        ns.getEdgeLabel(), true, -1);
-                buckets.add(b);
-
-                /* Update Port Neighborset map */
-                ArrayList<NeighborSet> portNeighborSets =
-                        portNeighborSetMap.get(sp);
-                if (portNeighborSets == null) {
-                    portNeighborSets = new ArrayList<NeighborSet>();
-                    portNeighborSets.add(ns);
-                    portNeighborSetMap.put(sp, portNeighborSets);
-                }
-                else
-                    portNeighborSets.add(ns);
-            }
-        }
-        EcmpInfo ecmpInfo = new EcmpInfo(groupId, buckets);
-        setEcmpGroup(ecmpInfo);
-        ecmpGroups.put(ns, ecmpInfo);
-        log.debug(
-                "createGroupForANeighborSet: Creating ecmp group {} in sw {} "
-                        + "for neighbor set {} with: {}",
-                groupId, getStringId(), ns, ecmpInfo);
-        return;
-    }
-
-    /**
-     * createGroups creates ECMP groups for all ports on this router connected
-     * to other routers (in the OF network). The information for ports is
-     * gleaned from the configured links. If no links are configured no groups
-     * will be created, and it is up to the caller of the IOF13Switch API to
-     * create groups.
-     * <p>
-     * By default all ports connected to the same neighbor router will be part
-     * of the same ECMP group. In addition, groups will be created for all
-     * possible combinations of neighbor routers.
-     * <p>
-     * For example, consider this router (R0) connected to 3 neighbors (R1, R2,
-     * and R3). The following groups will be created in R0:
-     * <li>1) all ports to R1,
-     * <li>2) all ports to R2,
-     * <li>3) all ports to R3,
-     * <li>4) all ports to R1 and R2
-     * <li>5) all ports to R1 and R3
-     * <li>6) all ports to R2 and R3
-     * <li>7) all ports to R1, R2, and R3
-     */
-    private void createGroups() {
-
-        Set<Dpid> dpids = neighbors.keySet();
-        if (dpids == null || dpids.isEmpty()) {
-            return;
-        }
-        /* Create all possible Neighbor sets from this router
-         * NOTE: Avoid any pairings of edge routers only
-         */
-        Set<Set<Dpid>> powerSet = getAllNeighborSets(dpids);
-        log.debug("createGroups: The size of neighbor powerset for sw {} is {}",
-                getStringId(), powerSet.size());
-        Set<NeighborSet> nsSet = new HashSet<NeighborSet>();
-        for (Set<Dpid> combo : powerSet) {
-            if (combo.isEmpty())
-                continue;
-            if (isEdgeRouter && !segmentIds.isEmpty()) {
-                for (Integer sId : segmentIds) {
-                    NeighborSet ns = new NeighborSet();
-                    ns.addDpids(combo);
-                    /* Check if the edge label being set is of the
-                     * same node in the Neighbor set
-                     */
-                    if ((combo.size() != 1) ||
-                            (!isSegmentIdSameAsNodeSegmentId(
-                                    combo.iterator().next(), sId))) {
-                        ns.setEdgeLabel(sId);
-                    }
-                    nsSet.add(ns);
-                }
-            } else {
-                NeighborSet ns = new NeighborSet();
-                ns.addDpids(combo);
-                nsSet.add(ns);
-            }
-        }
-        log.debug("createGroups: The neighborset with label for sw {} is {}",
-                getStringId(), nsSet);
-
-        for (NeighborSet ns : nsSet) {
-            createGroupForANeighborSet(ns, groupid.incrementAndGet());
-        }
-    }
-
-    private class EcmpInfo {
-        int groupId;
-        List<BucketInfo> buckets;
-
-        EcmpInfo(int gid, List<BucketInfo> bucketInfos) {
-            groupId = gid;
-            buckets = bucketInfos;
-        }
-
-        @Override
-        public String toString() {
-            return "groupId: " + groupId + ", buckets: " + buckets;
-        }
-    }
-
-    private class BucketInfo {
-        Dpid neighborDpid;
-        MacAddress srcMac;
-        MacAddress dstMac;
-        PortNumber outport;
-        int groupNo;
-        int mplsLabel;
-        boolean bos;
-
-        /*
-                BucketInfo(Dpid nDpid, MacAddress smac, MacAddress dmac,
-                        PortNumber p, int label) {
-                    neighborDpid = nDpid;
-                    srcMac = smac;
-                    dstMac = dmac;
-                    outport = p;
-                    mplsLabel = label;
-                    groupNo = -1;
-                }
-
-                BucketInfo(int no, int label, boolean b) {
-                    neighborDpid = null;
-                    srcMac = null;
-                    dstMac = null;
-                    outport = null;
-                    groupNo = no;
-                    mplsLabel = label;
-                    bos = b;
-                }
-        */
-        BucketInfo(Dpid nDpid, MacAddress smac, MacAddress dmac,
-                PortNumber p, int label, boolean bos, int gotoGroupNo) {
-            neighborDpid = nDpid;
-            srcMac = smac;
-            dstMac = dmac;
-            outport = p;
-            mplsLabel = label;
-            this.bos = bos;
-            groupNo = gotoGroupNo;
-        }
-
-
-        @Override
-        public String toString() {
-            return " {neighborDpid: " + neighborDpid + ", dstMac: " + dstMac +
-                    ", srcMac: " + srcMac + ", outport: " + outport +
-                    ", groupNo: " + groupNo +
-                    ", mplsLabel: " + mplsLabel + "}";
-        }
-    }
-
-    private void setEcmpGroup(EcmpInfo ecmpInfo) {
-        List<OFMessage> msglist = new ArrayList<OFMessage>();
-        OFGroup group = OFGroup.of(ecmpInfo.groupId);
-
-        List<OFBucket> buckets = new ArrayList<OFBucket>();
-        for (BucketInfo b : ecmpInfo.buckets) {
-            List<OFAction> actions = new ArrayList<OFAction>();
-            if (b.dstMac != null) {
-                OFOxmEthDst dmac = factory.oxms()
-                        .ethDst(b.dstMac);
-                OFAction setDA = factory.actions().buildSetField()
-                        .setField(dmac).build();
-                actions.add(setDA);
-            }
-            if (b.srcMac != null) {
-                OFOxmEthSrc smac = factory.oxms()
-                        .ethSrc(b.srcMac);
-                OFAction setSA = factory.actions().buildSetField()
-                        .setField(smac).build();
-                actions.add(setSA);
-            }
-            if (b.outport != null) {
-                OFAction outp = factory.actions().buildOutput()
-                        .setPort(OFPort.of(b.outport.shortValue()))
-                        .build();
-                actions.add(outp);
-            }
-            if (b.mplsLabel != -1) {
-                OFAction pushLabel = factory.actions().buildPushMpls()
-                        .setEthertype(EthType.MPLS_UNICAST).build();
-                OFBooleanValue bosValue = null;
-                if (b.bos)
-                    bosValue = OFBooleanValue.TRUE;
-                else
-                    bosValue = OFBooleanValue.FALSE;
-                OFOxmMplsBos bosX = factory.oxms()
-                        .mplsBos(bosValue);
-                OFAction setBX = factory.actions().buildSetField()
-                        .setField(bosX).build();
-                OFOxmMplsLabel lid = factory.oxms()
-                        .mplsLabel(U32.of(b.mplsLabel));
-                OFAction setLabel = factory.actions().buildSetField()
-                        .setField(lid).build();
-                OFAction copyTtl = factory.actions().copyTtlOut();
-                OFAction decrTtl = factory.actions().decMplsTtl();
-                actions.add(pushLabel);
-                actions.add(setLabel);
-                actions.add(setBX);
-                actions.add(copyTtl);
-                // decrement TTL only when the first MPLS label is pushed
-                if (b.bos)
-                    actions.add(decrTtl);
-            }
-            if (b.groupNo > 0) {
-                OFAction groupTo = factory.actions().buildGroup()
-                        .setGroup(OFGroup.of(b.groupNo))
-                        .build();
-                actions.add(groupTo);
-            }
-            OFBucket ofb = factory.buildBucket()
-                    .setWeight(1)
-                    .setActions(actions)
-                    .build();
-            buckets.add(ofb);
-        }
-
-        OFMessage gm = factory.buildGroupAdd()
-                .setGroup(group)
-                .setBuckets(buckets)
-                .setGroupType(OFGroupType.SELECT)
-                .setXid(getNextTransactionId())
-                .build();
-        msglist.add(gm);
-        try {
-            write(msglist);
-        } catch (IOException e) {
-            // TODO Auto-generated catch block
-            e.printStackTrace();
-        }
-    }
-
-    /*
-        private void setPolicyEcmpGroup(EcmpInfo ecmpInfo) {
-            List<OFMessage> msglist = new ArrayList<OFMessage>();
-            OFGroup group = OFGroup.of(ecmpInfo.groupId);
-
-            List<OFBucket> buckets = new ArrayList<OFBucket>();
-            List<OFAction> actions = new ArrayList<OFAction>();
-            for (BucketInfo b : ecmpInfo.buckets) {
-                if (b.dstMac != null && b.srcMac != null && b.outport != null) {
-                    OFOxmEthDst dmac = factory.oxms()
-                            .ethDst(b.dstMac);
-                    OFAction setDA = factory.actions().buildSetField()
-                            .setField(dmac).build();
-                    OFOxmEthSrc smac = factory.oxms()
-                            .ethSrc(b.srcMac);
-                    OFAction setSA = factory.actions().buildSetField()
-                            .setField(smac).build();
-                    OFAction outp = factory.actions().buildOutput()
-                            .setPort(OFPort.of(b.outport.shortValue()))
-                            .build();
-                    actions.add(setSA);
-                    actions.add(setDA);
-                    actions.add(outp);
-                }
-                if (b.groupNo > 0) {
-                    OFAction groupTo = factory.actions().buildGroup()
-                            .setGroup(OFGroup.of(b.groupNo))
-                            .build();
-                    actions.add(groupTo);
-                }
-                if (b.mplsLabel != -1) {
-                    OFAction pushLabel = factory.actions().buildPushMpls()
-                            .setEthertype(EthType.MPLS_UNICAST).build();
-
-                    OFBooleanValue bosValue = null;
-                    if (b.bos)
-                        bosValue = OFBooleanValue.TRUE;
-                    else
-                        bosValue = OFBooleanValue.FALSE;
-                    OFOxmMplsBos bosX = factory.oxms()
-                            .mplsBos(bosValue);
-                    OFAction setBX = factory.actions().buildSetField()
-                            .setField(bosX).build();
-                    OFOxmMplsLabel lid = factory.oxms()
-                            .mplsLabel(U32.of(b.mplsLabel));
-                    OFAction setLabel = factory.actions().buildSetField()
-                            .setField(lid).build();
-                    OFAction copyTtl = factory.actions().copyTtlOut();
-                    OFAction decrTtl = factory.actions().decMplsTtl();
-                    actions.add(pushLabel);
-                    actions.add(setLabel);
-                    actions.add(setBX);
-                    actions.add(copyTtl);
-                    // decrement TTL only when the first MPLS label is pushed
-                    if (b.bos)
-                        actions.add(decrTtl);
-                }
-                OFBucket ofb = factory.buildBucket()
-                        .setWeight(1)
-                        .setActions(actions)
-                        .build();
-                buckets.add(ofb);
-            }
-
-            OFMessage gm = factory.buildGroupAdd()
-                    .setGroup(group)
-                    .setBuckets(buckets)
-                    .setGroupType(OFGroupType.SELECT)
-                    .setXid(getNextTransactionId())
-                    .build();
-            msglist.add(gm);
-            try {
-                write(msglist);
-            } catch (IOException e) {
-                // TODO Auto-generated catch block
-                e.printStackTrace();
-            }
-        }
-    */
-    private void deleteGroup(int groupId) {
-
-        List<OFMessage> msglist = new ArrayList<OFMessage>();
-        OFGroup group = OFGroup.of(groupId);
-
-        OFMessage gm = factory.buildGroupDelete()
-                .setGroup(group)
-                .setGroupType(OFGroupType.SELECT)
-                .setXid(getNextTransactionId())
-                .build();
-        msglist.add(gm);
-        try {
-            write(msglist);
-        } catch (IOException e) {
-            // TODO Auto-generated catch block
-            e.printStackTrace();
-        }
-    }
-
-    private void modifyEcmpGroup(EcmpInfo ecmpInfo) {
-        List<OFMessage> msglist = new ArrayList<OFMessage>();
-        OFGroup group = OFGroup.of(ecmpInfo.groupId);
-
-        List<OFBucket> buckets = new ArrayList<OFBucket>();
-        for (BucketInfo b : ecmpInfo.buckets) {
-            OFOxmEthDst dmac = factory.oxms()
-                    .ethDst(b.dstMac);
-            OFAction setDA = factory.actions().buildSetField()
-                    .setField(dmac).build();
-            OFOxmEthSrc smac = factory.oxms()
-                    .ethSrc(b.srcMac);
-            OFAction setSA = factory.actions().buildSetField()
-                    .setField(smac).build();
-            OFAction outp = factory.actions().buildOutput()
-                    .setPort(OFPort.of(b.outport.shortValue()))
-                    .build();
-            List<OFAction> actions = new ArrayList<OFAction>();
-            actions.add(setSA);
-            actions.add(setDA);
-            actions.add(outp);
-            if (b.mplsLabel != -1) {
-                OFAction pushLabel = factory.actions().buildPushMpls()
-                        .setEthertype(EthType.MPLS_UNICAST).build();
-                OFOxmMplsBos bosX = factory.oxms()
-                        .mplsBos(OFBooleanValue.TRUE);
-                OFAction setBX = factory.actions().buildSetField()
-                        .setField(bosX).build();
-                OFOxmMplsLabel lid = factory.oxms()
-                        .mplsLabel(U32.of(b.mplsLabel));
-                OFAction setLabel = factory.actions().buildSetField()
-                        .setField(lid).build();
-                OFAction copyTtl = factory.actions().copyTtlOut();
-                OFAction decrTtl = factory.actions().decMplsTtl();
-                actions.add(pushLabel);
-                actions.add(setLabel);
-                actions.add(setBX);
-                actions.add(copyTtl);
-                actions.add(decrTtl);
-            }
-            OFBucket ofb = factory.buildBucket()
-                    .setWeight(1)
-                    .setActions(actions)
-                    .build();
-            buckets.add(ofb);
-        }
-
-        OFMessage gm = factory.buildGroupModify()
-                .setGroup(group)
-                .setBuckets(buckets)
-                .setGroupType(OFGroupType.SELECT)
-                .setXid(getNextTransactionId())
-                .build();
-        msglist.add(gm);
-        try {
-            write(msglist);
-        } catch (IOException e) {
-            // TODO Auto-generated catch block
-            e.printStackTrace();
-        }
-    }
-
-    private void verifyGroups() throws IOException {
-        sendGroupDescRequest();
-    }
-
-    private void sendGroupDescRequest() throws IOException {
-        OFMessage gdr = factory.buildGroupDescStatsRequest()
-                .setXid(getNextTransactionId())
-                .build();
-        write(gdr, null);
-    }
-
-    private void assignAdjacencyLabels() {
-        List<AdjacencySid> autogenAdjSids = new ArrayList<AdjacencySid>();
-        publishAttributes = new HashMap<String, String>();
-        if (srConfig == null) {
-            log.error("Cannot obtain SegmentRouterConfig in sw {}", getStringId());
-            return; // this will cause handshake to fail
-        }
-        for (OFPortDesc p : getPorts()) {
-            int pnum = p.getPortNo().getPortNumber();
-
-            if (U32.ofRaw(pnum).compareTo(U32.ofRaw(OFPort.MAX.getPortNumber())) >= 1) {
-                continue;
-            }
-            // create unique adj-sid assuming that operator only
-            // enters adjSids for multiple-ports and only in the range
-            // 1-10k XXX make sure that happens
-            int adjSid = srConfig.getNodeSid() * 1000 + pnum;
-            AdjacencySid as = new AdjacencySid(adjSid,
-                    Collections.singletonList(pnum));
-            autogenAdjSids.add(as);
-        }
-        ObjectMapper mapper = new ObjectMapper();
-        try {
-            publishAttributes.put("autogenAdjSids",
-                    mapper.writeValueAsString(autogenAdjSids));
-        } catch (IOException e1) {
-            log.error("Error while writing adjacency labels: {}", e1.getCause());
-        }
-
-        try {
-            nextDriverState();
-        } catch (IOException e) {
-            // TODO Auto-generated catch block
-            e.printStackTrace();
-        }
-    }
-
-    private OFAction getOFAction(Action action) {
-        OFAction ofAction = null;
-        if (action instanceof OutputAction) {
-            OutputAction outputAction = (OutputAction) action;
-            OFPort port = OFPort.of((int) outputAction.getPortNumber().value());
-            ofAction = factory.actions().output(port, Short.MAX_VALUE);
-        } else if (action instanceof ModifyDstMacAction) {
-            long dstMac = ((ModifyDstMacAction) action).getDstMac().toLong();
-            OFOxmEthDst dmac = factory.oxms()
-                    .ethDst(MacAddress.of(dstMac));
-            ofAction = factory.actions().buildSetField()
-                    .setField(dmac).build();
-        } else if (action instanceof ModifySrcMacAction) {
-            long srcMac = ((ModifySrcMacAction) action).getSrcMac().toLong();
-            OFOxmEthSrc smac = factory.oxms()
-                    .ethSrc(MacAddress.of(srcMac));
-            ofAction = factory.actions().buildSetField()
-                    .setField(smac).build();
-        } else if (action instanceof PushMplsAction) {
-            ofAction = factory.actions().pushMpls(EthType.MPLS_UNICAST);
-        } else if (action instanceof SetMplsIdAction) {
-            int labelid = ((SetMplsIdAction) action).getMplsId();
-            OFOxmMplsLabel lid = factory.oxms()
-                    .mplsLabel(U32.of(labelid));
-            ofAction = factory.actions().buildSetField()
-                    .setField(lid).build();
-        } else if (action instanceof SetMplsBosAction) {
-            OFBooleanValue val = OFBooleanValue.of(
-                    ((SetMplsBosAction) action).isSet());
-            OFOxmMplsBos bos = factory.oxms().mplsBos(val);
-            OFAction setBos = factory.actions().buildSetField()
-                    .setField(bos).build();
-        } else if (action instanceof PopMplsAction) {
-            EthType ethertype = ((PopMplsAction) action).getEthType();
-            ofAction = factory.actions().popMpls(ethertype);
-        } else if (action instanceof GroupAction) {
-            int gid = -1;
-            GroupAction ga = (GroupAction)action;
-            if (ga.getGroupId() > 0) {
-                gid = ga.getGroupId();
-            }
-            else {
-                NeighborSet ns = ((GroupAction) action).getDpids();
-                EcmpInfo ei = ecmpGroups.get(ns);
-                if (ei == null) {
-                    log.debug("Unable to find ecmp group for neighbors {} at "
-                            + "switch {} and hence creating it", ns, getStringId());
-                    createGroupForANeighborSet(ns, groupid.incrementAndGet());
-                    ei = ecmpGroups.get(ns);
-                }
-                gid = ei.groupId;
-            }
-            ofAction = factory.actions().buildGroup()
-                    .setGroup(OFGroup.of(gid))
-                    .build();
-        } else if (action instanceof DecNwTtlAction) {
-            ofAction = factory.actions().decNwTtl();
-        } else if (action instanceof DecMplsTtlAction) {
-            ofAction = factory.actions().decMplsTtl();
-        } else if (action instanceof CopyTtlInAction) {
-            ofAction = factory.actions().copyTtlIn();
-        } else if (action instanceof CopyTtlOutAction) {
-            ofAction = factory.actions().copyTtlOut();
-        } else if (action instanceof SetDAAction) {
-            OFOxmEthDst dmac = factory.oxms()
-                    .ethDst(((SetDAAction)action).getAddress());
-            ofAction = factory.actions().buildSetField()
-                    .setField(dmac).build();
-        } else if (action instanceof SetSAAction) {
-            OFOxmEthSrc smac = factory.oxms()
-                    .ethSrc(((SetSAAction)action).getAddress());
-            ofAction = factory.actions().buildSetField()
-                    .setField(smac).build();
-        } else {
-            log.warn("Unsupported Action type: {}", action.getClass().getName());
-            return null;
-        }
-
-        return ofAction;
-    }
-
-    private OFMessage getIpEntry(MatchActionOperationEntry mao) {
-        MatchAction ma = mao.getTarget();
-        Operator op = mao.getOperator();
-        Ipv4Match ipm = (Ipv4Match) ma.getMatch();
-
-        // set match
-        IPv4Net ipdst = ipm.getDestination();
-        OFOxmEthType ethTypeIp = factory.oxms()
-                .ethType(EthType.IPv4);
-        OFOxmIpv4DstMasked ipPrefix = factory.oxms()
-                .ipv4DstMasked(
-                        IPv4Address.of(ipdst.address().value()),
-                        IPv4Address.ofCidrMaskLength(ipdst.prefixLen())
-                );
-        OFOxmList oxmList = OFOxmList.of(ethTypeIp, ipPrefix);
-        OFMatchV3 match = factory.buildMatchV3()
-                .setOxmList(oxmList).build();
-
-        // set actions
-        List<OFAction> writeActions = new ArrayList<OFAction>();
-        for (Action action : ma.getActions()) {
-            OFAction ofAction = getOFAction(action);
-            if (ofAction != null) {
-                writeActions.add(ofAction);
-            }
-        }
-
-        // set instructions
-        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);
-
-        // set flow priority to emulate longest prefix match
-        int priority = ipdst.prefixLen() * PRIORITY_MULTIPLIER;
-        if (ipdst.prefixLen() == (short) 32) {
-            priority = MAX_PRIORITY;
-        }
-
-        // set flow-mod
-        OFFlowMod.Builder fmBuilder = null;
-        switch (op) {
-        case ADD:
-            fmBuilder = factory.buildFlowAdd();
-            break;
-        case REMOVE:
-            fmBuilder = factory.buildFlowDeleteStrict();
-            break;
-        case MODIFY: // TODO
-            fmBuilder = factory.buildFlowModifyStrict();
-            break;
-        default:
-            log.warn("Unsupported MatchAction Operator: {}", op);
-            return null;
-        }
-        OFMessage ipFlow = fmBuilder
-                .setTableId(TableId.of(TABLE_IPv4_UNICAST))
-                .setMatch(match)
-                .setInstructions(instructions)
-                .setPriority(priority)
-                .setBufferId(OFBufferId.NO_BUFFER)
-                .setIdleTimeout(0)
-                .setHardTimeout(0)
-                .setXid(getNextTransactionId())
-                .build();
-        log.debug("{} ip-rule {}-{} in sw {}",
-                (op == MatchActionOperations.Operator.ADD) ? "Adding" : "Deleting",
-                match, writeActions,
-                getStringId());
-        return ipFlow;
-    }
-
-    private OFMessage getMplsEntry(MatchActionOperationEntry mao) {
-        MatchAction ma = mao.getTarget();
-        Operator op = mao.getOperator();
-        MplsMatch mplsm = (MplsMatch) ma.getMatch();
-
-        // set match
-        OFOxmEthType ethTypeMpls = factory.oxms()
-                .ethType(EthType.MPLS_UNICAST);
-        OFOxmMplsLabel labelid = factory.oxms()
-                .mplsLabel(U32.of(mplsm.getMplsLabel()));
-        OFOxmMplsBos bos = factory.oxms()
-                .mplsBos(OFBooleanValue.of(mplsm.isBos()));
-        OFOxmList oxmList = OFOxmList.of(ethTypeMpls, labelid, bos);
-        OFMatchV3 matchlabel = factory.buildMatchV3()
-                .setOxmList(oxmList).build();
-
-        // set actions
-        List<OFAction> writeActions = new ArrayList<OFAction>();
-        for (Action action : ma.getActions()) {
-            OFAction ofAction = getOFAction(action);
-            if (ofAction != null) {
-                writeActions.add(ofAction);
-            }
-        }
-
-        // set instructions
-        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);
-
-        // set flow-mod
-        OFFlowMod.Builder fmBuilder = null;
-        switch (op) {
-        case ADD:
-            fmBuilder = factory.buildFlowAdd();
-            break;
-        case REMOVE:
-            fmBuilder = factory.buildFlowDeleteStrict();
-            break;
-         case MODIFY: // TODO
-            fmBuilder = factory.buildFlowModifyStrict();
-            break;
-        default:
-            log.warn("Unsupported MatchAction Operator: {}", op);
-            return null;
-        }
-
-        OFMessage mplsFlow = fmBuilder
-                .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();
-        log.debug("{} mpls-rule {}-{} in sw {}",
-                (op == MatchActionOperations.Operator.ADD) ? "Adding" : "Deleting",
-                matchlabel, writeActions,
-                getStringId());
-        return mplsFlow;
-    }
-
-    private OFMessage getAclEntry(MatchActionOperationEntry mao) {
-        MatchAction ma = mao.getTarget();
-        Operator op = mao.getOperator();
-        PacketMatch packetMatch = (PacketMatch) ma.getMatch();
-        Builder matchBuilder = factory.buildMatch();
-
-        // set match
-        int inport = 0;
-        if (ma.getSwitchPort() != null) {
-            inport = (int) ma.getSwitchPort().getPortNumber().value();
-        }
-        final MACAddress srcMac = packetMatch.getSrcMacAddress();
-        final MACAddress dstMac = packetMatch.getDstMacAddress();
-        final Short etherType = packetMatch.getEtherType();
-        final IPv4Net srcIp = packetMatch.getSrcIpAddress();
-        final IPv4Net dstIp = packetMatch.getDstIpAddress();
-        final Byte ipProto = packetMatch.getIpProtocolNumber();
-        final Short srcTcpPort = packetMatch.getSrcTcpPortNumber();
-        final Short dstTcpPort = packetMatch.getDstTcpPortNumber();
-        if (inport > 0) {
-            matchBuilder.setExact(MatchField.IN_PORT,
-                    OFPort.of(inport));
-        }
-        if (srcMac != null) {
-            matchBuilder.setExact(MatchField.ETH_SRC, MacAddress.of(srcMac.toLong()));
-        }
-        if (dstMac != null) {
-            matchBuilder.setExact(MatchField.ETH_DST, MacAddress.of(dstMac.toLong()));
-        }
-        if (etherType != null) {
-            matchBuilder.setExact(MatchField.ETH_TYPE, EthType.of(etherType));
-        }
-        if (srcIp != null) {
-            matchBuilder.setMasked(MatchField.IPV4_SRC,
-                    IPv4Address.of(srcIp.address().value())
-                            .withMaskOfLength(srcIp.prefixLen()));
-        }
-        if (dstIp != null) {
-            matchBuilder.setMasked(MatchField.IPV4_DST,
-                    IPv4Address.of(dstIp.address().value())
-                            .withMaskOfLength(dstIp.prefixLen()));
-        }
-        if (ipProto != null) {
-            matchBuilder.setExact(MatchField.IP_PROTO, IpProtocol.of(ipProto));
-        }
-        if (srcTcpPort != null) {
-            matchBuilder.setExact(MatchField.TCP_SRC, TransportPort.of(srcTcpPort));
-        }
-        if (dstTcpPort != null) {
-            matchBuilder.setExact(MatchField.TCP_DST, TransportPort.of(dstTcpPort));
-        }
-
-        // set actions
-        List<OFAction> writeActions = new ArrayList<OFAction>();
-        for (Action action : ma.getActions()) {
-            OFAction ofAction = getOFAction(action);
-            if (ofAction != null) {
-                writeActions.add(ofAction);
-            }
-        }
-
-        // set instructions
-        OFInstruction clearInstr = factory.instructions().clearActions();
-        OFInstruction writeInstr = factory.instructions().buildWriteActions()
-                .setActions(writeActions).build();
-        List<OFInstruction> instructions = new ArrayList<OFInstruction>();
-        instructions.add(clearInstr);
-        instructions.add(writeInstr);
-
-        // set flow-mod
-        OFFlowMod.Builder fmBuilder = null;
-        switch (op) {
-        case ADD:
-            fmBuilder = factory.buildFlowAdd();
-            break;
-        case REMOVE:
-            fmBuilder = factory.buildFlowDeleteStrict();
-            break;
-        case MODIFY: // TODO
-            fmBuilder = factory.buildFlowModifyStrict();
-            break;
-        default:
-            log.warn("Unsupported MatchAction Operator: {}", op);
-            return null;
-        }
-
-        OFMessage aclFlow = fmBuilder
-                .setTableId(TableId.of(TABLE_ACL))
-                .setMatch(matchBuilder.build())
-                .setInstructions(instructions)
-                .setPriority(ma.getPriority()) // exact match and exclusive
-                .setBufferId(OFBufferId.NO_BUFFER)
-                .setIdleTimeout(0)
-                .setHardTimeout(0)
-                .setXid(getNextTransactionId())
-                .build();
-
-        return aclFlow;
-    }
-
-    // *****************************
-    // IOF13Switch
-    // *****************************
-
-    @Override
-    public void pushFlow(MatchActionOperationEntry matchActionOp) throws IOException {
-        OFMessage ofm = getFlow(matchActionOp);
-        if (ofm != null) {
-            write(Collections.singletonList(ofm));
-        }
-    }
-
-    private OFMessage getFlow(MatchActionOperationEntry matchActionOp) {
-        final MatchAction matchAction = matchActionOp.getTarget();
-        final Match match = matchAction.getMatch();
-        if (match instanceof Ipv4Match) {
-            return getIpEntry(matchActionOp);
-        } else if (match instanceof MplsMatch) {
-            return getMplsEntry(matchActionOp);
-        } else if (match instanceof PacketMatch) {
-            return getAclEntry(matchActionOp);
-        } else {
-            log.error("Unknown match type {} pushed to switch {}", match,
-                    getStringId());
-        }
-        return null;
-    }
-
-    @Override
-    public void pushFlows(Collection<MatchActionOperationEntry> matchActionOps)
-            throws IOException {
-        List<OFMessage> flowMods = new ArrayList<OFMessage>();
-        for (MatchActionOperationEntry matchActionOp : matchActionOps) {
-            OFMessage ofm = getFlow(matchActionOp);
-            if (ofm != null) {
-                flowMods.add(ofm);
-            }
-        }
-        write(flowMods);
-    }
-
-    @Override
-    public int getEcmpGroupId(NeighborSet ns) {
-        EcmpInfo ei = ecmpGroups.get(ns);
-        if (ei == null) {
-            return -1;
-        } else {
-            return ei.groupId;
-        }
-    }
-
-    @Override
-    public TableId getTableId(String tableType) {
-        tableType = tableType.toLowerCase();
-        if (tableType.contentEquals("ip")) {
-            return TableId.of(OFSwitchImplCPqD13.TABLE_IPv4_UNICAST);
-        }
-        else if (tableType.contentEquals("mpls")) {
-            return TableId.of(OFSwitchImplCPqD13.TABLE_MPLS);
-        }
-        else if (tableType.contentEquals("acl")) {
-            return TableId.of(OFSwitchImplCPqD13.TABLE_ACL);
-        }
-        else {
-            log.warn("Invalid tableType: {}", tableType);
-            return null;
-        }
-    }
-
-    private EcmpInfo createIndirectGroup(int groupId, MacAddress srcMac,
-            MacAddress dstMac, PortNumber outPort, int gotoGroupNo,
-            int mplsLabel, boolean bos) {
-        List<BucketInfo> buckets = new ArrayList<BucketInfo>();
-        BucketInfo b = new BucketInfo(null, srcMac, dstMac, outPort,
-                mplsLabel, bos, gotoGroupNo);
-        buckets.add(b);
-
-        EcmpInfo ecmpInfo = new EcmpInfo(groupId, buckets);
-        setEcmpGroup(ecmpInfo);
-        log.debug(
-                "createIndirectGroup: Creating indirect group {} in sw {} "
-                        + "with: {}", groupId, getStringId(), ecmpInfo);
-        return ecmpInfo;
-    }
-
-    private EcmpInfo createInnermostLabelGroup(int innermostGroupId,
-            List<PortNumber> ports, int mplsLabel, boolean bos,
-            HashMap<PortNumber, Integer> lastSetOfGroupIds) {
-        List<BucketInfo> buckets = new ArrayList<BucketInfo>();
-        for (PortNumber sp : ports) {
-            Dpid neighborDpid = portToNeighbors.get(sp);
-            BucketInfo b = new BucketInfo(neighborDpid,
-                    MacAddress.of(srConfig.getRouterMac()),
-                    getNeighborRouterMacAddress(neighborDpid), null,
-                    mplsLabel, bos,
-                    lastSetOfGroupIds.get(sp));
-            buckets.add(b);
-        }
-        EcmpInfo ecmpInfo = new EcmpInfo(innermostGroupId, buckets);
-        setEcmpGroup(ecmpInfo);
-        log.debug(
-                "createInnermostLabelGroup: Creating select group {} in sw {} "
-                        + "with: {}", innermostGroupId, getStringId(), ecmpInfo);
-        return ecmpInfo;
-    }
-    @Override
-    /**
-     * Create a group chain with the specified label stack for a given set of
-     * ports. This API can be used by user to create groups for a tunnel based
-     * policy routing scenario. NOTE: This API can not be used if a group to be
-     * created with different label stacks for each port in the given set of
-     * ports. Use XXX API for this purpose
-     *
-     * @param labelStack list of router segment Ids to be pushed. Can be empty.
-     *        labelStack is processed from left to right with leftmost
-     *        representing the outermost label and rightmost representing
-     *        innermost label to be pushed
-     * @param ports List of ports on this switch to get to the first router in
-     *        the labelStack
-     * @return group identifier
-     */
-    public int createGroup(List<Integer> labelStack, List<PortNumber> ports) {
-
-        if ((ports == null) ||
-                ((labelStack != null) && (labelStack.size() > 3))) {
-            log.warn("createGroup with wrong input parameters");
-        }
-        log.debug("createGroup with labelStack {} and ports {}",
-                labelStack, ports);
-
-        HashMap<PortNumber, Integer> lastSetOfGroupIds =
-                new HashMap<PortNumber, Integer>();
-        int innermostGroupId = -1;
-        /* If it is empty label stack or label stack with only one label,
-         * Create a single select group with buckets for each port in the list
-         * of specified ports and specified label if any and return the
-         * created group id
-         */
-        if (labelStack.size() < 2) {
-            int curLabel = -1;
-            boolean bos = false;
-            if (labelStack.size()==1) {
-                curLabel = labelStack.get(0).intValue();
-                bos = true;
-            }
-
-            List<BucketInfo> buckets = new ArrayList<BucketInfo>();
-            for (PortNumber sp : ports) {
-                Dpid neighborDpid = portToNeighbors.get(sp);
-                BucketInfo b = new BucketInfo(neighborDpid,
-                        MacAddress.of(srConfig.getRouterMac()),
-                        getNeighborRouterMacAddress(neighborDpid),
-                        sp, curLabel, bos, -1);
-                buckets.add(b);
-            }
-            innermostGroupId = groupid.incrementAndGet();
-            EcmpInfo ecmpInfo = new EcmpInfo(innermostGroupId, buckets);
-            setEcmpGroup(ecmpInfo);
-            userDefinedGroups.put(innermostGroupId, ecmpInfo);
-            return innermostGroupId;
-        }
-
-        /* If the label stack has two or more labels, then a chain of groups
-         * to be created.
-         * Step1: Create for each port in the list of specified ports,
-         * an indirect group with the outermost label. These groups are the
-         * end of the chain and hence don't reference to any other groups
-         * Step2: Create for each port in the list of specified ports, an
-         * indirect group with middle labels (if any). These groups will
-         * have references to group ids that are created in the previous
-         * iteration for the same ports
-         * Step3: Create a select group with all ports and innermost label.
-         * This group will have references to indirect group ids that are
-         * created in the previous iteration for the same ports
-         */
-        for (int i = 0; i < labelStack.size(); i++) {
-            for (PortNumber sp : ports) {
-                if (i == 0) {
-                    /* Outermost label processing */
-                    int currGroupId = groupid.incrementAndGet();
-                    EcmpInfo indirectGroup = createIndirectGroup(currGroupId,
-                            null, null, sp, -1,
-                            labelStack.get(i).intValue(), false);
-                    lastSetOfGroupIds.put(sp, currGroupId);
-                    userDefinedGroups.put(currGroupId, indirectGroup);
-                }
-                else if (i == (labelStack.size() - 1)) {
-                    /* Innermost label processing */
-                    innermostGroupId = groupid.incrementAndGet();
-                    EcmpInfo topLevelGroup = createInnermostLabelGroup(
-                            innermostGroupId,
-                            ports,
-                            labelStack.get(i).intValue(), true,
-                            lastSetOfGroupIds);
-                    userDefinedGroups.put(
-                            innermostGroupId, topLevelGroup);
-                    break;
-                }
-                else {
-                    /* Middle label processing */
-                    int currGroupId = groupid.incrementAndGet();
-                    EcmpInfo indirectGroup = createIndirectGroup(currGroupId,
-                            null, null, null,
-                            lastSetOfGroupIds.get(sp),
-                            labelStack.get(i).intValue(), false);
-                    /* Overwrite with this iteration's group IDs */
-                    lastSetOfGroupIds.put(sp, currGroupId);
-                    userDefinedGroups.put(currGroupId, indirectGroup);
-                }
-            }
-        }
-        log.debug("createGroup: group created with innermost group id {}",
-                innermostGroupId);
-        return innermostGroupId;
-    }
-
-    /*
-    @Override
-    public void removeTunnel(String tunnelId) {
-        List<Integer> groups = tunnelGroupIdTable.get(tunnelId);
-        if (groups == null)
-            return;
-
-        // we need to delete groups in reverse order
-        for (int i = groups.size() - 1; i >= 0; i--) {
-            int groupId = groups.get(i);
-            deleteGroup(groupId);
-        }
-        tunnelGroupIdTable.remove(tunnelId);
-    }
-    */
-
-    /**
-     * Remove the specified group
-     *
-     * @param groupId group identifier
-     * @return success/fail
-     */
-    public boolean removeGroup(int groupId) {
-        EcmpInfo group = userDefinedGroups.get(groupId);
-        if (group == null) {
-            log.warn("removeGroup: with invalid group id");
-            return false;
-        }
-        for (BucketInfo bucket : group.buckets) {
-            int currGroupIdToBeDeleted = bucket.groupNo;
-            while (currGroupIdToBeDeleted != -1) {
-                /* Assuming indirect groups with single buckets */
-                int nextGroupIdToBeDeleted =
-                        userDefinedGroups.get(currGroupIdToBeDeleted).
-                        buckets.get(0).groupNo;
-                deleteGroup(currGroupIdToBeDeleted);
-                userDefinedGroups.remove(currGroupIdToBeDeleted);
-                currGroupIdToBeDeleted = nextGroupIdToBeDeleted;
-            }
-        }
-
-        deleteGroup(groupId);
-        userDefinedGroups.remove(groupId);
-        log.debug("removeGroup: removed group with group id {}", groupId);
-        return true;
-    }
-
-    @Override
-    public Map<String, String> getPublishAttributes() {
-        return publishAttributes;
-    }
-
-    // *****************************
-    // Unused
-    // *****************************
-
-    @SuppressWarnings("unused")
-    private void setAsyncConfig() throws IOException {
-        List<OFMessage> msglist = new ArrayList<OFMessage>(3);
-        OFMessage setAC = null;
-
-        if (role == Role.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 == Role.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);
-
-        write(msglist);
-    }
-
-    @SuppressWarnings("unused")
-    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 == Role.MASTER || role == Role.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)));
-        }
-
-    }
-
-    @SuppressWarnings("unused")
-    private void getTableFeatures() throws IOException {
-        OFMessage gtf = factory.buildTableFeaturesStatsRequest()
-                .setXid(getNextTransactionId())
-                .build();
-        write(gtf, null);
-    }
-
-    @SuppressWarnings("unused")
-    private void sendGroupFeaturesRequest() throws IOException {
-        OFMessage gfr = factory.buildGroupFeaturesStatsRequest()
-                .setXid(getNextTransactionId())
-                .build();
-        write(gfr, null);
-    }
-
-    private void processGroupFeatures(OFGroupFeaturesStatsReply gfsr) {
-        log.info("Sw: {} Group Features {}", getStringId(), gfsr);
-    }
-
-    @SuppressWarnings("unused")
-    private void testMultipleLabels() {
-        if (getId() == 1) {
-            List<OFMessage> msglist = new ArrayList<OFMessage>();
-
-            // first all the indirect groups
-
-            // the group to switch 2 with outer label
-            OFGroup g1 = OFGroup.of(201);
-            OFOxmEthDst dmac1 = factory.oxms().ethDst(MacAddress.of("00:00:02:02:02:80"));
-            OFAction push1 = factory.actions().pushMpls(EthType.MPLS_UNICAST);
-            OFOxmMplsLabel lid1 = factory.oxms()
-                    .mplsLabel(U32.of(105)); // outer label
-            OFAction setMpls1 = factory.actions().buildSetField()
-                    .setField(lid1).build();
-            OFOxmMplsBos bos1 = factory.oxms()
-                    .mplsBos(OFBooleanValue.FALSE);
-            OFAction setB1 = factory.actions().buildSetField()
-                    .setField(bos1).build();
-            OFAction setDA1 = factory.actions().buildSetField()
-                    .setField(dmac1).build();
-            OFAction outp1 = factory.actions().buildOutput()
-                    .setPort(OFPort.of(2))
-                    .build();
-            List<OFAction> a1 = new ArrayList<OFAction>();
-            a1.add(push1);
-            a1.add(setMpls1);
-            a1.add(setB1);
-            a1.add(setDA1);
-            a1.add(outp1);
-            OFBucket b1 = factory.buildBucket()
-                    .setActions(a1)
-                    .build();
-            OFMessage gm1 = factory.buildGroupAdd()
-                    .setGroup(g1)
-                    .setBuckets(Collections.singletonList(b1))
-                    .setGroupType(OFGroupType.INDIRECT)
-                    .setXid(getNextTransactionId())
-                    .build();
-            msglist.add(gm1);
-
-            // the group to switch 3 with outer label
-            OFGroup g2 = OFGroup.of(301);
-            OFOxmEthDst dmac2 = factory.oxms().ethDst(MacAddress.of("00:00:03:03:03:80"));
-            OFAction push2 = factory.actions().pushMpls(EthType.MPLS_UNICAST);
-            OFOxmMplsLabel lid2 = factory.oxms()
-                    .mplsLabel(U32.of(104)); // outer label
-            OFAction setMpls2 = factory.actions().buildSetField()
-                    .setField(lid2).build();
-            OFOxmMplsBos bos2 = factory.oxms()
-                    .mplsBos(OFBooleanValue.FALSE);
-            OFAction setB2 = factory.actions().buildSetField()
-                    .setField(bos2).build();
-            OFAction setDA2 = factory.actions().buildSetField()
-                    .setField(dmac2).build();
-            OFAction outp2 = factory.actions().buildOutput()
-                    .setPort(OFPort.of(3))
-                    .build();
-            List<OFAction> a2 = new ArrayList<OFAction>();
-            a2.add(push2);
-            a2.add(setMpls2);
-            a2.add(setB2);
-            a2.add(setDA2);
-            a2.add(outp2);
-            OFBucket b2 = factory.buildBucket()
-                    .setActions(a2)
-                    .build();
-            OFMessage gm2 = factory.buildGroupAdd()
-                    .setGroup(g2)
-                    .setBuckets(Collections.singletonList(b2))
-                    .setGroupType(OFGroupType.INDIRECT)
-                    .setXid(getNextTransactionId())
-                    .build();
-            msglist.add(gm2);
-
-            // now add main ECMP group with inner labels
-            OFGroup group = OFGroup.of(786);
-            List<OFBucket> buckets = new ArrayList<OFBucket>();
-            for (int i = 0; i < 2; i++) { // 2 buckets
-
-                List<OFAction> actions = new ArrayList<OFAction>();
-                OFOxmEthSrc smac = factory.oxms()
-                        .ethSrc(MacAddress.of("00:00:01:01:01:80"));
-                OFAction setSA = factory.actions().buildSetField()
-                        .setField(smac).build();
-                actions.add(setSA);
-
-                if (i == 0) {
-                    // send to switch 2
-                    OFAction pushX = factory.actions().pushMpls(EthType.MPLS_UNICAST);
-                    OFOxmMplsLabel lidX = factory.oxms()
-                            .mplsLabel(U32.of(106)); // inner label
-                    OFAction setX = factory.actions().buildSetField()
-                            .setField(lidX).build();
-                    OFOxmMplsBos bosX = factory.oxms()
-                            .mplsBos(OFBooleanValue.TRUE);
-                    OFAction setBX = factory.actions().buildSetField()
-                            .setField(bosX).build();
-                    OFAction ogX = factory.actions().buildGroup()
-                            .setGroup(g1).build();
-                    actions.add(pushX);
-                    actions.add(setX);
-                    actions.add(setBX);
-                    actions.add(ogX);
-
-                } else {
-                    // send to switch 3
-                    OFAction pushY = factory.actions().pushMpls(EthType.MPLS_UNICAST);
-                    OFOxmMplsLabel lidY = factory.oxms()
-                            .mplsLabel(U32.of(106)); // inner label
-                    OFAction setY = factory.actions().buildSetField()
-                            .setField(lidY).build();
-                    OFOxmMplsBos bosY = factory.oxms()
-                            .mplsBos(OFBooleanValue.TRUE);
-                    OFAction setBY = factory.actions().buildSetField()
-                            .setField(bosY).build();
-                    OFAction ogY = factory.actions().buildGroup()
-                            .setGroup(g2).build();
-                    actions.add(pushY);
-                    actions.add(setY);
-                    actions.add(setBY);
-                    actions.add(ogY);
-                }
-
-                OFBucket ofb = factory.buildBucket()
-                        .setWeight(1)
-                        .setActions(actions)
-                        .build();
-                buckets.add(ofb);
-            }
-
-            OFMessage gm = factory.buildGroupAdd()
-                    .setGroup(group)
-                    .setBuckets(buckets)
-                    .setGroupType(OFGroupType.SELECT)
-                    .setXid(getNextTransactionId())
-                    .build();
-            msglist.add(gm);
-
-            // create an ACL entry to use this ecmp group
-            Builder matchBuilder = factory.buildMatch();
-            matchBuilder.setExact(MatchField.ETH_TYPE, EthType.of(0x800));
-            matchBuilder.setMasked(MatchField.IPV4_DST,
-                    IPv4Address.of("7.7.7.0")
-                            .withMaskOfLength(24));
-
-            OFAction grp = factory.actions().buildGroup()
-                    .setGroup(OFGroup.of(786))
-                    .build();
-            List<OFAction> writeActions = Collections.singletonList(grp);
-
-            OFInstruction clearInstr = factory.instructions().clearActions();
-            OFInstruction writeInstr = factory.instructions().buildWriteActions()
-                    .setActions(writeActions).build();
-            List<OFInstruction> instructions = new ArrayList<OFInstruction>();
-            instructions.add(clearInstr);
-            instructions.add(writeInstr);
-
-            OFFlowMod.Builder fmBuilder = factory.buildFlowAdd();
-
-            OFMessage aclFlow = fmBuilder
-                    .setTableId(TableId.of(TABLE_ACL))
-                    .setMatch(matchBuilder.build())
-                    .setInstructions(instructions)
-                    .setPriority(10) // TODO: wrong - should be MA
-                                     // priority
-                    .setBufferId(OFBufferId.NO_BUFFER)
-                    .setIdleTimeout(0)
-                    .setHardTimeout(0)
-                    .setXid(getNextTransactionId())
-                    .build();
-            msglist.add(aclFlow);
-
-            try {
-                write(msglist);
-            } catch (IOException e) {
-                // TODO Auto-generated catch block
-                e.printStackTrace();
-            }
-        }
-    }
-
-
-
-}