/*
 * Copyright 2019-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.segmentrouting;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.google.common.collect.ImmutableSet;
import org.junit.Before;
import org.junit.Test;
import org.onlab.packet.Ethernet;
import org.onlab.packet.ICMP;
import org.onlab.packet.ICMP6;
import org.onlab.packet.IPv4;
import org.onlab.packet.IPv6;
import org.onlab.packet.MPLS;
import org.onosproject.TestApplicationId;
import org.onosproject.core.ApplicationId;
import org.onosproject.net.config.ConfigApplyDelegate;
import org.onosproject.net.config.basics.InterfaceConfig;
import org.onosproject.net.device.DeviceService;
import org.onosproject.segmentrouting.config.DeviceConfiguration;
import org.onosproject.segmentrouting.config.SegmentRoutingAppConfig;
import org.onosproject.segmentrouting.config.SegmentRoutingDeviceConfig;

import java.util.Collections;

import static org.easymock.EasyMock.*;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.*;
import static org.onlab.packet.ICMP.SUBTYPE_ECHO_REPLY;
import static org.onlab.packet.ICMP.TYPE_ECHO_REPLY;
import static org.onlab.packet.ICMP6.ECHO_REPLY;
import static org.onosproject.segmentrouting.TestUtils.*;

/**
 * Tests for IcmpHandler.
 */
public class IcmpHandlerTest {

    private IcmpHandler icmpHandler;
    private MockPacketService packetService;
    private SegmentRoutingManager segmentRoutingManager;
    private ApplicationId testApplicationId = TestApplicationId.create("test");

    @Before
    public void setUp() {

        // Init
        ObjectMapper mapper = new ObjectMapper();
        ConfigApplyDelegate delegate = config -> { };

        // Setup configuration for app
        SegmentRoutingAppConfig appConfig = new SegmentRoutingAppConfig();
        JsonNode appTree = mapper.createObjectNode();
        appConfig.init(testApplicationId, "icmp-handler-test", appTree, mapper, delegate);
        appConfig.setSuppressSubnet(Collections.emptySet());

        // Setup configuration for the devices
        SegmentRoutingDeviceConfig remoteLeafConfig = new SegmentRoutingDeviceConfig();
        JsonNode remoteLeafTree = mapper.createObjectNode();
        remoteLeafConfig.init(REMOTE_LEAF, "icmp-handler-test", remoteLeafTree, mapper, delegate);
        remoteLeafConfig.setNodeSidIPv4(REMOTE_LEAF_SID4)
                .setNodeSidIPv6(REMOTE_LEAF_SID6)
                .setRouterIpv4(REMOTE_LEAF_LB4)
                .setRouterIpv6(REMOTE_LEAF_LB6)
                .setIsEdgeRouter(true)
                .setRouterMac(REMOTE_MAC.toString());
        SegmentRoutingDeviceConfig localLeafConfig = new SegmentRoutingDeviceConfig();
        JsonNode localLeafTree = mapper.createObjectNode();
        localLeafConfig.init(LOCAL_LEAF, "icmp-handler-test", localLeafTree, mapper, delegate);
        localLeafConfig.setNodeSidIPv4(LOCAL_LEAF_SID4)
                .setRouterIpv4(LOCAL_LEAF_LB4)
                .setNodeSidIPv6(LOCAL_LEAF_SID6)
                .setRouterIpv6(LOCAL_LEAF_LB6)
                .setIsEdgeRouter(true)
                .setRouterMac(LOCAL_MAC.toString());
        SegmentRoutingDeviceConfig localLeaf1Config = new SegmentRoutingDeviceConfig();
        JsonNode localLeaf1Tree = mapper.createObjectNode();
        localLeaf1Config.init(LOCAL_LEAF1, "icmp-handler-test", localLeaf1Tree, mapper, delegate);
        localLeaf1Config.setNodeSidIPv4(LOCAL_LEAF1_SID4)
                .setRouterIpv4(LOCAL_LEAF1_LB4)
                .setNodeSidIPv6(LOCAL_LEAF1_SID6)
                .setRouterIpv6(LOCAL_LEAF1_LB6)
                .setIsEdgeRouter(true)
                .setRouterMac(LOCAL_MAC1.toString())
                .setPairDeviceId(LOCAL_LEAF2)
                .setPairLocalPort(P3);
        SegmentRoutingDeviceConfig localLeaf2Config = new SegmentRoutingDeviceConfig();
        JsonNode localLeaf2Tree = mapper.createObjectNode();
        localLeaf2Config.init(LOCAL_LEAF2, "icmp-handler-test", localLeaf2Tree, mapper, delegate);
        localLeaf2Config.setNodeSidIPv4(LOCAL_LEAF2_SID4)
                .setRouterIpv4(LOCAL_LEAF2_LB4)
                .setNodeSidIPv6(LOCAL_LEAF2_SID6)
                .setRouterIpv6(LOCAL_LEAF2_LB6)
                .setIsEdgeRouter(true)
                .setRouterMac(LOCAL_MAC2.toString())
                .setPairDeviceId(LOCAL_LEAF1)
                .setPairLocalPort(P3);

        // Setup configuration for ports
        InterfaceConfig remoteLeafPorts1Config = new InterfaceConfig();
        ArrayNode remoteLeafPorts1Tree = mapper.createArrayNode();
        remoteLeafPorts1Config.init(CP12, "icmp-handler-test", remoteLeafPorts1Tree, mapper, delegate);
        remoteLeafPorts1Config.addInterface(INTF1);
        InterfaceConfig remoteLeafPorts2Config = new InterfaceConfig();
        ArrayNode remoteLeafPorts2Tree = mapper.createArrayNode();
        remoteLeafPorts2Config.init(CP13, "icmp-handler-test", remoteLeafPorts2Tree, mapper, delegate);
        remoteLeafPorts2Config.addInterface(INTF2);
        InterfaceConfig localLeafPortsConfig = new InterfaceConfig();
        ArrayNode localLeafPortsTree = mapper.createArrayNode();
        localLeafPortsConfig.init(CP1011, "icmp-handler-test", localLeafPortsTree, mapper, delegate);
        localLeafPortsConfig.addInterface(INTF111);
        InterfaceConfig localLeaf1PortsConfig = new InterfaceConfig();
        ArrayNode localLeaf1PortsTree = mapper.createArrayNode();
        localLeaf1PortsConfig.init(CP2011, "icmp-handler-test", localLeaf1PortsTree, mapper, delegate);
        localLeaf1PortsConfig.addInterface(INTF211);
        InterfaceConfig localLeaf2Ports1Config = new InterfaceConfig();
        ArrayNode localLeaf2Ports1Tree = mapper.createArrayNode();
        localLeaf2Ports1Config.init(CP2021, "icmp-handler-test", localLeaf2Ports1Tree, mapper, delegate);
        localLeaf2Ports1Config.addInterface(INTF212);
        InterfaceConfig localLeaf2Ports2Config = new InterfaceConfig();
        ArrayNode localLeaf2Ports2Tree = mapper.createArrayNode();
        localLeaf2Ports2Config.init(CP2024, "icmp-handler-test", localLeaf2Ports2Tree, mapper, delegate);
        localLeaf2Ports2Config.addInterface(INTF213);

        // Apply config
        MockNetworkConfigRegistry mockNetworkConfigRegistry = new MockNetworkConfigRegistry();
        mockNetworkConfigRegistry.applyConfig(remoteLeafConfig);
        mockNetworkConfigRegistry.applyConfig(remoteLeafPorts1Config);
        mockNetworkConfigRegistry.applyConfig(remoteLeafPorts2Config);
        mockNetworkConfigRegistry.applyConfig(localLeafConfig);
        mockNetworkConfigRegistry.applyConfig(localLeafPortsConfig);
        mockNetworkConfigRegistry.applyConfig(localLeaf1Config);
        mockNetworkConfigRegistry.applyConfig(localLeaf1PortsConfig);
        mockNetworkConfigRegistry.applyConfig(localLeaf2Config);
        mockNetworkConfigRegistry.applyConfig(localLeaf2Ports1Config);
        mockNetworkConfigRegistry.applyConfig(localLeaf2Ports2Config);

        segmentRoutingManager = new SegmentRoutingManager();
        segmentRoutingManager.appId = testApplicationId;
        packetService = new MockPacketService();
        segmentRoutingManager.packetService = packetService;
        segmentRoutingManager.cfgService = mockNetworkConfigRegistry;
        segmentRoutingManager.neighbourResolutionService = new MockNeighbourResolutionService();
        segmentRoutingManager.interfaceService = new MockInterfaceService(ImmutableSet.of(
                INTF1, INTF2, INTF111, INTF211, INTF212, INTF213));
        segmentRoutingManager.deviceConfiguration = new DeviceConfiguration(segmentRoutingManager);
        segmentRoutingManager.ipHandler = new IpHandler(segmentRoutingManager);
        segmentRoutingManager.deviceService = createMock(DeviceService.class);
        segmentRoutingManager.routeService = new MockRouteService(ROUTE_STORE);
        segmentRoutingManager.hostService = new MockHostService(Collections.emptySet());
        icmpHandler = new IcmpHandler(segmentRoutingManager);
    }

    // Ping to our gateway
    @Test
    public void testPing4MyGateway() {
        // Expected behavior
        expect(segmentRoutingManager.deviceService.isAvailable(REMOTE_LEAF))
                .andReturn(true)
                .times(1);
        replay(segmentRoutingManager.deviceService);

        // Process
        icmpHandler.processIcmp(ETH_REQ_IPV4_MY, CP12);

        // Verify packet-out
        Ethernet ethernet = packetService.getEthernetPacket(ETH_REQ_IPV4_MY.getSourceMAC());
        assertNotNull(ethernet);
        assertThat(ethernet.getSourceMAC(), is(ETH_REQ_IPV4_MY.getDestinationMAC()));
        assertThat(ethernet.getDestinationMAC(), is(ETH_REQ_IPV4_MY.getSourceMAC()));
        assertTrue(ethernet.getPayload() instanceof IPv4);
        IPv4 ip = (IPv4) ethernet.getPayload();
        assertThat(ip.getSourceAddress(), is(DST_IPV4.toInt()));
        assertThat(ip.getDestinationAddress(), is(SRC_IPV4_MY.toInt()));
        assertTrue(ip.getPayload() instanceof ICMP);
        ICMP icmp = (ICMP) ip.getPayload();
        assertThat(icmp.getIcmpType(), is(TYPE_ECHO_REPLY));
        assertThat(icmp.getIcmpCode(), is(SUBTYPE_ECHO_REPLY));
        // Verify behavior
        verify(segmentRoutingManager.deviceService);
    }

    // Ping6 to our gateway
    @Test
    public void testPing6MyGateway() {
        // Expected behavior
        expect(segmentRoutingManager.deviceService.isAvailable(REMOTE_LEAF))
                .andReturn(true)
                .times(1);
        replay(segmentRoutingManager.deviceService);

        // Process
        icmpHandler.processIcmpv6(ETH_REQ_IPV6_MY, CP12);

        // Verify packet-out
        Ethernet ethernet = packetService.getEthernetPacket(ETH_REQ_IPV6_MY.getSourceMAC());
        assertNotNull(ethernet);
        assertThat(ethernet.getSourceMAC(), is(ETH_REQ_IPV6_MY.getDestinationMAC()));
        assertThat(ethernet.getDestinationMAC(), is(ETH_REQ_IPV6_MY.getSourceMAC()));
        assertTrue(ethernet.getPayload() instanceof IPv6);
        IPv6 ip = (IPv6) ethernet.getPayload();
        assertThat(ip.getSourceAddress(), is(DST_IPV6.toOctets()));
        assertThat(ip.getDestinationAddress(), is(SRC_IPV6_MY.toOctets()));
        assertTrue(ip.getPayload() instanceof ICMP6);
        ICMP6 icmp = (ICMP6) ip.getPayload();
        assertThat(icmp.getIcmpType(), is(ECHO_REPLY));
        // Verify behavior
        verify(segmentRoutingManager.deviceService);
    }

    // Ping to a gateway attached to our leaf
    @Test
    public void testPing4LocalGateway() {
        // Expected behavior
        expect(segmentRoutingManager.deviceService.isAvailable(REMOTE_LEAF))
                .andReturn(true)
                .times(1);
        replay(segmentRoutingManager.deviceService);

        // Process
        icmpHandler.processIcmp(ETH_REQ_IPV4_LOCAL, CP12);

        // Verify packet-out
        Ethernet ethernet = packetService.getEthernetPacket(ETH_REQ_IPV4_LOCAL.getSourceMAC());
        assertNotNull(ethernet);
        assertThat(ethernet.getSourceMAC(), is(ETH_REQ_IPV4_LOCAL.getDestinationMAC()));
        assertThat(ethernet.getDestinationMAC(), is(ETH_REQ_IPV4_LOCAL.getSourceMAC()));
        assertTrue(ethernet.getPayload() instanceof IPv4);
        IPv4 ip = (IPv4) ethernet.getPayload();
        assertThat(ip.getSourceAddress(), is(DST_IPV4_LOCAL.toInt()));
        assertThat(ip.getDestinationAddress(), is(SRC_IPV4_MY.toInt()));
        assertTrue(ip.getPayload() instanceof ICMP);
        ICMP icmp = (ICMP) ip.getPayload();
        assertThat(icmp.getIcmpType(), is(TYPE_ECHO_REPLY));
        assertThat(icmp.getIcmpCode(), is(SUBTYPE_ECHO_REPLY));
        // Verify behavior
        verify(segmentRoutingManager.deviceService);
    }

    // Ping6 to a gateway attached to our leaf
    @Test
    public void testPing6LocalGateway() {
        // Expected behavior
        expect(segmentRoutingManager.deviceService.isAvailable(REMOTE_LEAF))
                .andReturn(true)
                .times(1);
        replay(segmentRoutingManager.deviceService);

        // Process
        icmpHandler.processIcmpv6(ETH_REQ_IPV6_LOCAL, CP12);

        // Verify packet-out
        Ethernet ethernet = packetService.getEthernetPacket(ETH_REQ_IPV6_LOCAL.getSourceMAC());
        assertNotNull(ethernet);
        assertThat(ethernet.getSourceMAC(), is(ETH_REQ_IPV6_LOCAL.getDestinationMAC()));
        assertThat(ethernet.getDestinationMAC(), is(ETH_REQ_IPV6_LOCAL.getSourceMAC()));
        assertTrue(ethernet.getPayload() instanceof IPv6);
        IPv6 ip = (IPv6) ethernet.getPayload();
        assertThat(ip.getSourceAddress(), is(DST_IPV6_LOCAL.toOctets()));
        assertThat(ip.getDestinationAddress(), is(SRC_IPV6_MY.toOctets()));
        assertTrue(ip.getPayload() instanceof ICMP6);
        ICMP6 icmp = (ICMP6) ip.getPayload();
        assertThat(icmp.getIcmpType(), is(ECHO_REPLY));
        // Verify behavior
        verify(segmentRoutingManager.deviceService);
    }

    // Ping to a gateway attached only to the pair leaf (routing through spine)
    @Test
    public void testPing4RemoteGatewaySamePair() {
        // Expected behavior
        expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF1))
                .andReturn(true)
                .times(1);
        expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF2))
                .andReturn(true)
                .times(1);
        replay(segmentRoutingManager.deviceService);

        // Process
        icmpHandler.processIcmp(ETH_REQ_IPV4_SAME, CP2025);

        // Verify packet-out
        Ethernet ethernet = packetService.getEthernetPacket(ETH_REQ_IPV4_SAME.getSourceMAC());
        assertNotNull(ethernet);
        assertThat(ethernet.getSourceMAC(), is(ETH_REQ_IPV4_SAME.getDestinationMAC()));
        assertThat(ethernet.getDestinationMAC(), is(ETH_REQ_IPV4_SAME.getSourceMAC()));
        assertTrue(ethernet.getPayload() instanceof MPLS);
        MPLS mpls = (MPLS) ethernet.getPayload();
        assertThat(mpls.getLabel(), is(LOCAL_LEAF1_SID4));
        assertTrue(mpls.getPayload() instanceof IPv4);
        IPv4 ip = (IPv4) mpls.getPayload();
        assertThat(ip.getSourceAddress(), is(DST_IPV4_SAME.toInt()));
        assertThat(ip.getDestinationAddress(), is(SRC_IPV41.toInt()));
        assertTrue(ip.getPayload() instanceof ICMP);
        ICMP icmp = (ICMP) ip.getPayload();
        assertThat(icmp.getIcmpType(), is(TYPE_ECHO_REPLY));
        assertThat(icmp.getIcmpCode(), is(SUBTYPE_ECHO_REPLY));
        // Verify behavior
        verify(segmentRoutingManager.deviceService);
    }

    // Ping6 to a gateway attached only to the pair leaf (routing through spine)
    @Test
    public void testPing6RemoteGatewaySamePair() {
        // Expected behavior
        expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF1))
                .andReturn(true)
                .times(1);
        expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF2))
                .andReturn(true)
                .times(1);
        replay(segmentRoutingManager.deviceService);

        // Process
        icmpHandler.processIcmpv6(ETH_REQ_IPV6_SAME, CP2025);

        // Verify packet-out
        Ethernet ethernet = packetService.getEthernetPacket(ETH_REQ_IPV6_SAME.getSourceMAC());
        assertNotNull(ethernet);
        assertThat(ethernet.getSourceMAC(), is(ETH_REQ_IPV6_SAME.getDestinationMAC()));
        assertThat(ethernet.getDestinationMAC(), is(ETH_REQ_IPV6_SAME.getSourceMAC()));
        assertTrue(ethernet.getPayload() instanceof MPLS);
        MPLS mpls = (MPLS) ethernet.getPayload();
        assertThat(mpls.getLabel(), is(LOCAL_LEAF1_SID6));
        assertTrue(mpls.getPayload() instanceof IPv6);
        IPv6 ip = (IPv6) mpls.getPayload();
        assertThat(ip.getSourceAddress(), is(DST_IPV6_SAME.toOctets()));
        assertThat(ip.getDestinationAddress(), is(SRC_IPV61.toOctets()));
        assertTrue(ip.getPayload() instanceof ICMP6);
        ICMP6 icmp = (ICMP6) ip.getPayload();
        assertThat(icmp.getIcmpType(), is(ECHO_REPLY));
        // Verify behavior
        verify(segmentRoutingManager.deviceService);
    }

    // Ping to a gateway but destination leaf is down
    @Test
    public void testPing4RemoteGatewayLeafDown() {
        // Expected behavior
        expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF))
                .andReturn(false)
                .times(1);
        replay(segmentRoutingManager.deviceService);

        // Process
        icmpHandler.processIcmp(ETH_REQ_IPV4, CP11);

        // Verify packet-out
        Ethernet ethernet = packetService.getEthernetPacket(ETH_REQ_IPV4.getSourceMAC());
        assertNull(ethernet);

        // Verify behavior
        verify(segmentRoutingManager.deviceService);
    }

    // Ping6 to a gateway but destination leaf is down
    @Test
    public void testPing6RemoteGatewayLeafDown() {
        // Expected behavior
        expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF))
                .andReturn(false)
                .times(1);
        replay(segmentRoutingManager.deviceService);

        // Process
        icmpHandler.processIcmpv6(ETH_REQ_IPV6, CP11);

        // Verify packet-out
        Ethernet ethernet = packetService.getEthernetPacket(ETH_REQ_IPV6.getSourceMAC());
        assertNull(ethernet);

        // Verify behavior
        verify(segmentRoutingManager.deviceService);
    }

    // Ping to a gateway but one of the destination leaf is down
    @Test
    public void testPing4RemoteGatewayLeaf1Down() {
        // Expected behavior
        expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF1))
                .andReturn(false)
                .times(1);
        expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF2))
                .andReturn(true)
                .times(1);
        replay(segmentRoutingManager.deviceService);

        // Process
        icmpHandler.processIcmp(ETH_REQ_IPV41, CP11);

        // Verify packet-out
        Ethernet ethernet = packetService.getEthernetPacket(ETH_REQ_IPV41.getSourceMAC());
        assertNotNull(ethernet);
        assertThat(ethernet.getSourceMAC(), is(ETH_REQ_IPV41.getDestinationMAC()));
        assertThat(ethernet.getDestinationMAC(), is(ETH_REQ_IPV41.getSourceMAC()));
        assertThat(ethernet.getEtherType(), is(Ethernet.MPLS_UNICAST));
        assertTrue(ethernet.getPayload() instanceof MPLS);
        MPLS mpls = (MPLS) ethernet.getPayload();
        assertThat(mpls.getLabel(), is(LOCAL_LEAF2_SID4));
        assertTrue(mpls.getPayload() instanceof IPv4);
        IPv4 ip = (IPv4) mpls.getPayload();
        assertThat(ip.getSourceAddress(), is(DST_IPV4.toInt()));
        assertThat(ip.getDestinationAddress(), is(SRC_IPV41.toInt()));
        assertTrue(ip.getPayload() instanceof ICMP);
        ICMP icmp = (ICMP) ip.getPayload();
        assertThat(icmp.getIcmpType(), is(TYPE_ECHO_REPLY));
        assertThat(icmp.getIcmpCode(), is(SUBTYPE_ECHO_REPLY));
        // Verify behavior
        verify(segmentRoutingManager.deviceService);
    }

    // Ping6 to a gateway but one of the destination leaf is down
    @Test
    public void testPing6RemoteGatewayLeaf2Down() {
        // Expected behavior
        expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF1))
                .andReturn(true)
                .times(1);
        expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF2))
                .andReturn(false)
                .times(1);
        replay(segmentRoutingManager.deviceService);

        // Process
        icmpHandler.processIcmpv6(ETH_REQ_IPV61, CP11);

        // Verify packet-out
        Ethernet ethernet = packetService.getEthernetPacket(ETH_REQ_IPV61.getSourceMAC());
        assertNotNull(ethernet);
        assertThat(ethernet.getSourceMAC(), is(ETH_REQ_IPV61.getDestinationMAC()));
        assertThat(ethernet.getDestinationMAC(), is(ETH_REQ_IPV61.getSourceMAC()));
        assertThat(ethernet.getEtherType(), is(Ethernet.MPLS_UNICAST));
        assertTrue(ethernet.getPayload() instanceof MPLS);
        MPLS mpls = (MPLS) ethernet.getPayload();
        assertThat(mpls.getLabel(), is(LOCAL_LEAF1_SID6));
        assertTrue(mpls.getPayload() instanceof IPv6);
        IPv6 ip = (IPv6) mpls.getPayload();
        assertThat(ip.getSourceAddress(), is(DST_IPV6.toOctets()));
        assertThat(ip.getDestinationAddress(), is(SRC_IPV61.toOctets()));
        assertTrue(ip.getPayload() instanceof ICMP6);
        ICMP6 icmp = (ICMP6) ip.getPayload();
        assertThat(icmp.getIcmpType(), is(ECHO_REPLY));
        // Verify behavior
        verify(segmentRoutingManager.deviceService);
    }

    // Ping6 to a link local address
    @Test
    public void testPing6LinkLocalAddress() {
        // Process
        icmpHandler.processIcmpv6(ETH_REQ_IPV6_LL, CP12);

        // Verify packet-out
        Ethernet ethernet = packetService.getEthernetPacket(ETH_REQ_IPV6_LL.getSourceMAC());
        assertNotNull(ethernet);
        assertThat(ethernet.getSourceMAC(), is(ETH_REQ_IPV6_LL.getDestinationMAC()));
        assertThat(ethernet.getDestinationMAC(), is(ETH_REQ_IPV6_LL.getSourceMAC()));
        assertTrue(ethernet.getPayload() instanceof IPv6);
        IPv6 ip = (IPv6) ethernet.getPayload();
        assertThat(ip.getSourceAddress(), is(DST_IPV6_LL.toOctets()));
        assertThat(ip.getDestinationAddress(), is(SRC_IPV6_LL.toOctets()));
        assertTrue(ip.getPayload() instanceof ICMP6);
        ICMP6 icmp = (ICMP6) ip.getPayload();
        assertThat(icmp.getIcmpType(), is(ECHO_REPLY));
    }

    // Ping to the looback of our leaf
    @Test
    public void testPing4Loopback() {
        // Expected behavior
        expect(segmentRoutingManager.deviceService.isAvailable(REMOTE_LEAF))
                .andReturn(true)
                .times(1);
        replay(segmentRoutingManager.deviceService);

        // Process
        icmpHandler.processIcmp(ETH_REQ_IPV4_LOOPBACK, CP12);

        // Verify packet-out
        Ethernet ethernet = packetService.getEthernetPacket(ETH_REQ_IPV4_LOOPBACK.getSourceMAC());
        assertNotNull(ethernet);
        assertThat(ethernet.getSourceMAC(), is(ETH_REQ_IPV4_LOOPBACK.getDestinationMAC()));
        assertThat(ethernet.getDestinationMAC(), is(ETH_REQ_IPV4_LOOPBACK.getSourceMAC()));
        assertTrue(ethernet.getPayload() instanceof IPv4);
        IPv4 ip = (IPv4) ethernet.getPayload();
        assertThat(ip.getSourceAddress(), is(DST_IPV4_LOOPBACK.toInt()));
        assertThat(ip.getDestinationAddress(), is(SRC_IPV4_MY.toInt()));
        assertTrue(ip.getPayload() instanceof ICMP);
        ICMP icmp = (ICMP) ip.getPayload();
        assertThat(icmp.getIcmpType(), is(TYPE_ECHO_REPLY));
        assertThat(icmp.getIcmpCode(), is(SUBTYPE_ECHO_REPLY));
        // Verify behavior
        verify(segmentRoutingManager.deviceService);
    }

    // Ping6 to the looback of our leaf
    @Test
    public void testPing6Loopback() {
        // Expected behavior
        expect(segmentRoutingManager.deviceService.isAvailable(REMOTE_LEAF))
                .andReturn(true)
                .times(1);
        replay(segmentRoutingManager.deviceService);

        // Process
        icmpHandler.processIcmpv6(ETH_REQ_IPV6_LOOPBACK, CP12);

        // Verify packet-out
        Ethernet ethernet = packetService.getEthernetPacket(ETH_REQ_IPV6_LOOPBACK.getSourceMAC());
        assertNotNull(ethernet);
        assertThat(ethernet.getSourceMAC(), is(ETH_REQ_IPV6_LOOPBACK.getDestinationMAC()));
        assertThat(ethernet.getDestinationMAC(), is(ETH_REQ_IPV6_LOOPBACK.getSourceMAC()));
        assertTrue(ethernet.getPayload() instanceof IPv6);
        IPv6 ip = (IPv6) ethernet.getPayload();
        assertThat(ip.getSourceAddress(), is(DST_IPV6_LOOPBACK.toOctets()));
        assertThat(ip.getDestinationAddress(), is(SRC_IPV6_MY.toOctets()));
        assertTrue(ip.getPayload() instanceof ICMP6);
        ICMP6 icmp = (ICMP6) ip.getPayload();
        assertThat(icmp.getIcmpType(), is(ECHO_REPLY));
        // Verify behavior
        verify(segmentRoutingManager.deviceService);
    }

    // Ping to the looback of our leaf (pair)
    @Test
    public void testPing4LoopbackPair() {
        // Expected behavior
        expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF1))
                .andReturn(true)
                .times(1);
        expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF2))
                .andReturn(true)
                .times(1);
        replay(segmentRoutingManager.deviceService);

        // Process
        icmpHandler.processIcmp(ETH_REQ_IPV4_LOOPBACK_PAIR, CP2011);

        // Verify packet-out
        Ethernet ethernet = packetService.getEthernetPacket(ETH_REQ_IPV4_LOOPBACK_PAIR.getSourceMAC());
        assertNotNull(ethernet);
        assertThat(ethernet.getSourceMAC(), is(ETH_REQ_IPV4_LOOPBACK_PAIR.getDestinationMAC()));
        assertThat(ethernet.getDestinationMAC(), is(ETH_REQ_IPV4_LOOPBACK_PAIR.getSourceMAC()));
        assertTrue(ethernet.getPayload() instanceof IPv4);
        IPv4 ip = (IPv4) ethernet.getPayload();
        assertThat(ip.getSourceAddress(), is(DST_IPV4_LOOPBACK_PAIR.toInt()));
        assertThat(ip.getDestinationAddress(), is(SRC_IPV41.toInt()));
        assertTrue(ip.getPayload() instanceof ICMP);
        ICMP icmp = (ICMP) ip.getPayload();
        assertThat(icmp.getIcmpType(), is(TYPE_ECHO_REPLY));
        assertThat(icmp.getIcmpCode(), is(SUBTYPE_ECHO_REPLY));
        // Verify behavior
        verify(segmentRoutingManager.deviceService);
    }

    // Ping6 to the looback of our leaf (pair)
    @Test
    public void testPing6LoopbackPair() {
        // Expected behavior
        expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF1))
                .andReturn(true)
                .times(1);
        expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF2))
                .andReturn(true)
                .times(1);
        replay(segmentRoutingManager.deviceService);

        // Process
        icmpHandler.processIcmpv6(ETH_REQ_IPV6_LOOPBACK_PAIR, CP2021);

        // Verify packet-out
        Ethernet ethernet = packetService.getEthernetPacket(ETH_REQ_IPV6_LOOPBACK_PAIR.getSourceMAC());
        assertNotNull(ethernet);
        assertThat(ethernet.getSourceMAC(), is(ETH_REQ_IPV6_LOOPBACK_PAIR.getDestinationMAC()));
        assertThat(ethernet.getDestinationMAC(), is(ETH_REQ_IPV6_LOOPBACK_PAIR.getSourceMAC()));
        assertTrue(ethernet.getPayload() instanceof IPv6);
        IPv6 ip = (IPv6) ethernet.getPayload();
        assertThat(ip.getSourceAddress(), is(DST_IPV6_LOOPBACK_PAIR.toOctets()));
        assertThat(ip.getDestinationAddress(), is(SRC_IPV61.toOctets()));
        assertTrue(ip.getPayload() instanceof ICMP6);
        ICMP6 icmp = (ICMP6) ip.getPayload();
        assertThat(icmp.getIcmpType(), is(ECHO_REPLY));
        // Verify behavior
        verify(segmentRoutingManager.deviceService);
    }

    // Ping to the loopback of the leaf but hashing of the bond interfaces sends to wrong leaf
    @Test
    public void testPing4LoopbackPairDifferentLeaf() {
        // Expected behavior
        expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF1))
                .andReturn(true)
                .times(1);
        expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF2))
                .andReturn(true)
                .times(1);
        replay(segmentRoutingManager.deviceService);

        // Process
        icmpHandler.processIcmp(ETH_REQ_IPV4_LOOPBACK_PAIR, CP2021);

        // Verify packet-out
        Ethernet ethernet = packetService.getEthernetPacket(ETH_REQ_IPV4_LOOPBACK_PAIR.getSourceMAC());
        assertNotNull(ethernet);
        assertThat(ethernet.getSourceMAC(), is(ETH_REQ_IPV4_LOOPBACK_PAIR.getDestinationMAC()));
        assertThat(ethernet.getDestinationMAC(), is(ETH_REQ_IPV4_LOOPBACK_PAIR.getSourceMAC()));
        assertTrue(ethernet.getPayload() instanceof IPv4);
        IPv4 ip = (IPv4) ethernet.getPayload();
        assertThat(ip.getSourceAddress(), is(DST_IPV4_LOOPBACK_PAIR.toInt()));
        assertThat(ip.getDestinationAddress(), is(SRC_IPV41.toInt()));
        assertTrue(ip.getPayload() instanceof ICMP);
        ICMP icmp = (ICMP) ip.getPayload();
        assertThat(icmp.getIcmpType(), is(TYPE_ECHO_REPLY));
        assertThat(icmp.getIcmpCode(), is(SUBTYPE_ECHO_REPLY));
        // Verify behavior
        verify(segmentRoutingManager.deviceService);
    }

    // Ping6 to the loopback of the leaf but hashing of the bond interfaces sends to wrong leaf
    @Test
    public void testPing6LoopbackPairDifferentLeaf() {
        // Expected behavior
        expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF1))
                .andReturn(true)
                .times(1);
        expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF2))
                .andReturn(true)
                .times(1);
        replay(segmentRoutingManager.deviceService);

        // Process
        icmpHandler.processIcmpv6(ETH_REQ_IPV6_LOOPBACK_PAIR, CP2011);

        // Verify packet-out
        Ethernet ethernet = packetService.getEthernetPacket(ETH_REQ_IPV6_LOOPBACK_PAIR.getSourceMAC());
        assertNotNull(ethernet);
        assertThat(ethernet.getSourceMAC(), is(ETH_REQ_IPV6_LOOPBACK_PAIR.getDestinationMAC()));
        assertThat(ethernet.getDestinationMAC(), is(ETH_REQ_IPV6_LOOPBACK_PAIR.getSourceMAC()));
        assertTrue(ethernet.getPayload() instanceof IPv6);
        IPv6 ip = (IPv6) ethernet.getPayload();
        assertThat(ip.getSourceAddress(), is(DST_IPV6_LOOPBACK_PAIR.toOctets()));
        assertThat(ip.getDestinationAddress(), is(SRC_IPV61.toOctets()));
        assertTrue(ip.getPayload() instanceof ICMP6);
        ICMP6 icmp = (ICMP6) ip.getPayload();
        assertThat(icmp.getIcmpType(), is(ECHO_REPLY));
        // Verify behavior
        verify(segmentRoutingManager.deviceService);
    }

    // Ping loopback of a destination that is down but
    // hashing of the bond interfaces sends to other leaf
    @Test
    public void testPing4LoopbackPairDifferentLeafDown() {
        // Expected behavior
        expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF1))
                .andReturn(false)
                .times(1);
        expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF2))
                .andReturn(true)
                .times(1);
        replay(segmentRoutingManager.deviceService);

        // Process
        icmpHandler.processIcmp(ETH_REQ_IPV4_LOOPBACK_PAIR, CP2021);

        // Verify packet-out
        Ethernet ethernet = packetService.getEthernetPacket(ETH_REQ_IPV4_LOOPBACK_PAIR.getSourceMAC());
        assertNotNull(ethernet);
        assertThat(ethernet.getSourceMAC(), is(ETH_REQ_IPV4_LOOPBACK_PAIR.getDestinationMAC()));
        assertThat(ethernet.getDestinationMAC(), is(ETH_REQ_IPV4_LOOPBACK_PAIR.getSourceMAC()));
        assertTrue(ethernet.getPayload() instanceof IPv4);
        IPv4 ip = (IPv4) ethernet.getPayload();
        assertThat(ip.getSourceAddress(), is(DST_IPV4_LOOPBACK_PAIR.toInt()));
        assertThat(ip.getDestinationAddress(), is(SRC_IPV41.toInt()));
        assertTrue(ip.getPayload() instanceof ICMP);
        ICMP icmp = (ICMP) ip.getPayload();
        assertThat(icmp.getIcmpType(), is(TYPE_ECHO_REPLY));
        assertThat(icmp.getIcmpCode(), is(SUBTYPE_ECHO_REPLY));
        // Verify behavior
        verify(segmentRoutingManager.deviceService);
    }

    // Ping6 loopback of a destination that is down but
    // hashing of the bond interfaces sends to other leaf
    @Test
    public void testPing6LoopbackPairDifferentLeafDown() {
        // Expected behavior
        expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF1))
                .andReturn(true)
                .times(1);
        expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF2))
                .andReturn(false)
                .times(1);
        replay(segmentRoutingManager.deviceService);

        // Process
        icmpHandler.processIcmpv6(ETH_REQ_IPV6_LOOPBACK_PAIR, CP2011);

        // Verify packet-out
        Ethernet ethernet = packetService.getEthernetPacket(ETH_REQ_IPV6_LOOPBACK_PAIR.getSourceMAC());
        assertNotNull(ethernet);
        assertThat(ethernet.getSourceMAC(), is(ETH_REQ_IPV6_LOOPBACK_PAIR.getDestinationMAC()));
        assertThat(ethernet.getDestinationMAC(), is(ETH_REQ_IPV6_LOOPBACK_PAIR.getSourceMAC()));
        assertTrue(ethernet.getPayload() instanceof IPv6);
        IPv6 ip = (IPv6) ethernet.getPayload();
        assertThat(ip.getSourceAddress(), is(DST_IPV6_LOOPBACK_PAIR.toOctets()));
        assertThat(ip.getDestinationAddress(), is(SRC_IPV61.toOctets()));
        assertTrue(ip.getPayload() instanceof ICMP6);
        ICMP6 icmp = (ICMP6) ip.getPayload();
        assertThat(icmp.getIcmpType(), is(ECHO_REPLY));
        // Verify behavior
        verify(segmentRoutingManager.deviceService);
    }

    // Ping to a dh gateway
    @Test
    public void testPing4GatewayPair() {
        // Expected behavior
        expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF1))
                .andReturn(true)
                .times(1);
        expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF2))
                .andReturn(true)
                .times(1);
        replay(segmentRoutingManager.deviceService);

        // Process
        icmpHandler.processIcmp(ETH_REQ_IPV4_GATEWAY_PAIR, CP2011);

        // Verify packet-out
        Ethernet ethernet = packetService.getEthernetPacket(ETH_REQ_IPV4_GATEWAY_PAIR.getSourceMAC());
        assertNotNull(ethernet);
        assertThat(ethernet.getSourceMAC(), is(ETH_REQ_IPV4_GATEWAY_PAIR.getDestinationMAC()));
        assertThat(ethernet.getDestinationMAC(), is(ETH_REQ_IPV4_GATEWAY_PAIR.getSourceMAC()));
        assertTrue(ethernet.getPayload() instanceof IPv4);
        IPv4 ip = (IPv4) ethernet.getPayload();
        assertThat(ip.getSourceAddress(), is(DST_IPV4_GATEWAY_PAIR.toInt()));
        assertThat(ip.getDestinationAddress(), is(SRC_IPV41.toInt()));
        assertTrue(ip.getPayload() instanceof ICMP);
        ICMP icmp = (ICMP) ip.getPayload();
        assertThat(icmp.getIcmpType(), is(TYPE_ECHO_REPLY));
        assertThat(icmp.getIcmpCode(), is(SUBTYPE_ECHO_REPLY));
        // Verify behavior
        verify(segmentRoutingManager.deviceService);
    }

    // Ping6 to a dh gateway
    @Test
    public void testPing6GatewayPair() {
        // Expected behavior
        expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF1))
                .andReturn(true)
                .times(1);
        expect(segmentRoutingManager.deviceService.isAvailable(LOCAL_LEAF2))
                .andReturn(true)
                .times(1);
        replay(segmentRoutingManager.deviceService);

        // Process
        icmpHandler.processIcmpv6(ETH_REQ_IPV6_GATEWAY_PAIR, CP2021);

        // Verify packet-out
        Ethernet ethernet = packetService.getEthernetPacket(ETH_REQ_IPV6_GATEWAY_PAIR.getSourceMAC());
        assertNotNull(ethernet);
        assertThat(ethernet.getSourceMAC(), is(ETH_REQ_IPV6_GATEWAY_PAIR.getDestinationMAC()));
        assertThat(ethernet.getDestinationMAC(), is(ETH_REQ_IPV6_GATEWAY_PAIR.getSourceMAC()));
        assertTrue(ethernet.getPayload() instanceof IPv6);
        IPv6 ip = (IPv6) ethernet.getPayload();
        assertThat(ip.getSourceAddress(), is(DST_IPV6_GATEWAY_PAIR.toOctets()));
        assertThat(ip.getDestinationAddress(), is(SRC_IPV61.toOctets()));
        assertTrue(ip.getPayload() instanceof ICMP6);
        ICMP6 icmp = (ICMP6) ip.getPayload();
        assertThat(icmp.getIcmpType(), is(ECHO_REPLY));
        // Verify behavior
        verify(segmentRoutingManager.deviceService);
    }

}
