blob: add4f796d205336a8eaad6c024a82943b190f460 [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;
54import org.onlab.onos.net.intent.IntentService;
55import org.onlab.onos.net.intent.MultiPointToSinglePointIntent;
56import org.onlab.onos.net.provider.ProviderId;
57import org.onlab.onos.sdnip.config.BgpPeer;
58import org.onlab.onos.sdnip.config.Interface;
59import org.onlab.onos.sdnip.config.SdnIpConfigService;
60import org.onlab.packet.Ethernet;
61import org.onlab.packet.IpAddress;
62import org.onlab.packet.IpPrefix;
63import 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.
71 */
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
Jonathan Hart31582d12014-10-22 13:52:41 -0700153 Interface sw1Eth1 = new Interface(SW1_ETH1,
154 Sets.newHashSet(IpPrefix.valueOf("192.168.10.101/24")),
155 MacAddress.valueOf("00:00:00:00:00:01"));
Pingping3855f312014-10-22 12:50:37 -0700156
Jonathan Hart31582d12014-10-22 13:52:41 -0700157 expect(interfaceService.getInterface(SW1_ETH1)).andReturn(sw1Eth1).anyTimes();
158 interfaces.add(sw1Eth1);
Pingping3855f312014-10-22 12:50:37 -0700159
Jonathan Hart31582d12014-10-22 13:52:41 -0700160 Interface sw2Eth1 = new Interface(SW2_ETH1,
161 Sets.newHashSet(IpPrefix.valueOf("192.168.20.101/24")),
162 MacAddress.valueOf("00:00:00:00:00:02"));
Pingping3855f312014-10-22 12:50:37 -0700163
Jonathan Hart31582d12014-10-22 13:52:41 -0700164 expect(interfaceService.getInterface(SW2_ETH1)).andReturn(sw2Eth1).anyTimes();
165 interfaces.add(sw2Eth1);
166
167 Interface sw3Eth1 = new Interface(SW3_ETH1,
168 Sets.newHashSet(IpPrefix.valueOf("192.168.30.101/24")),
169 MacAddress.valueOf("00:00:00:00:00:03"));
170
171 expect(interfaceService.getInterface(SW3_ETH1)).andReturn(sw3Eth1).anyTimes();
172 interfaces.add(sw3Eth1);
173
174 expect(interfaceService.getInterfaces()).andReturn(interfaces).anyTimes();
175
176 replay(interfaceService);
177 }
178
179 /**
180 * Sets up the host service with details of some hosts.
181 */
182 private void setUpHostService() {
183 hostService = createMock(HostService.class);
184
185 hostService.addListener(anyObject(HostListener.class));
186 expectLastCall().anyTimes();
187
188 IpPrefix host1Address = IpPrefix.valueOf("192.168.10.1/32");
189 Host host1 = new DefaultHost(ProviderId.NONE, HostId.NONE,
190 MacAddress.valueOf("00:00:00:00:00:01"), VlanId.NONE,
191 new HostLocation(SW1_ETH1, 1),
192 Sets.newHashSet(host1Address));
193
194 expect(hostService.getHostsByIp(host1Address))
195 .andReturn(Sets.newHashSet(host1)).anyTimes();
196 hostService.startMonitoringIp(host1Address.toIpAddress());
197 expectLastCall().anyTimes();
198
199
200 IpPrefix host2Address = IpPrefix.valueOf("192.168.20.1/32");
201 Host host2 = new DefaultHost(ProviderId.NONE, HostId.NONE,
202 MacAddress.valueOf("00:00:00:00:00:02"), VlanId.NONE,
203 new HostLocation(SW2_ETH1, 1),
204 Sets.newHashSet(host2Address));
205
206 expect(hostService.getHostsByIp(host2Address))
207 .andReturn(Sets.newHashSet(host2)).anyTimes();
208 hostService.startMonitoringIp(host2Address.toIpAddress());
209 expectLastCall().anyTimes();
210
211
212 replay(hostService);
Pingping3855f312014-10-22 12:50:37 -0700213 }
214
215 /**
216 * This method tests adding a route entry.
217 */
218 @Test
219 public void testProcessRouteAdd() throws TestUtilsException {
Pingping3855f312014-10-22 12:50:37 -0700220 // Construct a route entry
221 RouteEntry routeEntry = new RouteEntry(
222 IpPrefix.valueOf("1.1.1.0/24"),
223 IpAddress.valueOf("192.168.10.1"));
224
225 // Construct a MultiPointToSinglePointIntent intent
226 TrafficSelector.Builder selectorBuilder =
227 DefaultTrafficSelector.builder();
228 selectorBuilder.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(
229 routeEntry.prefix());
230
231 TrafficTreatment.Builder treatmentBuilder =
232 DefaultTrafficTreatment.builder();
233 treatmentBuilder.setEthDst(MacAddress.valueOf("00:00:00:00:00:01"));
234
235 Set<ConnectPoint> ingressPoints = new HashSet<ConnectPoint>();
Jonathan Hart31582d12014-10-22 13:52:41 -0700236 ingressPoints.add(SW2_ETH1);
237 ingressPoints.add(SW3_ETH1);
Pingping3855f312014-10-22 12:50:37 -0700238
239 MultiPointToSinglePointIntent intent =
240 new MultiPointToSinglePointIntent(APPID,
241 selectorBuilder.build(), treatmentBuilder.build(),
Jonathan Hart31582d12014-10-22 13:52:41 -0700242 ingressPoints, SW1_ETH1);
Pingping3855f312014-10-22 12:50:37 -0700243
244 // Set up test expectation
245 reset(intentService);
246 intentService.submit(intent);
247 replay(intentService);
248
249 // Call the processRouteAdd() method in Router class
250 router.leaderChanged(true);
251 TestUtils.setField(router, "isActivatedLeader", true);
252 router.processRouteAdd(routeEntry);
253
254 // Verify
255 assertEquals(router.getRoutes().size(), 1);
256 assertTrue(router.getRoutes().contains(routeEntry));
257 assertEquals(router.getPushedRouteIntents().size(), 1);
258 assertEquals(router.getPushedRouteIntents().iterator().next(),
259 intent);
260 verify(intentService);
261 }
262
263 /**
264 * This method tests updating a route entry.
265 *
266 * @throws TestUtilsException
267 */
268 @Test
269 public void testRouteUpdate() throws TestUtilsException {
Pingping3855f312014-10-22 12:50:37 -0700270 // Firstly add a route
271 testProcessRouteAdd();
272
273 // Construct the existing route entry
274 RouteEntry routeEntry = new RouteEntry(
275 IpPrefix.valueOf("1.1.1.0/24"),
276 IpAddress.valueOf("192.168.10.1"));
277
278 // Construct the existing MultiPointToSinglePointIntent intent
279 TrafficSelector.Builder selectorBuilder =
280 DefaultTrafficSelector.builder();
281 selectorBuilder.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(
282 routeEntry.prefix());
283
284 TrafficTreatment.Builder treatmentBuilder =
285 DefaultTrafficTreatment.builder();
286 treatmentBuilder.setEthDst(MacAddress.valueOf("00:00:00:00:00:01"));
287
Pingping3855f312014-10-22 12:50:37 -0700288 Set<ConnectPoint> ingressPoints = new HashSet<ConnectPoint>();
Jonathan Hart31582d12014-10-22 13:52:41 -0700289 ingressPoints.add(SW2_ETH1);
290 ingressPoints.add(SW3_ETH1);
Pingping3855f312014-10-22 12:50:37 -0700291
292 MultiPointToSinglePointIntent intent =
293 new MultiPointToSinglePointIntent(APPID,
294 selectorBuilder.build(), treatmentBuilder.build(),
Jonathan Hart31582d12014-10-22 13:52:41 -0700295 ingressPoints, SW1_ETH1);
Pingping3855f312014-10-22 12:50:37 -0700296
297 // Start to construct a new route entry and new intent
298 RouteEntry routeEntryUpdate = new RouteEntry(
299 IpPrefix.valueOf("1.1.1.0/24"),
300 IpAddress.valueOf("192.168.20.1"));
301
302 // Construct a new MultiPointToSinglePointIntent intent
303 TrafficSelector.Builder selectorBuilderNew =
304 DefaultTrafficSelector.builder();
305 selectorBuilderNew.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(
306 routeEntryUpdate.prefix());
307
308 TrafficTreatment.Builder treatmentBuilderNew =
309 DefaultTrafficTreatment.builder();
310 treatmentBuilderNew.setEthDst(MacAddress.valueOf("00:00:00:00:00:02"));
311
Pingping3855f312014-10-22 12:50:37 -0700312
313 Set<ConnectPoint> ingressPointsNew = new HashSet<ConnectPoint>();
Jonathan Hart31582d12014-10-22 13:52:41 -0700314 ingressPointsNew.add(SW1_ETH1);
315 ingressPointsNew.add(SW3_ETH1);
Pingping3855f312014-10-22 12:50:37 -0700316
317 MultiPointToSinglePointIntent intentNew =
318 new MultiPointToSinglePointIntent(APPID,
319 selectorBuilderNew.build(),
320 treatmentBuilderNew.build(),
Jonathan Hart31582d12014-10-22 13:52:41 -0700321 ingressPointsNew, SW2_ETH1);
Pingping3855f312014-10-22 12:50:37 -0700322
323 // Set up test expectation
324 reset(intentService);
325 intentService.withdraw(intent);
326 intentService.submit(intentNew);
327 replay(intentService);
328
329 // Call the processRouteAdd() method in Router class
330 router.leaderChanged(true);
331 TestUtils.setField(router, "isActivatedLeader", true);
332 router.processRouteAdd(routeEntryUpdate);
333
334 // Verify
335 assertEquals(router.getRoutes().size(), 1);
336 assertTrue(router.getRoutes().contains(routeEntryUpdate));
337 assertEquals(router.getPushedRouteIntents().size(), 1);
338 assertEquals(router.getPushedRouteIntents().iterator().next(),
339 intentNew);
340 verify(intentService);
341 }
342
343 /**
344 * This method tests deleting a route entry.
345 */
346 @Test
347 public void testProcessRouteDelete() throws TestUtilsException {
Pingping3855f312014-10-22 12:50:37 -0700348 // Firstly add a route
349 testProcessRouteAdd();
350
351 // Construct the existing route entry
352 RouteEntry routeEntry = new RouteEntry(
353 IpPrefix.valueOf("1.1.1.0/24"),
354 IpAddress.valueOf("192.168.10.1"));
355
356 // Construct the existing MultiPointToSinglePointIntent intent
357 TrafficSelector.Builder selectorBuilder =
358 DefaultTrafficSelector.builder();
359 selectorBuilder.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(
360 routeEntry.prefix());
361
362 TrafficTreatment.Builder treatmentBuilder =
363 DefaultTrafficTreatment.builder();
364 treatmentBuilder.setEthDst(MacAddress.valueOf("00:00:00:00:00:01"));
365
Pingping3855f312014-10-22 12:50:37 -0700366 Set<ConnectPoint> ingressPoints = new HashSet<ConnectPoint>();
Jonathan Hart31582d12014-10-22 13:52:41 -0700367 ingressPoints.add(SW2_ETH1);
368 ingressPoints.add(SW3_ETH1);
Pingping3855f312014-10-22 12:50:37 -0700369
370 MultiPointToSinglePointIntent intent =
371 new MultiPointToSinglePointIntent(APPID,
372 selectorBuilder.build(), treatmentBuilder.build(),
Jonathan Hart31582d12014-10-22 13:52:41 -0700373 ingressPoints, SW1_ETH1);
Pingping3855f312014-10-22 12:50:37 -0700374
375 // Set up expectation
376 reset(intentService);
377 intentService.withdraw(intent);
378 replay(intentService);
379
380 // Call route deleting method in Router class
381 router.leaderChanged(true);
382 TestUtils.setField(router, "isActivatedLeader", true);
383 router.processRouteDelete(routeEntry);
384
385 // Verify
386 assertEquals(router.getRoutes().size(), 0);
387 assertEquals(router.getPushedRouteIntents().size(), 0);
388 verify(intentService);
389 }
390
391 /**
392 * This method tests when the next hop of a route is the local BGP speaker.
393 *
394 * @throws TestUtilsException
395 */
396 @Test
397 public void testLocalRouteAdd() throws TestUtilsException {
Pingping3855f312014-10-22 12:50:37 -0700398 // Construct a route entry, the next hop is the local BGP speaker
399 RouteEntry routeEntry = new RouteEntry(
400 IpPrefix.valueOf("1.1.1.0/24"), IpAddress.valueOf("0.0.0.0"));
401
402 // Reset intentService to check whether the submit method is called
403 reset(intentService);
404 replay(intentService);
405
406 // Call the processRouteAdd() method in Router class
407 router.leaderChanged(true);
408 TestUtils.setField(router, "isActivatedLeader", true);
409 router.processRouteAdd(routeEntry);
410
411 // Verify
412 assertEquals(router.getRoutes().size(), 1);
413 assertTrue(router.getRoutes().contains(routeEntry));
414 assertEquals(router.getPushedRouteIntents().size(), 0);
415 verify(intentService);
416 }
417}