IPv6 Unsolicited RA application.
Change-Id: I7dac31918708d85247a7831fd38f83d2e8781183
diff --git a/src/main/java/org/onosproject/segmentrouting/IcmpHandler.java b/src/main/java/org/onosproject/segmentrouting/IcmpHandler.java
index 23bbf07..4eec890 100644
--- a/src/main/java/org/onosproject/segmentrouting/IcmpHandler.java
+++ b/src/main/java/org/onosproject/segmentrouting/IcmpHandler.java
@@ -31,6 +31,7 @@
import org.onosproject.net.neighbour.NeighbourMessageType;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DeviceId;
+import org.onosproject.net.intf.Interface;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.host.HostService;
@@ -204,21 +205,31 @@
IPv6 ipv6Packet = (IPv6) eth.getPayload();
Ip6Address destinationAddress = Ip6Address.valueOf(ipv6Packet.getDestinationAddress());
Set<IpAddress> gatewayIpAddresses = config.getPortIPs(deviceId);
+ MacAddress interfaceMac;
IpAddress routerIp;
+
try {
routerIp = config.getRouterIpv6(deviceId);
+ Optional<MacAddress> macAddress = srManager.interfaceService.getInterfacesByPort(inPort).stream()
+ .map(Interface::mac)
+ .findFirst();
+ if (!macAddress.isPresent()) {
+ log.warn("Failed in fetching MAC address of {}. Aborting ICMP6 processing.", inPort);
+ return;
+ }
+ interfaceMac = MacAddress.valueOf(macAddress.get().toBytes());
+
+ // Ensure ICMP to the router IP, gateway IP or link-local EUI-64
+ ICMP6 icmp6 = (ICMP6) ipv6Packet.getPayload();
+ if (icmp6.getIcmpType() == ICMP6.ECHO_REQUEST && (destinationAddress.equals(routerIp.getIp6Address()) ||
+ destinationAddress.equals(Ip6Address.valueOf(IPv6.getLinkLocalAddress(interfaceMac.toBytes()))) ||
+ gatewayIpAddresses.contains(destinationAddress))) {
+ sendIcmpv6Response(eth, inPort);
+ } else {
+ log.trace("Ignore ICMPv6 that targets for {}", destinationAddress);
+ }
} catch (DeviceConfigNotFoundException e) {
- log.warn(e.getMessage() + " Aborting processPacketIn.");
- return;
- }
- ICMP6 icmp6 = (ICMP6) ipv6Packet.getPayload();
- // ICMP to the router IP or gateway IP
- if (icmp6.getIcmpType() == ICMP6.ECHO_REQUEST &&
- (destinationAddress.equals(routerIp.getIp6Address()) ||
- gatewayIpAddresses.contains(destinationAddress))) {
- sendIcmpv6Response(eth, inPort);
- } else {
- log.trace("Ignore ICMPv6 that targets for {}", destinationAddress);
+ log.warn(e.getMessage() + " Ignore ICMPv6 that targets to {}.", destinationAddress);
}
}
@@ -256,11 +267,15 @@
}
}
- int sid = config.getIPv6SegmentId(destRouterAddress);
- if (sid < 0) {
- log.warn("Failed to lookup SID of the switch that {} attaches to. " +
- "Unable to process ICMPv6 request.", destIpAddress);
- return;
+ // Search SID only if store lookup is success otherwise proceed with "sid=-1"
+ int sid = -1;
+ if (destRouterAddress != null) {
+ sid = config.getIPv6SegmentId(destRouterAddress);
+ if (sid < 0) {
+ 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());
}
@@ -301,16 +316,39 @@
/**
* Helper method to handle the ndp requests.
- *
* @param pkt the ndp packet request and context information
* @param hostService the host service
*/
private void handleNdpRequest(NeighbourMessageContext pkt, HostService hostService) {
// ND request for the gateway. We have to reply on behalf of the gateway.
if (isNdpForGateway(pkt)) {
- log.trace("Sending NDP reply on behalf of gateway IP for pkt: {}", pkt);
- sendResponse(pkt, config.getRouterMacForAGatewayIp(pkt.target()), hostService);
+ log.trace("Sending NDP reply on behalf of gateway IP for pkt: {}", pkt.target());
+ MacAddress routerMac = config.getRouterMacForAGatewayIp(pkt.target());
+ sendResponse(pkt, routerMac, hostService);
} else {
+
+ // Process NDP targets towards EUI-64 address.
+ try {
+ DeviceId deviceId = pkt.inPort().deviceId();
+ Optional<MacAddress> macAddress = srManager.interfaceService.getInterfacesByPort(pkt.inPort())
+ .stream()
+ .map(Interface::mac)
+ .findFirst();
+ if (!macAddress.isPresent()) {
+ log.warn("Failed in fetching MAC address of {}. Aborting NDP processing.", pkt.inPort());
+ return;
+ }
+ MacAddress interfaceMac = MacAddress.valueOf(macAddress.get().toBytes());
+ Ip6Address interfaceLinkLocalIP = Ip6Address.valueOf(IPv6.getLinkLocalAddress(interfaceMac.toBytes()));
+ if (pkt.target().equals(interfaceLinkLocalIP)) {
+ MacAddress routerMac = config.getDeviceMac(deviceId);
+ sendResponse(pkt, routerMac, hostService);
+ }
+ } catch (DeviceConfigNotFoundException e) {
+ log.warn(e.getMessage() + " Unable to handle NDP packet to {}. Aborting.", pkt.target());
+ return;
+ }
+
// NOTE: Ignore NDP packets except those target for the router
// We will reconsider enabling this when we have host learning support
/*
@@ -376,6 +414,7 @@
private boolean isNdpForGateway(NeighbourMessageContext pkt) {
DeviceId deviceId = pkt.inPort().deviceId();
Set<IpAddress> gatewayIpAddresses = null;
+
try {
if (pkt.target().equals(config.getRouterIpv6(deviceId))) {
return true;
@@ -383,14 +422,13 @@
gatewayIpAddresses = config.getPortIPs(deviceId);
} catch (DeviceConfigNotFoundException e) {
log.warn(e.getMessage() + " Aborting check for router IP in processing ndp");
+ return false;
}
-
return gatewayIpAddresses != null && gatewayIpAddresses.stream()
.filter(IpAddress::isIp6)
.anyMatch(gatewayIp -> gatewayIp.equals(pkt.target()) ||
Arrays.equals(IPv6.getSolicitNodeAddress(gatewayIp.toOctets()),
- pkt.target().toOctets())
- );
+ pkt.target().toOctets()));
}
/**