/*
 * Copyright 2016 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.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.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.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.PacketService;
import org.onosproject.routing.config.BgpConfig;

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

import static com.google.common.base.Preconditions.checkArgument;
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;

public class SdxL3ArpHandler {

    private static final String REQUEST_NULL = "ARP or NDP request cannot be null.";
    private static final String MSG_NOT_REQUEST = "Message is not an ARP or NDP request";

    private BgpConfig bgpConfig;
    private EdgePortService edgeService;
    private HostService hostService;
    private PacketService packetService;
    private InterfaceService interfaceService;

    private enum Protocol {
        ARP, NDP
    }

    private enum MessageType {
        REQUEST, REPLY
    }

    /**
     * Creates an ArpHandler object.
     *
     */
    public SdxL3ArpHandler(BgpConfig bgpConfig,
                           EdgePortService edgeService,
                           HostService hostService,
                           PacketService packetService,
                           InterfaceService interfaceService) {
        this.bgpConfig = bgpConfig;
        this.edgeService = edgeService;
        this.hostService = hostService;
        this.packetService = packetService;
        this.interfaceService = interfaceService;
    }

    /**
     * Processes incoming ARP packets.
     *
     * @param pkt incoming packet
     */
    public 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) {
            replyInternal(context);
        }
    }

    /**
     * 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 replyInternal(MessageContext context) {
        checkNotNull(context);
        checkArgument(context.type() == MessageType.REQUEST, MSG_NOT_REQUEST);

        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.ipAddresses()
                            .stream()
                            .anyMatch(ia -> ia.ipAddress().equals(context.target())))
                    .forEach(intf -> buildAndSendReply(context, intf.mac()));

            if (!isPeerAddress(context.sender()) || !isPeerAddress(context.target())) {
                // 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()));

        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 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.ipAddresses().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.ipAddresses().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.ipAddresses().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();
    }

    /**
     * Flood 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 = null;

        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;
        }
    }

}
