blob: 035fe4d23368523ec259e23737ab9a0fe601d2a6 [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 Hart41349e92015-02-09 14:14:02 -080044import org.onosproject.routingapi.FibEntry;
45import org.onosproject.routingapi.FibUpdate;
46import org.onosproject.routingapi.RouteEntry;
47import org.onosproject.sdnip.IntentSynchronizer.IntentKey;
48import org.onosproject.sdnip.config.BgpPeer;
Brian O'Connorabafb502014-12-02 22:26:20 -080049import org.onosproject.sdnip.config.Interface;
Jonathan Hart41349e92015-02-09 14:14:02 -080050import org.onosproject.sdnip.config.SdnIpConfigurationService;
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;
Brian O'Connor03406a42015-02-03 17:28:57 -080061import static org.junit.Assert.*;
Pingpingf5d90932014-10-27 10:50:04 -070062
63/**
Pavlin Radoslavova071b1e2014-11-17 13:37:57 -080064 * This class tests the intent synchronization function in the
65 * IntentSynchronizer class.
Pingpingf5d90932014-10-27 10:50:04 -070066 */
Brian O'Connor03406a42015-02-03 17:28:57 -080067@Ignore //FIXME
Brian O'Connor520c0522014-11-23 23:50:47 -080068public class IntentSyncTest extends AbstractIntentTest {
Pingpingf5d90932014-10-27 10:50:04 -070069
Jonathan Hart41349e92015-02-09 14:14:02 -080070 private SdnIpConfigurationService sdnIpConfigService;
Pingpingf5d90932014-10-27 10:50:04 -070071 private InterfaceService interfaceService;
72 private IntentService intentService;
Pingpingf5d90932014-10-27 10:50:04 -070073
74 private static final ConnectPoint SW1_ETH1 = new ConnectPoint(
75 DeviceId.deviceId("of:0000000000000001"),
76 PortNumber.portNumber(1));
77
78 private static final ConnectPoint SW2_ETH1 = new ConnectPoint(
79 DeviceId.deviceId("of:0000000000000002"),
80 PortNumber.portNumber(1));
81
82 private static final ConnectPoint SW3_ETH1 = new ConnectPoint(
83 DeviceId.deviceId("of:0000000000000003"),
84 PortNumber.portNumber(1));
85
Jonathan Hart41349e92015-02-09 14:14:02 -080086 private static final ConnectPoint SW4_ETH1 = new ConnectPoint(
87 DeviceId.deviceId("of:0000000000000004"),
88 PortNumber.portNumber(1));
89
Pavlin Radoslavova071b1e2014-11-17 13:37:57 -080090 private IntentSynchronizer intentSynchronizer;
Pingpingf5d90932014-10-27 10:50:04 -070091
92 private static final ApplicationId APPID = new ApplicationId() {
93 @Override
94 public short id() {
95 return 1;
96 }
97
98 @Override
99 public String name() {
100 return "SDNIP";
101 }
102 };
103
104 @Before
105 public void setUp() throws Exception {
Brian O'Connor520c0522014-11-23 23:50:47 -0800106 super.setUp();
Pingpingf5d90932014-10-27 10:50:04 -0700107 setUpInterfaceService();
Jonathan Hart41349e92015-02-09 14:14:02 -0800108
109 setUpBgpPeers();
Pingpingf5d90932014-10-27 10:50:04 -0700110 intentService = createMock(IntentService.class);
111
Jonathan Hart552e31f2015-02-06 11:11:59 -0800112 intentSynchronizer = new IntentSynchronizer(APPID, intentService,
Jonathan Hart41349e92015-02-09 14:14:02 -0800113 sdnIpConfigService, interfaceService);
114 }
115
116 /**
117 * Sets up BGP peers in external networks.
118 */
119 private void setUpBgpPeers() {
120
121 Map<IpAddress, BgpPeer> peers = new HashMap<>();
122
123 String peerSw1Eth1 = "192.168.10.1";
124 peers.put(IpAddress.valueOf(peerSw1Eth1),
125 new BgpPeer("00:00:00:00:00:00:00:01", 1, peerSw1Eth1));
126
127 // Two BGP peers are connected to switch 2 port 1.
128 String peer1Sw2Eth1 = "192.168.20.1";
129 peers.put(IpAddress.valueOf(peer1Sw2Eth1),
130 new BgpPeer("00:00:00:00:00:00:00:02", 1, peer1Sw2Eth1));
131
132 String peer2Sw2Eth1 = "192.168.20.2";
133 peers.put(IpAddress.valueOf(peer2Sw2Eth1),
134 new BgpPeer("00:00:00:00:00:00:00:02", 1, peer2Sw2Eth1));
135
136 String peer1Sw4Eth1 = "192.168.40.1";
137 peers.put(IpAddress.valueOf(peer1Sw4Eth1),
138 new BgpPeer("00:00:00:00:00:00:00:04", 1, peer1Sw4Eth1));
139
140 sdnIpConfigService = createMock(SdnIpConfigurationService.class);
141 expect(sdnIpConfigService.getBgpPeers()).andReturn(peers).anyTimes();
Brian O'Connor03406a42015-02-03 17:28:57 -0800142 replay(sdnIpConfigService);
Jonathan Hart41349e92015-02-09 14:14:02 -0800143
Pingpingf5d90932014-10-27 10:50:04 -0700144 }
145
146 /**
147 * Sets up InterfaceService.
148 */
149 private void setUpInterfaceService() {
150
151 interfaceService = createMock(InterfaceService.class);
152
153 Set<Interface> interfaces = Sets.newHashSet();
154
155 Set<InterfaceIpAddress> interfaceIpAddresses1 = Sets.newHashSet();
156 interfaceIpAddresses1.add(new InterfaceIpAddress(
157 IpAddress.valueOf("192.168.10.101"),
158 IpPrefix.valueOf("192.168.10.0/24")));
159 Interface sw1Eth1 = new Interface(SW1_ETH1,
Jonathan Hart6cd2f352015-01-13 17:44:45 -0800160 interfaceIpAddresses1, MacAddress.valueOf("00:00:00:00:00:01"),
161 VlanId.NONE);
Pingpingf5d90932014-10-27 10:50:04 -0700162 interfaces.add(sw1Eth1);
163
164 Set<InterfaceIpAddress> interfaceIpAddresses2 = Sets.newHashSet();
Jonathan Hart41349e92015-02-09 14:14:02 -0800165 interfaceIpAddresses2.add(
166 new InterfaceIpAddress(IpAddress.valueOf("192.168.20.101"),
167 IpPrefix.valueOf("192.168.20.0/24")));
Pingpingf5d90932014-10-27 10:50:04 -0700168 Interface sw2Eth1 = new Interface(SW2_ETH1,
Jonathan Hart6cd2f352015-01-13 17:44:45 -0800169 interfaceIpAddresses2, MacAddress.valueOf("00:00:00:00:00:02"),
170 VlanId.NONE);
Pingpingf5d90932014-10-27 10:50:04 -0700171 interfaces.add(sw2Eth1);
172
173 Set<InterfaceIpAddress> interfaceIpAddresses3 = Sets.newHashSet();
Jonathan Hart41349e92015-02-09 14:14:02 -0800174 interfaceIpAddresses3.add(
175 new InterfaceIpAddress(IpAddress.valueOf("192.168.30.101"),
176 IpPrefix.valueOf("192.168.30.0/24")));
Pingpingf5d90932014-10-27 10:50:04 -0700177 Interface sw3Eth1 = new Interface(SW3_ETH1,
Jonathan Hart6cd2f352015-01-13 17:44:45 -0800178 interfaceIpAddresses3, MacAddress.valueOf("00:00:00:00:00:03"),
179 VlanId.NONE);
Pingpingf5d90932014-10-27 10:50:04 -0700180 interfaces.add(sw3Eth1);
181
Jonathan Hart41349e92015-02-09 14:14:02 -0800182 InterfaceIpAddress interfaceIpAddress4 =
183 new InterfaceIpAddress(IpAddress.valueOf("192.168.40.101"),
184 IpPrefix.valueOf("192.168.40.0/24"));
185 Interface sw4Eth1 = new Interface(SW4_ETH1,
186 Sets.newHashSet(interfaceIpAddress4),
187 MacAddress.valueOf("00:00:00:00:00:04"),
188 VlanId.vlanId((short) 1));
189
190 expect(interfaceService.getInterface(SW4_ETH1)).andReturn(sw4Eth1).anyTimes();
191 interfaces.add(sw4Eth1);
192
Pingpingf5d90932014-10-27 10:50:04 -0700193 expect(interfaceService.getInterface(SW1_ETH1)).andReturn(
194 sw1Eth1).anyTimes();
195 expect(interfaceService.getInterface(SW2_ETH1)).andReturn(
196 sw2Eth1).anyTimes();
197 expect(interfaceService.getInterface(SW3_ETH1)).andReturn(
198 sw3Eth1).anyTimes();
Jonathan Hart41349e92015-02-09 14:14:02 -0800199 expect(interfaceService.getInterfaces()).andReturn(interfaces).anyTimes();
Pingpingf5d90932014-10-27 10:50:04 -0700200 replay(interfaceService);
201 }
202
203 /**
Jonathan Hart41349e92015-02-09 14:14:02 -0800204 * Tests adding a FIB entry to the IntentSynchronizer.
205 *
206 * We verify that the synchronizer records the correct state and that the
207 * correct intent is submitted to the IntentService.
208 *
209 * @throws TestUtilsException
Pingpingf5d90932014-10-27 10:50:04 -0700210 */
Jonathan Hart41349e92015-02-09 14:14:02 -0800211 @Test
212 public void testFibAdd() throws TestUtilsException {
213 FibEntry fibEntry = new FibEntry(
214 Ip4Prefix.valueOf("1.1.1.0/24"),
215 Ip4Address.valueOf("192.168.10.1"),
216 MacAddress.valueOf("00:00:00:00:00:01"));
Pingpingf5d90932014-10-27 10:50:04 -0700217
Jonathan Hart41349e92015-02-09 14:14:02 -0800218 // Construct a MultiPointToSinglePointIntent intent
219 TrafficSelector.Builder selectorBuilder =
220 DefaultTrafficSelector.builder();
221 selectorBuilder.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(
222 fibEntry.prefix());
Pingpingf5d90932014-10-27 10:50:04 -0700223
Jonathan Hart41349e92015-02-09 14:14:02 -0800224 TrafficTreatment.Builder treatmentBuilder =
225 DefaultTrafficTreatment.builder();
226 treatmentBuilder.setEthDst(MacAddress.valueOf("00:00:00:00:00:01"));
Pingpingf5d90932014-10-27 10:50:04 -0700227
Jonathan Hart41349e92015-02-09 14:14:02 -0800228 Set<ConnectPoint> ingressPoints = new HashSet<>();
229 ingressPoints.add(SW2_ETH1);
230 ingressPoints.add(SW3_ETH1);
231 ingressPoints.add(SW4_ETH1);
232
233 MultiPointToSinglePointIntent intent =
234 new MultiPointToSinglePointIntent(APPID,
235 selectorBuilder.build(), treatmentBuilder.build(),
236 ingressPoints, SW1_ETH1);
237
238 // Setup the expected intents
Brian O'Connor03406a42015-02-03 17:28:57 -0800239// FIXME Jono needs to refactor
240// IntentOperations.Builder builder = IntentOperations.builder(APPID);
241// builder.addSubmitOperation(intent);
242// intentService.execute(TestIntentServiceHelper.eqExceptId(
243// builder.build()));
Jonathan Hart41349e92015-02-09 14:14:02 -0800244 replay(intentService);
245
246 intentSynchronizer.leaderChanged(true);
247 TestUtils.setField(intentSynchronizer, "isActivatedLeader", true);
248
249 FibUpdate fibUpdate = new FibUpdate(FibUpdate.Type.UPDATE,
250 fibEntry);
251 intentSynchronizer.update(Collections.singleton(fibUpdate),
252 Collections.emptyList());
253
Brian O'Connor03406a42015-02-03 17:28:57 -0800254 assertEquals(intentSynchronizer.getRouteIntents().size(), 1);
Jonathan Hart41349e92015-02-09 14:14:02 -0800255 Intent firstIntent =
256 intentSynchronizer.getRouteIntents().iterator().next();
257 IntentKey firstIntentKey = new IntentKey(firstIntent);
258 IntentKey intentKey = new IntentKey(intent);
259 assertTrue(firstIntentKey.equals(intentKey));
260 verify(intentService);
261 }
262
263 /**
264 * Tests adding a FIB entry with to a next hop in a VLAN.
265 *
266 * We verify that the synchronizer records the correct state and that the
267 * correct intent is submitted to the IntentService.
268 *
269 * @throws TestUtilsException
270 */
271 @Test
272 public void testFibAddWithVlan() throws TestUtilsException {
273 FibEntry fibEntry = new FibEntry(
274 Ip4Prefix.valueOf("3.3.3.0/24"),
275 Ip4Address.valueOf("192.168.40.1"),
276 MacAddress.valueOf("00:00:00:00:00:04"));
277
278 // Construct a MultiPointToSinglePointIntent intent
279 TrafficSelector.Builder selectorBuilder =
280 DefaultTrafficSelector.builder();
281 selectorBuilder.matchEthType(Ethernet.TYPE_IPV4)
282 .matchIPDst(fibEntry.prefix())
283 .matchVlanId(VlanId.ANY);
284
285 TrafficTreatment.Builder treatmentBuilder =
286 DefaultTrafficTreatment.builder();
287 treatmentBuilder.setEthDst(MacAddress.valueOf("00:00:00:00:00:04"))
288 .setVlanId(VlanId.vlanId((short) 1));
289
290 Set<ConnectPoint> ingressPoints = new HashSet<>();
291 ingressPoints.add(SW1_ETH1);
292 ingressPoints.add(SW2_ETH1);
293 ingressPoints.add(SW3_ETH1);
294
295 MultiPointToSinglePointIntent intent =
296 new MultiPointToSinglePointIntent(APPID,
297 selectorBuilder.build(), treatmentBuilder.build(),
298 ingressPoints, SW4_ETH1);
299
300 // Setup the expected intents
Brian O'Connor03406a42015-02-03 17:28:57 -0800301// FIXME Jono needs to refactor
302// IntentOperations.Builder builder = IntentOperations.builder(APPID);
303// builder.addSubmitOperation(intent);
304// intentService.execute(
305// TestIntentServiceHelper.eqExceptId(builder.build()));
Jonathan Hart41349e92015-02-09 14:14:02 -0800306 replay(intentService);
307
308 // Run the test
309 intentSynchronizer.leaderChanged(true);
310 TestUtils.setField(intentSynchronizer, "isActivatedLeader", true);
311 FibUpdate fibUpdate = new FibUpdate(FibUpdate.Type.UPDATE, fibEntry);
312
313 intentSynchronizer.update(Collections.singleton(fibUpdate),
314 Collections.emptyList());
315
316 // Verify
Brian O'Connor03406a42015-02-03 17:28:57 -0800317 assertEquals(intentSynchronizer.getRouteIntents().size(), 1);
Jonathan Hart41349e92015-02-09 14:14:02 -0800318 Intent firstIntent =
319 intentSynchronizer.getRouteIntents().iterator().next();
320 IntentKey firstIntentKey = new IntentKey(firstIntent);
321 IntentKey intentKey = new IntentKey(intent);
322 assertTrue(firstIntentKey.equals(intentKey));
323 verify(intentService);
324 }
325
326 /**
327 * Tests updating a FIB entry.
328 *
329 * We verify that the synchronizer records the correct state and that the
330 * correct intent is submitted to the IntentService.
331 *
332 * @throws TestUtilsException
333 */
334 @Test
335 public void testFibUpdate() throws TestUtilsException {
336 // Firstly add a route
337 testFibAdd();
338
339 Intent addedIntent =
340 intentSynchronizer.getRouteIntents().iterator().next();
341
342 // Start to construct a new route entry and new intent
343 FibEntry fibEntryUpdate = new FibEntry(
344 Ip4Prefix.valueOf("1.1.1.0/24"),
345 Ip4Address.valueOf("192.168.20.1"),
346 MacAddress.valueOf("00:00:00:00:00:02"));
347
348 // Construct a new MultiPointToSinglePointIntent intent
349 TrafficSelector.Builder selectorBuilderNew =
350 DefaultTrafficSelector.builder();
351 selectorBuilderNew.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(
352 fibEntryUpdate.prefix());
353
354 TrafficTreatment.Builder treatmentBuilderNew =
355 DefaultTrafficTreatment.builder();
356 treatmentBuilderNew.setEthDst(MacAddress.valueOf("00:00:00:00:00:02"));
Pingpingf5d90932014-10-27 10:50:04 -0700357
358
Jonathan Hart41349e92015-02-09 14:14:02 -0800359 Set<ConnectPoint> ingressPointsNew = new HashSet<>();
360 ingressPointsNew.add(SW1_ETH1);
361 ingressPointsNew.add(SW3_ETH1);
362 ingressPointsNew.add(SW4_ETH1);
Pingpingf5d90932014-10-27 10:50:04 -0700363
Jonathan Hart41349e92015-02-09 14:14:02 -0800364 MultiPointToSinglePointIntent intentNew =
365 new MultiPointToSinglePointIntent(APPID,
366 selectorBuilderNew.build(),
367 treatmentBuilderNew.build(),
368 ingressPointsNew, SW2_ETH1);
Pingpingf5d90932014-10-27 10:50:04 -0700369
Jonathan Hart41349e92015-02-09 14:14:02 -0800370 // Set up test expectation
371 reset(intentService);
372 // Setup the expected intents
Brian O'Connor03406a42015-02-03 17:28:57 -0800373// FIXME Jono needs to refactor
374// IntentOperations.Builder builder = IntentOperations.builder(APPID);
375// builder.addWithdrawOperation(addedIntent.id());
376// intentService.execute(TestIntentServiceHelper.eqExceptId(
377// builder.build()));
378// builder = IntentOperations.builder(APPID);
379// builder.addSubmitOperation(intentNew);
380// intentService.execute(TestIntentServiceHelper.eqExceptId(
381// builder.build()));
Jonathan Hart41349e92015-02-09 14:14:02 -0800382 replay(intentService);
Pingpingf5d90932014-10-27 10:50:04 -0700383
Jonathan Hart41349e92015-02-09 14:14:02 -0800384 // Call the update() method in IntentSynchronizer class
385 intentSynchronizer.leaderChanged(true);
386 TestUtils.setField(intentSynchronizer, "isActivatedLeader", true);
387 FibUpdate fibUpdate = new FibUpdate(FibUpdate.Type.UPDATE,
388 fibEntryUpdate);
389 intentSynchronizer.update(Collections.singletonList(fibUpdate),
390 Collections.emptyList());
Pingpingf5d90932014-10-27 10:50:04 -0700391
Jonathan Hart41349e92015-02-09 14:14:02 -0800392 // Verify
Brian O'Connor03406a42015-02-03 17:28:57 -0800393 assertEquals(intentSynchronizer.getRouteIntents().size(), 1);
Jonathan Hart41349e92015-02-09 14:14:02 -0800394 Intent firstIntent =
395 intentSynchronizer.getRouteIntents().iterator().next();
396 IntentKey firstIntentKey = new IntentKey(firstIntent);
397 IntentKey intentNewKey = new IntentKey(intentNew);
398 assertTrue(firstIntentKey.equals(intentNewKey));
399 verify(intentService);
400 }
Pingpingf5d90932014-10-27 10:50:04 -0700401
Jonathan Hart41349e92015-02-09 14:14:02 -0800402 /**
403 * Tests deleting a FIB entry.
404 *
405 * We verify that the synchronizer records the correct state and that the
406 * correct intent is withdrawn from the IntentService.
407 *
408 * @throws TestUtilsException
409 */
410 @Test
411 public void testFibDelete() throws TestUtilsException {
412 // Firstly add a route
413 testFibAdd();
Pingpingf5d90932014-10-27 10:50:04 -0700414
Jonathan Hart41349e92015-02-09 14:14:02 -0800415 Intent addedIntent =
416 intentSynchronizer.getRouteIntents().iterator().next();
417
418 // Construct the existing route entry
419 FibEntry fibEntry = new FibEntry(
420 Ip4Prefix.valueOf("1.1.1.0/24"), null, null);
421
422 // Set up expectation
423 reset(intentService);
424 // Setup the expected intents
Brian O'Connor03406a42015-02-03 17:28:57 -0800425// FIXME Jono needs to refactor
426// IntentOperations.Builder builder = IntentOperations.builder(APPID);
427// builder.addWithdrawOperation(addedIntent.id());
428// intentService.execute(TestIntentServiceHelper.eqExceptId(
429// builder.build()));
Jonathan Hart41349e92015-02-09 14:14:02 -0800430 replay(intentService);
431
432 // Call the update() method in IntentSynchronizer class
433 intentSynchronizer.leaderChanged(true);
434 TestUtils.setField(intentSynchronizer, "isActivatedLeader", true);
435 FibUpdate fibUpdate = new FibUpdate(FibUpdate.Type.DELETE, fibEntry);
436 intentSynchronizer.update(Collections.emptyList(),
437 Collections.singletonList(fibUpdate));
438
439 // Verify
Brian O'Connor03406a42015-02-03 17:28:57 -0800440 assertEquals(intentSynchronizer.getRouteIntents().size(), 0);
Jonathan Hart41349e92015-02-09 14:14:02 -0800441 verify(intentService);
Pingpingf5d90932014-10-27 10:50:04 -0700442 }
443
444 /**
445 * This method tests the behavior of intent Synchronizer.
446 *
447 * @throws TestUtilsException
448 */
449 @Test
450 public void testIntentSync() throws TestUtilsException {
451
452 //
453 // Construct routes and intents.
454 // This test simulates the following cases during the master change
455 // time interval:
456 // 1. RouteEntry1 did not change and the intent also did not change.
457 // 2. RouteEntry2 was deleted, but the intent was not deleted.
458 // 3. RouteEntry3 was newly added, and the intent was also submitted.
459 // 4. RouteEntry4 was updated to RouteEntry4Update, and the intent was
460 // also updated to a new one.
461 // 5. RouteEntry5 did not change, but its intent id changed.
462 // 6. RouteEntry6 was newly added, but the intent was not submitted.
463 //
464 RouteEntry routeEntry1 = new RouteEntry(
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800465 Ip4Prefix.valueOf("1.1.1.0/24"),
466 Ip4Address.valueOf("192.168.10.1"));
Pingpingf5d90932014-10-27 10:50:04 -0700467
468 RouteEntry routeEntry2 = new RouteEntry(
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800469 Ip4Prefix.valueOf("2.2.2.0/24"),
470 Ip4Address.valueOf("192.168.20.1"));
Pingpingf5d90932014-10-27 10:50:04 -0700471
472 RouteEntry routeEntry3 = new RouteEntry(
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800473 Ip4Prefix.valueOf("3.3.3.0/24"),
474 Ip4Address.valueOf("192.168.30.1"));
Pingpingf5d90932014-10-27 10:50:04 -0700475
476 RouteEntry routeEntry4 = new RouteEntry(
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800477 Ip4Prefix.valueOf("4.4.4.0/24"),
478 Ip4Address.valueOf("192.168.30.1"));
Pingpingf5d90932014-10-27 10:50:04 -0700479
480 RouteEntry routeEntry4Update = new RouteEntry(
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800481 Ip4Prefix.valueOf("4.4.4.0/24"),
482 Ip4Address.valueOf("192.168.20.1"));
Pingpingf5d90932014-10-27 10:50:04 -0700483
484 RouteEntry routeEntry5 = new RouteEntry(
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800485 Ip4Prefix.valueOf("5.5.5.0/24"),
486 Ip4Address.valueOf("192.168.10.1"));
Pingpingf5d90932014-10-27 10:50:04 -0700487
488 RouteEntry routeEntry6 = new RouteEntry(
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800489 Ip4Prefix.valueOf("6.6.6.0/24"),
490 Ip4Address.valueOf("192.168.10.1"));
Pingpingf5d90932014-10-27 10:50:04 -0700491
Jonathan Hartec2df012014-10-23 16:40:24 -0700492 RouteEntry routeEntry7 = new RouteEntry(
Pavlin Radoslavov6b570732014-11-06 13:16:45 -0800493 Ip4Prefix.valueOf("7.7.7.0/24"),
494 Ip4Address.valueOf("192.168.10.1"));
Jonathan Hartec2df012014-10-23 16:40:24 -0700495
Pingpingf5d90932014-10-27 10:50:04 -0700496 MultiPointToSinglePointIntent intent1 = intentBuilder(
497 routeEntry1.prefix(), "00:00:00:00:00:01", SW1_ETH1);
498 MultiPointToSinglePointIntent intent2 = intentBuilder(
499 routeEntry2.prefix(), "00:00:00:00:00:02", SW2_ETH1);
500 MultiPointToSinglePointIntent intent3 = intentBuilder(
501 routeEntry3.prefix(), "00:00:00:00:00:03", SW3_ETH1);
502 MultiPointToSinglePointIntent intent4 = intentBuilder(
503 routeEntry4.prefix(), "00:00:00:00:00:03", SW3_ETH1);
504 MultiPointToSinglePointIntent intent4Update = intentBuilder(
505 routeEntry4Update.prefix(), "00:00:00:00:00:02", SW2_ETH1);
506 MultiPointToSinglePointIntent intent5 = intentBuilder(
507 routeEntry5.prefix(), "00:00:00:00:00:01", SW1_ETH1);
Jonathan Hartec2df012014-10-23 16:40:24 -0700508 MultiPointToSinglePointIntent intent7 = intentBuilder(
509 routeEntry7.prefix(), "00:00:00:00:00:01", SW1_ETH1);
Pingpingf5d90932014-10-27 10:50:04 -0700510
511 // Compose a intent, which is equal to intent5 but the id is different.
512 MultiPointToSinglePointIntent intent5New =
513 staticIntentBuilder(intent5, routeEntry5, "00:00:00:00:00:01");
Pavlin Radoslavova7243cc2014-11-22 21:38:02 -0800514 assertThat(IntentSynchronizer.IntentKey.equalIntents(
515 intent5, intent5New),
516 is(true));
Jonathan Hartec2df012014-10-23 16:40:24 -0700517 assertFalse(intent5.equals(intent5New));
Pingpingf5d90932014-10-27 10:50:04 -0700518
519 MultiPointToSinglePointIntent intent6 = intentBuilder(
520 routeEntry6.prefix(), "00:00:00:00:00:01", SW1_ETH1);
521
Jonathan Hart41349e92015-02-09 14:14:02 -0800522 // Set up the routeIntents field in IntentSynchronizer class
Pavlin Radoslavov3a0a52e2015-01-06 17:41:37 -0800523 ConcurrentHashMap<IpPrefix, MultiPointToSinglePointIntent>
524 routeIntents = new ConcurrentHashMap<>();
Pavlin Radoslavova7243cc2014-11-22 21:38:02 -0800525 routeIntents.put(routeEntry1.prefix(), intent1);
526 routeIntents.put(routeEntry3.prefix(), intent3);
527 routeIntents.put(routeEntry4Update.prefix(), intent4Update);
528 routeIntents.put(routeEntry5.prefix(), intent5New);
529 routeIntents.put(routeEntry6.prefix(), intent6);
530 routeIntents.put(routeEntry7.prefix(), intent7);
531 TestUtils.setField(intentSynchronizer, "routeIntents", routeIntents);
Pingpingf5d90932014-10-27 10:50:04 -0700532
533 // Set up expectation
534 reset(intentService);
535 Set<Intent> intents = new HashSet<Intent>();
536 intents.add(intent1);
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800537 expect(intentService.getIntentState(intent1.key()))
Jonathan Hartec2df012014-10-23 16:40:24 -0700538 .andReturn(IntentState.INSTALLED).anyTimes();
Pingpingf5d90932014-10-27 10:50:04 -0700539 intents.add(intent2);
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800540 expect(intentService.getIntentState(intent2.key()))
Jonathan Hartec2df012014-10-23 16:40:24 -0700541 .andReturn(IntentState.INSTALLED).anyTimes();
Pingpingf5d90932014-10-27 10:50:04 -0700542 intents.add(intent4);
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800543 expect(intentService.getIntentState(intent4.key()))
Jonathan Hartec2df012014-10-23 16:40:24 -0700544 .andReturn(IntentState.INSTALLED).anyTimes();
Pingpingf5d90932014-10-27 10:50:04 -0700545 intents.add(intent5);
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800546 expect(intentService.getIntentState(intent5.key()))
Jonathan Hartec2df012014-10-23 16:40:24 -0700547 .andReturn(IntentState.INSTALLED).anyTimes();
548 intents.add(intent7);
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800549 expect(intentService.getIntentState(intent7.key()))
Jonathan Hartec2df012014-10-23 16:40:24 -0700550 .andReturn(IntentState.WITHDRAWING).anyTimes();
Pingpingf5d90932014-10-27 10:50:04 -0700551 expect(intentService.getIntents()).andReturn(intents).anyTimes();
552
Brian O'Connor03406a42015-02-03 17:28:57 -0800553 intentService.withdraw(intent2);
554 intentService.withdraw(intent4);
Pavlin Radoslavova7243cc2014-11-22 21:38:02 -0800555
Brian O'Connor03406a42015-02-03 17:28:57 -0800556 intentService.submit(intent3);
557 intentService.submit(intent4Update);
558 intentService.submit(intent6);
559 intentService.submit(intent7);
Pingpingf5d90932014-10-27 10:50:04 -0700560 replay(intentService);
561
562 // Start the test
Pavlin Radoslavova071b1e2014-11-17 13:37:57 -0800563 intentSynchronizer.leaderChanged(true);
Pavlin Radoslavova7243cc2014-11-22 21:38:02 -0800564 intentSynchronizer.synchronizeIntents();
Pingpingf5d90932014-10-27 10:50:04 -0700565
566 // Verify
Pavlin Radoslavova7243cc2014-11-22 21:38:02 -0800567 assertEquals(intentSynchronizer.getRouteIntents().size(), 6);
568 assertTrue(intentSynchronizer.getRouteIntents().contains(intent1));
569 assertTrue(intentSynchronizer.getRouteIntents().contains(intent3));
570 assertTrue(intentSynchronizer.getRouteIntents().contains(intent4Update));
571 assertTrue(intentSynchronizer.getRouteIntents().contains(intent5));
572 assertTrue(intentSynchronizer.getRouteIntents().contains(intent6));
Pingpingf5d90932014-10-27 10:50:04 -0700573
574 verify(intentService);
575 }
576
577 /**
578 * MultiPointToSinglePointIntent builder.
579 *
580 * @param ipPrefix the ipPrefix to match
581 * @param nextHopMacAddress to which the destination MAC address in packet
582 * should be rewritten
583 * @param egressPoint to which packets should be sent
584 * @return the constructed MultiPointToSinglePointIntent
585 */
Pavlin Radoslavov3a0a52e2015-01-06 17:41:37 -0800586 private MultiPointToSinglePointIntent intentBuilder(IpPrefix ipPrefix,
Pingpingf5d90932014-10-27 10:50:04 -0700587 String nextHopMacAddress, ConnectPoint egressPoint) {
588
589 TrafficSelector.Builder selectorBuilder =
590 DefaultTrafficSelector.builder();
Pavlin Radoslavov3a0a52e2015-01-06 17:41:37 -0800591 if (ipPrefix.version() == Ip4Address.VERSION) {
592 selectorBuilder.matchEthType(Ethernet.TYPE_IPV4); // IPv4
593 } else {
594 selectorBuilder.matchEthType(Ethernet.TYPE_IPV6); // IPv6
595 }
596 selectorBuilder.matchIPDst(ipPrefix);
Pingpingf5d90932014-10-27 10:50:04 -0700597
598 TrafficTreatment.Builder treatmentBuilder =
599 DefaultTrafficTreatment.builder();
600 treatmentBuilder.setEthDst(MacAddress.valueOf(nextHopMacAddress));
601
602 Set<ConnectPoint> ingressPoints = new HashSet<ConnectPoint>();
603 for (Interface intf : interfaceService.getInterfaces()) {
604 if (!intf.equals(interfaceService.getInterface(egressPoint))) {
605 ConnectPoint srcPort = intf.connectPoint();
606 ingressPoints.add(srcPort);
607 }
608 }
609 MultiPointToSinglePointIntent intent =
610 new MultiPointToSinglePointIntent(APPID,
611 selectorBuilder.build(), treatmentBuilder.build(),
612 ingressPoints, egressPoint);
613 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}