package net.onrc.onos.apps.bgproute;

import java.io.File;
import java.io.IOException;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import net.floodlightcontroller.core.IFloodlightProviderService;
import net.floodlightcontroller.core.IOFSwitch;
import net.floodlightcontroller.core.IOFSwitchListener;
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.restserver.IRestApiService;
import net.floodlightcontroller.util.MACAddress;
import net.onrc.onos.apps.bgproute.RibUpdate.Operation;
import net.onrc.onos.apps.proxyarp.IArpRequester;
import net.onrc.onos.apps.proxyarp.IProxyArpService;
import net.onrc.onos.core.linkdiscovery.ILinkDiscovery.LDUpdate;
import net.onrc.onos.core.linkdiscovery.ILinkDiscoveryService;
import net.onrc.onos.core.main.config.IConfigInfoService;
import net.onrc.onos.core.packet.Ethernet;
import net.onrc.onos.core.packet.IPv4;
import net.onrc.onos.core.util.CallerId;
import net.onrc.onos.core.util.DataPath;
import net.onrc.onos.core.util.Dpid;
import net.onrc.onos.core.util.FlowEntryAction;
import net.onrc.onos.core.util.FlowEntryActions;
import net.onrc.onos.core.util.FlowEntryMatch;
import net.onrc.onos.core.util.FlowId;
import net.onrc.onos.core.util.FlowPath;
import net.onrc.onos.core.util.FlowPathFlags;
import net.onrc.onos.core.util.FlowPathType;
import net.onrc.onos.core.util.FlowPathUserState;
import net.onrc.onos.core.util.IPv4Net;
import net.onrc.onos.core.util.Port;
import net.onrc.onos.core.util.SwitchPort;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import net.sf.json.JSONSerializer;

import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.openflow.protocol.OFFlowMod;
import org.openflow.protocol.OFMatch;
import org.openflow.protocol.OFPacketOut;
import org.openflow.protocol.OFPort;
import org.openflow.protocol.action.OFAction;
import org.openflow.protocol.action.OFActionOutput;
import org.openflow.util.HexString;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import com.google.common.collect.Multimaps;
import com.google.common.collect.SetMultimap;
import com.google.common.net.InetAddresses;
import com.google.common.util.concurrent.ThreadFactoryBuilder;

public class BgpRoute implements IFloodlightModule, IBgpRouteService,
        IArpRequester,
        IOFSwitchListener, IConfigInfoService {

    private final static Logger log = LoggerFactory.getLogger(BgpRoute.class);

    private IFloodlightProviderService floodlightProvider;
    private ILinkDiscoveryService linkDiscoveryService;
    private IRestApiService restApi;
    private IProxyArpService proxyArp;

    private IPatriciaTrie<RibEntry> ptree;
    private IPatriciaTrie<Interface> interfacePtrie;
    private BlockingQueue<RibUpdate> ribUpdates;

    private String bgpdRestIp;
    private String routerId;
    private String configFilename = "config.json";

    //We need to identify our flows somehow. But like it says in LearningSwitch.java,
    //the controller/OS should hand out cookie IDs to prevent conflicts.
    private final long APP_COOKIE = 0xa0000000000000L;
    //Cookie for flows that do L2 forwarding within SDN domain to egress routers
    private final long L2_FWD_COOKIE = APP_COOKIE + 1;
    //Cookie for flows in ingress switches that rewrite the MAC address
    private final long MAC_RW_COOKIE = APP_COOKIE + 2;
    //Cookie for flows that setup BGP paths
    private final long BGP_COOKIE = APP_COOKIE + 3;
    //Forwarding uses priority 0, and the mac rewrite entries in ingress switches
    //need to be higher priority than this otherwise the rewrite may not get done
    private final short SDNIP_PRIORITY = 10;
    private final short ARP_PRIORITY = 20;

    private final short BGP_PORT = 179;

    private final int TOPO_DETECTION_WAIT = 2; //seconds

    //Configuration stuff
    private List<String> switches;
    private Map<String, Interface> interfaces;
    private Map<InetAddress, BgpPeer> bgpPeers;
    private SwitchPort bgpdAttachmentPoint;
    private MACAddress bgpdMacAddress;
    private short vlan;

    //True when all switches have connected
    private volatile boolean switchesConnected = false;
    //True when we have a full mesh of shortest paths between gateways
    private volatile boolean topologyReady = false;

    private ArrayList<LDUpdate> linkUpdates;
    private SingletonTask topologyChangeDetectorTask;

    private SetMultimap<InetAddress, RibUpdate> prefixesWaitingOnArp;

    private Map<InetAddress, Path> pathsWaitingOnArp;

    private ExecutorService bgpUpdatesExecutor;

    private Map<InetAddress, Path> pushedPaths;
    private Map<Prefix, Path> prefixToPath;
    //  private Multimap<Prefix, PushedFlowMod> pushedFlows;
    private Multimap<Prefix, FlowId> pushedFlowIds;

    private FlowCache flowCache;

    // TODO: Fix for the new Topology Network Graph
    // private volatile Topology topology = null;

    private class TopologyChangeDetector implements Runnable {
        @Override
        public void run() {
            log.debug("Running topology change detection task");
            synchronized (linkUpdates) {
                //This is the model the REST API uses to retrieve network graph info
                // TODO: Fix the code below after topoLinkService was removed
                /*
                ITopoLinkService topoLinkService = new TopoLinkServiceImpl();

                List<Link> activeLinks = topoLinkService.getActiveLinks();

                Iterator<LDUpdate> it = linkUpdates.iterator();
                while (it.hasNext()){
                    LDUpdate ldu = it.next();
                    Link l = new Link(ldu.getSrc(), ldu.getSrcPort(),
                            ldu.getDst(), ldu.getDstPort());

                    if (activeLinks.contains(l)){
                        it.remove();
                    }
                }
                */
            }

            if (!topologyReady) {
                if (linkUpdates.isEmpty()) {
                    //All updates have been seen in network map.
                    //We can check if topology is ready
                    log.debug("No known changes outstanding. Checking topology now");
                    checkStatus();
                } else {
                    //We know of some link updates that haven't propagated to the database yet
                    log.debug("Some changes not found in network map - {} links missing", linkUpdates.size());
                    topologyChangeDetectorTask.reschedule(TOPO_DETECTION_WAIT, TimeUnit.SECONDS);
                }
            }
        }
    }

    private void readConfiguration(String configFilename) {
        File gatewaysFile = new File(configFilename);
        ObjectMapper mapper = new ObjectMapper();

        try {
            Configuration config = mapper.readValue(gatewaysFile, Configuration.class);

            switches = config.getSwitches();
            interfaces = new HashMap<String, Interface>();
            for (Interface intf : config.getInterfaces()) {
                interfaces.put(intf.getName(), intf);
            }
            bgpPeers = new HashMap<InetAddress, BgpPeer>();
            for (BgpPeer peer : config.getPeers()) {
                bgpPeers.put(peer.getIpAddress(), peer);
            }

            bgpdAttachmentPoint = new SwitchPort(
                    new Dpid(config.getBgpdAttachmentDpid()),
                    new Port(config.getBgpdAttachmentPort()));

            bgpdMacAddress = config.getBgpdMacAddress();
            vlan = config.getVlan();
        } catch (JsonParseException e) {
            log.error("Error in JSON file", e);
            System.exit(1);
        } catch (JsonMappingException e) {
            log.error("Error in JSON file", e);
            System.exit(1);
        } catch (IOException e) {
            log.error("Error reading JSON file", e);
            System.exit(1);
        }

        //Populate the interface Patricia Trie
        for (Interface intf : interfaces.values()) {
            Prefix prefix = new Prefix(intf.getIpAddress().getAddress(), intf.getPrefixLength());
            interfacePtrie.put(prefix, intf);
        }
    }

    @Override
    public Collection<Class<? extends IFloodlightService>> getModuleServices() {
        Collection<Class<? extends IFloodlightService>> l
                = new ArrayList<Class<? extends IFloodlightService>>();
        l.add(IBgpRouteService.class);
        l.add(IConfigInfoService.class);
        return l;
    }

    @Override
    public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
        Map<Class<? extends IFloodlightService>, IFloodlightService> m
                = new HashMap<Class<? extends IFloodlightService>, IFloodlightService>();
        m.put(IBgpRouteService.class, this);
        m.put(IConfigInfoService.class, this);
        return m;
    }

    @Override
    public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
        Collection<Class<? extends IFloodlightService>> l
                = new ArrayList<Class<? extends IFloodlightService>>();
        l.add(IFloodlightProviderService.class);
        l.add(IRestApiService.class);
        return l;
    }

    @Override
    public void init(FloodlightModuleContext context)
            throws FloodlightModuleException {

        ptree = new PatriciaTrie<RibEntry>(32);
        interfacePtrie = new PatriciaTrie<Interface>(32);

        ribUpdates = new LinkedBlockingQueue<RibUpdate>();

        // Register floodlight provider and REST handler.
        floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
        linkDiscoveryService = context.getServiceImpl(ILinkDiscoveryService.class);
        restApi = context.getServiceImpl(IRestApiService.class);
        proxyArp = context.getServiceImpl(IProxyArpService.class);

        linkUpdates = new ArrayList<LDUpdate>();
        ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
        topologyChangeDetectorTask = new SingletonTask(executor, new TopologyChangeDetector());

        pathsWaitingOnArp = new HashMap<InetAddress, Path>();
        prefixesWaitingOnArp = Multimaps.synchronizedSetMultimap(
                HashMultimap.<InetAddress, RibUpdate>create());

        pushedPaths = new HashMap<InetAddress, Path>();
        prefixToPath = new HashMap<Prefix, Path>();
//              pushedFlows = HashMultimap.<Prefix, PushedFlowMod>create();
        pushedFlowIds = HashMultimap.<Prefix, FlowId>create();

        flowCache = new FlowCache(floodlightProvider);

        bgpUpdatesExecutor = Executors.newSingleThreadExecutor(
                new ThreadFactoryBuilder().setNameFormat("bgp-updates-%d").build());

        //Read in config values
        bgpdRestIp = context.getConfigParams(this).get("BgpdRestIp");
        if (bgpdRestIp == null) {
            log.error("BgpdRestIp property not found in config file");
            System.exit(1);
        } else {
            log.info("BgpdRestIp set to {}", bgpdRestIp);
        }

        routerId = context.getConfigParams(this).get("RouterId");
        if (routerId == null) {
            log.error("RouterId property not found in config file");
            System.exit(1);
        } else {
            log.info("RouterId set to {}", routerId);
        }

        String configFilenameParameter = context.getConfigParams(this).get("configfile");
        if (configFilenameParameter != null) {
            configFilename = configFilenameParameter;
        }
        log.debug("Config file set to {}", configFilename);

        readConfiguration(configFilename);
    }

    @Override
    public void startUp(FloodlightModuleContext context) {
        restApi.addRestletRoutable(new BgpRouteWebRoutable());
        floodlightProvider.addOFSwitchListener(this);

        //Retrieve the RIB from BGPd during startup
        retrieveRib();
    }

    @Override
    public IPatriciaTrie<RibEntry> getPtree() {
        return ptree;
    }

    @Override
    public void clearPtree() {
        ptree = new PatriciaTrie<RibEntry>(32);
    }

    @Override
    public String getBGPdRestIp() {
        return bgpdRestIp;
    }

    @Override
    public String getRouterId() {
        return routerId;
    }

    private void retrieveRib() {
        String url = "http://" + bgpdRestIp + "/wm/bgp/" + routerId;
        String response = RestClient.get(url);

        if (response.equals("")) {
            return;
        }

        response = response.replaceAll("\"", "'");
        JSONObject jsonObj = (JSONObject) JSONSerializer.toJSON(response);
        JSONArray rib_json_array = jsonObj.getJSONArray("rib");
        String router_id = jsonObj.getString("router-id");

        int size = rib_json_array.size();

        log.info("Retrived RIB of {} entries from BGPd", size);

        for (int j = 0; j < size; j++) {
            JSONObject second_json_object = rib_json_array.getJSONObject(j);
            String prefix = second_json_object.getString("prefix");
            String nexthop = second_json_object.getString("nexthop");

            //insert each rib entry into the local rib;
            String[] substring = prefix.split("/");
            String prefix1 = substring[0];
            String mask1 = substring[1];

            Prefix p;
            try {
                p = new Prefix(prefix1, Integer.valueOf(mask1));
            } catch (NumberFormatException e) {
                log.warn("Wrong mask format in RIB JSON: {}", mask1);
                continue;
            } catch (IllegalArgumentException e1) {
                log.warn("Wrong prefix format in RIB JSON: {}", prefix1);
                continue;
            }

            RibEntry rib = new RibEntry(router_id, nexthop);

            try {
                ribUpdates.put(new RibUpdate(Operation.UPDATE, p, rib));
            } catch (InterruptedException e) {
                log.debug("Interrupted while pushing onto update queue");
            }
        }
    }

    @Override
    public void newRibUpdate(RibUpdate update) {
        try {
            ribUpdates.put(update);
        } catch (InterruptedException e) {
            log.debug("Interrupted while putting on ribUpdates queue", e);
            Thread.currentThread().interrupt();
        }
    }

    public synchronized void processRibAdd(RibUpdate update) {
        Prefix prefix = update.getPrefix();

        log.debug("Processing prefix add {}", prefix);

        RibEntry rib = ptree.put(prefix, update.getRibEntry());

        if (rib != null && !rib.equals(update.getRibEntry())) {
            //There was an existing nexthop for this prefix. This update supersedes that,
            //so we need to remove the old flows for this prefix from the switches
            _processDeletePrefix(prefix, rib);
        }

        if (update.getRibEntry().getNextHop().equals(
                InetAddresses.forString("0.0.0.0"))) {
            //Route originated by SDN domain
            //We don't handle these at the moment
            log.debug("Own route {} to {}", prefix,
                    update.getRibEntry().getNextHop().getHostAddress());
            return;
        }

        _processRibAdd(update);
    }

    private void _processRibAdd(RibUpdate update) {
        Prefix prefix = update.getPrefix();
        RibEntry rib = update.getRibEntry();

        InetAddress dstIpAddress = rib.getNextHop();
        MACAddress nextHopMacAddress = null;

        // See if we know the MAC address of the next hop
        // TODO if we do not treat the next hop as a device in the future, we need to update this
        // TODO: Fix the code below after deviceStorage was removed
        /*
        IDeviceObject nextHopDevice =
                deviceStorage.getDeviceByIP(InetAddresses.coerceToInteger(dstIpAddress));

        if (nextHopDevice == null){
            log.debug("NextHopDevice for IP: {} is null", dstIpAddress);
            prefixesWaitingOnArp.put(dstIpAddress,
                    new RibUpdate(Operation.UPDATE, prefix, rib));
            proxyArp.sendArpRequest(dstIpAddress, this, true);
            return;

        }
        nextHopMacAddress = MACAddress.valueOf(nextHopDevice.getMACAddress());
        */

        // Find the attachment point (egress interface) of the next hop
        Interface egressInterface = null;
        if (bgpPeers.containsKey(dstIpAddress)) {
            //Route to a peer
            log.debug("Route to peer {}", dstIpAddress);
            BgpPeer peer = bgpPeers.get(dstIpAddress);
            egressInterface = interfaces.get(peer.getInterfaceName());
        } else {
            //Route to non-peer
            log.debug("Route to non-peer {}", dstIpAddress);
            egressInterface = interfacePtrie.match(
                    new Prefix(dstIpAddress.getAddress(), 32));
            if (egressInterface == null) {
                log.warn("No outgoing interface found for {}", dstIpAddress.getHostAddress());
                return;
            }
        }

        if (nextHopMacAddress == null) {
            prefixesWaitingOnArp.put(dstIpAddress,
                    new RibUpdate(Operation.UPDATE, prefix, rib));
            proxyArp.sendArpRequest(dstIpAddress, this, true);
            return;
        } else {
            if (!bgpPeers.containsKey(dstIpAddress)) {
                //If the prefix is for a non-peer we need to ensure there's a path,
                //and push one if there isn't.
                Path path = pushedPaths.get(dstIpAddress);
                if (path == null) {
                    path = new Path(egressInterface, dstIpAddress);
                    calculateAndPushPath(path, nextHopMacAddress);
                    pushedPaths.put(dstIpAddress, path);
                }

                path.incrementUsers();
                prefixToPath.put(prefix, path);
            }

            //For all prefixes we need to add the first-hop mac-rewriting flows
            addPrefixFlows(prefix, egressInterface, nextHopMacAddress);
        }
    }

    /**
     * Add a flow to match dst-IP prefix and rewrite MAC for one IP prefix
     * to all other border switches
     */
    private void addPrefixFlows(Prefix prefix, Interface egressInterface,
                                MACAddress nextHopMacAddress) {
        log.debug("Adding flows for prefix {}, next hop mac {}",
                prefix, nextHopMacAddress);

        FlowPath flowPath = new FlowPath();
        flowPath.setInstallerId(new CallerId("SDNIP"));

        // Set flowPath FlowPathType and FlowPathUserState
        flowPath.setFlowPathType(FlowPathType.FP_TYPE_SHORTEST_PATH);
        flowPath.setFlowPathUserState(FlowPathUserState.FP_USER_ADD);

        // Insert dst-ip prefix based forwarding and MAC rewrite flow entry
        // only to the first-host switches
        FlowPathFlags flowPathFlags = new FlowPathFlags();
        flowPathFlags.setFlags(FlowPathFlags.KEEP_ONLY_FIRST_HOP_ENTRY);
        flowPath.setFlowPathFlags(flowPathFlags);

        // Create the DataPath object: dstSwitchPort
        SwitchPort dstPort = new SwitchPort();
        dstPort.setDpid(new Dpid(egressInterface.getDpid()));
        dstPort.setPort(new Port(egressInterface.getPort()));

        // We only need one flow mod per switch, so pick one interface on each switch
        Map<Long, Interface> srcInterfaces = new HashMap<Long, Interface>();
        for (Interface intf : interfaces.values()) {
            if (!srcInterfaces.containsKey(intf.getDpid())
                    && !intf.equals(egressInterface)) {
                srcInterfaces.put(intf.getDpid(), intf);
            }
        }
        for (Interface srcInterface : srcInterfaces.values()) {

            if (egressInterface.equals(srcInterface)) {
                continue;
            }

            // Create flowPath FlowId
            flowPath.setFlowId(new FlowId());

            // Create DataPath object: srcSwitchPort
            SwitchPort srcPort = new SwitchPort();
            srcPort.setDpid(new Dpid(srcInterface.getDpid()));
            srcPort.setPort(new Port(srcInterface.getPort()));

            DataPath dataPath = new DataPath();
            dataPath.setSrcPort(srcPort);
            dataPath.setDstPort(dstPort);
            flowPath.setDataPath(dataPath);

            // Create flow path matching condition(s): IPv4 Prefix
            FlowEntryMatch flowEntryMatch = new FlowEntryMatch();
            flowEntryMatch.enableEthernetFrameType(Ethernet.TYPE_IPv4);
            IPv4Net dstIPv4Net = new IPv4Net(prefix.toString());
            flowEntryMatch.enableDstIPv4Net(dstIPv4Net);
            flowPath.setFlowEntryMatch(flowEntryMatch);

            /*
             * Create the Flow Entry Action(s): dst-MAC rewrite action
             */
            FlowEntryActions flowEntryActions = new FlowEntryActions();
            FlowEntryAction flowEntryAction1 = new FlowEntryAction();
            flowEntryAction1.setActionSetEthernetDstAddr(nextHopMacAddress);
            // flowEntryAction1.actionSetEthernetDstAddr(nextHopMacAddress);
            flowEntryActions.addAction(flowEntryAction1);
            flowPath.setFlowEntryActions(flowEntryActions);

            // Flow Path installation, only to first hop switches
            // TODO: Add the flow by using the new Path Intent framework
            /*
            if (flowManagerService.addFlow(flowPath) == null) {
                log.error("Failed to install flow path to the first hop for " +
                        "prefix: {}, nextHopMacAddress: {}", prefix.getAddress(),
                        nextHopMacAddress);
            }
            else {
                log.debug("Successfully installed flow path to the first hop " +
                        "for prefix: {}, nextHopMacAddress: {}", prefix.getAddress(),
                        nextHopMacAddress);

                pushedFlowIds.put(prefix, flowPath.flowId());
            }
            */
        }
    }

    public synchronized void processRibDelete(RibUpdate update) {
        Prefix prefix = update.getPrefix();

        if (ptree.remove(prefix, update.getRibEntry())) {
            /*
             * Only delete flows if an entry was actually removed from the trie.
             * If no entry was removed, the <prefix, nexthop> wasn't there so
             * it's probably already been removed and we don't need to do anything
             */
            _processDeletePrefix(prefix, update.getRibEntry());
        }
    }

    private void _processDeletePrefix(Prefix prefix, RibEntry ribEntry) {
        deletePrefixFlows(prefix);

        log.debug("Deleting {} to {}", prefix, ribEntry.getNextHop());

        if (!bgpPeers.containsKey(ribEntry.getNextHop())) {
            log.debug("Getting path for route with non-peer nexthop");
            Path path = prefixToPath.remove(prefix);

            if (path != null) {
                //path could be null if we added to the Ptree but didn't push
                //flows yet because we were waiting to resolve ARP

                path.decrementUsers();
                if (path.getUsers() <= 0 && !path.isPermanent()) {
                    deletePath(path);
                    pushedPaths.remove(path.getDstIpAddress());
                }
            }
        }
    }

    // TODO have not tested this module
    private void deletePrefixFlows(Prefix prefix) {
        log.debug("Deleting flows for prefix {}", prefix);

        Collection<FlowId> flowIds = pushedFlowIds.removeAll(prefix);
        for (FlowId flowId : flowIds) {
            // TODO: Delete the flow by using the new Path Intent framework
            /*
            if (log.isTraceEnabled()) {
                //Trace the flow status by flowPath in the switch before deleting it
                log.trace("Pushing a DELETE flow mod to flowPath : {}",
                        flowManagerService.getFlow(flowId).toString());
            }

            if( flowManagerService.deleteFlow(flowId))
            {
                log.debug("Successfully deleted FlowId: {}",flowId);
            }
            else
            {
                log.debug("Failed to delete FlowId: {}",flowId);
            }
            */
        }
    }

    // TODO need to record the path and then delete here
    private void deletePath(Path path) {
        log.debug("Deleting flows for path to {}",
                path.getDstIpAddress().getHostAddress());

        // TODO need update
        /*for (PushedFlowMod pfm : path.getFlowMods()) {
            if (log.isTraceEnabled()) {
                log.trace("Pushing a DELETE flow mod to {}, dst MAC {}",
                        new Object[] {HexString.toHexString(pfm.getDpid()),
                        HexString.toHexString(pfm.getFlowMod().getMatch().getDataLayerDestination())
                });
            }

            sendDeleteFlowMod(pfm.getFlowMod(), pfm.getDpid());
        }*/
    }


    //TODO test next-hop changes
    //TODO check delete/add synchronization

    /**
     * On startup, we need to calculate a full mesh of paths between all gateway
     * switches
     */
    private void setupFullMesh() {
        //For each border router, calculate and install a path from every other
        //border switch to said border router. However, don't install the entry
        //in to the first hop switch, as we need to install an entry to rewrite
        //for each prefix received. This will be done later when prefixes have
        //actually been received.

        for (BgpPeer peer : bgpPeers.values()) {
            Interface peerInterface = interfaces.get(peer.getInterfaceName());

            //We know there's not already a Path here pushed, because this is
            //called before all other routing
            Path path = new Path(peerInterface, peer.getIpAddress());
            path.setPermanent();

            //See if we know the MAC address of the peer. If not we can't
            //do anything until we learn it
            // TODO: Fix the code below after deviceStorage was removed
            MACAddress macAddress = null;
            /*
            IDeviceObject nextHopDevice =
                    deviceStorage.getDeviceByIP(InetAddresses.coerceToInteger(peer.getIpAddress()));

            if(nextHopDevice == null){
                log.debug("There is no DeviceObject for {}", peer.getIpAddress().getHostAddress());
                //Put in the pending paths list first
                pathsWaitingOnArp.put(peer.getIpAddress(), path);
                proxyArp.sendArpRequest(peer.getIpAddress(), this, true);
                continue;
            }

            macAddress = MACAddress.valueOf(nextHopDevice.getMACAddress());
            */

            if (macAddress == null) {
                log.debug("Don't know MAC for {}", peer.getIpAddress().getHostAddress());
                //Put in the pending paths list first
                pathsWaitingOnArp.put(peer.getIpAddress(), path);
                proxyArp.sendArpRequest(peer.getIpAddress(), this, true);
                continue;
            }

            //If we know the MAC, lets go ahead and push the paths to this peer
            calculateAndPushPath(path, macAddress);
        }
    }

    private void calculateAndPushPath(Path path, MACAddress dstMacAddress) {
        Interface dstInterface = path.getDstInterface();

        log.debug("Setting up path to {}, {}", path.getDstIpAddress().getHostAddress(),
                dstMacAddress);

        FlowPath flowPath = new FlowPath();

        flowPath.setInstallerId(new CallerId("SDNIP"));

        // Set flowPath FlowPathType and FlowPathUserState
        flowPath.setFlowPathType(FlowPathType.FP_TYPE_SHORTEST_PATH);
        flowPath.setFlowPathUserState(FlowPathUserState.FP_USER_ADD);

        // Insert the dest-mac based forwarding flow entry to the non-first-hop switches
        FlowPathFlags flowPathFlags = new FlowPathFlags();
        flowPathFlags.setFlags(FlowPathFlags.DISCARD_FIRST_HOP_ENTRY);
        flowPath.setFlowPathFlags(flowPathFlags);

        // Create the DataPath object: dstSwitchPort
        SwitchPort dstPort = new SwitchPort();
        dstPort.setDpid(new Dpid(dstInterface.getDpid()));
        dstPort.setPort(new Port(dstInterface.getPort()));

        for (Interface srcInterface : interfaces.values()) {

            if (dstInterface.equals(srcInterface)) {
                continue;
            }

            // Create flowPath FlowId
            flowPath.setFlowId(new FlowId());

            // Create the DataPath object: srcSwitchPort
            SwitchPort srcPort = new SwitchPort();
            srcPort.setDpid(new Dpid(srcInterface.getDpid()));
            srcPort.setPort(new Port(srcInterface.getPort()));

            DataPath dataPath = new DataPath();
            dataPath.setSrcPort(srcPort);
            dataPath.setDstPort(dstPort);
            flowPath.setDataPath(dataPath);

            // Create the Flow Path Match condition(s)
            FlowEntryMatch flowEntryMatch = new FlowEntryMatch();
            flowEntryMatch.enableEthernetFrameType(Ethernet.TYPE_IPv4);
            flowEntryMatch.enableDstMac(dstMacAddress);
            flowPath.setFlowEntryMatch(flowEntryMatch);

            // NOTE: No need to add ACTION_OUTPUT. It is implied when creating
            // Shortest Path Flow, and is always the last action for the Flow Entries
            log.debug("FlowPath of MAC based forwarding: {}", flowPath.toString());
            // TODO: Add the flow by using the new Path Intent framework
            /*
            if (flowManagerService.addFlow(flowPath) == null) {
                log.error("Failed to set up MAC based forwarding path to {}, {}",
                        path.getDstIpAddress().getHostAddress(),dstMacAddress);
            }
            else {
                log.debug("Successfully set up MAC based forwarding path to {}, {}",
                        path.getDstIpAddress().getHostAddress(),dstMacAddress);
            }
            */
        }
    }

    /**
     * Pre-actively install all BGP traffic paths from BGP host attachment point
     * in SDN network to all the virtual gateways to BGP peers in other networks
     */
    private void setupBgpPaths() {

        for (BgpPeer bgpPeer : bgpPeers.values()) {

            FlowPath flowPath = new FlowPath();
            flowPath.setInstallerId(new CallerId("SDNIP"));

            // Set flowPath FlowPathType and FlowPathUserState
            flowPath.setFlowPathType(FlowPathType.FP_TYPE_SHORTEST_PATH);
            flowPath.setFlowPathUserState(FlowPathUserState.FP_USER_ADD);

            // Install flow paths between BGPd and its peers
            // There is no need to set the FlowPathFlags
            flowPath.setFlowPathFlags(new FlowPathFlags(0));

            Interface peerInterface = interfaces.get(bgpPeer.getInterfaceName());

            // Create the Flow Path Match condition(s)
            FlowEntryMatch flowEntryMatch = new FlowEntryMatch();
            flowEntryMatch.enableEthernetFrameType(Ethernet.TYPE_IPv4);

            // Match both source address and dest address
            IPv4Net dstIPv4Net = new IPv4Net(bgpPeer.getIpAddress().getHostAddress() + "/32");
            flowEntryMatch.enableDstIPv4Net(dstIPv4Net);

            IPv4Net srcIPv4Net = new IPv4Net(peerInterface.getIpAddress().getHostAddress() + "/32");
            flowEntryMatch.enableSrcIPv4Net(srcIPv4Net);

            // Match TCP protocol
            flowEntryMatch.enableIpProto(IPv4.PROTOCOL_TCP);

            // Match destination TCP port
            flowEntryMatch.enableDstTcpUdpPort(BGP_PORT);
            flowPath.setFlowEntryMatch(flowEntryMatch);

            /**
             * Create the DataPath: BGP -> BGP peer
             */
            // Flow path for src-TCP-port
            DataPath dataPath = new DataPath();

            SwitchPort srcPort = new SwitchPort();
            srcPort.setDpid(bgpdAttachmentPoint.dpid());
            srcPort.setPort(bgpdAttachmentPoint.port());
            dataPath.setSrcPort(srcPort);

            SwitchPort dstPort = new SwitchPort();
            dstPort.setDpid(new Dpid(peerInterface.getDpid()));
            dstPort.setPort(new Port(peerInterface.getSwitchPort().port()));
            dataPath.setDstPort(dstPort);

            flowPath.setDataPath(dataPath);

            // TODO: Add the flow by using the new Path Intent framework
            /*
            if (flowManagerService.addFlow(flowPath) == null) {
                log.error("Failed to set up path BGP -> peer {}"+"; dst-TCP-port:179",
                        bgpPeer.getIpAddress().getHostAddress());
            }
            else {
                log.debug("Successfully set up path BGP -> peer {}"+"; dst-TCP-port:179",
                        bgpPeer.getIpAddress().getHostAddress());
            }
            */

            // Disable dst-TCP-port, and set src-TCP-port
            flowEntryMatch.disableDstTcpUdpPort();
            flowEntryMatch.enableSrcTcpUdpPort(BGP_PORT);
            flowPath.setFlowEntryMatch(flowEntryMatch);

            // Create a new FlowId
            flowPath.setFlowId(new FlowId());

            // TODO: Add the flow by using the new Path Intent framework
            /*
            if (flowManagerService.addFlow(flowPath) == null) {
                log.error("Failed to set up path BGP -> Peer {}" + "; src-TCP-port:179",
                        bgpPeer.getIpAddress().getHostAddress());
            }
            else {
                log.debug("Successfully set up path BGP -> Peer {}" + "; src-TCP-port:179",
                        bgpPeer.getIpAddress().getHostAddress());
            }
            */

            /**
             * Create the DataPath: BGP <-BGP peer
             */
            // Reversed BGP flow path for src-TCP-port
            flowPath.setFlowId(new FlowId());

            DataPath reverse_dataPath = new DataPath();

            SwitchPort reverse_dstPort = new SwitchPort();
            reverse_dstPort.setDpid(bgpdAttachmentPoint.dpid());
            reverse_dstPort.setPort(bgpdAttachmentPoint.port());
            reverse_dataPath.setDstPort(reverse_dstPort);

            SwitchPort reverse_srcPort = new SwitchPort();
            reverse_srcPort.setDpid(new Dpid(peerInterface.getDpid()));
            reverse_srcPort.setPort(new Port(peerInterface.getSwitchPort().port()));
            reverse_dataPath.setSrcPort(reverse_srcPort);
            flowPath.setDataPath(reverse_dataPath);

            // reverse the dst IP and src IP addresses
            flowEntryMatch.enableDstIPv4Net(srcIPv4Net);
            flowEntryMatch.enableSrcIPv4Net(dstIPv4Net);
            flowPath.setFlowEntryMatch(flowEntryMatch);

            log.debug("Reversed BGP FlowPath: {}", flowPath.toString());

            // TODO: Add the flow by using the new Path Intent framework
            /*
            if (flowManagerService.addFlow(flowPath) == null) {

                log.error("Failed to set up path BGP <- Peer {}" + "; src-TCP-port:179",
                        bgpPeer.getIpAddress().getHostAddress());
            }
            else {
                log.debug("Successfully set up path BGP <- Peer {}" + "; src-TCP-port:179",
                        bgpPeer.getIpAddress().getHostAddress());
            }
            */

            // Reversed BGP flow path for dst-TCP-port
            flowPath.setFlowId(new FlowId());

            // Disable src-TCP-port, and set the dst-TCP-port
            flowEntryMatch.disableSrcTcpUdpPort();
            flowEntryMatch.enableDstTcpUdpPort(BGP_PORT);
            flowPath.setFlowEntryMatch(flowEntryMatch);

            log.debug("Reversed BGP FlowPath: {}", flowPath.toString());

            // TODO: Add the flow by using the new Path Intent framework
            /*
            if (flowManagerService.addFlow(flowPath) == null) {
                log.error("Failed to setting up path BGP <- Peer {}" + "; dst-TCP-port:179",
                        bgpPeer.getIpAddress().getHostAddress());
            }
            else {
                log.debug("Successfully setting up path BGP <- Peer {}" + "; dst-TCP-port:179",
                        bgpPeer.getIpAddress().getHostAddress());
            }
            */

            /**
             * ICMP paths between BGPd and its peers
             */
            //match ICMP protocol BGP <- Peer
            flowPath.setFlowId(new FlowId());

            flowEntryMatch.enableIpProto(IPv4.PROTOCOL_ICMP);
            flowEntryMatch.disableSrcTcpUdpPort();
            flowEntryMatch.disableDstTcpUdpPort();

            flowPath.setFlowEntryMatch(flowEntryMatch);

            flowPath.setDataPath(reverse_dataPath);

            log.debug("Reversed ICMP FlowPath: {}", flowPath.toString());

            // TODO: Add the flow by using the new Path Intent framework
            /*
            if (flowManagerService.addFlow(flowPath) == null) {

                log.error("Failed to set up ICMP path BGP <- Peer {}",
                        bgpPeer.getIpAddress().getHostAddress());
            }
            else {
                log.debug("Successfully set up ICMP path BGP <- Peer {}",
                        bgpPeer.getIpAddress().getHostAddress());
            }
            */

            //match ICMP protocol BGP -> Peer
            flowPath.setFlowId(new FlowId());

            flowEntryMatch.enableDstIPv4Net(dstIPv4Net);
            flowEntryMatch.enableSrcIPv4Net(srcIPv4Net);
            flowPath.setFlowEntryMatch(flowEntryMatch);

            flowPath.setDataPath(dataPath);

            log.debug("ICMP flowPath: {}", flowPath.toString());

            // TODO: Add the flow by using the new Path Intent framework
            /*
            if (flowManagerService.addFlow(flowPath) == null) {

                log.error("Failed to set up ICMP path BGP -> Peer {}",
                        bgpPeer.getIpAddress().getHostAddress());
            }
            else {
                log.debug("Successfully set up ICMP path BGP -> Peer {}",
                        bgpPeer.getIpAddress().getHostAddress());
            }
            */
        }
    }

    @Override
    public void arpResponse(InetAddress ipAddress, MACAddress macAddress) {
        log.debug("Received ARP response: {} => {}",
                ipAddress.getHostAddress(), macAddress);

        /*
         * We synchronize on this to prevent changes to the ptree while we're pushing
         * flows to the switches. If the ptree changes, the ptree and switches
         * could get out of sync.
         */
        synchronized (this) {
            Path path = pathsWaitingOnArp.remove(ipAddress);

            if (path != null) {
                log.debug("Pushing path to {} at {} on {}", new Object[]{
                        path.getDstIpAddress().getHostAddress(), macAddress,
                        path.getDstInterface().getSwitchPort()});
                //These paths should always be to BGP peers. Paths to non-peers are
                //handled once the first prefix is ready to push
                if (pushedPaths.containsKey(path.getDstIpAddress())) {
                    //A path already got pushed to this endpoint while we were waiting
                    //for ARP. We'll copy over the permanent attribute if it is set on this path.
                    if (path.isPermanent()) {
                        pushedPaths.get(path.getDstIpAddress()).setPermanent();
                    }
                } else {
                    calculateAndPushPath(path, macAddress);
                    pushedPaths.put(path.getDstIpAddress(), path);
                }
            }

            Set<RibUpdate> prefixesToPush = prefixesWaitingOnArp.removeAll(ipAddress);

            for (RibUpdate update : prefixesToPush) {
                //These will always be adds

                RibEntry rib = ptree.lookup(update.getPrefix());
                if (rib != null && rib.equals(update.getRibEntry())) {
                    log.debug("Pushing prefix {} next hop {}", update.getPrefix(),
                            rib.getNextHop().getHostAddress());
                    //We only push prefix flows if the prefix is still in the ptree
                    //and the next hop is the same as our update. The prefix could
                    //have been removed while we were waiting for the ARP, or the
                    //next hop could have changed.
                    _processRibAdd(update);
                } else {
                    log.debug("Received ARP response, but {},{} is no longer in ptree",
                            update.getPrefix(), update.getRibEntry());
                }
            }
        }
    }

    //TODO wait the priority module of the flow Manager
    private void setupArpFlows() {
        OFMatch match = new OFMatch();
        match.setDataLayerType(Ethernet.TYPE_ARP);
        match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_TYPE);

        OFFlowMod fm = new OFFlowMod();
        fm.setMatch(match);

        OFActionOutput action = new OFActionOutput();
        action.setPort(OFPort.OFPP_CONTROLLER.getValue());
        action.setMaxLength((short) 0xffff);
        List<OFAction> actions = new ArrayList<OFAction>(1);
        actions.add(action);
        fm.setActions(actions);

        fm.setIdleTimeout((short) 0)
                .setHardTimeout((short) 0)
                .setBufferId(OFPacketOut.BUFFER_ID_NONE)
                .setCookie(0)
                .setCommand(OFFlowMod.OFPFC_ADD)
                .setPriority(ARP_PRIORITY)
                .setLengthU(OFFlowMod.MINIMUM_LENGTH + OFActionOutput.MINIMUM_LENGTH);

        for (String strdpid : switches) {
            flowCache.write(HexString.toLong(strdpid), fm);
        }
    }

    //TODO need update, waiting for the priority feature from flow Manager
    private void setupDefaultDropFlows() {
        OFFlowMod fm = new OFFlowMod();
        fm.setMatch(new OFMatch());
        fm.setActions(new ArrayList<OFAction>()); //No action means drop

        fm.setIdleTimeout((short) 0)
                .setHardTimeout((short) 0)
                .setBufferId(OFPacketOut.BUFFER_ID_NONE)
                .setCookie(0)
                .setCommand(OFFlowMod.OFPFC_ADD)
                .setPriority((short) 0)
                .setLengthU(OFFlowMod.MINIMUM_LENGTH);

        OFFlowMod fmLLDP;
        OFFlowMod fmBDDP;
        try {
            fmLLDP = fm.clone();
            fmBDDP = fm.clone();
        } catch (CloneNotSupportedException e1) {
            log.error("Error cloning flow mod", e1);
            return;
        }

        OFMatch matchLLDP = new OFMatch();
        matchLLDP.setDataLayerType((short) 0x88cc);
        matchLLDP.setWildcards(matchLLDP.getWildcards() & ~OFMatch.OFPFW_DL_TYPE);
        fmLLDP.setMatch(matchLLDP);

        OFMatch matchBDDP = new OFMatch();
        matchBDDP.setDataLayerType((short) 0x8942);
        matchBDDP.setWildcards(matchBDDP.getWildcards() & ~OFMatch.OFPFW_DL_TYPE);
        fmBDDP.setMatch(matchBDDP);

        OFActionOutput action = new OFActionOutput();
        action.setPort(OFPort.OFPP_CONTROLLER.getValue());
        action.setMaxLength((short) 0xffff);
        List<OFAction> actions = new ArrayList<OFAction>(1);
        actions.add(action);

        fmLLDP.setActions(actions);
        fmBDDP.setActions(actions);

        fmLLDP.setPriority(ARP_PRIORITY);
        fmLLDP.setLengthU(OFFlowMod.MINIMUM_LENGTH + OFActionOutput.MINIMUM_LENGTH);
        fmBDDP.setPriority(ARP_PRIORITY);
        fmBDDP.setLengthU(OFFlowMod.MINIMUM_LENGTH + OFActionOutput.MINIMUM_LENGTH);

        List<OFFlowMod> flowModList = new ArrayList<OFFlowMod>(3);
        flowModList.add(fm);
        flowModList.add(fmLLDP);
        flowModList.add(fmBDDP);

        for (String strdpid : switches) {
            flowCache.write(HexString.toLong(strdpid), flowModList);
        }
    }

    private void beginRouting() {
        log.debug("Topology is now ready, beginning routing function");
        // TODO: Fix for the new Topology Network Graph
        // topology = topologyNetService.newDatabaseTopology();

        // Wait Pavlin's API. We need the following functions.
        /*setupArpFlows();
        setupDefaultDropFlows();*/

        setupBgpPaths();
        setupFullMesh();

        //Suppress link discovery on external-facing router ports
        for (Interface intf : interfaces.values()) {
            linkDiscoveryService.AddToSuppressLLDPs(intf.getDpid(), intf.getPort());
        }

        bgpUpdatesExecutor.execute(new Runnable() {
            @Override
            public void run() {
                doUpdatesThread();
            }
        });
    }

    // Before inserting the paths for BGP traffic, we should check
    // whether all the switches in the configure file are discovered by onos.
    private void checkSwitchesConnected() {
        for (String dpid : switches) {
            // TODO: Fix the code below after topoSwitchSerice was removed
            /*
            Iterator<ISwitchObject> activeSwitches = topoSwitchService.
                    getActiveSwitches().iterator();
            while(activeSwitches.hasNext())
            {
                ISwitchObject switchObject = activeSwitches.next();
                if (switchObject.getDPID().equals(dpid)) {
                    break;
                }
                if(activeSwitches.hasNext() == false) {
                    log.debug("Not all switches are here yet");
                    return;
                }
            }
            */
        }
        switchesConnected = true;
    }

    //Actually we only need to go half way round to verify full mesh connectivity
    //(n^2)/2
    private void checkTopologyReady() {
        for (Interface dstInterface : interfaces.values()) {
            for (Interface srcInterface : interfaces.values()) {
                if (dstInterface.equals(srcInterface)) {
                    continue;
                }

                // TODO: Fix for the new Topology Network Graph
                /*
                DataPath shortestPath = topologyNetService.getDatabaseShortestPath(
                        srcInterface.getSwitchPort(), dstInterface.getSwitchPort());

                if (shortestPath == null){
                    log.debug("Shortest path between {} and {} not found",
                            srcInterface.getSwitchPort(), dstInterface.getSwitchPort());
                    return;
                }
                */
            }
        }
        topologyReady = true;
    }

    private void checkStatus() {
        if (!switchesConnected) {
            checkSwitchesConnected();
        }
        boolean oldTopologyReadyStatus = topologyReady;
        if (switchesConnected && !topologyReady) {
            checkTopologyReady();
        }
        if (!oldTopologyReadyStatus && topologyReady) {
            beginRouting();
        }
    }

    private void doUpdatesThread() {
        boolean interrupted = false;
        try {
            while (true) {
                try {
                    RibUpdate update = ribUpdates.take();
                    switch (update.getOperation()) {
                        case UPDATE:
                            if (validateUpdate(update)) {
                                processRibAdd(update);
                            } else {
                                log.debug("Rib UPDATE out of order: {} via {}",
                                        update.getPrefix(), update.getRibEntry().getNextHop());
                            }
                            break;
                        case DELETE:
                            if (validateUpdate(update)) {
                                processRibDelete(update);
                            } else {
                                log.debug("Rib DELETE out of order: {} via {}",
                                        update.getPrefix(), update.getRibEntry().getNextHop());
                            }
                            break;
                    }
                } catch (InterruptedException e) {
                    log.debug("Interrupted while taking from updates queue", e);
                    interrupted = true;
                } catch (Exception e) {
                    log.debug("exception", e);
                }
            }
        } finally {
            if (interrupted) {
                Thread.currentThread().interrupt();
            }
        }
    }

    private boolean validateUpdate(RibUpdate update) {
        RibEntry newEntry = update.getRibEntry();
        RibEntry oldEntry = ptree.lookup(update.getPrefix());

        //If there is no existing entry we must assume this is the most recent
        //update. However this might not always be the case as we might have a
        //POST then DELETE reordering.
        //if (oldEntry == null || !newEntry.getNextHop().equals(oldEntry.getNextHop())) {
        if (oldEntry == null) {
            return true;
        }

        // This handles the case where routes are gathered in the initial
        // request because they don't have sequence number info
        if (newEntry.getSysUpTime() == -1 && newEntry.getSequenceNum() == -1) {
            return true;
        }

        if (newEntry.getSysUpTime() > oldEntry.getSysUpTime()) {
            return true;
        } else if (newEntry.getSysUpTime() == oldEntry.getSysUpTime()) {
            if (newEntry.getSequenceNum() > oldEntry.getSequenceNum()) {
                return true;
            } else {
                return false;
            }
        } else {
            return false;
        }
    }

    // The code below should be reimplemented after removal of Floodlight's
    // ITopologyService API. It should be implemented on top of network graph
    // notifications. (It was pretty hacky anyway...)
    /*
    @Override
    public void topologyChanged() {
        if (topologyReady) {
            return;
        }

        boolean refreshNeeded = false;
        for (LDUpdate ldu : topologyService.getLastLinkUpdates()){
            if (!ldu.getOperation().equals(ILinkDiscovery.UpdateOperation.LINK_UPDATED)){
                //We don't need to recalculate anything for just link updates
                //They happen very frequently
                refreshNeeded = true;
            }

            log.debug("Topo change {}", ldu.getOperation());

            if (ldu.getOperation().equals(ILinkDiscovery.UpdateOperation.LINK_ADDED)){
                synchronized (linkUpdates) {
                    linkUpdates.add(ldu);
                }
            }
        }

        if (refreshNeeded && !topologyReady){
            topologyChangeDetectorTask.reschedule(TOPO_DETECTION_WAIT, TimeUnit.SECONDS);
        }
    }
    */

    @Override
    public void addedSwitch(IOFSwitch sw) {
        if (!topologyReady) {
            sw.clearAllFlowMods();
        }

        flowCache.switchConnected(sw);
    }

    @Override
    public void removedSwitch(IOFSwitch sw) {
    }

    @Override
    public void switchPortChanged(Long switchId) {
    }

    @Override
    public String getName() {
        return "BgpRoute";
    }

    /*
     * IConfigInfoService methods
     */

    @Override
    public boolean isInterfaceAddress(InetAddress address) {
        Interface intf = interfacePtrie.match(new Prefix(address.getAddress(), 32));
        return (intf != null && intf.getIpAddress().equals(address));
    }

    @Override
    public boolean inConnectedNetwork(InetAddress address) {
        Interface intf = interfacePtrie.match(new Prefix(address.getAddress(), 32));
        return (intf != null && !intf.getIpAddress().equals(address));
    }

    @Override
    public boolean fromExternalNetwork(long inDpid, short inPort) {
        for (Interface intf : interfaces.values()) {
            if (intf.getDpid() == inDpid && intf.getPort() == inPort) {
                return true;
            }
        }
        return false;
    }

    @Override
    public Interface getOutgoingInterface(InetAddress dstIpAddress) {
        return interfacePtrie.match(new Prefix(dstIpAddress.getAddress(), 32));
    }

    @Override
    public boolean hasLayer3Configuration() {
        return !interfaces.isEmpty();
    }

    @Override
    public MACAddress getRouterMacAddress() {
        return bgpdMacAddress;
    }

    @Override
    public short getVlan() {
        return vlan;
    }
}
