package net.onrc.onos.apps.segmentrouting;

import java.io.IOException;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import net.floodlightcontroller.core.IFloodlightProviderService;
import net.floodlightcontroller.core.IOF13Switch;
import net.floodlightcontroller.core.IOF13Switch.NeighborSet;
import net.floodlightcontroller.core.module.FloodlightModuleContext;
import net.floodlightcontroller.core.module.FloodlightModuleException;
import net.floodlightcontroller.core.module.IFloodlightModule;
import net.floodlightcontroller.core.module.IFloodlightService;
import net.floodlightcontroller.core.util.SingletonTask;
import net.floodlightcontroller.threadpool.IThreadPoolService;
import net.onrc.onos.api.packet.IPacketListener;
import net.onrc.onos.api.packet.IPacketService;
import net.onrc.onos.core.flowprogrammer.IFlowPusherService;
import net.onrc.onos.core.main.config.IConfigInfoService;
import net.onrc.onos.core.matchaction.MatchAction;
import net.onrc.onos.core.matchaction.MatchActionId;
import net.onrc.onos.core.matchaction.MatchActionOperationEntry;
import net.onrc.onos.core.matchaction.action.Action;
import net.onrc.onos.core.matchaction.action.CopyTtlInAction;
import net.onrc.onos.core.matchaction.action.CopyTtlOutAction;
import net.onrc.onos.core.matchaction.action.DecMplsTtlAction;
import net.onrc.onos.core.matchaction.action.DecNwTtlAction;
import net.onrc.onos.core.matchaction.action.GroupAction;
import net.onrc.onos.core.matchaction.action.PopMplsAction;
import net.onrc.onos.core.matchaction.action.PushMplsAction;
import net.onrc.onos.core.matchaction.action.SetMplsIdAction;
import net.onrc.onos.core.matchaction.match.Ipv4Match;
import net.onrc.onos.core.matchaction.match.Match;
import net.onrc.onos.core.matchaction.match.MplsMatch;
import net.onrc.onos.core.packet.ARP;
import net.onrc.onos.core.packet.Ethernet;
import net.onrc.onos.core.packet.IPv4;
import net.onrc.onos.core.topology.ITopologyListener;
import net.onrc.onos.core.topology.ITopologyService;
import net.onrc.onos.core.topology.MutableTopology;
import net.onrc.onos.core.topology.Port;
import net.onrc.onos.core.topology.Switch;
import net.onrc.onos.core.topology.TopologyEvents;
import net.onrc.onos.core.util.Dpid;
import net.onrc.onos.core.util.IPv4Net;
import net.onrc.onos.core.util.SwitchPort;

import org.json.JSONArray;
import org.json.JSONException;
import org.projectfloodlight.openflow.types.EthType;
import org.projectfloodlight.openflow.types.IPv4Address;
import org.projectfloodlight.openflow.util.HexString;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class SegmentRoutingManager implements IFloodlightModule,
						ITopologyListener, IPacketListener {

    private static final Logger log = LoggerFactory
            .getLogger(SegmentRoutingManager.class);
    private ITopologyService topologyService;
    private IPacketService packetService;
    private MutableTopology mutableTopology;

    private List<ArpEntry> arpEntries;
    private ArpHandler arpHandler;
    private GenericIpHandler ipHandler;
    private IcmpHandler icmpHandler;
    private boolean networkConverged;
    private IThreadPoolService threadPool;
    private SingletonTask discoveryTask;
    private IFloodlightProviderService floodlightProvider;

    @Override
    public Collection<Class<? extends IFloodlightService>> getModuleServices() {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
        Collection<Class<? extends IFloodlightService>> l = new ArrayList<Class<? extends IFloodlightService>>();

        l.add(IFloodlightProviderService.class);
        l.add(IConfigInfoService.class);
        l.add(ITopologyService.class);
        l.add(IPacketService.class);
        l.add(IFlowPusherService.class);
        l.add(ITopologyService.class);

        return l;

    }

    @Override
    public void init(FloodlightModuleContext context) throws FloodlightModuleException {
        floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
        arpHandler = new ArpHandler(context, this);
        icmpHandler = new IcmpHandler(context, this);
        ipHandler = new GenericIpHandler(context, this);
        arpEntries = new ArrayList<ArpEntry>();
        topologyService = context.getServiceImpl(ITopologyService.class);
        threadPool = context.getServiceImpl(IThreadPoolService.class);
        mutableTopology = topologyService.getTopology();
        topologyService.addListener(this, false);

        this.packetService = context.getServiceImpl(IPacketService.class);
        packetService.registerPacketListener(this);

    }

    @Override
    public void startUp(FloodlightModuleContext context) throws FloodlightModuleException {
        networkConverged = false;

        ScheduledExecutorService ses = threadPool.getScheduledExecutor();

        discoveryTask = new SingletonTask(ses, new Runnable() {
            @Override
            public void run() {
                populateEcmpRoutingRules();
            }
        });

        discoveryTask.reschedule(15, TimeUnit.SECONDS);
    }

    @Override
    public void receive(Switch sw, Port inPort, Ethernet payload) {
    	if (payload.getEtherType() == Ethernet.TYPE_ARP)
    		arpHandler.processPacketIn(sw, inPort, payload);
        if (payload.getEtherType() == Ethernet.TYPE_IPV4) {
        	if (((IPv4)payload.getPayload()).getProtocol() == IPv4.PROTOCOL_ICMP)
        		icmpHandler.processPacketIn(sw, inPort, payload);
        	else
        		ipHandler.processPacketIn(sw, inPort, payload);
        }
    }
    /**
     * Update ARP Cache using ARP packets
     * It is used to set destination MAC address to forward packets to known hosts.
     * But, it will be replace with Host information of Topology service later.
     *
     * @param arp APR packets to use for updating ARP entries
     */
    public void updateArpCache(ARP arp) {

        ArpEntry arpEntry = new ArpEntry(arp.getSenderHardwareAddress(), arp.getSenderProtocolAddress());
        // TODO: Need to check the duplication
        arpEntries.add(arpEntry);
    }

    /**
     * Get MAC address to known hosts
     *
     * @param destinationAddress IP address to get MAC address
     * @return MAC Address to given IP address
     */
    public byte[] getMacAddressFromIpAddress(int destinationAddress) {

        // Can't we get the host IP address from the TopologyService ??

        Iterator<ArpEntry> iterator = arpEntries.iterator();

        IPv4Address ipAddress = IPv4Address.of(destinationAddress);
        byte[] ipAddressInByte = ipAddress.getBytes();

        while (iterator.hasNext() ) {
            ArpEntry arpEntry = iterator.next();
            byte[] address = arpEntry.targetIpAddress;

            IPv4Address a = IPv4Address.of(address);
            IPv4Address b = IPv4Address.of(ipAddressInByte);

            if ( a.equals(b)) {
                log.debug("Found an arp entry");
                return arpEntry.targetMacAddress;
            }
        }

        return null;
    }

    /**
     * Send an ARP request via ArpHandler
     * @param destinationAddress
     * @param sw
     * @param inPort
     *
     */
    public void sendArpRequest(Switch sw, int destinationAddress, Port inPort) {
        arpHandler.sendArpRequest(sw, destinationAddress, inPort);
    }

    /**
     * Temporary class to to keep ARP entry
     *
     */
    private class ArpEntry {

        byte[] targetMacAddress;
        byte[] targetIpAddress;

        private ArpEntry(byte[] macAddress, byte[] ipAddress) {
            this.targetMacAddress = macAddress;
            this.targetIpAddress = ipAddress;
        }
    }

    /**
     * Topology events that have been generated.
     *
     * @param topologyEvents the generated Topology Events
     * @see TopologyEvents
     */
    public void topologyEvents(TopologyEvents topologyEvents)
    {
    	/**
    	 * Any Link update events, compute the ECMP path graph for all switch nodes

    	if ((topologyEvents.getAddedLinkDataEntries() != null) ||
    		(topologyEvents.getRemovedLinkDataEntries() != null))
    	{
    		Iterable<Switch> switches= mutableTopology.getSwitches();
            for (Switch sw : switches) {
            	ECMPShortestPathGraph ecmpSPG = new ECMPShortestPathGraph(sw);
                log.debug("ECMPShortestPathGraph is computed for switch {}",
                		HexString.toHexString(sw.getDpid().value()));


                HashMap<Integer, HashMap<Switch,ArrayList<Path>>> pathGraph =
                                    ecmpSPG.getCompleteLearnedSwitchesAndPaths();
                for (Integer itrIdx: pathGraph.keySet()){

                    HashMap<Switch, ArrayList<Path>> swPathsMap =
                                                pathGraph.get(itrIdx);
                    for (Switch targetSw: swPathsMap.keySet()){
                        log.debug("ECMPShortestPathGraph:Paths in Pass{} from "
                                + "             switch {} to switch {}:****",
                                itrIdx,
                                HexString.toHexString(sw.getDpid().value()),
                                HexString.toHexString(targetSw.getDpid().value()));
                        int i=0;
                        for (Path path:swPathsMap.get(targetSw)){
                            log.debug("****ECMPShortestPathGraph:Path{} is {}",i++,path);
                        }
                    }
                }

                HashMap<Integer, HashMap<Switch,ArrayList<ArrayList<Dpid>>>> switchVia =
                        ecmpSPG.getAllLearnedSwitchesAndVia();
                for (Integer itrIdx: switchVia.keySet()){
                    log.debug("ECMPShortestPathGraph:Switches learned in "
                            + "Iteration{} from switch {}:",
                            itrIdx,
                            HexString.toHexString(sw.getDpid().value()));

                    HashMap<Switch, ArrayList<ArrayList<Dpid>>> swViaMap =
                                    switchVia.get(itrIdx);
                    for (Switch targetSw: swViaMap.keySet()){
                        log.debug("ECMPShortestPathGraph:****switch {} via:",
                                HexString.toHexString(targetSw.getDpid().value()));
                        int i=0;
                        for (ArrayList<Dpid> via:swViaMap.get(targetSw)){
                            log.debug("ECMPShortestPathGraph:******{}) {}",++i,via);
                        }
                    }
                }

            }
    	}
    	*/

        if ((topologyEvents.getAddedLinkDataEntries() != null) ||
                (topologyEvents.getRemovedLinkDataEntries() != null))
        {

            if (networkConverged) {
                populateEcmpRoutingRules();
            }
        }

    }

    /**
     * Populate routing rules walking through the ECMP shortest paths
     *
     */
    private void populateEcmpRoutingRules() {

        Iterable<Switch> switches= mutableTopology.getSwitches();
        for (Switch sw : switches) {
            ECMPShortestPathGraph ecmpSPG = new ECMPShortestPathGraph(sw);
            log.debug("ECMPShortestPathGraph is computed for switch {}",
                    HexString.toHexString(sw.getDpid().value()));

            HashMap<Integer, HashMap<Switch,ArrayList<ArrayList<Dpid>>>> switchVia =
                    ecmpSPG.getAllLearnedSwitchesAndVia();
            for (Integer itrIdx: switchVia.keySet()){
                log.debug("ECMPShortestPathGraph:Switches learned in "
                        + "Iteration{} from switch {}:",
                        itrIdx,
                        HexString.toHexString(sw.getDpid().value()));
                HashMap<Switch, ArrayList<ArrayList<Dpid>>> swViaMap =
                                switchVia.get(itrIdx);
                for (Switch targetSw: swViaMap.keySet()){
                    log.debug("ECMPShortestPathGraph:****switch {} via:",
                            HexString.toHexString(targetSw.getDpid().value()));
                    String destSw = sw.getDpid().toString();
                    List<String> fwdToSw = new ArrayList<String>();

                    int i=0;
                    for (ArrayList<Dpid> via:swViaMap.get(targetSw)){
                        log.debug("ECMPShortestPathGraph:******{}) {}",++i,via);
                        if (via.isEmpty()) {
                            fwdToSw.add(destSw);
                        }
                        else {
                            fwdToSw.add(via.get(0).toString());
                        }
                    }
                    setRoutingRule(targetSw, destSw, fwdToSw);
                }
            }
        }

        networkConverged = true;
    }

    /**
     *
     * Set routing rules in targetSw
     * {forward packets to fwdToSw switches in order to send packets to destSw}
     * - If the target switch is an edge router and final destnation switch is also
     *   an edge router, then set IP forwarding rules to subnets
     * - If only the target switch is an edge router, then set IP forwarding rule to
     *   the transit router loopback IP address
     * - If the target is a transit router, then just set the MPLS forwarding rule
     *
     * @param targetSw Switch to set the rules
     * @param destSw  Final destination switches
     * @param fwdToSw next hop switches
     */
    private void setRoutingRule(Switch targetSw, String destSw, List<String> fwdToSw) {


        if (fwdToSw.isEmpty()) {
            fwdToSw.add(destSw);
        }

        // if both target SW and dest SW are an edge router, then set IP table
        if (IsEdgeRouter(targetSw.getDpid().toString()) &&
                IsEdgeRouter(destSw)) {
            // We assume that there is at least one transit router b/w edge routers
            Switch destSwitch = mutableTopology.getSwitch(new Dpid(destSw));
            String subnets = destSwitch.getStringAttribute("subnets");
            try {
                JSONArray arry = new JSONArray(subnets);
                for (int i = 0; i < arry.length(); i++) {
                    String subnetIp = (String) arry.getJSONObject(i).get("subnetIp");
                    setIpTableRouter(targetSw, subnetIp, getMplsLabel(destSw)
                            ,fwdToSw);

                }
            } catch (JSONException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            String routerIp = destSwitch.getStringAttribute("routerIp");
            setIpTableRouter(targetSw, routerIp, getMplsLabel(destSw), fwdToSw);
        }
        // Only if the target switch is the edge router, then set the IP rules
        else if (IsEdgeRouter(targetSw.getDpid().toString())) {
            // We assume that there is at least one transit router b/w edge routers
            Switch destSwitch = mutableTopology.getSwitch(new Dpid(destSw));
            String routerIp = destSwitch.getStringAttribute("routerIp");
            setIpTableRouter(targetSw, routerIp, getMplsLabel(destSw), fwdToSw);
        }
        // if it is a transit router, then set rules in the MPLS table
        else {
            setMplsTable(targetSw, getMplsLabel(destSw), fwdToSw);
        }

    }

    /**
     * Check if the switch is the edge router or not
     * If any subnet information is defined in the config file, the we assume
     * it is an edge router
     *
     * @param dpid  Dpid of the switch to check
     * @return true if it is an edge router, otherwise false
     */
    private boolean IsEdgeRouter(String dpid) {

        for (Switch sw: mutableTopology.getSwitches()) {
            String dpidStr = sw.getDpid().toString();
            if (dpid.equals(dpidStr)) {
                String subnetInfo = sw.getStringAttribute("subnets");
                if (subnetInfo == null || subnetInfo.equals("[]")) {
                    return false;
                }
                else
                    return true;
            }
        }

        return false;
    }

    /**
     * Set IP forwarding rule
     *  - If the destination is the next hop, then do not push MPLS,
     *    just decrease the NW TTL
     *  - Otherwise, push MPLS label and set the MPLS ID
     *
     * @param sw  target switch to set rules
     * @param subnetIp Match IP address
     * @param mplsLabel MPLS label of final destination router
     * @param fwdToSws next hop routers
     */
    private void setIpTableRouter(Switch sw, String subnetIp, String mplsLabel,
            List<String> fwdToSws) {

        Ipv4Match ipMatch = new Ipv4Match(subnetIp);
        List<Action> actions = new ArrayList<>();

        // If destination SW is the same as the fwd SW, then do not push MPLS label

        if (fwdToSws.size() > 1) {
            PushMplsAction pushMplsAction = new PushMplsAction();
            SetMplsIdAction setIdAction = new SetMplsIdAction(Integer.parseInt(mplsLabel));
            CopyTtlOutAction copyTtlOutAction = new CopyTtlOutAction();

            actions.add(pushMplsAction);
            actions.add(setIdAction);
            actions.add(copyTtlOutAction);
        }
        else {
            String fwdToSw = fwdToSws.get(0);
            if (getMplsLabel(fwdToSw).equals(mplsLabel)) {
                DecNwTtlAction decTtlAction = new DecNwTtlAction(1);
                actions.add(decTtlAction);
            }
            else {
                PushMplsAction pushMplsAction = new PushMplsAction();
                SetMplsIdAction setIdAction = new SetMplsIdAction(Integer.parseInt(mplsLabel));
                CopyTtlOutAction copyTtlOutAction = new CopyTtlOutAction();

                actions.add(pushMplsAction);
                actions.add(setIdAction);
                actions.add(copyTtlOutAction);
            }
        }

        GroupAction groupAction = new GroupAction();

        for (String fwdSw : fwdToSws) {
            groupAction.addSwitch(new Dpid(fwdSw));
        }
        actions.add(groupAction);

        //MatchAction matchAction = new MatchAction(maIdGenerator.getNewId(),
        MatchAction matchAction = new MatchAction(new MatchActionId(0),
                new SwitchPort((long)0,(short)0), ipMatch, actions);

        MatchActionOperationEntry maEntry =
            new MatchActionOperationEntry(
                    net.onrc.onos.core.matchaction.MatchActionOperations.Operator.ADD,
                    matchAction);

      IOF13Switch sw13 = (IOF13Switch)floodlightProvider.getMasterSwitch(
                getSwId(sw.getDpid().toString()));

        try {
            printMatchActionOperationEntry(sw, maEntry);
            sw13.pushFlow(maEntry);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }


    /**
     * Convert a string DPID to its Switch Id (integer)
     *
     * @param dpid
     * @return
     */
    private long getSwId(String dpid) {

        long swId = 0;

        String swIdStr = dpid.substring(dpid.lastIndexOf(":")+1);
        if (swIdStr != null)
            swId = Integer.parseInt(swIdStr);

        return swId;
    }

    /**
     * Set MPLS forwarding rules to MPLS table
     *   - If the destination is the same as the next hop to forward packets
     *     then, pop the MPLS label according to PHP rule
     *   - Otherwise, just forward packets to next hops using Group action
     *
     * @param sw  Switch to set the rules
     * @param mplsLabel destination MPLS label
     * @param fwdSws  next hop switches
     */
    private void setMplsTable(Switch sw, String mplsLabel, List<String> fwdSws) {
        if (mplsLabel == null) {
            log.error("mpls label not configured for sw: {}. Not populating"
                    + " MPLS table entries.", sw.getDpid());
            return;
        }
        MplsMatch mplsMatch = new MplsMatch(Integer.parseInt(mplsLabel));

        List<Action> actions = new ArrayList<Action>();

        if (fwdSws.size() > 1) {
            DecMplsTtlAction decMplsTtlAction = new DecMplsTtlAction(1);
            actions.add(decMplsTtlAction);
        }
        // If the destination is the same as the next hop, then pop MPLS
        else {
            String fwdMplsId = getMplsLabel(fwdSws.get(0));
            if (fwdMplsId.equals(mplsLabel)) {
                String fwdSw = fwdSws.get(0);
                if (mplsLabel.equals(getMplsLabel(fwdSw))) {
                    PopMplsAction popAction = new PopMplsAction(EthType.IPv4);
                    CopyTtlInAction copyTtlInAction = new CopyTtlInAction();

                    actions.add(popAction);
                    actions.add(copyTtlInAction);
                }
            }
        }

        GroupAction groupAction = new GroupAction();
        for (String fwdSw: fwdSws)
            groupAction.addSwitch(new Dpid(fwdSw));
        actions.add(groupAction);

        MatchAction matchAction = new MatchAction(new MatchActionId(0),
                new SwitchPort((long)0,(short)0), mplsMatch, actions);

        MatchActionOperationEntry maEntry =
            new MatchActionOperationEntry(
                    net.onrc.onos.core.matchaction.MatchActionOperations.Operator.ADD,
                    matchAction);

        IOF13Switch sw13 = (IOF13Switch)floodlightProvider.getMasterSwitch(
                getSwId(sw.getDpid().toString()));

        try {
            printMatchActionOperationEntry(sw, maEntry);
            sw13.pushFlow(maEntry);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }


    /**
     * Debugging function to print out the Match Action Entry
     *
     * @param maEntry
     */
    private void printMatchActionOperationEntry(Switch sw,
            MatchActionOperationEntry maEntry) {

        StringBuilder logStr = new StringBuilder("In switch " + sw.getDpid() + ", ");

        MatchAction ma = maEntry.getTarget();
        Match m = ma.getMatch();
        List<Action> actions = ma.getActions();

        if (m instanceof Ipv4Match) {
            logStr.append("If the IP matches with ");
            IPv4Net ip = ((Ipv4Match) m).getDestination();
            logStr.append(ip.toString());
            logStr.append(" then ");
        }
        else if (m instanceof MplsMatch) {
            logStr.append("If the MPLS label matches with ");
            int mplsLabel = ((MplsMatch) m).getMplsLabel();
            logStr.append(mplsLabel);
            logStr.append(" then ");
        }

        logStr.append(" do { ");
        for (Action action: actions) {
            if (action instanceof CopyTtlInAction) {
                logStr.append("copy ttl In, ");
            }
            else if (action instanceof CopyTtlOutAction) {
                logStr.append("copy ttl Out, ");
            }
            else if (action instanceof DecMplsTtlAction) {
                logStr.append("Dec MPLS TTL , ");
            }
            else if (action instanceof GroupAction) {
                logStr.append("Forward packet to < ");
                NeighborSet dpids = ((GroupAction)action).getDpids();
                logStr.append(dpids.toString() + ",");

            }
            else if (action instanceof PopMplsAction) {
                logStr.append("Pop MPLS label, ");
            }
            else if (action instanceof PushMplsAction) {
                logStr.append("Push MPLS label, ");
            }
            else if (action instanceof SetMplsIdAction) {
                int id = ((SetMplsIdAction)action).getMplsId();
                logStr.append("Set MPLS ID as " + id + ", ");

            }
        }

        log.debug(logStr.toString());

    }

    /**
     * Get MPLS label reading the config file
     *
     * @param dipid  DPID of the switch
     * @return MPLS label for the switch
     */

    private String getMplsLabel(String dpid) {

        String mplsLabel = null;
        for (Switch sw: mutableTopology.getSwitches()) {
            String dpidStr = sw.getDpid().toString();
            if (dpid.equals(dpidStr)) {
                mplsLabel = sw.getStringAttribute("nodeSid");
                break;
            }
        }

        return mplsLabel;
    }



    /**
     * The function checks if given IP matches to the given subnet mask
     *
     * @param addr - subnet address to match
     * @param addr1 - IP address to check
     * @return true if the IP address matches to the subnet, otherwise false
     */
    public boolean netMatch(String addr, String addr1){ //addr is subnet address and addr1 is ip address. Function will return true, if addr1 is within addr(subnet)

        String[] parts = addr.split("/");
        String ip = parts[0];
        int prefix;

        if (parts.length < 2) {
            prefix = 0;
        } else {
            prefix = Integer.parseInt(parts[1]);
        }

        Inet4Address a =null;
        Inet4Address a1 =null;
        try {
            a = (Inet4Address) InetAddress.getByName(ip);
            a1 = (Inet4Address) InetAddress.getByName(addr1);
        } catch (UnknownHostException e){}

        byte[] b = a.getAddress();
        int ipInt = ((b[0] & 0xFF) << 24) |
                         ((b[1] & 0xFF) << 16) |
                         ((b[2] & 0xFF) << 8)  |
                         ((b[3] & 0xFF) << 0);

        byte[] b1 = a1.getAddress();
        int ipInt1 = ((b1[0] & 0xFF) << 24) |
                         ((b1[1] & 0xFF) << 16) |
                         ((b1[2] & 0xFF) << 8)  |
                         ((b1[3] & 0xFF) << 0);

        int mask = ~((1 << (32 - prefix)) - 1);

        if ((ipInt & mask) == (ipInt1 & mask)) {
            return true;
        }
        else {
            return false;
        }
    }

    /**
     * Add a routing rule for the host
     *
     * @param sw - Switch to add the rule
     * @param hostIpAddress Destination host IP address
     * @param hostMacAddress Destination host MAC address
     */
    public void addRouteToHost(Switch sw, int hostIpAddress, byte[] hostMacAddress) {
        ipHandler.addRouteToHost(sw, hostIpAddress, hostMacAddress);

    }

}
