Remove next hop location from resolved route
The next hop location should be obtained from host service
Change-Id: I8652e6b8b1367097ffbfcb1651538c34819f67d6
diff --git a/apps/route-service/api/src/main/java/org/onosproject/routeservice/ResolvedRoute.java b/apps/route-service/api/src/main/java/org/onosproject/routeservice/ResolvedRoute.java
index 828827d..1795e1e 100644
--- a/apps/route-service/api/src/main/java/org/onosproject/routeservice/ResolvedRoute.java
+++ b/apps/route-service/api/src/main/java/org/onosproject/routeservice/ResolvedRoute.java
@@ -29,6 +29,7 @@
/**
* Represents a route with the next hop MAC address resolved.
*/
+// TODO Remove location from ResolvedRoute
public class ResolvedRoute {
private final Route route;
@@ -42,7 +43,9 @@
* @param route input route
* @param nextHopMac next hop MAC address
* @param location connect point where the next hop connects to
+ * @deprecated in 1.11 ("Loon")
*/
+ @Deprecated
public ResolvedRoute(Route route, MacAddress nextHopMac, ConnectPoint location) {
this(route, nextHopMac, VlanId.NONE, location);
}
@@ -54,7 +57,9 @@
* @param nextHopMac next hop MAC address
* @param nextHopVlan next hop VLAN ID
* @param location connect point where the next hop connects to
+ * @deprecated in 1.11 ("Loon")
*/
+ @Deprecated
public ResolvedRoute(Route route, MacAddress nextHopMac, VlanId nextHopVlan,
ConnectPoint location) {
this.route = route;
@@ -63,6 +68,31 @@
this.location = location;
}
+
+ /**
+ * Creates a new resolved route.
+ *
+ * @param route input route
+ * @param nextHopMac next hop MAC address
+ */
+ public ResolvedRoute(Route route, MacAddress nextHopMac) {
+ this(route, nextHopMac, VlanId.NONE);
+ }
+
+ /**
+ * Creates a new resolved route.
+ *
+ * @param route input route
+ * @param nextHopMac next hop MAC address
+ * @param nextHopVlan next hop VLAN ID
+ */
+ public ResolvedRoute(Route route, MacAddress nextHopMac, VlanId nextHopVlan) {
+ this.route = route;
+ this.nextHopMac = nextHopMac;
+ this.nextHopVlan = nextHopVlan;
+ this.location = null;
+ }
+
/**
* Returns the original route.
*
@@ -112,7 +142,9 @@
* Returns the next hop location.
*
* @return connect point where the next hop attaches to
+ * @deprecated in 1.11 ("Loon")
*/
+ @Deprecated
public ConnectPoint location() {
return location;
}
diff --git a/apps/route-service/app/src/main/java/org/onosproject/routeservice/impl/RouteManager.java b/apps/route-service/app/src/main/java/org/onosproject/routeservice/impl/RouteManager.java
index e5db364..8914a1e 100644
--- a/apps/route-service/app/src/main/java/org/onosproject/routeservice/impl/RouteManager.java
+++ b/apps/route-service/app/src/main/java/org/onosproject/routeservice/impl/RouteManager.java
@@ -197,7 +197,7 @@
private ResolvedRoute tryResolve(Route route) {
ResolvedRoute resolvedRoute = resolve(route);
if (resolvedRoute == null) {
- resolvedRoute = new ResolvedRoute(route, null, null);
+ resolvedRoute = new ResolvedRoute(route, null, null, null);
}
return resolvedRoute;
}
@@ -238,13 +238,9 @@
hostService.startMonitoringIp(route.nextHop());
Set<Host> hosts = hostService.getHostsByIp(route.nextHop());
- Optional<Host> host = hosts.stream().findFirst();
- if (host.isPresent()) {
- return new ResolvedRoute(route, host.get().mac(), host.get().vlan(),
- host.get().location());
- } else {
- return null;
- }
+ return hosts.stream().findFirst()
+ .map(host -> new ResolvedRoute(route, host.mac(), host.vlan(), host.location()))
+ .orElse(null);
}
private ResolvedRoute decide(ResolvedRoute route1, ResolvedRoute route2) {
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 2113e71..23bbf07 100644
--- a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/IcmpHandler.java
+++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/IcmpHandler.java
@@ -29,7 +29,6 @@
import org.onlab.packet.ndp.NeighborSolicitation;
import org.onosproject.net.neighbour.NeighbourMessageContext;
import org.onosproject.net.neighbour.NeighbourMessageType;
-import org.onosproject.routeservice.ResolvedRoute;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DeviceId;
import org.onosproject.net.flow.DefaultTrafficTreatment;
@@ -165,12 +164,15 @@
// 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()) {
+ Optional<DeviceId> deviceId = srManager.routeService
+ .longestPrefixLookup(destIpAddress).map(srManager::nextHopLocations)
+ .flatMap(locations -> locations.stream().findFirst())
+ .map(ConnectPoint::deviceId);
+ if (deviceId.isPresent()) {
try {
- destRouterAddress = config.getRouterIpv4(nexthop.get().location().deviceId());
+ destRouterAddress = config.getRouterIpv4(deviceId.get());
} catch (DeviceConfigNotFoundException e) {
- log.warn("Device config not found. Abort ICMP processing");
+ log.warn("Device config for {} not found. Abort ICMP processing", deviceId);
return;
}
}
@@ -240,12 +242,15 @@
// 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()) {
+ Optional<DeviceId> deviceId = srManager.routeService
+ .longestPrefixLookup(destIpAddress).map(srManager::nextHopLocations)
+ .flatMap(locations -> locations.stream().findFirst())
+ .map(ConnectPoint::deviceId);
+ if (deviceId.isPresent()) {
try {
- destRouterAddress = config.getRouterIpv6(nexthop.get().location().deviceId());
+ destRouterAddress = config.getRouterIpv6(deviceId.get());
} catch (DeviceConfigNotFoundException e) {
- log.warn("Device config not found. Abort ICMPv6 processing");
+ log.warn("Device config for {} not found. Abort ICMPv6 processing", deviceId);
return;
}
}
diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/RouteHandler.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/RouteHandler.java
index c82b39b..214ba6b 100644
--- a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/RouteHandler.java
+++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/RouteHandler.java
@@ -22,9 +22,9 @@
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
+import org.onosproject.net.ConnectPoint;
import org.onosproject.routeservice.ResolvedRoute;
import org.onosproject.routeservice.RouteEvent;
-import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DeviceId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -38,22 +38,24 @@
private static final Logger log = LoggerFactory.getLogger(RouteHandler.class);
private final SegmentRoutingManager srManager;
- public RouteHandler(SegmentRoutingManager srManager) {
+ RouteHandler(SegmentRoutingManager srManager) {
this.srManager = srManager;
}
protected void init(DeviceId deviceId) {
- srManager.routeService.getRouteTables().forEach(routeTableId -> {
- srManager.routeService.getRoutes(routeTableId).forEach(routeInfo -> {
- routeInfo.allRoutes().stream()
- .filter(resolvedRoute -> resolvedRoute.location() != null &&
- resolvedRoute.location().deviceId().equals(deviceId))
- .forEach(this::processRouteAddedInternal);
- });
- });
+ srManager.routeService.getRouteTables().forEach(routeTableId ->
+ srManager.routeService.getRoutes(routeTableId).forEach(routeInfo ->
+ routeInfo.allRoutes().forEach(resolvedRoute ->
+ srManager.nextHopLocations(resolvedRoute).stream()
+ .filter(location -> deviceId.equals(location.deviceId()))
+ .forEach(location -> processRouteAddedInternal(resolvedRoute)
+ )
+ )
+ )
+ );
}
- protected void processRouteAdded(RouteEvent event) {
+ void processRouteAdded(RouteEvent event) {
log.info("processRouteAdded {}", event);
processRouteAddedInternal(event.subject());
}
@@ -67,7 +69,12 @@
IpPrefix prefix = route.prefix();
MacAddress nextHopMac = route.nextHopMac();
VlanId nextHopVlan = route.nextHopVlan();
- ConnectPoint location = route.location();
+ ConnectPoint location = srManager.nextHopLocations(route).stream().findFirst().orElse(null);
+
+ if (location == null) {
+ log.info("{} ignored. Cannot find nexthop location", prefix);
+ return;
+ }
srManager.deviceConfiguration.addSubnet(location, prefix);
// XXX need to handle the case where there are two connectpoints
@@ -77,13 +84,13 @@
nextHopMac, nextHopVlan, location.port());
}
- protected void processRouteUpdated(RouteEvent event) {
+ void processRouteUpdated(RouteEvent event) {
log.info("processRouteUpdated {}", event);
processRouteRemovedInternal(event.prevSubject());
processRouteAddedInternal(event.subject());
}
- protected void processRouteRemoved(RouteEvent event) {
+ void processRouteRemoved(RouteEvent event) {
log.info("processRouteRemoved {}", event);
processRouteRemovedInternal(event.subject());
}
@@ -97,7 +104,12 @@
IpPrefix prefix = route.prefix();
MacAddress nextHopMac = route.nextHopMac();
VlanId nextHopVlan = route.nextHopVlan();
- ConnectPoint location = route.location();
+ ConnectPoint location = srManager.nextHopLocations(route).stream().findFirst().orElse(null);
+
+ if (location == null) {
+ log.info("{} ignored. Cannot find nexthop location", prefix);
+ return;
+ }
srManager.deviceConfiguration.removeSubnet(location, prefix);
srManager.defaultRoutingHandler.revokeSubnet(ImmutableSet.of(prefix));
diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
index 39b901b..6be675a 100644
--- a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
+++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
@@ -29,6 +29,7 @@
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;
+import com.google.common.collect.Sets;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
@@ -50,6 +51,8 @@
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
+import org.onosproject.net.Host;
+import org.onosproject.net.HostId;
import org.onosproject.net.Link;
import org.onosproject.net.Port;
import org.onosproject.net.PortNumber;
@@ -84,6 +87,7 @@
import org.onosproject.net.packet.PacketService;
import org.onosproject.net.topology.PathService;
import org.onosproject.net.topology.TopologyService;
+import org.onosproject.routeservice.ResolvedRoute;
import org.onosproject.routeservice.RouteEvent;
import org.onosproject.routeservice.RouteListener;
import org.onosproject.routeservice.RouteService;
@@ -696,6 +700,19 @@
}
/**
+ * Returns locations of given resolved route.
+ *
+ * @param resolvedRoute resolved route
+ * @return locations of nexthop. Might be empty if next hop is not found
+ */
+ Set<ConnectPoint> nextHopLocations(ResolvedRoute resolvedRoute) {
+ HostId hostId = HostId.hostId(resolvedRoute.nextHopMac(), resolvedRoute.nextHopVlan());
+ return Optional.ofNullable(hostService.getHost(hostId))
+ .map(Host::locations).orElse(Sets.newHashSet())
+ .stream().map(l -> (ConnectPoint) l).collect(Collectors.toSet());
+ }
+
+ /**
* Returns vlan port map of given device.
*
* @param deviceId device id
diff --git a/apps/segmentrouting/src/test/java/org/onosproject/segmentrouting/MockHostService.java b/apps/segmentrouting/src/test/java/org/onosproject/segmentrouting/MockHostService.java
index 1bd593c..e8c4701 100644
--- a/apps/segmentrouting/src/test/java/org/onosproject/segmentrouting/MockHostService.java
+++ b/apps/segmentrouting/src/test/java/org/onosproject/segmentrouting/MockHostService.java
@@ -18,6 +18,7 @@
import com.google.common.collect.ImmutableSet;
import org.onosproject.net.Host;
+import org.onosproject.net.HostId;
import org.onosproject.net.host.HostServiceAdapter;
import java.util.Set;
@@ -36,4 +37,9 @@
public Set<Host> getHosts() {
return hosts;
}
+
+ @Override
+ public Host getHost(HostId hostId) {
+ return hosts.stream().filter(host -> hostId.equals(host.id())).findFirst().orElse(null);
+ }
}
diff --git a/apps/segmentrouting/src/test/java/org/onosproject/segmentrouting/RouteHandlerTest.java b/apps/segmentrouting/src/test/java/org/onosproject/segmentrouting/RouteHandlerTest.java
index fc8c294..383f800 100644
--- a/apps/segmentrouting/src/test/java/org/onosproject/segmentrouting/RouteHandlerTest.java
+++ b/apps/segmentrouting/src/test/java/org/onosproject/segmentrouting/RouteHandlerTest.java
@@ -25,11 +25,15 @@
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DefaultHost;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Host;
+import org.onosproject.net.HostId;
+import org.onosproject.net.HostLocation;
import org.onosproject.net.config.NetworkConfigRegistryAdapter;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.intf.Interface;
+import org.onosproject.net.provider.ProviderId;
import org.onosproject.routeservice.ResolvedRoute;
import org.onosproject.routeservice.Route;
import org.onosproject.routeservice.RouteEvent;
@@ -62,19 +66,24 @@
private static final VlanId V1 = VlanId.vlanId((short) 1);
private static final ConnectPoint CP1 = ConnectPoint.deviceConnectPoint("of:0000000000000001/1");
private static final Route R1 = new Route(Route.Source.STATIC, P1, N1);
- private static final ResolvedRoute RR1 = new ResolvedRoute(R1, M1, V1, CP1);
+ private static final ResolvedRoute RR1 = new ResolvedRoute(R1, M1, V1);
private static final IpAddress N2 = IpAddress.valueOf("10.0.2.254");
private static final MacAddress M2 = MacAddress.valueOf("00:00:00:00:00:02");
private static final VlanId V2 = VlanId.vlanId((short) 2);
private static final ConnectPoint CP2 = ConnectPoint.deviceConnectPoint("of:0000000000000001/2");
private static final Route R2 = new Route(Route.Source.STATIC, P1, N2);
- private static final ResolvedRoute RR2 = new ResolvedRoute(R2, M2, V2, CP2);
+ private static final ResolvedRoute RR2 = new ResolvedRoute(R2, M2, V2);
private static final RouteInfo RI1 = new RouteInfo(P1, RR1, Sets.newHashSet(RR1));
+ private static final Host H1 = new DefaultHost(ProviderId.NONE, HostId.hostId(M1, V1), M1, V1,
+ Sets.newHashSet(new HostLocation(CP1, 0)), Sets.newHashSet(N1), false);
+ private static final Host H2 = new DefaultHost(ProviderId.NONE, HostId.hostId(M2, V2), M2, V2,
+ Sets.newHashSet(new HostLocation(CP2, 0)), Sets.newHashSet(N2), false);
+
// A set of hosts
- private static final Set<Host> HOSTS = Sets.newHashSet();
+ private static final Set<Host> HOSTS = Sets.newHashSet(H1, H2);
// A set of devices of which we have mastership
private static final Set<DeviceId> LOCAL_DEVICES = Sets.newHashSet();
// A set of interfaces
@@ -127,7 +136,11 @@
routeHandler.init(CP1.deviceId());
assertEquals(1, ROUTING_TABLE.size());
- assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1)));
+ MockRoutingTableValue rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
+ assertEquals(M1, rtv1.macAddress);
+ assertEquals(V1, rtv1.vlanId);
+ assertEquals(CP1.port(), rtv1.portNumber);
+
assertEquals(1, SUBNET_TABLE.size());
assertTrue(SUBNET_TABLE.get(CP1).contains(P1));
}
@@ -138,7 +151,11 @@
routeHandler.processRouteAdded(re);
assertEquals(1, ROUTING_TABLE.size());
- assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1)));
+ MockRoutingTableValue rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
+ assertEquals(M1, rtv1.macAddress);
+ assertEquals(V1, rtv1.vlanId);
+ assertEquals(CP1.port(), rtv1.portNumber);
+
assertEquals(1, SUBNET_TABLE.size());
assertTrue(SUBNET_TABLE.get(CP1).contains(P1));
}
@@ -151,7 +168,11 @@
routeHandler.processRouteUpdated(re);
assertEquals(1, ROUTING_TABLE.size());
- assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(CP2.deviceId(), P1)));
+ MockRoutingTableValue rtv2 = ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1));
+ assertEquals(M2, rtv2.macAddress);
+ assertEquals(V2, rtv2.vlanId);
+ assertEquals(CP2.port(), rtv2.portNumber);
+
assertEquals(1, SUBNET_TABLE.size());
assertTrue(SUBNET_TABLE.get(CP2).contains(P1));
}
@@ -166,5 +187,4 @@
assertEquals(0, ROUTING_TABLE.size());
assertEquals(0, SUBNET_TABLE.size());
}
-
}
\ No newline at end of file