package net.onrc.onos.apps.proxyarp;

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.Set;
import java.util.Timer;
import java.util.TimerTask;

import net.floodlightcontroller.core.module.FloodlightModuleContext;
import net.floodlightcontroller.core.module.IFloodlightModule;
import net.floodlightcontroller.core.module.IFloodlightService;
import net.floodlightcontroller.restserver.IRestApiService;
import net.floodlightcontroller.util.MACAddress;
import net.onrc.onos.api.packet.IPacketListener;
import net.onrc.onos.api.packet.IPacketService;
import net.onrc.onos.apps.proxyarp.web.ArpWebRoutable;
import net.onrc.onos.apps.sdnip.Interface;
import net.onrc.onos.core.datagrid.IDatagridService;
import net.onrc.onos.core.datagrid.IEventChannel;
import net.onrc.onos.core.datagrid.IEventChannelListener;
import net.onrc.onos.core.main.config.IConfigInfoService;
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.Host;
import net.onrc.onos.core.topology.ITopologyService;
import net.onrc.onos.core.topology.Port;
import net.onrc.onos.core.topology.Switch;
import net.onrc.onos.core.topology.Topology;
import net.onrc.onos.core.util.Dpid;
import net.onrc.onos.core.util.PortNumber;
import net.onrc.onos.core.util.SwitchPort;

import org.openflow.util.HexString;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimaps;
import com.google.common.collect.SetMultimap;
import com.google.common.net.InetAddresses;

public class ProxyArpManager implements IProxyArpService, IFloodlightModule,
                                        IPacketListener {
    private static final Logger log = LoggerFactory
            .getLogger(ProxyArpManager.class);

    private static long arpTimerPeriodConfig = 2000; // ms
    private static int arpRequestTimeoutConfig = 2000; // ms
    private long arpCleaningTimerPeriodConfig = 60 * 1000; // ms (1 min)

    private IDatagridService datagrid;
    private IEventChannel<Long, ArpReplyNotification> arpReplyEventChannel;
    private IEventChannel<String, ArpCacheNotification> arpCacheEventChannel;
    private static final String ARP_REPLY_CHANNEL_NAME = "onos.arp_reply";
    private static final String ARP_CACHE_CHANNEL_NAME = "onos.arp_cache";
    private final ArpReplyEventHandler arpReplyEventHandler = new ArpReplyEventHandler();
    private final ArpCacheEventHandler arpCacheEventHandler = new ArpCacheEventHandler();

    private IConfigInfoService configService;
    private IRestApiService restApi;

    private ITopologyService topologyService;
    private Topology topology;
    private IPacketService packetService;

    private short vlan;
    private static final short NO_VLAN = 0;

    private SetMultimap<InetAddress, ArpRequest> arpRequests;

    private ArpCache arpCache;

    private class ArpReplyEventHandler implements
            IEventChannelListener<Long, ArpReplyNotification> {

        @Override
        public void entryAdded(ArpReplyNotification arpReply) {
            log.debug("Received ARP reply notification for ip {}, mac {}",
                    arpReply.getTargetAddress(), arpReply.getTargetMacAddress());

            InetAddress addr = InetAddresses.fromInteger(arpReply.getTargetAddress());

            sendArpReplyToWaitingRequesters(addr,
                    arpReply.getTargetMacAddress());
        }

        @Override
        public void entryUpdated(ArpReplyNotification arpReply) {
            entryAdded(arpReply);
        }

        @Override
        public void entryRemoved(ArpReplyNotification arpReply) {
            //Not implemented. ArpReplyEventHandler is used only for remote messaging.
        }
    }

    private class ArpCacheEventHandler implements
    IEventChannelListener<String, ArpCacheNotification> {

        /**
         * Startup processing.
         */
        private void startUp() {
            //
            // TODO: Read all state from the database:
            // For now, as a shortcut we read it from the datagrid
            //
            Collection<ArpCacheNotification> arpCacheEvents =
                    arpCacheEventChannel.getAllEntries();

            for (ArpCacheNotification arpCacheEvent : arpCacheEvents) {
                entryAdded(arpCacheEvent);
            }
        }

        @Override
        public void entryAdded(ArpCacheNotification value) {
            try {
                InetAddress targetIpAddress =
                        InetAddress.getByAddress(value.getTargetAddress());

                log.debug("Received entryAdded for ARP cache notification " +
                        "for ip {}, mac {}", targetIpAddress, value.getTargetMacAddress());
                arpCache.update(targetIpAddress,
                        MACAddress.valueOf(value.getTargetMacAddress()));
            } catch (UnknownHostException e) {
                log.error("Exception: ", e);
            }
        }

        @Override
        public void entryRemoved(ArpCacheNotification value) {
            log.debug("Received entryRemoved for ARP cache notification for ip {}, mac {}",
                    value.getTargetAddress(), value.getTargetMacAddress());
            try {
                arpCache.remove(InetAddress.getByAddress(value.getTargetAddress()));
            } catch (UnknownHostException e) {
                log.error("Exception: ", e);
            }
        }

        @Override
        public void entryUpdated(ArpCacheNotification value) {
            try {
                InetAddress targetIpAddress =
                        InetAddress.getByAddress(value.getTargetAddress());

                log.debug("Received entryUpdated for ARP cache notification " +
                        "for ip {}, mac {}", targetIpAddress, value.getTargetMacAddress());
                arpCache.update(targetIpAddress,
                        MACAddress.valueOf(value.getTargetMacAddress()));
            } catch (UnknownHostException e) {
                log.error("Exception: ", e);
            }
        }
    }

    private static class ArpRequest {
        private final IArpRequester requester;
        private final boolean retry;
        private long requestTime;

        public ArpRequest(IArpRequester requester, boolean retry) {
            this.requester = requester;
            this.retry = retry;

            requestTime = System.currentTimeMillis();
        }

        public ArpRequest(ArpRequest old) {
            this.requester = old.requester;
            this.retry = old.retry;
        }

        public boolean isExpired() {
            return ((System.currentTimeMillis() - requestTime)
                    > arpRequestTimeoutConfig);
        }

        public boolean shouldRetry() {
            return retry;
        }

        public void dispatchReply(InetAddress ipAddress,
                                  MACAddress replyMacAddress) {
            requester.arpResponse(ipAddress, replyMacAddress);
        }
    }

    private class HostArpRequester implements IArpRequester {
        private final ARP arpRequest;
        private final long dpid;
        private final short port;

        public HostArpRequester(ARP arpRequest, long dpid, short port) {
            this.arpRequest = arpRequest;
            this.dpid = dpid;
            this.port = port;
        }

        @Override
        public void arpResponse(InetAddress ipAddress, MACAddress macAddress) {
            ProxyArpManager.this.sendArpReply(arpRequest, dpid, port,
                    macAddress);
        }
    }

    @Override
    public Collection<Class<? extends IFloodlightService>> getModuleServices() {
        Collection<Class<? extends IFloodlightService>> l =
                new ArrayList<Class<? extends IFloodlightService>>();
        l.add(IProxyArpService.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(IProxyArpService.class, this);
        return m;
    }

    @Override
    public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
        Collection<Class<? extends IFloodlightService>> dependencies =
                new ArrayList<Class<? extends IFloodlightService>>();
        dependencies.add(IRestApiService.class);
        dependencies.add(IDatagridService.class);
        dependencies.add(IConfigInfoService.class);
        dependencies.add(ITopologyService.class);
        dependencies.add(IPacketService.class);
        return dependencies;
    }

    @Override
    public void init(FloodlightModuleContext context) {
        this.configService = context.getServiceImpl(IConfigInfoService.class);
        this.restApi = context.getServiceImpl(IRestApiService.class);
        this.datagrid = context.getServiceImpl(IDatagridService.class);
        this.topologyService = context.getServiceImpl(ITopologyService.class);
        this.packetService = context.getServiceImpl(IPacketService.class);

        arpRequests = Multimaps.synchronizedSetMultimap(HashMultimap
                .<InetAddress, ArpRequest>create());
    }

    @Override
    public void startUp(FloodlightModuleContext context) {
        Map<String, String> configOptions = context.getConfigParams(this);

        try {
            arpCleaningTimerPeriodConfig =
                    Long.parseLong(configOptions.get("cleanupmsec"));
        } catch (NumberFormatException e) {
            log.debug("ArpCleaningTimerPeriod related config options were " +
                    "not set. Using default.");
        }

        Long agingmsec = null;
        try {
            agingmsec = Long.parseLong(configOptions.get("agingmsec"));
        } catch (NumberFormatException e) {
            log.debug("ArpEntryTimeout related config options were " +
                    "not set. Using default.");
        }

        arpCache = new ArpCache();
        if (agingmsec != null) {
            arpCache.setArpEntryTimeoutConfig(agingmsec);
        }

        this.vlan = configService.getVlan();
        log.info("vlan set to {}", this.vlan);

        restApi.addRestletRoutable(new ArpWebRoutable());
        packetService.registerPacketListener(this);
        topology = topologyService.getTopology();

        //
        // Event notification setup: channels and event handlers
        //

        arpReplyEventChannel = datagrid.addListener(ARP_REPLY_CHANNEL_NAME,
                arpReplyEventHandler,
                Long.class,
                ArpReplyNotification.class);

        arpCacheEventChannel = datagrid.addListener(ARP_CACHE_CHANNEL_NAME,
                arpCacheEventHandler,
                String.class,
                ArpCacheNotification.class);
        arpCacheEventHandler.startUp();

        Timer arpTimer = new Timer("arp-processing");
        arpTimer.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                doPeriodicArpProcessing();
            }
        }, 0, arpTimerPeriodConfig);

        Timer arpCacheTimer = new Timer("arp-cleaning");
        arpCacheTimer.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                doPeriodicArpCleaning();
            }
        }, 0, arpCleaningTimerPeriodConfig);
    }

    /*
     * Function that runs periodically to manage the asynchronous request mechanism.
     * It basically cleans up old ARP requests if we don't get a response for them.
     * The caller can designate that a request should be retried indefinitely, and
     * this task will handle that as well.
     */
    private void doPeriodicArpProcessing() {
        SetMultimap<InetAddress, ArpRequest> retryList = HashMultimap
                .<InetAddress, ArpRequest>create();

        // We must synchronize externally on the Multimap while using an
        // iterator, even though it's a synchronizedMultimap
        synchronized (arpRequests) {
            Iterator<Map.Entry<InetAddress, ArpRequest>> it = arpRequests
                    .entries().iterator();

            while (it.hasNext()) {
                Map.Entry<InetAddress, ArpRequest> entry = it.next();
                ArpRequest request = entry.getValue();
                if (request.isExpired()) {
                    log.debug("Cleaning expired ARP request for {}", entry
                            .getKey().getHostAddress());

                    it.remove();

                    if (request.shouldRetry()) {
                        retryList.put(entry.getKey(), request);
                    }
                }
            }
        }

        for (Map.Entry<InetAddress, Collection<ArpRequest>> entry : retryList
                .asMap().entrySet()) {

            InetAddress address = entry.getKey();

            log.debug("Resending ARP request for {}", address.getHostAddress());

            // Only ARP requests sent by the controller will have the retry flag
            // set, so for now we can just send a new ARP request for that
            // address.
            sendArpRequestForAddress(address);

            for (ArpRequest request : entry.getValue()) {
                arpRequests.put(address, new ArpRequest(request));
            }
        }
    }

    @Override
    public void receive(Switch sw, Port inPort, Ethernet eth) {

        if (eth.getEtherType() == Ethernet.TYPE_ARP) {
            ARP arp = (ARP) eth.getPayload();
            learnArp(arp);
            if (arp.getOpCode() == ARP.OP_REQUEST) {
                handleArpRequest(sw.getDpid().value(), inPort.getNumber().shortValue(),
                        arp, eth);
            } else if (arp.getOpCode() == ARP.OP_REPLY) {
                // For replies we simply send a notification via Hazelcast
                sendArpReplyNotification(eth);
            }
        }
    }

    private void learnArp(ARP arp) {
        ArpCacheNotification arpCacheNotification = null;

        arpCacheNotification = new ArpCacheNotification(
                arp.getSenderProtocolAddress(), arp.getSenderHardwareAddress());

        try {
            arpCacheEventChannel.addEntry(InetAddress.getByAddress(
                    arp.getSenderProtocolAddress()).toString(), arpCacheNotification);
        } catch (UnknownHostException e) {
            log.error("Exception : ", e);
        }
    }

    private void handleArpRequest(long dpid, short inPort, ARP arp, Ethernet eth) {
        if (log.isTraceEnabled()) {
            log.trace("ARP request received for {}",
                    inetAddressToString(arp.getTargetProtocolAddress()));
        }

        InetAddress target;
        try {
            target = InetAddress.getByAddress(arp.getTargetProtocolAddress());
        } catch (UnknownHostException e) {
            log.debug("Invalid address in ARP request", e);
            return;
        }

        if (configService.fromExternalNetwork(dpid, inPort)) {
            // If the request came from outside our network, we only care if
            // it was a request for one of our interfaces.
            if (configService.isInterfaceAddress(target)) {
                log.trace(
                        "ARP request for our interface. Sending reply {} => {}",
                        target.getHostAddress(),
                        configService.getRouterMacAddress());

                sendArpReply(arp, dpid, inPort,
                        configService.getRouterMacAddress());
            }

            return;
        }

        //MACAddress mac = arpCache.lookup(target);

        arpRequests.put(target, new ArpRequest(
                new HostArpRequester(arp, dpid, inPort), false));

        topology.acquireReadLock();
        Host targetHost = topology.getHostByMac(
                MACAddress.valueOf(arp.getTargetHardwareAddress()));
        topology.releaseReadLock();

        if (targetHost == null) {
            if (log.isTraceEnabled()) {
                log.trace("No device info found for {} - broadcasting",
                        target.getHostAddress());
            }

            // We don't know the device so broadcast the request out
            packetService.broadcastPacketOutEdge(eth,
                    new SwitchPort(dpid, inPort));
        } else {
            // Even if the device exists in our database, we do not reply to
            // the request directly, but check whether the device is still valid
            MACAddress macAddress = MACAddress.valueOf(arp.getTargetHardwareAddress());

            if (log.isTraceEnabled()) {
                log.trace("The target Host Record in DB is: {} => {} " +
                        "from ARP request host at {}/{}", new Object[]{
                                inetAddressToString(arp.getTargetProtocolAddress()),
                                macAddress, HexString.toHexString(dpid), inPort});
            }

            // sendArpReply(arp, sw.getId(), pi.getInPort(), macAddress);

            Iterable<Port> outPorts = targetHost.getAttachmentPoints();

            if (!outPorts.iterator().hasNext()) {
                if (log.isTraceEnabled()) {
                    log.trace("Host {} exists but is not connected to any ports" +
                            " - broadcasting", macAddress);
                }

                packetService.broadcastPacketOutEdge(eth,
                        new SwitchPort(dpid, inPort));
            } else {
                for (Port portObject : outPorts) {

                    if (portObject.getOutgoingLink() != null ||
                            portObject.getIncomingLink() != null) {
                        continue;
                    }

                    PortNumber outPort = portObject.getNumber();
                    Switch outSwitchObject = portObject.getSwitch();
                    Dpid outSwitch = outSwitchObject.getDpid();

                    if (log.isTraceEnabled()) {
                        log.trace("Probing device {} on port {}/{}",
                                new Object[]{macAddress,
                                        outSwitch, outPort});
                    }

                    packetService.sendPacket(
                            eth, new SwitchPort(outSwitch, outPort));
                }
            }
        }
    }

    // TODO this method has not been tested after recent implementation changes.
    private void sendArpRequestForAddress(InetAddress ipAddress) {
        // TODO what should the sender IP address and MAC address be if no
        // IP addresses are configured? Will there ever be a need to send
        // ARP requests from the controller in that case?
        // All-zero MAC address doesn't seem to work - hosts don't respond to it

        byte[] zeroIpv4 = {0x0, 0x0, 0x0, 0x0};
        byte[] zeroMac = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
        byte[] genericNonZeroMac = {0x0, 0x0, 0x0, 0x0, 0x0, 0x01};
        byte[] broadcastMac = {(byte) 0xff, (byte) 0xff, (byte) 0xff,
                (byte) 0xff, (byte) 0xff, (byte) 0xff};

        ARP arpRequest = new ARP();

        arpRequest
                .setHardwareType(ARP.HW_TYPE_ETHERNET)
                .setProtocolType(ARP.PROTO_TYPE_IP)
                .setHardwareAddressLength(
                        (byte) Ethernet.DATALAYER_ADDRESS_LENGTH)
                .setProtocolAddressLength((byte) IPv4.ADDRESS_LENGTH)
                .setOpCode(ARP.OP_REQUEST).setTargetHardwareAddress(zeroMac)
                .setTargetProtocolAddress(ipAddress.getAddress());

        MACAddress routerMacAddress = configService.getRouterMacAddress();
        // As for now, it's unclear what the MAC address should be
        byte[] senderMacAddress = genericNonZeroMac;
        if (routerMacAddress != null) {
            senderMacAddress = routerMacAddress.toBytes();
        }
        arpRequest.setSenderHardwareAddress(senderMacAddress);

        byte[] senderIPAddress = zeroIpv4;
        Interface intf = configService.getOutgoingInterface(ipAddress);
        if (intf == null) {
            // TODO handle the case where the controller needs to send an ARP
            // request but there's not IP configuration. In this case the
            // request should be broadcast out all edge ports in the network.
            log.warn("Sending ARP requests with default configuration "
                    + "not supported");
            return;
        }

        senderIPAddress = intf.getIpAddress().getAddress();

        arpRequest.setSenderProtocolAddress(senderIPAddress);

        Ethernet eth = new Ethernet();
        eth.setSourceMACAddress(senderMacAddress)
                .setDestinationMACAddress(broadcastMac)
                .setEtherType(Ethernet.TYPE_ARP).setPayload(arpRequest);

        if (vlan != NO_VLAN) {
            eth.setVlanID(vlan).setPriorityCode((byte) 0);
        }

        // sendArpRequestToSwitches(ipAddress, eth.serialize());

        packetService.sendPacket(
                eth, new SwitchPort(intf.getDpid(), intf.getPort()));
    }

    // Please leave it for now because this code is needed for SDN-IP.
    // It will be removed soon.
    /*
    private void sendArpRequestToSwitches(InetAddress dstAddress, byte[] arpRequest) {
        sendArpRequestToSwitches(dstAddress, arpRequest,
                0, OFPort.OFPP_NONE.getValue());
    }

    private void sendArpRequestToSwitches(InetAddress dstAddress, byte[] arpRequest,
            long inSwitch, short inPort) {

        if (configService.hasLayer3Configuration()) {
            Interface intf = configService.getOutgoingInterface(dstAddress);
            if (intf != null) {
                sendArpRequestOutPort(arpRequest, intf.getDpid(), intf.getPort());
            }
            else {
                //TODO here it should be broadcast out all non-interface edge ports.
                //I think we can assume that if it's not a request for an external
                //network, it's an ARP for a host in our own network. So we want to
                //send it out all edge ports that don't have an interface configured
                //to ensure it reaches all hosts in our network.
                log.debug("No interface found to send ARP request for {}",
                        dstAddress.getHostAddress());
            }
        }
        else {
            broadcastArpRequestOutEdge(arpRequest, inSwitch, inPort);
        }
    }
    */

    private void sendArpReplyNotification(Ethernet eth) {
        ARP arp = (ARP) eth.getPayload();

        if (log.isTraceEnabled()) {
            log.trace("Sending ARP reply for {} to other ONOS instances",
                    inetAddressToString(arp.getSenderProtocolAddress()));
        }

        InetAddress targetAddress;

        try {
            targetAddress = InetAddress.getByAddress(arp
                    .getSenderProtocolAddress());
        } catch (UnknownHostException e) {
            log.error("Unknown host", e);
            return;
        }

        int intAddress = InetAddresses.coerceToInteger(targetAddress);

        MACAddress mac = new MACAddress(arp.getSenderHardwareAddress());

        ArpReplyNotification value = new ArpReplyNotification(intAddress, mac);

        log.debug("ArpReplyNotification ip {}, mac {}", intAddress, mac);
        arpReplyEventChannel.addTransientEntry(mac.toLong(), value);
    }

    private void sendArpReply(ARP arpRequest, long dpid, short port,
                              MACAddress targetMac) {
        if (log.isTraceEnabled()) {
            log.trace("Sending reply {} => {} to {}",
                    new Object[]{
                    inetAddressToString(arpRequest.getTargetProtocolAddress()),
                    targetMac, inetAddressToString(arpRequest
                                    .getSenderProtocolAddress())});
        }

        ARP arpReply = new ARP();
        arpReply.setHardwareType(ARP.HW_TYPE_ETHERNET)
                .setProtocolType(ARP.PROTO_TYPE_IP)
                .setHardwareAddressLength(
                        (byte) Ethernet.DATALAYER_ADDRESS_LENGTH)
                .setProtocolAddressLength((byte) IPv4.ADDRESS_LENGTH)
                .setOpCode(ARP.OP_REPLY)
                .setSenderHardwareAddress(targetMac.toBytes())
                .setSenderProtocolAddress(arpRequest.getTargetProtocolAddress())
                .setTargetHardwareAddress(arpRequest.getSenderHardwareAddress())
                .setTargetProtocolAddress(arpRequest.getSenderProtocolAddress());

        Ethernet eth = new Ethernet();
        eth.setDestinationMACAddress(arpRequest.getSenderHardwareAddress())
                .setSourceMACAddress(targetMac.toBytes())
                .setEtherType(Ethernet.TYPE_ARP).setPayload(arpReply);

        if (vlan != NO_VLAN) {
            eth.setVlanID(vlan).setPriorityCode((byte) 0);
        }

        packetService.sendPacket(eth, new SwitchPort(dpid, port));
    }

    private String inetAddressToString(byte[] bytes) {
        try {
            return InetAddress.getByAddress(bytes).getHostAddress();
        } catch (UnknownHostException e) {
            log.debug("Invalid IP address", e);
            return "";
        }
    }

    /*
     * IProxyArpService methods
     */

    @Override
    public MACAddress getMacAddress(InetAddress ipAddress) {
        return arpCache.lookup(ipAddress);
    }

    @Override
    public void sendArpRequest(InetAddress ipAddress, IArpRequester requester,
                               boolean retry) {
        arpRequests.put(ipAddress, new ArpRequest(requester, retry));

        // Sanity check to make sure we don't send a request for our own address
        if (!configService.isInterfaceAddress(ipAddress)) {
            sendArpRequestForAddress(ipAddress);
        }
    }

    @Override
    public List<String> getMappings() {
        return arpCache.getMappings();
    }

    private void sendArpReplyToWaitingRequesters(InetAddress address,
                                                 MACAddress mac) {
        log.debug("Sending ARP reply for {} to requesters",
                address.getHostAddress());

        // See if anyone's waiting for this ARP reply
        Set<ArpRequest> requests = arpRequests.get(address);

        // Synchronize on the Multimap while using an iterator for one of the
        // sets
        List<ArpRequest> requestsToSend = new ArrayList<ArpRequest>(
                requests.size());
        synchronized (arpRequests) {
            Iterator<ArpRequest> it = requests.iterator();
            while (it.hasNext()) {
                ArpRequest request = it.next();
                it.remove();
                requestsToSend.add(request);
            }
        }

        // Don't hold an ARP lock while dispatching requests
        for (ArpRequest request : requestsToSend) {
            request.dispatchReply(address, mac);
        }
    }

    private void doPeriodicArpCleaning() {
        List<InetAddress> expiredipslist = arpCache.getExpiredArpCacheIps();
        for (InetAddress expireIp : expiredipslist) {
            log.debug("call arpCacheEventChannel.removeEntry, ip {}", expireIp);
            arpCacheEventChannel.removeEntry(expireIp.toString());
        }
    }

    public long getArpEntryTimeout() {
        return arpCache.getArpEntryTimeout();
    }

    public long getArpCleaningTimerPeriod() {
        return arpCleaningTimerPeriodConfig;
    }

    /**
     * Replaces the internal ArpCache.
     *
     * @param cache ArpCache instance
     *
     * @exclude Backdoor for unit testing purpose only, do not use.
     */
    void debugReplaceArpCache(final ArpCache cache) {
        this.arpCache = cache;
    }
}
