blob: 6d77a2ca8d36bdebba927a99945d0525a3ca35a1 [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.
72 */
73public class RouterTest {
74
75 private SdnIpConfigService sdnIpConfigService;
76 private InterfaceService interfaceService;
77 private IntentService intentService;
78 private HostService hostService;
79
Jonathan Hart31582d12014-10-22 13:52:41 -070080 private static final ConnectPoint SW1_ETH1 = new ConnectPoint(
81 DeviceId.deviceId("of:0000000000000001"),
82 PortNumber.portNumber(1));
83
84 private static final ConnectPoint SW2_ETH1 = new ConnectPoint(
85 DeviceId.deviceId("of:0000000000000002"),
86 PortNumber.portNumber(1));
87
88 private static final ConnectPoint SW3_ETH1 = new ConnectPoint(
89 DeviceId.deviceId("of:0000000000000003"),
90 PortNumber.portNumber(1));
Pingping3855f312014-10-22 12:50:37 -070091
92 private static final ApplicationId APPID = new ApplicationId() {
93 @Override
94 public short id() {
95 return 1;
96 }
97
98 @Override
99 public String name() {
100 return "SDNIP";
101 }
102 };
103
104 private Router router;
105
106 @Before
107 public void setUp() throws Exception {
Jonathan Hart31582d12014-10-22 13:52:41 -0700108 setUpBgpPeers();
Pingping3855f312014-10-22 12:50:37 -0700109
Jonathan Hart31582d12014-10-22 13:52:41 -0700110 setUpInterfaceService();
111 setUpHostService();
Pingping3855f312014-10-22 12:50:37 -0700112
113 intentService = createMock(IntentService.class);
Pingping3855f312014-10-22 12:50:37 -0700114
115 router = new Router(APPID, intentService,
116 hostService, sdnIpConfigService, interfaceService);
117 }
118
119 /**
120 * Sets up BGP peers in external networks.
Pingping3855f312014-10-22 12:50:37 -0700121 */
Jonathan Hart31582d12014-10-22 13:52:41 -0700122 private void setUpBgpPeers() {
Pingping3855f312014-10-22 12:50:37 -0700123
Jonathan Hart31582d12014-10-22 13:52:41 -0700124 Map<IpAddress, BgpPeer> peers = new HashMap<>();
Pingping3855f312014-10-22 12:50:37 -0700125
126 String peerSw1Eth1 = "192.168.10.1";
Jonathan Hart31582d12014-10-22 13:52:41 -0700127 peers.put(IpAddress.valueOf(peerSw1Eth1),
Pingping3855f312014-10-22 12:50:37 -0700128 new BgpPeer("00:00:00:00:00:00:00:01", 1, peerSw1Eth1));
129
130 // Two BGP peers are connected to switch 2 port 1.
131 String peer1Sw2Eth1 = "192.168.20.1";
Jonathan Hart31582d12014-10-22 13:52:41 -0700132 peers.put(IpAddress.valueOf(peer1Sw2Eth1),
Pingping3855f312014-10-22 12:50:37 -0700133 new BgpPeer("00:00:00:00:00:00:00:02", 1, peer1Sw2Eth1));
134
135 String peer2Sw2Eth1 = "192.168.20.2";
Jonathan Hart31582d12014-10-22 13:52:41 -0700136 peers.put(IpAddress.valueOf(peer2Sw2Eth1),
Pingping3855f312014-10-22 12:50:37 -0700137 new BgpPeer("00:00:00:00:00:00:00:02", 1, peer2Sw2Eth1));
138
Jonathan Hart31582d12014-10-22 13:52:41 -0700139 sdnIpConfigService = createMock(SdnIpConfigService.class);
140 expect(sdnIpConfigService.getBgpPeers()).andReturn(peers).anyTimes();
141 replay(sdnIpConfigService);
142
Pingping3855f312014-10-22 12:50:37 -0700143 }
144
145 /**
146 * Sets up logical interfaces, which emulate the configured interfaces
147 * in SDN-IP application.
Pingping3855f312014-10-22 12:50:37 -0700148 */
Jonathan Hart31582d12014-10-22 13:52:41 -0700149 private void setUpInterfaceService() {
150 interfaceService = createMock(InterfaceService.class);
Pingping3855f312014-10-22 12:50:37 -0700151
Jonathan Hart31582d12014-10-22 13:52:41 -0700152 Set<Interface> interfaces = Sets.newHashSet();
Pingping3855f312014-10-22 12:50:37 -0700153
Pavlin Radoslavov76b0ae22014-10-27 15:33:19 -0700154 InterfaceIpAddress ia1 =
155 new InterfaceIpAddress(IpAddress.valueOf("192.168.10.101"),
156 IpPrefix.valueOf("192.168.10.0/24"));
Jonathan Hart31582d12014-10-22 13:52:41 -0700157 Interface sw1Eth1 = new Interface(SW1_ETH1,
Pavlin Radoslavov76b0ae22014-10-27 15:33:19 -0700158 Sets.newHashSet(ia1),
Jonathan Hart31582d12014-10-22 13:52:41 -0700159 MacAddress.valueOf("00:00:00:00:00:01"));
Pingping3855f312014-10-22 12:50:37 -0700160
Jonathan Hart31582d12014-10-22 13:52:41 -0700161 expect(interfaceService.getInterface(SW1_ETH1)).andReturn(sw1Eth1).anyTimes();
162 interfaces.add(sw1Eth1);
Pingping3855f312014-10-22 12:50:37 -0700163
Pavlin Radoslavov76b0ae22014-10-27 15:33:19 -0700164 InterfaceIpAddress ia2 =
165 new InterfaceIpAddress(IpAddress.valueOf("192.168.20.101"),
166 IpPrefix.valueOf("192.168.20.0/24"));
Jonathan Hart31582d12014-10-22 13:52:41 -0700167 Interface sw2Eth1 = new Interface(SW2_ETH1,
Pavlin Radoslavov76b0ae22014-10-27 15:33:19 -0700168 Sets.newHashSet(ia2),
Jonathan Hart31582d12014-10-22 13:52:41 -0700169 MacAddress.valueOf("00:00:00:00:00:02"));
Pingping3855f312014-10-22 12:50:37 -0700170
Jonathan Hart31582d12014-10-22 13:52:41 -0700171 expect(interfaceService.getInterface(SW2_ETH1)).andReturn(sw2Eth1).anyTimes();
172 interfaces.add(sw2Eth1);
173
Pavlin Radoslavov76b0ae22014-10-27 15:33:19 -0700174 InterfaceIpAddress ia3 =
175 new InterfaceIpAddress(IpAddress.valueOf("192.168.30.101"),
176 IpPrefix.valueOf("192.168.30.0/24"));
Jonathan Hart31582d12014-10-22 13:52:41 -0700177 Interface sw3Eth1 = new Interface(SW3_ETH1,
Pavlin Radoslavov76b0ae22014-10-27 15:33:19 -0700178 Sets.newHashSet(ia3),
Jonathan Hart31582d12014-10-22 13:52:41 -0700179 MacAddress.valueOf("00:00:00:00:00:03"));
180
181 expect(interfaceService.getInterface(SW3_ETH1)).andReturn(sw3Eth1).anyTimes();
182 interfaces.add(sw3Eth1);
183
184 expect(interfaceService.getInterfaces()).andReturn(interfaces).anyTimes();
185
186 replay(interfaceService);
187 }
188
189 /**
190 * Sets up the host service with details of some hosts.
191 */
192 private void setUpHostService() {
193 hostService = createMock(HostService.class);
194
195 hostService.addListener(anyObject(HostListener.class));
196 expectLastCall().anyTimes();
197
198 IpPrefix host1Address = IpPrefix.valueOf("192.168.10.1/32");
199 Host host1 = new DefaultHost(ProviderId.NONE, HostId.NONE,
200 MacAddress.valueOf("00:00:00:00:00:01"), VlanId.NONE,
201 new HostLocation(SW1_ETH1, 1),
202 Sets.newHashSet(host1Address));
203
204 expect(hostService.getHostsByIp(host1Address))
205 .andReturn(Sets.newHashSet(host1)).anyTimes();
206 hostService.startMonitoringIp(host1Address.toIpAddress());
207 expectLastCall().anyTimes();
208
209
210 IpPrefix host2Address = IpPrefix.valueOf("192.168.20.1/32");
211 Host host2 = new DefaultHost(ProviderId.NONE, HostId.NONE,
212 MacAddress.valueOf("00:00:00:00:00:02"), VlanId.NONE,
213 new HostLocation(SW2_ETH1, 1),
214 Sets.newHashSet(host2Address));
215
216 expect(hostService.getHostsByIp(host2Address))
217 .andReturn(Sets.newHashSet(host2)).anyTimes();
218 hostService.startMonitoringIp(host2Address.toIpAddress());
219 expectLastCall().anyTimes();
220
221
222 replay(hostService);
Pingping3855f312014-10-22 12:50:37 -0700223 }
224
225 /**
226 * This method tests adding a route entry.
227 */
228 @Test
229 public void testProcessRouteAdd() throws TestUtilsException {
Pingping3855f312014-10-22 12:50:37 -0700230 // Construct a route entry
231 RouteEntry routeEntry = new RouteEntry(
232 IpPrefix.valueOf("1.1.1.0/24"),
233 IpAddress.valueOf("192.168.10.1"));
234
235 // Construct a MultiPointToSinglePointIntent intent
236 TrafficSelector.Builder selectorBuilder =
237 DefaultTrafficSelector.builder();
238 selectorBuilder.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(
239 routeEntry.prefix());
240
241 TrafficTreatment.Builder treatmentBuilder =
242 DefaultTrafficTreatment.builder();
243 treatmentBuilder.setEthDst(MacAddress.valueOf("00:00:00:00:00:01"));
244
245 Set<ConnectPoint> ingressPoints = new HashSet<ConnectPoint>();
Jonathan Hart31582d12014-10-22 13:52:41 -0700246 ingressPoints.add(SW2_ETH1);
247 ingressPoints.add(SW3_ETH1);
Pingping3855f312014-10-22 12:50:37 -0700248
249 MultiPointToSinglePointIntent intent =
250 new MultiPointToSinglePointIntent(APPID,
251 selectorBuilder.build(), treatmentBuilder.build(),
Jonathan Hart31582d12014-10-22 13:52:41 -0700252 ingressPoints, SW1_ETH1);
Pingping3855f312014-10-22 12:50:37 -0700253
254 // Set up test expectation
255 reset(intentService);
256 intentService.submit(intent);
257 replay(intentService);
258
259 // Call the processRouteAdd() method in Router class
260 router.leaderChanged(true);
261 TestUtils.setField(router, "isActivatedLeader", true);
262 router.processRouteAdd(routeEntry);
263
264 // Verify
265 assertEquals(router.getRoutes().size(), 1);
266 assertTrue(router.getRoutes().contains(routeEntry));
267 assertEquals(router.getPushedRouteIntents().size(), 1);
268 assertEquals(router.getPushedRouteIntents().iterator().next(),
269 intent);
270 verify(intentService);
271 }
272
273 /**
274 * This method tests updating a route entry.
275 *
276 * @throws TestUtilsException
277 */
278 @Test
279 public void testRouteUpdate() throws TestUtilsException {
Pingping3855f312014-10-22 12:50:37 -0700280 // Firstly add a route
281 testProcessRouteAdd();
282
283 // Construct the existing route entry
284 RouteEntry routeEntry = new RouteEntry(
285 IpPrefix.valueOf("1.1.1.0/24"),
286 IpAddress.valueOf("192.168.10.1"));
287
288 // Construct the existing MultiPointToSinglePointIntent intent
289 TrafficSelector.Builder selectorBuilder =
290 DefaultTrafficSelector.builder();
291 selectorBuilder.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(
292 routeEntry.prefix());
293
294 TrafficTreatment.Builder treatmentBuilder =
295 DefaultTrafficTreatment.builder();
296 treatmentBuilder.setEthDst(MacAddress.valueOf("00:00:00:00:00:01"));
297
Pingping3855f312014-10-22 12:50:37 -0700298 Set<ConnectPoint> ingressPoints = new HashSet<ConnectPoint>();
Jonathan Hart31582d12014-10-22 13:52:41 -0700299 ingressPoints.add(SW2_ETH1);
300 ingressPoints.add(SW3_ETH1);
Pingping3855f312014-10-22 12:50:37 -0700301
302 MultiPointToSinglePointIntent intent =
303 new MultiPointToSinglePointIntent(APPID,
304 selectorBuilder.build(), treatmentBuilder.build(),
Jonathan Hart31582d12014-10-22 13:52:41 -0700305 ingressPoints, SW1_ETH1);
Pingping3855f312014-10-22 12:50:37 -0700306
307 // Start to construct a new route entry and new intent
308 RouteEntry routeEntryUpdate = new RouteEntry(
309 IpPrefix.valueOf("1.1.1.0/24"),
310 IpAddress.valueOf("192.168.20.1"));
311
312 // Construct a new MultiPointToSinglePointIntent intent
313 TrafficSelector.Builder selectorBuilderNew =
314 DefaultTrafficSelector.builder();
315 selectorBuilderNew.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(
316 routeEntryUpdate.prefix());
317
318 TrafficTreatment.Builder treatmentBuilderNew =
319 DefaultTrafficTreatment.builder();
320 treatmentBuilderNew.setEthDst(MacAddress.valueOf("00:00:00:00:00:02"));
321
Pingping3855f312014-10-22 12:50:37 -0700322
323 Set<ConnectPoint> ingressPointsNew = new HashSet<ConnectPoint>();
Jonathan Hart31582d12014-10-22 13:52:41 -0700324 ingressPointsNew.add(SW1_ETH1);
325 ingressPointsNew.add(SW3_ETH1);
Pingping3855f312014-10-22 12:50:37 -0700326
327 MultiPointToSinglePointIntent intentNew =
328 new MultiPointToSinglePointIntent(APPID,
329 selectorBuilderNew.build(),
330 treatmentBuilderNew.build(),
Jonathan Hart31582d12014-10-22 13:52:41 -0700331 ingressPointsNew, SW2_ETH1);
Pingping3855f312014-10-22 12:50:37 -0700332
333 // Set up test expectation
334 reset(intentService);
335 intentService.withdraw(intent);
336 intentService.submit(intentNew);
337 replay(intentService);
338
339 // Call the processRouteAdd() method in Router class
340 router.leaderChanged(true);
341 TestUtils.setField(router, "isActivatedLeader", true);
342 router.processRouteAdd(routeEntryUpdate);
343
344 // Verify
345 assertEquals(router.getRoutes().size(), 1);
346 assertTrue(router.getRoutes().contains(routeEntryUpdate));
347 assertEquals(router.getPushedRouteIntents().size(), 1);
348 assertEquals(router.getPushedRouteIntents().iterator().next(),
349 intentNew);
350 verify(intentService);
351 }
352
353 /**
354 * This method tests deleting a route entry.
355 */
356 @Test
357 public void testProcessRouteDelete() throws TestUtilsException {
Pingping3855f312014-10-22 12:50:37 -0700358 // Firstly add a route
359 testProcessRouteAdd();
360
361 // Construct the existing route entry
362 RouteEntry routeEntry = new RouteEntry(
363 IpPrefix.valueOf("1.1.1.0/24"),
364 IpAddress.valueOf("192.168.10.1"));
365
366 // Construct the existing MultiPointToSinglePointIntent intent
367 TrafficSelector.Builder selectorBuilder =
368 DefaultTrafficSelector.builder();
369 selectorBuilder.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(
370 routeEntry.prefix());
371
372 TrafficTreatment.Builder treatmentBuilder =
373 DefaultTrafficTreatment.builder();
374 treatmentBuilder.setEthDst(MacAddress.valueOf("00:00:00:00:00:01"));
375
Pingping3855f312014-10-22 12:50:37 -0700376 Set<ConnectPoint> ingressPoints = new HashSet<ConnectPoint>();
Jonathan Hart31582d12014-10-22 13:52:41 -0700377 ingressPoints.add(SW2_ETH1);
378 ingressPoints.add(SW3_ETH1);
Pingping3855f312014-10-22 12:50:37 -0700379
380 MultiPointToSinglePointIntent intent =
381 new MultiPointToSinglePointIntent(APPID,
382 selectorBuilder.build(), treatmentBuilder.build(),
Jonathan Hart31582d12014-10-22 13:52:41 -0700383 ingressPoints, SW1_ETH1);
Pingping3855f312014-10-22 12:50:37 -0700384
385 // Set up expectation
386 reset(intentService);
387 intentService.withdraw(intent);
388 replay(intentService);
389
390 // Call route deleting method in Router class
391 router.leaderChanged(true);
392 TestUtils.setField(router, "isActivatedLeader", true);
393 router.processRouteDelete(routeEntry);
394
395 // Verify
396 assertEquals(router.getRoutes().size(), 0);
397 assertEquals(router.getPushedRouteIntents().size(), 0);
398 verify(intentService);
399 }
400
401 /**
402 * This method tests when the next hop of a route is the local BGP speaker.
403 *
404 * @throws TestUtilsException
405 */
406 @Test
407 public void testLocalRouteAdd() throws TestUtilsException {
Pingping3855f312014-10-22 12:50:37 -0700408 // Construct a route entry, the next hop is the local BGP speaker
409 RouteEntry routeEntry = new RouteEntry(
410 IpPrefix.valueOf("1.1.1.0/24"), IpAddress.valueOf("0.0.0.0"));
411
412 // Reset intentService to check whether the submit method is called
413 reset(intentService);
414 replay(intentService);
415
416 // Call the processRouteAdd() method in Router class
417 router.leaderChanged(true);
418 TestUtils.setField(router, "isActivatedLeader", true);
419 router.processRouteAdd(routeEntry);
420
421 // Verify
422 assertEquals(router.getRoutes().size(), 1);
423 assertTrue(router.getRoutes().contains(routeEntry));
424 assertEquals(router.getPushedRouteIntents().size(), 0);
425 verify(intentService);
426 }
427}