/*
 * 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 boolean isRelayAgentIpFromCfgEmpty(DhcpServerInfo serverInfo, DeviceId receivedFromDevice) {
        if (!serverInfo.getRelayAgentIp6(receivedFromDevice).isPresent()) {
            log.warn("indirect connection: relayAgentIp NOT availale from config file! Use dynamic.");
            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 (isRelayAgentIpFromCfgEmpty(serverInfo, receivedFromDevice)) {
                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;
    }
}
