blob: 7bc9473d0ab699b3bf4b0c33a43605057540694f [file] [log] [blame]
Thomas Vachuska781d18b2014-10-27 10:31:25 -07001/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
Pingping3855f312014-10-22 12:50:37 -070019package org.onlab.onos.sdnip;
20
Jonathan Hart31582d12014-10-22 13:52:41 -070021import static org.easymock.EasyMock.anyObject;
Pingping3855f312014-10-22 12:50:37 -070022import static org.easymock.EasyMock.createMock;
23import static org.easymock.EasyMock.expect;
Jonathan Hart31582d12014-10-22 13:52:41 -070024import static org.easymock.EasyMock.expectLastCall;
Pingping3855f312014-10-22 12:50:37 -070025import static org.easymock.EasyMock.replay;
26import static org.easymock.EasyMock.reset;
27import static org.easymock.EasyMock.verify;
28import static org.junit.Assert.assertEquals;
29import static org.junit.Assert.assertTrue;
30
31import java.util.HashMap;
32import java.util.HashSet;
33import java.util.Map;
34import java.util.Set;
35
36import org.junit.Before;
37import org.junit.Test;
Pavlin Radoslavovd26f57a2014-10-23 17:19:45 -070038import org.onlab.junit.TestUtils;
39import org.onlab.junit.TestUtils.TestUtilsException;
Pingping3855f312014-10-22 12:50:37 -070040import org.onlab.onos.ApplicationId;
41import org.onlab.onos.net.ConnectPoint;
42import org.onlab.onos.net.DefaultHost;
43import org.onlab.onos.net.DeviceId;
44import org.onlab.onos.net.Host;
45import org.onlab.onos.net.HostId;
46import org.onlab.onos.net.HostLocation;
47import org.onlab.onos.net.PortNumber;
48import org.onlab.onos.net.flow.DefaultTrafficSelector;
49import org.onlab.onos.net.flow.DefaultTrafficTreatment;
50import org.onlab.onos.net.flow.TrafficSelector;
51import org.onlab.onos.net.flow.TrafficTreatment;
Jonathan Hart31582d12014-10-22 13:52:41 -070052import org.onlab.onos.net.host.HostListener;
Pingping3855f312014-10-22 12:50:37 -070053import org.onlab.onos.net.host.HostService;
Pavlin Radoslavov76b0ae22014-10-27 15:33:19 -070054import org.onlab.onos.net.host.InterfaceIpAddress;
Pingping3855f312014-10-22 12:50:37 -070055import org.onlab.onos.net.intent.IntentService;
56import org.onlab.onos.net.intent.MultiPointToSinglePointIntent;
57import org.onlab.onos.net.provider.ProviderId;
58import org.onlab.onos.sdnip.config.BgpPeer;
59import org.onlab.onos.sdnip.config.Interface;
60import org.onlab.onos.sdnip.config.SdnIpConfigService;
61import org.onlab.packet.Ethernet;
62import org.onlab.packet.IpAddress;
63import org.onlab.packet.IpPrefix;
64import org.onlab.packet.MacAddress;
65import org.onlab.packet.VlanId;
Pingping3855f312014-10-22 12:50:37 -070066
67import com.google.common.collect.Sets;
68
69/**
70 * This class tests adding a route, updating a route, deleting a route,
71 * and adding a route whose next hop is the local BGP speaker.
Pingpingfc584672014-10-23 10:51:19 -070072 * <p/>
73 * ARP module answers the MAC address synchronously.
Pingping3855f312014-10-22 12:50:37 -070074 */
75public class RouterTest {
76
77 private SdnIpConfigService sdnIpConfigService;
78 private InterfaceService interfaceService;
79 private IntentService intentService;
80 private HostService hostService;
81
Jonathan Hart31582d12014-10-22 13:52:41 -070082 private static final ConnectPoint SW1_ETH1 = new ConnectPoint(
83 DeviceId.deviceId("of:0000000000000001"),
84 PortNumber.portNumber(1));
85
86 private static final ConnectPoint SW2_ETH1 = new ConnectPoint(
87 DeviceId.deviceId("of:0000000000000002"),
88 PortNumber.portNumber(1));
89
90 private static final ConnectPoint SW3_ETH1 = new ConnectPoint(
91 DeviceId.deviceId("of:0000000000000003"),
92 PortNumber.portNumber(1));
Pingping3855f312014-10-22 12:50:37 -070093
94 private static final ApplicationId APPID = new ApplicationId() {
95 @Override
96 public short id() {
97 return 1;
98 }
99
100 @Override
101 public String name() {
102 return "SDNIP";
103 }
104 };
105
106 private Router router;
107
108 @Before
109 public void setUp() throws Exception {
Jonathan Hart31582d12014-10-22 13:52:41 -0700110 setUpBgpPeers();
Pingping3855f312014-10-22 12:50:37 -0700111
Jonathan Hart31582d12014-10-22 13:52:41 -0700112 setUpInterfaceService();
113 setUpHostService();
Pingping3855f312014-10-22 12:50:37 -0700114
115 intentService = createMock(IntentService.class);
Pingping3855f312014-10-22 12:50:37 -0700116
117 router = new Router(APPID, intentService,
118 hostService, sdnIpConfigService, interfaceService);
119 }
120
121 /**
122 * Sets up BGP peers in external networks.
Pingping3855f312014-10-22 12:50:37 -0700123 */
Jonathan Hart31582d12014-10-22 13:52:41 -0700124 private void setUpBgpPeers() {
Pingping3855f312014-10-22 12:50:37 -0700125
Jonathan Hart31582d12014-10-22 13:52:41 -0700126 Map<IpAddress, BgpPeer> peers = new HashMap<>();
Pingping3855f312014-10-22 12:50:37 -0700127
128 String peerSw1Eth1 = "192.168.10.1";
Jonathan Hart31582d12014-10-22 13:52:41 -0700129 peers.put(IpAddress.valueOf(peerSw1Eth1),
Pingping3855f312014-10-22 12:50:37 -0700130 new BgpPeer("00:00:00:00:00:00:00:01", 1, peerSw1Eth1));
131
132 // Two BGP peers are connected to switch 2 port 1.
133 String peer1Sw2Eth1 = "192.168.20.1";
Jonathan Hart31582d12014-10-22 13:52:41 -0700134 peers.put(IpAddress.valueOf(peer1Sw2Eth1),
Pingping3855f312014-10-22 12:50:37 -0700135 new BgpPeer("00:00:00:00:00:00:00:02", 1, peer1Sw2Eth1));
136
137 String peer2Sw2Eth1 = "192.168.20.2";
Jonathan Hart31582d12014-10-22 13:52:41 -0700138 peers.put(IpAddress.valueOf(peer2Sw2Eth1),
Pingping3855f312014-10-22 12:50:37 -0700139 new BgpPeer("00:00:00:00:00:00:00:02", 1, peer2Sw2Eth1));
140
Jonathan Hart31582d12014-10-22 13:52:41 -0700141 sdnIpConfigService = createMock(SdnIpConfigService.class);
142 expect(sdnIpConfigService.getBgpPeers()).andReturn(peers).anyTimes();
143 replay(sdnIpConfigService);
144
Pingping3855f312014-10-22 12:50:37 -0700145 }
146
147 /**
148 * Sets up logical interfaces, which emulate the configured interfaces
149 * in SDN-IP application.
Pingping3855f312014-10-22 12:50:37 -0700150 */
Jonathan Hart31582d12014-10-22 13:52:41 -0700151 private void setUpInterfaceService() {
152 interfaceService = createMock(InterfaceService.class);
Pingping3855f312014-10-22 12:50:37 -0700153
Jonathan Hart31582d12014-10-22 13:52:41 -0700154 Set<Interface> interfaces = Sets.newHashSet();
Pingping3855f312014-10-22 12:50:37 -0700155
Pavlin Radoslavov76b0ae22014-10-27 15:33:19 -0700156 InterfaceIpAddress ia1 =
157 new InterfaceIpAddress(IpAddress.valueOf("192.168.10.101"),
158 IpPrefix.valueOf("192.168.10.0/24"));
Jonathan Hart31582d12014-10-22 13:52:41 -0700159 Interface sw1Eth1 = new Interface(SW1_ETH1,
Pavlin Radoslavov76b0ae22014-10-27 15:33:19 -0700160 Sets.newHashSet(ia1),
Jonathan Hart31582d12014-10-22 13:52:41 -0700161 MacAddress.valueOf("00:00:00:00:00:01"));
Pingping3855f312014-10-22 12:50:37 -0700162
Jonathan Hart31582d12014-10-22 13:52:41 -0700163 expect(interfaceService.getInterface(SW1_ETH1)).andReturn(sw1Eth1).anyTimes();
164 interfaces.add(sw1Eth1);
Pingping3855f312014-10-22 12:50:37 -0700165
Pavlin Radoslavov76b0ae22014-10-27 15:33:19 -0700166 InterfaceIpAddress ia2 =
167 new InterfaceIpAddress(IpAddress.valueOf("192.168.20.101"),
168 IpPrefix.valueOf("192.168.20.0/24"));
Jonathan Hart31582d12014-10-22 13:52:41 -0700169 Interface sw2Eth1 = new Interface(SW2_ETH1,
Pavlin Radoslavov76b0ae22014-10-27 15:33:19 -0700170 Sets.newHashSet(ia2),
Jonathan Hart31582d12014-10-22 13:52:41 -0700171 MacAddress.valueOf("00:00:00:00:00:02"));
Pingping3855f312014-10-22 12:50:37 -0700172
Jonathan Hart31582d12014-10-22 13:52:41 -0700173 expect(interfaceService.getInterface(SW2_ETH1)).andReturn(sw2Eth1).anyTimes();
174 interfaces.add(sw2Eth1);
175
Pavlin Radoslavov76b0ae22014-10-27 15:33:19 -0700176 InterfaceIpAddress ia3 =
177 new InterfaceIpAddress(IpAddress.valueOf("192.168.30.101"),
178 IpPrefix.valueOf("192.168.30.0/24"));
Jonathan Hart31582d12014-10-22 13:52:41 -0700179 Interface sw3Eth1 = new Interface(SW3_ETH1,
Pavlin Radoslavov76b0ae22014-10-27 15:33:19 -0700180 Sets.newHashSet(ia3),
Jonathan Hart31582d12014-10-22 13:52:41 -0700181 MacAddress.valueOf("00:00:00:00:00:03"));
182
183 expect(interfaceService.getInterface(SW3_ETH1)).andReturn(sw3Eth1).anyTimes();
184 interfaces.add(sw3Eth1);
185
186 expect(interfaceService.getInterfaces()).andReturn(interfaces).anyTimes();
187
188 replay(interfaceService);
189 }
190
191 /**
192 * Sets up the host service with details of some hosts.
193 */
194 private void setUpHostService() {
195 hostService = createMock(HostService.class);
196
197 hostService.addListener(anyObject(HostListener.class));
198 expectLastCall().anyTimes();
199
Pavlin Radoslavov33f228a2014-10-27 19:33:16 -0700200 IpAddress host1Address = IpAddress.valueOf("192.168.10.1");
Jonathan Hart31582d12014-10-22 13:52:41 -0700201 Host host1 = new DefaultHost(ProviderId.NONE, HostId.NONE,
202 MacAddress.valueOf("00:00:00:00:00:01"), VlanId.NONE,
203 new HostLocation(SW1_ETH1, 1),
Pavlin Radoslavov33f228a2014-10-27 19:33:16 -0700204 Sets.newHashSet(host1Address));
Jonathan Hart31582d12014-10-22 13:52:41 -0700205
206 expect(hostService.getHostsByIp(host1Address))
207 .andReturn(Sets.newHashSet(host1)).anyTimes();
Pavlin Radoslavov33f228a2014-10-27 19:33:16 -0700208 hostService.startMonitoringIp(host1Address);
Jonathan Hart31582d12014-10-22 13:52:41 -0700209 expectLastCall().anyTimes();
210
211
Pavlin Radoslavov33f228a2014-10-27 19:33:16 -0700212 IpAddress host2Address = IpAddress.valueOf("192.168.20.1");
Jonathan Hart31582d12014-10-22 13:52:41 -0700213 Host host2 = new DefaultHost(ProviderId.NONE, HostId.NONE,
214 MacAddress.valueOf("00:00:00:00:00:02"), VlanId.NONE,
215 new HostLocation(SW2_ETH1, 1),
Pavlin Radoslavov33f228a2014-10-27 19:33:16 -0700216 Sets.newHashSet(host2Address));
Jonathan Hart31582d12014-10-22 13:52:41 -0700217
218 expect(hostService.getHostsByIp(host2Address))
219 .andReturn(Sets.newHashSet(host2)).anyTimes();
Pavlin Radoslavov33f228a2014-10-27 19:33:16 -0700220 hostService.startMonitoringIp(host2Address);
Jonathan Hart31582d12014-10-22 13:52:41 -0700221 expectLastCall().anyTimes();
222
223
224 replay(hostService);
Pingping3855f312014-10-22 12:50:37 -0700225 }
226
227 /**
228 * This method tests adding a route entry.
229 */
230 @Test
231 public void testProcessRouteAdd() throws TestUtilsException {
Pingping3855f312014-10-22 12:50:37 -0700232 // Construct a route entry
233 RouteEntry routeEntry = new RouteEntry(
234 IpPrefix.valueOf("1.1.1.0/24"),
235 IpAddress.valueOf("192.168.10.1"));
236
237 // Construct a MultiPointToSinglePointIntent intent
238 TrafficSelector.Builder selectorBuilder =
239 DefaultTrafficSelector.builder();
240 selectorBuilder.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(
241 routeEntry.prefix());
242
243 TrafficTreatment.Builder treatmentBuilder =
244 DefaultTrafficTreatment.builder();
245 treatmentBuilder.setEthDst(MacAddress.valueOf("00:00:00:00:00:01"));
246
247 Set<ConnectPoint> ingressPoints = new HashSet<ConnectPoint>();
Jonathan Hart31582d12014-10-22 13:52:41 -0700248 ingressPoints.add(SW2_ETH1);
249 ingressPoints.add(SW3_ETH1);
Pingping3855f312014-10-22 12:50:37 -0700250
251 MultiPointToSinglePointIntent intent =
252 new MultiPointToSinglePointIntent(APPID,
253 selectorBuilder.build(), treatmentBuilder.build(),
Jonathan Hart31582d12014-10-22 13:52:41 -0700254 ingressPoints, SW1_ETH1);
Pingping3855f312014-10-22 12:50:37 -0700255
256 // Set up test expectation
257 reset(intentService);
258 intentService.submit(intent);
259 replay(intentService);
260
261 // Call the processRouteAdd() method in Router class
262 router.leaderChanged(true);
263 TestUtils.setField(router, "isActivatedLeader", true);
264 router.processRouteAdd(routeEntry);
265
266 // Verify
267 assertEquals(router.getRoutes().size(), 1);
268 assertTrue(router.getRoutes().contains(routeEntry));
269 assertEquals(router.getPushedRouteIntents().size(), 1);
270 assertEquals(router.getPushedRouteIntents().iterator().next(),
271 intent);
272 verify(intentService);
273 }
274
275 /**
276 * This method tests updating a route entry.
277 *
278 * @throws TestUtilsException
279 */
280 @Test
281 public void testRouteUpdate() throws TestUtilsException {
Pingping3855f312014-10-22 12:50:37 -0700282 // Firstly add a route
283 testProcessRouteAdd();
284
285 // Construct the existing route entry
286 RouteEntry routeEntry = new RouteEntry(
287 IpPrefix.valueOf("1.1.1.0/24"),
288 IpAddress.valueOf("192.168.10.1"));
289
290 // Construct the existing MultiPointToSinglePointIntent intent
291 TrafficSelector.Builder selectorBuilder =
292 DefaultTrafficSelector.builder();
293 selectorBuilder.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(
294 routeEntry.prefix());
295
296 TrafficTreatment.Builder treatmentBuilder =
297 DefaultTrafficTreatment.builder();
298 treatmentBuilder.setEthDst(MacAddress.valueOf("00:00:00:00:00:01"));
299
Pingping3855f312014-10-22 12:50:37 -0700300 Set<ConnectPoint> ingressPoints = new HashSet<ConnectPoint>();
Jonathan Hart31582d12014-10-22 13:52:41 -0700301 ingressPoints.add(SW2_ETH1);
302 ingressPoints.add(SW3_ETH1);
Pingping3855f312014-10-22 12:50:37 -0700303
304 MultiPointToSinglePointIntent intent =
305 new MultiPointToSinglePointIntent(APPID,
306 selectorBuilder.build(), treatmentBuilder.build(),
Jonathan Hart31582d12014-10-22 13:52:41 -0700307 ingressPoints, SW1_ETH1);
Pingping3855f312014-10-22 12:50:37 -0700308
309 // Start to construct a new route entry and new intent
310 RouteEntry routeEntryUpdate = new RouteEntry(
311 IpPrefix.valueOf("1.1.1.0/24"),
312 IpAddress.valueOf("192.168.20.1"));
313
314 // Construct a new MultiPointToSinglePointIntent intent
315 TrafficSelector.Builder selectorBuilderNew =
316 DefaultTrafficSelector.builder();
317 selectorBuilderNew.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(
318 routeEntryUpdate.prefix());
319
320 TrafficTreatment.Builder treatmentBuilderNew =
321 DefaultTrafficTreatment.builder();
322 treatmentBuilderNew.setEthDst(MacAddress.valueOf("00:00:00:00:00:02"));
323
Pingping3855f312014-10-22 12:50:37 -0700324
325 Set<ConnectPoint> ingressPointsNew = new HashSet<ConnectPoint>();
Jonathan Hart31582d12014-10-22 13:52:41 -0700326 ingressPointsNew.add(SW1_ETH1);
327 ingressPointsNew.add(SW3_ETH1);
Pingping3855f312014-10-22 12:50:37 -0700328
329 MultiPointToSinglePointIntent intentNew =
330 new MultiPointToSinglePointIntent(APPID,
331 selectorBuilderNew.build(),
332 treatmentBuilderNew.build(),
Jonathan Hart31582d12014-10-22 13:52:41 -0700333 ingressPointsNew, SW2_ETH1);
Pingping3855f312014-10-22 12:50:37 -0700334
335 // Set up test expectation
336 reset(intentService);
337 intentService.withdraw(intent);
338 intentService.submit(intentNew);
339 replay(intentService);
340
341 // Call the processRouteAdd() method in Router class
342 router.leaderChanged(true);
343 TestUtils.setField(router, "isActivatedLeader", true);
344 router.processRouteAdd(routeEntryUpdate);
345
346 // Verify
347 assertEquals(router.getRoutes().size(), 1);
348 assertTrue(router.getRoutes().contains(routeEntryUpdate));
349 assertEquals(router.getPushedRouteIntents().size(), 1);
350 assertEquals(router.getPushedRouteIntents().iterator().next(),
351 intentNew);
352 verify(intentService);
353 }
354
355 /**
356 * This method tests deleting a route entry.
357 */
358 @Test
359 public void testProcessRouteDelete() throws TestUtilsException {
Pingping3855f312014-10-22 12:50:37 -0700360 // Firstly add a route
361 testProcessRouteAdd();
362
363 // Construct the existing route entry
364 RouteEntry routeEntry = new RouteEntry(
365 IpPrefix.valueOf("1.1.1.0/24"),
366 IpAddress.valueOf("192.168.10.1"));
367
368 // Construct the existing MultiPointToSinglePointIntent intent
369 TrafficSelector.Builder selectorBuilder =
370 DefaultTrafficSelector.builder();
371 selectorBuilder.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(
372 routeEntry.prefix());
373
374 TrafficTreatment.Builder treatmentBuilder =
375 DefaultTrafficTreatment.builder();
376 treatmentBuilder.setEthDst(MacAddress.valueOf("00:00:00:00:00:01"));
377
Pingping3855f312014-10-22 12:50:37 -0700378 Set<ConnectPoint> ingressPoints = new HashSet<ConnectPoint>();
Jonathan Hart31582d12014-10-22 13:52:41 -0700379 ingressPoints.add(SW2_ETH1);
380 ingressPoints.add(SW3_ETH1);
Pingping3855f312014-10-22 12:50:37 -0700381
382 MultiPointToSinglePointIntent intent =
383 new MultiPointToSinglePointIntent(APPID,
384 selectorBuilder.build(), treatmentBuilder.build(),
Jonathan Hart31582d12014-10-22 13:52:41 -0700385 ingressPoints, SW1_ETH1);
Pingping3855f312014-10-22 12:50:37 -0700386
387 // Set up expectation
388 reset(intentService);
389 intentService.withdraw(intent);
390 replay(intentService);
391
392 // Call route deleting method in Router class
393 router.leaderChanged(true);
394 TestUtils.setField(router, "isActivatedLeader", true);
395 router.processRouteDelete(routeEntry);
396
397 // Verify
398 assertEquals(router.getRoutes().size(), 0);
399 assertEquals(router.getPushedRouteIntents().size(), 0);
400 verify(intentService);
401 }
402
403 /**
404 * This method tests when the next hop of a route is the local BGP speaker.
405 *
406 * @throws TestUtilsException
407 */
408 @Test
409 public void testLocalRouteAdd() throws TestUtilsException {
Pingping3855f312014-10-22 12:50:37 -0700410 // Construct a route entry, the next hop is the local BGP speaker
411 RouteEntry routeEntry = new RouteEntry(
412 IpPrefix.valueOf("1.1.1.0/24"), IpAddress.valueOf("0.0.0.0"));
413
414 // Reset intentService to check whether the submit method is called
415 reset(intentService);
416 replay(intentService);
417
418 // Call the processRouteAdd() method in Router class
419 router.leaderChanged(true);
420 TestUtils.setField(router, "isActivatedLeader", true);
421 router.processRouteAdd(routeEntry);
422
423 // Verify
424 assertEquals(router.getRoutes().size(), 1);
425 assertTrue(router.getRoutes().contains(routeEntry));
426 assertEquals(router.getPushedRouteIntents().size(), 0);
427 verify(intentService);
428 }
429}