/*
 * Copyright 2014 Open Networking Laboratory
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.onlab.onos.openflow.drivers;

import org.onlab.onos.openflow.controller.Dpid;
import org.onlab.onos.openflow.controller.RoleState;
import org.onlab.onos.openflow.controller.driver.AbstractOpenFlowSwitch;
import org.onlab.onos.openflow.controller.driver.SwitchDriverSubHandshakeAlreadyStarted;
import org.onlab.onos.openflow.controller.driver.SwitchDriverSubHandshakeCompleted;
import org.onlab.onos.openflow.controller.driver.SwitchDriverSubHandshakeNotStarted;
import org.projectfloodlight.openflow.protocol.OFAsyncGetReply;
import org.projectfloodlight.openflow.protocol.OFBarrierRequest;
import org.projectfloodlight.openflow.protocol.OFBucket;
import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
import org.projectfloodlight.openflow.protocol.OFFactory;
import org.projectfloodlight.openflow.protocol.OFGroupDescStatsReply;
import org.projectfloodlight.openflow.protocol.OFGroupFeaturesStatsReply;
import org.projectfloodlight.openflow.protocol.OFGroupType;
import org.projectfloodlight.openflow.protocol.OFMatchV3;
import org.projectfloodlight.openflow.protocol.OFMessage;
import org.projectfloodlight.openflow.protocol.OFOxmList;
import org.projectfloodlight.openflow.protocol.OFPortDesc;
import org.projectfloodlight.openflow.protocol.OFStatsReply;
import org.projectfloodlight.openflow.protocol.action.OFAction;
import org.projectfloodlight.openflow.protocol.instruction.OFInstruction;
import org.projectfloodlight.openflow.protocol.oxm.OFOxmEthDst;
import org.projectfloodlight.openflow.protocol.oxm.OFOxmEthSrc;
import org.projectfloodlight.openflow.protocol.oxm.OFOxmEthType;
import org.projectfloodlight.openflow.protocol.oxm.OFOxmInPort;
import org.projectfloodlight.openflow.protocol.oxm.OFOxmIpv4DstMasked;
import org.projectfloodlight.openflow.protocol.oxm.OFOxmMetadataMasked;
import org.projectfloodlight.openflow.protocol.oxm.OFOxmMplsLabel;
import org.projectfloodlight.openflow.protocol.oxm.OFOxmVlanVid;
import org.projectfloodlight.openflow.types.EthType;
import org.projectfloodlight.openflow.types.IPv4Address;
import org.projectfloodlight.openflow.types.MacAddress;
import org.projectfloodlight.openflow.types.OFBufferId;
import org.projectfloodlight.openflow.types.OFGroup;
import org.projectfloodlight.openflow.types.OFMetadata;
import org.projectfloodlight.openflow.types.OFPort;
import org.projectfloodlight.openflow.types.OFVlanVidMatch;
import org.projectfloodlight.openflow.types.TableId;
import org.projectfloodlight.openflow.types.U32;
import org.projectfloodlight.openflow.types.U64;
import org.projectfloodlight.openflow.util.HexString;

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

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

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

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

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

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

    private final Map<Integer, OFGroup> l2groups;

    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);
        }

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

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

        case GET_ASYNC_REPLY:
            OFAsyncGetReply asrep = (OFAsyncGetReply) m;
            decodeAsyncGetReply(asrep);
            break;
        case STATS_REPLY:
            processStatsReply((OFStatsReply) m);
            break;
        case PACKET_IN:
        case PORT_STATUS:
        case QUEUE_GET_CONFIG_REPLY:
        case ROLE_REPLY:
        case FEATURES_REPLY:
        case FLOW_REMOVED:
            break;

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

        }
    }

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

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

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

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

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

        sendMsg(msglist);
    }

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

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

    }

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

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

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

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

    private int getVlanConfig(int portnum) {
        int portVlan = 10 * portnum;
        if ((getId() == 0x1 && portnum == 6) ||
                (getId() == 0x2) ||
                (getId() == 0x3 && portnum == 2)) {
            portVlan = 192; // 0xc0
        }
        return portVlan;
    }

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

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

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

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

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

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

            OFBucket bucket = factory.buildBucket()
                    .setActions(actions).build();
            List<OFBucket> buckets = Collections.singletonList(bucket);
            OFMessage gmAdd = factory.buildGroupAdd()
                    .setGroup(gl3)
                    .setBuckets(buckets)
                    .setGroupType(OFGroupType.INDIRECT)
                    .setXid(getNextTransactionId())
                    .build();
            msglist.add(gmAdd);
        }
        sendMsg(msglist);
        log.debug("Creating {} L3 groups in sw {}", msglist.size(), getStringId());
    }

    /*
     * L2.5 or mpls-unicast groups are only created for those router ports
     * connected to other router ports. They differ from the corresponding
     * L3-unicast group only by the fact that they decrement the MPLS TTL
     * instead of the IP ttl
     */
    private void setL25Groups() throws IOException {
        List<OFMessage> msglist = new ArrayList<OFMessage>();
        for (OFGroup gl2 : l2groups.values()) {
            int gnum = gl2.getGroupNumber();
            int portnum = gnum & 0x0000ffff;
            int vlanid = ((gnum & 0x0fff0000) >> VLAN_ID_OFFSET);
            MacAddress sAddr = getRouterMacAddr();
            OFAction setDA = getDestAction(portnum);
            // setDA will only be non-null for ports connected to routers
            if (setDA != null) {
                OFGroup gl3 = OFGroup.of(0xa0000000 | portnum); // different id
                // for mpls
                // group
                OFAction group = factory.actions().buildGroup()
                        .setGroup(gl2).build();
                OFOxmEthSrc srcAddr = factory.oxms().ethSrc(sAddr);
                OFAction setSA = factory.actions().buildSetField()
                        .setField(srcAddr).build();
                OFOxmVlanVid vid = factory.oxms().vlanVid(OFVlanVidMatch.ofVlan(vlanid));
                OFAction setVlan = factory.actions().buildSetField()
                        .setField(vid).build();
                OFAction decMplsTtl = factory.actions().decMplsTtl();
                List<OFAction> actions = new ArrayList<OFAction>();
                actions.add(decMplsTtl); // decrement the MPLS
                // TTL/do-checksum/check TTL and MTU
                actions.add(setVlan); // set the vlan-id of the exit-port (and
                // l2group)
                actions.add(setSA); // set this routers mac address
                actions.add(setDA);
                actions.add(group);
                OFBucket bucket = factory.buildBucket()
                        .setActions(actions).build();
                List<OFBucket> buckets = Collections.singletonList(bucket);
                OFMessage gmAdd = factory.buildGroupAdd()
                        .setGroup(gl3)
                        .setBuckets(buckets)
                        .setGroupType(OFGroupType.INDIRECT)
                        .setXid(getNextTransactionId())
                        .build();
                msglist.add(gmAdd);
            }
        }
        sendMsg(msglist);
        log.debug("Creating {} MPLS groups in sw {}", msglist.size(), getStringId());
    }

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

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

        }
    }

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

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

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

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

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

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

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

    private List<String> getMySubnetIps() { // send to controller
        List<String> subnetIps = new ArrayList<String>();
        if (getId() == 0x1) {
            subnetIps.add("10.0.2.0");
            subnetIps.add("10.0.3.0");
            subnetIps.add("10.0.1.0");
        }
        // 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);
        }
        sendMsg(msglist);
        log.debug("Adding {} my-ip-rules in sw {}", msglist.size(), getStringId());
    }

    private void populateMySubnets() throws IOException {
        List<OFMessage> msglist = new ArrayList<OFMessage>();
        // next prefix-based subnet-IP's configured on my interfaces
        // need to ARP for exact-IP, so write-action instruction to send to
        // controller
        // this has different mask and priority than earlier case
        List<String> subnetIps = getMySubnetIps();
        for (int i = 0; i < subnetIps.size(); i++) {
            OFOxmEthType ethTypeIp = factory.oxms()
                    .ethType(EthType.IPv4);
            OFOxmIpv4DstMasked ipPrefix = factory.oxms().ipv4DstMasked(
                    IPv4Address.of(subnetIps.get(i)),
                    IPv4Address.of(0xffffff00)); // '/24' mask
            OFOxmList oxmListSlash24 = OFOxmList.of(ethTypeIp, ipPrefix);
            OFMatchV3 match = factory.buildMatchV3()
                    .setOxmList(oxmListSlash24).build();
            OFAction outc = factory.actions().buildOutput()
                    .setPort(OFPort.CONTROLLER).setMaxLen(OFPCML_NO_BUFFER)
                    .build();
            OFInstruction writeInstr = factory.instructions().buildWriteActions()
                    .setActions(Collections.singletonList(outc)).build();
            OFInstruction gotoInstr = factory.instructions().buildGotoTable()
                    .setTableId(TableId.of(TABLE_ACL)).build();
            List<OFInstruction> instructions = new ArrayList<OFInstruction>();
            instructions.add(writeInstr);
            instructions.add(gotoInstr);
            OFMessage myIpEntry = factory.buildFlowAdd()
                    .setTableId(TableId.of(TABLE_IPV4_UNICAST))
                    .setMatch(match)
                    .setInstructions(instructions)
                    .setPriority(SLASH_24_PRIORITY)
                    .setBufferId(OFBufferId.NO_BUFFER)
                    .setIdleTimeout(0)
                    .setHardTimeout(0)
                    .setXid(getNextTransactionId())
                    .build();
            msglist.add(myIpEntry);
        }
        sendMsg(msglist);
        log.debug("Adding {} subnet-ip-rules in sw {}", msglist.size(), getStringId());
        msglist.clear();
    }

    private void populateRoutes() throws IOException {
        List<OFMessage> msglist = new ArrayList<OFMessage>();
        // addresses where I know the next-hop's mac-address because it is a
        // router port - so I have an L3 interface to it (and an MPLS interface)
        List<RouteEntry> routerNextHopIps = getRouterNextHopIps();
        for (int i = 0; i < routerNextHopIps.size(); i++) {
            OFOxmEthType ethTypeIp = factory.oxms()
                    .ethType(EthType.IPv4);
            OFOxmIpv4DstMasked ipPrefix = factory.oxms()
                    .ipv4DstMasked(
                            IPv4Address.of(routerNextHopIps.get(i).prefix),
                            IPv4Address.of(routerNextHopIps.get(i).mask)
                            );
            OFOxmList oxmListSlash32 = OFOxmList.of(ethTypeIp, ipPrefix);
            OFMatchV3 match = factory.buildMatchV3()
                    .setOxmList(oxmListSlash32).build();
            OFAction outg = factory.actions().buildGroup()
                    .setGroup(OFGroup.of(0xa0000000 | // mpls group id
                            routerNextHopIps.get(i).nextHopPort))
                            .build();
            // lots of actions before forwarding to mpls group, and
            // unfortunately
            // they need to be apply-actions

            OFAction pushlabel = factory.actions().pushMpls(EthType.MPLS_UNICAST);
            OFOxmMplsLabel l = factory.oxms()
                    .mplsLabel(U32.of(routerNextHopIps.get(i).label));
            OFAction setlabelid = factory.actions().buildSetField()
                    .setField(l).build();
            OFAction copyTtlOut = factory.actions().copyTtlOut();
            // OFAction setBos =
            // factory.actions().buildSetField().setField(bos).build();

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

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

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

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

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

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

        }
        sendMsg(msglist);
        log.debug("Adding {} next-hop-router-rules in sw {}", msglist.size(),
                getStringId());

        // add a table-miss entry to table 4 for debugging - leave it out
        // unclear packet state - causes switch to crash
        // populateTableMissEntry(TABLE_META, false, true,
        // true, TABLE_ACL);
    }

    private void populateHostRoutes() throws IOException {
        List<OFMessage> msglist = new ArrayList<OFMessage>();
        // addresses where I know the next hop's mac-address and I can set the
        // destination mac in the match-instruction.write-action
        // either I sent out arp-request or I got an arp-request from this host
        List<RouteEntry> hostNextHopIps = getHostNextHopIps();
        for (int i = 0; i < hostNextHopIps.size(); i++) {
            OFOxmEthType ethTypeIp = factory.oxms()
                    .ethType(EthType.IPv4);
            OFOxmIpv4DstMasked ipPrefix = factory.oxms()
                    .ipv4DstMasked(
                            IPv4Address.of(hostNextHopIps.get(i).prefix),
                            IPv4Address.NO_MASK); // host addr should be /32
            OFOxmList oxmListSlash32 = OFOxmList.of(ethTypeIp, ipPrefix);
            OFMatchV3 match = factory.buildMatchV3()
                    .setOxmList(oxmListSlash32).build();
            OFAction setDmac = null, outg = null;
            OFOxmEthDst dmac = factory.oxms()
                    .ethDst(MacAddress.of(hostNextHopIps.get(i).dstMac));
            setDmac = factory.actions().buildSetField()
                    .setField(dmac).build();
            outg = factory.actions().buildGroup()
                    .setGroup(OFGroup.of(0x20000000 | hostNextHopIps.get(i).nextHopPort)) // l3group
                    // id
                    .build();
            List<OFAction> writeActions = new ArrayList<OFAction>();
            writeActions.add(setDmac);
            writeActions.add(outg);
            OFInstruction writeInstr = factory.instructions().buildWriteActions()
                    .setActions(writeActions).build();
            OFInstruction gotoInstr = factory.instructions().buildGotoTable()
                    .setTableId(TableId.of(TABLE_ACL)).build();
            List<OFInstruction> instructions = new ArrayList<OFInstruction>();
            instructions.add(writeInstr);
            instructions.add(gotoInstr);
            OFMessage myIpEntry = factory.buildFlowAdd()
                    .setTableId(TableId.of(TABLE_IPV4_UNICAST))
                    .setMatch(match)
                    .setInstructions(instructions)
                    .setPriority(MAX_PRIORITY) // highest priority for exact
                    // match
                    .setBufferId(OFBufferId.NO_BUFFER)
                    .setIdleTimeout(0)
                    .setHardTimeout(0)
                    .setXid(getNextTransactionId())
                    .build();
            msglist.add(myIpEntry);
        }
        sendMsg(msglist);
        log.debug("Adding {} next-hop-host-rules in sw {}", msglist.size(), getStringId());
    }

    private static class MplsEntry {
        int labelid;
        int portnum;

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

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

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

        // match for everything else to send to ACL table. Essentially
        // the table miss flow entry
        populateTableMissEntry(TABLE_MPLS, false, true,
                true, TABLE_ACL);

    }

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

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

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

        if (!toControllerNow && !toControllerWrite && !toTable) {
            // table-miss has no instruction - at which point action-set will be
            // executed - if there is an action to output/group in the action
            // set
            // the packet will be sent there, otherwise it will be dropped.
            instructions = Collections.EMPTY_LIST;
        }

        OFMessage tableMissEntry = factory.buildFlowAdd()
                .setTableId(TableId.of(tableToAdd))
                .setMatch(match) // match everything
                .setInstructions(instructions)
                .setPriority(MIN_PRIORITY)
                .setBufferId(OFBufferId.NO_BUFFER)
                .setIdleTimeout(0)
                .setHardTimeout(0)
                .setXid(getNextTransactionId())
                .build();

        write(tableMissEntry);
    }

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

        write(br);
    }

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

    @Override
    public void write(OFMessage msg) {
        this.channel.write(Collections.singletonList(msg));

    }

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

}
