blob: 400015816a78aa53d7812f6c86f2e1a7e6362426 [file] [log] [blame]
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07001/*
2 * Copyright 2014 Open Networking Laboratory
3 *
4 * 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
7 *
8 * 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.
15 */
Pingpingfc584672014-10-23 10:51:19 -070016package org.onlab.onos.sdnip;
17
18import static org.easymock.EasyMock.anyObject;
19import static org.easymock.EasyMock.createMock;
20import static org.easymock.EasyMock.expect;
21import static org.easymock.EasyMock.replay;
22import static org.easymock.EasyMock.reset;
23import static org.easymock.EasyMock.verify;
24import static org.junit.Assert.assertEquals;
25import static org.junit.Assert.assertTrue;
26
27import java.util.HashMap;
28import java.util.HashSet;
29import java.util.Map;
30import java.util.Set;
31import java.util.concurrent.ConcurrentHashMap;
32
33import org.junit.Before;
Brian O'Connor520c0522014-11-23 23:50:47 -080034import org.junit.Ignore;
Pingpingfc584672014-10-23 10:51:19 -070035import org.junit.Test;
36import org.onlab.junit.TestUtils;
37import org.onlab.junit.TestUtils.TestUtilsException;
Thomas Vachuskae0f804a2014-10-27 23:40:48 -070038import org.onlab.onos.core.ApplicationId;
Pingpingfc584672014-10-23 10:51:19 -070039import org.onlab.onos.net.ConnectPoint;
40import org.onlab.onos.net.DefaultHost;
41import org.onlab.onos.net.DeviceId;
42import org.onlab.onos.net.Host;
43import org.onlab.onos.net.HostId;
44import org.onlab.onos.net.HostLocation;
45import org.onlab.onos.net.PortNumber;
46import org.onlab.onos.net.flow.DefaultTrafficSelector;
47import org.onlab.onos.net.flow.DefaultTrafficTreatment;
48import org.onlab.onos.net.flow.TrafficSelector;
49import org.onlab.onos.net.flow.TrafficTreatment;
50import org.onlab.onos.net.host.HostEvent;
51import org.onlab.onos.net.host.HostService;
52import org.onlab.onos.net.host.InterfaceIpAddress;
53import org.onlab.onos.net.intent.IntentService;
54import org.onlab.onos.net.intent.MultiPointToSinglePointIntent;
Brian O'Connor520c0522014-11-23 23:50:47 -080055import org.onlab.onos.net.intent.AbstractIntentTest;
Pingpingfc584672014-10-23 10:51:19 -070056import org.onlab.onos.net.provider.ProviderId;
57import org.onlab.onos.sdnip.Router.InternalHostListener;
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;
Pavlin Radoslavov6b570732014-11-06 13:16:45 -080063import org.onlab.packet.Ip4Address;
Pingpingfc584672014-10-23 10:51:19 -070064import org.onlab.packet.IpPrefix;
Pavlin Radoslavov6b570732014-11-06 13:16:45 -080065import org.onlab.packet.Ip4Prefix;
Pingpingfc584672014-10-23 10:51:19 -070066import org.onlab.packet.MacAddress;
67import org.onlab.packet.VlanId;
68
69import com.google.common.collect.Sets;
70import com.googlecode.concurrenttrees.radix.node.concrete.DefaultByteArrayNodeFactory;
71import com.googlecode.concurrenttrees.radixinverted.ConcurrentInvertedRadixTree;
72import com.googlecode.concurrenttrees.radixinverted.InvertedRadixTree;
73
74/**
75 * This class tests adding a route, updating a route, deleting a route, and
76 * the ARP module answers the MAC address asynchronously.
77 */
Brian O'Connor520c0522014-11-23 23:50:47 -080078public class RouterTestWithAsyncArp extends AbstractIntentTest {
Pingpingfc584672014-10-23 10:51:19 -070079
80 private SdnIpConfigService sdnIpConfigService;
81 private InterfaceService interfaceService;
82 private IntentService intentService;
83 private HostService hostService;
84
85 private static final ConnectPoint SW1_ETH1 = new ConnectPoint(
86 DeviceId.deviceId("of:0000000000000001"),
87 PortNumber.portNumber(1));
88
89 private static final ConnectPoint SW2_ETH1 = new ConnectPoint(
90 DeviceId.deviceId("of:0000000000000002"),
91 PortNumber.portNumber(1));
92
93 private static final ConnectPoint SW3_ETH1 = new ConnectPoint(
94 DeviceId.deviceId("of:0000000000000003"),
95 PortNumber.portNumber(1));
96
Pavlin Radoslavova071b1e2014-11-17 13:37:57 -080097 private IntentSynchronizer intentSynchronizer;
Pingpingfc584672014-10-23 10:51:19 -070098 private Router router;
99 private InternalHostListener internalHostListener;
100
101 private static final ApplicationId APPID = new ApplicationId() {
102 @Override
103 public short id() {
104 return 1;
105 }
106
107 @Override
108 public String name() {
109 return "SDNIP";
110 }
111 };
112
113 @Before
114 public void setUp() throws Exception {
Brian O'Connor520c0522014-11-23 23:50:47 -0800115 super.setUp();
116
Pingpingfc584672014-10-23 10:51:19 -0700117 setUpSdnIpConfigService();
118 setUpInterfaceService();
119 hostService = createMock(HostService.class);
120 intentService = createMock(IntentService.class);
121
Pavlin Radoslavova071b1e2014-11-17 13:37:57 -0800122 intentSynchronizer = new IntentSynchronizer(APPID, intentService);
123 router = new Router(APPID, intentSynchronizer,
Pavlin Radoslavova7243cc2014-11-22 21:38:02 -0800124 sdnIpConfigService, interfaceService, hostService);
Pingpingfc584672014-10-23 10:51:19 -0700125 internalHostListener = router.new InternalHostListener();
126 }
127
128 /**
129 * Sets up SdnIpConfigService.
130 */
131 private void setUpSdnIpConfigService() {
132
133 sdnIpConfigService = createMock(SdnIpConfigService.class);
134
135 Map<IpAddress, BgpPeer> peers = new HashMap<>();
136
137 String peerSw1Eth1 = "192.168.10.1";
138 peers.put(IpAddress.valueOf(peerSw1Eth1),
139 new BgpPeer("00:00:00:00:00:00:00:01", 1, peerSw1Eth1));
140
141 // Two BGP peers are connected to switch 2 port 1.
142 String peer1Sw2Eth1 = "192.168.20.1";
143 peers.put(IpAddress.valueOf(peer1Sw2Eth1),
144 new BgpPeer("00:00:00:00:00:00:00:02", 1, peer1Sw2Eth1));
145
146 String peer2Sw2Eth1 = "192.168.20.2";
147 peers.put(IpAddress.valueOf(peer2Sw2Eth1),
148 new BgpPeer("00:00:00:00:00:00:00:02", 1, peer2Sw2Eth1));
149
150 expect(sdnIpConfigService.getBgpPeers()).andReturn(peers).anyTimes();
151 replay(sdnIpConfigService);
152 }
153
154 /**
155 * Sets up InterfaceService.
156 */
157 private void setUpInterfaceService() {
158
159 interfaceService = createMock(InterfaceService.class);
160
161 Set<Interface> interfaces = Sets.newHashSet();
162
163 Set<InterfaceIpAddress> interfaceIpAddresses1 = Sets.newHashSet();
164 interfaceIpAddresses1.add(new InterfaceIpAddress(
165 IpAddress.valueOf("192.168.10.101"),
166 IpPrefix.valueOf("192.168.10.0/24")));
167 Interface sw1Eth1 = new Interface(SW1_ETH1,
168 interfaceIpAddresses1, MacAddress.valueOf("00:00:00:00:00:01"));
169 interfaces.add(sw1Eth1);
170
171 Set<InterfaceIpAddress> interfaceIpAddresses2 = Sets.newHashSet();
172 interfaceIpAddresses2.add(new InterfaceIpAddress(
173 IpAddress.valueOf("192.168.20.101"),
174 IpPrefix.valueOf("192.168.20.0/24")));
175 Interface sw2Eth1 = new Interface(SW2_ETH1,
176 interfaceIpAddresses2, MacAddress.valueOf("00:00:00:00:00:02"));
177 interfaces.add(sw2Eth1);
178
179 Set<InterfaceIpAddress> interfaceIpAddresses3 = Sets.newHashSet();
180 interfaceIpAddresses3.add(new InterfaceIpAddress(
181 IpAddress.valueOf("192.168.30.101"),
182 IpPrefix.valueOf("192.168.30.0/24")));
183 Interface sw3Eth1 = new Interface(SW3_ETH1,
184 interfaceIpAddresses3, MacAddress.valueOf("00:00:00:00:00:03"));
185 interfaces.add(sw3Eth1);
186
187 expect(interfaceService.getInterface(SW1_ETH1)).andReturn(sw1Eth1).anyTimes();
188 expect(interfaceService.getInterface(SW2_ETH1)).andReturn(sw2Eth1).anyTimes();
189 expect(interfaceService.getInterface(SW3_ETH1)).andReturn(sw3Eth1).anyTimes();
190 expect(interfaceService.getInterfaces()).andReturn(interfaces).anyTimes();
191 replay(interfaceService);
192 }
193
194 /**
195 * This method tests adding a route entry.
196 */
Brian O'Connor520c0522014-11-23 23:50:47 -0800197 @Test @Ignore("needs fix from intents")
Pingpingfc584672014-10-23 10:51:19 -0700198 public void testProcessRouteAdd() throws TestUtilsException {
199
200 // Construct a route entry
201 RouteEntry routeEntry = new RouteEntry(
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800202 Ip4Prefix.valueOf("1.1.1.0/24"),
203 Ip4Address.valueOf("192.168.10.1"));
Pingpingfc584672014-10-23 10:51:19 -0700204
205 // Construct a route intent
206 MultiPointToSinglePointIntent intent = staticIntentBuilder();
207
208 // Set up test expectation
209 reset(hostService);
Pavlin Radoslavov33f228a2014-10-27 19:33:16 -0700210 expect(hostService.getHostsByIp(anyObject(IpAddress.class))).andReturn(
Pingpingfc584672014-10-23 10:51:19 -0700211 new HashSet<Host>()).anyTimes();
212 hostService.startMonitoringIp(IpAddress.valueOf("192.168.10.1"));
213 replay(hostService);
214
215 reset(intentService);
216 intentService.submit(intent);
217 replay(intentService);
218
219 // Call the processRouteAdd() method in Router class
Pavlin Radoslavova071b1e2014-11-17 13:37:57 -0800220 intentSynchronizer.leaderChanged(true);
221 TestUtils.setField(intentSynchronizer, "isActivatedLeader", true);
Pingpingfc584672014-10-23 10:51:19 -0700222 router.processRouteAdd(routeEntry);
223
224 Host host = new DefaultHost(ProviderId.NONE, HostId.NONE,
225 MacAddress.valueOf("00:00:00:00:00:01"), VlanId.NONE,
226 new HostLocation(
227 SW1_ETH1.deviceId(),
228 SW1_ETH1.port(), 1),
Pavlin Radoslavov33f228a2014-10-27 19:33:16 -0700229 Sets.newHashSet(IpAddress.valueOf("192.168.10.1")));
Pingpingfc584672014-10-23 10:51:19 -0700230 internalHostListener.event(
231 new HostEvent(HostEvent.Type.HOST_ADDED, host));
232
233 // Verify
234 assertEquals(router.getRoutes().size(), 1);
235 assertTrue(router.getRoutes().contains(routeEntry));
Pavlin Radoslavova7243cc2014-11-22 21:38:02 -0800236 assertEquals(intentSynchronizer.getRouteIntents().size(), 1);
237 assertEquals(intentSynchronizer.getRouteIntents().iterator().next(),
Pavlin Radoslavova071b1e2014-11-17 13:37:57 -0800238 intent);
Pingpingfc584672014-10-23 10:51:19 -0700239 verify(intentService);
240 verify(hostService);
241
242 }
243
244 /**
245 * This method tests updating a route entry.
246 *
247 * @throws TestUtilsException
248 */
Brian O'Connor520c0522014-11-23 23:50:47 -0800249 @Test @Ignore("needs fix from intents")
Pingpingfc584672014-10-23 10:51:19 -0700250 public void testRouteUpdate() throws TestUtilsException {
251
252 // Construct the existing route entry
253 RouteEntry routeEntry = new RouteEntry(
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800254 Ip4Prefix.valueOf("1.1.1.0/24"),
255 Ip4Address.valueOf("192.168.10.1"));
Pingpingfc584672014-10-23 10:51:19 -0700256
257 // Construct the existing MultiPointToSinglePointIntent intent
258 MultiPointToSinglePointIntent intent = staticIntentBuilder();
259
260 // Set up the bgpRoutes field of Router class with existing route, and
Pavlin Radoslavova7243cc2014-11-22 21:38:02 -0800261 // routeIntents field with the corresponding existing intent
Pingpingfc584672014-10-23 10:51:19 -0700262 setBgpRoutesField(routeEntry);
Pavlin Radoslavova7243cc2014-11-22 21:38:02 -0800263 setRouteIntentsField(routeEntry, intent);
Pingpingfc584672014-10-23 10:51:19 -0700264
265 // Start to construct a new route entry and new intent
266 RouteEntry routeEntryUpdate = new RouteEntry(
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800267 Ip4Prefix.valueOf("1.1.1.0/24"),
268 Ip4Address.valueOf("192.168.20.1"));
Pingpingfc584672014-10-23 10:51:19 -0700269
270 // Construct a new MultiPointToSinglePointIntent intent
271 TrafficSelector.Builder selectorBuilderNew =
272 DefaultTrafficSelector.builder();
273 selectorBuilderNew.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(
274 routeEntryUpdate.prefix());
275
276 TrafficTreatment.Builder treatmentBuilderNew =
277 DefaultTrafficTreatment.builder();
278 treatmentBuilderNew.setEthDst(MacAddress.valueOf("00:00:00:00:00:02"));
279
280 Set<ConnectPoint> ingressPointsNew = new HashSet<ConnectPoint>();
281 ingressPointsNew.add(SW1_ETH1);
282 ingressPointsNew.add(SW3_ETH1);
283
284 MultiPointToSinglePointIntent intentNew =
285 new MultiPointToSinglePointIntent(APPID,
286 selectorBuilderNew.build(),
287 treatmentBuilderNew.build(),
288 ingressPointsNew, SW2_ETH1);
289
290 // Set up test expectation
291 reset(hostService);
Pavlin Radoslavov33f228a2014-10-27 19:33:16 -0700292 expect(hostService.getHostsByIp(anyObject(IpAddress.class))).andReturn(
Pingpingfc584672014-10-23 10:51:19 -0700293 new HashSet<Host>()).anyTimes();
294 hostService.startMonitoringIp(IpAddress.valueOf("192.168.20.1"));
295 replay(hostService);
296
297 reset(intentService);
298 intentService.withdraw(intent);
299 intentService.submit(intentNew);
300 replay(intentService);
301
302 // Call the processRouteAdd() method in Router class
Pavlin Radoslavova071b1e2014-11-17 13:37:57 -0800303 intentSynchronizer.leaderChanged(true);
304 TestUtils.setField(intentSynchronizer, "isActivatedLeader", true);
Pingpingfc584672014-10-23 10:51:19 -0700305 router.processRouteAdd(routeEntryUpdate);
306
307 Host host = new DefaultHost(ProviderId.NONE, HostId.NONE,
308 MacAddress.valueOf("00:00:00:00:00:02"), VlanId.NONE,
309 new HostLocation(
310 SW2_ETH1.deviceId(),
311 SW2_ETH1.port(), 1),
Pavlin Radoslavov33f228a2014-10-27 19:33:16 -0700312 Sets.newHashSet(IpAddress.valueOf("192.168.20.1")));
Pingpingfc584672014-10-23 10:51:19 -0700313 internalHostListener.event(
314 new HostEvent(HostEvent.Type.HOST_ADDED, host));
315
316 // Verify
317 assertEquals(router.getRoutes().size(), 1);
318 assertTrue(router.getRoutes().contains(routeEntryUpdate));
Pavlin Radoslavova7243cc2014-11-22 21:38:02 -0800319 assertEquals(intentSynchronizer.getRouteIntents().size(), 1);
320 assertEquals(intentSynchronizer.getRouteIntents().iterator().next(),
Pingpingfc584672014-10-23 10:51:19 -0700321 intentNew);
322 verify(intentService);
323 verify(hostService);
324 }
325
326 /**
327 * This method tests deleting a route entry.
328 */
329 @Test
330 public void testProcessRouteDelete() throws TestUtilsException {
331
332 // Construct the existing route entry
333 RouteEntry routeEntry = new RouteEntry(
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800334 Ip4Prefix.valueOf("1.1.1.0/24"),
335 Ip4Address.valueOf("192.168.10.1"));
Pingpingfc584672014-10-23 10:51:19 -0700336
337 // Construct the existing MultiPointToSinglePointIntent intent
338 MultiPointToSinglePointIntent intent = staticIntentBuilder();
339
340 // Set up the bgpRoutes field of Router class with existing route, and
Pavlin Radoslavova7243cc2014-11-22 21:38:02 -0800341 // routeIntents field with the corresponding existing intent
Pingpingfc584672014-10-23 10:51:19 -0700342 setBgpRoutesField(routeEntry);
Pavlin Radoslavova7243cc2014-11-22 21:38:02 -0800343 setRouteIntentsField(routeEntry, intent);
Pingpingfc584672014-10-23 10:51:19 -0700344
345 // Set up expectation
346 reset(intentService);
347 intentService.withdraw(intent);
348 replay(intentService);
349
350 // Call route deleting method in Router class
Pavlin Radoslavova071b1e2014-11-17 13:37:57 -0800351 intentSynchronizer.leaderChanged(true);
352 TestUtils.setField(intentSynchronizer, "isActivatedLeader", true);
Pingpingfc584672014-10-23 10:51:19 -0700353 router.processRouteDelete(routeEntry);
354
355 // Verify
356 assertEquals(router.getRoutes().size(), 0);
Pavlin Radoslavova7243cc2014-11-22 21:38:02 -0800357 assertEquals(intentSynchronizer.getRouteIntents().size(), 0);
Pingpingfc584672014-10-23 10:51:19 -0700358 verify(intentService);
359 }
360
361 /**
362 * Constructs a static MultiPointToSinglePointIntent.
363 */
364 private MultiPointToSinglePointIntent staticIntentBuilder() {
365
366 TrafficSelector.Builder selectorBuilder =
367 DefaultTrafficSelector.builder();
368 selectorBuilder.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(
369 IpPrefix.valueOf("1.1.1.0/24"));
370
371 TrafficTreatment.Builder treatmentBuilder =
372 DefaultTrafficTreatment.builder();
373 treatmentBuilder.setEthDst(MacAddress.valueOf("00:00:00:00:00:01"));
374
375 Set<ConnectPoint> ingressPoints = new HashSet<ConnectPoint>();
376 ingressPoints.add(SW2_ETH1);
377 ingressPoints.add(SW3_ETH1);
378
379 MultiPointToSinglePointIntent intent =
380 new MultiPointToSinglePointIntent(APPID,
381 selectorBuilder.build(), treatmentBuilder.build(),
382 ingressPoints, SW1_ETH1);
383
384 return intent;
385 }
386
387 /**
388 * Sets bgpRoutesField in Router class.
389 *
390 * @throws TestUtilsException
391 */
392 private void setBgpRoutesField(RouteEntry routeEntry)
393 throws TestUtilsException {
394
395 InvertedRadixTree<RouteEntry> bgpRoutes =
396 new ConcurrentInvertedRadixTree<>(
397 new DefaultByteArrayNodeFactory());
398 bgpRoutes.put(RouteEntry.createBinaryString(routeEntry.prefix()),
399 routeEntry);
400 TestUtils.setField(router, "bgpRoutes", bgpRoutes);
401 }
402
403 /**
Pavlin Radoslavova7243cc2014-11-22 21:38:02 -0800404 * Sets routeIntentsField in IntentSynchronizer class.
Pingpingfc584672014-10-23 10:51:19 -0700405 *
406 * @throws TestUtilsException
407 */
Pavlin Radoslavova7243cc2014-11-22 21:38:02 -0800408 private void setRouteIntentsField(RouteEntry routeEntry,
Pingpingfc584672014-10-23 10:51:19 -0700409 MultiPointToSinglePointIntent intent)
410 throws TestUtilsException {
411
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800412 ConcurrentHashMap<Ip4Prefix, MultiPointToSinglePointIntent>
Pavlin Radoslavova7243cc2014-11-22 21:38:02 -0800413 routeIntents = new ConcurrentHashMap<>();
414 routeIntents.put(routeEntry.prefix(), intent);
415 TestUtils.setField(intentSynchronizer, "routeIntents", routeIntents);
Pingpingfc584672014-10-23 10:51:19 -0700416 }
417}