/*
 * 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.onlab.packet.dhcp;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.io.Resources;

import org.apache.commons.io.Charsets;
import org.junit.Test;
import org.onlab.packet.DHCP6;
import org.onlab.packet.Ethernet;
import org.onlab.packet.IPv6;
import org.onlab.packet.Ip6Address;
import org.onlab.packet.MacAddress;
import org.onlab.packet.UDP;

import java.util.List;

import static org.junit.Assert.*;

/**
 * Test serializing/deserializing DHCPv6 relay message.
 */
public class Dhcp6RelayTest {
    private static final String SOLICIT = "dhcp6_relay_solicit.bin";
    private static final String ADVERTISE = "dhcp6_relay_advertise.bin";
    private static final String REQUEST = "dhcp6_relay_request.bin";
    private static final String REPLY = "dhcp6_relay_reply.bin";

    private static final int HOP_COUNT = 0;
    private static final Ip6Address LINK_ADDRESS = Ip6Address.valueOf("2000::2ff");
    private static final Ip6Address PEER_ADDRESS = Ip6Address.valueOf("fe80::2bb:ff:fe00:1");
    private static final int XID_1 = 8135067;
    private static final int XID_2 = 14742082;
    private static final int IA_ID = 1;
    private static final int T1_CLIENT = 3600;
    private static final int T2_CLIENT = 5400;
    private static final int T1_SERVER = 0;
    private static final int T2_SERVER = 0;
    private static final Ip6Address IA_ADDRESS = Ip6Address.valueOf("2000::201");
    private static final int PREFFERRED_LT_SERVER = 375;
    private static final int VALID_LT_SERVER = 600;
    private static final int PREFFERRED_LT_REQ = 7200;
    private static final int VALID_LT_REQ = 10800;
    private static final int VALID_LT_REQ_2 = 7500;
    private static final MacAddress DOWNSTREAM_MAC = MacAddress.valueOf("4a:c0:c2:78:92:34");
    private static final MacAddress CLIENT_MAC = MacAddress.valueOf("00:bb:00:00:00:01");
    private static final int CLIENT_DUID_TIME = 555636143;
    private static final MacAddress IPV6_MCAST = MacAddress.valueOf("33:33:00:01:00:03");
    private static final Ip6Address DOWNSTREAM_LL = Ip6Address.valueOf("fe80::48c0:c2ff:fe78:9234");
    private static final Ip6Address DHCP6_BRC = Ip6Address.valueOf("ff05::1:3");
    private static final Ip6Address SERVER_IP = Ip6Address.valueOf("2000::9903");
    private static final MacAddress SERVER_MAC = MacAddress.valueOf("00:99:66:00:00:01");
    private static final Ip6Address SERVER_LL = Ip6Address.valueOf("fe80::299:66ff:fe00:1");


    /**
     * Test deserialize relay message with solicit message.
     *
     * @throws Exception exception while deserialize the DHCPv6 payload
     */
    @Test
    public void deserializeSolicit() throws Exception {
        byte[] data = Resources.toByteArray(Dhcp6RelayTest.class.getResource(SOLICIT));
        Ethernet eth = Ethernet.deserializer().deserialize(data, 0, data.length);
        DHCP6 relayMsg = (DHCP6) eth.getPayload().getPayload().getPayload();
        assertEquals(relayMsg.getMsgType(), DHCP6.MsgType.RELAY_FORW.value());
        assertEquals(relayMsg.getHopCount(), HOP_COUNT);
        assertEquals(relayMsg.getIp6LinkAddress(), LINK_ADDRESS);
        assertEquals(relayMsg.getIp6PeerAddress(), PEER_ADDRESS);

        assertEquals(relayMsg.getOptions().size(), 2);
        Dhcp6Option option = relayMsg.getOptions().get(0);
        assertEquals(option.getCode(), DHCP6.OptionCode.SUBSCRIBER_ID.value());
        assertEquals(option.getLength(), 10);
        assertArrayEquals(option.getData(), SERVER_IP.toString().getBytes(Charsets.US_ASCII));

        option = relayMsg.getOptions().get(1);
        assertEquals(option.getCode(), DHCP6.OptionCode.RELAY_MSG.value());
        assertEquals(option.getLength(), 84);
        assertTrue(option.getPayload() instanceof DHCP6);

        DHCP6 relaiedDhcp6 = (DHCP6) option.getPayload();
        assertEquals(relaiedDhcp6.getMsgType(), DHCP6.MsgType.SOLICIT.value());
        assertEquals(relaiedDhcp6.getTransactionId(), XID_1);
        assertEquals(relaiedDhcp6.getOptions().size(), 4);

        // Client ID
        option = relaiedDhcp6.getOptions().get(0);
        assertTrue(option instanceof Dhcp6ClientIdOption);
        Dhcp6ClientIdOption clientIdOption = (Dhcp6ClientIdOption) option;
        assertEquals(clientIdOption.getCode(), DHCP6.OptionCode.CLIENTID.value());
        assertEquals(clientIdOption.getLength(), 14);
        assertEquals(clientIdOption.getDuid().getDuidType(), Dhcp6Duid.DuidType.DUID_LLT);
        assertEquals(clientIdOption.getDuid().getHardwareType(), 1);
        assertEquals(clientIdOption.getDuid().getDuidTime(), CLIENT_DUID_TIME);
        assertArrayEquals(clientIdOption.getDuid().getLinkLayerAddress(), CLIENT_MAC.toBytes());

        // ORO
        option = relaiedDhcp6.getOptions().get(1);
        assertEquals(option.getCode(), DHCP6.OptionCode.ORO.value());
        assertEquals(option.getLength(), 8);
        assertArrayEquals(option.getData(),
                          new byte[]{0, 23, 0, 24, 0, 39, 0, 31});

        // ELAPSED_TIME
        option = relaiedDhcp6.getOptions().get(2);
        assertEquals(option.getCode(), DHCP6.OptionCode.ELAPSED_TIME.value());
        assertEquals(option.getLength(), 2);
        assertArrayEquals(option.getData(),
                          new byte[]{0, 0});

        // IA NA
        option = relaiedDhcp6.getOptions().get(3);
        assertTrue(option instanceof Dhcp6IaNaOption);
        Dhcp6IaNaOption iaNaOption = (Dhcp6IaNaOption) option;
        assertEquals(iaNaOption.getCode(), DHCP6.OptionCode.IA_NA.value());
        assertEquals(iaNaOption.getLength(), 40);
        assertEquals(iaNaOption.getIaId(), IA_ID);
        assertEquals(iaNaOption.getT1(), T1_CLIENT);
        assertEquals(iaNaOption.getT2(), T2_CLIENT);
        assertEquals(iaNaOption.getOptions().size(), 1);
        Dhcp6IaAddressOption subOption = (Dhcp6IaAddressOption) iaNaOption.getOptions().get(0);
        assertEquals(subOption.getIp6Address(), IA_ADDRESS);
        assertEquals(subOption.getPreferredLifetime(), PREFFERRED_LT_REQ);
        assertEquals(subOption.getValidLifetime(), VALID_LT_REQ);

        assertArrayEquals(data, eth.serialize());
    }

    /**
     * Test serialize relay message with solicit message.
     *
     * @throws Exception exception while serialize the DHCPv6 payload
     */
    @Test
    public void serializeSolicit() throws Exception {
        DHCP6 relayMsg = new DHCP6();
        relayMsg.setMsgType(DHCP6.MsgType.RELAY_FORW.value());
        relayMsg.setHopCount((byte) HOP_COUNT);
        relayMsg.setLinkAddress(LINK_ADDRESS.toOctets());
        relayMsg.setPeerAddress(PEER_ADDRESS.toOctets());

        DHCP6 relaiedDhcp6 = new DHCP6();
        relaiedDhcp6.setMsgType(DHCP6.MsgType.SOLICIT.value());
        relaiedDhcp6.setTransactionId(XID_1);
        List<Dhcp6Option> options = Lists.newArrayList();

        // Client ID
        Dhcp6Duid duid = new Dhcp6Duid();
        duid.setDuidType(Dhcp6Duid.DuidType.DUID_LLT);
        duid.setHardwareType((short) 1);
        duid.setDuidTime(CLIENT_DUID_TIME);
        duid.setLinkLayerAddress(CLIENT_MAC.toBytes());
        Dhcp6ClientIdOption clientIdOption = new Dhcp6ClientIdOption();
        clientIdOption.setDuid(duid);
        options.add(clientIdOption);

        // Option request
        Dhcp6Option option = new Dhcp6Option();
        option.setCode(DHCP6.OptionCode.ORO.value());
        option.setLength((short) 8);
        option.setData(new byte[]{0, 23, 0, 24, 0, 39, 0, 31});
        options.add(option);

        // Elapsed Time
        option = new Dhcp6Option();
        option.setCode(DHCP6.OptionCode.ELAPSED_TIME.value());
        option.setLength((short) 2);
        option.setData(new byte[]{0, 0});
        options.add(option);

        // IA NA
        Dhcp6IaNaOption iaNaOption = new Dhcp6IaNaOption();
        iaNaOption.setIaId(IA_ID);
        iaNaOption.setT1(T1_CLIENT);
        iaNaOption.setT2(T2_CLIENT);
        Dhcp6IaAddressOption iaAddressOption = new Dhcp6IaAddressOption();
        iaAddressOption.setIp6Address(IA_ADDRESS);
        iaAddressOption.setPreferredLifetime(PREFFERRED_LT_REQ);
        iaAddressOption.setValidLifetime(VALID_LT_REQ);
        iaNaOption.setOptions(ImmutableList.of(iaAddressOption));
        options.add(iaNaOption);
        relaiedDhcp6.setOptions(options);

        Dhcp6RelayOption relayOption = new Dhcp6RelayOption();
        relayOption.setPayload(relaiedDhcp6);

        Dhcp6Option subscriberId = new Dhcp6Option();
        subscriberId.setCode(DHCP6.OptionCode.SUBSCRIBER_ID.value());
        subscriberId.setLength((short) 10);
        subscriberId.setData(SERVER_IP.toString().getBytes(Charsets.US_ASCII));

        relayMsg.setOptions(ImmutableList.of(subscriberId, relayOption));

        UDP udp = new UDP();
        udp.setSourcePort(UDP.DHCP_V6_SERVER_PORT);
        udp.setDestinationPort(UDP.DHCP_V6_SERVER_PORT);
        udp.setPayload(relayMsg);
        udp.setChecksum((short) 0x9a99);

        IPv6 ipv6 = new IPv6();
        ipv6.setHopLimit((byte) 32);
        ipv6.setSourceAddress(DOWNSTREAM_LL.toOctets());
        ipv6.setDestinationAddress(DHCP6_BRC.toOctets());
        ipv6.setNextHeader(IPv6.PROTOCOL_UDP);
        ipv6.setTrafficClass((byte) 0);
        ipv6.setFlowLabel(0x000cbf64);
        ipv6.setPayload(udp);

        Ethernet eth = new Ethernet();
        eth.setDestinationMACAddress(IPV6_MCAST);
        eth.setSourceMACAddress(DOWNSTREAM_MAC);
        eth.setEtherType(Ethernet.TYPE_IPV6);
        eth.setPayload(ipv6);

        assertArrayEquals(Resources.toByteArray(Dhcp6RelayTest.class.getResource(SOLICIT)),
                          eth.serialize());
    }

    /**
     * Test deserialize relay message with advertise message.
     *
     * @throws Exception exception while deserialize the DHCPv6 payload
     */
    @Test
    public void deserializeAdvertise() throws Exception {
        byte[] data = Resources.toByteArray(getClass().getResource(ADVERTISE));
        Ethernet eth = Ethernet.deserializer().deserialize(data, 0, data.length);
        DHCP6 relayMsg = (DHCP6) eth.getPayload().getPayload().getPayload();
        assertEquals(relayMsg.getMsgType(), DHCP6.MsgType.RELAY_REPL.value());
        assertEquals(relayMsg.getHopCount(), HOP_COUNT);
        assertEquals(relayMsg.getIp6LinkAddress(), LINK_ADDRESS);
        assertEquals(relayMsg.getIp6PeerAddress(), PEER_ADDRESS);

        assertEquals(relayMsg.getOptions().size(), 1);
        Dhcp6Option option = relayMsg.getOptions().get(0);
        assertEquals(option.getCode(), DHCP6.OptionCode.RELAY_MSG.value());
        assertEquals(option.getLength(), 84);
        assertTrue(option.getPayload() instanceof DHCP6);

        DHCP6 relaiedDhcp6 = (DHCP6) option.getPayload();
        assertEquals(relaiedDhcp6.getMsgType(), DHCP6.MsgType.ADVERTISE.value());
        assertEquals(relaiedDhcp6.getTransactionId(), XID_1);
        assertEquals(relaiedDhcp6.getOptions().size(), 3);

        // IA NA
        option = relaiedDhcp6.getOptions().get(0);
        assertTrue(option instanceof Dhcp6IaNaOption);
        Dhcp6IaNaOption iaNaOption = (Dhcp6IaNaOption) option;
        assertEquals(iaNaOption.getCode(), DHCP6.OptionCode.IA_NA.value());
        assertEquals(iaNaOption.getLength(), 40);
        assertEquals(iaNaOption.getIaId(), IA_ID);
        assertEquals(iaNaOption.getT1(), T1_SERVER);
        assertEquals(iaNaOption.getT2(), T2_SERVER);
        assertEquals(iaNaOption.getOptions().size(), 1);

        // IA Address (in IA NA)
        assertTrue(iaNaOption.getOptions().get(0) instanceof Dhcp6IaAddressOption);
        Dhcp6IaAddressOption iaAddressOption =
                (Dhcp6IaAddressOption) iaNaOption.getOptions().get(0);
        assertEquals(iaAddressOption.getIp6Address(), IA_ADDRESS);
        assertEquals(iaAddressOption.getPreferredLifetime(), PREFFERRED_LT_SERVER);
        assertEquals(iaAddressOption.getValidLifetime(), VALID_LT_SERVER);
        assertNull(iaAddressOption.getOptions());

        // Client ID
        option = relaiedDhcp6.getOptions().get(1);
        assertTrue(option instanceof Dhcp6ClientIdOption);
        Dhcp6ClientIdOption clientIdOption = (Dhcp6ClientIdOption) option;
        assertEquals(clientIdOption.getCode(), DHCP6.OptionCode.CLIENTID.value());
        assertEquals(clientIdOption.getLength(), 14);
        assertEquals(clientIdOption.getDuid().getDuidType(), Dhcp6Duid.DuidType.DUID_LLT);
        assertEquals(clientIdOption.getDuid().getHardwareType(), 1);
        assertEquals(clientIdOption.getDuid().getDuidTime(), CLIENT_DUID_TIME);
        assertArrayEquals(clientIdOption.getDuid().getLinkLayerAddress(), CLIENT_MAC.toBytes());

        // Server ID
        option = relaiedDhcp6.getOptions().get(2);
        assertEquals(option.getCode(), DHCP6.OptionCode.SERVERID.value());
        assertEquals(option.getLength(), 14);
        Dhcp6Duid serverDuid =
                Dhcp6Duid.deserializer().deserialize(option.getData(), 0, option.getData().length);
        assertEquals(serverDuid.getDuidType(), Dhcp6Duid.DuidType.DUID_LLT);
        assertEquals(serverDuid.getDuidTime(), 0x211e5340);
        assertEquals(serverDuid.getHardwareType(), 1);
        assertArrayEquals(serverDuid.getLinkLayerAddress(), SERVER_MAC.toBytes());
        assertArrayEquals(data, eth.serialize());
    }

    /**
     * Test serialize relay message with advertise message.
     *
     * @throws Exception exception while serialize the DHCPv6 payload
     */
    @Test
    public void serializeAdvertise() throws Exception {
        DHCP6 relayMsg = new DHCP6();
        relayMsg.setMsgType(DHCP6.MsgType.RELAY_REPL.value());
        relayMsg.setHopCount((byte) HOP_COUNT);
        relayMsg.setLinkAddress(LINK_ADDRESS.toOctets());
        relayMsg.setPeerAddress(PEER_ADDRESS.toOctets());

        DHCP6 relaiedDhcp6 = new DHCP6();
        relaiedDhcp6.setMsgType(DHCP6.MsgType.ADVERTISE.value());
        relaiedDhcp6.setTransactionId(XID_1);
        List<Dhcp6Option> options = Lists.newArrayList();

        // IA address
        Dhcp6IaAddressOption iaAddressOption = new Dhcp6IaAddressOption();
        iaAddressOption.setIp6Address(IA_ADDRESS);
        iaAddressOption.setPreferredLifetime(PREFFERRED_LT_SERVER);
        iaAddressOption.setValidLifetime(VALID_LT_SERVER);

        // IA NA
        Dhcp6IaNaOption iaNaOption = new Dhcp6IaNaOption();
        iaNaOption.setIaId(IA_ID);
        iaNaOption.setT1(T1_SERVER);
        iaNaOption.setT2(T2_SERVER);
        iaNaOption.setOptions(ImmutableList.of(iaAddressOption));
        options.add(iaNaOption);

        // Client ID
        Dhcp6Duid duid = new Dhcp6Duid();
        duid.setDuidType(Dhcp6Duid.DuidType.DUID_LLT);
        duid.setHardwareType((short) 1);
        duid.setDuidTime(CLIENT_DUID_TIME);
        duid.setLinkLayerAddress(CLIENT_MAC.toBytes());
        Dhcp6ClientIdOption clientIdOption = new Dhcp6ClientIdOption();
        clientIdOption.setDuid(duid);
        options.add(clientIdOption);

        // Server ID
        Dhcp6Option option = new Dhcp6Option();
        option.setCode(DHCP6.OptionCode.SERVERID.value());
        option.setLength((short) 14);
        Dhcp6Duid serverDuid = new Dhcp6Duid();
        serverDuid.setDuidType(Dhcp6Duid.DuidType.DUID_LLT);
        serverDuid.setLinkLayerAddress(SERVER_MAC.toBytes());
        serverDuid.setHardwareType((short) 1);
        serverDuid.setDuidTime(0x211e5340);
        option.setData(serverDuid.serialize());
        options.add(option);

        relaiedDhcp6.setOptions(options);

        Dhcp6RelayOption relayOption = new Dhcp6RelayOption();
        relayOption.setPayload(relaiedDhcp6);

        relayMsg.setOptions(ImmutableList.of(relayOption));

        UDP udp = new UDP();
        udp.setSourcePort(UDP.DHCP_V6_SERVER_PORT);
        udp.setDestinationPort(UDP.DHCP_V6_SERVER_PORT);
        udp.setPayload(relayMsg);
        udp.setChecksum((short) 0x0000019d);

        IPv6 ipv6 = new IPv6();
        ipv6.setHopLimit((byte) 64);
        ipv6.setSourceAddress(SERVER_LL.toOctets());
        ipv6.setDestinationAddress(DOWNSTREAM_LL.toOctets());
        ipv6.setNextHeader(IPv6.PROTOCOL_UDP);
        ipv6.setTrafficClass((byte) 0);
        ipv6.setFlowLabel(0x000c72ef);
        ipv6.setPayload(udp);

        Ethernet eth = new Ethernet();
        eth.setDestinationMACAddress(DOWNSTREAM_MAC);
        eth.setSourceMACAddress(SERVER_MAC);
        eth.setEtherType(Ethernet.TYPE_IPV6);
        eth.setPayload(ipv6);
        assertArrayEquals(Resources.toByteArray(Dhcp6RelayTest.class.getResource(ADVERTISE)),
                          eth.serialize());
    }

    /**
     * Test deserialize relay message with request message.
     *
     * @throws Exception exception while deserialize the DHCPv6 payload
     */
    @Test
    public void deserializeRequest() throws Exception {
        byte[] data = Resources.toByteArray(getClass().getResource(REQUEST));
        Ethernet eth = Ethernet.deserializer().deserialize(data, 0, data.length);
        DHCP6 relayMsg = (DHCP6) eth.getPayload().getPayload().getPayload();
        assertEquals(relayMsg.getMsgType(), DHCP6.MsgType.RELAY_FORW.value());
        assertEquals(relayMsg.getHopCount(), HOP_COUNT);
        assertEquals(relayMsg.getIp6LinkAddress(), LINK_ADDRESS);
        assertEquals(relayMsg.getIp6PeerAddress(), PEER_ADDRESS);

        assertEquals(relayMsg.getOptions().size(), 2);
        Dhcp6Option option = relayMsg.getOptions().get(0);
        assertEquals(option.getCode(), DHCP6.OptionCode.SUBSCRIBER_ID.value());
        assertEquals(option.getLength(), 10);
        assertArrayEquals(option.getData(), SERVER_IP.toString().getBytes(Charsets.US_ASCII));

        option = relayMsg.getOptions().get(1);
        assertEquals(option.getCode(), DHCP6.OptionCode.RELAY_MSG.value());
        assertEquals(option.getLength(), 102);
        assertTrue(option.getPayload() instanceof DHCP6);

        DHCP6 relaiedDhcp6 = (DHCP6) option.getPayload();
        assertEquals(relaiedDhcp6.getMsgType(), DHCP6.MsgType.REQUEST.value());
        assertEquals(relaiedDhcp6.getTransactionId(), XID_2);
        assertEquals(relaiedDhcp6.getOptions().size(), 5);

        // Client ID
        option = relaiedDhcp6.getOptions().get(0);
        assertTrue(option instanceof Dhcp6ClientIdOption);
        Dhcp6ClientIdOption clientIdOption = (Dhcp6ClientIdOption) option;
        assertEquals(clientIdOption.getCode(), DHCP6.OptionCode.CLIENTID.value());
        assertEquals(clientIdOption.getLength(), 14);
        assertEquals(clientIdOption.getDuid().getDuidType(), Dhcp6Duid.DuidType.DUID_LLT);
        assertEquals(clientIdOption.getDuid().getHardwareType(), 1);
        assertEquals(clientIdOption.getDuid().getDuidTime(), CLIENT_DUID_TIME);
        assertArrayEquals(clientIdOption.getDuid().getLinkLayerAddress(), CLIENT_MAC.toBytes());

        // Server ID
        option = relaiedDhcp6.getOptions().get(1);
        assertEquals(option.getCode(), DHCP6.OptionCode.SERVERID.value());
        assertEquals(option.getLength(), 14);
        Dhcp6Duid serverDuid =
                Dhcp6Duid.deserializer().deserialize(option.getData(), 0, option.getData().length);
        assertEquals(serverDuid.getDuidType(), Dhcp6Duid.DuidType.DUID_LLT);
        assertEquals(serverDuid.getDuidTime(), 0x211e5340);
        assertEquals(serverDuid.getHardwareType(), 1);
        assertArrayEquals(serverDuid.getLinkLayerAddress(), SERVER_MAC.toBytes());

        // Option Request
        option = relaiedDhcp6.getOptions().get(2);
        assertEquals(option.getCode(), DHCP6.OptionCode.ORO.value());
        assertEquals(option.getLength(), 8);
        assertArrayEquals(option.getData(), new byte[]{0, 23, 0, 24, 0, 39, 0, 31});

        // ELAPSED_TIME
        option = relaiedDhcp6.getOptions().get(3);
        assertEquals(option.getCode(), DHCP6.OptionCode.ELAPSED_TIME.value());
        assertEquals(option.getLength(), 2);
        assertArrayEquals(option.getData(), new byte[]{0, 0});

        // IA NA
        option = relaiedDhcp6.getOptions().get(4);
        assertTrue(option instanceof Dhcp6IaNaOption);
        Dhcp6IaNaOption iaNaOption = (Dhcp6IaNaOption) option;
        assertEquals(iaNaOption.getCode(), DHCP6.OptionCode.IA_NA.value());
        assertEquals(iaNaOption.getLength(), 40);
        assertEquals(iaNaOption.getIaId(), IA_ID);
        assertEquals(iaNaOption.getT1(), T1_CLIENT);
        assertEquals(iaNaOption.getT2(), T2_CLIENT);
        assertEquals(iaNaOption.getOptions().size(), 1);

        // IA Address (in IA NA)
        assertTrue(iaNaOption.getOptions().get(0) instanceof Dhcp6IaAddressOption);
        Dhcp6IaAddressOption iaAddressOption =
                (Dhcp6IaAddressOption) iaNaOption.getOptions().get(0);
        assertEquals(iaAddressOption.getIp6Address(), IA_ADDRESS);
        assertEquals(iaAddressOption.getPreferredLifetime(), PREFFERRED_LT_REQ);
        assertEquals(iaAddressOption.getValidLifetime(), VALID_LT_REQ_2);
        assertNull(iaAddressOption.getOptions());

        assertArrayEquals(data, eth.serialize());
    }

    /**
     * Test serialize relay message with request message.
     *
     * @throws Exception exception while serialize the DHCPv6 payload
     */
    @Test
    public void serializeRequest() throws Exception {
        DHCP6 relayMsg = new DHCP6();
        relayMsg.setMsgType(DHCP6.MsgType.RELAY_FORW.value());
        relayMsg.setHopCount((byte) HOP_COUNT);
        relayMsg.setLinkAddress(LINK_ADDRESS.toOctets());
        relayMsg.setPeerAddress(PEER_ADDRESS.toOctets());

        DHCP6 relaiedDhcp6 = new DHCP6();
        relaiedDhcp6.setMsgType(DHCP6.MsgType.REQUEST.value());
        relaiedDhcp6.setTransactionId(XID_2);
        List<Dhcp6Option> options = Lists.newArrayList();

        // Client ID
        Dhcp6Duid duid = new Dhcp6Duid();
        duid.setDuidType(Dhcp6Duid.DuidType.DUID_LLT);
        duid.setHardwareType((short) 1);
        duid.setDuidTime(CLIENT_DUID_TIME);
        duid.setLinkLayerAddress(CLIENT_MAC.toBytes());
        Dhcp6ClientIdOption clientIdOption = new Dhcp6ClientIdOption();
        clientIdOption.setDuid(duid);
        options.add(clientIdOption);

        // Server ID
        Dhcp6Option option = new Dhcp6Option();
        option.setCode(DHCP6.OptionCode.SERVERID.value());
        option.setLength((short) 14);
        Dhcp6Duid serverDuid = new Dhcp6Duid();
        serverDuid.setDuidType(Dhcp6Duid.DuidType.DUID_LLT);
        serverDuid.setLinkLayerAddress(SERVER_MAC.toBytes());
        serverDuid.setHardwareType((short) 1);
        serverDuid.setDuidTime(0x211e5340);
        option.setData(serverDuid.serialize());
        options.add(option);

        // Option request
        option = new Dhcp6Option();
        option.setCode(DHCP6.OptionCode.ORO.value());
        option.setLength((short) 8);
        option.setData(new byte[]{0, 23, 0, 24, 0, 39, 0, 31});
        options.add(option);

        // Elapsed Time
        option = new Dhcp6Option();
        option.setCode(DHCP6.OptionCode.ELAPSED_TIME.value());
        option.setLength((short) 2);
        option.setData(new byte[]{0, 0});
        options.add(option);

        // IA address
        Dhcp6IaAddressOption iaAddressOption = new Dhcp6IaAddressOption();
        iaAddressOption.setIp6Address(IA_ADDRESS);
        iaAddressOption.setPreferredLifetime(PREFFERRED_LT_REQ);
        iaAddressOption.setValidLifetime(VALID_LT_REQ_2);

        // IA NA
        Dhcp6IaNaOption iaNaOption = new Dhcp6IaNaOption();
        iaNaOption.setIaId(IA_ID);
        iaNaOption.setT1(T1_CLIENT);
        iaNaOption.setT2(T2_CLIENT);
        iaNaOption.setOptions(ImmutableList.of(iaAddressOption));
        options.add(iaNaOption);

        relaiedDhcp6.setOptions(options);

        Dhcp6Option subscriberId = new Dhcp6Option();
        subscriberId.setCode(DHCP6.OptionCode.SUBSCRIBER_ID.value());
        subscriberId.setLength((short) 10);
        subscriberId.setData(SERVER_IP.toString().getBytes(Charsets.US_ASCII));

        Dhcp6RelayOption relayOption = new Dhcp6RelayOption();
        relayOption.setPayload(relaiedDhcp6);

        relayMsg.setOptions(ImmutableList.of(subscriberId, relayOption));

        UDP udp = new UDP();
        udp.setSourcePort(UDP.DHCP_V6_SERVER_PORT);
        udp.setDestinationPort(UDP.DHCP_V6_SERVER_PORT);
        udp.setPayload(relayMsg);
        udp.setChecksum((short) 0x9aab);

        IPv6 ipv6 = new IPv6();
        ipv6.setHopLimit((byte) 32);
        ipv6.setSourceAddress(DOWNSTREAM_LL.toOctets());
        ipv6.setDestinationAddress(DHCP6_BRC.toOctets());
        ipv6.setNextHeader(IPv6.PROTOCOL_UDP);
        ipv6.setTrafficClass((byte) 0);
        ipv6.setFlowLabel(0x000cbf64);
        ipv6.setPayload(udp);

        Ethernet eth = new Ethernet();
        eth.setDestinationMACAddress(IPV6_MCAST);
        eth.setSourceMACAddress(DOWNSTREAM_MAC);
        eth.setEtherType(Ethernet.TYPE_IPV6);
        eth.setPayload(ipv6);

        assertArrayEquals(Resources.toByteArray(Dhcp6RelayTest.class.getResource(REQUEST)),
                          eth.serialize());
    }

    /**
     * Test deserialize relay message with reply message.
     *
     * @throws Exception exception while deserialize the DHCPv6 payload
     */
    @Test
    public void deserializeReply() throws Exception {
        byte[] data = Resources.toByteArray(getClass().getResource(REPLY));
        Ethernet eth = Ethernet.deserializer().deserialize(data, 0, data.length);
        DHCP6 relayMsg = (DHCP6) eth.getPayload().getPayload().getPayload();
        assertEquals(relayMsg.getMsgType(), DHCP6.MsgType.RELAY_REPL.value());
        assertEquals(relayMsg.getHopCount(), HOP_COUNT);
        assertEquals(relayMsg.getIp6LinkAddress(), LINK_ADDRESS);
        assertEquals(relayMsg.getIp6PeerAddress(), PEER_ADDRESS);

        assertEquals(relayMsg.getOptions().size(), 1);
        Dhcp6Option option = relayMsg.getOptions().get(0);
        assertEquals(option.getCode(), DHCP6.OptionCode.RELAY_MSG.value());
        assertEquals(option.getLength(), 84);
        assertTrue(option.getPayload() instanceof DHCP6);

        DHCP6 relaiedDhcp6 = (DHCP6) option.getPayload();
        assertEquals(relaiedDhcp6.getMsgType(), DHCP6.MsgType.REPLY.value());
        assertEquals(relaiedDhcp6.getTransactionId(), XID_2);
        assertEquals(relaiedDhcp6.getOptions().size(), 3);

        // IA NA
        option = relaiedDhcp6.getOptions().get(0);
        assertTrue(option instanceof Dhcp6IaNaOption);
        Dhcp6IaNaOption iaNaOption = (Dhcp6IaNaOption) option;
        assertEquals(iaNaOption.getCode(), DHCP6.OptionCode.IA_NA.value());
        assertEquals(iaNaOption.getLength(), 40);
        assertEquals(iaNaOption.getIaId(), IA_ID);
        assertEquals(iaNaOption.getT1(), T1_SERVER);
        assertEquals(iaNaOption.getT2(), T2_SERVER);
        assertEquals(iaNaOption.getOptions().size(), 1);

        // IA Address (in IA NA)
        assertTrue(iaNaOption.getOptions().get(0) instanceof Dhcp6IaAddressOption);
        Dhcp6IaAddressOption iaAddressOption =
                (Dhcp6IaAddressOption) iaNaOption.getOptions().get(0);
        assertEquals(iaAddressOption.getIp6Address(), IA_ADDRESS);
        assertEquals(iaAddressOption.getPreferredLifetime(), PREFFERRED_LT_SERVER);
        assertEquals(iaAddressOption.getValidLifetime(), VALID_LT_SERVER);
        assertNull(iaAddressOption.getOptions());

        // Client ID
        option = relaiedDhcp6.getOptions().get(1);
        assertTrue(option instanceof Dhcp6ClientIdOption);
        Dhcp6ClientIdOption clientIdOption = (Dhcp6ClientIdOption) option;
        assertEquals(clientIdOption.getCode(), DHCP6.OptionCode.CLIENTID.value());
        assertEquals(clientIdOption.getLength(), 14);
        assertEquals(clientIdOption.getDuid().getDuidType(), Dhcp6Duid.DuidType.DUID_LLT);
        assertEquals(clientIdOption.getDuid().getHardwareType(), 1);
        assertEquals(clientIdOption.getDuid().getDuidTime(), CLIENT_DUID_TIME);
        assertArrayEquals(clientIdOption.getDuid().getLinkLayerAddress(), CLIENT_MAC.toBytes());

        // Server ID
        option = relaiedDhcp6.getOptions().get(2);
        assertEquals(option.getCode(), DHCP6.OptionCode.SERVERID.value());
        assertEquals(option.getLength(), 14);
        Dhcp6Duid serverDuid =
                Dhcp6Duid.deserializer().deserialize(option.getData(), 0, option.getData().length);
        assertEquals(serverDuid.getDuidType(), Dhcp6Duid.DuidType.DUID_LLT);
        assertEquals(serverDuid.getDuidTime(), 0x211e5340);
        assertEquals(serverDuid.getHardwareType(), 1);
        assertArrayEquals(serverDuid.getLinkLayerAddress(), SERVER_MAC.toBytes());

        assertArrayEquals(data, eth.serialize());
    }

    @Test
    public void serializeReply() throws Exception {
        DHCP6 relayMsg = new DHCP6();
        relayMsg.setMsgType(DHCP6.MsgType.RELAY_REPL.value());
        relayMsg.setHopCount((byte) HOP_COUNT);
        relayMsg.setLinkAddress(LINK_ADDRESS.toOctets());
        relayMsg.setPeerAddress(PEER_ADDRESS.toOctets());

        DHCP6 relaiedDhcp6 = new DHCP6();
        relaiedDhcp6.setMsgType(DHCP6.MsgType.REPLY.value());
        relaiedDhcp6.setTransactionId(XID_2);
        List<Dhcp6Option> options = Lists.newArrayList();

        // IA address
        Dhcp6IaAddressOption iaAddressOption = new Dhcp6IaAddressOption();
        iaAddressOption.setIp6Address(IA_ADDRESS);
        iaAddressOption.setPreferredLifetime(PREFFERRED_LT_SERVER);
        iaAddressOption.setValidLifetime(VALID_LT_SERVER);

        // IA NA
        Dhcp6IaNaOption iaNaOption = new Dhcp6IaNaOption();
        iaNaOption.setIaId(IA_ID);
        iaNaOption.setT1(T1_SERVER);
        iaNaOption.setT2(T2_SERVER);
        iaNaOption.setOptions(ImmutableList.of(iaAddressOption));
        options.add(iaNaOption);

        // Client ID
        Dhcp6Duid duid = new Dhcp6Duid();
        duid.setDuidType(Dhcp6Duid.DuidType.DUID_LLT);
        duid.setHardwareType((short) 1);
        duid.setDuidTime(CLIENT_DUID_TIME);
        duid.setLinkLayerAddress(CLIENT_MAC.toBytes());
        Dhcp6ClientIdOption clientIdOption = new Dhcp6ClientIdOption();
        clientIdOption.setDuid(duid);
        options.add(clientIdOption);

        // Server ID
        Dhcp6Option option = new Dhcp6Option();
        option.setCode(DHCP6.OptionCode.SERVERID.value());
        option.setLength((short) 14);
        Dhcp6Duid serverDuid = new Dhcp6Duid();
        serverDuid.setDuidType(Dhcp6Duid.DuidType.DUID_LLT);
        serverDuid.setLinkLayerAddress(SERVER_MAC.toBytes());
        serverDuid.setHardwareType((short) 1);
        serverDuid.setDuidTime(0x211e5340);
        option.setData(serverDuid.serialize());
        options.add(option);

        relaiedDhcp6.setOptions(options);

        Dhcp6RelayOption relayOption = new Dhcp6RelayOption();
        relayOption.setPayload(relaiedDhcp6);

        relayMsg.setOptions(ImmutableList.of(relayOption));

        UDP udp = new UDP();
        udp.setSourcePort(UDP.DHCP_V6_SERVER_PORT);
        udp.setDestinationPort(UDP.DHCP_V6_SERVER_PORT);
        udp.setPayload(relayMsg);
        udp.setChecksum((short) 0x019d);

        IPv6 ipv6 = new IPv6();
        ipv6.setHopLimit((byte) 64);
        ipv6.setSourceAddress(SERVER_LL.toOctets());
        ipv6.setDestinationAddress(DOWNSTREAM_LL.toOctets());
        ipv6.setNextHeader(IPv6.PROTOCOL_UDP);
        ipv6.setTrafficClass((byte) 0);
        ipv6.setFlowLabel(0x000c72ef);
        ipv6.setPayload(udp);

        Ethernet eth = new Ethernet();
        eth.setDestinationMACAddress(DOWNSTREAM_MAC);
        eth.setSourceMACAddress(SERVER_MAC);
        eth.setEtherType(Ethernet.TYPE_IPV6);
        eth.setPayload(ipv6);

        assertArrayEquals(Resources.toByteArray(Dhcp6RelayTest.class.getResource(REPLY)),
                          eth.serialize());
    }
}
