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

import org.onlab.packet.ARP;
import org.onlab.packet.Ethernet;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onosproject.incubator.net.neighbour.NeighbourMessageContext;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Host;
import org.onosproject.net.HostId;
import org.onosproject.net.host.HostService;
import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
import org.onosproject.segmentrouting.config.SegmentRoutingAppConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Set;
import java.util.stream.Collectors;

import static org.onosproject.incubator.net.neighbour.NeighbourMessageType.REQUEST;

/**
 * Handler of ARP packets that responses or forwards ARP packets that
 * are sent to the controller.
 */
public class ArpHandler extends SegmentRoutingNeighbourHandler {

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

    /**
     * Creates an ArpHandler object.
     *
     * @param srManager SegmentRoutingManager object
     */
    public ArpHandler(SegmentRoutingManager srManager) {
        super(srManager);
    }

    /**
     * Processes incoming ARP packets.
     *
     * If it is an ARP request to router itself or known hosts,
     * then it sends ARP response.
     * If it is an ARP request to unknown hosts in its own subnet,
     * then it flood the ARP request to the ports.
     * If it is an ARP response, then set a flow rule for the host
     * and forward any IP packets to the host in the packet buffer to the host.
     * <p>
     * Note: We handles all ARP packet in, even for those ARP packets between
     * hosts in the same subnet.
     * For an ARP packet with broadcast destination MAC,
     * some switches pipelines will send it to the controller due to table miss,
     * other switches will flood the packets directly in the data plane without
     * packet in.
     * We can deal with both cases.
     *
     * @param pkt incoming ARP packet and context information
     * @param hostService the host service
     */
    public void processPacketIn(NeighbourMessageContext pkt, HostService hostService) {

        SegmentRoutingAppConfig appConfig = srManager.cfgService
                .getConfig(srManager.appId, SegmentRoutingAppConfig.class);
        if (appConfig != null && appConfig.suppressSubnet().contains(pkt.inPort())) {
            // Ignore ARP packets come from suppressed ports
            pkt.drop();
            return;
        }

        if (!validateArpSpa(pkt)) {
            log.debug("Ignore ARP packet discovered on {} with unexpected src protocol address {}.",
                    pkt.inPort(), pkt.sender().getIp4Address());
            pkt.drop();
            return;
        }

        if (pkt.type() == REQUEST) {
            handleArpRequest(pkt, hostService);
        } else {
            handleArpReply(pkt, hostService);
        }
    }

    private void handleArpRequest(NeighbourMessageContext pkt, HostService hostService) {
        // ARP request for router. Send ARP reply.
        if (isArpForRouter(pkt)) {
            MacAddress targetMac = config.getRouterMacForAGatewayIp(pkt.target().getIp4Address());
            sendResponse(pkt, targetMac, hostService);
        } else {
            Set<Host> hosts = hostService.getHostsByIp(pkt.target());
            if (hosts.size() > 1) {
                log.warn("More than one host with the same ip {}", pkt.target());
            }
            Host targetHost = hosts.stream().findFirst().orElse(null);
            // ARP request for known hosts. Send proxy ARP reply on behalf of the target.
            if (targetHost != null) {
                pkt.forward(targetHost.location());
            // ARP request for unknown host in the subnet. Flood in the subnet.
            } else {
                flood(pkt);
            }
        }
    }

    private void handleArpReply(NeighbourMessageContext pkt, HostService hostService) {
        // ARP reply for router. Process all pending IP packets.
        if (isArpForRouter(pkt)) {
            Ip4Address hostIpAddress = pkt.sender().getIp4Address();
            srManager.ipHandler.forwardPackets(pkt.inPort().deviceId(), hostIpAddress);
        } else {
            HostId targetHostId = HostId.hostId(pkt.dstMac(), pkt.vlan());
            Host targetHost = hostService.getHost(targetHostId);
            // ARP reply for known hosts. Forward to the host.
            if (targetHost != null) {
                pkt.forward(targetHost.location());
            // ARP reply for unknown host, Flood in the subnet.
            } else {
                // Don't flood to non-edge ports
                if (pkt.vlan().equals(SegmentRoutingManager.INTERNAL_VLAN)) {
                    return;
                }
                flood(pkt);
            }
        }
    }

    /**
     * Check if the source protocol address of an ARP packet belongs to the same
     * subnet configured on the port it is seen.
     *
     * @param pkt ARP packet and context information
     * @return true if the source protocol address belongs to the configured subnet
     */
    private boolean validateArpSpa(NeighbourMessageContext pkt) {
        Ip4Address spa = pkt.sender().getIp4Address();
        Set<IpPrefix> subnet = config.getPortSubnets(pkt.inPort().deviceId(), pkt.inPort().port())
                .stream()
                .filter(ipPrefix -> ipPrefix.isIp4() && ipPrefix.contains(spa))
                .collect(Collectors.toSet());
        return !subnet.isEmpty();
    }


    private boolean isArpForRouter(NeighbourMessageContext pkt) {
        Ip4Address targetProtocolAddress = pkt.target().getIp4Address();
        Set<IpAddress> gatewayIpAddresses = null;
        try {
            if (targetProtocolAddress.equals(config.getRouterIpv4(pkt.inPort().deviceId()))) {
                return true;
            }
            gatewayIpAddresses = config.getPortIPs(pkt.inPort().deviceId());
        } catch (DeviceConfigNotFoundException e) {
            log.warn(e.getMessage() + " Aborting check for router IP in processing arp");
        }
        if (gatewayIpAddresses != null &&
                gatewayIpAddresses.contains(targetProtocolAddress)) {
            return true;
        }
        return false;
    }

    /**
     * Sends an APR request for the target IP address to all ports except in-port.
     *
     * @param deviceId Switch device ID
     * @param targetAddress target IP address for ARP
     * @param inPort in-port
     */
    public void sendArpRequest(DeviceId deviceId, IpAddress targetAddress, ConnectPoint inPort) {
        byte[] senderMacAddress = new byte[MacAddress.MAC_ADDRESS_LENGTH];
        byte[] senderIpAddress = new byte[Ip4Address.BYTE_LENGTH];
        /*
         * Retrieves device info.
         */
        if (!getSenderInfo(senderMacAddress, senderIpAddress, deviceId, targetAddress)) {
            log.warn("Aborting sendArpRequest, we cannot get all the information needed");
            return;
        }
        /*
         * Creates the request.
         */
        Ethernet arpRequest = ARP.buildArpRequest(
                senderMacAddress,
                senderIpAddress,
                targetAddress.toOctets(),
                VlanId.NO_VID
        );
        flood(arpRequest, inPort, targetAddress);
    }

}
