/*
 * Copyright 2017-present Open Networking Foundation
 *
 * 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.dhcprelay;

import org.onlab.packet.BasePacket;
import org.onlab.packet.DHCP6;
import org.onlab.packet.DHCP6.MsgType;
import org.onlab.packet.Ip6Address;
import org.onlab.packet.IpAddress;
import org.onlab.packet.VlanId;
import org.onlab.packet.dhcp.Dhcp6ClientIdOption;
import org.onlab.packet.dhcp.Dhcp6RelayOption;
import org.onlab.packet.dhcp.Dhcp6Option;

import org.onlab.packet.Ethernet;
import org.onlab.packet.IPv6;
import org.onlab.packet.MacAddress;
import org.onlab.packet.UDP;

import org.onlab.util.HexString;
import org.onosproject.dhcprelay.api.DhcpServerInfo;
import org.onosproject.dhcprelay.store.DhcpRelayCounters;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.host.InterfaceIpAddress;
import org.onosproject.net.intf.Interface;
import org.onosproject.net.packet.PacketContext;
import org.onosproject.net.DeviceId;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Set;
import java.util.List;
import java.util.ArrayList;
import org.onosproject.net.intf.InterfaceService;

import org.onosproject.net.Host;
import org.onosproject.net.host.HostService;
import org.onosproject.net.HostLocation;

import static com.google.common.base.Preconditions.checkNotNull;

public final class Dhcp6HandlerUtil {

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

    private Dhcp6HandlerUtil() {
    }

    // Returns the first v6 interface ip out of a set of interfaces or null.
    // Checks all interfaces, and ignores v6 interface ips
    public static Ip6Address getRelayAgentIPv6Address(Set<Interface> intfs) {
        for (Interface intf : intfs) {
            for (InterfaceIpAddress ip : intf.ipAddressesList()) {
                Ip6Address relayAgentIp = ip.ipAddress().getIp6Address();
                if (relayAgentIp != null) {
                    return relayAgentIp;
                }
            }
        }
        return null;
    }

    /**
     * Returns the first interface ip from interface.
     *
     * @param iface interface of one connect point
     * @return the first interface IP; null if not exists an IP address in
     *         these interfaces
     */
    private static Ip6Address getFirstIpFromInterface(Interface iface) {
        checkNotNull(iface, "Interface can't be null");
        return iface.ipAddressesList().stream()
                .map(InterfaceIpAddress::ipAddress)
                .filter(IpAddress::isIp6)
                .map(IpAddress::getIp6Address)
                .findFirst()
                .orElse(null);
    }
    /**
     *
     * process the LQ reply packet from dhcp server.
     *
     * @param defaultServerInfoList default server list
     * @param indirectServerInfoList default indirect server list
     * @param serverInterface server interface
     * @param interfaceService interface service
     * @param hostService host service
     * @param context packet context
     * @param receivedPacket server ethernet packet
     * @param recevingInterfaces set of server side interfaces
     * @return a packet ready to be sent to relevant output interface
     */
    public static InternalPacket processLQ6PacketFromServer(
            List<DhcpServerInfo> defaultServerInfoList,
            List<DhcpServerInfo> indirectServerInfoList,
            Interface serverInterface,
            InterfaceService interfaceService,
            HostService hostService,
            PacketContext context,
            Ethernet receivedPacket, Set<Interface> recevingInterfaces) {
        // get dhcp6 header.
        Ethernet etherReply = (Ethernet) receivedPacket.clone();
        IPv6 ipv6Packet = (IPv6) etherReply.getPayload();
        UDP udpPacket = (UDP) ipv6Packet.getPayload();
        DHCP6 lq6Reply = (DHCP6) udpPacket.getPayload();

        // TODO: refactor
        ConnectPoint receivedFrom = context.inPacket().receivedFrom();
        DeviceId receivedFromDevice = receivedFrom.deviceId();
        DhcpServerInfo serverInfo;
        Ip6Address dhcpServerIp = null;
        ConnectPoint dhcpServerConnectPoint = null;
        MacAddress dhcpConnectMac = null;
        VlanId dhcpConnectVlan = null;
        Ip6Address dhcpGatewayIp = null;

        // todo: refactor
        Ip6Address indirectDhcpServerIp = null;
        ConnectPoint indirectDhcpServerConnectPoint = null;
        MacAddress indirectDhcpConnectMac = null;
        VlanId indirectDhcpConnectVlan = null;
        Ip6Address indirectDhcpGatewayIp = null;
        Ip6Address indirectRelayAgentIpFromCfg = null;

        if (!defaultServerInfoList.isEmpty()) {
            serverInfo = defaultServerInfoList.get(0);
            dhcpConnectMac = serverInfo.getDhcpConnectMac().orElse(null);
            dhcpGatewayIp = serverInfo.getDhcpGatewayIp6().orElse(null);
            dhcpServerIp = serverInfo.getDhcpServerIp6().orElse(null);
            dhcpServerConnectPoint = serverInfo.getDhcpServerConnectPoint().orElse(null);
            dhcpConnectVlan = serverInfo.getDhcpConnectVlan().orElse(null);
        }

        if (!indirectServerInfoList.isEmpty()) {
            serverInfo = indirectServerInfoList.get(0);
            indirectDhcpConnectMac = serverInfo.getDhcpConnectMac().orElse(null);
            indirectDhcpGatewayIp = serverInfo.getDhcpGatewayIp6().orElse(null);
            indirectDhcpServerIp = serverInfo.getDhcpServerIp6().orElse(null);
            indirectDhcpServerConnectPoint = serverInfo.getDhcpServerConnectPoint().orElse(null);
            indirectDhcpConnectVlan = serverInfo.getDhcpConnectVlan().orElse(null);
            indirectRelayAgentIpFromCfg = serverInfo.getRelayAgentIp6(receivedFromDevice).orElse(null);
        }

        Boolean directConnFlag = directlyConnected(lq6Reply);
        ConnectPoint inPort = context.inPacket().receivedFrom();
        if ((directConnFlag || indirectDhcpServerIp == null)
                && !inPort.equals(dhcpServerConnectPoint)) {
            log.warn("Receiving port {} is not the same as server connect point {} for direct or indirect-null",
                    inPort, dhcpServerConnectPoint);
            return null;
        }

        if (!directConnFlag && indirectDhcpServerIp != null &&
                !inPort.equals(indirectDhcpServerConnectPoint)) {
            log.warn("Receiving port {} is not the same as server connect point {} for indirect",
                    inPort, indirectDhcpServerConnectPoint);
            return null;
        }


        Ip6Address nextHopIP =  Ip6Address.valueOf(ipv6Packet.getDestinationAddress());
        // use hosts store to find out the next hop mac and connection point
        Set<Host> hosts = hostService.getHostsByIp(nextHopIP);
        Host host;
        if (!hosts.isEmpty()) {
            host = hosts.iterator().next();
        } else {
            log.warn("Host {} is not in store", nextHopIP);
            return null;
        }

        HostLocation hl = host.location();
        String clientConnectionPointStr = hl.toString(); // iterator().next());
        ConnectPoint clientConnectionPoint = ConnectPoint.deviceConnectPoint(clientConnectionPointStr);


        VlanId originalPacketVlanId = VlanId.vlanId(etherReply.getVlanID());
        Interface iface;
        iface = interfaceService.getInterfacesByPort(clientConnectionPoint)
                .stream()
                .filter(iface1 -> interfaceContainsVlan(iface1, originalPacketVlanId))
                .findFirst()
                .orElse(null);

        etherReply.setSourceMACAddress(iface.mac());
        etherReply.setDestinationMACAddress(host.mac());

        // workaround for a bug where core sends src port as 547 (server)
        udpPacket.setDestinationPort(UDP.DHCP_V6_SERVER_PORT);
        udpPacket.setPayload(lq6Reply);
        udpPacket.resetChecksum();
        ipv6Packet.setPayload(udpPacket);
        etherReply.setPayload(ipv6Packet);

        return InternalPacket.internalPacket(etherReply, clientConnectionPoint);
    }

    /**
     * extract DHCP6 payload from dhcp6 relay message within relay-forwrd/reply.
     *
     * @param dhcp6 dhcp6 relay-reply or relay-forward
     * @return dhcp6Packet dhcp6 packet extracted from relay-message
     */
    public static DHCP6 dhcp6PacketFromRelayPacket(DHCP6 dhcp6) {

        // extract the relay message if exist
        DHCP6 dhcp6Payload = dhcp6.getOptions().stream()
                .filter(opt -> opt instanceof Dhcp6RelayOption)
                .map(BasePacket::getPayload)
                .map(pld -> (DHCP6) pld)
                .findFirst()
                .orElse(null);
        if (dhcp6Payload == null) {
            // Can't find dhcp payload
            log.debug("Can't find dhcp6 payload from relay message");
        } else {
            log.debug("dhcp6 payload found from relay message {}", dhcp6Payload);
        }
        return dhcp6Payload;
    }

    /**
     * find the leaf DHCP6 packet from multi-level relay packet.
     *
     * @param relayPacket dhcp6 relay packet
     * @return leafPacket non-relay dhcp6 packet
     */
    public static DHCP6 getDhcp6Leaf(DHCP6 relayPacket) {
        DHCP6 dhcp6Parent = relayPacket;
        DHCP6 dhcp6Child = null;

        log.debug("getDhcp6Leaf entered.");
        while (dhcp6Parent != null) {
            dhcp6Child = dhcp6PacketFromRelayPacket(dhcp6Parent);
            if (dhcp6Child != null) {
                if (dhcp6Child.getMsgType() != DHCP6.MsgType.RELAY_FORW.value() &&
                        dhcp6Child.getMsgType() != DHCP6.MsgType.RELAY_REPL.value()) {
                    log.debug("leaf dhcp6 packet found.");
                    break;
                } else {
                    // found another relay, go for another loop
                    dhcp6Parent = dhcp6Child;
                }
            } else {
                log.debug("Expected dhcp6 within relay pkt, but no dhcp6 leaf found.");
                break;
            }
        }
        return dhcp6Child;
    }

    /**
     * Determine DHCP message type (direct DHCPv6 or wrapped into relay messages).
     *
     * @param relayPacket {@link DHCP6} packet to be parsed
     * @return {@link DHCP6.MsgType} contained message type of dhcpv6 packet/relay-message
     */
    public static DHCP6.MsgType getDhcp6LeafMessageType(DHCP6 relayPacket) {
        checkNotNull(relayPacket);
        DHCP6 dhcp6Child = getDhcp6Leaf(relayPacket);
        return DHCP6.MsgType.getType(dhcp6Child != null ? dhcp6Child.getMsgType() : relayPacket.getMsgType());
    }

    /**
     * check if DHCP6 relay-reply is reply.
     *
     * @param relayPacket dhcp6 relay-reply
     * @return boolean relay-reply contains ack
     */
    public static boolean isDhcp6Reply(DHCP6 relayPacket) {
        DHCP6 leafDhcp6 = getDhcp6Leaf(relayPacket);
        if (leafDhcp6 != null) {
            if (leafDhcp6.getMsgType() == DHCP6.MsgType.REPLY.value()) {
                log.debug("isDhcp6Reply  true.");
                return true;  // must be directly connected
            } else {
                log.debug("isDhcp6Reply false. leaf dhcp6 is not replay. MsgType {}", leafDhcp6.getMsgType());
            }
        } else {
            log.debug("isDhcp6Reply false. Expected dhcp6 within relay pkt but not found.");
        }
        log.debug("isDhcp6Reply  false.");
        return false;
    }

    /**
     * check if DHCP6 is release or relay-forward contains release.
     *
     * @param dhcp6Payload dhcp6 packet
     * @return boolean dhcp6 contains release
     */
    public static  boolean isDhcp6Release(DHCP6 dhcp6Payload) {
        if (dhcp6Payload.getMsgType() ==  DHCP6.MsgType.RELEASE.value()) {
            log.debug("isDhcp6Release  true.");
            return true;  // must be directly connected
        } else {
            DHCP6 dhcp6Leaf = getDhcp6Leaf(dhcp6Payload);
            if (dhcp6Leaf != null) {
                if (dhcp6Leaf.getMsgType() ==  DHCP6.MsgType.RELEASE.value()) {
                    log.debug("isDhcp6Release  true. indirectlry connected");
                    return true;
                } else {
                    log.debug("leaf dhcp6 is not release. MsgType {}",  dhcp6Leaf.getMsgType());
                    return false;
                }
            } else {
                log.debug("isDhcp6Release  false. dhcp6 is niether relay nor release.");
                return false;
            }
        }
    }


    /**
     * convert dhcp6 msgType to String.
     *
     * @param msgTypeVal msgType byte of dhcp6 packet
     * @return String string value of dhcp6 msg type
     */
    public static String getMsgTypeStr(byte msgTypeVal) {
        MsgType msgType = DHCP6.MsgType.getType(msgTypeVal);
        return DHCP6.MsgType.getMsgTypeStr(msgType);
    }

    /**
     * find the string of dhcp6 leaf packets's msg type.
     *
     * @param directConnFlag boolean value indicating direct/indirect connection
     * @param dhcp6Packet dhcp6 packet
     * @return String string value of dhcp6 leaf packet msg type
     */
    public static String findLeafMsgType(boolean directConnFlag, DHCP6  dhcp6Packet) {
        if (directConnFlag) {
            return getMsgTypeStr(dhcp6Packet.getMsgType());
        } else {
            DHCP6 leafDhcp = getDhcp6Leaf(dhcp6Packet);
            if (leafDhcp != null) {
                return getMsgTypeStr(leafDhcp.getMsgType());
            } else {
                return DhcpRelayCounters.INVALID_PACKET;
            }
        }
    }

    /**
     * Determind if an Interface contains a vlan id.
     *
     * @param iface the Interface
     * @param vlanId the vlan id
     * @return true if the Interface contains the vlan id
     */
    public static boolean interfaceContainsVlan(Interface iface, VlanId vlanId) {
        if (vlanId.equals(VlanId.NONE)) {
            // untagged packet, check if vlan untagged or vlan native is not NONE
            return !iface.vlanUntagged().equals(VlanId.NONE) ||
                    !iface.vlanNative().equals(VlanId.NONE);
        }
        // tagged packet, check if the interface contains the vlan
        return iface.vlanTagged().contains(vlanId);
    }

    /**
     * Check if the host is directly connected to the network or not.
     *
     * @param dhcp6Payload the dhcp6 payload
     * @return true if the host is directly connected to the network; false otherwise
     */
    public static boolean directlyConnected(DHCP6 dhcp6Payload) {

        log.debug("directlyConnected enters");
        if (dhcp6Payload.getMsgType() == DHCP6.MsgType.LEASEQUERY.value() ||
                dhcp6Payload.getMsgType() == DHCP6.MsgType.LEASEQUERY_REPLY.value()) {
            log.debug("directlyConnected false. MsgType {}", dhcp6Payload.getMsgType());

            return false;
        }

        if (dhcp6Payload.getMsgType() != DHCP6.MsgType.RELAY_FORW.value() &&
                dhcp6Payload.getMsgType() != DHCP6.MsgType.RELAY_REPL.value()) {
            log.debug("directlyConnected true. MsgType {}", dhcp6Payload.getMsgType());

            return true;
        }
        // Regardless of relay-forward or relay-replay, check if we see another relay message
        DHCP6 dhcp6Payload2 = dhcp6PacketFromRelayPacket(dhcp6Payload);
        if (dhcp6Payload2 != null) {
            if (dhcp6Payload.getMsgType() == DHCP6.MsgType.RELAY_FORW.value()) {
                log.debug("directlyConnected  false. 1st relay-forward, 2nd MsgType {}", dhcp6Payload2.getMsgType());
                return false;
            } else {
                // relay-reply
                if (dhcp6Payload2.getMsgType() != DHCP6.MsgType.RELAY_REPL.value()
                        && dhcp6Payload2.getMsgType() != MsgType.LEASEQUERY_REPLY.value()) {
                    log.debug("directlyConnected  true. 2nd MsgType {}", dhcp6Payload2.getMsgType());
                    return true;  // must be directly connected
                } else {
                    log.debug("directlyConnected  false. 1st relay-reply, 2nd relay-reply MsgType {}",
                            dhcp6Payload2.getMsgType());
                    return false;  // must be indirectly connected
                }
            }
        } else {
            log.debug("directlyConnected  true.");
            return true;
        }
    }
    /**
     * Check if a given server info has v6 ipaddress.
     *
     * @param serverInfo server info to check
     * @return true if server info has v6 ip address; false otherwise
     */
    public static boolean isServerIpEmpty(DhcpServerInfo serverInfo) {
        if (!serverInfo.getDhcpServerIp6().isPresent()) {
            log.warn("DhcpServerIp not available, use default DhcpServerIp {}",
                    HexString.toHexString(serverInfo.getDhcpServerIp6().get().toOctets()));
            return true;
        }
        return false;
    }

    private static boolean isConnectMacEmpty(DhcpServerInfo serverInfo, Set<Interface> clientInterfaces) {
        if (!serverInfo.getDhcpConnectMac().isPresent()) {
            log.warn("DHCP6 {} not yet resolved .. Aborting DHCP "
                            + "packet processing from client on port: {}",
                    !serverInfo.getDhcpGatewayIp6().isPresent() ? "server IP " + serverInfo.getDhcpServerIp6()
                            : "gateway IP " + serverInfo.getDhcpGatewayIp6(),
                    clientInterfaces.iterator().next().connectPoint());
            return true;
        }
        return false;
    }

    private static Dhcp6Option getInterfaceIdIdOption(PacketContext context, Ethernet clientPacket) {
        String inPortString = "-" + context.inPacket().receivedFrom().toString() + ":";
        Dhcp6Option interfaceId = new Dhcp6Option();
        interfaceId.setCode(DHCP6.OptionCode.INTERFACE_ID.value());
        byte[] clientSoureMacBytes = clientPacket.getSourceMACAddress();
        byte[] inPortStringBytes = inPortString.getBytes();
        byte[] vlanIdBytes = new byte[2];
        vlanIdBytes[0] = (byte) (clientPacket.getVlanID() & 0xff);
        vlanIdBytes[1] = (byte) ((clientPacket.getVlanID() >> 8) & 0xff);
        byte[] interfaceIdBytes = new byte[clientSoureMacBytes.length +
                inPortStringBytes.length + vlanIdBytes.length];
        log.debug("Length: interfaceIdBytes  {} clientSoureMacBytes {} inPortStringBytes {} vlan {}",
                interfaceIdBytes.length, clientSoureMacBytes.length, inPortStringBytes.length,
                vlanIdBytes.length);

        System.arraycopy(clientSoureMacBytes, 0, interfaceIdBytes, 0, clientSoureMacBytes.length);
        System.arraycopy(inPortStringBytes, 0, interfaceIdBytes, clientSoureMacBytes.length,
                inPortStringBytes.length);
        System.arraycopy(vlanIdBytes, 0, interfaceIdBytes,
                clientSoureMacBytes.length + inPortStringBytes.length,
                vlanIdBytes.length);
        interfaceId.setData(interfaceIdBytes);
        interfaceId.setLength((short) interfaceIdBytes.length);
        log.debug("interfaceId write srcMac {} portString {}",
                HexString.toHexString(clientSoureMacBytes, ":"), inPortString);
        return interfaceId;
    }

    private static void addDhcp6OptionsFromClient(List<Dhcp6Option> options, byte[] dhcp6PacketByte,
                                           PacketContext context, Ethernet clientPacket) {
        Dhcp6Option relayMessage = new Dhcp6Option();
        relayMessage.setCode(DHCP6.OptionCode.RELAY_MSG.value());
        relayMessage.setLength((short) dhcp6PacketByte.length);
        relayMessage.setData(dhcp6PacketByte);
        options.add(relayMessage);
        // create interfaceId option
        Dhcp6Option interfaceId = getInterfaceIdIdOption(context, clientPacket);
        options.add(interfaceId);
    }

    /**
     * build the DHCP6 solicit/request packet with gatewayip.
     *
     * @param context packet context
     * @param clientPacket client ethernet packet
     * @param clientInterfaces set of client side interfaces
     * @param serverInfo target server which a packet is generated for
     * @param serverInterface target server interface
     * @return ethernet packet with dhcp6 packet info
     */
    public static Ethernet buildDhcp6PacketFromClient(PacketContext context, Ethernet clientPacket,
                                               Set<Interface> clientInterfaces, DhcpServerInfo serverInfo,
                                               Interface serverInterface) {
        ConnectPoint receivedFrom = context.inPacket().receivedFrom();
        DeviceId receivedFromDevice = receivedFrom.deviceId();

        Ip6Address relayAgentIp = getRelayAgentIPv6Address(clientInterfaces);
        MacAddress relayAgentMac = clientInterfaces.iterator().next().mac();
        if (relayAgentIp == null || relayAgentMac == null) {
            log.warn("Missing DHCP relay agent interface Ipv6 addr config for "
                            + "packet from client on port: {}. Aborting packet processing",
                    clientInterfaces.iterator().next().connectPoint());
            return null;
        }
        IPv6 clientIpv6 = (IPv6) clientPacket.getPayload();
        UDP clientUdp = (UDP) clientIpv6.getPayload();
        DHCP6 clientDhcp6 = (DHCP6) clientUdp.getPayload();
        boolean directConnFlag = directlyConnected(clientDhcp6);

        Ip6Address serverIpFacing = getFirstIpFromInterface(serverInterface);
        if (serverIpFacing == null || serverInterface.mac() == null) {
            log.warn("No IP v6 address for server Interface {}", serverInterface);
            return null;
        }

        Ethernet etherReply = clientPacket.duplicate();
        etherReply.setSourceMACAddress(serverInterface.mac());

        // set default info and replace with indirect if available later on.
        if (serverInfo.getDhcpConnectMac().isPresent()) {
            etherReply.setDestinationMACAddress(serverInfo.getDhcpConnectMac().get());
        }
        if (serverInfo.getDhcpConnectVlan().isPresent()) {
            etherReply.setVlanID(serverInfo.getDhcpConnectVlan().get().toShort());
        }
        IPv6 ipv6Packet = (IPv6) etherReply.getPayload();
        byte[] peerAddress = clientIpv6.getSourceAddress();
        ipv6Packet.setSourceAddress(serverIpFacing.toOctets());
        ipv6Packet.setDestinationAddress(serverInfo.getDhcpServerIp6().get().toOctets());
        UDP udpPacket = (UDP) ipv6Packet.getPayload();
        udpPacket.setSourcePort(UDP.DHCP_V6_SERVER_PORT);
        DHCP6 dhcp6Packet = (DHCP6) udpPacket.getPayload();
        byte[] dhcp6PacketByte = dhcp6Packet.serialize();

        DHCP6 dhcp6Relay = new DHCP6();

        dhcp6Relay.setMsgType(DHCP6.MsgType.RELAY_FORW.value());

        if (directConnFlag) {
            dhcp6Relay.setLinkAddress(relayAgentIp.toOctets());
        } else {
            if (isServerIpEmpty(serverInfo)) {
                log.warn("indirect DhcpServerIp empty... use default server ");
            } else {
                // Indirect case, replace destination to indirect dhcp server if exist
                // Check if mac is obtained for valid server ip
                if (isConnectMacEmpty(serverInfo, clientInterfaces)) {
                    log.warn("indirect Dhcp ConnectMac empty ...");
                    return null;
                }
                etherReply.setDestinationMACAddress(serverInfo.getDhcpConnectMac().get());
                etherReply.setVlanID(serverInfo.getDhcpConnectVlan().get().toShort());
                ipv6Packet.setDestinationAddress(serverInfo.getDhcpServerIp6().get().toOctets());
            }
            if (!serverInfo.getRelayAgentIp6(receivedFromDevice).isPresent()) {
                log.debug("indirect connection: relayAgentIp NOT availale from config file! Use dynamic. {}",
                        HexString.toHexString(relayAgentIp.toOctets(), ":"));
                serverIpFacing = relayAgentIp;
            } else {
                serverIpFacing = serverInfo.getRelayAgentIp6(receivedFromDevice).get();
            }
            log.debug("Source IP address set as relay agent IP with value: {}", serverIpFacing);
            dhcp6Relay.setLinkAddress(serverIpFacing.toOctets());
            ipv6Packet.setSourceAddress(serverIpFacing.toOctets());
        }
        // peer address: address of the client or relay agent from which the message to be relayed was received.
        dhcp6Relay.setPeerAddress(peerAddress);
        // directly connected case, hop count is zero; otherwise, hop count + 1
        if (directConnFlag) {
            dhcp6Relay.setHopCount((byte) 0);
        } else {
            dhcp6Relay.setHopCount((byte) (dhcp6Packet.getHopCount() + 1));
        }

        List<Dhcp6Option> options = new ArrayList<>();
        addDhcp6OptionsFromClient(options, dhcp6PacketByte, context, clientPacket);
        dhcp6Relay.setOptions(options);
        udpPacket.setPayload(dhcp6Relay);
        udpPacket.resetChecksum();
        ipv6Packet.setPayload(udpPacket);
        ipv6Packet.setHopLimit((byte) 64);
        etherReply.setPayload(ipv6Packet);

        return etherReply;
    }

    /**
     * build the DHCP6 solicit/request packet with gatewayip.
     *
     * @param directConnFlag flag indicating if packet is from direct client or not
     * @param serverInfo server to check its connect point
     * @return boolean true if serverInfo is found; false otherwise
     */
    public static boolean checkDhcpServerConnPt(boolean directConnFlag,
                                          DhcpServerInfo serverInfo) {
        if (serverInfo.getDhcpServerConnectPoint() == null) {
            log.warn("DHCP6 server connect point for {} connPt {}",
                    directConnFlag ? "direct" : "indirect", serverInfo.getDhcpServerConnectPoint());
            return false;
        }
        return true;
    }

    /**
     * extract from dhcp6 packet ClientIdOption.
     *
     * @param directConnFlag directly connected host
     * @param dhcp6Payload the dhcp6 payload
     * @return Dhcp6ClientIdOption clientIdOption, or null if not exists.
     */
    static Dhcp6ClientIdOption extractClientId(Boolean directConnFlag, DHCP6 dhcp6Payload) {
        Dhcp6ClientIdOption clientIdOption;

        if (directConnFlag) {
            clientIdOption = dhcp6Payload.getOptions()
                    .stream()
                    .filter(opt -> opt instanceof Dhcp6ClientIdOption)
                    .map(opt -> (Dhcp6ClientIdOption) opt)
                    .findFirst()
                    .orElse(null);
        } else {
            DHCP6 leafDhcp = Dhcp6HandlerUtil.getDhcp6Leaf(dhcp6Payload);
            clientIdOption = leafDhcp.getOptions()
                    .stream()
                    .filter(opt -> opt instanceof Dhcp6ClientIdOption)
                    .map(opt -> (Dhcp6ClientIdOption) opt)
                    .findFirst()
                    .orElse(null);
        }

        return clientIdOption;
    }
}
