blob: f60bbc5f2a8ecb37c7ff011aa3a9f4412ce2e382 [file] [log] [blame]
Jonathan Hart41349e92015-02-09 14:14:02 -08001/*
Ray Milkey34c95902015-04-15 09:47:53 -07002 * Copyright 2014-2015 Open Networking Laboratory
Jonathan Hart41349e92015-02-09 14:14:02 -08003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Jonathan Hart2da1e602015-02-18 19:09:24 -080016package org.onosproject.routing.impl;
Jonathan Hart41349e92015-02-09 14:14:02 -080017
18import com.google.common.collect.Sets;
Pingping Line28ae4c2015-03-13 11:37:03 -070019
Jonathan Hart41349e92015-02-09 14:14:02 -080020import org.junit.After;
21import org.junit.Before;
22import org.junit.Test;
23import org.onlab.packet.Ip4Address;
24import org.onlab.packet.Ip4Prefix;
Charles Chand4db3ab2015-09-24 21:14:00 -070025import org.onlab.packet.Ip6Address;
26import org.onlab.packet.Ip6Prefix;
Jonathan Hart41349e92015-02-09 14:14:02 -080027import org.onlab.packet.IpAddress;
28import org.onlab.packet.IpPrefix;
29import org.onlab.packet.MacAddress;
30import org.onlab.packet.VlanId;
Jonathan Hart66018992015-07-31 11:19:27 -070031import org.onosproject.core.CoreService;
Jonathan Hart41349e92015-02-09 14:14:02 -080032import org.onosproject.net.ConnectPoint;
33import org.onosproject.net.DefaultHost;
34import org.onosproject.net.DeviceId;
35import org.onosproject.net.Host;
36import org.onosproject.net.HostId;
37import org.onosproject.net.HostLocation;
38import org.onosproject.net.PortNumber;
39import org.onosproject.net.host.HostListener;
40import org.onosproject.net.host.HostService;
41import org.onosproject.net.provider.ProviderId;
Jonathan Hart3930f632015-10-19 12:12:51 -070042import org.onosproject.routing.RouteSourceService;
Jonathan Hart2da1e602015-02-18 19:09:24 -080043import org.onosproject.routing.FibEntry;
44import org.onosproject.routing.FibListener;
45import org.onosproject.routing.FibUpdate;
46import org.onosproject.routing.RouteEntry;
47import org.onosproject.routing.RouteListener;
48import org.onosproject.routing.RouteUpdate;
Pingping Line28ae4c2015-03-13 11:37:03 -070049import org.onosproject.routing.config.RoutingConfigurationService;
Jonathan Hart41349e92015-02-09 14:14:02 -080050
51import java.util.Collections;
52
53import static org.easymock.EasyMock.*;
54import static org.junit.Assert.assertEquals;
55import static org.junit.Assert.assertTrue;
56
57/**
58 * This class tests adding a route, updating a route, deleting a route,
59 * and adding a route whose next hop is the local BGP speaker.
60 * <p/>
61 * The HostService answers requests synchronously.
62 */
63public class RouterTest {
64
65 private HostService hostService;
Pingping Line28ae4c2015-03-13 11:37:03 -070066 private RoutingConfigurationService routingConfigurationService;
Jonathan Hart41349e92015-02-09 14:14:02 -080067
68 private FibListener fibListener;
69
70 private static final ConnectPoint SW1_ETH1 = new ConnectPoint(
71 DeviceId.deviceId("of:0000000000000001"),
72 PortNumber.portNumber(1));
73
74 private static final ConnectPoint SW2_ETH1 = new ConnectPoint(
75 DeviceId.deviceId("of:0000000000000002"),
76 PortNumber.portNumber(1));
77
78 private static final ConnectPoint SW3_ETH1 = new ConnectPoint(
79 DeviceId.deviceId("of:0000000000000003"),
80 PortNumber.portNumber(1));
81
82 private static final ConnectPoint SW4_ETH1 = new ConnectPoint(
83 DeviceId.deviceId("of:0000000000000004"),
84 PortNumber.portNumber(1));
85
Charles Chand4db3ab2015-09-24 21:14:00 -070086 private static final ConnectPoint SW5_ETH1 = new ConnectPoint(
87 DeviceId.deviceId("of:0000000000000005"),
88 PortNumber.portNumber(1));
89
90 private static final ConnectPoint SW6_ETH1 = new ConnectPoint(
91 DeviceId.deviceId("of:0000000000000006"),
92 PortNumber.portNumber(1));
Jonathan Hart41349e92015-02-09 14:14:02 -080093 private Router router;
94
95 @Before
96 public void setUp() throws Exception {
97 setUpHostService();
Pingping Line28ae4c2015-03-13 11:37:03 -070098 routingConfigurationService =
99 createMock(RoutingConfigurationService.class);
Jonathan Hart41349e92015-02-09 14:14:02 -0800100
Jonathan Hart3930f632015-10-19 12:12:51 -0700101 RouteSourceService routeSourceService = createMock(RouteSourceService.class);
102 routeSourceService.start(anyObject(RouteListener.class));
103 routeSourceService.stop();
104 replay(routeSourceService);
Jonathan Hart41349e92015-02-09 14:14:02 -0800105
106 fibListener = createMock(FibListener.class);
107
108 router = new Router();
Jonathan Hart66018992015-07-31 11:19:27 -0700109 router.coreService = createNiceMock(CoreService.class);
Jonathan Hart41349e92015-02-09 14:14:02 -0800110 router.hostService = hostService;
Pingping Line28ae4c2015-03-13 11:37:03 -0700111 router.routingConfigurationService = routingConfigurationService;
Jonathan Hart3930f632015-10-19 12:12:51 -0700112 router.routeSourceService = routeSourceService;
Jonathan Hart41349e92015-02-09 14:14:02 -0800113 router.activate();
114
Pingping Line28ae4c2015-03-13 11:37:03 -0700115 router.addFibListener(fibListener);
116 router.start();
Jonathan Hart41349e92015-02-09 14:14:02 -0800117 }
118
119 @After
120 public void tearDown() {
121 router.stop();
122 }
123
124 /**
125 * Sets up the host service with details of some hosts.
126 */
127 private void setUpHostService() {
128 hostService = createMock(HostService.class);
129
130 hostService.addListener(anyObject(HostListener.class));
131 expectLastCall().anyTimes();
132
133 IpAddress host1Address = IpAddress.valueOf("192.168.10.1");
134 Host host1 = new DefaultHost(ProviderId.NONE, HostId.NONE,
135 MacAddress.valueOf("00:00:00:00:00:01"), VlanId.NONE,
136 new HostLocation(SW1_ETH1, 1),
137 Sets.newHashSet(host1Address));
138
139 expect(hostService.getHostsByIp(host1Address))
140 .andReturn(Sets.newHashSet(host1)).anyTimes();
141 hostService.startMonitoringIp(host1Address);
142 expectLastCall().anyTimes();
143
Jonathan Hart41349e92015-02-09 14:14:02 -0800144 IpAddress host2Address = IpAddress.valueOf("192.168.20.1");
145 Host host2 = new DefaultHost(ProviderId.NONE, HostId.NONE,
146 MacAddress.valueOf("00:00:00:00:00:02"), VlanId.NONE,
147 new HostLocation(SW2_ETH1, 1),
148 Sets.newHashSet(host2Address));
149
150 expect(hostService.getHostsByIp(host2Address))
151 .andReturn(Sets.newHashSet(host2)).anyTimes();
152 hostService.startMonitoringIp(host2Address);
153 expectLastCall().anyTimes();
154
155 // Next hop on a VLAN
156 IpAddress host3Address = IpAddress.valueOf("192.168.40.1");
157 Host host3 = new DefaultHost(ProviderId.NONE, HostId.NONE,
158 MacAddress.valueOf("00:00:00:00:00:03"), VlanId.vlanId((short) 1),
Charles Chand4db3ab2015-09-24 21:14:00 -0700159 new HostLocation(SW3_ETH1, 1),
Jonathan Hart41349e92015-02-09 14:14:02 -0800160 Sets.newHashSet(host3Address));
161
162 expect(hostService.getHostsByIp(host3Address))
163 .andReturn(Sets.newHashSet(host3)).anyTimes();
164 hostService.startMonitoringIp(host3Address);
165 expectLastCall().anyTimes();
166
Charles Chand4db3ab2015-09-24 21:14:00 -0700167 IpAddress host4Address = IpAddress.valueOf("1000::1");
168 Host host4 = new DefaultHost(ProviderId.NONE, HostId.NONE,
169 MacAddress.valueOf("00:00:00:00:00:04"), VlanId.NONE,
170 new HostLocation(SW4_ETH1, 1),
171 Sets.newHashSet(host4Address));
172
173 expect(hostService.getHostsByIp(host4Address))
174 .andReturn(Sets.newHashSet(host4)).anyTimes();
175 hostService.startMonitoringIp(host4Address);
176 expectLastCall().anyTimes();
177
178 IpAddress host5Address = IpAddress.valueOf("2000::1");
179 Host host5 = new DefaultHost(ProviderId.NONE, HostId.NONE,
180 MacAddress.valueOf("00:00:00:00:00:05"), VlanId.NONE,
181 new HostLocation(SW5_ETH1, 1),
182 Sets.newHashSet(host5Address));
183
184 expect(hostService.getHostsByIp(host5Address))
185 .andReturn(Sets.newHashSet(host5)).anyTimes();
186 hostService.startMonitoringIp(host5Address);
187 expectLastCall().anyTimes();
188
189 // Next hop on a VLAN
190 IpAddress host6Address = IpAddress.valueOf("3000::1");
191 Host host6 = new DefaultHost(ProviderId.NONE, HostId.NONE,
192 MacAddress.valueOf("00:00:00:00:00:06"), VlanId.vlanId((short) 1),
193 new HostLocation(SW6_ETH1, 1),
194 Sets.newHashSet(host6Address));
195
196 expect(hostService.getHostsByIp(host6Address))
197 .andReturn(Sets.newHashSet(host6)).anyTimes();
198 hostService.startMonitoringIp(host6Address);
199 expectLastCall().anyTimes();
200
201
Jonathan Hart41349e92015-02-09 14:14:02 -0800202 // Called during shutdown
203 hostService.removeListener(anyObject(HostListener.class));
204
205 replay(hostService);
206 }
207
208 /**
Charles Chand4db3ab2015-09-24 21:14:00 -0700209 * Tests adding a IPv4 route entry.
Jonathan Hart41349e92015-02-09 14:14:02 -0800210 */
211 @Test
Charles Chand4db3ab2015-09-24 21:14:00 -0700212 public void testIpv4RouteAdd() {
Jonathan Hart41349e92015-02-09 14:14:02 -0800213 // Construct a route entry
214 IpPrefix prefix = Ip4Prefix.valueOf("1.1.1.0/24");
215 IpAddress nextHopIp = Ip4Address.valueOf("192.168.10.1");
216
217 RouteEntry routeEntry = new RouteEntry(prefix, nextHopIp);
218
219 // Expected FIB entry
220 FibEntry fibEntry = new FibEntry(prefix, nextHopIp,
Charles Chand4db3ab2015-09-24 21:14:00 -0700221 MacAddress.valueOf("00:00:00:00:00:01"));
Jonathan Hart41349e92015-02-09 14:14:02 -0800222
223 fibListener.update(Collections.singletonList(new FibUpdate(
224 FibUpdate.Type.UPDATE, fibEntry)), Collections.emptyList());
225
226 replay(fibListener);
227
228 router.processRouteUpdates(Collections.singletonList(
229 new RouteUpdate(RouteUpdate.Type.UPDATE, routeEntry)));
230
231 verify(fibListener);
232 }
233
Charles Chand4db3ab2015-09-24 21:14:00 -0700234
Jonathan Hart41349e92015-02-09 14:14:02 -0800235 /**
Charles Chand4db3ab2015-09-24 21:14:00 -0700236 * Tests adding a IPv6 route entry.
237 */
238 @Test
239 public void testIpv6RouteAdd() {
240 // Construct a route entry
241 IpPrefix prefix = Ip6Prefix.valueOf("4000::/64");
242 IpAddress nextHopIp = Ip6Address.valueOf("1000::1");
243
244 RouteEntry routeEntry = new RouteEntry(prefix, nextHopIp);
245
246 // Expected FIB entry
247 FibEntry fibEntry = new FibEntry(prefix, nextHopIp,
248 MacAddress.valueOf("00:00:00:00:00:04"));
249
250 fibListener.update(Collections.singletonList(new FibUpdate(
251 FibUpdate.Type.UPDATE, fibEntry)), Collections.emptyList());
252
253 replay(fibListener);
254
255 router.processRouteUpdates(Collections.singletonList(
256 new RouteUpdate(RouteUpdate.Type.UPDATE, routeEntry)));
257
258 verify(fibListener);
259 }
260
261
262 /**
263 * Tests updating a IPv4 route entry.
Jonathan Hart41349e92015-02-09 14:14:02 -0800264 */
265 @Test
266 public void testRouteUpdate() {
267 // Firstly add a route
Charles Chand4db3ab2015-09-24 21:14:00 -0700268 testIpv4RouteAdd();
Jonathan Hart41349e92015-02-09 14:14:02 -0800269
270 // Route entry with updated next hop for the original prefix
271 RouteEntry routeEntryUpdate = new RouteEntry(
272 Ip4Prefix.valueOf("1.1.1.0/24"),
273 Ip4Address.valueOf("192.168.20.1"));
274
275 // The old FIB entry will be withdrawn
276 FibEntry withdrawFibEntry = new FibEntry(
277 Ip4Prefix.valueOf("1.1.1.0/24"), null, null);
278
279 // A new FIB entry will be added
280 FibEntry updateFibEntry = new FibEntry(
281 Ip4Prefix.valueOf("1.1.1.0/24"),
282 Ip4Address.valueOf("192.168.20.1"),
283 MacAddress.valueOf("00:00:00:00:00:02"));
284
285 reset(fibListener);
286 fibListener.update(Collections.singletonList(new FibUpdate(
287 FibUpdate.Type.UPDATE, updateFibEntry)),
288 Collections.singletonList(new FibUpdate(
289 FibUpdate.Type.DELETE, withdrawFibEntry)));
Jonathan Hart41349e92015-02-09 14:14:02 -0800290 replay(fibListener);
291
Pingping Line28ae4c2015-03-13 11:37:03 -0700292 reset(routingConfigurationService);
293 expect(routingConfigurationService.isIpPrefixLocal(
294 anyObject(IpPrefix.class))).andReturn(false);
295 replay(routingConfigurationService);
296
Jonathan Hart41349e92015-02-09 14:14:02 -0800297 router.processRouteUpdates(Collections.singletonList(new RouteUpdate(
298 RouteUpdate.Type.UPDATE, routeEntryUpdate)));
299
300 verify(fibListener);
301 }
302
303 /**
Charles Chand4db3ab2015-09-24 21:14:00 -0700304 * Tests updating a IPv6 route entry.
Jonathan Hart41349e92015-02-09 14:14:02 -0800305 */
306 @Test
Charles Chand4db3ab2015-09-24 21:14:00 -0700307 public void testIpv6RouteUpdate() {
Jonathan Hart41349e92015-02-09 14:14:02 -0800308 // Firstly add a route
Charles Chand4db3ab2015-09-24 21:14:00 -0700309 testIpv6RouteAdd();
310
311 // Route entry with updated next hop for the original prefix
312 RouteEntry routeEntryUpdate = new RouteEntry(
313 Ip6Prefix.valueOf("4000::/64"),
314 Ip6Address.valueOf("2000::1"));
315
316 // The old FIB entry will be withdrawn
317 FibEntry withdrawFibEntry = new FibEntry(
318 Ip6Prefix.valueOf("4000::/64"), null, null);
319
320 // A new FIB entry will be added
321 FibEntry updateFibEntry = new FibEntry(
322 Ip6Prefix.valueOf("4000::/64"),
323 Ip6Address.valueOf("2000::1"),
324 MacAddress.valueOf("00:00:00:00:00:05"));
325
326 reset(fibListener);
327 fibListener.update(Collections.singletonList(new FibUpdate(
328 FibUpdate.Type.UPDATE, updateFibEntry)),
329 Collections.singletonList(new FibUpdate(
330 FibUpdate.Type.DELETE, withdrawFibEntry)));
331 replay(fibListener);
332
333 reset(routingConfigurationService);
334 expect(routingConfigurationService.isIpPrefixLocal(
335 anyObject(IpPrefix.class))).andReturn(false);
336 replay(routingConfigurationService);
337
338 router.processRouteUpdates(Collections.singletonList(new RouteUpdate(
339 RouteUpdate.Type.UPDATE, routeEntryUpdate)));
340
341 verify(fibListener);
342 }
343
344 /**
345 * Tests deleting a IPv4 route entry.
346 */
347 @Test
348 public void testIpv4RouteDelete() {
349 // Firstly add a route
350 testIpv4RouteAdd();
Jonathan Hart41349e92015-02-09 14:14:02 -0800351
352 RouteEntry deleteRouteEntry = new RouteEntry(
353 Ip4Prefix.valueOf("1.1.1.0/24"),
354 Ip4Address.valueOf("192.168.10.1"));
355
356 FibEntry deleteFibEntry = new FibEntry(
357 Ip4Prefix.valueOf("1.1.1.0/24"), null, null);
358
359 reset(fibListener);
360 fibListener.update(Collections.emptyList(), Collections.singletonList(
361 new FibUpdate(FibUpdate.Type.DELETE, deleteFibEntry)));
362
363 replay(fibListener);
364
365 router.processRouteUpdates(Collections.singletonList(
366 new RouteUpdate(RouteUpdate.Type.DELETE, deleteRouteEntry)));
367
368 verify(fibListener);
369 }
370
371 /**
Charles Chand4db3ab2015-09-24 21:14:00 -0700372 * Tests deleting a IPv6 route entry.
Jonathan Hart41349e92015-02-09 14:14:02 -0800373 */
374 @Test
Charles Chand4db3ab2015-09-24 21:14:00 -0700375 public void testIpv6RouteDelete() {
376 // Firstly add a route
377 testIpv6RouteAdd();
378
379 RouteEntry deleteRouteEntry = new RouteEntry(
380 Ip6Prefix.valueOf("4000::/64"),
381 Ip6Address.valueOf("1000::1"));
382
383 FibEntry deleteFibEntry = new FibEntry(
384 Ip6Prefix.valueOf("4000::/64"), null, null);
385
386 reset(fibListener);
387 fibListener.update(Collections.emptyList(), Collections.singletonList(
388 new FibUpdate(FibUpdate.Type.DELETE, deleteFibEntry)));
389
390 replay(fibListener);
391
392 router.processRouteUpdates(Collections.singletonList(
393 new RouteUpdate(RouteUpdate.Type.DELETE, deleteRouteEntry)));
394
395 verify(fibListener);
396 }
397
398 /**
399 * Tests adding a IPv4 route whose next hop is the local BGP speaker.
400 */
401 @Test
402 public void testIpv4LocalRouteAdd() {
Jonathan Hart41349e92015-02-09 14:14:02 -0800403 // Construct a route entry, the next hop is the local BGP speaker
404 RouteEntry routeEntry = new RouteEntry(
405 Ip4Prefix.valueOf("1.1.1.0/24"),
406 Ip4Address.valueOf("0.0.0.0"));
407
408 // No methods on the FIB listener should be called
409 replay(fibListener);
410
Pingping Line28ae4c2015-03-13 11:37:03 -0700411 reset(routingConfigurationService);
412 expect(routingConfigurationService.isIpPrefixLocal(
413 anyObject(IpPrefix.class))).andReturn(true);
414 replay(routingConfigurationService);
415
Jonathan Hart41349e92015-02-09 14:14:02 -0800416 // Call the processRouteUpdates() method in Router class
417 RouteUpdate routeUpdate = new RouteUpdate(RouteUpdate.Type.UPDATE,
418 routeEntry);
419 router.processRouteUpdates(Collections.singletonList(routeUpdate));
420
421 // Verify
422 assertEquals(1, router.getRoutes4().size());
423 assertTrue(router.getRoutes4().contains(routeEntry));
424 verify(fibListener);
425 }
Charles Chand4db3ab2015-09-24 21:14:00 -0700426
427 /**
428 * Tests adding a IPv6 route whose next hop is the local BGP speaker.
429 */
430 @Test
431 public void testIpv6LocalRouteAdd() {
432 // Construct a route entry, the next hop is the local BGP speaker
433 RouteEntry routeEntry = new RouteEntry(
434 Ip6Prefix.valueOf("4000::/64"),
435 Ip6Address.valueOf("::"));
436
437 // No methods on the FIB listener should be called
438 replay(fibListener);
439
440 reset(routingConfigurationService);
441 expect(routingConfigurationService.isIpPrefixLocal(
442 anyObject(IpPrefix.class))).andReturn(true);
443 replay(routingConfigurationService);
444
445 // Call the processRouteUpdates() method in Router class
446 RouteUpdate routeUpdate = new RouteUpdate(RouteUpdate.Type.UPDATE,
447 routeEntry);
448 router.processRouteUpdates(Collections.singletonList(routeUpdate));
449
450 // Verify
451 assertEquals(1, router.getRoutes6().size());
452 assertTrue(router.getRoutes6().contains(routeEntry));
453 verify(fibListener);
454 }
Jonathan Hart41349e92015-02-09 14:14:02 -0800455}