package org.onlab.onos.of.drivers;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;

import org.onlab.onos.of.controller.Dpid;
import org.onlab.onos.of.controller.RoleState;
import org.onlab.onos.of.controller.impl.internal.AbstractOpenFlowSwitch;
import org.onlab.onos.of.controller.impl.internal.SwitchDriverSubHandshakeAlreadyStarted;
import org.onlab.onos.of.controller.impl.internal.SwitchDriverSubHandshakeCompleted;
import org.onlab.onos.of.controller.impl.internal.SwitchDriverSubHandshakeNotStarted;
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.OFGroupDescStatsReply;
import org.projectfloodlight.openflow.protocol.OFGroupFeaturesStatsReply;
import org.projectfloodlight.openflow.protocol.OFGroupType;
import org.projectfloodlight.openflow.protocol.OFMatchV3;
import org.projectfloodlight.openflow.protocol.OFMessage;
import org.projectfloodlight.openflow.protocol.OFOxmList;
import org.projectfloodlight.openflow.protocol.OFPortDesc;
import org.projectfloodlight.openflow.protocol.OFStatsReply;
import org.projectfloodlight.openflow.protocol.action.OFAction;
import org.projectfloodlight.openflow.protocol.instruction.OFInstruction;
import org.projectfloodlight.openflow.protocol.oxm.OFOxmEthDst;
import org.projectfloodlight.openflow.protocol.oxm.OFOxmEthSrc;
import org.projectfloodlight.openflow.protocol.oxm.OFOxmEthType;
import org.projectfloodlight.openflow.protocol.oxm.OFOxmInPort;
import org.projectfloodlight.openflow.protocol.oxm.OFOxmIpv4DstMasked;
import org.projectfloodlight.openflow.protocol.oxm.OFOxmMetadataMasked;
import org.projectfloodlight.openflow.protocol.oxm.OFOxmMplsLabel;
import org.projectfloodlight.openflow.protocol.oxm.OFOxmVlanVid;
import org.projectfloodlight.openflow.types.EthType;
import org.projectfloodlight.openflow.types.IPv4Address;
import org.projectfloodlight.openflow.types.MacAddress;
import org.projectfloodlight.openflow.types.OFBufferId;
import org.projectfloodlight.openflow.types.OFGroup;
import org.projectfloodlight.openflow.types.OFMetadata;
import org.projectfloodlight.openflow.types.OFPort;
import org.projectfloodlight.openflow.types.OFVlanVidMatch;
import org.projectfloodlight.openflow.types.TableId;
import org.projectfloodlight.openflow.types.U32;
import org.projectfloodlight.openflow.types.U64;
import org.projectfloodlight.openflow.util.HexString;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * OFDescriptionStatistics Vendor (Manufacturer Desc.): Stanford University,
 * Ericsson Research and CPqD Research. Make (Hardware Desc.) : OpenFlow 1.3
 * Reference Userspace Switch Model (Datapath Desc.) : None Software : Serial :
 * None
 */
public class OFSwitchImplCPqD13 extends AbstractOpenFlowSwitch {

    private Logger log =
            LoggerFactory.getLogger(OFSwitchImplCPqD13.class);

    private static final int VLAN_ID_OFFSET = 16;
    private AtomicBoolean driverHandshakeComplete;
    private OFFactory factory;
    private static final int OFPCML_NO_BUFFER = 0xffff;
    // Configuration of asynch messages to controller. We need different
    // asynch messages depending on role-equal or role-master.
    // We don't want to get anything if we are slave.
    private static final long SET_FLOW_REMOVED_MASK_MASTER = 0xf;
    private static final long SET_PACKET_IN_MASK_MASTER = 0x7;
    private static final long SET_PORT_STATUS_MASK_MASTER = 0x7;
    private static final long SET_FLOW_REMOVED_MASK_EQUAL = 0x0;
    private static final long SET_PACKET_IN_MASK_EQUAL = 0x0;
    private static final long SET_PORT_STATUS_MASK_EQUAL = 0x7;
    private static final long SET_ALL_SLAVE = 0x0;

    private static final long TEST_FLOW_REMOVED_MASK = 0xf;
    private static final long TEST_PACKET_IN_MASK = 0x7;
    private static final long TEST_PORT_STATUS_MASK = 0x7;
    private long barrierXidToWaitFor = -1;

    private static final int TABLE_VLAN = 0;
    private static final int TABLE_TMAC = 1;
    private static final int TABLE_IPV4_UNICAST = 2;
    private static final int TABLE_MPLS = 3;
    private static final int TABLE_META = 4;
    private static final int TABLE_ACL = 5;

    private static final short MAX_PRIORITY = (short) 0xffff;
    private static final short SLASH_24_PRIORITY = (short) 0xfff0;
    private static final short MIN_PRIORITY = 0x0;
    private static final U64 METADATA_MASK = U64.of(Long.MAX_VALUE << 1 | 0x1);

    private Map<Integer, OFGroup> l2groups;

    private final boolean usePipeline13;

    public OFSwitchImplCPqD13(Dpid dpid, OFDescStatsReply desc, boolean usePipeline13) {
        super(dpid);
        driverHandshakeComplete = new AtomicBoolean(false);
        l2groups = new ConcurrentHashMap<Integer, OFGroup>();
        setSwitchDescription(desc);

        this.usePipeline13 = usePipeline13;
    }

    /* (non-Javadoc)
     * @see java.lang.Object#toString()
     */
    @Override
    public String toString() {
        return "OFSwitchImplCPqD13 [" + ((channel != null)
                ? channel.getRemoteAddress() : "?")
                + " DPID[" + ((this.getStringId() != null) ? this.getStringId() : "?") + "]]";
    }

    @Override
    public void startDriverHandshake() {
        log.debug("Starting driver handshake for sw {}", getStringId());
        if (startDriverHandshakeCalled) {
            throw new SwitchDriverSubHandshakeAlreadyStarted();
        }
        startDriverHandshakeCalled = true;
        factory = this.factory();
        if (!usePipeline13) {
            // Send packet-in to controller if a packet misses the first table
            populateTableMissEntry(0, true, false, false, 0);
        } //else {
            // configureSwitch();
        //}
        sendBarrier(true);
    }

    @Override
    public boolean isDriverHandshakeComplete() {
        if (!startDriverHandshakeCalled) {
            throw new SwitchDriverSubHandshakeNotStarted();
        }
        return driverHandshakeComplete.get();
    }

    @Override
    public void processDriverHandshakeMessage(OFMessage m) {
        if (!startDriverHandshakeCalled) {
            throw new SwitchDriverSubHandshakeNotStarted();
        }
        if (driverHandshakeComplete.get()) {
            throw new SwitchDriverSubHandshakeCompleted(m);
        }

        if (!startDriverHandshakeCalled) {
            throw new SwitchDriverSubHandshakeNotStarted();
        }
        if (driverHandshakeComplete.get()) {
            throw new SwitchDriverSubHandshakeCompleted(m);
        }

        switch (m.getType()) {
        case BARRIER_REPLY:
            if (m.getXid() == barrierXidToWaitFor) {
                driverHandshakeComplete.set(true);
            }
            break;

        case ERROR:
            log.error("Switch {} Error {}", getStringId(), (OFErrorMsg) m);
            break;

        case FEATURES_REPLY:
            break;
        case FLOW_REMOVED:
            break;
        case GET_ASYNC_REPLY:
            OFAsyncGetReply asrep = (OFAsyncGetReply) m;
            decodeAsyncGetReply(asrep);
            break;

        case PACKET_IN:
            break;
        case PORT_STATUS:
            break;
        case QUEUE_GET_CONFIG_REPLY:
            break;
        case ROLE_REPLY:
            break;

        case STATS_REPLY:
            processStatsReply((OFStatsReply) m);
            break;

        default:
            log.debug("Received message {} during switch-driver subhandshake "
                    + "from switch {} ... Ignoring message", m, getStringId());

        }
    }

    private void configureSwitch() throws IOException {
        // setAsyncConfig();
        // getTableFeatures();
        sendGroupFeaturesRequest();
        setL2Groups();
        sendBarrier(false);
        setL3Groups();
        setL25Groups();
        sendGroupDescRequest();
        populateTableVlan();
        populateTableTMac();
        populateIpTable();
        populateMplsTable();
        populateTableMissEntry(TABLE_ACL, false, false, false, -1);
        sendBarrier(true);
    }

    private void setAsyncConfig() throws IOException {
        List<OFMessage> msglist = new ArrayList<OFMessage>(3);
        OFMessage setAC = null;

        if (role == RoleState.MASTER) {
            setAC = factory.buildAsyncSet()
                    .setFlowRemovedMaskEqualMaster(SET_FLOW_REMOVED_MASK_MASTER)
                    .setPacketInMaskEqualMaster(SET_PACKET_IN_MASK_MASTER)
                    .setPortStatusMaskEqualMaster(SET_PORT_STATUS_MASK_MASTER)
                    .setFlowRemovedMaskSlave(SET_ALL_SLAVE)
                    .setPacketInMaskSlave(SET_ALL_SLAVE)
                    .setPortStatusMaskSlave(SET_ALL_SLAVE)
                    .setXid(getNextTransactionId())
                    .build();
        } else if (role == RoleState.EQUAL) {
            setAC = factory.buildAsyncSet()
                    .setFlowRemovedMaskEqualMaster(SET_FLOW_REMOVED_MASK_EQUAL)
                    .setPacketInMaskEqualMaster(SET_PACKET_IN_MASK_EQUAL)
                    .setPortStatusMaskEqualMaster(SET_PORT_STATUS_MASK_EQUAL)
                    .setFlowRemovedMaskSlave(SET_ALL_SLAVE)
                    .setPacketInMaskSlave(SET_ALL_SLAVE)
                    .setPortStatusMaskSlave(SET_ALL_SLAVE)
                    .setXid(getNextTransactionId())
                    .build();
        }
        msglist.add(setAC);

        OFMessage br = factory.buildBarrierRequest()
                .setXid(getNextTransactionId())
                .build();
        msglist.add(br);

        OFMessage getAC = factory.buildAsyncGetRequest()
                .setXid(getNextTransactionId())
                .build();
        msglist.add(getAC);

        write(msglist);
    }

    private void decodeAsyncGetReply(OFAsyncGetReply rep) {
        long frm = rep.getFlowRemovedMaskEqualMaster();
        //long frs = rep.getFlowRemovedMaskSlave();
        long pim = rep.getPacketInMaskEqualMaster();
        //long pis = rep.getPacketInMaskSlave();
        long psm = rep.getPortStatusMaskEqualMaster();
        //long pss = rep.getPortStatusMaskSlave();

        if (role == RoleState.MASTER || role == RoleState.EQUAL) { // should separate
            log.info("FRM:{}", HexString.toHexString((frm & TEST_FLOW_REMOVED_MASK)));
            log.info("PIM:{}", HexString.toHexString((pim & TEST_PACKET_IN_MASK)));
            log.info("PSM:{}", HexString.toHexString((psm & TEST_PORT_STATUS_MASK)));
        }

    }

    private void getTableFeatures() throws IOException {
        OFMessage gtf = factory.buildTableFeaturesStatsRequest()
                .setXid(getNextTransactionId())
                .build();
        sendMsg(gtf);
    }

    private void sendGroupFeaturesRequest() throws IOException {
        OFMessage gfr = factory.buildGroupFeaturesStatsRequest()
                .setXid(getNextTransactionId())
                .build();
        sendMsg(gfr);
    }

    private void sendGroupDescRequest() throws IOException {
        OFMessage gdr = factory.buildGroupDescStatsRequest()
                .setXid(getNextTransactionId())
                .build();
        sendMsg(gdr);
    }

    /*Create L2 interface groups for all physical ports
     Naming convention followed is the same as OF-DPA spec
     eg. port 1 with allowed vlan 10, is enveloped in group with id,
         0x0 00a 0001, where the uppermost 4 bits identify an L2 interface,
         the next 12 bits identify the vlan-id, and the lowermost 16 bits
         identify the port number.*/
    private void setL2Groups() throws IOException {
        List<OFMessage> msglist = new ArrayList<OFMessage>();
        for (OFPortDesc p : getPorts()) {
            int pnum = p.getPortNo().getPortNumber();
            int portVlan = getVlanConfig(pnum);
            if (U32.of(pnum).compareTo(U32.of(OFPort.MAX.getPortNumber())) < 1) {
                OFGroup gl2 = OFGroup.of(pnum | (portVlan << VLAN_ID_OFFSET));
                OFAction out = factory.actions().buildOutput()
                        .setPort(p.getPortNo()).build();
                OFAction popVlan = factory.actions().popVlan();
                List<OFAction> actions = new ArrayList<OFAction>();
                actions.add(popVlan);
                actions.add(out);
                OFBucket bucket = factory.buildBucket()
                        .setActions(actions).build();
                List<OFBucket> buckets = Collections.singletonList(bucket);
                OFMessage gmAdd = factory.buildGroupAdd()
                        .setGroup(gl2)
                        .setBuckets(buckets)
                        .setGroupType(OFGroupType.INDIRECT)
                        .setXid(getNextTransactionId())
                        .build();
                msglist.add(gmAdd);
                l2groups.put(pnum, gl2);
            }
        }
        log.debug("Creating {} L2 groups in sw {}", msglist.size(), getStringId());
        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;
    }

    private MacAddress getRouterMacAddr() {
        if (getId() == 0x3) {
            return MacAddress.of("00:00:07:07:07:80"); // router mac
        }
        if (getId() == 0x1) {
            return MacAddress.of("00:00:01:01:01:80");
        }
        // switch 0x2
        return MacAddress.of("00:00:02:02:02:80");
    }

    // only for ports connected to other routers
    private OFAction getDestAction(int portnum) {
        OFAction setDA = null;
        MacAddress dAddr = null;
        if (getId() == 0x1 && portnum == 6) { // connected to switch 2
            dAddr = MacAddress.of("00:00:02:02:02:80");
        }
        if (getId() == 0x2) {
            if (portnum == 1) { // connected to sw 1
                dAddr = MacAddress.of("00:00:01:01:01:80");
            } else if (portnum == 2) { // connected to sw 3
                dAddr = MacAddress.of("00:00:07:07:07:80");
            }
        }
        if (getId() == 0x3) {
            if (portnum == 2) { // connected to switch 2
                dAddr = MacAddress.of("00:00:02:02:02:80");
            }
        }

        if (dAddr != null) {
            OFOxmEthDst dstAddr = factory.oxms().ethDst(dAddr);
            setDA = factory.actions().buildSetField()
                    .setField(dstAddr).build();
        }
        return setDA;
    }

    /*
     * L3 groups are created for all router ports and they all point to corresponding
     * L2 groups. Only the ports that connect to other routers will have the
     * DA set.
     */
    private void setL3Groups() throws IOException {
        List<OFMessage> msglist = new ArrayList<OFMessage>();
        for (OFGroup gl2 : l2groups.values()) {
            int gnum = gl2.getGroupNumber();
            int portnum = gnum & 0x0000ffff;
            int vlanid = ((gnum & 0x0fff0000) >> VLAN_ID_OFFSET);
            MacAddress sAddr = getRouterMacAddr();

            OFGroup gl3 = OFGroup.of(0x20000000 | portnum);
            OFAction group = factory.actions().buildGroup()
                    .setGroup(gl2).build();
            OFOxmEthSrc srcAddr = factory.oxms().ethSrc(sAddr);
            OFAction setSA = factory.actions().buildSetField()
                    .setField(srcAddr).build();
            OFOxmVlanVid vid = factory.oxms().vlanVid(OFVlanVidMatch.ofVlan(vlanid));
            OFAction setVlan = factory.actions().buildSetField()
                    .setField(vid).build();
            OFAction decTtl = factory.actions().decNwTtl();

            List<OFAction> actions = new ArrayList<OFAction>();
            actions.add(decTtl); // decrement the IP TTL/do-checksum/check TTL
                                 // and MTU
            actions.add(setVlan); // set the vlan-id of the exit-port (and
                                  // l2group)
            actions.add(setSA); // set this routers mac address
            // make L3Unicast group setDA for known (configured) ports
            // that connect to other routers
            OFAction setDA = getDestAction(portnum);
            if (setDA != null) {
                actions.add(setDA);
            }
            actions.add(group);

            OFBucket bucket = factory.buildBucket()
                    .setActions(actions).build();
            List<OFBucket> buckets = Collections.singletonList(bucket);
            OFMessage gmAdd = factory.buildGroupAdd()
                    .setGroup(gl3)
                    .setBuckets(buckets)
                    .setGroupType(OFGroupType.INDIRECT)
                    .setXid(getNextTransactionId())
                    .build();
            msglist.add(gmAdd);
        }
        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());
    }

    /* Using ECMP groups
     *
     * OFGroup group47 = OFGroup.of(47);
        OFAction outgroup1 = factory.actions()
                        .buildGroup()
                        .setGroup(group61)
                        .build();
        OFBucket buc47_1 = factory.buildBucket()
                        .setWeight(1)
                        .setActions(Collections.singletonList(outgroup1))
                        .build();
        OFAction outgroup2 = factory.actions()
                        .buildGroup()
                        .setGroup(group62)
                        .build();
        OFBucket buc47_2 = factory.buildBucket()
                        .setWeight(1)
                        .setActions(Collections.singletonList(outgroup2))
                        .build();
        List<OFBucket> buckets47 = new ArrayList<OFBucket>();
        buckets47.add(buc47_1);
        buckets47.add(buc47_2);
        OFMessage gmS12 = factory.buildGroupAdd()
                        .setGroup(group47)
                        .setBuckets(buckets47)
                        .setGroupType(OFGroupType.SELECT)
                        .setXid(getNextTransactionId())
                        .build();
        write(gmS12, null);     */

    private void processStatsReply(OFStatsReply sr) {
        switch (sr.getStatsType()) {
        case AGGREGATE:
            break;
        case DESC:
            break;
        case EXPERIMENTER:
            break;
        case FLOW:
            break;
        case GROUP_DESC:
            processGroupDesc((OFGroupDescStatsReply) sr);
            break;
        case GROUP_FEATURES:
            processGroupFeatures((OFGroupFeaturesStatsReply) sr);
            break;
        case METER_CONFIG:
            break;
        case METER_FEATURES:
            break;
        case PORT_DESC:
            break;
        case TABLE_FEATURES:
            break;
        default:
            break;

        }
    }

    private void processGroupFeatures(OFGroupFeaturesStatsReply gfsr) {
        log.info("Sw: {} Group Features {}", getStringId(), gfsr);
    }

    private void processGroupDesc(OFGroupDescStatsReply gdsr) {
        log.info("Sw: {} Group Desc {}", getStringId(), gdsr);
    }

    private void populateTableVlan() throws IOException {
        // for all incoming ports assign configured port-vlans
        // currently assign portnum*10 -> vlanid to access ports
        // and vlan 192 to router to router ports
        List<OFMessage> msglist = new ArrayList<OFMessage>();
        for (OFPortDesc p : getPorts()) {
            int pnum = p.getPortNo().getPortNumber();
            if (U32.of(pnum).compareTo(U32.of(OFPort.MAX.getPortNumber())) < 1) {
                int vlanid = getVlanConfig(pnum);
                OFOxmInPort oxp = factory.oxms().inPort(p.getPortNo());
                OFOxmVlanVid oxv = factory.oxms()
                        .vlanVid(OFVlanVidMatch.UNTAGGED);
                OFOxmList oxmList = OFOxmList.of(oxp, oxv);
                OFMatchV3 match = factory.buildMatchV3()
                        .setOxmList(oxmList).build();
                OFOxmVlanVid vidToSet = factory.oxms()
                        .vlanVid(OFVlanVidMatch.ofVlan(vlanid));
                OFAction pushVlan = factory.actions().pushVlan(EthType.VLAN_FRAME);
                OFAction setVlan = factory.actions().setField(vidToSet);
                List<OFAction> actionlist = new ArrayList<OFAction>();
                actionlist.add(pushVlan);
                actionlist.add(setVlan);
                OFInstruction appAction = factory.instructions().buildApplyActions()
                        .setActions(actionlist).build();
                OFInstruction gotoTbl = factory.instructions().buildGotoTable()
                        .setTableId(TableId.of(TABLE_TMAC)).build();
                List<OFInstruction> instructions = new ArrayList<OFInstruction>();
                instructions.add(appAction);
                instructions.add(gotoTbl);
                OFMessage flowEntry = factory.buildFlowAdd()
                        .setTableId(TableId.of(TABLE_VLAN))
                        .setMatch(match)
                        .setInstructions(instructions)
                        .setPriority(1000) // does not matter - all rules
                                           // exclusive
                        .setBufferId(OFBufferId.NO_BUFFER)
                        .setIdleTimeout(0)
                        .setHardTimeout(0)
                        .setXid(getNextTransactionId())
                        .build();
                msglist.add(flowEntry);
            }
        }
        // table-vlan has no table-miss entry, and so packets that miss are
        // essentially dropped
        write(msglist);
        log.debug("Adding {} vlan-rules in sw {}", msglist.size(), getStringId());
    }

    private void populateTableTMac() throws IOException {
        // match for ip packets
        OFOxmEthType oxe = factory.oxms().ethType(EthType.IPv4);
        OFOxmList oxmListIp = OFOxmList.of(oxe);
        OFMatchV3 matchIp = factory.buildMatchV3()
                .setOxmList(oxmListIp).build();
        OFInstruction gotoTblIp = factory.instructions().buildGotoTable()
                .setTableId(TableId.of(TABLE_IPV4_UNICAST)).build();
        List<OFInstruction> instructionsIp = Collections.singletonList(gotoTblIp);
        OFMessage ipEntry = factory.buildFlowAdd()
                .setTableId(TableId.of(TABLE_TMAC))
                .setMatch(matchIp)
                .setInstructions(instructionsIp)
                .setPriority(1000) // strict priority required lower than
                                   // multicastMac
                .setBufferId(OFBufferId.NO_BUFFER)
                .setIdleTimeout(0)
                .setHardTimeout(0)
                .setXid(getNextTransactionId())
                .build();

        // match for mpls packets
        OFOxmEthType oxmpls = factory.oxms().ethType(EthType.MPLS_UNICAST);
        OFOxmList oxmListMpls = OFOxmList.of(oxmpls);
        OFMatchV3 matchMpls = factory.buildMatchV3()
                .setOxmList(oxmListMpls).build();
        OFInstruction gotoTblMpls = factory.instructions().buildGotoTable()
                .setTableId(TableId.of(TABLE_MPLS)).build();
        List<OFInstruction> instructionsMpls = Collections.singletonList(gotoTblMpls);
        OFMessage mplsEntry = factory.buildFlowAdd()
                .setTableId(TableId.of(TABLE_TMAC))
                .setMatch(matchMpls)
                .setInstructions(instructionsMpls)
                .setPriority(1001) // strict priority required lower than
                                   // multicastMac
                .setBufferId(OFBufferId.NO_BUFFER)
                .setIdleTimeout(0)
                .setHardTimeout(0)
                .setXid(getNextTransactionId())
                .build();

        // match for everything else to send to controller. Essentially
        // the table miss flow entry
        populateTableMissEntry(TABLE_TMAC, true, false, false, -1);
        log.debug("Adding termination-mac-rules in sw {}", getStringId());
        List<OFMessage> msglist = new ArrayList<OFMessage>(2);
        msglist.add(ipEntry);
        msglist.add(mplsEntry);
        write(msglist);
    }

    private List<String> getMyIps() { // send to controller
        List<String> myIps = new ArrayList<String>();
        if (getId() == 0x1) {
            myIps.add("10.0.2.128");
            myIps.add("10.0.3.128");
            myIps.add("10.0.1.128");
            myIps.add("192.168.0.1");
        }
        if (getId() == 0x2) {
            myIps.add("192.168.0.2");
        }
        if (getId() == 0x3) {
            myIps.add("192.168.0.3");
            myIps.add("7.7.7.128");
        }
        return myIps;
    }

    private List<String> getMySubnetIps() { // send to controller
        List<String> subnetIps = new ArrayList<String>();
        if (getId() == 0x1) {
            subnetIps.add("10.0.2.0");
            subnetIps.add("10.0.3.0");
            subnetIps.add("10.0.1.0");
        }
        // TODO needed?
        //if (getId() == 0x2) {
        //}
        if (getId() == 0x3) {
            subnetIps.add("7.7.7.0");
        }
        return subnetIps;
    }

    private static class RouteEntry {
        String prefix;
        String mask;
        int nextHopPort;
        String dstMac;
        int label;

        public RouteEntry(String prefix, String mask, int nextHopPort, int label) {
            this.prefix = prefix;
            this.mask = mask;
            this.nextHopPort = nextHopPort;
            this.label = label;
        }

        public RouteEntry(String prefix, int nextHopPort, String dstMac) {
            this.prefix = prefix;
            this.nextHopPort = nextHopPort;
            this.dstMac = dstMac;
        }
    }

    // send out of mpls-group where the next-hop mac-da is already set
    private List<RouteEntry> getRouterNextHopIps() {
        List<RouteEntry> routerNextHopIps = new ArrayList<RouteEntry>();
        if (getId() == 0x1) {
            routerNextHopIps
                    .add(new RouteEntry("192.168.0.2", "255.255.255.255", 6, 102));
            routerNextHopIps
                    .add(new RouteEntry("192.168.0.3", "255.255.255.255", 6, 103));
            routerNextHopIps.add(new RouteEntry("7.7.7.0", "255.255.255.0", 6, 103));
        }
        //if (getId() == 0x2) {
            /* These are required for normal IP routing without labels.
            routerNextHopIps.add(new RouteEntry("192.168.0.1","255.255.255.255",1));
            routerNextHopIps.add(new RouteEntry("192.168.0.3","255.255.255.255",2));
            routerNextHopIps.add(new RouteEntry("10.0.1.0","255.255.255.0",1));
            routerNextHopIps.add(new RouteEntry("10.0.2.0","255.255.255.0",1));
            routerNextHopIps.add(new RouteEntry("10.0.3.0","255.255.255.0",1));
            routerNextHopIps.add(new RouteEntry("7.7.7.0","255.255.255.0",2));*/
        //}
        if (getId() == 0x3) {
            routerNextHopIps
                    .add(new RouteEntry("192.168.0.2", "255.255.255.255", 2, 102));
            routerNextHopIps
                    .add(new RouteEntry("192.168.0.1", "255.255.255.255", 2, 101));
            routerNextHopIps.add(new RouteEntry("10.0.1.0", "255.255.255.0", 2, 101));
            routerNextHopIps.add(new RouteEntry("10.0.2.0", "255.255.255.0", 2, 101));
            routerNextHopIps.add(new RouteEntry("10.0.3.0", "255.255.255.0", 2, 101));
        }
        return routerNextHopIps;
    }

    // known host mac-addr, setDA/send out of l3group
    private List<RouteEntry> getHostNextHopIps() {
        List<RouteEntry> hostNextHopIps = new ArrayList<RouteEntry>();
        if (getId() == 0x1) {
            hostNextHopIps.add(new RouteEntry("10.0.2.1", 4, "00:00:00:00:02:01"));
            hostNextHopIps.add(new RouteEntry("10.0.3.1", 5, "00:00:00:00:03:01"));
        }
        // TODO needed?
        //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(SLASH_24_PRIORITY)
                    .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();

            /*
            writeActions.add(pushlabel);  // need to be apply actions so can be
            writeActions.add(copyTtlOut); // matched in pseudo-table
            //writeActions.add(setlabelid); // bad support in cpqd
            //writeActions.add(setBos); no support in loxigen
            */

            List<OFAction> applyActions = new ArrayList<OFAction>();
            applyActions.add(pushlabel);
            applyActions.add(copyTtlOut);
            OFInstruction applyInstr = factory.instructions().buildApplyActions()
                    .setActions(applyActions).build();
            List<OFAction> writeActions = new ArrayList<OFAction>();
            writeActions.add(outg); // group will decr mpls-ttl, set mac-sa/da,
                                    // vlan
            OFInstruction writeInstr = factory.instructions().buildWriteActions()
                    .setActions(writeActions).build();

            // necessary to match in pseudo-table to overcome cpqd 1.3 flaw
            OFInstruction writeMeta = factory.instructions().buildWriteMetadata()
                    .setMetadata(U64.of(routerNextHopIps.get(i).label))
                    .setMetadataMask(METADATA_MASK).build();
            /*OFInstruction gotoInstr = factory.instructions().buildGotoTable()
                        .setTableId(TableId.of(TABLE_ACL)).build();*/
            OFInstruction gotoInstr = factory.instructions().buildGotoTable()
                    .setTableId(TableId.of(TABLE_META)).build();
            List<OFInstruction> instructions = new ArrayList<OFInstruction>();
            instructions.add(applyInstr);
            // instructions.add(writeInstr);// cannot write here - causes switch
            // to crash
            instructions.add(writeMeta);
            instructions.add(gotoInstr);

            int priority = -1;
            if (routerNextHopIps.get(i).mask.equals("255.255.255.255")) {
                priority = MAX_PRIORITY;
            } else {
                priority = SLASH_24_PRIORITY;
            }
            OFMessage myIpEntry = factory.buildFlowAdd()
                    .setTableId(TableId.of(TABLE_IPV4_UNICAST))
                    .setMatch(match)
                    .setInstructions(instructions)
                    .setPriority(priority)
                    .setBufferId(OFBufferId.NO_BUFFER)
                    .setIdleTimeout(0)
                    .setHardTimeout(0)
                    .setXid(getNextTransactionId())
                    .build();
            msglist.add(myIpEntry);

            // need to also handle psuedo-table entries to match-metadata and
            // set mpls
            // label-id
            OFOxmEthType ethTypeMpls = factory.oxms()
                    .ethType(EthType.MPLS_UNICAST);
            OFOxmMetadataMasked meta = factory.oxms()
                    .metadataMasked(
                            OFMetadata.ofRaw(routerNextHopIps.get(i).label),
                            OFMetadata.NO_MASK);
            OFOxmList oxmListMeta = OFOxmList.of(ethTypeMpls, meta);
            OFMatchV3 matchMeta = factory.buildMatchV3()
                    .setOxmList(oxmListMeta).build();
            List<OFAction> writeActions2 = new ArrayList<OFAction>();
            writeActions2.add(setlabelid);
            OFAction outg2 = factory.actions().buildGroup()
                    .setGroup(OFGroup.of(routerNextHopIps.get(i).nextHopPort |
                            (192 << VLAN_ID_OFFSET)))
                    .build();
            writeActions2.add(outg2);
            OFInstruction writeInstr2 = factory.instructions().buildWriteActions()
                    .setActions(writeActions2).build();
            OFInstruction gotoInstr2 = factory.instructions().buildGotoTable()
                    .setTableId(TableId.of(TABLE_ACL)).build();
            List<OFInstruction> instructions2 = new ArrayList<OFInstruction>();
            // unfortunately have to apply this action too
            OFInstruction applyInstr2 = factory.instructions().buildApplyActions()
                    .setActions(writeActions2).build();
            instructions2.add(applyInstr2);
            // instructions2.add(writeInstr2);
            // instructions2.add(gotoInstr2);

            /*OFMatchV3 match3 = factory.buildMatchV3()
                        .setOxmList(OFOxmList.of(meta)).build();
            OFInstruction clearInstruction = factory.instructions().clearActions();
            List<OFInstruction> instructions3 = new ArrayList<OFInstruction>();
            OFAction outc = factory.actions().buildOutput()
                        .setPort(OFPort.CONTROLLER).setMaxLen(OFPCML_NO_BUFFER)
                        .build();
            OFInstruction writec = factory.instructions()
                        .writeActions(Collections.singletonList(outc));
            instructions3.add(clearInstruction);
            instructions3.add(writec);
            instructions3.add(gotoInstr2); */
            OFMessage myMetaEntry = factory.buildFlowAdd()
                    .setTableId(TableId.of(TABLE_META))
                    .setMatch(matchMeta)
                    .setInstructions(instructions2)
                    .setPriority(MAX_PRIORITY)
                    .setBufferId(OFBufferId.NO_BUFFER)
                    .setIdleTimeout(0)
                    .setHardTimeout(0)
                    .setXid(getNextTransactionId())
                    .build();
            msglist.add(myMetaEntry);

        }
        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 static class MplsEntry {
        int labelid;
        int portnum;

        public MplsEntry(int labelid, int portnum) {
            this.labelid = labelid;
            this.portnum = portnum;
        }
    }

    private List<MplsEntry> getMplsEntries() {
        List<MplsEntry> myLabels = new ArrayList<MplsEntry>();
        if (getId() == 0x1) {
            myLabels.add(new MplsEntry(101, OFPort.CONTROLLER.getPortNumber()));
            myLabels.add(new MplsEntry(103, 6));
        }
        if (getId() == 0x2) {
            myLabels.add(new MplsEntry(103, 2));
            myLabels.add(new MplsEntry(102, OFPort.CONTROLLER.getPortNumber()));
            myLabels.add(new MplsEntry(101, 1));
        }
        if (getId() == 0x3) {
            myLabels.add(new MplsEntry(103, OFPort.CONTROLLER.getPortNumber()));
            myLabels.add(new MplsEntry(101, 2));
        }
        return myLabels;
    }

    private void populateMplsTable() throws IOException {
        List<OFMessage> msglist = new ArrayList<OFMessage>();
        List<MplsEntry> lfibEntries = getMplsEntries();
        for (int i = 0; i < lfibEntries.size(); i++) {
            OFOxmEthType ethTypeMpls = factory.oxms()
                    .ethType(EthType.MPLS_UNICAST);
            OFOxmMplsLabel labelid = factory.oxms()
                    .mplsLabel(U32.of(lfibEntries.get(i).labelid));
            OFOxmList oxmList = OFOxmList.of(ethTypeMpls, labelid);
            OFMatchV3 matchlabel = factory.buildMatchV3()
                    .setOxmList(oxmList).build();
            OFAction poplabel = factory.actions().popMpls(EthType.IPv4);
            OFAction sendTo = null;
            if (lfibEntries.get(i).portnum == OFPort.CONTROLLER.getPortNumber()) {
                sendTo = factory.actions().output(OFPort.CONTROLLER,
                        OFPCML_NO_BUFFER);
            } else {
                sendTo = factory.actions().group(OFGroup.of(
                        0xa0000000 | lfibEntries.get(i).portnum));
            }
            List<OFAction> writeActions = new ArrayList<OFAction>();
            writeActions.add(poplabel);
            writeActions.add(sendTo);
            OFInstruction writeInstr = factory.instructions().buildWriteActions()
                    .setActions(writeActions).build();
            OFInstruction gotoInstr = factory.instructions().buildGotoTable()
                    .setTableId(TableId.of(TABLE_ACL)).build();
            List<OFInstruction> instructions = new ArrayList<OFInstruction>();
            instructions.add(writeInstr);
            instructions.add(gotoInstr);
            OFMessage myMplsEntry = factory.buildFlowAdd()
                    .setTableId(TableId.of(TABLE_MPLS))
                    .setMatch(matchlabel)
                    .setInstructions(instructions)
                    .setPriority(MAX_PRIORITY) // exact match and exclusive
                    .setBufferId(OFBufferId.NO_BUFFER)
                    .setIdleTimeout(0)
                    .setHardTimeout(0)
                    .setXid(getNextTransactionId())
                    .build();
            msglist.add(myMplsEntry);
        }
        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);

    }

    /**
     * By default if none of the booleans in the call are set, then the
     * table-miss entry is added with no instructions, which means that pipeline
     * execution will stop, and the action set associated with the packet will
     * be executed.
     *
     * @param tableToAdd
     * @param toControllerNow as an APPLY_ACTION instruction
     * @param toControllerWrite as a WRITE_ACITION instruction
     * @param toTable as a GOTO_TABLE instruction
     * @param tableToSend
     * @throws IOException
     */
    @SuppressWarnings("unchecked")
    private void populateTableMissEntry(int tableToAdd, boolean toControllerNow,
            boolean toControllerWrite,
            boolean toTable, int tableToSend) {
        OFOxmList oxmList = OFOxmList.EMPTY;
        OFMatchV3 match = factory.buildMatchV3()
                .setOxmList(oxmList)
                .build();
        OFAction outc = factory.actions()
                .buildOutput()
                .setPort(OFPort.CONTROLLER)
                .setMaxLen(OFPCML_NO_BUFFER)
                .build();
        List<OFInstruction> instructions = new ArrayList<OFInstruction>();
        if (toControllerNow) {
            // table-miss instruction to send to controller immediately
            OFInstruction instr = factory.instructions()
                    .buildApplyActions()
                    .setActions(Collections.singletonList(outc))
                    .build();
            instructions.add(instr);
        }

        if (toControllerWrite) {
            // table-miss instruction to write-action to send to controller
            // this will be executed whenever the action-set gets executed
            OFInstruction instr = factory.instructions()
                    .buildWriteActions()
                    .setActions(Collections.singletonList(outc))
                    .build();
            instructions.add(instr);
        }

        if (toTable) {
            // table-miss instruction to goto-table x
            OFInstruction instr = factory.instructions()
                    .gotoTable(TableId.of(tableToSend));
            instructions.add(instr);
        }

        if (!toControllerNow && !toControllerWrite && !toTable) {
            // table-miss has no instruction - at which point action-set will be
            // executed - if there is an action to output/group in the action
            // set
            // the packet will be sent there, otherwise it will be dropped.
            instructions = (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();
        sendMsg(tableMissEntry);
    }

    private void sendBarrier(boolean finalBarrier) {
        int xid = getNextTransactionId();
        if (finalBarrier) {
            barrierXidToWaitFor = xid;
        }
        OFBarrierRequest br = factory
                .buildBarrierRequest()
                .setXid(xid)
                .build();
        sendMsg(br);
    }

    @Override
    public void sendMsg(OFMessage m) {
        channel.write(m);
    }

    @Override
    public void write(List<OFMessage> msgs) {
        for (OFMessage m : msgs) {
            channel.write(m);
        }
    }

    @Override
    public Boolean supportNxRole() {
        return false;
    }

}
