Committed by
Gerrit Code Review
Distinguish between route added and route updated
Change-Id: Ia82ccf8e457bf07c9a8eed8141df013030eb8389
Showing
2 changed files
with
83 additions
and
26 deletions
... | @@ -65,6 +65,7 @@ public class RouteManagerTest { | ... | @@ -65,6 +65,7 @@ public class RouteManagerTest { |
65 | PortNumber.portNumber(1)); | 65 | PortNumber.portNumber(1)); |
66 | 66 | ||
67 | private static final IpPrefix V4_PREFIX1 = Ip4Prefix.valueOf("1.1.1.0/24"); | 67 | private static final IpPrefix V4_PREFIX1 = Ip4Prefix.valueOf("1.1.1.0/24"); |
68 | + private static final IpPrefix V4_PREFIX2 = Ip4Prefix.valueOf("2.2.2.0/24"); | ||
68 | private static final IpPrefix V6_PREFIX1 = Ip6Prefix.valueOf("4000::/64"); | 69 | private static final IpPrefix V6_PREFIX1 = Ip6Prefix.valueOf("4000::/64"); |
69 | 70 | ||
70 | private static final IpAddress V4_NEXT_HOP1 = Ip4Address.valueOf("192.168.10.1"); | 71 | private static final IpAddress V4_NEXT_HOP1 = Ip4Address.valueOf("192.168.10.1"); |
... | @@ -175,16 +176,16 @@ public class RouteManagerTest { | ... | @@ -175,16 +176,16 @@ public class RouteManagerTest { |
175 | * Tests adding routes to the route manager. | 176 | * Tests adding routes to the route manager. |
176 | */ | 177 | */ |
177 | @Test | 178 | @Test |
178 | - public void testIpv4RouteAdd() { | 179 | + public void testRouteAdd() { |
179 | Route route = new Route(Route.Source.STATIC, V4_PREFIX1, V4_NEXT_HOP1); | 180 | Route route = new Route(Route.Source.STATIC, V4_PREFIX1, V4_NEXT_HOP1); |
180 | ResolvedRoute resolvedRoute = new ResolvedRoute(route, MAC1); | 181 | ResolvedRoute resolvedRoute = new ResolvedRoute(route, MAC1); |
181 | 182 | ||
182 | - testRouteAdd(route, resolvedRoute); | 183 | + verifyRouteAdd(route, resolvedRoute); |
183 | 184 | ||
184 | route = new Route(Route.Source.STATIC, V6_PREFIX1, V6_NEXT_HOP1); | 185 | route = new Route(Route.Source.STATIC, V6_PREFIX1, V6_NEXT_HOP1); |
185 | resolvedRoute = new ResolvedRoute(route, MAC3); | 186 | resolvedRoute = new ResolvedRoute(route, MAC3); |
186 | 187 | ||
187 | - testRouteAdd(route, resolvedRoute); | 188 | + verifyRouteAdd(route, resolvedRoute); |
188 | } | 189 | } |
189 | 190 | ||
190 | /** | 191 | /** |
... | @@ -195,10 +196,10 @@ public class RouteManagerTest { | ... | @@ -195,10 +196,10 @@ public class RouteManagerTest { |
195 | * @param resolvedRoute resolved route that should be sent to the route | 196 | * @param resolvedRoute resolved route that should be sent to the route |
196 | * listener | 197 | * listener |
197 | */ | 198 | */ |
198 | - private void testRouteAdd(Route route, ResolvedRoute resolvedRoute) { | 199 | + private void verifyRouteAdd(Route route, ResolvedRoute resolvedRoute) { |
199 | reset(routeListener); | 200 | reset(routeListener); |
200 | 201 | ||
201 | - routeListener.event(new RouteEvent(RouteEvent.Type.ROUTE_UPDATED, resolvedRoute)); | 202 | + routeListener.event(new RouteEvent(RouteEvent.Type.ROUTE_ADDED, resolvedRoute)); |
202 | 203 | ||
203 | replay(routeListener); | 204 | replay(routeListener); |
204 | 205 | ||
... | @@ -216,31 +217,63 @@ public class RouteManagerTest { | ... | @@ -216,31 +217,63 @@ public class RouteManagerTest { |
216 | Route updatedRoute = new Route(Route.Source.STATIC, V4_PREFIX1, V4_NEXT_HOP2); | 217 | Route updatedRoute = new Route(Route.Source.STATIC, V4_PREFIX1, V4_NEXT_HOP2); |
217 | ResolvedRoute updatedResolvedRoute = new ResolvedRoute(updatedRoute, MAC2); | 218 | ResolvedRoute updatedResolvedRoute = new ResolvedRoute(updatedRoute, MAC2); |
218 | 219 | ||
219 | - testRouteUpdated(route, updatedRoute, updatedResolvedRoute); | 220 | + verifyRouteRemoveThenAdd(route, updatedRoute, updatedResolvedRoute); |
221 | + | ||
222 | + // Different prefix pointing to the same next hop. | ||
223 | + // In this case we expect to receive a ROUTE_UPDATED event. | ||
224 | + route = new Route(Route.Source.STATIC, V4_PREFIX2, V4_NEXT_HOP1); | ||
225 | + updatedRoute = new Route(Route.Source.STATIC, V4_PREFIX2, V4_NEXT_HOP2); | ||
226 | + updatedResolvedRoute = new ResolvedRoute(updatedRoute, MAC2); | ||
227 | + | ||
228 | + verifyRouteUpdated(route, updatedRoute, updatedResolvedRoute); | ||
220 | 229 | ||
221 | route = new Route(Route.Source.STATIC, V6_PREFIX1, V6_NEXT_HOP1); | 230 | route = new Route(Route.Source.STATIC, V6_PREFIX1, V6_NEXT_HOP1); |
222 | updatedRoute = new Route(Route.Source.STATIC, V6_PREFIX1, V6_NEXT_HOP2); | 231 | updatedRoute = new Route(Route.Source.STATIC, V6_PREFIX1, V6_NEXT_HOP2); |
223 | updatedResolvedRoute = new ResolvedRoute(updatedRoute, MAC4); | 232 | updatedResolvedRoute = new ResolvedRoute(updatedRoute, MAC4); |
224 | 233 | ||
225 | - testRouteUpdated(route, updatedRoute, updatedResolvedRoute); | 234 | + verifyRouteRemoveThenAdd(route, updatedRoute, updatedResolvedRoute); |
226 | } | 235 | } |
227 | 236 | ||
228 | /** | 237 | /** |
229 | - * Tests updating a route and verifies that the correct events are sent to | 238 | + * Tests updating a route and verifies that the route listener receives a |
230 | - * the route listener. | 239 | + * route remove event followed by a route add event. |
231 | * | 240 | * |
232 | * @param original original route | 241 | * @param original original route |
233 | * @param updated updated route | 242 | * @param updated updated route |
234 | * @param updatedResolvedRoute resolved route that is expected to be sent to | 243 | * @param updatedResolvedRoute resolved route that is expected to be sent to |
235 | - * the routelistener | 244 | + * the route listener |
236 | */ | 245 | */ |
237 | - private void testRouteUpdated(Route original, Route updated, | 246 | + private void verifyRouteRemoveThenAdd(Route original, Route updated, |
238 | ResolvedRoute updatedResolvedRoute) { | 247 | ResolvedRoute updatedResolvedRoute) { |
239 | // First add the original route | 248 | // First add the original route |
240 | addRoute(original); | 249 | addRoute(original); |
241 | 250 | ||
242 | routeListener.event(new RouteEvent(RouteEvent.Type.ROUTE_REMOVED, new ResolvedRoute(original, null))); | 251 | routeListener.event(new RouteEvent(RouteEvent.Type.ROUTE_REMOVED, new ResolvedRoute(original, null))); |
243 | expectLastCall().once(); | 252 | expectLastCall().once(); |
253 | + routeListener.event(new RouteEvent(RouteEvent.Type.ROUTE_ADDED, updatedResolvedRoute)); | ||
254 | + expectLastCall().once(); | ||
255 | + | ||
256 | + replay(routeListener); | ||
257 | + | ||
258 | + routeManager.update(Collections.singleton(updated)); | ||
259 | + | ||
260 | + verify(routeListener); | ||
261 | + } | ||
262 | + | ||
263 | + /** | ||
264 | + * Tests updating a route and verifies that the route listener receives a | ||
265 | + * route updated event. | ||
266 | + * | ||
267 | + * @param original original route | ||
268 | + * @param updated updated route | ||
269 | + * @param updatedResolvedRoute resolved route that is expected to be sent to | ||
270 | + * the route listener | ||
271 | + */ | ||
272 | + private void verifyRouteUpdated(Route original, Route updated, | ||
273 | + ResolvedRoute updatedResolvedRoute) { | ||
274 | + // First add the original route | ||
275 | + addRoute(original); | ||
276 | + | ||
244 | routeListener.event(new RouteEvent(RouteEvent.Type.ROUTE_UPDATED, updatedResolvedRoute)); | 277 | routeListener.event(new RouteEvent(RouteEvent.Type.ROUTE_UPDATED, updatedResolvedRoute)); |
245 | expectLastCall().once(); | 278 | expectLastCall().once(); |
246 | 279 | ||
... | @@ -255,14 +288,14 @@ public class RouteManagerTest { | ... | @@ -255,14 +288,14 @@ public class RouteManagerTest { |
255 | * Tests deleting routes from the route manager. | 288 | * Tests deleting routes from the route manager. |
256 | */ | 289 | */ |
257 | @Test | 290 | @Test |
258 | - public void testIpv4RouteDelete() { | 291 | + public void testRouteDelete() { |
259 | Route route = new Route(Route.Source.STATIC, V4_PREFIX1, V4_NEXT_HOP1); | 292 | Route route = new Route(Route.Source.STATIC, V4_PREFIX1, V4_NEXT_HOP1); |
260 | 293 | ||
261 | - testDelete(route); | 294 | + verifyDelete(route); |
262 | 295 | ||
263 | route = new Route(Route.Source.STATIC, V6_PREFIX1, V6_NEXT_HOP1); | 296 | route = new Route(Route.Source.STATIC, V6_PREFIX1, V6_NEXT_HOP1); |
264 | 297 | ||
265 | - testDelete(route); | 298 | + verifyDelete(route); |
266 | } | 299 | } |
267 | 300 | ||
268 | /** | 301 | /** |
... | @@ -271,7 +304,7 @@ public class RouteManagerTest { | ... | @@ -271,7 +304,7 @@ public class RouteManagerTest { |
271 | * | 304 | * |
272 | * @param route route to delete | 305 | * @param route route to delete |
273 | */ | 306 | */ |
274 | - private void testDelete(Route route) { | 307 | + private void verifyDelete(Route route) { |
275 | addRoute(route); | 308 | addRoute(route); |
276 | 309 | ||
277 | RouteEvent withdrawRouteEvent = new RouteEvent(RouteEvent.Type.ROUTE_REMOVED, | 310 | RouteEvent withdrawRouteEvent = new RouteEvent(RouteEvent.Type.ROUTE_REMOVED, |
... | @@ -288,7 +321,8 @@ public class RouteManagerTest { | ... | @@ -288,7 +321,8 @@ public class RouteManagerTest { |
288 | } | 321 | } |
289 | 322 | ||
290 | /** | 323 | /** |
291 | - * Tests adding a route entry with asynchronous HostService replies. | 324 | + * Tests adding a route entry where the HostService does not immediately |
325 | + * know the MAC address of the next hop, but this is learnt later. | ||
292 | */ | 326 | */ |
293 | @Test | 327 | @Test |
294 | public void testAsyncRouteAdd() { | 328 | public void testAsyncRouteAdd() { |
... | @@ -311,7 +345,7 @@ public class RouteManagerTest { | ... | @@ -311,7 +345,7 @@ public class RouteManagerTest { |
311 | 345 | ||
312 | // Now when we send the event, we expect the FIB update to be sent | 346 | // Now when we send the event, we expect the FIB update to be sent |
313 | reset(routeListener); | 347 | reset(routeListener); |
314 | - routeListener.event(new RouteEvent(RouteEvent.Type.ROUTE_UPDATED, | 348 | + routeListener.event(new RouteEvent(RouteEvent.Type.ROUTE_ADDED, |
315 | new ResolvedRoute(route, MAC1))); | 349 | new ResolvedRoute(route, MAC1))); |
316 | replay(routeListener); | 350 | replay(routeListener); |
317 | 351 | ... | ... |
... | @@ -118,10 +118,16 @@ public class LocalRouteStore extends AbstractStore<RouteEvent, RouteStoreDelegat | ... | @@ -118,10 +118,16 @@ public class LocalRouteStore extends AbstractStore<RouteEvent, RouteStoreDelegat |
118 | Collection<Route> routes = getDefaultRouteTable(ip).getRoutesForNextHop(ip); | 118 | Collection<Route> routes = getDefaultRouteTable(ip).getRoutesForNextHop(ip); |
119 | 119 | ||
120 | if (!routes.isEmpty() && !mac.equals(nextHops.get(ip))) { | 120 | if (!routes.isEmpty() && !mac.equals(nextHops.get(ip))) { |
121 | - nextHops.put(ip, mac); | 121 | + MacAddress oldMac = nextHops.put(ip, mac); |
122 | 122 | ||
123 | for (Route route : routes) { | 123 | for (Route route : routes) { |
124 | - notifyDelegate(new RouteEvent(RouteEvent.Type.ROUTE_UPDATED, new ResolvedRoute(route, mac))); | 124 | + if (oldMac == null) { |
125 | + notifyDelegate(new RouteEvent(RouteEvent.Type.ROUTE_ADDED, | ||
126 | + new ResolvedRoute(route, mac))); | ||
127 | + } else { | ||
128 | + notifyDelegate(new RouteEvent(RouteEvent.Type.ROUTE_UPDATED, | ||
129 | + new ResolvedRoute(route, mac))); | ||
130 | + } | ||
125 | } | 131 | } |
126 | } | 132 | } |
127 | } | 133 | } |
... | @@ -131,7 +137,8 @@ public class LocalRouteStore extends AbstractStore<RouteEvent, RouteStoreDelegat | ... | @@ -131,7 +137,8 @@ public class LocalRouteStore extends AbstractStore<RouteEvent, RouteStoreDelegat |
131 | if (nextHops.remove(ip, mac)) { | 137 | if (nextHops.remove(ip, mac)) { |
132 | Collection<Route> routes = getDefaultRouteTable(ip).getRoutesForNextHop(ip); | 138 | Collection<Route> routes = getDefaultRouteTable(ip).getRoutesForNextHop(ip); |
133 | for (Route route : routes) { | 139 | for (Route route : routes) { |
134 | - notifyDelegate(new RouteEvent(RouteEvent.Type.ROUTE_REMOVED, new ResolvedRoute(route, null))); | 140 | + notifyDelegate(new RouteEvent(RouteEvent.Type.ROUTE_REMOVED, |
141 | + new ResolvedRoute(route, null))); | ||
135 | } | 142 | } |
136 | } | 143 | } |
137 | } | 144 | } |
... | @@ -211,15 +218,30 @@ public class LocalRouteStore extends AbstractStore<RouteEvent, RouteStoreDelegat | ... | @@ -211,15 +218,30 @@ public class LocalRouteStore extends AbstractStore<RouteEvent, RouteStoreDelegat |
211 | } | 218 | } |
212 | } | 219 | } |
213 | 220 | ||
214 | - if (oldRoute != null && !oldRoute.nextHop().equals(route.nextHop())) { | 221 | + if (route.equals(oldRoute)) { |
215 | - // Remove old route because new one is different | 222 | + // No need to send events if the new route is the same |
216 | - // TODO ROUTE_UPDATED? | 223 | + return; |
217 | - notifyDelegate(new RouteEvent(RouteEvent.Type.ROUTE_REMOVED, new ResolvedRoute(oldRoute, null))); | ||
218 | } | 224 | } |
219 | 225 | ||
220 | MacAddress nextHopMac = nextHops.get(route.nextHop()); | 226 | MacAddress nextHopMac = nextHops.get(route.nextHop()); |
227 | + | ||
228 | + if (oldRoute != null && !oldRoute.nextHop().equals(route.nextHop())) { | ||
229 | + if (nextHopMac == null) { | ||
230 | + // We don't know the new MAC address yet so delete the route | ||
231 | + notifyDelegate(new RouteEvent(RouteEvent.Type.ROUTE_REMOVED, | ||
232 | + new ResolvedRoute(oldRoute, null))); | ||
233 | + } else { | ||
234 | + // We know the new MAC address so update the route | ||
235 | + notifyDelegate(new RouteEvent(RouteEvent.Type.ROUTE_UPDATED, | ||
236 | + new ResolvedRoute(route, nextHopMac))); | ||
237 | + } | ||
238 | + return; | ||
239 | + } | ||
240 | + | ||
241 | + | ||
221 | if (nextHopMac != null) { | 242 | if (nextHopMac != null) { |
222 | - notifyDelegate(new RouteEvent(RouteEvent.Type.ROUTE_UPDATED, new ResolvedRoute(route, nextHopMac))); | 243 | + notifyDelegate(new RouteEvent(RouteEvent.Type.ROUTE_ADDED, |
244 | + new ResolvedRoute(route, nextHopMac))); | ||
223 | } | 245 | } |
224 | } | 246 | } |
225 | } | 247 | } |
... | @@ -236,7 +258,8 @@ public class LocalRouteStore extends AbstractStore<RouteEvent, RouteStoreDelegat | ... | @@ -236,7 +258,8 @@ public class LocalRouteStore extends AbstractStore<RouteEvent, RouteStoreDelegat |
236 | 258 | ||
237 | if (removed != null) { | 259 | if (removed != null) { |
238 | reverseIndex.remove(removed.nextHop(), removed); | 260 | reverseIndex.remove(removed.nextHop(), removed); |
239 | - notifyDelegate(new RouteEvent(RouteEvent.Type.ROUTE_REMOVED, new ResolvedRoute(route, null))); | 261 | + notifyDelegate(new RouteEvent(RouteEvent.Type.ROUTE_REMOVED, |
262 | + new ResolvedRoute(route, null))); | ||
240 | } | 263 | } |
241 | } | 264 | } |
242 | } | 265 | } | ... | ... |
-
Please register or login to post a comment