blob: c61e1ec7a7a349317bdca24cc51990c0c4908b43 [file] [log] [blame]
Pingping3855f312014-10-22 12:50:37 -07001package org.onlab.onos.sdnip;
2
Jonathan Hart31582d12014-10-22 13:52:41 -07003import static org.easymock.EasyMock.anyObject;
Pingping3855f312014-10-22 12:50:37 -07004import static org.easymock.EasyMock.createMock;
5import static org.easymock.EasyMock.expect;
Jonathan Hart31582d12014-10-22 13:52:41 -07006import static org.easymock.EasyMock.expectLastCall;
Pingping3855f312014-10-22 12:50:37 -07007import static org.easymock.EasyMock.replay;
8import static org.easymock.EasyMock.reset;
9import static org.easymock.EasyMock.verify;
10import static org.junit.Assert.assertEquals;
11import static org.junit.Assert.assertTrue;
12
13import java.util.HashMap;
14import java.util.HashSet;
15import java.util.Map;
16import java.util.Set;
17
18import org.junit.Before;
19import org.junit.Test;
Pavlin Radoslavovd26f57a2014-10-23 17:19:45 -070020import org.onlab.junit.TestUtils;
21import org.onlab.junit.TestUtils.TestUtilsException;
Pingping3855f312014-10-22 12:50:37 -070022import org.onlab.onos.ApplicationId;
23import org.onlab.onos.net.ConnectPoint;
24import org.onlab.onos.net.DefaultHost;
25import org.onlab.onos.net.DeviceId;
26import org.onlab.onos.net.Host;
27import org.onlab.onos.net.HostId;
28import org.onlab.onos.net.HostLocation;
29import org.onlab.onos.net.PortNumber;
30import org.onlab.onos.net.flow.DefaultTrafficSelector;
31import org.onlab.onos.net.flow.DefaultTrafficTreatment;
32import org.onlab.onos.net.flow.TrafficSelector;
33import org.onlab.onos.net.flow.TrafficTreatment;
Jonathan Hart31582d12014-10-22 13:52:41 -070034import org.onlab.onos.net.host.HostListener;
Pingping3855f312014-10-22 12:50:37 -070035import org.onlab.onos.net.host.HostService;
36import org.onlab.onos.net.intent.IntentService;
37import org.onlab.onos.net.intent.MultiPointToSinglePointIntent;
38import org.onlab.onos.net.provider.ProviderId;
39import org.onlab.onos.sdnip.config.BgpPeer;
40import org.onlab.onos.sdnip.config.Interface;
41import org.onlab.onos.sdnip.config.SdnIpConfigService;
42import org.onlab.packet.Ethernet;
43import org.onlab.packet.IpAddress;
44import org.onlab.packet.IpPrefix;
45import org.onlab.packet.MacAddress;
46import org.onlab.packet.VlanId;
Pingping3855f312014-10-22 12:50:37 -070047
48import com.google.common.collect.Sets;
49
50/**
51 * This class tests adding a route, updating a route, deleting a route,
52 * and adding a route whose next hop is the local BGP speaker.
53 */
54public class RouterTest {
55
56 private SdnIpConfigService sdnIpConfigService;
57 private InterfaceService interfaceService;
58 private IntentService intentService;
59 private HostService hostService;
60
Jonathan Hart31582d12014-10-22 13:52:41 -070061 private static final ConnectPoint SW1_ETH1 = new ConnectPoint(
62 DeviceId.deviceId("of:0000000000000001"),
63 PortNumber.portNumber(1));
64
65 private static final ConnectPoint SW2_ETH1 = new ConnectPoint(
66 DeviceId.deviceId("of:0000000000000002"),
67 PortNumber.portNumber(1));
68
69 private static final ConnectPoint SW3_ETH1 = new ConnectPoint(
70 DeviceId.deviceId("of:0000000000000003"),
71 PortNumber.portNumber(1));
Pingping3855f312014-10-22 12:50:37 -070072
73 private static final ApplicationId APPID = new ApplicationId() {
74 @Override
75 public short id() {
76 return 1;
77 }
78
79 @Override
80 public String name() {
81 return "SDNIP";
82 }
83 };
84
85 private Router router;
86
87 @Before
88 public void setUp() throws Exception {
Jonathan Hart31582d12014-10-22 13:52:41 -070089 setUpBgpPeers();
Pingping3855f312014-10-22 12:50:37 -070090
Jonathan Hart31582d12014-10-22 13:52:41 -070091 setUpInterfaceService();
92 setUpHostService();
Pingping3855f312014-10-22 12:50:37 -070093
94 intentService = createMock(IntentService.class);
Pingping3855f312014-10-22 12:50:37 -070095
96 router = new Router(APPID, intentService,
97 hostService, sdnIpConfigService, interfaceService);
98 }
99
100 /**
101 * Sets up BGP peers in external networks.
Pingping3855f312014-10-22 12:50:37 -0700102 */
Jonathan Hart31582d12014-10-22 13:52:41 -0700103 private void setUpBgpPeers() {
Pingping3855f312014-10-22 12:50:37 -0700104
Jonathan Hart31582d12014-10-22 13:52:41 -0700105 Map<IpAddress, BgpPeer> peers = new HashMap<>();
Pingping3855f312014-10-22 12:50:37 -0700106
107 String peerSw1Eth1 = "192.168.10.1";
Jonathan Hart31582d12014-10-22 13:52:41 -0700108 peers.put(IpAddress.valueOf(peerSw1Eth1),
Pingping3855f312014-10-22 12:50:37 -0700109 new BgpPeer("00:00:00:00:00:00:00:01", 1, peerSw1Eth1));
110
111 // Two BGP peers are connected to switch 2 port 1.
112 String peer1Sw2Eth1 = "192.168.20.1";
Jonathan Hart31582d12014-10-22 13:52:41 -0700113 peers.put(IpAddress.valueOf(peer1Sw2Eth1),
Pingping3855f312014-10-22 12:50:37 -0700114 new BgpPeer("00:00:00:00:00:00:00:02", 1, peer1Sw2Eth1));
115
116 String peer2Sw2Eth1 = "192.168.20.2";
Jonathan Hart31582d12014-10-22 13:52:41 -0700117 peers.put(IpAddress.valueOf(peer2Sw2Eth1),
Pingping3855f312014-10-22 12:50:37 -0700118 new BgpPeer("00:00:00:00:00:00:00:02", 1, peer2Sw2Eth1));
119
Jonathan Hart31582d12014-10-22 13:52:41 -0700120 sdnIpConfigService = createMock(SdnIpConfigService.class);
121 expect(sdnIpConfigService.getBgpPeers()).andReturn(peers).anyTimes();
122 replay(sdnIpConfigService);
123
Pingping3855f312014-10-22 12:50:37 -0700124 }
125
126 /**
127 * Sets up logical interfaces, which emulate the configured interfaces
128 * in SDN-IP application.
Pingping3855f312014-10-22 12:50:37 -0700129 */
Jonathan Hart31582d12014-10-22 13:52:41 -0700130 private void setUpInterfaceService() {
131 interfaceService = createMock(InterfaceService.class);
Pingping3855f312014-10-22 12:50:37 -0700132
Jonathan Hart31582d12014-10-22 13:52:41 -0700133 Set<Interface> interfaces = Sets.newHashSet();
Pingping3855f312014-10-22 12:50:37 -0700134
Jonathan Hart31582d12014-10-22 13:52:41 -0700135 Interface sw1Eth1 = new Interface(SW1_ETH1,
136 Sets.newHashSet(IpPrefix.valueOf("192.168.10.101/24")),
137 MacAddress.valueOf("00:00:00:00:00:01"));
Pingping3855f312014-10-22 12:50:37 -0700138
Jonathan Hart31582d12014-10-22 13:52:41 -0700139 expect(interfaceService.getInterface(SW1_ETH1)).andReturn(sw1Eth1).anyTimes();
140 interfaces.add(sw1Eth1);
Pingping3855f312014-10-22 12:50:37 -0700141
Jonathan Hart31582d12014-10-22 13:52:41 -0700142 Interface sw2Eth1 = new Interface(SW2_ETH1,
143 Sets.newHashSet(IpPrefix.valueOf("192.168.20.101/24")),
144 MacAddress.valueOf("00:00:00:00:00:02"));
Pingping3855f312014-10-22 12:50:37 -0700145
Jonathan Hart31582d12014-10-22 13:52:41 -0700146 expect(interfaceService.getInterface(SW2_ETH1)).andReturn(sw2Eth1).anyTimes();
147 interfaces.add(sw2Eth1);
148
149 Interface sw3Eth1 = new Interface(SW3_ETH1,
150 Sets.newHashSet(IpPrefix.valueOf("192.168.30.101/24")),
151 MacAddress.valueOf("00:00:00:00:00:03"));
152
153 expect(interfaceService.getInterface(SW3_ETH1)).andReturn(sw3Eth1).anyTimes();
154 interfaces.add(sw3Eth1);
155
156 expect(interfaceService.getInterfaces()).andReturn(interfaces).anyTimes();
157
158 replay(interfaceService);
159 }
160
161 /**
162 * Sets up the host service with details of some hosts.
163 */
164 private void setUpHostService() {
165 hostService = createMock(HostService.class);
166
167 hostService.addListener(anyObject(HostListener.class));
168 expectLastCall().anyTimes();
169
170 IpPrefix host1Address = IpPrefix.valueOf("192.168.10.1/32");
171 Host host1 = new DefaultHost(ProviderId.NONE, HostId.NONE,
172 MacAddress.valueOf("00:00:00:00:00:01"), VlanId.NONE,
173 new HostLocation(SW1_ETH1, 1),
174 Sets.newHashSet(host1Address));
175
176 expect(hostService.getHostsByIp(host1Address))
177 .andReturn(Sets.newHashSet(host1)).anyTimes();
178 hostService.startMonitoringIp(host1Address.toIpAddress());
179 expectLastCall().anyTimes();
180
181
182 IpPrefix host2Address = IpPrefix.valueOf("192.168.20.1/32");
183 Host host2 = new DefaultHost(ProviderId.NONE, HostId.NONE,
184 MacAddress.valueOf("00:00:00:00:00:02"), VlanId.NONE,
185 new HostLocation(SW2_ETH1, 1),
186 Sets.newHashSet(host2Address));
187
188 expect(hostService.getHostsByIp(host2Address))
189 .andReturn(Sets.newHashSet(host2)).anyTimes();
190 hostService.startMonitoringIp(host2Address.toIpAddress());
191 expectLastCall().anyTimes();
192
193
194 replay(hostService);
Pingping3855f312014-10-22 12:50:37 -0700195 }
196
197 /**
198 * This method tests adding a route entry.
199 */
200 @Test
201 public void testProcessRouteAdd() throws TestUtilsException {
Pingping3855f312014-10-22 12:50:37 -0700202 // Construct a route entry
203 RouteEntry routeEntry = new RouteEntry(
204 IpPrefix.valueOf("1.1.1.0/24"),
205 IpAddress.valueOf("192.168.10.1"));
206
207 // Construct a MultiPointToSinglePointIntent intent
208 TrafficSelector.Builder selectorBuilder =
209 DefaultTrafficSelector.builder();
210 selectorBuilder.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(
211 routeEntry.prefix());
212
213 TrafficTreatment.Builder treatmentBuilder =
214 DefaultTrafficTreatment.builder();
215 treatmentBuilder.setEthDst(MacAddress.valueOf("00:00:00:00:00:01"));
216
217 Set<ConnectPoint> ingressPoints = new HashSet<ConnectPoint>();
Jonathan Hart31582d12014-10-22 13:52:41 -0700218 ingressPoints.add(SW2_ETH1);
219 ingressPoints.add(SW3_ETH1);
Pingping3855f312014-10-22 12:50:37 -0700220
221 MultiPointToSinglePointIntent intent =
222 new MultiPointToSinglePointIntent(APPID,
223 selectorBuilder.build(), treatmentBuilder.build(),
Jonathan Hart31582d12014-10-22 13:52:41 -0700224 ingressPoints, SW1_ETH1);
Pingping3855f312014-10-22 12:50:37 -0700225
226 // Set up test expectation
227 reset(intentService);
228 intentService.submit(intent);
229 replay(intentService);
230
231 // Call the processRouteAdd() method in Router class
232 router.leaderChanged(true);
233 TestUtils.setField(router, "isActivatedLeader", true);
234 router.processRouteAdd(routeEntry);
235
236 // Verify
237 assertEquals(router.getRoutes().size(), 1);
238 assertTrue(router.getRoutes().contains(routeEntry));
239 assertEquals(router.getPushedRouteIntents().size(), 1);
240 assertEquals(router.getPushedRouteIntents().iterator().next(),
241 intent);
242 verify(intentService);
243 }
244
245 /**
246 * This method tests updating a route entry.
247 *
248 * @throws TestUtilsException
249 */
250 @Test
251 public void testRouteUpdate() throws TestUtilsException {
Pingping3855f312014-10-22 12:50:37 -0700252 // Firstly add a route
253 testProcessRouteAdd();
254
255 // Construct the existing route entry
256 RouteEntry routeEntry = new RouteEntry(
257 IpPrefix.valueOf("1.1.1.0/24"),
258 IpAddress.valueOf("192.168.10.1"));
259
260 // Construct the existing MultiPointToSinglePointIntent intent
261 TrafficSelector.Builder selectorBuilder =
262 DefaultTrafficSelector.builder();
263 selectorBuilder.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(
264 routeEntry.prefix());
265
266 TrafficTreatment.Builder treatmentBuilder =
267 DefaultTrafficTreatment.builder();
268 treatmentBuilder.setEthDst(MacAddress.valueOf("00:00:00:00:00:01"));
269
Pingping3855f312014-10-22 12:50:37 -0700270 Set<ConnectPoint> ingressPoints = new HashSet<ConnectPoint>();
Jonathan Hart31582d12014-10-22 13:52:41 -0700271 ingressPoints.add(SW2_ETH1);
272 ingressPoints.add(SW3_ETH1);
Pingping3855f312014-10-22 12:50:37 -0700273
274 MultiPointToSinglePointIntent intent =
275 new MultiPointToSinglePointIntent(APPID,
276 selectorBuilder.build(), treatmentBuilder.build(),
Jonathan Hart31582d12014-10-22 13:52:41 -0700277 ingressPoints, SW1_ETH1);
Pingping3855f312014-10-22 12:50:37 -0700278
279 // Start to construct a new route entry and new intent
280 RouteEntry routeEntryUpdate = new RouteEntry(
281 IpPrefix.valueOf("1.1.1.0/24"),
282 IpAddress.valueOf("192.168.20.1"));
283
284 // Construct a new MultiPointToSinglePointIntent intent
285 TrafficSelector.Builder selectorBuilderNew =
286 DefaultTrafficSelector.builder();
287 selectorBuilderNew.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(
288 routeEntryUpdate.prefix());
289
290 TrafficTreatment.Builder treatmentBuilderNew =
291 DefaultTrafficTreatment.builder();
292 treatmentBuilderNew.setEthDst(MacAddress.valueOf("00:00:00:00:00:02"));
293
Pingping3855f312014-10-22 12:50:37 -0700294
295 Set<ConnectPoint> ingressPointsNew = new HashSet<ConnectPoint>();
Jonathan Hart31582d12014-10-22 13:52:41 -0700296 ingressPointsNew.add(SW1_ETH1);
297 ingressPointsNew.add(SW3_ETH1);
Pingping3855f312014-10-22 12:50:37 -0700298
299 MultiPointToSinglePointIntent intentNew =
300 new MultiPointToSinglePointIntent(APPID,
301 selectorBuilderNew.build(),
302 treatmentBuilderNew.build(),
Jonathan Hart31582d12014-10-22 13:52:41 -0700303 ingressPointsNew, SW2_ETH1);
Pingping3855f312014-10-22 12:50:37 -0700304
305 // Set up test expectation
306 reset(intentService);
307 intentService.withdraw(intent);
308 intentService.submit(intentNew);
309 replay(intentService);
310
311 // Call the processRouteAdd() method in Router class
312 router.leaderChanged(true);
313 TestUtils.setField(router, "isActivatedLeader", true);
314 router.processRouteAdd(routeEntryUpdate);
315
316 // Verify
317 assertEquals(router.getRoutes().size(), 1);
318 assertTrue(router.getRoutes().contains(routeEntryUpdate));
319 assertEquals(router.getPushedRouteIntents().size(), 1);
320 assertEquals(router.getPushedRouteIntents().iterator().next(),
321 intentNew);
322 verify(intentService);
323 }
324
325 /**
326 * This method tests deleting a route entry.
327 */
328 @Test
329 public void testProcessRouteDelete() throws TestUtilsException {
Pingping3855f312014-10-22 12:50:37 -0700330 // Firstly add a route
331 testProcessRouteAdd();
332
333 // Construct the existing route entry
334 RouteEntry routeEntry = new RouteEntry(
335 IpPrefix.valueOf("1.1.1.0/24"),
336 IpAddress.valueOf("192.168.10.1"));
337
338 // Construct the existing MultiPointToSinglePointIntent intent
339 TrafficSelector.Builder selectorBuilder =
340 DefaultTrafficSelector.builder();
341 selectorBuilder.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(
342 routeEntry.prefix());
343
344 TrafficTreatment.Builder treatmentBuilder =
345 DefaultTrafficTreatment.builder();
346 treatmentBuilder.setEthDst(MacAddress.valueOf("00:00:00:00:00:01"));
347
Pingping3855f312014-10-22 12:50:37 -0700348 Set<ConnectPoint> ingressPoints = new HashSet<ConnectPoint>();
Jonathan Hart31582d12014-10-22 13:52:41 -0700349 ingressPoints.add(SW2_ETH1);
350 ingressPoints.add(SW3_ETH1);
Pingping3855f312014-10-22 12:50:37 -0700351
352 MultiPointToSinglePointIntent intent =
353 new MultiPointToSinglePointIntent(APPID,
354 selectorBuilder.build(), treatmentBuilder.build(),
Jonathan Hart31582d12014-10-22 13:52:41 -0700355 ingressPoints, SW1_ETH1);
Pingping3855f312014-10-22 12:50:37 -0700356
357 // Set up expectation
358 reset(intentService);
359 intentService.withdraw(intent);
360 replay(intentService);
361
362 // Call route deleting method in Router class
363 router.leaderChanged(true);
364 TestUtils.setField(router, "isActivatedLeader", true);
365 router.processRouteDelete(routeEntry);
366
367 // Verify
368 assertEquals(router.getRoutes().size(), 0);
369 assertEquals(router.getPushedRouteIntents().size(), 0);
370 verify(intentService);
371 }
372
373 /**
374 * This method tests when the next hop of a route is the local BGP speaker.
375 *
376 * @throws TestUtilsException
377 */
378 @Test
379 public void testLocalRouteAdd() throws TestUtilsException {
Pingping3855f312014-10-22 12:50:37 -0700380 // Construct a route entry, the next hop is the local BGP speaker
381 RouteEntry routeEntry = new RouteEntry(
382 IpPrefix.valueOf("1.1.1.0/24"), IpAddress.valueOf("0.0.0.0"));
383
384 // Reset intentService to check whether the submit method is called
385 reset(intentService);
386 replay(intentService);
387
388 // Call the processRouteAdd() method in Router class
389 router.leaderChanged(true);
390 TestUtils.setField(router, "isActivatedLeader", true);
391 router.processRouteAdd(routeEntry);
392
393 // Verify
394 assertEquals(router.getRoutes().size(), 1);
395 assertTrue(router.getRoutes().contains(routeEntry));
396 assertEquals(router.getPushedRouteIntents().size(), 0);
397 verify(intentService);
398 }
399}