Pingping
Committed by Pavlin Radoslavov

IntentSync test without state

The current Router class does not check the Intent state.
So I did not add the state in this patch.
I will push another patch for testing the intent state.

Change-Id: Idb44dcace5f33a0144852a999445931bc2189448
...@@ -447,7 +447,8 @@ public class Router implements RouteListener { ...@@ -447,7 +447,8 @@ public class Router implements RouteListener {
447 Objects.equal(action1, action2) && 447 Objects.equal(action1, action2) &&
448 Objects.equal(egressPort1, egressPort2) && 448 Objects.equal(egressPort1, egressPort2) &&
449 Objects.equal(ingressPorts1, ingressPorts2);*/ 449 Objects.equal(ingressPorts1, ingressPorts2);*/
450 - return Objects.equal(intent1.selector(), intent2.selector()) && 450 + return Objects.equal(intent1.appId(), intent2.appId()) &&
451 + Objects.equal(intent1.selector(), intent2.selector()) &&
451 Objects.equal(intent1.treatment(), intent2.treatment()) && 452 Objects.equal(intent1.treatment(), intent2.treatment()) &&
452 Objects.equal(intent1.ingressPoints(), intent2.ingressPoints()) && 453 Objects.equal(intent1.ingressPoints(), intent2.ingressPoints()) &&
453 Objects.equal(intent1.egressPoint(), intent2.egressPoint()); 454 Objects.equal(intent1.egressPoint(), intent2.egressPoint());
......
1 +package org.onlab.onos.sdnip;
2 +
3 +import static org.easymock.EasyMock.anyObject;
4 +import static org.easymock.EasyMock.createMock;
5 +import static org.easymock.EasyMock.expect;
6 +import static org.easymock.EasyMock.expectLastCall;
7 +import static org.easymock.EasyMock.replay;
8 +import static org.easymock.EasyMock.reset;
9 +import static org.easymock.EasyMock.verify;
10 +import static org.junit.Assert.assertEquals;
11 +import static org.junit.Assert.assertTrue;
12 +
13 +import java.util.HashSet;
14 +import java.util.Set;
15 +import java.util.concurrent.ConcurrentHashMap;
16 +
17 +import org.junit.Before;
18 +import org.junit.Test;
19 +import org.onlab.junit.TestUtils;
20 +import org.onlab.junit.TestUtils.TestUtilsException;
21 +import org.onlab.onos.core.ApplicationId;
22 +import org.onlab.onos.net.ConnectPoint;
23 +import org.onlab.onos.net.DefaultHost;
24 +import org.onlab.onos.net.DeviceId;
25 +import org.onlab.onos.net.Host;
26 +import org.onlab.onos.net.HostId;
27 +import org.onlab.onos.net.HostLocation;
28 +import org.onlab.onos.net.PortNumber;
29 +import org.onlab.onos.net.flow.DefaultTrafficSelector;
30 +import org.onlab.onos.net.flow.DefaultTrafficTreatment;
31 +import org.onlab.onos.net.flow.TrafficSelector;
32 +import org.onlab.onos.net.flow.TrafficTreatment;
33 +import org.onlab.onos.net.host.HostListener;
34 +import org.onlab.onos.net.host.HostService;
35 +import org.onlab.onos.net.host.InterfaceIpAddress;
36 +import org.onlab.onos.net.intent.Intent;
37 +import org.onlab.onos.net.intent.IntentService;
38 +import org.onlab.onos.net.intent.MultiPointToSinglePointIntent;
39 +import org.onlab.onos.net.provider.ProviderId;
40 +import org.onlab.onos.sdnip.config.Interface;
41 +import org.onlab.packet.Ethernet;
42 +import org.onlab.packet.IpAddress;
43 +import org.onlab.packet.IpPrefix;
44 +import org.onlab.packet.MacAddress;
45 +import org.onlab.packet.VlanId;
46 +
47 +import com.google.common.collect.Sets;
48 +import com.googlecode.concurrenttrees.radix.node.concrete.DefaultByteArrayNodeFactory;
49 +import com.googlecode.concurrenttrees.radixinverted.ConcurrentInvertedRadixTree;
50 +import com.googlecode.concurrenttrees.radixinverted.InvertedRadixTree;
51 +
52 +/**
53 + * This class tests the intent synchronization function in Router class.
54 + */
55 +public class IntentSyncTest {
56 +
57 + private InterfaceService interfaceService;
58 + private IntentService intentService;
59 + private HostService hostService;
60 +
61 + 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));
72 +
73 + private Router router;
74 +
75 + private static final ApplicationId APPID = new ApplicationId() {
76 + @Override
77 + public short id() {
78 + return 1;
79 + }
80 +
81 + @Override
82 + public String name() {
83 + return "SDNIP";
84 + }
85 + };
86 +
87 + @Before
88 + public void setUp() throws Exception {
89 + setUpInterfaceService();
90 + setUpHostService();
91 + intentService = createMock(IntentService.class);
92 +
93 + router = new Router(APPID, intentService,
94 + hostService, null, interfaceService);
95 + }
96 +
97 + /**
98 + * Sets up InterfaceService.
99 + */
100 + private void setUpInterfaceService() {
101 +
102 + interfaceService = createMock(InterfaceService.class);
103 +
104 + Set<Interface> interfaces = Sets.newHashSet();
105 +
106 + Set<InterfaceIpAddress> interfaceIpAddresses1 = Sets.newHashSet();
107 + interfaceIpAddresses1.add(new InterfaceIpAddress(
108 + IpAddress.valueOf("192.168.10.101"),
109 + IpPrefix.valueOf("192.168.10.0/24")));
110 + Interface sw1Eth1 = new Interface(SW1_ETH1,
111 + interfaceIpAddresses1, MacAddress.valueOf("00:00:00:00:00:01"));
112 + interfaces.add(sw1Eth1);
113 +
114 + Set<InterfaceIpAddress> interfaceIpAddresses2 = Sets.newHashSet();
115 + interfaceIpAddresses2.add(new InterfaceIpAddress(
116 + IpAddress.valueOf("192.168.20.101"),
117 + IpPrefix.valueOf("192.168.20.0/24")));
118 + Interface sw2Eth1 = new Interface(SW2_ETH1,
119 + interfaceIpAddresses2, MacAddress.valueOf("00:00:00:00:00:02"));
120 + interfaces.add(sw2Eth1);
121 +
122 + Set<InterfaceIpAddress> interfaceIpAddresses3 = Sets.newHashSet();
123 + interfaceIpAddresses3.add(new InterfaceIpAddress(
124 + IpAddress.valueOf("192.168.30.101"),
125 + IpPrefix.valueOf("192.168.30.0/24")));
126 + Interface sw3Eth1 = new Interface(SW3_ETH1,
127 + interfaceIpAddresses3, MacAddress.valueOf("00:00:00:00:00:03"));
128 + interfaces.add(sw3Eth1);
129 +
130 + expect(interfaceService.getInterface(SW1_ETH1)).andReturn(
131 + sw1Eth1).anyTimes();
132 + expect(interfaceService.getInterface(SW2_ETH1)).andReturn(
133 + sw2Eth1).anyTimes();
134 + expect(interfaceService.getInterface(SW3_ETH1)).andReturn(
135 + sw3Eth1).anyTimes();
136 + expect(interfaceService.getInterfaces()).andReturn(
137 + interfaces).anyTimes();
138 + replay(interfaceService);
139 + }
140 +
141 + /**
142 + * Sets up the host service with details of hosts.
143 + */
144 + private void setUpHostService() {
145 + hostService = createMock(HostService.class);
146 +
147 + hostService.addListener(anyObject(HostListener.class));
148 + expectLastCall().anyTimes();
149 +
150 + IpAddress host1Address = IpAddress.valueOf("192.168.10.1");
151 + Host host1 = new DefaultHost(ProviderId.NONE, HostId.NONE,
152 + MacAddress.valueOf("00:00:00:00:00:01"), VlanId.NONE,
153 + new HostLocation(SW1_ETH1, 1),
154 + Sets.newHashSet(host1Address));
155 +
156 + expect(hostService.getHostsByIp(host1Address))
157 + .andReturn(Sets.newHashSet(host1)).anyTimes();
158 + hostService.startMonitoringIp(host1Address);
159 + expectLastCall().anyTimes();
160 +
161 +
162 + IpAddress host2Address = IpAddress.valueOf("192.168.20.1");
163 + Host host2 = new DefaultHost(ProviderId.NONE, HostId.NONE,
164 + MacAddress.valueOf("00:00:00:00:00:02"), VlanId.NONE,
165 + new HostLocation(SW2_ETH1, 1),
166 + Sets.newHashSet(host2Address));
167 +
168 + expect(hostService.getHostsByIp(host2Address))
169 + .andReturn(Sets.newHashSet(host2)).anyTimes();
170 + hostService.startMonitoringIp(host2Address);
171 + expectLastCall().anyTimes();
172 +
173 +
174 + IpAddress host3Address = IpAddress.valueOf("192.168.30.1");
175 + Host host3 = new DefaultHost(ProviderId.NONE, HostId.NONE,
176 + MacAddress.valueOf("00:00:00:00:00:03"), VlanId.NONE,
177 + new HostLocation(SW3_ETH1, 1),
178 + Sets.newHashSet(host3Address));
179 +
180 + expect(hostService.getHostsByIp(host3Address))
181 + .andReturn(Sets.newHashSet(host3)).anyTimes();
182 + hostService.startMonitoringIp(host3Address);
183 + expectLastCall().anyTimes();
184 +
185 +
186 + replay(hostService);
187 + }
188 +
189 + /**
190 + * This method tests the behavior of intent Synchronizer.
191 + *
192 + * @throws TestUtilsException
193 + */
194 + @Test
195 + public void testIntentSync() throws TestUtilsException {
196 +
197 + //
198 + // Construct routes and intents.
199 + // This test simulates the following cases during the master change
200 + // time interval:
201 + // 1. RouteEntry1 did not change and the intent also did not change.
202 + // 2. RouteEntry2 was deleted, but the intent was not deleted.
203 + // 3. RouteEntry3 was newly added, and the intent was also submitted.
204 + // 4. RouteEntry4 was updated to RouteEntry4Update, and the intent was
205 + // also updated to a new one.
206 + // 5. RouteEntry5 did not change, but its intent id changed.
207 + // 6. RouteEntry6 was newly added, but the intent was not submitted.
208 + //
209 + RouteEntry routeEntry1 = new RouteEntry(
210 + IpPrefix.valueOf("1.1.1.0/24"),
211 + IpAddress.valueOf("192.168.10.1"));
212 +
213 + RouteEntry routeEntry2 = new RouteEntry(
214 + IpPrefix.valueOf("2.2.2.0/24"),
215 + IpAddress.valueOf("192.168.20.1"));
216 +
217 + RouteEntry routeEntry3 = new RouteEntry(
218 + IpPrefix.valueOf("3.3.3.0/24"),
219 + IpAddress.valueOf("192.168.30.1"));
220 +
221 + RouteEntry routeEntry4 = new RouteEntry(
222 + IpPrefix.valueOf("4.4.4.0/24"),
223 + IpAddress.valueOf("192.168.30.1"));
224 +
225 + RouteEntry routeEntry4Update = new RouteEntry(
226 + IpPrefix.valueOf("4.4.4.0/24"),
227 + IpAddress.valueOf("192.168.20.1"));
228 +
229 + RouteEntry routeEntry5 = new RouteEntry(
230 + IpPrefix.valueOf("5.5.5.0/24"),
231 + IpAddress.valueOf("192.168.10.1"));
232 +
233 + RouteEntry routeEntry6 = new RouteEntry(
234 + IpPrefix.valueOf("6.6.6.0/24"),
235 + IpAddress.valueOf("192.168.10.1"));
236 +
237 + MultiPointToSinglePointIntent intent1 = intentBuilder(
238 + routeEntry1.prefix(), "00:00:00:00:00:01", SW1_ETH1);
239 + MultiPointToSinglePointIntent intent2 = intentBuilder(
240 + routeEntry2.prefix(), "00:00:00:00:00:02", SW2_ETH1);
241 + MultiPointToSinglePointIntent intent3 = intentBuilder(
242 + routeEntry3.prefix(), "00:00:00:00:00:03", SW3_ETH1);
243 + MultiPointToSinglePointIntent intent4 = intentBuilder(
244 + routeEntry4.prefix(), "00:00:00:00:00:03", SW3_ETH1);
245 + MultiPointToSinglePointIntent intent4Update = intentBuilder(
246 + routeEntry4Update.prefix(), "00:00:00:00:00:02", SW2_ETH1);
247 + MultiPointToSinglePointIntent intent5 = intentBuilder(
248 + routeEntry5.prefix(), "00:00:00:00:00:01", SW1_ETH1);
249 +
250 + // Compose a intent, which is equal to intent5 but the id is different.
251 + MultiPointToSinglePointIntent intent5New =
252 + staticIntentBuilder(intent5, routeEntry5, "00:00:00:00:00:01");
253 + assertTrue(TestUtils.callMethod(router,
254 + "compareMultiPointToSinglePointIntents",
255 + new Class<?>[] {MultiPointToSinglePointIntent.class,
256 + MultiPointToSinglePointIntent.class},
257 + intent5, intent5New).equals(true));
258 + assertTrue(!intent5.equals(intent5New));
259 +
260 + MultiPointToSinglePointIntent intent6 = intentBuilder(
261 + routeEntry6.prefix(), "00:00:00:00:00:01", SW1_ETH1);
262 +
263 + // Set up the bgpRoutes and pushedRouteIntents fields in Router class
264 + InvertedRadixTree<RouteEntry> bgpRoutes =
265 + new ConcurrentInvertedRadixTree<>(
266 + new DefaultByteArrayNodeFactory());
267 + bgpRoutes.put(RouteEntry.createBinaryString(routeEntry1.prefix()),
268 + routeEntry1);
269 + bgpRoutes.put(RouteEntry.createBinaryString(routeEntry3.prefix()),
270 + routeEntry3);
271 + bgpRoutes.put(RouteEntry.createBinaryString(routeEntry4Update.prefix()),
272 + routeEntry4Update);
273 + bgpRoutes.put(RouteEntry.createBinaryString(routeEntry5.prefix()),
274 + routeEntry5);
275 + bgpRoutes.put(RouteEntry.createBinaryString(routeEntry6.prefix()),
276 + routeEntry6);
277 + TestUtils.setField(router, "bgpRoutes", bgpRoutes);
278 +
279 + ConcurrentHashMap<IpPrefix, MultiPointToSinglePointIntent>
280 + pushedRouteIntents = new ConcurrentHashMap<>();
281 + pushedRouteIntents.put(routeEntry1.prefix(), intent1);
282 + pushedRouteIntents.put(routeEntry3.prefix(), intent3);
283 + pushedRouteIntents.put(routeEntry4Update.prefix(), intent4Update);
284 + pushedRouteIntents.put(routeEntry5.prefix(), intent5New);
285 + pushedRouteIntents.put(routeEntry6.prefix(), intent6);
286 + TestUtils.setField(router, "pushedRouteIntents", pushedRouteIntents);
287 +
288 + // Set up expectation
289 + reset(intentService);
290 + Set<Intent> intents = new HashSet<Intent>();
291 + intents.add(intent1);
292 + intents.add(intent2);
293 + intents.add(intent4);
294 + intents.add(intent5);
295 + expect(intentService.getIntents()).andReturn(intents).anyTimes();
296 +
297 + intentService.withdraw(intent2);
298 + intentService.submit(intent3);
299 + intentService.withdraw(intent4);
300 + intentService.submit(intent4Update);
301 + intentService.submit(intent6);
302 + replay(intentService);
303 +
304 + // Start the test
305 + router.leaderChanged(true);
306 + TestUtils.callMethod(router, "syncIntents", new Class<?>[] {});
307 +
308 + // Verify
309 + assertEquals(router.getRoutes().size(), 5);
310 + assertTrue(router.getRoutes().contains(routeEntry1));
311 + assertTrue(router.getRoutes().contains(routeEntry3));
312 + assertTrue(router.getRoutes().contains(routeEntry4Update));
313 + assertTrue(router.getRoutes().contains(routeEntry5));
314 + assertTrue(router.getRoutes().contains(routeEntry6));
315 +
316 + assertEquals(router.getPushedRouteIntents().size(), 5);
317 + assertTrue(router.getPushedRouteIntents().contains(intent1));
318 + assertTrue(router.getPushedRouteIntents().contains(intent3));
319 + assertTrue(router.getPushedRouteIntents().contains(intent4Update));
320 + assertTrue(router.getPushedRouteIntents().contains(intent5));
321 + assertTrue(router.getPushedRouteIntents().contains(intent6));
322 +
323 + verify(intentService);
324 + }
325 +
326 + /**
327 + * MultiPointToSinglePointIntent builder.
328 + *
329 + * @param ipPrefix the ipPrefix to match
330 + * @param nextHopMacAddress to which the destination MAC address in packet
331 + * should be rewritten
332 + * @param egressPoint to which packets should be sent
333 + * @return the constructed MultiPointToSinglePointIntent
334 + */
335 + private MultiPointToSinglePointIntent intentBuilder(IpPrefix ipPrefix,
336 + String nextHopMacAddress, ConnectPoint egressPoint) {
337 +
338 + TrafficSelector.Builder selectorBuilder =
339 + DefaultTrafficSelector.builder();
340 + selectorBuilder.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(ipPrefix);
341 +
342 + TrafficTreatment.Builder treatmentBuilder =
343 + DefaultTrafficTreatment.builder();
344 + treatmentBuilder.setEthDst(MacAddress.valueOf(nextHopMacAddress));
345 +
346 + Set<ConnectPoint> ingressPoints = new HashSet<ConnectPoint>();
347 + for (Interface intf : interfaceService.getInterfaces()) {
348 + if (!intf.equals(interfaceService.getInterface(egressPoint))) {
349 + ConnectPoint srcPort = intf.connectPoint();
350 + ingressPoints.add(srcPort);
351 + }
352 + }
353 + MultiPointToSinglePointIntent intent =
354 + new MultiPointToSinglePointIntent(APPID,
355 + selectorBuilder.build(), treatmentBuilder.build(),
356 + ingressPoints, egressPoint);
357 + return intent;
358 + }
359 +
360 + /**
361 + * A static MultiPointToSinglePointIntent builder, the returned intent is
362 + * equal to the input intent except that the id is different.
363 + *
364 + *
365 + * @param intent the intent to be used for building a new intent
366 + * @param routeEntry the relative routeEntry of the intent
367 + * @return the newly constructed MultiPointToSinglePointIntent
368 + * @throws TestUtilsException
369 + */
370 + private MultiPointToSinglePointIntent staticIntentBuilder(
371 + MultiPointToSinglePointIntent intent, RouteEntry routeEntry,
372 + String nextHopMacAddress) throws TestUtilsException {
373 +
374 + // Use a different egress ConnectPoint with that in intent
375 + // to generate a different id
376 + MultiPointToSinglePointIntent intentNew = intentBuilder(
377 + routeEntry.prefix(), nextHopMacAddress, SW2_ETH1);
378 + TestUtils.setField(intentNew, "egressPoint", intent.egressPoint());
379 + TestUtils.setField(intentNew,
380 + "ingressPoints", intent.ingressPoints());
381 + return intentNew;
382 + }
383 +}