blob: 9ab59168b55885edbefeee62db8e151ba47d4945 [file] [log] [blame]
Pingping3855f312014-10-22 12:50:37 -07001package org.onlab.onos.sdnip;
2
3import static org.easymock.EasyMock.createMock;
4import static org.easymock.EasyMock.expect;
5import static org.easymock.EasyMock.replay;
6import static org.easymock.EasyMock.reset;
7import static org.easymock.EasyMock.verify;
8import static org.junit.Assert.assertEquals;
9import static org.junit.Assert.assertTrue;
10
11import java.util.HashMap;
12import java.util.HashSet;
13import java.util.Map;
14import java.util.Set;
15
16import org.junit.Before;
17import org.junit.Test;
18import org.onlab.onos.ApplicationId;
19import org.onlab.onos.net.ConnectPoint;
20import org.onlab.onos.net.DefaultHost;
21import org.onlab.onos.net.DeviceId;
22import org.onlab.onos.net.Host;
23import org.onlab.onos.net.HostId;
24import org.onlab.onos.net.HostLocation;
25import org.onlab.onos.net.PortNumber;
26import org.onlab.onos.net.flow.DefaultTrafficSelector;
27import org.onlab.onos.net.flow.DefaultTrafficTreatment;
28import org.onlab.onos.net.flow.TrafficSelector;
29import org.onlab.onos.net.flow.TrafficTreatment;
30import org.onlab.onos.net.host.HostService;
31import org.onlab.onos.net.intent.IntentService;
32import org.onlab.onos.net.intent.MultiPointToSinglePointIntent;
33import org.onlab.onos.net.provider.ProviderId;
34import org.onlab.onos.sdnip.config.BgpPeer;
35import org.onlab.onos.sdnip.config.Interface;
36import org.onlab.onos.sdnip.config.SdnIpConfigService;
37import org.onlab.packet.Ethernet;
38import org.onlab.packet.IpAddress;
39import org.onlab.packet.IpPrefix;
40import org.onlab.packet.MacAddress;
41import org.onlab.packet.VlanId;
42import org.onlab.util.TestUtils;
43import org.onlab.util.TestUtils.TestUtilsException;
44
45import com.google.common.collect.Sets;
46
47/**
48 * This class tests adding a route, updating a route, deleting a route,
49 * and adding a route whose next hop is the local BGP speaker.
50 */
51public class RouterTest {
52
53 private SdnIpConfigService sdnIpConfigService;
54 private InterfaceService interfaceService;
55 private IntentService intentService;
56 private HostService hostService;
57
58 private Map<IpAddress, BgpPeer> bgpPeers;
59 private Map<IpAddress, BgpPeer> configuredPeers;
60 private Set<Interface> interfaces;
61 private Set<Interface> configuredInterfaces;
62
63 private static final ApplicationId APPID = new ApplicationId() {
64 @Override
65 public short id() {
66 return 1;
67 }
68
69 @Override
70 public String name() {
71 return "SDNIP";
72 }
73 };
74
75 private Router router;
76
77 @Before
78 public void setUp() throws Exception {
79 bgpPeers = setUpBgpPeers();
80 interfaces = setUpInterfaces();
81 initRouter();
82 }
83
84 /**
85 * Initializes Router class.
86 */
87 private void initRouter() {
88
89 intentService = createMock(IntentService.class);
90 hostService = createMock(HostService.class);
91
92 interfaceService = createMock(InterfaceService.class);
93 expect(interfaceService.getInterfaces()).andReturn(
94 interfaces).anyTimes();
95
96 Set<IpPrefix> ipAddressesOnSw1Eth1 = new HashSet<IpPrefix>();
97 ipAddressesOnSw1Eth1.add(IpPrefix.valueOf("192.168.10.0/24"));
98 Interface expectedInterface =
99 new Interface(new ConnectPoint(
100 DeviceId.deviceId("of:0000000000000001"),
101 PortNumber.portNumber("1")),
102 ipAddressesOnSw1Eth1,
103 MacAddress.valueOf("00:00:00:00:00:01"));
104 ConnectPoint egressPoint = new ConnectPoint(
105 DeviceId.deviceId("of:0000000000000001"),
106 PortNumber.portNumber(1));
107 expect(interfaceService.getInterface(egressPoint)).andReturn(
108 expectedInterface).anyTimes();
109
110 Set<IpPrefix> ipAddressesOnSw2Eth1 = new HashSet<IpPrefix>();
111 ipAddressesOnSw2Eth1.add(IpPrefix.valueOf("192.168.20.0/24"));
112 Interface expectedInterfaceNew =
113 new Interface(new ConnectPoint(
114 DeviceId.deviceId("of:0000000000000002"),
115 PortNumber.portNumber("1")),
116 ipAddressesOnSw2Eth1,
117 MacAddress.valueOf("00:00:00:00:00:02"));
118 ConnectPoint egressPointNew = new ConnectPoint(
119 DeviceId.deviceId("of:0000000000000002"),
120 PortNumber.portNumber(1));
121 expect(interfaceService.getInterface(egressPointNew)).andReturn(
122 expectedInterfaceNew).anyTimes();
123 replay(interfaceService);
124
125 sdnIpConfigService = createMock(SdnIpConfigService.class);
126 expect(sdnIpConfigService.getBgpPeers()).andReturn(bgpPeers).anyTimes();
127 replay(sdnIpConfigService);
128
129 router = new Router(APPID, intentService,
130 hostService, sdnIpConfigService, interfaceService);
131 }
132
133 /**
134 * Sets up BGP peers in external networks.
135 *
136 * @return configured BGP peers as a Map from peer IP address to BgpPeer
137 */
138 private Map<IpAddress, BgpPeer> setUpBgpPeers() {
139
140 configuredPeers = new HashMap<>();
141
142 String peerSw1Eth1 = "192.168.10.1";
143 configuredPeers.put(IpAddress.valueOf(peerSw1Eth1),
144 new BgpPeer("00:00:00:00:00:00:00:01", 1, peerSw1Eth1));
145
146 // Two BGP peers are connected to switch 2 port 1.
147 String peer1Sw2Eth1 = "192.168.20.1";
148 configuredPeers.put(IpAddress.valueOf(peer1Sw2Eth1),
149 new BgpPeer("00:00:00:00:00:00:00:02", 1, peer1Sw2Eth1));
150
151 String peer2Sw2Eth1 = "192.168.20.2";
152 configuredPeers.put(IpAddress.valueOf(peer2Sw2Eth1),
153 new BgpPeer("00:00:00:00:00:00:00:02", 1, peer2Sw2Eth1));
154
155 return configuredPeers;
156 }
157
158 /**
159 * Sets up logical interfaces, which emulate the configured interfaces
160 * in SDN-IP application.
161 *
162 * @return configured interfaces as a Set
163 */
164 private Set<Interface> setUpInterfaces() {
165
166 configuredInterfaces = Sets.newHashSet();
167
168 Set<IpPrefix> ipAddressesOnSw1Eth1 = new HashSet<IpPrefix>();
169 ipAddressesOnSw1Eth1.add(IpPrefix.valueOf("192.168.10.0/24"));
170 configuredInterfaces.add(
171 new Interface(new ConnectPoint(
172 DeviceId.deviceId("of:0000000000000001"),
173 PortNumber.portNumber(1)),
174 ipAddressesOnSw1Eth1,
175 MacAddress.valueOf("00:00:00:00:00:01")));
176
177 Set<IpPrefix> ipAddressesOnSw2Eth1 = new HashSet<IpPrefix>();
178 ipAddressesOnSw2Eth1.add(IpPrefix.valueOf("192.168.20.0/24"));
179 configuredInterfaces.add(
180 new Interface(new ConnectPoint(
181 DeviceId.deviceId("of:0000000000000002"),
182 PortNumber.portNumber(1)),
183 ipAddressesOnSw2Eth1,
184 MacAddress.valueOf("00:00:00:00:00:02")));
185
186 Set<IpPrefix> ipAddressesOnSw3Eth1 = new HashSet<IpPrefix>();
187 ipAddressesOnSw3Eth1.add(IpPrefix.valueOf("192.168.30.0/24"));
188 configuredInterfaces.add(
189 new Interface(new ConnectPoint(
190 DeviceId.deviceId("of:0000000000000003"),
191 PortNumber.portNumber(1)),
192 ipAddressesOnSw3Eth1,
193 MacAddress.valueOf("00:00:00:00:00:03")));
194
195 return configuredInterfaces;
196 }
197
198 /**
199 * This method tests adding a route entry.
200 */
201 @Test
202 public void testProcessRouteAdd() throws TestUtilsException {
203
204 // Construct a route entry
205 RouteEntry routeEntry = new RouteEntry(
206 IpPrefix.valueOf("1.1.1.0/24"),
207 IpAddress.valueOf("192.168.10.1"));
208
209 // Construct a MultiPointToSinglePointIntent intent
210 TrafficSelector.Builder selectorBuilder =
211 DefaultTrafficSelector.builder();
212 selectorBuilder.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(
213 routeEntry.prefix());
214
215 TrafficTreatment.Builder treatmentBuilder =
216 DefaultTrafficTreatment.builder();
217 treatmentBuilder.setEthDst(MacAddress.valueOf("00:00:00:00:00:01"));
218
219 Set<ConnectPoint> ingressPoints = new HashSet<ConnectPoint>();
220 ingressPoints.add(new ConnectPoint(
221 DeviceId.deviceId("of:0000000000000002"),
222 PortNumber.portNumber("1")));
223 ingressPoints.add(new ConnectPoint(
224 DeviceId.deviceId("of:0000000000000003"),
225 PortNumber.portNumber("1")));
226
227 ConnectPoint egressPoint = new ConnectPoint(
228 DeviceId.deviceId("of:0000000000000001"),
229 PortNumber.portNumber("1"));
230
231 MultiPointToSinglePointIntent intent =
232 new MultiPointToSinglePointIntent(APPID,
233 selectorBuilder.build(), treatmentBuilder.build(),
234 ingressPoints, egressPoint);
235
236 // Reset host service
237 reset(hostService);
238 Set<Host> hosts = new HashSet<Host>(1);
239 Set<IpPrefix> ipPrefixes = new HashSet<IpPrefix>();
240 ipPrefixes.add(IpPrefix.valueOf("192.168.10.1/32"));
241 hosts.add(new DefaultHost(ProviderId.NONE, HostId.NONE,
242 MacAddress.valueOf("00:00:00:00:00:01"), VlanId.NONE,
243 new HostLocation(
244 DeviceId.deviceId("of:0000000000000001"),
245 PortNumber.portNumber(1), 1),
246 ipPrefixes));
247 expect(hostService.getHostsByIp(
248 IpPrefix.valueOf("192.168.10.1/32"))).andReturn(hosts);
249 replay(hostService);
250
251 // Set up test expectation
252 reset(intentService);
253 intentService.submit(intent);
254 replay(intentService);
255
256 // Call the processRouteAdd() method in Router class
257 router.leaderChanged(true);
258 TestUtils.setField(router, "isActivatedLeader", true);
259 router.processRouteAdd(routeEntry);
260
261 // Verify
262 assertEquals(router.getRoutes().size(), 1);
263 assertTrue(router.getRoutes().contains(routeEntry));
264 assertEquals(router.getPushedRouteIntents().size(), 1);
265 assertEquals(router.getPushedRouteIntents().iterator().next(),
266 intent);
267 verify(intentService);
268 }
269
270 /**
271 * This method tests updating a route entry.
272 *
273 * @throws TestUtilsException
274 */
275 @Test
276 public void testRouteUpdate() throws TestUtilsException {
277
278 // Firstly add a route
279 testProcessRouteAdd();
280
281 // Construct the existing route entry
282 RouteEntry routeEntry = new RouteEntry(
283 IpPrefix.valueOf("1.1.1.0/24"),
284 IpAddress.valueOf("192.168.10.1"));
285
286 // Construct the existing MultiPointToSinglePointIntent intent
287 TrafficSelector.Builder selectorBuilder =
288 DefaultTrafficSelector.builder();
289 selectorBuilder.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(
290 routeEntry.prefix());
291
292 TrafficTreatment.Builder treatmentBuilder =
293 DefaultTrafficTreatment.builder();
294 treatmentBuilder.setEthDst(MacAddress.valueOf("00:00:00:00:00:01"));
295
296 ConnectPoint egressPoint = new ConnectPoint(
297 DeviceId.deviceId("of:0000000000000001"),
298 PortNumber.portNumber("1"));
299
300 Set<ConnectPoint> ingressPoints = new HashSet<ConnectPoint>();
301 ingressPoints.add(new ConnectPoint(
302 DeviceId.deviceId("of:0000000000000002"),
303 PortNumber.portNumber("1")));
304 ingressPoints.add(new ConnectPoint(
305 DeviceId.deviceId("of:0000000000000003"),
306 PortNumber.portNumber("1")));
307
308 MultiPointToSinglePointIntent intent =
309 new MultiPointToSinglePointIntent(APPID,
310 selectorBuilder.build(), treatmentBuilder.build(),
311 ingressPoints, egressPoint);
312
313 // Start to construct a new route entry and new intent
314 RouteEntry routeEntryUpdate = new RouteEntry(
315 IpPrefix.valueOf("1.1.1.0/24"),
316 IpAddress.valueOf("192.168.20.1"));
317
318 // Construct a new MultiPointToSinglePointIntent intent
319 TrafficSelector.Builder selectorBuilderNew =
320 DefaultTrafficSelector.builder();
321 selectorBuilderNew.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(
322 routeEntryUpdate.prefix());
323
324 TrafficTreatment.Builder treatmentBuilderNew =
325 DefaultTrafficTreatment.builder();
326 treatmentBuilderNew.setEthDst(MacAddress.valueOf("00:00:00:00:00:02"));
327
328 ConnectPoint egressPointNew = new ConnectPoint(
329 DeviceId.deviceId("of:0000000000000002"),
330 PortNumber.portNumber("1"));
331
332 Set<ConnectPoint> ingressPointsNew = new HashSet<ConnectPoint>();
333 ingressPointsNew.add(new ConnectPoint(
334 DeviceId.deviceId("of:0000000000000001"),
335 PortNumber.portNumber("1")));
336 ingressPointsNew.add(new ConnectPoint(
337 DeviceId.deviceId("of:0000000000000003"),
338 PortNumber.portNumber("1")));
339
340 MultiPointToSinglePointIntent intentNew =
341 new MultiPointToSinglePointIntent(APPID,
342 selectorBuilderNew.build(),
343 treatmentBuilderNew.build(),
344 ingressPointsNew, egressPointNew);
345
346 // Reset host service
347 reset(hostService);
348 Set<Host> hosts = new HashSet<Host>(1);
349 Set<IpPrefix> ipPrefixes = new HashSet<IpPrefix>();
350 ipPrefixes.add(IpPrefix.valueOf("192.168.20.1/32"));
351 hosts.add(new DefaultHost(ProviderId.NONE, HostId.NONE,
352 MacAddress.valueOf("00:00:00:00:00:02"), VlanId.NONE,
353 new HostLocation(
354 DeviceId.deviceId("of:0000000000000002"),
355 PortNumber.portNumber(1), 1),
356 ipPrefixes));
357 expect(hostService.getHostsByIp(
358 IpPrefix.valueOf("192.168.20.1/32"))).andReturn(hosts);
359 replay(hostService);
360
361 // Set up test expectation
362 reset(intentService);
363 intentService.withdraw(intent);
364 intentService.submit(intentNew);
365 replay(intentService);
366
367 // Call the processRouteAdd() method in Router class
368 router.leaderChanged(true);
369 TestUtils.setField(router, "isActivatedLeader", true);
370 router.processRouteAdd(routeEntryUpdate);
371
372 // Verify
373 assertEquals(router.getRoutes().size(), 1);
374 assertTrue(router.getRoutes().contains(routeEntryUpdate));
375 assertEquals(router.getPushedRouteIntents().size(), 1);
376 assertEquals(router.getPushedRouteIntents().iterator().next(),
377 intentNew);
378 verify(intentService);
379 }
380
381 /**
382 * This method tests deleting a route entry.
383 */
384 @Test
385 public void testProcessRouteDelete() throws TestUtilsException {
386
387 // Firstly add a route
388 testProcessRouteAdd();
389
390 // Construct the existing route entry
391 RouteEntry routeEntry = new RouteEntry(
392 IpPrefix.valueOf("1.1.1.0/24"),
393 IpAddress.valueOf("192.168.10.1"));
394
395 // Construct the existing MultiPointToSinglePointIntent intent
396 TrafficSelector.Builder selectorBuilder =
397 DefaultTrafficSelector.builder();
398 selectorBuilder.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(
399 routeEntry.prefix());
400
401 TrafficTreatment.Builder treatmentBuilder =
402 DefaultTrafficTreatment.builder();
403 treatmentBuilder.setEthDst(MacAddress.valueOf("00:00:00:00:00:01"));
404
405 ConnectPoint egressPoint = new ConnectPoint(
406 DeviceId.deviceId("of:0000000000000001"),
407 PortNumber.portNumber("1"));
408
409 Set<ConnectPoint> ingressPoints = new HashSet<ConnectPoint>();
410 ingressPoints.add(new ConnectPoint(
411 DeviceId.deviceId("of:0000000000000002"),
412 PortNumber.portNumber("1")));
413 ingressPoints.add(new ConnectPoint(
414 DeviceId.deviceId("of:0000000000000003"),
415 PortNumber.portNumber("1")));
416
417 MultiPointToSinglePointIntent intent =
418 new MultiPointToSinglePointIntent(APPID,
419 selectorBuilder.build(), treatmentBuilder.build(),
420 ingressPoints, egressPoint);
421
422 // Set up expectation
423 reset(intentService);
424 intentService.withdraw(intent);
425 replay(intentService);
426
427 // Call route deleting method in Router class
428 router.leaderChanged(true);
429 TestUtils.setField(router, "isActivatedLeader", true);
430 router.processRouteDelete(routeEntry);
431
432 // Verify
433 assertEquals(router.getRoutes().size(), 0);
434 assertEquals(router.getPushedRouteIntents().size(), 0);
435 verify(intentService);
436 }
437
438 /**
439 * This method tests when the next hop of a route is the local BGP speaker.
440 *
441 * @throws TestUtilsException
442 */
443 @Test
444 public void testLocalRouteAdd() throws TestUtilsException {
445
446 // Construct a route entry, the next hop is the local BGP speaker
447 RouteEntry routeEntry = new RouteEntry(
448 IpPrefix.valueOf("1.1.1.0/24"), IpAddress.valueOf("0.0.0.0"));
449
450 // Reset intentService to check whether the submit method is called
451 reset(intentService);
452 replay(intentService);
453
454 // Call the processRouteAdd() method in Router class
455 router.leaderChanged(true);
456 TestUtils.setField(router, "isActivatedLeader", true);
457 router.processRouteAdd(routeEntry);
458
459 // Verify
460 assertEquals(router.getRoutes().size(), 1);
461 assertTrue(router.getRoutes().contains(routeEntry));
462 assertEquals(router.getPushedRouteIntents().size(), 0);
463 verify(intentService);
464 }
465}