blob: 91315c947b574807a8a5906bc98b2bc40c8dd5b1 [file] [log] [blame]
alshabibab984662014-12-04 18:56:18 -08001/*
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 */
Brian O'Connorabafb502014-12-02 22:26:20 -080016package org.onosproject.sdnip;
Pingpingf5d90932014-10-27 10:50:04 -070017
Jonathan Hart552e31f2015-02-06 11:11:59 -080018import com.google.common.collect.Sets;
Pingpingf5d90932014-10-27 10:50:04 -070019import org.junit.Before;
20import org.junit.Test;
21import org.onlab.junit.TestUtils;
22import org.onlab.junit.TestUtils.TestUtilsException;
Jonathan Hart6cd2f352015-01-13 17:44:45 -080023import org.onlab.packet.Ethernet;
24import org.onlab.packet.Ip4Address;
25import org.onlab.packet.Ip4Prefix;
26import org.onlab.packet.IpAddress;
27import org.onlab.packet.IpPrefix;
28import org.onlab.packet.MacAddress;
29import org.onlab.packet.VlanId;
Brian O'Connorabafb502014-12-02 22:26:20 -080030import org.onosproject.core.ApplicationId;
31import org.onosproject.net.ConnectPoint;
Brian O'Connorabafb502014-12-02 22:26:20 -080032import org.onosproject.net.DeviceId;
Brian O'Connorabafb502014-12-02 22:26:20 -080033import org.onosproject.net.PortNumber;
34import org.onosproject.net.flow.DefaultTrafficSelector;
35import org.onosproject.net.flow.DefaultTrafficTreatment;
36import org.onosproject.net.flow.TrafficSelector;
37import org.onosproject.net.flow.TrafficTreatment;
Brian O'Connorabafb502014-12-02 22:26:20 -080038import org.onosproject.net.host.InterfaceIpAddress;
39import org.onosproject.net.intent.AbstractIntentTest;
40import org.onosproject.net.intent.Intent;
Brian O'Connorabafb502014-12-02 22:26:20 -080041import org.onosproject.net.intent.IntentService;
42import org.onosproject.net.intent.IntentState;
43import org.onosproject.net.intent.MultiPointToSinglePointIntent;
Jonathan Hart2da1e602015-02-18 19:09:24 -080044import org.onosproject.routing.FibEntry;
45import org.onosproject.routing.FibUpdate;
46import org.onosproject.routing.RouteEntry;
47import org.onosproject.routing.config.BgpPeer;
48import org.onosproject.routing.config.Interface;
49import org.onosproject.routing.config.RoutingConfigurationService;
Jonathan Hart41349e92015-02-09 14:14:02 -080050import org.onosproject.sdnip.IntentSynchronizer.IntentKey;
Pingpingf5d90932014-10-27 10:50:04 -070051
Jonathan Hart41349e92015-02-09 14:14:02 -080052import java.util.Collections;
53import java.util.HashMap;
Jonathan Hart552e31f2015-02-06 11:11:59 -080054import java.util.HashSet;
Jonathan Hart41349e92015-02-09 14:14:02 -080055import java.util.Map;
Jonathan Hart552e31f2015-02-06 11:11:59 -080056import java.util.Set;
57import java.util.concurrent.ConcurrentHashMap;
58
59import static org.easymock.EasyMock.*;
60import static org.hamcrest.Matchers.is;
Jonathan Hartcb726fc2015-02-13 16:26:22 -080061import static org.junit.Assert.assertEquals;
62import static org.junit.Assert.assertFalse;
63import static org.junit.Assert.assertThat;
64import static org.junit.Assert.assertTrue;
65import static org.onosproject.sdnip.TestIntentServiceHelper.eqExceptId;
Pingpingf5d90932014-10-27 10:50:04 -070066
67/**
Pavlin Radoslavova071b1e2014-11-17 13:37:57 -080068 * This class tests the intent synchronization function in the
69 * IntentSynchronizer class.
Pingpingf5d90932014-10-27 10:50:04 -070070 */
Brian O'Connor520c0522014-11-23 23:50:47 -080071public class IntentSyncTest extends AbstractIntentTest {
Pingpingf5d90932014-10-27 10:50:04 -070072
Jonathan Hart90a02c22015-02-13 11:52:07 -080073 private RoutingConfigurationService routingConfig;
Pingpingf5d90932014-10-27 10:50:04 -070074 private IntentService intentService;
Pingpingf5d90932014-10-27 10:50:04 -070075
76 private static final ConnectPoint SW1_ETH1 = new ConnectPoint(
77 DeviceId.deviceId("of:0000000000000001"),
78 PortNumber.portNumber(1));
79
80 private static final ConnectPoint SW2_ETH1 = new ConnectPoint(
81 DeviceId.deviceId("of:0000000000000002"),
82 PortNumber.portNumber(1));
83
84 private static final ConnectPoint SW3_ETH1 = new ConnectPoint(
85 DeviceId.deviceId("of:0000000000000003"),
86 PortNumber.portNumber(1));
87
Jonathan Hart41349e92015-02-09 14:14:02 -080088 private static final ConnectPoint SW4_ETH1 = new ConnectPoint(
89 DeviceId.deviceId("of:0000000000000004"),
90 PortNumber.portNumber(1));
91
Pavlin Radoslavova071b1e2014-11-17 13:37:57 -080092 private IntentSynchronizer intentSynchronizer;
Pingpingf5d90932014-10-27 10:50:04 -070093
94 private static final ApplicationId APPID = new ApplicationId() {
95 @Override
96 public short id() {
97 return 1;
98 }
99
100 @Override
101 public String name() {
102 return "SDNIP";
103 }
104 };
105
106 @Before
107 public void setUp() throws Exception {
Brian O'Connor520c0522014-11-23 23:50:47 -0800108 super.setUp();
Jonathan Hart41349e92015-02-09 14:14:02 -0800109
Jonathan Hart90a02c22015-02-13 11:52:07 -0800110 routingConfig = createMock(RoutingConfigurationService.class);
111
112 // These will set expectations on routingConfig
113 setUpInterfaceService();
Jonathan Hart41349e92015-02-09 14:14:02 -0800114 setUpBgpPeers();
Jonathan Hart90a02c22015-02-13 11:52:07 -0800115
116 replay(routingConfig);
117
Pingpingf5d90932014-10-27 10:50:04 -0700118 intentService = createMock(IntentService.class);
119
Jonathan Hart552e31f2015-02-06 11:11:59 -0800120 intentSynchronizer = new IntentSynchronizer(APPID, intentService,
Pingping Line28ae4c2015-03-13 11:37:03 -0700121 null, routingConfig);
Jonathan Hart41349e92015-02-09 14:14:02 -0800122 }
123
124 /**
125 * Sets up BGP peers in external networks.
126 */
127 private void setUpBgpPeers() {
128
129 Map<IpAddress, BgpPeer> peers = new HashMap<>();
130
131 String peerSw1Eth1 = "192.168.10.1";
132 peers.put(IpAddress.valueOf(peerSw1Eth1),
133 new BgpPeer("00:00:00:00:00:00:00:01", 1, peerSw1Eth1));
134
135 // Two BGP peers are connected to switch 2 port 1.
136 String peer1Sw2Eth1 = "192.168.20.1";
137 peers.put(IpAddress.valueOf(peer1Sw2Eth1),
138 new BgpPeer("00:00:00:00:00:00:00:02", 1, peer1Sw2Eth1));
139
140 String peer2Sw2Eth1 = "192.168.20.2";
141 peers.put(IpAddress.valueOf(peer2Sw2Eth1),
142 new BgpPeer("00:00:00:00:00:00:00:02", 1, peer2Sw2Eth1));
143
144 String peer1Sw4Eth1 = "192.168.40.1";
145 peers.put(IpAddress.valueOf(peer1Sw4Eth1),
146 new BgpPeer("00:00:00:00:00:00:00:04", 1, peer1Sw4Eth1));
147
Jonathan Hart90a02c22015-02-13 11:52:07 -0800148 expect(routingConfig.getBgpPeers()).andReturn(peers).anyTimes();
Pingpingf5d90932014-10-27 10:50:04 -0700149 }
150
151 /**
152 * Sets up InterfaceService.
153 */
154 private void setUpInterfaceService() {
155
Pingpingf5d90932014-10-27 10:50:04 -0700156 Set<Interface> interfaces = Sets.newHashSet();
157
158 Set<InterfaceIpAddress> interfaceIpAddresses1 = Sets.newHashSet();
159 interfaceIpAddresses1.add(new InterfaceIpAddress(
160 IpAddress.valueOf("192.168.10.101"),
161 IpPrefix.valueOf("192.168.10.0/24")));
162 Interface sw1Eth1 = new Interface(SW1_ETH1,
Jonathan Hart6cd2f352015-01-13 17:44:45 -0800163 interfaceIpAddresses1, MacAddress.valueOf("00:00:00:00:00:01"),
164 VlanId.NONE);
Pingpingf5d90932014-10-27 10:50:04 -0700165 interfaces.add(sw1Eth1);
166
167 Set<InterfaceIpAddress> interfaceIpAddresses2 = Sets.newHashSet();
Jonathan Hart41349e92015-02-09 14:14:02 -0800168 interfaceIpAddresses2.add(
169 new InterfaceIpAddress(IpAddress.valueOf("192.168.20.101"),
170 IpPrefix.valueOf("192.168.20.0/24")));
Pingpingf5d90932014-10-27 10:50:04 -0700171 Interface sw2Eth1 = new Interface(SW2_ETH1,
Jonathan Hart6cd2f352015-01-13 17:44:45 -0800172 interfaceIpAddresses2, MacAddress.valueOf("00:00:00:00:00:02"),
173 VlanId.NONE);
Pingpingf5d90932014-10-27 10:50:04 -0700174 interfaces.add(sw2Eth1);
175
176 Set<InterfaceIpAddress> interfaceIpAddresses3 = Sets.newHashSet();
Jonathan Hart41349e92015-02-09 14:14:02 -0800177 interfaceIpAddresses3.add(
178 new InterfaceIpAddress(IpAddress.valueOf("192.168.30.101"),
179 IpPrefix.valueOf("192.168.30.0/24")));
Pingpingf5d90932014-10-27 10:50:04 -0700180 Interface sw3Eth1 = new Interface(SW3_ETH1,
Jonathan Hart6cd2f352015-01-13 17:44:45 -0800181 interfaceIpAddresses3, MacAddress.valueOf("00:00:00:00:00:03"),
182 VlanId.NONE);
Pingpingf5d90932014-10-27 10:50:04 -0700183 interfaces.add(sw3Eth1);
184
Jonathan Hart41349e92015-02-09 14:14:02 -0800185 InterfaceIpAddress interfaceIpAddress4 =
186 new InterfaceIpAddress(IpAddress.valueOf("192.168.40.101"),
187 IpPrefix.valueOf("192.168.40.0/24"));
188 Interface sw4Eth1 = new Interface(SW4_ETH1,
189 Sets.newHashSet(interfaceIpAddress4),
190 MacAddress.valueOf("00:00:00:00:00:04"),
191 VlanId.vlanId((short) 1));
192
Jonathan Hart90a02c22015-02-13 11:52:07 -0800193 expect(routingConfig.getInterface(SW4_ETH1)).andReturn(
194 sw4Eth1).anyTimes();
Jonathan Hart41349e92015-02-09 14:14:02 -0800195 interfaces.add(sw4Eth1);
196
Jonathan Hart90a02c22015-02-13 11:52:07 -0800197 expect(routingConfig.getInterface(SW1_ETH1)).andReturn(
Pingpingf5d90932014-10-27 10:50:04 -0700198 sw1Eth1).anyTimes();
Jonathan Hart90a02c22015-02-13 11:52:07 -0800199 expect(routingConfig.getInterface(SW2_ETH1)).andReturn(
Pingpingf5d90932014-10-27 10:50:04 -0700200 sw2Eth1).anyTimes();
Jonathan Hart90a02c22015-02-13 11:52:07 -0800201 expect(routingConfig.getInterface(SW3_ETH1)).andReturn(sw3Eth1).anyTimes();
202 expect(routingConfig.getInterfaces()).andReturn(interfaces).anyTimes();
Pingpingf5d90932014-10-27 10:50:04 -0700203 }
204
205 /**
Jonathan Hart41349e92015-02-09 14:14:02 -0800206 * Tests adding a FIB entry to the IntentSynchronizer.
207 *
208 * We verify that the synchronizer records the correct state and that the
209 * correct intent is submitted to the IntentService.
210 *
211 * @throws TestUtilsException
Pingpingf5d90932014-10-27 10:50:04 -0700212 */
Jonathan Hart41349e92015-02-09 14:14:02 -0800213 @Test
214 public void testFibAdd() throws TestUtilsException {
215 FibEntry fibEntry = new FibEntry(
216 Ip4Prefix.valueOf("1.1.1.0/24"),
217 Ip4Address.valueOf("192.168.10.1"),
218 MacAddress.valueOf("00:00:00:00:00:01"));
Pingpingf5d90932014-10-27 10:50:04 -0700219
Jonathan Hart41349e92015-02-09 14:14:02 -0800220 // Construct a MultiPointToSinglePointIntent intent
221 TrafficSelector.Builder selectorBuilder =
222 DefaultTrafficSelector.builder();
223 selectorBuilder.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(
224 fibEntry.prefix());
Pingpingf5d90932014-10-27 10:50:04 -0700225
Jonathan Hart41349e92015-02-09 14:14:02 -0800226 TrafficTreatment.Builder treatmentBuilder =
227 DefaultTrafficTreatment.builder();
228 treatmentBuilder.setEthDst(MacAddress.valueOf("00:00:00:00:00:01"));
Pingpingf5d90932014-10-27 10:50:04 -0700229
Jonathan Hart41349e92015-02-09 14:14:02 -0800230 Set<ConnectPoint> ingressPoints = new HashSet<>();
231 ingressPoints.add(SW2_ETH1);
232 ingressPoints.add(SW3_ETH1);
233 ingressPoints.add(SW4_ETH1);
234
235 MultiPointToSinglePointIntent intent =
Ray Milkeyebc5d222015-03-18 15:45:36 -0700236 MultiPointToSinglePointIntent.builder()
237 .appId(APPID)
238 .selector(selectorBuilder.build())
239 .treatment(treatmentBuilder.build())
240 .ingressPoints(ingressPoints)
241 .egressPoint(SW1_ETH1)
242 .build();
Jonathan Hart41349e92015-02-09 14:14:02 -0800243
244 // Setup the expected intents
Jonathan Hartcb726fc2015-02-13 16:26:22 -0800245 intentService.submit(eqExceptId(intent));
Jonathan Hart41349e92015-02-09 14:14:02 -0800246 replay(intentService);
247
248 intentSynchronizer.leaderChanged(true);
249 TestUtils.setField(intentSynchronizer, "isActivatedLeader", true);
250
251 FibUpdate fibUpdate = new FibUpdate(FibUpdate.Type.UPDATE,
252 fibEntry);
253 intentSynchronizer.update(Collections.singleton(fibUpdate),
254 Collections.emptyList());
255
Brian O'Connor03406a42015-02-03 17:28:57 -0800256 assertEquals(intentSynchronizer.getRouteIntents().size(), 1);
Jonathan Hart41349e92015-02-09 14:14:02 -0800257 Intent firstIntent =
258 intentSynchronizer.getRouteIntents().iterator().next();
259 IntentKey firstIntentKey = new IntentKey(firstIntent);
260 IntentKey intentKey = new IntentKey(intent);
261 assertTrue(firstIntentKey.equals(intentKey));
262 verify(intentService);
263 }
264
265 /**
266 * Tests adding a FIB entry with to a next hop in a VLAN.
267 *
268 * We verify that the synchronizer records the correct state and that the
269 * correct intent is submitted to the IntentService.
270 *
271 * @throws TestUtilsException
272 */
273 @Test
274 public void testFibAddWithVlan() throws TestUtilsException {
275 FibEntry fibEntry = new FibEntry(
276 Ip4Prefix.valueOf("3.3.3.0/24"),
277 Ip4Address.valueOf("192.168.40.1"),
278 MacAddress.valueOf("00:00:00:00:00:04"));
279
280 // Construct a MultiPointToSinglePointIntent intent
281 TrafficSelector.Builder selectorBuilder =
282 DefaultTrafficSelector.builder();
283 selectorBuilder.matchEthType(Ethernet.TYPE_IPV4)
284 .matchIPDst(fibEntry.prefix())
285 .matchVlanId(VlanId.ANY);
286
287 TrafficTreatment.Builder treatmentBuilder =
288 DefaultTrafficTreatment.builder();
289 treatmentBuilder.setEthDst(MacAddress.valueOf("00:00:00:00:00:04"))
290 .setVlanId(VlanId.vlanId((short) 1));
291
292 Set<ConnectPoint> ingressPoints = new HashSet<>();
293 ingressPoints.add(SW1_ETH1);
294 ingressPoints.add(SW2_ETH1);
295 ingressPoints.add(SW3_ETH1);
296
297 MultiPointToSinglePointIntent intent =
Ray Milkeyebc5d222015-03-18 15:45:36 -0700298 MultiPointToSinglePointIntent.builder()
299 .appId(APPID)
300 .selector(selectorBuilder.build())
301 .treatment(treatmentBuilder.build())
302 .ingressPoints(ingressPoints)
303 .egressPoint(SW4_ETH1)
304 .build();
Jonathan Hart41349e92015-02-09 14:14:02 -0800305
306 // Setup the expected intents
Jonathan Hartcb726fc2015-02-13 16:26:22 -0800307 intentService.submit(eqExceptId(intent));
308
Jonathan Hart41349e92015-02-09 14:14:02 -0800309 replay(intentService);
310
311 // Run the test
312 intentSynchronizer.leaderChanged(true);
313 TestUtils.setField(intentSynchronizer, "isActivatedLeader", true);
314 FibUpdate fibUpdate = new FibUpdate(FibUpdate.Type.UPDATE, fibEntry);
315
316 intentSynchronizer.update(Collections.singleton(fibUpdate),
317 Collections.emptyList());
318
319 // Verify
Brian O'Connor03406a42015-02-03 17:28:57 -0800320 assertEquals(intentSynchronizer.getRouteIntents().size(), 1);
Jonathan Hart41349e92015-02-09 14:14:02 -0800321 Intent firstIntent =
322 intentSynchronizer.getRouteIntents().iterator().next();
323 IntentKey firstIntentKey = new IntentKey(firstIntent);
324 IntentKey intentKey = new IntentKey(intent);
325 assertTrue(firstIntentKey.equals(intentKey));
326 verify(intentService);
327 }
328
329 /**
330 * Tests updating a FIB entry.
331 *
332 * We verify that the synchronizer records the correct state and that the
333 * correct intent is submitted to the IntentService.
334 *
335 * @throws TestUtilsException
336 */
337 @Test
338 public void testFibUpdate() throws TestUtilsException {
339 // Firstly add a route
340 testFibAdd();
341
342 Intent addedIntent =
343 intentSynchronizer.getRouteIntents().iterator().next();
344
345 // Start to construct a new route entry and new intent
346 FibEntry fibEntryUpdate = new FibEntry(
347 Ip4Prefix.valueOf("1.1.1.0/24"),
348 Ip4Address.valueOf("192.168.20.1"),
349 MacAddress.valueOf("00:00:00:00:00:02"));
350
351 // Construct a new MultiPointToSinglePointIntent intent
352 TrafficSelector.Builder selectorBuilderNew =
353 DefaultTrafficSelector.builder();
354 selectorBuilderNew.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(
355 fibEntryUpdate.prefix());
356
357 TrafficTreatment.Builder treatmentBuilderNew =
358 DefaultTrafficTreatment.builder();
359 treatmentBuilderNew.setEthDst(MacAddress.valueOf("00:00:00:00:00:02"));
Pingpingf5d90932014-10-27 10:50:04 -0700360
361
Jonathan Hart41349e92015-02-09 14:14:02 -0800362 Set<ConnectPoint> ingressPointsNew = new HashSet<>();
363 ingressPointsNew.add(SW1_ETH1);
364 ingressPointsNew.add(SW3_ETH1);
365 ingressPointsNew.add(SW4_ETH1);
Pingpingf5d90932014-10-27 10:50:04 -0700366
Jonathan Hart41349e92015-02-09 14:14:02 -0800367 MultiPointToSinglePointIntent intentNew =
Ray Milkeyebc5d222015-03-18 15:45:36 -0700368 MultiPointToSinglePointIntent.builder()
369 .appId(APPID)
370 .selector(selectorBuilderNew.build())
371 .treatment(treatmentBuilderNew.build())
372 .ingressPoints(ingressPointsNew)
373 .egressPoint(SW2_ETH1)
374 .build();
Pingpingf5d90932014-10-27 10:50:04 -0700375
Jonathan Hart41349e92015-02-09 14:14:02 -0800376 // Set up test expectation
377 reset(intentService);
378 // Setup the expected intents
Jonathan Hartcb726fc2015-02-13 16:26:22 -0800379 intentService.withdraw(eqExceptId(addedIntent));
380 intentService.submit(eqExceptId(intentNew));
Jonathan Hart41349e92015-02-09 14:14:02 -0800381 replay(intentService);
Pingpingf5d90932014-10-27 10:50:04 -0700382
Jonathan Hart41349e92015-02-09 14:14:02 -0800383 // Call the update() method in IntentSynchronizer class
384 intentSynchronizer.leaderChanged(true);
385 TestUtils.setField(intentSynchronizer, "isActivatedLeader", true);
386 FibUpdate fibUpdate = new FibUpdate(FibUpdate.Type.UPDATE,
387 fibEntryUpdate);
388 intentSynchronizer.update(Collections.singletonList(fibUpdate),
389 Collections.emptyList());
Pingpingf5d90932014-10-27 10:50:04 -0700390
Jonathan Hart41349e92015-02-09 14:14:02 -0800391 // Verify
Brian O'Connor03406a42015-02-03 17:28:57 -0800392 assertEquals(intentSynchronizer.getRouteIntents().size(), 1);
Jonathan Hart41349e92015-02-09 14:14:02 -0800393 Intent firstIntent =
394 intentSynchronizer.getRouteIntents().iterator().next();
395 IntentKey firstIntentKey = new IntentKey(firstIntent);
396 IntentKey intentNewKey = new IntentKey(intentNew);
397 assertTrue(firstIntentKey.equals(intentNewKey));
398 verify(intentService);
399 }
Pingpingf5d90932014-10-27 10:50:04 -0700400
Jonathan Hart41349e92015-02-09 14:14:02 -0800401 /**
402 * Tests deleting a FIB entry.
403 *
404 * We verify that the synchronizer records the correct state and that the
405 * correct intent is withdrawn from the IntentService.
406 *
407 * @throws TestUtilsException
408 */
409 @Test
410 public void testFibDelete() throws TestUtilsException {
411 // Firstly add a route
412 testFibAdd();
Pingpingf5d90932014-10-27 10:50:04 -0700413
Jonathan Hart41349e92015-02-09 14:14:02 -0800414 Intent addedIntent =
415 intentSynchronizer.getRouteIntents().iterator().next();
416
417 // Construct the existing route entry
418 FibEntry fibEntry = new FibEntry(
419 Ip4Prefix.valueOf("1.1.1.0/24"), null, null);
420
421 // Set up expectation
422 reset(intentService);
423 // Setup the expected intents
Jonathan Hartcb726fc2015-02-13 16:26:22 -0800424 intentService.withdraw(eqExceptId(addedIntent));
Jonathan Hart41349e92015-02-09 14:14:02 -0800425 replay(intentService);
426
427 // Call the update() method in IntentSynchronizer class
428 intentSynchronizer.leaderChanged(true);
429 TestUtils.setField(intentSynchronizer, "isActivatedLeader", true);
430 FibUpdate fibUpdate = new FibUpdate(FibUpdate.Type.DELETE, fibEntry);
431 intentSynchronizer.update(Collections.emptyList(),
432 Collections.singletonList(fibUpdate));
433
434 // Verify
Brian O'Connor03406a42015-02-03 17:28:57 -0800435 assertEquals(intentSynchronizer.getRouteIntents().size(), 0);
Jonathan Hart41349e92015-02-09 14:14:02 -0800436 verify(intentService);
Pingpingf5d90932014-10-27 10:50:04 -0700437 }
438
439 /**
440 * This method tests the behavior of intent Synchronizer.
441 *
442 * @throws TestUtilsException
443 */
444 @Test
445 public void testIntentSync() throws TestUtilsException {
446
447 //
448 // Construct routes and intents.
449 // This test simulates the following cases during the master change
450 // time interval:
451 // 1. RouteEntry1 did not change and the intent also did not change.
452 // 2. RouteEntry2 was deleted, but the intent was not deleted.
453 // 3. RouteEntry3 was newly added, and the intent was also submitted.
454 // 4. RouteEntry4 was updated to RouteEntry4Update, and the intent was
455 // also updated to a new one.
456 // 5. RouteEntry5 did not change, but its intent id changed.
457 // 6. RouteEntry6 was newly added, but the intent was not submitted.
458 //
459 RouteEntry routeEntry1 = new RouteEntry(
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800460 Ip4Prefix.valueOf("1.1.1.0/24"),
461 Ip4Address.valueOf("192.168.10.1"));
Pingpingf5d90932014-10-27 10:50:04 -0700462
463 RouteEntry routeEntry2 = new RouteEntry(
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800464 Ip4Prefix.valueOf("2.2.2.0/24"),
465 Ip4Address.valueOf("192.168.20.1"));
Pingpingf5d90932014-10-27 10:50:04 -0700466
467 RouteEntry routeEntry3 = new RouteEntry(
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800468 Ip4Prefix.valueOf("3.3.3.0/24"),
469 Ip4Address.valueOf("192.168.30.1"));
Pingpingf5d90932014-10-27 10:50:04 -0700470
471 RouteEntry routeEntry4 = new RouteEntry(
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800472 Ip4Prefix.valueOf("4.4.4.0/24"),
473 Ip4Address.valueOf("192.168.30.1"));
Pingpingf5d90932014-10-27 10:50:04 -0700474
475 RouteEntry routeEntry4Update = new RouteEntry(
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800476 Ip4Prefix.valueOf("4.4.4.0/24"),
477 Ip4Address.valueOf("192.168.20.1"));
Pingpingf5d90932014-10-27 10:50:04 -0700478
479 RouteEntry routeEntry5 = new RouteEntry(
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800480 Ip4Prefix.valueOf("5.5.5.0/24"),
481 Ip4Address.valueOf("192.168.10.1"));
Pingpingf5d90932014-10-27 10:50:04 -0700482
483 RouteEntry routeEntry6 = new RouteEntry(
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800484 Ip4Prefix.valueOf("6.6.6.0/24"),
485 Ip4Address.valueOf("192.168.10.1"));
Pingpingf5d90932014-10-27 10:50:04 -0700486
Jonathan Hartec2df012014-10-23 16:40:24 -0700487 RouteEntry routeEntry7 = new RouteEntry(
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800488 Ip4Prefix.valueOf("7.7.7.0/24"),
489 Ip4Address.valueOf("192.168.10.1"));
Jonathan Hartec2df012014-10-23 16:40:24 -0700490
Pingpingf5d90932014-10-27 10:50:04 -0700491 MultiPointToSinglePointIntent intent1 = intentBuilder(
492 routeEntry1.prefix(), "00:00:00:00:00:01", SW1_ETH1);
493 MultiPointToSinglePointIntent intent2 = intentBuilder(
494 routeEntry2.prefix(), "00:00:00:00:00:02", SW2_ETH1);
495 MultiPointToSinglePointIntent intent3 = intentBuilder(
496 routeEntry3.prefix(), "00:00:00:00:00:03", SW3_ETH1);
497 MultiPointToSinglePointIntent intent4 = intentBuilder(
498 routeEntry4.prefix(), "00:00:00:00:00:03", SW3_ETH1);
499 MultiPointToSinglePointIntent intent4Update = intentBuilder(
500 routeEntry4Update.prefix(), "00:00:00:00:00:02", SW2_ETH1);
501 MultiPointToSinglePointIntent intent5 = intentBuilder(
502 routeEntry5.prefix(), "00:00:00:00:00:01", SW1_ETH1);
Jonathan Hartec2df012014-10-23 16:40:24 -0700503 MultiPointToSinglePointIntent intent7 = intentBuilder(
504 routeEntry7.prefix(), "00:00:00:00:00:01", SW1_ETH1);
Pingpingf5d90932014-10-27 10:50:04 -0700505
506 // Compose a intent, which is equal to intent5 but the id is different.
507 MultiPointToSinglePointIntent intent5New =
508 staticIntentBuilder(intent5, routeEntry5, "00:00:00:00:00:01");
Pavlin Radoslavova7243cc2014-11-22 21:38:02 -0800509 assertThat(IntentSynchronizer.IntentKey.equalIntents(
510 intent5, intent5New),
511 is(true));
Jonathan Hartec2df012014-10-23 16:40:24 -0700512 assertFalse(intent5.equals(intent5New));
Pingpingf5d90932014-10-27 10:50:04 -0700513
514 MultiPointToSinglePointIntent intent6 = intentBuilder(
515 routeEntry6.prefix(), "00:00:00:00:00:01", SW1_ETH1);
516
Jonathan Hart41349e92015-02-09 14:14:02 -0800517 // Set up the routeIntents field in IntentSynchronizer class
Pavlin Radoslavov3a0a52e2015-01-06 17:41:37 -0800518 ConcurrentHashMap<IpPrefix, MultiPointToSinglePointIntent>
519 routeIntents = new ConcurrentHashMap<>();
Pavlin Radoslavova7243cc2014-11-22 21:38:02 -0800520 routeIntents.put(routeEntry1.prefix(), intent1);
521 routeIntents.put(routeEntry3.prefix(), intent3);
522 routeIntents.put(routeEntry4Update.prefix(), intent4Update);
523 routeIntents.put(routeEntry5.prefix(), intent5New);
524 routeIntents.put(routeEntry6.prefix(), intent6);
525 routeIntents.put(routeEntry7.prefix(), intent7);
526 TestUtils.setField(intentSynchronizer, "routeIntents", routeIntents);
Pingpingf5d90932014-10-27 10:50:04 -0700527
528 // Set up expectation
529 reset(intentService);
Jonathan Hart90a02c22015-02-13 11:52:07 -0800530 Set<Intent> intents = new HashSet<>();
Pingpingf5d90932014-10-27 10:50:04 -0700531 intents.add(intent1);
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800532 expect(intentService.getIntentState(intent1.key()))
Jonathan Hartec2df012014-10-23 16:40:24 -0700533 .andReturn(IntentState.INSTALLED).anyTimes();
Pingpingf5d90932014-10-27 10:50:04 -0700534 intents.add(intent2);
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800535 expect(intentService.getIntentState(intent2.key()))
Jonathan Hartec2df012014-10-23 16:40:24 -0700536 .andReturn(IntentState.INSTALLED).anyTimes();
Pingpingf5d90932014-10-27 10:50:04 -0700537 intents.add(intent4);
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800538 expect(intentService.getIntentState(intent4.key()))
Jonathan Hartec2df012014-10-23 16:40:24 -0700539 .andReturn(IntentState.INSTALLED).anyTimes();
Pingpingf5d90932014-10-27 10:50:04 -0700540 intents.add(intent5);
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800541 expect(intentService.getIntentState(intent5.key()))
Jonathan Hartec2df012014-10-23 16:40:24 -0700542 .andReturn(IntentState.INSTALLED).anyTimes();
543 intents.add(intent7);
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800544 expect(intentService.getIntentState(intent7.key()))
Jonathan Hartec2df012014-10-23 16:40:24 -0700545 .andReturn(IntentState.WITHDRAWING).anyTimes();
Pingpingf5d90932014-10-27 10:50:04 -0700546 expect(intentService.getIntents()).andReturn(intents).anyTimes();
547
Brian O'Connor03406a42015-02-03 17:28:57 -0800548 intentService.withdraw(intent2);
549 intentService.withdraw(intent4);
Pavlin Radoslavova7243cc2014-11-22 21:38:02 -0800550
Brian O'Connor03406a42015-02-03 17:28:57 -0800551 intentService.submit(intent3);
552 intentService.submit(intent4Update);
553 intentService.submit(intent6);
554 intentService.submit(intent7);
Pingpingf5d90932014-10-27 10:50:04 -0700555 replay(intentService);
556
557 // Start the test
Pavlin Radoslavova071b1e2014-11-17 13:37:57 -0800558 intentSynchronizer.leaderChanged(true);
Pavlin Radoslavova7243cc2014-11-22 21:38:02 -0800559 intentSynchronizer.synchronizeIntents();
Pingpingf5d90932014-10-27 10:50:04 -0700560
561 // Verify
Pavlin Radoslavova7243cc2014-11-22 21:38:02 -0800562 assertEquals(intentSynchronizer.getRouteIntents().size(), 6);
563 assertTrue(intentSynchronizer.getRouteIntents().contains(intent1));
564 assertTrue(intentSynchronizer.getRouteIntents().contains(intent3));
565 assertTrue(intentSynchronizer.getRouteIntents().contains(intent4Update));
566 assertTrue(intentSynchronizer.getRouteIntents().contains(intent5));
567 assertTrue(intentSynchronizer.getRouteIntents().contains(intent6));
Pingpingf5d90932014-10-27 10:50:04 -0700568
569 verify(intentService);
570 }
571
572 /**
573 * MultiPointToSinglePointIntent builder.
574 *
575 * @param ipPrefix the ipPrefix to match
576 * @param nextHopMacAddress to which the destination MAC address in packet
577 * should be rewritten
578 * @param egressPoint to which packets should be sent
579 * @return the constructed MultiPointToSinglePointIntent
580 */
Pavlin Radoslavov3a0a52e2015-01-06 17:41:37 -0800581 private MultiPointToSinglePointIntent intentBuilder(IpPrefix ipPrefix,
Pingpingf5d90932014-10-27 10:50:04 -0700582 String nextHopMacAddress, ConnectPoint egressPoint) {
583
584 TrafficSelector.Builder selectorBuilder =
585 DefaultTrafficSelector.builder();
Pavlin Radoslavov87dd9302015-03-10 13:53:24 -0700586 if (ipPrefix.isIp4()) {
Pavlin Radoslavov3a0a52e2015-01-06 17:41:37 -0800587 selectorBuilder.matchEthType(Ethernet.TYPE_IPV4); // IPv4
Pavlin Radoslavova8537092015-02-23 10:15:20 -0800588 selectorBuilder.matchIPDst(ipPrefix);
Pavlin Radoslavov3a0a52e2015-01-06 17:41:37 -0800589 } else {
590 selectorBuilder.matchEthType(Ethernet.TYPE_IPV6); // IPv6
Pavlin Radoslavova8537092015-02-23 10:15:20 -0800591 selectorBuilder.matchIPv6Dst(ipPrefix);
Pavlin Radoslavov3a0a52e2015-01-06 17:41:37 -0800592 }
Pingpingf5d90932014-10-27 10:50:04 -0700593
594 TrafficTreatment.Builder treatmentBuilder =
595 DefaultTrafficTreatment.builder();
596 treatmentBuilder.setEthDst(MacAddress.valueOf(nextHopMacAddress));
597
Jonathan Hart90a02c22015-02-13 11:52:07 -0800598 Set<ConnectPoint> ingressPoints = new HashSet<>();
599 for (Interface intf : routingConfig.getInterfaces()) {
600 if (!intf.equals(routingConfig.getInterface(egressPoint))) {
Pingpingf5d90932014-10-27 10:50:04 -0700601 ConnectPoint srcPort = intf.connectPoint();
602 ingressPoints.add(srcPort);
603 }
604 }
605 MultiPointToSinglePointIntent intent =
Ray Milkeyebc5d222015-03-18 15:45:36 -0700606 MultiPointToSinglePointIntent.builder()
607 .appId(APPID)
608 .selector(selectorBuilder.build())
609 .treatment(treatmentBuilder.build())
610 .ingressPoints(ingressPoints)
611 .egressPoint(egressPoint)
612 .build();
Pingpingf5d90932014-10-27 10:50:04 -0700613 return intent;
614 }
615
616 /**
617 * A static MultiPointToSinglePointIntent builder, the returned intent is
618 * equal to the input intent except that the id is different.
619 *
620 *
621 * @param intent the intent to be used for building a new intent
622 * @param routeEntry the relative routeEntry of the intent
623 * @return the newly constructed MultiPointToSinglePointIntent
624 * @throws TestUtilsException
625 */
626 private MultiPointToSinglePointIntent staticIntentBuilder(
627 MultiPointToSinglePointIntent intent, RouteEntry routeEntry,
628 String nextHopMacAddress) throws TestUtilsException {
629
630 // Use a different egress ConnectPoint with that in intent
631 // to generate a different id
632 MultiPointToSinglePointIntent intentNew = intentBuilder(
633 routeEntry.prefix(), nextHopMacAddress, SW2_ETH1);
634 TestUtils.setField(intentNew, "egressPoint", intent.egressPoint());
635 TestUtils.setField(intentNew,
636 "ingressPoints", intent.ingressPoints());
637 return intentNew;
638 }
Pingpingf5d90932014-10-27 10:50:04 -0700639}