blob: b4b05518a29c8382c02bb82dc337d0311b42fc93 [file] [log] [blame]
Thomas Vachuska781d18b2014-10-27 10:31:25 -07001/*
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07002 * Copyright 2014 Open Networking Laboratory
Thomas Vachuska781d18b2014-10-27 10:31:25 -07003 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07004 * 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
Thomas Vachuska781d18b2014-10-27 10:31:25 -07007 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07008 * 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.
Thomas Vachuska781d18b2014-10-27 10:31:25 -070015 */
Pingping3855f312014-10-22 12:50:37 -070016package org.onlab.onos.sdnip;
17
Jonathan Hart31582d12014-10-22 13:52:41 -070018import static org.easymock.EasyMock.anyObject;
Pingping3855f312014-10-22 12:50:37 -070019import static org.easymock.EasyMock.createMock;
20import static org.easymock.EasyMock.expect;
Jonathan Hart31582d12014-10-22 13:52:41 -070021import static org.easymock.EasyMock.expectLastCall;
Pingping3855f312014-10-22 12:50:37 -070022import static org.easymock.EasyMock.replay;
23import static org.easymock.EasyMock.reset;
24import static org.easymock.EasyMock.verify;
25import static org.junit.Assert.assertEquals;
26import static org.junit.Assert.assertTrue;
27
28import java.util.HashMap;
29import java.util.HashSet;
30import java.util.Map;
31import java.util.Set;
32
33import org.junit.Before;
34import org.junit.Test;
Pavlin Radoslavovd26f57a2014-10-23 17:19:45 -070035import org.onlab.junit.TestUtils;
36import org.onlab.junit.TestUtils.TestUtilsException;
Thomas Vachuskae0f804a2014-10-27 23:40:48 -070037import org.onlab.onos.core.ApplicationId;
Pingping3855f312014-10-22 12:50:37 -070038import org.onlab.onos.net.ConnectPoint;
39import org.onlab.onos.net.DefaultHost;
40import org.onlab.onos.net.DeviceId;
41import org.onlab.onos.net.Host;
42import org.onlab.onos.net.HostId;
43import org.onlab.onos.net.HostLocation;
44import org.onlab.onos.net.PortNumber;
45import org.onlab.onos.net.flow.DefaultTrafficSelector;
46import org.onlab.onos.net.flow.DefaultTrafficTreatment;
47import org.onlab.onos.net.flow.TrafficSelector;
48import org.onlab.onos.net.flow.TrafficTreatment;
Jonathan Hart31582d12014-10-22 13:52:41 -070049import org.onlab.onos.net.host.HostListener;
Pingping3855f312014-10-22 12:50:37 -070050import org.onlab.onos.net.host.HostService;
Pavlin Radoslavov76b0ae22014-10-27 15:33:19 -070051import org.onlab.onos.net.host.InterfaceIpAddress;
Pingping3855f312014-10-22 12:50:37 -070052import org.onlab.onos.net.intent.IntentService;
53import org.onlab.onos.net.intent.MultiPointToSinglePointIntent;
54import org.onlab.onos.net.provider.ProviderId;
55import org.onlab.onos.sdnip.config.BgpPeer;
56import org.onlab.onos.sdnip.config.Interface;
57import org.onlab.onos.sdnip.config.SdnIpConfigService;
58import org.onlab.packet.Ethernet;
59import org.onlab.packet.IpAddress;
Pavlin Radoslavov6b570732014-11-06 13:16:45 -080060import org.onlab.packet.Ip4Address;
Pingping3855f312014-10-22 12:50:37 -070061import org.onlab.packet.IpPrefix;
Pavlin Radoslavov6b570732014-11-06 13:16:45 -080062import org.onlab.packet.Ip4Prefix;
Pingping3855f312014-10-22 12:50:37 -070063import org.onlab.packet.MacAddress;
64import org.onlab.packet.VlanId;
Pingping3855f312014-10-22 12:50:37 -070065
66import com.google.common.collect.Sets;
67
68/**
69 * This class tests adding a route, updating a route, deleting a route,
70 * and adding a route whose next hop is the local BGP speaker.
Pingpingfc584672014-10-23 10:51:19 -070071 * <p/>
72 * ARP module answers the MAC address synchronously.
Pingping3855f312014-10-22 12:50:37 -070073 */
74public class RouterTest {
75
76 private SdnIpConfigService sdnIpConfigService;
77 private InterfaceService interfaceService;
78 private IntentService intentService;
79 private HostService hostService;
80
Jonathan Hart31582d12014-10-22 13:52:41 -070081 private static final ConnectPoint SW1_ETH1 = new ConnectPoint(
82 DeviceId.deviceId("of:0000000000000001"),
83 PortNumber.portNumber(1));
84
85 private static final ConnectPoint SW2_ETH1 = new ConnectPoint(
86 DeviceId.deviceId("of:0000000000000002"),
87 PortNumber.portNumber(1));
88
89 private static final ConnectPoint SW3_ETH1 = new ConnectPoint(
90 DeviceId.deviceId("of:0000000000000003"),
91 PortNumber.portNumber(1));
Pingping3855f312014-10-22 12:50:37 -070092
93 private static final ApplicationId APPID = new ApplicationId() {
94 @Override
95 public short id() {
96 return 1;
97 }
98
99 @Override
100 public String name() {
101 return "SDNIP";
102 }
103 };
104
105 private Router router;
106
107 @Before
108 public void setUp() throws Exception {
Jonathan Hart31582d12014-10-22 13:52:41 -0700109 setUpBgpPeers();
Pingping3855f312014-10-22 12:50:37 -0700110
Jonathan Hart31582d12014-10-22 13:52:41 -0700111 setUpInterfaceService();
112 setUpHostService();
Pingping3855f312014-10-22 12:50:37 -0700113
114 intentService = createMock(IntentService.class);
Pingping3855f312014-10-22 12:50:37 -0700115
116 router = new Router(APPID, intentService,
117 hostService, sdnIpConfigService, interfaceService);
118 }
119
120 /**
121 * Sets up BGP peers in external networks.
Pingping3855f312014-10-22 12:50:37 -0700122 */
Jonathan Hart31582d12014-10-22 13:52:41 -0700123 private void setUpBgpPeers() {
Pingping3855f312014-10-22 12:50:37 -0700124
Jonathan Hart31582d12014-10-22 13:52:41 -0700125 Map<IpAddress, BgpPeer> peers = new HashMap<>();
Pingping3855f312014-10-22 12:50:37 -0700126
127 String peerSw1Eth1 = "192.168.10.1";
Jonathan Hart31582d12014-10-22 13:52:41 -0700128 peers.put(IpAddress.valueOf(peerSw1Eth1),
Pingping3855f312014-10-22 12:50:37 -0700129 new BgpPeer("00:00:00:00:00:00:00:01", 1, peerSw1Eth1));
130
131 // Two BGP peers are connected to switch 2 port 1.
132 String peer1Sw2Eth1 = "192.168.20.1";
Jonathan Hart31582d12014-10-22 13:52:41 -0700133 peers.put(IpAddress.valueOf(peer1Sw2Eth1),
Pingping3855f312014-10-22 12:50:37 -0700134 new BgpPeer("00:00:00:00:00:00:00:02", 1, peer1Sw2Eth1));
135
136 String peer2Sw2Eth1 = "192.168.20.2";
Jonathan Hart31582d12014-10-22 13:52:41 -0700137 peers.put(IpAddress.valueOf(peer2Sw2Eth1),
Pingping3855f312014-10-22 12:50:37 -0700138 new BgpPeer("00:00:00:00:00:00:00:02", 1, peer2Sw2Eth1));
139
Jonathan Hart31582d12014-10-22 13:52:41 -0700140 sdnIpConfigService = createMock(SdnIpConfigService.class);
141 expect(sdnIpConfigService.getBgpPeers()).andReturn(peers).anyTimes();
142 replay(sdnIpConfigService);
143
Pingping3855f312014-10-22 12:50:37 -0700144 }
145
146 /**
147 * Sets up logical interfaces, which emulate the configured interfaces
148 * in SDN-IP application.
Pingping3855f312014-10-22 12:50:37 -0700149 */
Jonathan Hart31582d12014-10-22 13:52:41 -0700150 private void setUpInterfaceService() {
151 interfaceService = createMock(InterfaceService.class);
Pingping3855f312014-10-22 12:50:37 -0700152
Jonathan Hart31582d12014-10-22 13:52:41 -0700153 Set<Interface> interfaces = Sets.newHashSet();
Pingping3855f312014-10-22 12:50:37 -0700154
Pavlin Radoslavov76b0ae22014-10-27 15:33:19 -0700155 InterfaceIpAddress ia1 =
156 new InterfaceIpAddress(IpAddress.valueOf("192.168.10.101"),
157 IpPrefix.valueOf("192.168.10.0/24"));
Jonathan Hart31582d12014-10-22 13:52:41 -0700158 Interface sw1Eth1 = new Interface(SW1_ETH1,
Pavlin Radoslavov76b0ae22014-10-27 15:33:19 -0700159 Sets.newHashSet(ia1),
Jonathan Hart31582d12014-10-22 13:52:41 -0700160 MacAddress.valueOf("00:00:00:00:00:01"));
Pingping3855f312014-10-22 12:50:37 -0700161
Jonathan Hart31582d12014-10-22 13:52:41 -0700162 expect(interfaceService.getInterface(SW1_ETH1)).andReturn(sw1Eth1).anyTimes();
163 interfaces.add(sw1Eth1);
Pingping3855f312014-10-22 12:50:37 -0700164
Pavlin Radoslavov76b0ae22014-10-27 15:33:19 -0700165 InterfaceIpAddress ia2 =
166 new InterfaceIpAddress(IpAddress.valueOf("192.168.20.101"),
167 IpPrefix.valueOf("192.168.20.0/24"));
Jonathan Hart31582d12014-10-22 13:52:41 -0700168 Interface sw2Eth1 = new Interface(SW2_ETH1,
Pavlin Radoslavov76b0ae22014-10-27 15:33:19 -0700169 Sets.newHashSet(ia2),
Jonathan Hart31582d12014-10-22 13:52:41 -0700170 MacAddress.valueOf("00:00:00:00:00:02"));
Pingping3855f312014-10-22 12:50:37 -0700171
Jonathan Hart31582d12014-10-22 13:52:41 -0700172 expect(interfaceService.getInterface(SW2_ETH1)).andReturn(sw2Eth1).anyTimes();
173 interfaces.add(sw2Eth1);
174
Pavlin Radoslavov76b0ae22014-10-27 15:33:19 -0700175 InterfaceIpAddress ia3 =
176 new InterfaceIpAddress(IpAddress.valueOf("192.168.30.101"),
177 IpPrefix.valueOf("192.168.30.0/24"));
Jonathan Hart31582d12014-10-22 13:52:41 -0700178 Interface sw3Eth1 = new Interface(SW3_ETH1,
Pavlin Radoslavov76b0ae22014-10-27 15:33:19 -0700179 Sets.newHashSet(ia3),
Jonathan Hart31582d12014-10-22 13:52:41 -0700180 MacAddress.valueOf("00:00:00:00:00:03"));
181
182 expect(interfaceService.getInterface(SW3_ETH1)).andReturn(sw3Eth1).anyTimes();
183 interfaces.add(sw3Eth1);
184
185 expect(interfaceService.getInterfaces()).andReturn(interfaces).anyTimes();
186
187 replay(interfaceService);
188 }
189
190 /**
191 * Sets up the host service with details of some hosts.
192 */
193 private void setUpHostService() {
194 hostService = createMock(HostService.class);
195
196 hostService.addListener(anyObject(HostListener.class));
197 expectLastCall().anyTimes();
198
Pavlin Radoslavov33f228a2014-10-27 19:33:16 -0700199 IpAddress host1Address = IpAddress.valueOf("192.168.10.1");
Jonathan Hart31582d12014-10-22 13:52:41 -0700200 Host host1 = new DefaultHost(ProviderId.NONE, HostId.NONE,
201 MacAddress.valueOf("00:00:00:00:00:01"), VlanId.NONE,
202 new HostLocation(SW1_ETH1, 1),
Pavlin Radoslavov33f228a2014-10-27 19:33:16 -0700203 Sets.newHashSet(host1Address));
Jonathan Hart31582d12014-10-22 13:52:41 -0700204
205 expect(hostService.getHostsByIp(host1Address))
206 .andReturn(Sets.newHashSet(host1)).anyTimes();
Pavlin Radoslavov33f228a2014-10-27 19:33:16 -0700207 hostService.startMonitoringIp(host1Address);
Jonathan Hart31582d12014-10-22 13:52:41 -0700208 expectLastCall().anyTimes();
209
210
Pavlin Radoslavov33f228a2014-10-27 19:33:16 -0700211 IpAddress host2Address = IpAddress.valueOf("192.168.20.1");
Jonathan Hart31582d12014-10-22 13:52:41 -0700212 Host host2 = new DefaultHost(ProviderId.NONE, HostId.NONE,
213 MacAddress.valueOf("00:00:00:00:00:02"), VlanId.NONE,
214 new HostLocation(SW2_ETH1, 1),
Pavlin Radoslavov33f228a2014-10-27 19:33:16 -0700215 Sets.newHashSet(host2Address));
Jonathan Hart31582d12014-10-22 13:52:41 -0700216
217 expect(hostService.getHostsByIp(host2Address))
218 .andReturn(Sets.newHashSet(host2)).anyTimes();
Pavlin Radoslavov33f228a2014-10-27 19:33:16 -0700219 hostService.startMonitoringIp(host2Address);
Jonathan Hart31582d12014-10-22 13:52:41 -0700220 expectLastCall().anyTimes();
221
222
223 replay(hostService);
Pingping3855f312014-10-22 12:50:37 -0700224 }
225
226 /**
227 * This method tests adding a route entry.
228 */
229 @Test
230 public void testProcessRouteAdd() throws TestUtilsException {
Pingping3855f312014-10-22 12:50:37 -0700231 // Construct a route entry
232 RouteEntry routeEntry = new RouteEntry(
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800233 Ip4Prefix.valueOf("1.1.1.0/24"),
234 Ip4Address.valueOf("192.168.10.1"));
Pingping3855f312014-10-22 12:50:37 -0700235
236 // Construct a MultiPointToSinglePointIntent intent
237 TrafficSelector.Builder selectorBuilder =
238 DefaultTrafficSelector.builder();
239 selectorBuilder.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(
240 routeEntry.prefix());
241
242 TrafficTreatment.Builder treatmentBuilder =
243 DefaultTrafficTreatment.builder();
244 treatmentBuilder.setEthDst(MacAddress.valueOf("00:00:00:00:00:01"));
245
246 Set<ConnectPoint> ingressPoints = new HashSet<ConnectPoint>();
Jonathan Hart31582d12014-10-22 13:52:41 -0700247 ingressPoints.add(SW2_ETH1);
248 ingressPoints.add(SW3_ETH1);
Pingping3855f312014-10-22 12:50:37 -0700249
250 MultiPointToSinglePointIntent intent =
251 new MultiPointToSinglePointIntent(APPID,
252 selectorBuilder.build(), treatmentBuilder.build(),
Jonathan Hart31582d12014-10-22 13:52:41 -0700253 ingressPoints, SW1_ETH1);
Pingping3855f312014-10-22 12:50:37 -0700254
255 // Set up test expectation
256 reset(intentService);
257 intentService.submit(intent);
258 replay(intentService);
259
260 // Call the processRouteAdd() method in Router class
261 router.leaderChanged(true);
262 TestUtils.setField(router, "isActivatedLeader", true);
263 router.processRouteAdd(routeEntry);
264
265 // Verify
266 assertEquals(router.getRoutes().size(), 1);
267 assertTrue(router.getRoutes().contains(routeEntry));
268 assertEquals(router.getPushedRouteIntents().size(), 1);
269 assertEquals(router.getPushedRouteIntents().iterator().next(),
270 intent);
271 verify(intentService);
272 }
273
274 /**
275 * This method tests updating a route entry.
276 *
277 * @throws TestUtilsException
278 */
279 @Test
280 public void testRouteUpdate() throws TestUtilsException {
Pingping3855f312014-10-22 12:50:37 -0700281 // Firstly add a route
282 testProcessRouteAdd();
283
284 // Construct the existing route entry
285 RouteEntry routeEntry = new RouteEntry(
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800286 Ip4Prefix.valueOf("1.1.1.0/24"),
287 Ip4Address.valueOf("192.168.10.1"));
Pingping3855f312014-10-22 12:50:37 -0700288
289 // Construct the existing MultiPointToSinglePointIntent intent
290 TrafficSelector.Builder selectorBuilder =
291 DefaultTrafficSelector.builder();
292 selectorBuilder.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(
293 routeEntry.prefix());
294
295 TrafficTreatment.Builder treatmentBuilder =
296 DefaultTrafficTreatment.builder();
297 treatmentBuilder.setEthDst(MacAddress.valueOf("00:00:00:00:00:01"));
298
Pingping3855f312014-10-22 12:50:37 -0700299 Set<ConnectPoint> ingressPoints = new HashSet<ConnectPoint>();
Jonathan Hart31582d12014-10-22 13:52:41 -0700300 ingressPoints.add(SW2_ETH1);
301 ingressPoints.add(SW3_ETH1);
Pingping3855f312014-10-22 12:50:37 -0700302
303 MultiPointToSinglePointIntent intent =
304 new MultiPointToSinglePointIntent(APPID,
305 selectorBuilder.build(), treatmentBuilder.build(),
Jonathan Hart31582d12014-10-22 13:52:41 -0700306 ingressPoints, SW1_ETH1);
Pingping3855f312014-10-22 12:50:37 -0700307
308 // Start to construct a new route entry and new intent
309 RouteEntry routeEntryUpdate = new RouteEntry(
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800310 Ip4Prefix.valueOf("1.1.1.0/24"),
311 Ip4Address.valueOf("192.168.20.1"));
Pingping3855f312014-10-22 12:50:37 -0700312
313 // Construct a new MultiPointToSinglePointIntent intent
314 TrafficSelector.Builder selectorBuilderNew =
315 DefaultTrafficSelector.builder();
316 selectorBuilderNew.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(
317 routeEntryUpdate.prefix());
318
319 TrafficTreatment.Builder treatmentBuilderNew =
320 DefaultTrafficTreatment.builder();
321 treatmentBuilderNew.setEthDst(MacAddress.valueOf("00:00:00:00:00:02"));
322
Pingping3855f312014-10-22 12:50:37 -0700323
324 Set<ConnectPoint> ingressPointsNew = new HashSet<ConnectPoint>();
Jonathan Hart31582d12014-10-22 13:52:41 -0700325 ingressPointsNew.add(SW1_ETH1);
326 ingressPointsNew.add(SW3_ETH1);
Pingping3855f312014-10-22 12:50:37 -0700327
328 MultiPointToSinglePointIntent intentNew =
329 new MultiPointToSinglePointIntent(APPID,
330 selectorBuilderNew.build(),
331 treatmentBuilderNew.build(),
Jonathan Hart31582d12014-10-22 13:52:41 -0700332 ingressPointsNew, SW2_ETH1);
Pingping3855f312014-10-22 12:50:37 -0700333
334 // Set up test expectation
335 reset(intentService);
336 intentService.withdraw(intent);
337 intentService.submit(intentNew);
338 replay(intentService);
339
340 // Call the processRouteAdd() method in Router class
341 router.leaderChanged(true);
342 TestUtils.setField(router, "isActivatedLeader", true);
343 router.processRouteAdd(routeEntryUpdate);
344
345 // Verify
346 assertEquals(router.getRoutes().size(), 1);
347 assertTrue(router.getRoutes().contains(routeEntryUpdate));
348 assertEquals(router.getPushedRouteIntents().size(), 1);
349 assertEquals(router.getPushedRouteIntents().iterator().next(),
350 intentNew);
351 verify(intentService);
352 }
353
354 /**
355 * This method tests deleting a route entry.
356 */
357 @Test
358 public void testProcessRouteDelete() throws TestUtilsException {
Pingping3855f312014-10-22 12:50:37 -0700359 // Firstly add a route
360 testProcessRouteAdd();
361
362 // Construct the existing route entry
363 RouteEntry routeEntry = new RouteEntry(
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800364 Ip4Prefix.valueOf("1.1.1.0/24"),
365 Ip4Address.valueOf("192.168.10.1"));
Pingping3855f312014-10-22 12:50:37 -0700366
367 // Construct the existing MultiPointToSinglePointIntent intent
368 TrafficSelector.Builder selectorBuilder =
369 DefaultTrafficSelector.builder();
370 selectorBuilder.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(
371 routeEntry.prefix());
372
373 TrafficTreatment.Builder treatmentBuilder =
374 DefaultTrafficTreatment.builder();
375 treatmentBuilder.setEthDst(MacAddress.valueOf("00:00:00:00:00:01"));
376
Pingping3855f312014-10-22 12:50:37 -0700377 Set<ConnectPoint> ingressPoints = new HashSet<ConnectPoint>();
Jonathan Hart31582d12014-10-22 13:52:41 -0700378 ingressPoints.add(SW2_ETH1);
379 ingressPoints.add(SW3_ETH1);
Pingping3855f312014-10-22 12:50:37 -0700380
381 MultiPointToSinglePointIntent intent =
382 new MultiPointToSinglePointIntent(APPID,
383 selectorBuilder.build(), treatmentBuilder.build(),
Jonathan Hart31582d12014-10-22 13:52:41 -0700384 ingressPoints, SW1_ETH1);
Pingping3855f312014-10-22 12:50:37 -0700385
386 // Set up expectation
387 reset(intentService);
388 intentService.withdraw(intent);
389 replay(intentService);
390
391 // Call route deleting method in Router class
392 router.leaderChanged(true);
393 TestUtils.setField(router, "isActivatedLeader", true);
394 router.processRouteDelete(routeEntry);
395
396 // Verify
397 assertEquals(router.getRoutes().size(), 0);
398 assertEquals(router.getPushedRouteIntents().size(), 0);
399 verify(intentService);
400 }
401
402 /**
403 * This method tests when the next hop of a route is the local BGP speaker.
404 *
405 * @throws TestUtilsException
406 */
407 @Test
408 public void testLocalRouteAdd() throws TestUtilsException {
Pingping3855f312014-10-22 12:50:37 -0700409 // Construct a route entry, the next hop is the local BGP speaker
410 RouteEntry routeEntry = new RouteEntry(
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800411 Ip4Prefix.valueOf("1.1.1.0/24"),
412 Ip4Address.valueOf("0.0.0.0"));
Pingping3855f312014-10-22 12:50:37 -0700413
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}