diff --git a/app/src/test/java/org/onosproject/segmentrouting/IcmpHandlerTest.java b/app/src/test/java/org/onosproject/segmentrouting/IcmpHandlerTest.java
new file mode 100644
index 0000000..cc7c6a8
--- /dev/null
+++ b/app/src/test/java/org/onosproject/segmentrouting/IcmpHandlerTest.java
@@ -0,0 +1,794 @@
+/*
+ * 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.*;
+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(CODE_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(CODE_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(CODE_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(CODE_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(CODE_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(CODE_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(CODE_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(CODE_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(CODE_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);
+    }
+
+}
