blob: b361123a1bfb3397794cafddac7045169ed2177d [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;
60import org.onlab.packet.IpPrefix;
61import org.onlab.packet.MacAddress;
62import org.onlab.packet.VlanId;
Pingping3855f312014-10-22 12:50:37 -070063
64import com.google.common.collect.Sets;
65
66/**
67 * This class tests adding a route, updating a route, deleting a route,
68 * and adding a route whose next hop is the local BGP speaker.
Pingpingfc584672014-10-23 10:51:19 -070069 * <p/>
70 * ARP module answers the MAC address synchronously.
Pingping3855f312014-10-22 12:50:37 -070071 */
72public class RouterTest {
73
74 private SdnIpConfigService sdnIpConfigService;
75 private InterfaceService interfaceService;
76 private IntentService intentService;
77 private HostService hostService;
78
Jonathan Hart31582d12014-10-22 13:52:41 -070079 private static final ConnectPoint SW1_ETH1 = new ConnectPoint(
80 DeviceId.deviceId("of:0000000000000001"),
81 PortNumber.portNumber(1));
82
83 private static final ConnectPoint SW2_ETH1 = new ConnectPoint(
84 DeviceId.deviceId("of:0000000000000002"),
85 PortNumber.portNumber(1));
86
87 private static final ConnectPoint SW3_ETH1 = new ConnectPoint(
88 DeviceId.deviceId("of:0000000000000003"),
89 PortNumber.portNumber(1));
Pingping3855f312014-10-22 12:50:37 -070090
91 private static final ApplicationId APPID = new ApplicationId() {
92 @Override
93 public short id() {
94 return 1;
95 }
96
97 @Override
98 public String name() {
99 return "SDNIP";
100 }
101 };
102
103 private Router router;
104
105 @Before
106 public void setUp() throws Exception {
Jonathan Hart31582d12014-10-22 13:52:41 -0700107 setUpBgpPeers();
Pingping3855f312014-10-22 12:50:37 -0700108
Jonathan Hart31582d12014-10-22 13:52:41 -0700109 setUpInterfaceService();
110 setUpHostService();
Pingping3855f312014-10-22 12:50:37 -0700111
112 intentService = createMock(IntentService.class);
Pingping3855f312014-10-22 12:50:37 -0700113
114 router = new Router(APPID, intentService,
115 hostService, sdnIpConfigService, interfaceService);
116 }
117
118 /**
119 * Sets up BGP peers in external networks.
Pingping3855f312014-10-22 12:50:37 -0700120 */
Jonathan Hart31582d12014-10-22 13:52:41 -0700121 private void setUpBgpPeers() {
Pingping3855f312014-10-22 12:50:37 -0700122
Jonathan Hart31582d12014-10-22 13:52:41 -0700123 Map<IpAddress, BgpPeer> peers = new HashMap<>();
Pingping3855f312014-10-22 12:50:37 -0700124
125 String peerSw1Eth1 = "192.168.10.1";
Jonathan Hart31582d12014-10-22 13:52:41 -0700126 peers.put(IpAddress.valueOf(peerSw1Eth1),
Pingping3855f312014-10-22 12:50:37 -0700127 new BgpPeer("00:00:00:00:00:00:00:01", 1, peerSw1Eth1));
128
129 // Two BGP peers are connected to switch 2 port 1.
130 String peer1Sw2Eth1 = "192.168.20.1";
Jonathan Hart31582d12014-10-22 13:52:41 -0700131 peers.put(IpAddress.valueOf(peer1Sw2Eth1),
Pingping3855f312014-10-22 12:50:37 -0700132 new BgpPeer("00:00:00:00:00:00:00:02", 1, peer1Sw2Eth1));
133
134 String peer2Sw2Eth1 = "192.168.20.2";
Jonathan Hart31582d12014-10-22 13:52:41 -0700135 peers.put(IpAddress.valueOf(peer2Sw2Eth1),
Pingping3855f312014-10-22 12:50:37 -0700136 new BgpPeer("00:00:00:00:00:00:00:02", 1, peer2Sw2Eth1));
137
Jonathan Hart31582d12014-10-22 13:52:41 -0700138 sdnIpConfigService = createMock(SdnIpConfigService.class);
139 expect(sdnIpConfigService.getBgpPeers()).andReturn(peers).anyTimes();
140 replay(sdnIpConfigService);
141
Pingping3855f312014-10-22 12:50:37 -0700142 }
143
144 /**
145 * Sets up logical interfaces, which emulate the configured interfaces
146 * in SDN-IP application.
Pingping3855f312014-10-22 12:50:37 -0700147 */
Jonathan Hart31582d12014-10-22 13:52:41 -0700148 private void setUpInterfaceService() {
149 interfaceService = createMock(InterfaceService.class);
Pingping3855f312014-10-22 12:50:37 -0700150
Jonathan Hart31582d12014-10-22 13:52:41 -0700151 Set<Interface> interfaces = Sets.newHashSet();
Pingping3855f312014-10-22 12:50:37 -0700152
Pavlin Radoslavov76b0ae22014-10-27 15:33:19 -0700153 InterfaceIpAddress ia1 =
154 new InterfaceIpAddress(IpAddress.valueOf("192.168.10.101"),
155 IpPrefix.valueOf("192.168.10.0/24"));
Jonathan Hart31582d12014-10-22 13:52:41 -0700156 Interface sw1Eth1 = new Interface(SW1_ETH1,
Pavlin Radoslavov76b0ae22014-10-27 15:33:19 -0700157 Sets.newHashSet(ia1),
Jonathan Hart31582d12014-10-22 13:52:41 -0700158 MacAddress.valueOf("00:00:00:00:00:01"));
Pingping3855f312014-10-22 12:50:37 -0700159
Jonathan Hart31582d12014-10-22 13:52:41 -0700160 expect(interfaceService.getInterface(SW1_ETH1)).andReturn(sw1Eth1).anyTimes();
161 interfaces.add(sw1Eth1);
Pingping3855f312014-10-22 12:50:37 -0700162
Pavlin Radoslavov76b0ae22014-10-27 15:33:19 -0700163 InterfaceIpAddress ia2 =
164 new InterfaceIpAddress(IpAddress.valueOf("192.168.20.101"),
165 IpPrefix.valueOf("192.168.20.0/24"));
Jonathan Hart31582d12014-10-22 13:52:41 -0700166 Interface sw2Eth1 = new Interface(SW2_ETH1,
Pavlin Radoslavov76b0ae22014-10-27 15:33:19 -0700167 Sets.newHashSet(ia2),
Jonathan Hart31582d12014-10-22 13:52:41 -0700168 MacAddress.valueOf("00:00:00:00:00:02"));
Pingping3855f312014-10-22 12:50:37 -0700169
Jonathan Hart31582d12014-10-22 13:52:41 -0700170 expect(interfaceService.getInterface(SW2_ETH1)).andReturn(sw2Eth1).anyTimes();
171 interfaces.add(sw2Eth1);
172
Pavlin Radoslavov76b0ae22014-10-27 15:33:19 -0700173 InterfaceIpAddress ia3 =
174 new InterfaceIpAddress(IpAddress.valueOf("192.168.30.101"),
175 IpPrefix.valueOf("192.168.30.0/24"));
Jonathan Hart31582d12014-10-22 13:52:41 -0700176 Interface sw3Eth1 = new Interface(SW3_ETH1,
Pavlin Radoslavov76b0ae22014-10-27 15:33:19 -0700177 Sets.newHashSet(ia3),
Jonathan Hart31582d12014-10-22 13:52:41 -0700178 MacAddress.valueOf("00:00:00:00:00:03"));
179
180 expect(interfaceService.getInterface(SW3_ETH1)).andReturn(sw3Eth1).anyTimes();
181 interfaces.add(sw3Eth1);
182
183 expect(interfaceService.getInterfaces()).andReturn(interfaces).anyTimes();
184
185 replay(interfaceService);
186 }
187
188 /**
189 * Sets up the host service with details of some hosts.
190 */
191 private void setUpHostService() {
192 hostService = createMock(HostService.class);
193
194 hostService.addListener(anyObject(HostListener.class));
195 expectLastCall().anyTimes();
196
Pavlin Radoslavov33f228a2014-10-27 19:33:16 -0700197 IpAddress host1Address = IpAddress.valueOf("192.168.10.1");
Jonathan Hart31582d12014-10-22 13:52:41 -0700198 Host host1 = new DefaultHost(ProviderId.NONE, HostId.NONE,
199 MacAddress.valueOf("00:00:00:00:00:01"), VlanId.NONE,
200 new HostLocation(SW1_ETH1, 1),
Pavlin Radoslavov33f228a2014-10-27 19:33:16 -0700201 Sets.newHashSet(host1Address));
Jonathan Hart31582d12014-10-22 13:52:41 -0700202
203 expect(hostService.getHostsByIp(host1Address))
204 .andReturn(Sets.newHashSet(host1)).anyTimes();
Pavlin Radoslavov33f228a2014-10-27 19:33:16 -0700205 hostService.startMonitoringIp(host1Address);
Jonathan Hart31582d12014-10-22 13:52:41 -0700206 expectLastCall().anyTimes();
207
208
Pavlin Radoslavov33f228a2014-10-27 19:33:16 -0700209 IpAddress host2Address = IpAddress.valueOf("192.168.20.1");
Jonathan Hart31582d12014-10-22 13:52:41 -0700210 Host host2 = new DefaultHost(ProviderId.NONE, HostId.NONE,
211 MacAddress.valueOf("00:00:00:00:00:02"), VlanId.NONE,
212 new HostLocation(SW2_ETH1, 1),
Pavlin Radoslavov33f228a2014-10-27 19:33:16 -0700213 Sets.newHashSet(host2Address));
Jonathan Hart31582d12014-10-22 13:52:41 -0700214
215 expect(hostService.getHostsByIp(host2Address))
216 .andReturn(Sets.newHashSet(host2)).anyTimes();
Pavlin Radoslavov33f228a2014-10-27 19:33:16 -0700217 hostService.startMonitoringIp(host2Address);
Jonathan Hart31582d12014-10-22 13:52:41 -0700218 expectLastCall().anyTimes();
219
220
221 replay(hostService);
Pingping3855f312014-10-22 12:50:37 -0700222 }
223
224 /**
225 * This method tests adding a route entry.
226 */
227 @Test
228 public void testProcessRouteAdd() throws TestUtilsException {
Pingping3855f312014-10-22 12:50:37 -0700229 // Construct a route entry
230 RouteEntry routeEntry = new RouteEntry(
231 IpPrefix.valueOf("1.1.1.0/24"),
232 IpAddress.valueOf("192.168.10.1"));
233
234 // Construct a MultiPointToSinglePointIntent intent
235 TrafficSelector.Builder selectorBuilder =
236 DefaultTrafficSelector.builder();
237 selectorBuilder.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(
238 routeEntry.prefix());
239
240 TrafficTreatment.Builder treatmentBuilder =
241 DefaultTrafficTreatment.builder();
242 treatmentBuilder.setEthDst(MacAddress.valueOf("00:00:00:00:00:01"));
243
244 Set<ConnectPoint> ingressPoints = new HashSet<ConnectPoint>();
Jonathan Hart31582d12014-10-22 13:52:41 -0700245 ingressPoints.add(SW2_ETH1);
246 ingressPoints.add(SW3_ETH1);
Pingping3855f312014-10-22 12:50:37 -0700247
248 MultiPointToSinglePointIntent intent =
249 new MultiPointToSinglePointIntent(APPID,
250 selectorBuilder.build(), treatmentBuilder.build(),
Jonathan Hart31582d12014-10-22 13:52:41 -0700251 ingressPoints, SW1_ETH1);
Pingping3855f312014-10-22 12:50:37 -0700252
253 // Set up test expectation
254 reset(intentService);
255 intentService.submit(intent);
256 replay(intentService);
257
258 // Call the processRouteAdd() method in Router class
259 router.leaderChanged(true);
260 TestUtils.setField(router, "isActivatedLeader", true);
261 router.processRouteAdd(routeEntry);
262
263 // Verify
264 assertEquals(router.getRoutes().size(), 1);
265 assertTrue(router.getRoutes().contains(routeEntry));
266 assertEquals(router.getPushedRouteIntents().size(), 1);
267 assertEquals(router.getPushedRouteIntents().iterator().next(),
268 intent);
269 verify(intentService);
270 }
271
272 /**
273 * This method tests updating a route entry.
274 *
275 * @throws TestUtilsException
276 */
277 @Test
278 public void testRouteUpdate() throws TestUtilsException {
Pingping3855f312014-10-22 12:50:37 -0700279 // Firstly add a route
280 testProcessRouteAdd();
281
282 // Construct the existing route entry
283 RouteEntry routeEntry = new RouteEntry(
284 IpPrefix.valueOf("1.1.1.0/24"),
285 IpAddress.valueOf("192.168.10.1"));
286
287 // Construct the existing MultiPointToSinglePointIntent intent
288 TrafficSelector.Builder selectorBuilder =
289 DefaultTrafficSelector.builder();
290 selectorBuilder.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(
291 routeEntry.prefix());
292
293 TrafficTreatment.Builder treatmentBuilder =
294 DefaultTrafficTreatment.builder();
295 treatmentBuilder.setEthDst(MacAddress.valueOf("00:00:00:00:00:01"));
296
Pingping3855f312014-10-22 12:50:37 -0700297 Set<ConnectPoint> ingressPoints = new HashSet<ConnectPoint>();
Jonathan Hart31582d12014-10-22 13:52:41 -0700298 ingressPoints.add(SW2_ETH1);
299 ingressPoints.add(SW3_ETH1);
Pingping3855f312014-10-22 12:50:37 -0700300
301 MultiPointToSinglePointIntent intent =
302 new MultiPointToSinglePointIntent(APPID,
303 selectorBuilder.build(), treatmentBuilder.build(),
Jonathan Hart31582d12014-10-22 13:52:41 -0700304 ingressPoints, SW1_ETH1);
Pingping3855f312014-10-22 12:50:37 -0700305
306 // Start to construct a new route entry and new intent
307 RouteEntry routeEntryUpdate = new RouteEntry(
308 IpPrefix.valueOf("1.1.1.0/24"),
309 IpAddress.valueOf("192.168.20.1"));
310
311 // Construct a new MultiPointToSinglePointIntent intent
312 TrafficSelector.Builder selectorBuilderNew =
313 DefaultTrafficSelector.builder();
314 selectorBuilderNew.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(
315 routeEntryUpdate.prefix());
316
317 TrafficTreatment.Builder treatmentBuilderNew =
318 DefaultTrafficTreatment.builder();
319 treatmentBuilderNew.setEthDst(MacAddress.valueOf("00:00:00:00:00:02"));
320
Pingping3855f312014-10-22 12:50:37 -0700321
322 Set<ConnectPoint> ingressPointsNew = new HashSet<ConnectPoint>();
Jonathan Hart31582d12014-10-22 13:52:41 -0700323 ingressPointsNew.add(SW1_ETH1);
324 ingressPointsNew.add(SW3_ETH1);
Pingping3855f312014-10-22 12:50:37 -0700325
326 MultiPointToSinglePointIntent intentNew =
327 new MultiPointToSinglePointIntent(APPID,
328 selectorBuilderNew.build(),
329 treatmentBuilderNew.build(),
Jonathan Hart31582d12014-10-22 13:52:41 -0700330 ingressPointsNew, SW2_ETH1);
Pingping3855f312014-10-22 12:50:37 -0700331
332 // Set up test expectation
333 reset(intentService);
334 intentService.withdraw(intent);
335 intentService.submit(intentNew);
336 replay(intentService);
337
338 // Call the processRouteAdd() method in Router class
339 router.leaderChanged(true);
340 TestUtils.setField(router, "isActivatedLeader", true);
341 router.processRouteAdd(routeEntryUpdate);
342
343 // Verify
344 assertEquals(router.getRoutes().size(), 1);
345 assertTrue(router.getRoutes().contains(routeEntryUpdate));
346 assertEquals(router.getPushedRouteIntents().size(), 1);
347 assertEquals(router.getPushedRouteIntents().iterator().next(),
348 intentNew);
349 verify(intentService);
350 }
351
352 /**
353 * This method tests deleting a route entry.
354 */
355 @Test
356 public void testProcessRouteDelete() throws TestUtilsException {
Pingping3855f312014-10-22 12:50:37 -0700357 // Firstly add a route
358 testProcessRouteAdd();
359
360 // Construct the existing route entry
361 RouteEntry routeEntry = new RouteEntry(
362 IpPrefix.valueOf("1.1.1.0/24"),
363 IpAddress.valueOf("192.168.10.1"));
364
365 // Construct the existing MultiPointToSinglePointIntent intent
366 TrafficSelector.Builder selectorBuilder =
367 DefaultTrafficSelector.builder();
368 selectorBuilder.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(
369 routeEntry.prefix());
370
371 TrafficTreatment.Builder treatmentBuilder =
372 DefaultTrafficTreatment.builder();
373 treatmentBuilder.setEthDst(MacAddress.valueOf("00:00:00:00:00:01"));
374
Pingping3855f312014-10-22 12:50:37 -0700375 Set<ConnectPoint> ingressPoints = new HashSet<ConnectPoint>();
Jonathan Hart31582d12014-10-22 13:52:41 -0700376 ingressPoints.add(SW2_ETH1);
377 ingressPoints.add(SW3_ETH1);
Pingping3855f312014-10-22 12:50:37 -0700378
379 MultiPointToSinglePointIntent intent =
380 new MultiPointToSinglePointIntent(APPID,
381 selectorBuilder.build(), treatmentBuilder.build(),
Jonathan Hart31582d12014-10-22 13:52:41 -0700382 ingressPoints, SW1_ETH1);
Pingping3855f312014-10-22 12:50:37 -0700383
384 // Set up expectation
385 reset(intentService);
386 intentService.withdraw(intent);
387 replay(intentService);
388
389 // Call route deleting method in Router class
390 router.leaderChanged(true);
391 TestUtils.setField(router, "isActivatedLeader", true);
392 router.processRouteDelete(routeEntry);
393
394 // Verify
395 assertEquals(router.getRoutes().size(), 0);
396 assertEquals(router.getPushedRouteIntents().size(), 0);
397 verify(intentService);
398 }
399
400 /**
401 * This method tests when the next hop of a route is the local BGP speaker.
402 *
403 * @throws TestUtilsException
404 */
405 @Test
406 public void testLocalRouteAdd() throws TestUtilsException {
Pingping3855f312014-10-22 12:50:37 -0700407 // Construct a route entry, the next hop is the local BGP speaker
408 RouteEntry routeEntry = new RouteEntry(
409 IpPrefix.valueOf("1.1.1.0/24"), IpAddress.valueOf("0.0.0.0"));
410
411 // Reset intentService to check whether the submit method is called
412 reset(intentService);
413 replay(intentService);
414
415 // Call the processRouteAdd() method in Router class
416 router.leaderChanged(true);
417 TestUtils.setField(router, "isActivatedLeader", true);
418 router.processRouteAdd(routeEntry);
419
420 // Verify
421 assertEquals(router.getRoutes().size(), 1);
422 assertTrue(router.getRoutes().contains(routeEntry));
423 assertEquals(router.getPushedRouteIntents().size(), 0);
424 verify(intentService);
425 }
426}