Allow indirect hosts to ping gateway IP
Change-Id: If555eebb88d2bc6ea016ca083c479dadd13d801d
diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/IcmpHandler.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/IcmpHandler.java
index aaa8d4c..3f02d91 100644
--- a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/IcmpHandler.java
+++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/IcmpHandler.java
@@ -29,6 +29,7 @@
import org.onlab.packet.ndp.NeighborSolicitation;
import org.onosproject.incubator.net.neighbour.NeighbourMessageContext;
import org.onosproject.incubator.net.neighbour.NeighbourMessageType;
+import org.onosproject.incubator.net.routing.ResolvedRoute;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DeviceId;
import org.onosproject.net.flow.DefaultTrafficTreatment;
@@ -43,6 +44,7 @@
import java.nio.ByteBuffer;
import java.util.Arrays;
+import java.util.Optional;
import java.util.Set;
/**
@@ -149,22 +151,35 @@
/**
* Sends an ICMP reply message.
*
- * Note: we assume that packets sending from the edge switches to the hosts
- * have untagged VLAN.
* @param icmpRequest the original ICMP request
* @param outport the output port where the ICMP reply should be sent to
*/
private void sendIcmpResponse(Ethernet icmpRequest, ConnectPoint outport) {
- // Note: We assume that packets arrive at the edge switches have
- // untagged VLAN.
Ethernet icmpReplyEth = ICMP.buildIcmpReply(icmpRequest);
IPv4 icmpRequestIpv4 = (IPv4) icmpRequest.getPayload();
IPv4 icmpReplyIpv4 = (IPv4) icmpReplyEth.getPayload();
Ip4Address destIpAddress = Ip4Address.valueOf(icmpRequestIpv4.getSourceAddress());
Ip4Address destRouterAddress = config.getRouterIpAddressForASubnetHost(destIpAddress);
+
+ // Note: Source IP of the ICMP request doesn't belong to any configured subnet.
+ // The source might be an indirectly attached host (e.g. behind a router)
+ // Lookup the route store for the nexthop instead.
+ if (destRouterAddress == null) {
+ Optional<ResolvedRoute> nexthop = srManager.routeService.longestPrefixLookup(destIpAddress);
+ if (nexthop.isPresent()) {
+ try {
+ destRouterAddress = config.getRouterIpv4(nexthop.get().location().deviceId());
+ } catch (DeviceConfigNotFoundException e) {
+ log.warn("Device config not found. Abort ICMP processing");
+ return;
+ }
+ }
+ }
+
int destSid = config.getIPv4SegmentId(destRouterAddress);
if (destSid < 0) {
- log.warn("Cannot find the Segment ID for {}", destIpAddress);
+ log.warn("Failed to lookup SID of the switch that {} attaches to. " +
+ "Unable to process ICMP request.", destIpAddress);
return;
}
sendPacketOut(outport, icmpReplyEth, destSid, destIpAddress, icmpReplyIpv4.getTtl());
@@ -214,16 +229,32 @@
* @param outport the output port where the ICMP reply should be sent to
*/
private void sendIcmpv6Response(Ethernet ethRequest, ConnectPoint outport) {
- // Note: We assume that packets arrive at the edge switches have
- // untagged VLAN.
+ // Note: We assume that packets arrive at the edge switches have untagged VLAN.
Ethernet ethReply = ICMP6.buildIcmp6Reply(ethRequest);
IPv6 icmpRequestIpv6 = (IPv6) ethRequest.getPayload();
IPv6 icmpReplyIpv6 = (IPv6) ethRequest.getPayload();
Ip6Address destIpAddress = Ip6Address.valueOf(icmpRequestIpv6.getSourceAddress());
Ip6Address destRouterAddress = config.getRouterIpAddressForASubnetHost(destIpAddress);
+
+ // Note: Source IP of the ICMP request doesn't belong to any configured subnet.
+ // The source might be an indirect host behind a router.
+ // Lookup the route store for the nexthop instead.
+ if (destRouterAddress == null) {
+ Optional<ResolvedRoute> nexthop = srManager.routeService.longestPrefixLookup(destIpAddress);
+ if (nexthop.isPresent()) {
+ try {
+ destRouterAddress = config.getRouterIpv6(nexthop.get().location().deviceId());
+ } catch (DeviceConfigNotFoundException e) {
+ log.warn("Device config not found. Abort ICMPv6 processing");
+ return;
+ }
+ }
+ }
+
int sid = config.getIPv6SegmentId(destRouterAddress);
if (sid < 0) {
- log.warn("Cannot find the Segment ID for {}", destIpAddress);
+ log.warn("Failed to lookup SID of the switch that {} attaches to. " +
+ "Unable to process ICMPv6 request.", destIpAddress);
return;
}
sendPacketOut(outport, ethReply, sid, destIpAddress, icmpReplyIpv6.getHopLimit());