/*
 * Copyright 2016-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.sdxl3;

import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.onlab.packet.ARP;
import org.onlab.packet.Ethernet;
import org.onlab.packet.ICMP6;
import org.onlab.packet.IPv6;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.Ip6Address;
import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onlab.packet.ndp.NeighborAdvertisement;
import org.onlab.packet.ndp.NeighborDiscoveryOptions;
import org.onlab.packet.ndp.NeighborSolicitation;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.incubator.net.intf.Interface;
import org.onosproject.incubator.net.intf.InterfaceService;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.Host;
import org.onosproject.net.config.NetworkConfigService;
import org.onosproject.net.edge.EdgePortService;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.host.HostService;
import org.onosproject.net.packet.DefaultOutboundPacket;
import org.onosproject.net.packet.InboundPacket;
import org.onosproject.net.packet.PacketContext;
import org.onosproject.net.packet.PacketProcessor;
import org.onosproject.net.packet.PacketService;
import org.onosproject.routing.RoutingService;
import org.onosproject.routing.config.BgpConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

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

import static com.google.common.base.Preconditions.checkNotNull;
import static org.onosproject.net.HostId.hostId;
import static org.onosproject.security.AppGuard.checkPermission;
import static org.onosproject.security.AppPermission.Type.PACKET_WRITE;

/**
 * Proxy-ARP functionality adapted to SDX-L3.
 */
@Component(immediate = true, enabled = false)
public class SdxL3ArpHandler {
    private static final String REQUEST_NULL = "ARP or NDP request cannot be null.";

    private Logger log = LoggerFactory.getLogger(getClass());

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected CoreService coreService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected InterfaceService interfaceService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected EdgePortService edgeService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected HostService hostService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected PacketService packetService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected NetworkConfigService networkConfigService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected SdxL3PeerService sdxL3PeerService;

    private BgpConfig bgpConfig;
    private InternalPacketProcessor processor = null;

    private enum Protocol {
        ARP, NDP
    }

    private enum MessageType {
        REQUEST, REPLY
    }

    @Activate
    public void activate() {
        ApplicationId routerAppId = coreService.getAppId(RoutingService.ROUTER_APP_ID);
        bgpConfig = networkConfigService.getConfig(routerAppId, RoutingService.CONFIG_CLASS);
        processor = new InternalPacketProcessor();
        packetService.addProcessor(processor, PacketProcessor.director(2));
        log.info("Started");
    }

    @Deactivate
    public void deactivate() {
        packetService.removeProcessor(processor);
        log.info("Stopped");
    }

    /**
     * Processes incoming ARP packets.
     *
     * @param pkt incoming packet
     */
    protected void processPacketIn(InboundPacket pkt) {
        checkPermission(PACKET_WRITE);

        Ethernet eth = pkt.parsed();
        checkNotNull(eth, REQUEST_NULL);

        ConnectPoint inPort = pkt.receivedFrom();
        MessageContext context = createContext(eth, inPort);
        if (context != null) {
            if (context.type() == MessageType.REQUEST) {
                handleRequest(context);
            } else if (context.type() == MessageType.REPLY) {
                handleReply(context);
            }
        }
    }

    /**
     * Handles a reply message only in the case it concerns a reply from an
     * internal speaker to external peer where VLAN translation is necessary.
     *
     * @param context reply message context to process
     */
    private void handleReply(MessageContext context) {
        if (fromPeerToSpeaker(context)) {
            translateVlanAndSendToSpeaker(context);
        } else if (fromPeerToPeer(context)) {
            translateVlanAndSendToPeer(context);
        }
    }

    private boolean fromPeerToSpeaker(MessageContext context) {
        return sdxL3PeerService != null &&
                isPeerAddress(context.sender()) &&
                !interfaceService.getInterfacesByIp(context.target()).isEmpty();
    }

    /**
     * Makes the VLAN translation if necessary and sends the packet at the port
     * configured for the speaker.
     *
     * @param context reply message context to process
     */
    private void translateVlanAndSendToSpeaker(MessageContext context) {
        BgpConfig.BgpSpeakerConfig speaker =
                bgpConfig.getSpeakerFromPeer(context.sender());
        if (speaker != null) {
            Interface peeringInterface = sdxL3PeerService.getInterfaceForPeer(context.sender());
            if (context.vlan().equals(peeringInterface.vlan())) {
                context.setVlan(speaker.vlan());
                sendTo(context.packet(), speaker.connectPoint());
            }
        }
    }

    /**
     * Makes the VLAN translation if necessary and sends the packet at the port
     * configured for the peer.
     *
     * @param context reply message context to process
     */
    private void translateVlanAndSendToPeer(MessageContext context) {
        Interface interfaceForPeer = sdxL3PeerService.getInterfaceForPeer(context.target());
        if (interfaceForPeer != null) {
            context.setVlan(interfaceForPeer.vlan());
            sendTo(context.packet(), interfaceForPeer.connectPoint());
        }
    }

    /**
     * Handles a request message also when it concerns an SDX peering address.
     *
     * If the MAC address of the target is known, we can reply directly to the
     * requestor. Otherwise, we forward the request out other ports in an
     * attempt to find the correct host.
     *
     * @param context request message context to process
     */
    private void handleRequest(MessageContext context) {
        if (hasIpAddress(context.inPort())) {
            // If the request came from outside the network, only reply if it was
            // for one of our external addresses.

            interfaceService.getInterfacesByPort(context.inPort())
                    .stream()
                    .filter(intf -> intf.ipAddressesList()
                            .stream()
                            .anyMatch(ia -> ia.ipAddress().equals(context.target())))
                    .forEach(intf -> buildAndSendReply(context, intf.mac()));

            if (!fromPeerToPeer(context)) {
                // Only care about requests from/towards external BGP peers
                return;
            }
        }

        // See if we have the target host in the host store
        Set<Host> hosts = hostService.getHostsByIp(context.target());

        Host dst = null;
        Host src = hostService.getHost(hostId(context.srcMac(), context.vlan()));

        // If the request concerns an external BGP peer address and an internal
        // BGP speaker or is between external BGP peers, VLAN translation may be
        // necessary on the ARP request.
        if (fromSpeakerToPeer(context) || fromPeerToPeer(context)) {
            translateVlanAndSendToPeer(context);
            return;
        }

        for (Host host : hosts) {
            if (host.vlan().equals(context.vlan())) {
                dst = host;
                break;
            }
        }

        if (src != null && dst != null) {
            // We know the target host so we can respond
            buildAndSendReply(context, dst.mac());
            return;
        }

        // If the source address matches one of our external addresses
        // it could be a request from an internal host to an external
        // address. Forward it over to the correct connectPoint.
        boolean matched = false;
        Set<Interface> interfaces = interfaceService.getInterfacesByIp(context.sender());
        for (Interface intf : interfaces) {
            if (intf.vlan().equals(context.vlan())) {
                matched = true;
                sendTo(context.packet(), intf.connectPoint());
                break;
            }
        }

        if (matched) {
            return;
        }

        // If the packets has a vlanId look if there are some other
        // interfaces in the configuration on the same vlan and broadcast
        // the packet out just of through those interfaces.
        VlanId vlanId = context.vlan();

        Set<Interface> filteredVlanInterfaces =
                filterVlanInterfacesNoIp(interfaceService.getInterfacesByVlan(vlanId));

        if (vlanId != null
                && !vlanId.equals(VlanId.NONE)
                && confContainsVlans(vlanId, context.inPort())) {
            vlanFlood(context.packet(), filteredVlanInterfaces, context.inPort);
            return;
        }

        // The request couldn't be resolved.
        // Flood the request on all ports except the incoming connectPoint.
        flood(context.packet(), context.inPort());
    }

    private boolean fromPeerToPeer(MessageContext context) {
        return isPeerAddress(context.sender()) && isPeerAddress(context.target());
    }

    private boolean fromSpeakerToPeer(MessageContext context) {
        return sdxL3PeerService != null &&
                isPeerAddress(context.target()) &&
                !interfaceService.getInterfacesByIp(context.sender()).isEmpty();
    }

    /**
     * Makes the VLAN translation if necessary on the packet.
     *
     * @param context request message context to process
     */
    private VlanId getDestinationPeerVlan(MessageContext context) {
        return sdxL3PeerService.getInterfaceForPeer(context.target()).vlan();
    }

    /**
     * Controls whether an IP address is configured for an external peer.
     *
     * @param ip the examined IP address
     * @return result of the control
     */
    private boolean isPeerAddress(IpAddress ip) {
        return bgpConfig.bgpSpeakers()
                .stream()
                .flatMap(speaker -> speaker.peers().stream())
                .anyMatch(peerAddress -> peerAddress.equals(ip));
    }

    private Set<Interface> filterVlanInterfacesNoIp(Set<Interface> vlanInterfaces) {
        return vlanInterfaces
                .stream()
                .filter(intf -> intf.ipAddressesList().isEmpty())
                .collect(Collectors.toSet());
    }

    /**
     * States if the interface configuration contains more than one interface configured
     * on a specific vlan, including the interface passed as argument.
     *
     * @param vlanId the vlanid to look for in the interface configuration
     * @param connectPoint the connect point to exclude from the search
     * @return true if interfaces are found. False otherwise
     */
    private boolean confContainsVlans(VlanId vlanId, ConnectPoint connectPoint) {
        Set<Interface> vlanInterfaces = interfaceService.getInterfacesByVlan(vlanId);
        return interfaceService.getInterfacesByVlan(vlanId)
                .stream()
                .anyMatch(intf -> intf.connectPoint().equals(connectPoint) &&
                        intf.ipAddressesList().isEmpty())
                && vlanInterfaces.size() > 1;
    }

    /**
     * Builds and sends a reply message given a request context and the resolved
     * MAC address to answer with.
     *
     * @param context message context of request
     * @param targetMac MAC address to be given in the response
     */
    private void buildAndSendReply(MessageContext context, MacAddress targetMac) {
        switch (context.protocol()) {
            case ARP:
                sendTo(ARP.buildArpReply((Ip4Address) context.target(),
                        targetMac, context.packet()), context.inPort());
                break;
            case NDP:
                sendTo(buildNdpReply((Ip6Address) context.target(), targetMac,
                        context.packet()), context.inPort());
                break;
            default:
                break;
        }
    }

    /**
     * Outputs a packet out a specific connectPoint.
     *
     * @param packet  the packet to send
     * @param outPort the connectPoint to send it out
     */
    private void sendTo(Ethernet packet, ConnectPoint outPort) {
        sendTo(outPort, ByteBuffer.wrap(packet.serialize()));
    }

    /**
     * Outputs a packet out a specific connectPoint.
     *
     * @param outPort connectPoint to send it out
     * @param packet packet to send
     */
    private void sendTo(ConnectPoint outPort, ByteBuffer packet) {
        if (!edgeService.isEdgePoint(outPort)) {
            // Sanity check to make sure we don't send the packet out an
            // internal connectPoint and create a loop (could happen due to
            // misconfiguration).
            return;
        }

        TrafficTreatment.Builder builder = DefaultTrafficTreatment.builder();
        builder.setOutput(outPort.port());
        packetService.emit(new DefaultOutboundPacket(outPort.deviceId(),
                builder.build(), packet));
    }

    /**
     * Returns whether the given connectPoint has any IP addresses configured or not.
     *
     * @param connectPoint the connectPoint to check
     * @return true if the connectPoint has at least one IP address configured,
     * false otherwise
     */
    private boolean hasIpAddress(ConnectPoint connectPoint) {
        return interfaceService.getInterfacesByPort(connectPoint)
                .stream()
                .flatMap(intf -> intf.ipAddressesList().stream())
                .findAny()
                .isPresent();
    }

    /**
     * Returns whether the given connectPoint has any VLAN configured or not.
     *
     * @param connectPoint the connectPoint to check
     * @return true if the connectPoint has at least one VLAN configured,
     * false otherwise
     */
    private boolean hasVlan(ConnectPoint connectPoint) {
        return interfaceService.getInterfacesByPort(connectPoint)
                .stream()
                .filter(intf -> !intf.vlan().equals(VlanId.NONE))
                .findAny()
                .isPresent();
    }

    /**
     * Floods the arp request at all edges on a specifc VLAN.
     *
     * @param request the arp request
     * @param dsts the destination interfaces
     * @param inPort the connect point the arp request was received on
     */
    private void vlanFlood(Ethernet request, Set<Interface> dsts, ConnectPoint inPort) {
        TrafficTreatment.Builder builder = null;
        ByteBuffer buf = ByteBuffer.wrap(request.serialize());

        for (Interface intf : dsts) {
            ConnectPoint cPoint = intf.connectPoint();
            if (cPoint.equals(inPort)) {
                continue;
            }

            builder = DefaultTrafficTreatment.builder();
            builder.setOutput(cPoint.port());
            packetService.emit(new DefaultOutboundPacket(cPoint.deviceId(),
                    builder.build(), buf));
        }
    }

    /**
     * Flood the arp request at all edges in the network.
     *
     * @param request the arp request
     * @param inPort  the connect point the arp request was received on
     */
    private void flood(Ethernet request, ConnectPoint inPort) {
        TrafficTreatment.Builder builder = null;
        ByteBuffer buf = ByteBuffer.wrap(request.serialize());

        for (ConnectPoint connectPoint : edgeService.getEdgePoints()) {
            if (hasIpAddress(connectPoint)
                    || hasVlan(connectPoint)
                    || connectPoint.equals(inPort)) {
                continue;
            }

            builder = DefaultTrafficTreatment.builder();
            builder.setOutput(connectPoint.port());
            packetService.emit(new DefaultOutboundPacket(connectPoint.deviceId(),
                    builder.build(), buf));
        }
    }

    /**
     * Builds an Neighbor Discovery reply based on a request.
     *
     * @param srcIp   the IP address to use as the reply source
     * @param srcMac  the MAC address to use as the reply source
     * @param request the Neighbor Solicitation request we got
     * @return an Ethernet frame containing the Neighbor Advertisement reply
     */
    private Ethernet buildNdpReply(Ip6Address srcIp, MacAddress srcMac,
                                   Ethernet request) {
        Ethernet eth = new Ethernet();
        eth.setDestinationMACAddress(request.getSourceMAC());
        eth.setSourceMACAddress(srcMac);
        eth.setEtherType(Ethernet.TYPE_IPV6);
        eth.setVlanID(request.getVlanID());

        IPv6 requestIp = (IPv6) request.getPayload();
        IPv6 ipv6 = new IPv6();
        ipv6.setSourceAddress(srcIp.toOctets());
        ipv6.setDestinationAddress(requestIp.getSourceAddress());
        ipv6.setHopLimit((byte) 255);

        ICMP6 icmp6 = new ICMP6();
        icmp6.setIcmpType(ICMP6.NEIGHBOR_ADVERTISEMENT);
        icmp6.setIcmpCode((byte) 0);

        NeighborAdvertisement nadv = new NeighborAdvertisement();
        nadv.setTargetAddress(srcIp.toOctets());
        nadv.setSolicitedFlag((byte) 1);
        nadv.setOverrideFlag((byte) 1);
        nadv.addOption(NeighborDiscoveryOptions.TYPE_TARGET_LL_ADDRESS,
                srcMac.toBytes());

        icmp6.setPayload(nadv);
        ipv6.setPayload(icmp6);
        eth.setPayload(ipv6);
        return eth;
    }

    /**
     * Attempts to create a MessageContext for the given Ethernet frame. If the
     * frame is a valid ARP or NDP request or response, a context will be
     * created.
     *
     * @param eth input Ethernet frame
     * @param inPort in connectPoint
     * @return MessageContext if the packet was ARP or NDP, otherwise null
     */
    private MessageContext createContext(Ethernet eth, ConnectPoint inPort) {
        if (eth.getEtherType() == Ethernet.TYPE_ARP) {
            return createArpContext(eth, inPort);
        } else if (eth.getEtherType() == Ethernet.TYPE_IPV6) {
            return createNdpContext(eth, inPort);
        }

        return null;
    }

    /**
     * Extracts context information from ARP packets.
     *
     * @param eth input Ethernet frame that is thought to be ARP
     * @param inPort in connectPoint
     * @return MessageContext object if the packet was a valid ARP packet,
     * otherwise null
     */
    private MessageContext createArpContext(Ethernet eth, ConnectPoint inPort) {
        if (eth.getEtherType() != Ethernet.TYPE_ARP) {
            return null;
        }

        ARP arp = (ARP) eth.getPayload();

        IpAddress target = Ip4Address.valueOf(arp.getTargetProtocolAddress());
        IpAddress sender = Ip4Address.valueOf(arp.getSenderProtocolAddress());

        MessageType type;
        if (arp.getOpCode() == ARP.OP_REQUEST) {
            type = MessageType.REQUEST;
        } else if (arp.getOpCode() == ARP.OP_REPLY) {
            type = MessageType.REPLY;
        } else {
            return null;
        }

        return new MessageContext(eth, inPort, Protocol.ARP, type, target, sender);
    }

    /**
     * Extracts context information from NDP packets.
     *
     * @param eth input Ethernet frame that is thought to be NDP
     * @param inPort in connectPoint
     * @return MessageContext object if the packet was a valid NDP packet,
     * otherwise null
     */
    private MessageContext createNdpContext(Ethernet eth, ConnectPoint inPort) {
        if (eth.getEtherType() != Ethernet.TYPE_IPV6) {
            return null;
        }
        IPv6 ipv6 = (IPv6) eth.getPayload();

        if (ipv6.getNextHeader() != IPv6.PROTOCOL_ICMP6) {
            return null;
        }
        ICMP6 icmpv6 = (ICMP6) ipv6.getPayload();

        IpAddress sender = Ip6Address.valueOf(ipv6.getSourceAddress());
        IpAddress target = Ip6Address.valueOf(ipv6.getDestinationAddress());

        MessageType type;
        if (icmpv6.getIcmpType() == ICMP6.NEIGHBOR_SOLICITATION) {
            type = MessageType.REQUEST;
            NeighborSolicitation nsol = (NeighborSolicitation) icmpv6.getPayload();
            target = Ip6Address.valueOf(nsol.getTargetAddress());
        } else if (icmpv6.getIcmpType() == ICMP6.NEIGHBOR_ADVERTISEMENT) {
            type = MessageType.REPLY;
        } else {
            return null;
        }

        return new MessageContext(eth, inPort, Protocol.NDP, type, target, sender);
    }

    /**
     * Provides context information for a particular ARP or NDP message, with
     * a unified interface to access data regardless of protocol.
     */
    private class MessageContext {
        private Protocol protocol;
        private MessageType type;

        private IpAddress target;
        private IpAddress sender;

        private Ethernet eth;
        private ConnectPoint inPort;


        public MessageContext(Ethernet eth, ConnectPoint inPort,
                              Protocol protocol, MessageType type,
                              IpAddress target, IpAddress sender) {
            this.eth = eth;
            this.inPort = inPort;
            this.protocol = protocol;
            this.type = type;
            this.target = target;
            this.sender = sender;
        }

        public ConnectPoint inPort() {
            return inPort;
        }

        public Ethernet packet() {
            return eth;
        }

        public Protocol protocol() {
            return protocol;
        }

        public MessageType type() {
            return type;
        }

        public VlanId vlan() {
            return VlanId.vlanId(eth.getVlanID());
        }

        public MacAddress srcMac() {
            return MacAddress.valueOf(eth.getSourceMACAddress());
        }

        public IpAddress target() {
            return target;
        }

        public IpAddress sender() {
            return sender;
        }

        public void setVlan(VlanId vlanId) {
            this.eth.setVlanID(vlanId.toShort());
        }
    }

    private class InternalPacketProcessor implements PacketProcessor {
        @Override
        public void process(PacketContext context) {

            if (context.isHandled()) {
                return;
            }

            InboundPacket pkt = context.inPacket();
            Ethernet ethernet = pkt.parsed();
            if (ethernet.getEtherType() == Ethernet.TYPE_ARP) {
                processPacketIn(pkt);
            }
        }
    }

}
