/*
 * 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 com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.common.collect.Streams;
import com.google.common.io.Resources;
import org.apache.commons.io.Charsets;
import org.easymock.Capture;
import org.easymock.CaptureType;
import org.easymock.EasyMock;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.onlab.packet.ARP;
import org.onlab.packet.DHCP;
import org.onlab.packet.DeserializationException;
import org.onlab.packet.Ethernet;
import org.onlab.packet.IPv4;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.Ip6Address;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
import org.onlab.packet.UDP;
import org.onlab.packet.VlanId;
import org.onlab.packet.dhcp.CircuitId;
import org.onlab.packet.dhcp.DhcpOption;
import org.onlab.packet.dhcp.DhcpRelayAgentOption;
import org.onlab.packet.dhcp.Dhcp6InterfaceIdOption;
import org.onlab.packet.dhcp.Dhcp6RelayOption;
import org.onlab.packet.dhcp.Dhcp6IaNaOption;
import org.onlab.packet.dhcp.Dhcp6IaPdOption;
import org.onlab.packet.dhcp.Dhcp6IaAddressOption;
import org.onlab.packet.dhcp.Dhcp6IaPrefixOption;
import org.onlab.packet.dhcp.Dhcp6Option;
import org.onosproject.net.ConnectPoint;
import org.onosproject.TestApplicationId;
import org.onosproject.cfg.ComponentConfigService;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.dhcprelay.config.DefaultDhcpRelayConfig;
import org.onosproject.dhcprelay.config.DhcpServerConfig;
import org.onosproject.dhcprelay.config.IgnoreDhcpConfig;
import org.onosproject.dhcprelay.config.IndirectDhcpRelayConfig;
import org.onosproject.dhcprelay.store.DhcpRecord;
import org.onosproject.dhcprelay.store.DhcpRelayStore;
import org.onosproject.dhcprelay.store.DhcpRelayStoreEvent;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.behaviour.Pipeliner;
import org.onosproject.net.device.DeviceEvent;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flowobjective.FlowObjectiveService;
import org.onosproject.net.flowobjective.ForwardingObjective;
import org.onosproject.net.flowobjective.Objective;
import org.onosproject.net.host.HostProviderService;
import org.onosproject.net.intf.Interface;
import org.onosproject.net.intf.InterfaceServiceAdapter;
import org.onosproject.net.packet.PacketPriority;
import org.onosproject.routeservice.Route;
import org.onosproject.routeservice.RouteStoreAdapter;
import org.onosproject.net.DefaultHost;
import org.onosproject.net.Host;
import org.onosproject.net.HostId;
import org.onosproject.net.HostLocation;
import org.onosproject.net.config.NetworkConfigRegistry;
import org.onosproject.net.host.HostDescription;
import org.onosproject.net.host.HostService;
import org.onosproject.net.host.InterfaceIpAddress;
import org.onosproject.net.packet.DefaultInboundPacket;
import org.onosproject.net.packet.InboundPacket;
import org.onosproject.net.packet.OutboundPacket;
import org.onosproject.net.packet.PacketContext;
import org.onosproject.net.packet.PacketContextAdapter;
import org.onosproject.net.packet.PacketProcessor;
import org.onosproject.net.packet.PacketServiceAdapter;
import org.onosproject.store.StoreDelegate;
import org.osgi.service.component.ComponentContext;
import org.onlab.packet.DHCP6;
import org.onlab.packet.IPv6;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Collection;
import java.util.Dictionary;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

import static org.easymock.EasyMock.*;
import static org.junit.Assert.*;
import static org.onosproject.dhcprelay.DhcpRelayManager.DHCP_RELAY_APP;

public class DhcpRelayManagerTest {
    private static final short VLAN_LEN = 2;
    private static final short SEPARATOR_LEN = 1;
    private static final String CONFIG_FILE_PATH = "dhcp-relay.json";
    private static final DeviceId DEV_1_ID = DeviceId.deviceId("of:0000000000000001");
    private static final DeviceId DEV_2_ID = DeviceId.deviceId("of:0000000000000002");
    // Ip address for interfaces
    private static final InterfaceIpAddress INTERFACE_IP = InterfaceIpAddress.valueOf("10.0.3.254/32");
    private static final InterfaceIpAddress INTERFACE_IP_V6 = InterfaceIpAddress.valueOf("2001:db8:1::254/128");
    private static final List<InterfaceIpAddress> INTERFACE_IPS = ImmutableList.of(INTERFACE_IP, INTERFACE_IP_V6);

    // DHCP client (will send without option 82)
    private static final Ip4Address IP_FOR_CLIENT = Ip4Address.valueOf("10.0.0.1");
    private static final Ip6Address IP_FOR_CLIENT_V6 = Ip6Address.valueOf("2001:db8:1::110");
    private static final IpPrefix PREFIX_FOR_CLIENT_V6 = IpPrefix.valueOf("2001:db8:10::/56");
    private static final IpPrefix PREFIX_FOR_ZERO = IpPrefix.valueOf("::/0");
    private static final MacAddress CLIENT_MAC = MacAddress.valueOf("00:00:00:00:00:01");
    private static final VlanId CLIENT_VLAN = VlanId.vlanId("100");
    private static final ConnectPoint CLIENT_CP = ConnectPoint.deviceConnectPoint("of:0000000000000001/1");
    private static final MacAddress CLIENT_IFACE_MAC = MacAddress.valueOf("00:00:00:00:11:01");
    private static final HostLocation CLIENT_LOCATION = new HostLocation(CLIENT_CP, 0);
    private static final HostId CLIENT_HOST_ID = HostId.hostId(CLIENT_MAC, CLIENT_VLAN);
    private static final Ip6Address CLIENT_LL_IP_V6 = Ip6Address.valueOf("fe80::200:00ff:fe00:0001");
    private static final Host EXISTS_HOST = new DefaultHost(Dhcp4HandlerImpl.PROVIDER_ID,
                                                            CLIENT_HOST_ID, CLIENT_MAC, CLIENT_VLAN,
                                                            CLIENT_LOCATION, ImmutableSet.of(CLIENT_LL_IP_V6));
    private static final Interface CLIENT_INTERFACE = createInterface("C1",
                                                                      CLIENT_CP,
                                                                      INTERFACE_IPS,
                                                                      CLIENT_IFACE_MAC,
                                                                      CLIENT_VLAN,
                                                                      null);



    // Dual homing test
    private static final ConnectPoint CLIENT_DH_CP = ConnectPoint.deviceConnectPoint("of:0000000000000001/3");
    private static final HostLocation CLIENT_DH_LOCATION = new HostLocation(CLIENT_DH_CP, 0);
    private static final Interface CLIENT_DH_INTERFACE = createInterface("C1-DH",
                                                                         CLIENT_DH_CP,
                                                                         INTERFACE_IPS,
                                                                         CLIENT_IFACE_MAC,
                                                                         CLIENT_VLAN,
                                                                         null);


    // DHCP client 2 (will send with option 82, so the vlan should equals to vlan from server)
    private static final MacAddress CLIENT2_MAC = MacAddress.valueOf("00:00:00:00:00:01");
    private static final VlanId CLIENT2_VLAN = VlanId.NONE;
    private static final VlanId CLIENT2_VLAN_NATIVE = VlanId.vlanId("20");
    private static final ConnectPoint CLIENT2_CP = ConnectPoint.deviceConnectPoint("of:0000000000000001/2");
    private static final MacAddress CLIENT2_IFACE_MAC = MacAddress.valueOf("00:00:00:00:11:01");
    private static final Interface CLIENT2_INTERFACE = createInterface("C2",
                                                                       CLIENT2_CP,
                                                                       INTERFACE_IPS,
                                                                       CLIENT2_IFACE_MAC,
                                                                       CLIENT2_VLAN,
                                                                       CLIENT2_VLAN_NATIVE);
    private static final VlanId CLIENT_BOGUS_VLAN = VlanId.vlanId("108");


    // Outer relay information
    private static final Ip4Address OUTER_RELAY_IP = Ip4Address.valueOf("10.0.5.253");
    private static final Ip6Address OUTER_RELAY_IP_V6 = Ip6Address.valueOf("2001:db8:1::4");
    private static final Set<IpAddress> OUTER_RELAY_IPS = ImmutableSet.of(OUTER_RELAY_IP, OUTER_RELAY_IP_V6);
    private static final MacAddress OUTER_RELAY_MAC = MacAddress.valueOf("00:01:02:03:04:05");
    private static final VlanId OUTER_RELAY_VLAN = VlanId.NONE;
    private static final ConnectPoint OUTER_RELAY_CP = ConnectPoint.deviceConnectPoint("of:0000000000000001/2");
    private static final HostLocation OUTER_REPLAY_HL = new HostLocation(OUTER_RELAY_CP, 0);
    private static final HostId OUTER_RELAY_HOST_ID = HostId.hostId(OUTER_RELAY_MAC, OUTER_RELAY_VLAN);
    private static final Host OUTER_RELAY_HOST = new DefaultHost(Dhcp4HandlerImpl.PROVIDER_ID,
                                                                 OUTER_RELAY_HOST_ID,
                                                                 OUTER_RELAY_MAC,
                                                                 OUTER_RELAY_VLAN,
                                                                 OUTER_REPLAY_HL,
                                                                 OUTER_RELAY_IPS);

    // DHCP Server
    private static final MacAddress SERVER_MAC = MacAddress.valueOf("00:00:00:00:00:01");
    private static final VlanId SERVER_VLAN = VlanId.NONE;
    private static final VlanId SERVER_VLAN_NATIVE = VlanId.vlanId("10");
    private static final ConnectPoint SERVER_CONNECT_POINT =
            ConnectPoint.deviceConnectPoint("of:0000000000000001/5");
    private static final HostLocation SERVER_LOCATION =
            new HostLocation(SERVER_CONNECT_POINT, 0);
    private static final Ip4Address GATEWAY_IP = Ip4Address.valueOf("10.0.5.253");
    private static final Ip6Address GATEWAY_IP_V6 = Ip6Address.valueOf("2000::105:253");
    private static final Ip4Address SERVER_IP = Ip4Address.valueOf("10.0.3.253");
    private static final Ip6Address SERVER_IP_V6 = Ip6Address.valueOf("2000::103:253");
    private static final Ip6Address SERVER_IP_V6_MCAST = Ip6Address.valueOf("ff02::1:2");
    private static final Set<IpAddress> DHCP_SERVER_IPS = ImmutableSet.of(SERVER_IP, SERVER_IP_V6);
    private static final HostId SERVER_HOST_ID = HostId.hostId(SERVER_MAC, SERVER_VLAN);
    private static final Host SERVER_HOST = new DefaultHost(Dhcp4HandlerImpl.PROVIDER_ID,
                                                            SERVER_HOST_ID,
                                                            SERVER_MAC,
                                                            SERVER_VLAN,
                                                            SERVER_LOCATION,
                                                            DHCP_SERVER_IPS);
    private static final MacAddress SERVER_IFACE_MAC = MacAddress.valueOf("00:00:00:00:00:01");
    private static final Interface SERVER_INTERFACE = createInterface("SERVER",
                                                                      SERVER_CONNECT_POINT,
                                                                      INTERFACE_IPS,
                                                                      SERVER_IFACE_MAC,
                                                                      SERVER_VLAN,
                                                                      SERVER_VLAN_NATIVE);

    // Relay agent config
    private static final Ip4Address RELAY_AGENT_IP = Ip4Address.valueOf("10.0.4.254");

    private static final List<TrafficSelector> DHCP_SELECTORS = buildClientDhcpSelectors();

    // Components
    private static final ApplicationId APP_ID = TestApplicationId.create(DhcpRelayManager.DHCP_RELAY_APP);
    private static final DefaultDhcpRelayConfig CONFIG = new MockDefaultDhcpRelayConfig();
    private static final IndirectDhcpRelayConfig CONFIG_INDIRECT = new MockIndirectDhcpRelayConfig();
    private static final Set<Interface> INTERFACES = ImmutableSet.of(
            CLIENT_INTERFACE,
            CLIENT2_INTERFACE,
            SERVER_INTERFACE,
            CLIENT_DH_INTERFACE
    );
    private static final String NON_ONOS_CID = "Non-ONOS circuit ID";
    private static final VlanId IGNORED_VLAN = VlanId.vlanId("100");
    private static final int IGNORE_CONTROL_PRIORITY = PacketPriority.CONTROL.priorityValue() + 1000;

    private DhcpRelayManager manager;
    private MockPacketService packetService;
    private MockRouteStore mockRouteStore;
    private MockDhcpRelayStore mockDhcpRelayStore;
    private HostProviderService mockHostProviderService;
    private FlowObjectiveService flowObjectiveService;
    private DeviceService deviceService;
    private Dhcp4HandlerImpl v4Handler;
    private Dhcp6HandlerImpl v6Handler;

    private static Interface createInterface(String name, ConnectPoint connectPoint,
                                             List<InterfaceIpAddress> interfaceIps,
                                             MacAddress macAddress,
                                             VlanId vlanId,
                                             VlanId vlanNative) {

        if (vlanId.equals(VlanId.NONE)) {
            return new Interface(name, connectPoint, interfaceIps, macAddress, vlanId,
                                 null, null, vlanNative);
        } else {
            return new Interface(name, connectPoint, interfaceIps, macAddress, vlanId,
                                 null, ImmutableSet.of(vlanId), null);
        }
    }

    @Before
    public void setup() {
        manager = new DhcpRelayManager();
        manager.cfgService = createNiceMock(NetworkConfigRegistry.class);

        expect(manager.cfgService.getConfig(APP_ID, DefaultDhcpRelayConfig.class))
                .andReturn(CONFIG)
                .anyTimes();

        expect(manager.cfgService.getConfig(APP_ID, IndirectDhcpRelayConfig.class))
                .andReturn(CONFIG_INDIRECT)
                .anyTimes();

        manager.coreService = createNiceMock(CoreService.class);
        expect(manager.coreService.registerApplication(anyString()))
                .andReturn(APP_ID).anyTimes();

        manager.hostService = createNiceMock(HostService.class);
        expect(manager.hostService.getHostsByIp(anyObject())).andReturn(ImmutableSet.of(SERVER_HOST)).anyTimes();
        expect(manager.hostService.getHost(OUTER_RELAY_HOST_ID)).andReturn(OUTER_RELAY_HOST).anyTimes();

        packetService = new MockPacketService();
        manager.packetService = packetService;
        manager.compCfgService = createNiceMock(ComponentConfigService.class);
        deviceService = createNiceMock(DeviceService.class);

        Device device = createNiceMock(Device.class);
        expect(device.is(Pipeliner.class)).andReturn(true).anyTimes();

        expect(deviceService.getDevice(DEV_1_ID)).andReturn(device).anyTimes();
        expect(deviceService.getDevice(DEV_2_ID)).andReturn(device).anyTimes();
        replay(deviceService, device);

        mockRouteStore = new MockRouteStore();
        mockDhcpRelayStore = new MockDhcpRelayStore();
        manager.dhcpRelayStore = mockDhcpRelayStore;
        manager.deviceService = deviceService;

        manager.interfaceService = new MockInterfaceService();
        flowObjectiveService = EasyMock.niceMock(FlowObjectiveService.class);
        mockHostProviderService = createNiceMock(HostProviderService.class);
        v4Handler = new Dhcp4HandlerImpl();
        v4Handler.providerService = mockHostProviderService;
        v4Handler.dhcpRelayStore = mockDhcpRelayStore;
        v4Handler.hostService = manager.hostService;
        v4Handler.interfaceService = manager.interfaceService;
        v4Handler.packetService = manager.packetService;
        v4Handler.routeStore = mockRouteStore;
        v4Handler.coreService = createNiceMock(CoreService.class);
        v4Handler.flowObjectiveService = flowObjectiveService;
        v4Handler.appId = TestApplicationId.create(Dhcp4HandlerImpl.DHCP_V4_RELAY_APP);
        v4Handler.deviceService = deviceService;
        manager.v4Handler = v4Handler;

        v6Handler = new Dhcp6HandlerImpl();
        v6Handler.dhcpRelayStore = mockDhcpRelayStore;
        v6Handler.hostService = manager.hostService;
        v6Handler.interfaceService = manager.interfaceService;
        v6Handler.packetService = manager.packetService;
        v6Handler.routeStore = mockRouteStore;
        v6Handler.providerService = mockHostProviderService;
        v6Handler.coreService = createNiceMock(CoreService.class);
        v6Handler.flowObjectiveService = flowObjectiveService;
        v6Handler.appId = TestApplicationId.create(Dhcp6HandlerImpl.DHCP_V6_RELAY_APP);
        v6Handler.deviceService = deviceService;
        manager.v6Handler = v6Handler;

        // properties
        Dictionary<String, Object> dictionary = createNiceMock(Dictionary.class);
        expect(dictionary.get("arpEnabled")).andReturn(true).anyTimes();
        ComponentContext context = createNiceMock(ComponentContext.class);
        expect(context.getProperties()).andReturn(dictionary).anyTimes();

        replay(manager.cfgService, manager.coreService, manager.hostService,
               manager.compCfgService, dictionary, context);
        manager.activate(context);
    }

    @After
    public void tearDown() {
        manager.deactivate();
    }

    /**
     * Relay a DHCP packet without option 82.
     * Should add new host to host store after dhcp ack.
     */
    @Test
    public void relayDhcpWithoutAgentInfo() {
        replay(mockHostProviderService);
        // send request
        packetService.processPacket(new TestDhcpRequestPacketContext(CLIENT_MAC,
                                                                     CLIENT_VLAN,
                                                                     CLIENT_CP,
                                                                     INTERFACE_IP.ipAddress().getIp4Address(),
                                                                     false));
        // won't trigger the host provider service
        verify(mockHostProviderService);
        reset(mockHostProviderService);

        assertEquals(0, mockRouteStore.routes.size());

        HostId expectHostId = HostId.hostId(CLIENT_MAC, CLIENT_VLAN);
        Capture<HostDescription> capturedHostDesc = newCapture();
        mockHostProviderService.hostDetected(eq(expectHostId), capture(capturedHostDesc), eq(false));
        replay(mockHostProviderService);
        // send ack
        packetService.processPacket(new TestDhcpAckPacketContext(CLIENT_CP, CLIENT_MAC,
                                                                 CLIENT_VLAN, INTERFACE_IP.ipAddress().getIp4Address(),
                                                                 false));
        verify(mockHostProviderService);
        assertEquals(0, mockRouteStore.routes.size());

        HostDescription host = capturedHostDesc.getValue();
        assertEquals(false, host.configured());
        assertEquals(CLIENT_CP.deviceId(), host.location().elementId());
        assertEquals(CLIENT_CP.port(), host.location().port());
        assertEquals(1, host.ipAddress().size());
        assertEquals(IP_FOR_CLIENT, host.ipAddress().iterator().next());
    }

    /**
     * Relay a DHCP packet with option 82 (Indirectly connected host).
     */
    @Test
    public void relayDhcpWithAgentInfo() {
        replay(mockHostProviderService);
        // Assume outer dhcp relay agent exists in store already
        // send request
        packetService.processPacket(new TestDhcpRequestPacketContext(CLIENT2_MAC,
                                                                     CLIENT2_VLAN,
                                                                     CLIENT2_CP,
                                                                     INTERFACE_IP.ipAddress().getIp4Address(),
                                                                     true));
        // No routes
        assertEquals(0, mockRouteStore.routes.size());
        // send ack
        packetService.processPacket(new TestDhcpAckPacketContext(CLIENT2_CP,
                                                                 CLIENT2_MAC,
                                                                 CLIENT2_VLAN,
                                                                 INTERFACE_IP.ipAddress().getIp4Address(),
                                                                 true));

        // won't trigger the host provider service
        verify(mockHostProviderService);
        reset(mockHostProviderService);

        assertEquals(1, mockRouteStore.routes.size());

        Route route = mockRouteStore.routes.get(0);
        assertEquals(OUTER_RELAY_IP, route.nextHop());
        assertEquals(IP_FOR_CLIENT.toIpPrefix(), route.prefix());
        assertEquals(Route.Source.STATIC, route.source());
    }

    @Test
    public void testWithRelayAgentConfig() throws DeserializationException {
        manager.v4Handler
                .setDefaultDhcpServerConfigs(ImmutableList.of(new MockDhcpServerConfig(RELAY_AGENT_IP)));
        manager.v4Handler
                .setIndirectDhcpServerConfigs(ImmutableList.of(new MockDhcpServerConfig(RELAY_AGENT_IP)));
        packetService.processPacket(new TestDhcpRequestPacketContext(CLIENT2_MAC,
                                                                     CLIENT2_VLAN,
                                                                     CLIENT2_CP,
                                                                     INTERFACE_IP.ipAddress().getIp4Address(),
                                                                     true));
        OutboundPacket outPacket = packetService.emittedPacket;
        byte[] outData = outPacket.data().array();
        Ethernet eth = Ethernet.deserializer().deserialize(outData, 0, outData.length);
        IPv4 ip = (IPv4) eth.getPayload();
        UDP udp = (UDP) ip.getPayload();
        DHCP dhcp = (DHCP) udp.getPayload();
        assertEquals(RELAY_AGENT_IP.toInt(), dhcp.getGatewayIPAddress());
    }

    @Test
    public void testArpRequest() throws Exception {
        packetService.processPacket(new TestArpRequestPacketContext(CLIENT_INTERFACE));
        OutboundPacket outboundPacket = packetService.emittedPacket;
        byte[] outPacketData = outboundPacket.data().array();
        Ethernet eth = Ethernet.deserializer().deserialize(outPacketData, 0, outPacketData.length);

        assertEquals(eth.getEtherType(), Ethernet.TYPE_ARP);
        ARP arp = (ARP) eth.getPayload();
        assertArrayEquals(arp.getSenderHardwareAddress(), CLIENT_INTERFACE.mac().toBytes());
    }

    /**
     * Ignores specific vlans from specific devices if config.
     *
     * @throws Exception the exception from this test
     */
    @Test
    public void testIgnoreVlan() throws Exception {
        ObjectMapper om = new ObjectMapper();
        JsonNode json = om.readTree(Resources.getResource(CONFIG_FILE_PATH));
        IgnoreDhcpConfig config = new IgnoreDhcpConfig();
        json = json.path("apps").path(DHCP_RELAY_APP).path(IgnoreDhcpConfig.KEY);
        config.init(APP_ID, IgnoreDhcpConfig.KEY, json, om, null);

        Capture<Objective> capturedFromDev1 = newCapture(CaptureType.ALL);
        flowObjectiveService.apply(eq(DEV_1_ID), capture(capturedFromDev1));
        expectLastCall().times(DHCP_SELECTORS.size());
        Capture<Objective> capturedFromDev2 = newCapture(CaptureType.ALL);
        flowObjectiveService.apply(eq(DEV_2_ID), capture(capturedFromDev2));
        expectLastCall().times(DHCP_SELECTORS.size());
        replay(flowObjectiveService);
        manager.updateConfig(config);
        verify(flowObjectiveService);

        List<Objective> objectivesFromDev1 = capturedFromDev1.getValues();
        List<Objective> objectivesFromDev2 = capturedFromDev2.getValues();

        assertTrue(objectivesFromDev1.containsAll(objectivesFromDev2));
        assertTrue(objectivesFromDev2.containsAll(objectivesFromDev1));
        TrafficTreatment dropTreatment = DefaultTrafficTreatment.builder().wipeDeferred().build();

        for (int index = 0; index < objectivesFromDev1.size(); index++) {
            TrafficSelector selector =
                    DefaultTrafficSelector.builder(DHCP_SELECTORS.get(index))
                    .matchVlanId(IGNORED_VLAN)
                    .build();
            ForwardingObjective fwd = (ForwardingObjective) objectivesFromDev1.get(index);
            assertEquals(selector, fwd.selector());
            assertEquals(dropTreatment, fwd.treatment());
            assertEquals(IGNORE_CONTROL_PRIORITY, fwd.priority());
            assertEquals(ForwardingObjective.Flag.VERSATILE, fwd.flag());
            assertEquals(Objective.Operation.ADD, fwd.op());
            fwd.context().ifPresent(ctx -> {
                ctx.onSuccess(fwd);
            });
        }
        objectivesFromDev2.forEach(obj -> obj.context().ifPresent(ctx -> ctx.onSuccess(obj)));
        assertEquals(2, v4Handler.ignoredVlans.size());
        assertEquals(2, v6Handler.ignoredVlans.size());
    }

    /**
     * "IgnoreVlan" policy should be removed when the config removed.
     */
    @Test
    public void testRemoveIgnoreVlan() {
        v4Handler.ignoredVlans.put(DEV_1_ID, IGNORED_VLAN);
        v4Handler.ignoredVlans.put(DEV_2_ID, IGNORED_VLAN);
        v6Handler.ignoredVlans.put(DEV_1_ID, IGNORED_VLAN);
        v6Handler.ignoredVlans.put(DEV_2_ID, IGNORED_VLAN);
        IgnoreDhcpConfig config = new IgnoreDhcpConfig();

        Capture<Objective> capturedFromDev1 = newCapture(CaptureType.ALL);
        flowObjectiveService.apply(eq(DEV_1_ID), capture(capturedFromDev1));
        expectLastCall().times(DHCP_SELECTORS.size());
        Capture<Objective> capturedFromDev2 = newCapture(CaptureType.ALL);
        flowObjectiveService.apply(eq(DEV_2_ID), capture(capturedFromDev2));
        expectLastCall().times(DHCP_SELECTORS.size());
        replay(flowObjectiveService);
        manager.removeConfig(config);
        verify(flowObjectiveService);

        List<Objective> objectivesFromDev1 = capturedFromDev1.getValues();
        List<Objective> objectivesFromDev2 = capturedFromDev2.getValues();

        assertTrue(objectivesFromDev1.containsAll(objectivesFromDev2));
        assertTrue(objectivesFromDev2.containsAll(objectivesFromDev1));
        TrafficTreatment dropTreatment = DefaultTrafficTreatment.builder().wipeDeferred().build();

        for (int index = 0; index < objectivesFromDev1.size(); index++) {
            TrafficSelector selector =
                    DefaultTrafficSelector.builder(DHCP_SELECTORS.get(index))
                    .matchVlanId(IGNORED_VLAN)
                    .build();
            ForwardingObjective fwd = (ForwardingObjective) objectivesFromDev1.get(index);
            assertEquals(selector, fwd.selector());
            assertEquals(dropTreatment, fwd.treatment());
            assertEquals(IGNORE_CONTROL_PRIORITY, fwd.priority());
            assertEquals(ForwardingObjective.Flag.VERSATILE, fwd.flag());
            assertEquals(Objective.Operation.REMOVE, fwd.op());
            fwd.context().ifPresent(ctx -> {
                ctx.onSuccess(fwd);
            });
        }
        objectivesFromDev2.forEach(obj -> obj.context().ifPresent(ctx -> ctx.onSuccess(obj)));
        assertEquals(0, v4Handler.ignoredVlans.size());
        assertEquals(0, v6Handler.ignoredVlans.size());
    }

    /**
     * Should ignore ignore rules installation when device not available.
     */
    @Test
    public void testIgnoreUnknownDevice() throws IOException {
        reset(manager.deviceService);
        Device device = createNiceMock(Device.class);
        expect(device.is(Pipeliner.class)).andReturn(true).anyTimes();

        expect(manager.deviceService.getDevice(DEV_1_ID)).andReturn(device).anyTimes();
        expect(manager.deviceService.getDevice(DEV_2_ID)).andReturn(null).anyTimes();

        ObjectMapper om = new ObjectMapper();
        JsonNode json = om.readTree(Resources.getResource(CONFIG_FILE_PATH));
        IgnoreDhcpConfig config = new IgnoreDhcpConfig();
        json = json.path("apps").path(DHCP_RELAY_APP).path(IgnoreDhcpConfig.KEY);
        config.init(APP_ID, IgnoreDhcpConfig.KEY, json, om, null);

        Capture<Objective> capturedFromDev1 = newCapture(CaptureType.ALL);
        flowObjectiveService.apply(eq(DEV_1_ID), capture(capturedFromDev1));
        expectLastCall().times(DHCP_SELECTORS.size());
        replay(flowObjectiveService, manager.deviceService, device);

        manager.updateConfig(config);
        capturedFromDev1.getValues().forEach(obj -> obj.context().ifPresent(ctx -> ctx.onSuccess(obj)));

        assertEquals(1, v4Handler.ignoredVlans.size());
        assertEquals(1, v6Handler.ignoredVlans.size());
    }

    /**
     * Should try install ignore rules when device comes up.
     */
    @Test
    public void testInstallIgnoreRuleWhenDeviceComesUp() throws IOException {
        ObjectMapper om = new ObjectMapper();
        JsonNode json = om.readTree(Resources.getResource(CONFIG_FILE_PATH));
        IgnoreDhcpConfig config = new IgnoreDhcpConfig();
        json = json.path("apps").path(DHCP_RELAY_APP).path(IgnoreDhcpConfig.KEY);
        config.init(APP_ID, IgnoreDhcpConfig.KEY, json, om, null);

        reset(manager.cfgService, flowObjectiveService, manager.deviceService);
        expect(manager.cfgService.getConfig(APP_ID, IgnoreDhcpConfig.class))
                .andReturn(config).anyTimes();

        Device device = createNiceMock(Device.class);
        expect(device.is(Pipeliner.class)).andReturn(true).anyTimes();
        expect(device.id()).andReturn(DEV_1_ID).anyTimes();
        expect(manager.deviceService.getDevice(DEV_1_ID)).andReturn(device).anyTimes();
        DeviceEvent event = new DeviceEvent(DeviceEvent.Type.DEVICE_ADDED, device);
        Capture<Objective> capturedFromDev1 = newCapture(CaptureType.ALL);
        flowObjectiveService.apply(eq(DEV_1_ID), capture(capturedFromDev1));
        expectLastCall().times(DHCP_SELECTORS.size());
        replay(manager.cfgService, flowObjectiveService, manager.deviceService, device);
        manager.deviceListener.event(event);
        capturedFromDev1.getValues().forEach(obj -> obj.context().ifPresent(ctx -> ctx.onSuccess(obj)));
        assertEquals(1, v4Handler.ignoredVlans.size());
        assertEquals(1, v6Handler.ignoredVlans.size());
    }

    /**
     * Relay a DHCP6 packet without relay option
     * Note: Should add new host to host store after dhcp ack.
     */
    @Test
    public void relayDhcp6WithoutAgentInfo() {
        replay(mockHostProviderService);
        // send request
        packetService.processPacket(new TestDhcp6RequestPacketContext(DHCP6.MsgType.REQUEST.value(),
                                                                     CLIENT_MAC,
                                                                     CLIENT_VLAN,
                                                                     CLIENT_CP,
                                                                     INTERFACE_IP_V6.ipAddress().getIp6Address(),
                                                                     0));

        verify(mockHostProviderService);
        reset(mockHostProviderService);
        assertEquals(0, mockRouteStore.routes.size());

        Capture<HostDescription> capturedHostDesc = newCapture();
        mockHostProviderService.hostDetected(eq(HostId.hostId(CLIENT_MAC, CLIENT_VLAN)),
                                             capture(capturedHostDesc), eq(false));
        replay(mockHostProviderService);
        // send reply
        packetService.processPacket(new TestDhcp6ReplyPacketContext(DHCP6.MsgType.REPLY.value(),
                                                                    CLIENT_CP, CLIENT_MAC,
                                                                    CLIENT_VLAN,
                                                                    INTERFACE_IP_V6.ipAddress().getIp6Address(),
                                                                    0));
        verify(mockHostProviderService);
        assertEquals(0, mockRouteStore.routes.size());

        HostDescription host = capturedHostDesc.getValue();
        assertEquals(CLIENT_VLAN, host.vlan());
        assertEquals(CLIENT_CP.deviceId(), host.location().elementId());
        assertEquals(CLIENT_CP.port(), host.location().port());
        assertEquals(1, host.ipAddress().size());
        assertEquals(IP_FOR_CLIENT_V6, host.ipAddress().iterator().next());

        // send release
        packetService.processPacket(new TestDhcp6RequestPacketContext(DHCP6.MsgType.RELEASE.value(),
                CLIENT_MAC,
                CLIENT_VLAN,
                CLIENT_CP,
                INTERFACE_IP_V6.ipAddress().getIp6Address(),
                0));

        assertEquals(null, manager.hostService.getHost(HostId.hostId(CLIENT_MAC, CLIENT_VLAN)));
    }

    /**
     * Relay a DHCP6 packet with Relay Message opion (Indirectly connected host).
     */
    @Test
    public void relayDhcp6WithAgentInfo() {
        replay(mockHostProviderService);
        // Assume outer dhcp6 relay agent exists in store already
        // send request
        packetService.processPacket(new TestDhcp6RequestPacketContext(DHCP6.MsgType.REQUEST.value(),
                CLIENT2_MAC,
                CLIENT2_VLAN,
                CLIENT2_CP,
                OUTER_RELAY_IP_V6,
                1));

        assertEquals(0, mockRouteStore.routes.size());

        // send reply
        packetService.processPacket(new TestDhcp6ReplyPacketContext(DHCP6.MsgType.REPLY.value(), CLIENT2_CP,
                CLIENT2_MAC,
                CLIENT2_VLAN,
                OUTER_RELAY_IP_V6,
                1));

        // won't trigger the host provider service
        verify(mockHostProviderService);
        reset(mockHostProviderService);
        assertEquals(2, mockRouteStore.routes.size()); // ipAddress and prefix

        Route aRoute = mockRouteStore.routes.stream()
                             .filter(rt -> rt.prefix().contains(IP_FOR_CLIENT_V6))
                             .findFirst()
                             .orElse(null);
        assertNotEquals(null, aRoute);

        aRoute = mockRouteStore.routes.stream()
                .filter(rt -> rt.prefix().contains(PREFIX_FOR_CLIENT_V6))
                .findFirst()
                .orElse(null);
        assertNotEquals(null, aRoute);

        // send release msg
        packetService.processPacket(new TestDhcp6RequestPacketContext(DHCP6.MsgType.RELEASE.value(),
                CLIENT2_MAC,
                CLIENT2_VLAN,
                CLIENT2_CP,
                OUTER_RELAY_IP_V6,
                1));

        aRoute = mockRouteStore.routes.stream()
                .filter(rt -> rt.prefix().contains(IP_FOR_CLIENT_V6))
                .findFirst()
                .orElse(null);
        assertEquals(null, aRoute);

        aRoute = mockRouteStore.routes.stream()
                .filter(rt -> rt.prefix().contains(PREFIX_FOR_CLIENT_V6))
                .findFirst()
                .orElse(null);
        assertEquals(null, aRoute);

        assertEquals(0, mockRouteStore.routes.size());

    }

    /**
     * Relay a DHCP6 packet with Relay Message opion (Indirectly connected host) and server responded
     * with vlan differnt from client interface vlan.
     */
    @Test
    public void relayDhcp6WithAgentInfoWrongVlan() {
        replay(mockHostProviderService);
        // Assume outer dhcp6 relay agent exists in store already
        // send request
        packetService.processPacket(new TestDhcp6RequestPacketContext(DHCP6.MsgType.REQUEST.value(),
                CLIENT2_MAC,
                CLIENT2_VLAN,
                CLIENT2_CP,
                INTERFACE_IP_V6.ipAddress().getIp6Address(),
                1));

        assertEquals(0, mockRouteStore.routes.size());

        // send reply
        packetService.processPacket(new TestDhcp6ReplyPacketContext(DHCP6.MsgType.REPLY.value(),
                CLIENT2_CP,
                CLIENT2_MAC,
                CLIENT_BOGUS_VLAN,  // mismatch
                INTERFACE_IP_V6.ipAddress().getIp6Address(),
                1));

        // won't trigger the host provider service
        verify(mockHostProviderService);
        reset(mockHostProviderService);
        assertEquals(0, mockRouteStore.routes.size()); // ipAddress and prefix

    }


    @Test
    public void testDhcp4DualHome() {
        PacketContext packetContext =
                new TestDhcpAckPacketContext(CLIENT_DH_CP, CLIENT_MAC, CLIENT_VLAN,
                                             INTERFACE_IP.ipAddress().getIp4Address(),
                                             false);
        reset(manager.hostService);
        expect(manager.hostService.getHost(CLIENT_HOST_ID)).andReturn(EXISTS_HOST).anyTimes();
        Capture<HostDescription> capturedHostDesc = newCapture();
        mockHostProviderService.hostDetected(eq(CLIENT_HOST_ID), capture(capturedHostDesc), eq(false));
        replay(mockHostProviderService, manager.hostService);
        packetService.processPacket(packetContext);
        verify(mockHostProviderService);

        HostDescription hostDesc = capturedHostDesc.getValue();
        Set<HostLocation> hostLocations = hostDesc.locations();
        assertEquals(2, hostLocations.size());
        assertTrue(hostLocations.contains(CLIENT_LOCATION));
        assertTrue(hostLocations.contains(CLIENT_DH_LOCATION));
    }

    @Test
    public void testDhcp6DualHome() {
        PacketContext packetContext =
                new TestDhcp6ReplyPacketContext(DHCP6.MsgType.REPLY.value(),
                                                CLIENT_DH_CP, CLIENT_MAC, CLIENT_VLAN,
                                                INTERFACE_IP_V6.ipAddress().getIp6Address(),
                                                0);
        reset(manager.hostService);
        expect(manager.hostService.getHostsByIp(CLIENT_LL_IP_V6)).andReturn(ImmutableSet.of(EXISTS_HOST)).anyTimes();

        // FIXME: currently DHCPv6 has a bug, we can't get correct vlan of client......
        // XXX: The vlan relied from DHCP6 handler might be wrong, do hack here
        HostId hostId = HostId.hostId(CLIENT_MAC, VlanId.NONE);
        expect(manager.hostService.getHost(hostId)).andReturn(EXISTS_HOST).anyTimes();

        // XXX: sometimes this will work, sometimes not
         expect(manager.hostService.getHost(CLIENT_HOST_ID)).andReturn(EXISTS_HOST).anyTimes();

        Capture<HostDescription> capturedHostDesc = newCapture();

        // XXX: also a hack here
        mockHostProviderService.hostDetected(eq(hostId), capture(capturedHostDesc), eq(false));
        expectLastCall().anyTimes();

        mockHostProviderService.hostDetected(eq(CLIENT_HOST_ID), capture(capturedHostDesc), eq(false));
        expectLastCall().anyTimes();
        replay(mockHostProviderService, manager.hostService);
        packetService.processPacket(packetContext);
        verify(mockHostProviderService);

        HostDescription hostDesc = capturedHostDesc.getValue();
        Set<HostLocation> hostLocations = hostDesc.locations();
        assertEquals(2, hostLocations.size());
        assertTrue(hostLocations.contains(CLIENT_LOCATION));
        assertTrue(hostLocations.contains(CLIENT_DH_LOCATION));
    }

    private static class MockDefaultDhcpRelayConfig extends DefaultDhcpRelayConfig {
        @Override
        public boolean isValid() {
            return true;
        }

        @Override
        public List<DhcpServerConfig> dhcpServerConfigs() {
            return ImmutableList.of(new MockDhcpServerConfig(null));
        }
    }

    private static class MockIndirectDhcpRelayConfig extends IndirectDhcpRelayConfig {
        @Override
        public boolean isValid() {
            return true;
        }

        @Override
        public List<DhcpServerConfig> dhcpServerConfigs() {
            return ImmutableList.of(new MockDhcpServerConfig(null));
        }
    }

    private static class MockDhcpServerConfig extends DhcpServerConfig {
        Ip4Address relayAgentIp;

        /**
         * Create mocked version DHCP server config.
         *
         * @param relayAgentIp the relay agent Ip config; null if we don't need it
         */
        public MockDhcpServerConfig(Ip4Address relayAgentIp) {
            this.relayAgentIp = relayAgentIp;
        }

        @Override
        public Optional<Ip4Address> getRelayAgentIp4() {
            return Optional.ofNullable(relayAgentIp);
        }

        @Override
        public Optional<ConnectPoint> getDhcpServerConnectPoint() {
            return Optional.of(SERVER_CONNECT_POINT);
        }

        @Override
        public Optional<Ip4Address> getDhcpServerIp4() {
            return Optional.of(SERVER_IP);
        }

        @Override
        public Optional<Ip4Address> getDhcpGatewayIp4() {
            return Optional.of(GATEWAY_IP);
        }

        @Override
        public Optional<Ip6Address> getDhcpServerIp6() {
            return Optional.of(SERVER_IP_V6);
        }

        @Override
        public Optional<Ip6Address> getDhcpGatewayIp6() {
            return Optional.of(GATEWAY_IP_V6);
        }
    }

    private class MockRouteStore extends RouteStoreAdapter {
        private List<Route> routes = Lists.newArrayList();

        @Override
        public void updateRoute(Route route) {
            routes.add(route);
        }

        @Override
        public void removeRoute(Route route) {
            routes.remove(route);
        }
    }

    private class MockInterfaceService extends InterfaceServiceAdapter {

        @Override
        public Set<Interface> getInterfaces() {
            return INTERFACES;
        }

        @Override
        public Set<Interface> getInterfacesByIp(IpAddress ip) {
            return INTERFACES.stream()
                    .filter(iface -> {
                        return iface.ipAddressesList().stream()
                                .anyMatch(ifaceIp -> ifaceIp.ipAddress().equals(ip));
                    })
                    .collect(Collectors.toSet());
        }

        @Override
        public Set<Interface> getInterfacesByPort(ConnectPoint port) {
            return INTERFACES.stream()
                    .filter(iface -> iface.connectPoint().equals(port))
                    .collect(Collectors.toSet());
        }
    }

    private class MockDhcpRelayStore implements DhcpRelayStore {
        StoreDelegate<DhcpRelayStoreEvent> delegate;
        private Map<HostId, DhcpRecord> records = Maps.newHashMap();

        @Override
        public void updateDhcpRecord(HostId hostId, DhcpRecord dhcpRecord) {
            records.put(hostId, dhcpRecord);
            DhcpRelayStoreEvent event = new DhcpRelayStoreEvent(DhcpRelayStoreEvent.Type.UPDATED,
                                                                dhcpRecord);
            if (delegate != null) {
                delegate.notify(event);
            }
        }

        @Override
        public Optional<DhcpRecord> getDhcpRecord(HostId hostId) {
            return Optional.ofNullable(records.get(hostId));
        }

        @Override
        public Collection<DhcpRecord> getDhcpRecords() {
            return records.values();
        }

        @Override
        public Optional<DhcpRecord> removeDhcpRecord(HostId hostId) {
            DhcpRecord dhcpRecord = records.remove(hostId);
            if (dhcpRecord != null) {
                DhcpRelayStoreEvent event = new DhcpRelayStoreEvent(DhcpRelayStoreEvent.Type.REMOVED,
                                                                    dhcpRecord);
                if (delegate != null) {
                    delegate.notify(event);
                }
            }
            return Optional.ofNullable(dhcpRecord);
        }

        @Override
        public void setDelegate(StoreDelegate<DhcpRelayStoreEvent> delegate) {
            this.delegate = delegate;
        }

        @Override
        public void unsetDelegate(StoreDelegate<DhcpRelayStoreEvent> delegate) {
            this.delegate = null;
        }

        @Override
        public boolean hasDelegate() {
            return this.delegate != null;
        }
    }

    private class MockPacketService extends PacketServiceAdapter {
        Set<PacketProcessor> packetProcessors = Sets.newHashSet();
        OutboundPacket emittedPacket;

        @Override
        public void addProcessor(PacketProcessor processor, int priority) {
            packetProcessors.add(processor);
        }

        public void processPacket(PacketContext packetContext) {
            packetProcessors.forEach(p -> p.process(packetContext));
        }

        @Override
        public void emit(OutboundPacket packet) {
            this.emittedPacket = packet;
        }
    }



    /**
     * Generates DHCP REQUEST packet.
     */
    private class TestDhcpRequestPacketContext extends PacketContextAdapter {


        private InboundPacket inPacket;

        public TestDhcpRequestPacketContext(MacAddress clientMac, VlanId vlanId,
                                            ConnectPoint clientCp,
                                            Ip4Address clientGwAddr,
                                            boolean withNonOnosRelayInfo) {
            super(0, null, null, false);
            byte[] dhcpMsgType = new byte[1];
            dhcpMsgType[0] = (byte) DHCP.MsgType.DHCPREQUEST.getValue();

            DhcpOption dhcpOption = new DhcpOption();
            dhcpOption.setCode(DHCP.DHCPOptionCode.OptionCode_MessageType.getValue());
            dhcpOption.setData(dhcpMsgType);
            dhcpOption.setLength((byte) 1);
            DhcpOption endOption = new DhcpOption();
            endOption.setCode(DHCP.DHCPOptionCode.OptionCode_END.getValue());

            DHCP dhcp = new DHCP();
            dhcp.setHardwareType(DHCP.HWTYPE_ETHERNET);
            dhcp.setHardwareAddressLength((byte) 6);
            dhcp.setClientHardwareAddress(clientMac.toBytes());
            if (withNonOnosRelayInfo) {
                DhcpRelayAgentOption relayOption = new DhcpRelayAgentOption();
                DhcpOption circuitIdOption = new DhcpOption();
                CircuitId circuitId = new CircuitId("Custom option", VlanId.NONE);
                byte[] cid = circuitId.serialize();
                circuitIdOption.setCode(DhcpRelayAgentOption.RelayAgentInfoOptions.CIRCUIT_ID.getValue());
                circuitIdOption.setLength((byte) cid.length);
                circuitIdOption.setData(cid);
                relayOption.setCode(DHCP.DHCPOptionCode.OptionCode_CircuitID.getValue());
                relayOption.addSubOption(circuitIdOption);
                dhcp.setOptions(ImmutableList.of(dhcpOption, relayOption, endOption));
                dhcp.setGatewayIPAddress(OUTER_RELAY_IP.getIp4Address().toInt());
            } else {
                dhcp.setOptions(ImmutableList.of(dhcpOption, endOption));
            }


            UDP udp = new UDP();
            udp.setPayload(dhcp);
            udp.setSourcePort(UDP.DHCP_CLIENT_PORT);
            udp.setDestinationPort(UDP.DHCP_SERVER_PORT);

            IPv4 ipv4 = new IPv4();
            ipv4.setPayload(udp);
            ipv4.setDestinationAddress(SERVER_IP.toInt());
            ipv4.setSourceAddress(clientGwAddr.toInt());

            Ethernet eth = new Ethernet();
            if (withNonOnosRelayInfo) {
                eth.setEtherType(Ethernet.TYPE_IPV4)
                        .setVlanID(vlanId.toShort())
                        .setSourceMACAddress(OUTER_RELAY_MAC)
                        .setDestinationMACAddress(MacAddress.BROADCAST)
                        .setPayload(ipv4);
            } else {
                eth.setEtherType(Ethernet.TYPE_IPV4)
                        .setVlanID(vlanId.toShort())
                        .setSourceMACAddress(clientMac)
                        .setDestinationMACAddress(MacAddress.BROADCAST)
                        .setPayload(ipv4);
            }

            this.inPacket = new DefaultInboundPacket(clientCp, eth,
                                                     ByteBuffer.wrap(eth.serialize()));
        }

        @Override
        public InboundPacket inPacket() {
            return this.inPacket;
        }
    }

    /**
     * Generates DHCP ACK packet.
     */
    private class TestDhcpAckPacketContext extends PacketContextAdapter {
        private InboundPacket inPacket;

        public TestDhcpAckPacketContext(ConnectPoint clientCp, MacAddress clientMac,
                                        VlanId clientVlan, Ip4Address clientGwAddr,
                                        boolean withNonOnosRelayInfo) {
            super(0, null, null, false);

            byte[] dhcpMsgType = new byte[1];
            dhcpMsgType[0] = (byte) DHCP.MsgType.DHCPACK.getValue();

            DhcpOption dhcpOption = new DhcpOption();
            dhcpOption.setCode(DHCP.DHCPOptionCode.OptionCode_MessageType.getValue());
            dhcpOption.setData(dhcpMsgType);
            dhcpOption.setLength((byte) 1);

            DhcpOption endOption = new DhcpOption();
            endOption.setCode(DHCP.DHCPOptionCode.OptionCode_END.getValue());

            DHCP dhcp = new DHCP();
            if (withNonOnosRelayInfo) {
                DhcpRelayAgentOption relayOption = new DhcpRelayAgentOption();
                DhcpOption circuitIdOption = new DhcpOption();
                String circuitId = NON_ONOS_CID;
                byte[] cid = circuitId.getBytes(Charsets.US_ASCII);
                circuitIdOption.setCode(DhcpRelayAgentOption.RelayAgentInfoOptions.CIRCUIT_ID.getValue());
                circuitIdOption.setLength((byte) cid.length);
                circuitIdOption.setData(cid);
                relayOption.setCode(DHCP.DHCPOptionCode.OptionCode_CircuitID.getValue());
                relayOption.addSubOption(circuitIdOption);
                dhcp.setOptions(ImmutableList.of(dhcpOption, relayOption, endOption));
                dhcp.setGatewayIPAddress(OUTER_RELAY_IP.getIp4Address().toInt());
            } else {
                CircuitId cid = new CircuitId(clientCp.toString(), clientVlan);
                byte[] circuitId = cid.serialize();
                DhcpOption circuitIdSubOption = new DhcpOption();
                circuitIdSubOption.setCode(DhcpRelayAgentOption.RelayAgentInfoOptions.CIRCUIT_ID.getValue());
                circuitIdSubOption.setData(circuitId);
                circuitIdSubOption.setLength((byte) circuitId.length);

                DhcpRelayAgentOption relayInfoOption = new DhcpRelayAgentOption();
                relayInfoOption.setCode(DHCP.DHCPOptionCode.OptionCode_CircuitID.getValue());
                relayInfoOption.addSubOption(circuitIdSubOption);
                dhcp.setOptions(ImmutableList.of(dhcpOption, relayInfoOption, endOption));
                dhcp.setGatewayIPAddress(clientGwAddr.toInt());
            }
            dhcp.setHardwareType(DHCP.HWTYPE_ETHERNET);
            dhcp.setHardwareAddressLength((byte) 6);
            dhcp.setClientHardwareAddress(clientMac.toBytes());
            dhcp.setYourIPAddress(IP_FOR_CLIENT.toInt());

            UDP udp = new UDP();
            udp.setPayload(dhcp);
            udp.setSourcePort(UDP.DHCP_SERVER_PORT);
            udp.setDestinationPort(UDP.DHCP_CLIENT_PORT);
            IPv4 ipv4 = new IPv4();
            ipv4.setPayload(udp);
            ipv4.setDestinationAddress(IP_FOR_CLIENT.toString());
            ipv4.setSourceAddress(SERVER_IP.toString());
            Ethernet eth = new Ethernet();
            if (withNonOnosRelayInfo) {
                eth.setEtherType(Ethernet.TYPE_IPV4)
                        .setVlanID(SERVER_VLAN.toShort())
                        .setSourceMACAddress(SERVER_MAC)
                        .setDestinationMACAddress(OUTER_RELAY_MAC)
                        .setPayload(ipv4);
            } else {
                eth.setEtherType(Ethernet.TYPE_IPV4)
                        .setVlanID(SERVER_VLAN.toShort())
                        .setSourceMACAddress(SERVER_MAC)
                        .setDestinationMACAddress(CLIENT_MAC)
                        .setPayload(ipv4);
            }

            this.inPacket = new DefaultInboundPacket(SERVER_CONNECT_POINT, eth,
                                                     ByteBuffer.wrap(eth.serialize()));

        }

        @Override
        public InboundPacket inPacket() {
            return this.inPacket;
        }
    }

    private class TestArpRequestPacketContext extends PacketContextAdapter {
        private InboundPacket inPacket;

        public TestArpRequestPacketContext(Interface fromInterface) {
            super(0, null, null, false);
            ARP arp = new ARP();
            arp.setOpCode(ARP.OP_REQUEST);

            IpAddress targetIp = fromInterface.ipAddressesList().get(0).ipAddress();
            arp.setTargetProtocolAddress(targetIp.toOctets());
            arp.setTargetHardwareAddress(MacAddress.BROADCAST.toBytes());
            arp.setSenderHardwareAddress(MacAddress.NONE.toBytes());
            arp.setSenderProtocolAddress(Ip4Address.valueOf(0).toOctets());
            arp.setHardwareAddressLength((byte) MacAddress.MAC_ADDRESS_LENGTH);
            Ethernet eth = new Ethernet();
            eth.setEtherType(Ethernet.TYPE_ARP);
            eth.setSourceMACAddress(MacAddress.NONE);
            eth.setDestinationMACAddress(MacAddress.BROADCAST);
            eth.setVlanID(fromInterface.vlan().toShort());
            eth.setPayload(arp);

            this.inPacket = new DefaultInboundPacket(fromInterface.connectPoint(), eth,
                                                     ByteBuffer.wrap(eth.serialize()));
        }

        @Override
        public InboundPacket inPacket() {
            return this.inPacket;
        }
    }

    /**
     * Generates DHCP6 REQUEST packet.
     */
    private void buildDhcp6Packet(DHCP6 dhcp6, byte msgType, Ip6Address ip6Addr, IpPrefix prefix) {

        // build address option
        Dhcp6IaAddressOption iaAddressOption = new Dhcp6IaAddressOption();
        iaAddressOption.setCode(DHCP6.OptionCode.IAADDR.value());
        iaAddressOption.setIp6Address(ip6Addr);
        iaAddressOption.setPreferredLifetime(3600);
        iaAddressOption.setValidLifetime(1200);
        iaAddressOption.setLength((short) Dhcp6IaAddressOption.DEFAULT_LEN);

        Dhcp6IaNaOption iaNaOption = new Dhcp6IaNaOption();
        iaNaOption.setCode(DHCP6.OptionCode.IA_NA.value());
        iaNaOption.setIaId(0);
        iaNaOption.setT1(302400);
        iaNaOption.setT2(483840);
        List<Dhcp6Option> iaNaSubOptions = new ArrayList<Dhcp6Option>();
        iaNaSubOptions.add(iaAddressOption);
        iaNaOption.setOptions(iaNaSubOptions);
        iaNaOption.setLength((short) (Dhcp6IaNaOption.DEFAULT_LEN + iaAddressOption.getLength()));

        // build prefix option
        Dhcp6IaPrefixOption iaPrefixOption = new Dhcp6IaPrefixOption();
        iaPrefixOption.setCode(DHCP6.OptionCode.IAPREFIX.value());
        iaPrefixOption.setIp6Prefix(prefix.address().getIp6Address());
        iaPrefixOption.setPrefixLength((byte) prefix.prefixLength());
        iaPrefixOption.setPreferredLifetime(3601);
        iaPrefixOption.setValidLifetime(1201);
        iaPrefixOption.setLength((short) Dhcp6IaPrefixOption.DEFAULT_LEN);

        Dhcp6IaPdOption iaPdOption = new Dhcp6IaPdOption();
        iaPdOption.setCode(DHCP6.OptionCode.IA_PD.value());
        iaPdOption.setIaId(0);
        iaPdOption.setT1(302401);
        iaPdOption.setT2(483841);
        List<Dhcp6Option> iaPdSubOptions = new ArrayList<Dhcp6Option>();
        iaPdSubOptions.add(iaPrefixOption);
        iaPdOption.setOptions(iaPdSubOptions);
        iaPdOption.setLength((short) (Dhcp6IaPdOption.DEFAULT_LEN + iaPrefixOption.getLength()));

        dhcp6.setMsgType(msgType);
        List<Dhcp6Option> dhcp6Options = new ArrayList<Dhcp6Option>();
        dhcp6Options.add(iaNaOption);
        dhcp6Options.add(iaPdOption);
        dhcp6.setOptions(dhcp6Options);

    }

    private void buildRelayMsg(DHCP6 dhcp6Relay, byte msgType, Ip6Address linkAddr,
                               Ip6Address peerAddr, byte hop, byte[] interfaceIdBytes,
                               DHCP6 dhcp6Payload) {

        dhcp6Relay.setMsgType(msgType);

        dhcp6Relay.setLinkAddress(linkAddr.toOctets());
        dhcp6Relay.setPeerAddress(peerAddr.toOctets());
        dhcp6Relay.setHopCount(hop);
        List<Dhcp6Option> options = new ArrayList<Dhcp6Option>();

        // interfaceId  option
        Dhcp6Option interfaceId = new Dhcp6Option();
        interfaceId.setCode(DHCP6.OptionCode.INTERFACE_ID.value());


        interfaceId.setData(interfaceIdBytes);
        interfaceId.setLength((short) interfaceIdBytes.length);
        Dhcp6InterfaceIdOption interfaceIdOption = new Dhcp6InterfaceIdOption(interfaceId);
        byte[] optionData = interfaceIdOption.getData();
        ByteBuffer bb = ByteBuffer.wrap(interfaceIdBytes);

        byte[] macAddr = new byte[MacAddress.MAC_ADDRESS_LENGTH];
        byte[] port =  new byte[optionData.length - MacAddress.MAC_ADDRESS_LENGTH -
                VLAN_LEN - SEPARATOR_LEN * 2];
        short vlan;
        bb.get(macAddr);
        bb.get();  // separator
        bb.get(port);
        bb.get();  // separator
        vlan = bb.getShort();
        interfaceIdOption.setMacAddress(MacAddress.valueOf(macAddr));
        interfaceIdOption.setInPort(port);
        interfaceIdOption.setVlanId(vlan);

        options.add(interfaceIdOption);

        // relay message option
        Dhcp6Option relayMsgOption = new Dhcp6Option();
        relayMsgOption.setCode(DHCP6.OptionCode.RELAY_MSG.value());
        byte[] dhcp6PayloadByte = dhcp6Payload.serialize();
        relayMsgOption.setLength((short) dhcp6PayloadByte.length);
        relayMsgOption.setPayload(dhcp6Payload);
        Dhcp6RelayOption relayOpt = new Dhcp6RelayOption(relayMsgOption);

        options.add(relayOpt);

        dhcp6Relay.setOptions(options);
    }
    private byte[] buildInterfaceId(MacAddress clientMac, short vlanId, ConnectPoint clientCp) {
        String inPortString = "-" + clientCp.toString() + ":";
        byte[] clientSoureMacBytes = clientMac.toBytes();
        byte[] inPortStringBytes = inPortString.getBytes();
        byte[] vlanIdBytes = new byte[2];
        vlanIdBytes[0] = (byte) ((vlanId >> 8) & 0xff);  // high-order byte first
        vlanIdBytes[1] = (byte) (vlanId & 0xff);
        byte[] interfaceIdBytes = new byte[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);

        return interfaceIdBytes;
    }

    private static List<TrafficSelector> buildClientDhcpSelectors() {
        return Streams.concat(Dhcp4HandlerImpl.DHCP_SELECTORS.stream(),
                              Dhcp6HandlerImpl.DHCP_SELECTORS.stream())
                .collect(Collectors.toList());
    }

    private class TestDhcp6RequestPacketContext extends PacketContextAdapter {


        private InboundPacket inPacket;


        public TestDhcp6RequestPacketContext(byte msgType, MacAddress clientMac, VlanId vlanId,
                                            ConnectPoint clientCp,
                                            Ip6Address clientGwAddr,
                                            int relayLevel) {
            super(0, null, null, false);

            DHCP6 dhcp6 = new DHCP6();
            if (relayLevel > 0) {
                DHCP6 dhcp6Payload = new DHCP6();
                buildDhcp6Packet(dhcp6Payload, msgType,
                                 IP_FOR_CLIENT_V6,
                        msgType == DHCP6.MsgType.REQUEST.value() ? PREFIX_FOR_ZERO : PREFIX_FOR_CLIENT_V6);
                DHCP6 dhcp6Parent = null;
                DHCP6 dhcp6Child = dhcp6Payload;
                for (int i = 0; i < relayLevel; i++) {
                    dhcp6Parent = new DHCP6();
                    byte[] interfaceId = buildInterfaceId(clientMac, vlanId.toShort(), clientCp);
                    buildRelayMsg(dhcp6Parent, DHCP6.MsgType.RELAY_FORW.value(),
                            INTERFACE_IP_V6.ipAddress().getIp6Address(),
                            OUTER_RELAY_IP_V6,
                            (byte) (relayLevel - 1), interfaceId,
                            dhcp6Child);
                    dhcp6Child = dhcp6Parent;
                }
                if (dhcp6Parent != null) {
                    dhcp6 = dhcp6Parent;
                }
            } else {
                buildDhcp6Packet(dhcp6, msgType,
                                        IP_FOR_CLIENT_V6,
                        msgType == DHCP6.MsgType.REQUEST.value() ? PREFIX_FOR_ZERO : PREFIX_FOR_CLIENT_V6);
            }

            UDP udp = new UDP();
            udp.setPayload(dhcp6);
            if (relayLevel > 0) {
                udp.setSourcePort(UDP.DHCP_V6_SERVER_PORT);
            } else {
                udp.setSourcePort(UDP.DHCP_V6_CLIENT_PORT);
            }
            udp.setDestinationPort(UDP.DHCP_V6_SERVER_PORT);

            IPv6 ipv6 = new IPv6();
            ipv6.setPayload(udp);
            ipv6.setNextHeader(IPv6.PROTOCOL_UDP);
            ipv6.setDestinationAddress(SERVER_IP_V6_MCAST.toOctets());
            ipv6.setSourceAddress(clientGwAddr.toOctets());

            Ethernet eth = new Ethernet();
            if (relayLevel > 0) {
                eth.setEtherType(Ethernet.TYPE_IPV6)
                        .setVlanID(vlanId.toShort())
                        .setSourceMACAddress(OUTER_RELAY_MAC)
                        .setDestinationMACAddress(MacAddress.valueOf("33:33:00:01:00:02"))
                        .setPayload(ipv6);
            } else {
                eth.setEtherType(Ethernet.TYPE_IPV6)
                        .setVlanID(vlanId.toShort())
                        .setSourceMACAddress(clientMac)
                        .setDestinationMACAddress(MacAddress.valueOf("33:33:00:01:00:02"))
                        .setPayload(ipv6);
            }
            this.inPacket = new DefaultInboundPacket(clientCp, eth,
                                                     ByteBuffer.wrap(eth.serialize()));
        }

        @Override
        public InboundPacket inPacket() {
            return this.inPacket;
        }
    }

    /**
     * Generates DHCP6 REPLY  packet.
     */

    private class TestDhcp6ReplyPacketContext extends PacketContextAdapter {
        private InboundPacket inPacket;

        public TestDhcp6ReplyPacketContext(byte msgType, ConnectPoint clientCp, MacAddress clientMac,
                                        VlanId clientVlan, Ip6Address clientGwAddr,
                                        int relayLevel) {
            super(0, null, null, false);


            DHCP6 dhcp6Payload = new DHCP6();
            buildDhcp6Packet(dhcp6Payload, msgType,
                    IP_FOR_CLIENT_V6,
                    PREFIX_FOR_CLIENT_V6);
            byte[] interfaceId = buildInterfaceId(clientMac, clientVlan.toShort(), clientCp);
            DHCP6 dhcp6 = new DHCP6();
            buildRelayMsg(dhcp6, DHCP6.MsgType.RELAY_REPL.value(),
                          INTERFACE_IP_V6.ipAddress().getIp6Address(),
                          CLIENT_LL_IP_V6,
                          (byte) 0, interfaceId,
                          dhcp6Payload);

            DHCP6 dhcp6Parent = null;
            DHCP6 dhcp6Child = dhcp6;
            for (int i = 0; i < relayLevel; i++) {   // relayLevel 0 : no relay
                dhcp6Parent = new DHCP6();

                buildRelayMsg(dhcp6Parent, DHCP6.MsgType.RELAY_REPL.value(),
                        INTERFACE_IP_V6.ipAddress().getIp6Address(),
                        OUTER_RELAY_IP_V6,
                        (byte) relayLevel, interfaceId,
                        dhcp6Child);

                dhcp6Child = dhcp6Parent;
            }
            if (dhcp6Parent != null) {
                dhcp6 = dhcp6Parent;
            }


            UDP udp = new UDP();
            udp.setPayload(dhcp6);
            udp.setSourcePort(UDP.DHCP_V6_SERVER_PORT);
            udp.setDestinationPort(UDP.DHCP_V6_CLIENT_PORT);
            IPv6 ipv6 = new IPv6();
            ipv6.setPayload(udp);
            ipv6.setNextHeader(IPv6.PROTOCOL_UDP);
            ipv6.setDestinationAddress(IP_FOR_CLIENT_V6.toOctets());
            ipv6.setSourceAddress(SERVER_IP_V6.toOctets());
            Ethernet eth = new Ethernet();
            if (relayLevel > 0) {
                eth.setEtherType(Ethernet.TYPE_IPV6)
                        .setVlanID(SERVER_VLAN.toShort())
                        .setSourceMACAddress(SERVER_MAC)
                        .setDestinationMACAddress(OUTER_RELAY_MAC)
                        .setPayload(ipv6);
            } else {
                eth.setEtherType(Ethernet.TYPE_IPV6)
                        .setVlanID(SERVER_VLAN.toShort())
                        .setSourceMACAddress(SERVER_MAC)
                        .setDestinationMACAddress(CLIENT_MAC)
                        .setPayload(ipv6);
            }

            this.inPacket = new DefaultInboundPacket(SERVER_CONNECT_POINT, eth,
                                                     ByteBuffer.wrap(eth.serialize()));

        }

        @Override
        public InboundPacket inPacket() {
            return this.inPacket;
        }
    }

}
