blob: 3e25bd6de37841293bc8e73babfb0825a3faa205 [file] [log] [blame]
Ray Milkeyb3c5ce22015-08-10 09:07:36 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2015-present Open Networking Foundation
Ray Milkeyb3c5ce22015-08-10 09:07:36 -07003 *
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 */
16package org.onosproject.store.group.impl;
17
18import java.util.ArrayList;
19import java.util.LinkedList;
20import java.util.List;
21
22import org.junit.After;
23import org.junit.Before;
24import org.junit.Test;
25import org.onlab.junit.TestUtils;
alshabibb0285992016-03-28 23:30:37 -070026import org.onosproject.cfg.ComponentConfigAdapter;
Charles Chanf4838a72015-12-07 18:13:45 -080027import org.onosproject.cluster.NodeId;
Ray Milkeyb3c5ce22015-08-10 09:07:36 -070028import org.onosproject.core.GroupId;
29import org.onosproject.mastership.MastershipServiceAdapter;
30import org.onosproject.net.DeviceId;
31import org.onosproject.net.MastershipRole;
32import org.onosproject.net.PortNumber;
33import org.onosproject.net.flow.DefaultTrafficTreatment;
34import org.onosproject.net.flow.TrafficTreatment;
35import org.onosproject.net.group.DefaultGroup;
36import org.onosproject.net.group.DefaultGroupBucket;
37import org.onosproject.net.group.DefaultGroupDescription;
38import org.onosproject.net.group.DefaultGroupKey;
39import org.onosproject.net.group.Group;
40import org.onosproject.net.group.GroupBucket;
41import org.onosproject.net.group.GroupBuckets;
42import org.onosproject.net.group.GroupDescription;
43import org.onosproject.net.group.GroupEvent;
44import org.onosproject.net.group.GroupKey;
45import org.onosproject.net.group.GroupOperation;
46import org.onosproject.net.group.GroupStore;
47import org.onosproject.net.group.GroupStoreDelegate;
48import org.onosproject.store.cluster.messaging.ClusterCommunicationServiceAdapter;
Madan Jampani0b847532016-03-03 13:44:15 -080049import org.onosproject.store.service.ConsistentMap;
Ray Milkeyb3c5ce22015-08-10 09:07:36 -070050import org.onosproject.store.service.TestStorageService;
51
52import com.google.common.collect.ImmutableList;
53import com.google.common.collect.Lists;
54import com.google.common.testing.EqualsTester;
55
56import static org.hamcrest.MatcherAssert.assertThat;
57import static org.hamcrest.Matchers.hasSize;
58import static org.hamcrest.Matchers.instanceOf;
59import static org.hamcrest.Matchers.is;
60import static org.hamcrest.Matchers.notNullValue;
61import static org.hamcrest.Matchers.nullValue;
Victor Silvadf1eeae2016-08-12 15:28:57 -030062import static org.junit.Assert.assertEquals;
Ray Milkeyb3c5ce22015-08-10 09:07:36 -070063import static org.onosproject.net.NetTestTools.APP_ID;
64import static org.onosproject.net.NetTestTools.did;
Jayasree Ghosh2d459852016-07-02 19:06:52 +053065import static org.onosproject.net.group.GroupDescription.Type.*;
66import static org.onosproject.net.group.GroupStore.UpdateType.*;
Ray Milkeyb3c5ce22015-08-10 09:07:36 -070067/**
68 * Distributed group store test.
69 */
70public class DistributedGroupStoreTest {
71
72 DeviceId deviceId1 = did("dev1");
73 DeviceId deviceId2 = did("dev2");
Yi Tsengfa394de2017-02-01 11:26:40 -080074 GroupId groupId1 = new GroupId(1);
75 GroupId groupId2 = new GroupId(2);
76 GroupId groupId3 = new GroupId(3);
Ray Milkeyb3c5ce22015-08-10 09:07:36 -070077 GroupKey groupKey1 = new DefaultGroupKey("abc".getBytes());
78 GroupKey groupKey2 = new DefaultGroupKey("def".getBytes());
Charles Chan0c7c43b2016-01-14 17:39:20 -080079 GroupKey groupKey3 = new DefaultGroupKey("ghi".getBytes());
Ray Milkeyb3c5ce22015-08-10 09:07:36 -070080
81 TrafficTreatment treatment =
82 DefaultTrafficTreatment.emptyTreatment();
83 GroupBucket selectGroupBucket =
84 DefaultGroupBucket.createSelectGroupBucket(treatment);
85 GroupBucket failoverGroupBucket =
86 DefaultGroupBucket.createFailoverGroupBucket(treatment,
87 PortNumber.IN_PORT, groupId1);
88
89 GroupBuckets buckets = new GroupBuckets(ImmutableList.of(selectGroupBucket));
90 GroupDescription groupDescription1 = new DefaultGroupDescription(
91 deviceId1,
Jayasree Ghosh2d459852016-07-02 19:06:52 +053092 ALL,
Ray Milkeyb3c5ce22015-08-10 09:07:36 -070093 buckets,
94 groupKey1,
95 groupId1.id(),
96 APP_ID);
97 GroupDescription groupDescription2 = new DefaultGroupDescription(
98 deviceId2,
Jayasree Ghosh2d459852016-07-02 19:06:52 +053099 INDIRECT,
Ray Milkeyb3c5ce22015-08-10 09:07:36 -0700100 buckets,
101 groupKey2,
102 groupId2.id(),
103 APP_ID);
Charles Chan0c7c43b2016-01-14 17:39:20 -0800104 GroupDescription groupDescription3 = new DefaultGroupDescription(
105 deviceId2,
Jayasree Ghosh2d459852016-07-02 19:06:52 +0530106 INDIRECT,
Charles Chan0c7c43b2016-01-14 17:39:20 -0800107 buckets,
108 groupKey3,
109 groupId3.id(),
110 APP_ID);
Ray Milkeyb3c5ce22015-08-10 09:07:36 -0700111
112 DistributedGroupStore groupStoreImpl;
113 GroupStore groupStore;
Madan Jampani0b847532016-03-03 13:44:15 -0800114 ConsistentMap auditPendingReqQueue;
Ray Milkeyb3c5ce22015-08-10 09:07:36 -0700115
116 static class MasterOfAll extends MastershipServiceAdapter {
117 @Override
118 public MastershipRole getLocalRole(DeviceId deviceId) {
119 return MastershipRole.MASTER;
120 }
Charles Chanf4838a72015-12-07 18:13:45 -0800121
122 @Override
123 public NodeId getMasterFor(DeviceId deviceId) {
124 return new NodeId("foo");
125 }
Ray Milkeyb3c5ce22015-08-10 09:07:36 -0700126 }
127
128 @Before
129 public void setUp() throws Exception {
130 groupStoreImpl = new DistributedGroupStore();
131 groupStoreImpl.storageService = new TestStorageService();
132 groupStoreImpl.clusterCommunicator = new ClusterCommunicationServiceAdapter();
133 groupStoreImpl.mastershipService = new MasterOfAll();
alshabibb0285992016-03-28 23:30:37 -0700134 groupStoreImpl.cfgService = new ComponentConfigAdapter();
sisubram4beea652017-08-09 10:38:14 +0000135 groupStoreImpl.activate(null);
Ray Milkeyb3c5ce22015-08-10 09:07:36 -0700136 groupStore = groupStoreImpl;
137 auditPendingReqQueue =
138 TestUtils.getField(groupStoreImpl, "auditPendingReqQueue");
139 }
140
141 @After
142 public void tearDown() throws Exception {
143 groupStoreImpl.deactivate();
144 }
145
146 /**
147 * Tests the initial state of the store.
148 */
149 @Test
150 public void testEmptyStore() {
151 assertThat(groupStore.getGroupCount(deviceId1), is(0));
152 assertThat(groupStore.getGroup(deviceId1, groupId1), nullValue());
153 assertThat(groupStore.getGroup(deviceId1, groupKey1), nullValue());
154 }
155
156 /**
157 * Tests adding a pending group.
158 */
159 @Test
160 public void testAddPendingGroup() throws Exception {
161 // Make sure the pending list starts out empty
162 assertThat(auditPendingReqQueue.size(), is(0));
163
164 // Add a new pending group. Make sure that the store remains empty
165 groupStore.storeGroupDescription(groupDescription1);
166 assertThat(groupStore.getGroupCount(deviceId1), is(0));
167 assertThat(groupStore.getGroup(deviceId1, groupId1), nullValue());
168 assertThat(groupStore.getGroup(deviceId1, groupKey1), nullValue());
169
170 // Make sure the group is pending
171 assertThat(auditPendingReqQueue.size(), is(1));
172
173 groupStore.deviceInitialAuditCompleted(deviceId1, true);
174
175 // Make sure the group isn't pending anymore
176 assertThat(auditPendingReqQueue.size(), is(0));
177 }
178
179
180 /**
181 * Tests adding and removing a group.
182 */
183 @Test
184 public void testAddRemoveGroup() throws Exception {
185 groupStore.deviceInitialAuditCompleted(deviceId1, true);
186 assertThat(groupStore.deviceInitialAuditStatus(deviceId1), is(true));
187
188 // Make sure the pending list starts out empty
189 assertThat(auditPendingReqQueue.size(), is(0));
190
191 groupStore.storeGroupDescription(groupDescription1);
192 assertThat(groupStore.getGroupCount(deviceId1), is(1));
193 assertThat(groupStore.getGroup(deviceId1, groupId1), notNullValue());
194 assertThat(groupStore.getGroup(deviceId1, groupKey1), notNullValue());
195
196 // Make sure that nothing is pending
197 assertThat(auditPendingReqQueue.size(), is(0));
198
199 Group groupById = groupStore.getGroup(deviceId1, groupId1);
200 Group groupByKey = groupStore.getGroup(deviceId1, groupKey1);
201 assertThat(groupById, notNullValue());
202 assertThat(groupByKey, notNullValue());
203 assertThat(groupById, is(groupByKey));
204 assertThat(groupById.deviceId(), is(did("dev1")));
205
206 groupStore.removeGroupEntry(groupById);
207
208 assertThat(groupStore.getGroupCount(deviceId1), is(0));
209 assertThat(groupStore.getGroup(deviceId1, groupId1), nullValue());
210 assertThat(groupStore.getGroup(deviceId1, groupKey1), nullValue());
211
212 // Make sure that nothing is pending
213 assertThat(auditPendingReqQueue.size(), is(0));
214 }
215
216 /**
Charles Chan0c7c43b2016-01-14 17:39:20 -0800217 * Tests removing all groups on the given device.
218 */
219 @Test
220 public void testRemoveGroupOnDevice() throws Exception {
221 groupStore.deviceInitialAuditCompleted(deviceId1, true);
222 assertThat(groupStore.deviceInitialAuditStatus(deviceId1), is(true));
223 groupStore.deviceInitialAuditCompleted(deviceId2, true);
224 assertThat(groupStore.deviceInitialAuditStatus(deviceId2), is(true));
225
226 // Make sure the pending list starts out empty
227 assertThat(auditPendingReqQueue.size(), is(0));
228
229 groupStore.storeGroupDescription(groupDescription1);
230 groupStore.storeGroupDescription(groupDescription2);
231 groupStore.storeGroupDescription(groupDescription3);
232 assertThat(groupStore.getGroupCount(deviceId1), is(1));
233 assertThat(groupStore.getGroupCount(deviceId2), is(2));
234
235 groupStore.purgeGroupEntry(deviceId2);
236 assertThat(groupStore.getGroupCount(deviceId1), is(1));
237 assertThat(groupStore.getGroupCount(deviceId2), is(0));
Victor Silva4e8b7832016-08-17 17:11:19 -0300238
239 groupStore.purgeGroupEntries();
240 assertThat(groupStore.getGroupCount(deviceId1), is(0));
241 assertThat(groupStore.getGroupCount(deviceId2), is(0));
Charles Chan0c7c43b2016-01-14 17:39:20 -0800242 }
243
244 /**
Ray Milkeyb3c5ce22015-08-10 09:07:36 -0700245 * Tests adding and removing a group.
246 */
247 @Test
248 public void testRemoveGroupDescription() throws Exception {
249 groupStore.deviceInitialAuditCompleted(deviceId1, true);
250
251 groupStore.storeGroupDescription(groupDescription1);
252
253 groupStore.deleteGroupDescription(deviceId1, groupKey1);
254
255 // Group should still be there, marked for removal
256 assertThat(groupStore.getGroupCount(deviceId1), is(1));
257 Group queriedGroup = groupStore.getGroup(deviceId1, groupId1);
258 assertThat(queriedGroup.state(), is(Group.GroupState.PENDING_DELETE));
259
260 }
261
262 /**
263 * Tests pushing group metrics.
264 */
265 @Test
266 public void testPushGroupMetrics() {
267 groupStore.deviceInitialAuditCompleted(deviceId1, true);
268 groupStore.deviceInitialAuditCompleted(deviceId2, true);
269
270 GroupDescription groupDescription3 = new DefaultGroupDescription(
271 deviceId1,
Jayasree Ghosh2d459852016-07-02 19:06:52 +0530272 SELECT,
Ray Milkeyb3c5ce22015-08-10 09:07:36 -0700273 buckets,
274 new DefaultGroupKey("aaa".getBytes()),
275 null,
276 APP_ID);
277
278 groupStore.storeGroupDescription(groupDescription1);
279 groupStore.storeGroupDescription(groupDescription2);
280 groupStore.storeGroupDescription(groupDescription3);
281 Group group1 = groupStore.getGroup(deviceId1, groupId1);
282
283 assertThat(group1, instanceOf(DefaultGroup.class));
284 DefaultGroup defaultGroup1 = (DefaultGroup) group1;
285 defaultGroup1.setPackets(55L);
286 defaultGroup1.setBytes(66L);
287 groupStore.pushGroupMetrics(deviceId1, ImmutableList.of(group1));
288
289 // Make sure the group was updated.
290
291 Group requeryGroup1 = groupStore.getGroup(deviceId1, groupId1);
292 assertThat(requeryGroup1.packets(), is(55L));
293 assertThat(requeryGroup1.bytes(), is(66L));
294
295 }
296
297 class TestDelegate implements GroupStoreDelegate {
298 private List<GroupEvent> eventsSeen = new LinkedList<>();
299 @Override
300 public void notify(GroupEvent event) {
301 eventsSeen.add(event);
302 }
303
304 public List<GroupEvent> eventsSeen() {
305 return eventsSeen;
306 }
307
308 public void resetEvents() {
309 eventsSeen.clear();
310 }
311 }
312
313 /**
314 * Tests group operation failed interface.
315 */
316 @Test
317 public void testGroupOperationFailed() {
318 TestDelegate delegate = new TestDelegate();
319 groupStore.setDelegate(delegate);
320 groupStore.deviceInitialAuditCompleted(deviceId1, true);
321 groupStore.deviceInitialAuditCompleted(deviceId2, true);
322
323 groupStore.storeGroupDescription(groupDescription1);
324 groupStore.storeGroupDescription(groupDescription2);
325
326 List<GroupEvent> eventsAfterAdds = delegate.eventsSeen();
327 assertThat(eventsAfterAdds, hasSize(2));
Sho SHIMIZUa09e1bb2016-08-01 14:25:25 -0700328 eventsAfterAdds.forEach(event -> assertThat(event.type(), is(GroupEvent.Type.GROUP_ADD_REQUESTED)));
Ray Milkeyb3c5ce22015-08-10 09:07:36 -0700329 delegate.resetEvents();
330
331 GroupOperation opAdd =
332 GroupOperation.createAddGroupOperation(groupId1,
Jayasree Ghosh2d459852016-07-02 19:06:52 +0530333 INDIRECT,
Ray Milkeyb3c5ce22015-08-10 09:07:36 -0700334 buckets);
335 groupStore.groupOperationFailed(deviceId1, opAdd);
336
337 List<GroupEvent> eventsAfterAddFailed = delegate.eventsSeen();
338 assertThat(eventsAfterAddFailed, hasSize(2));
339 assertThat(eventsAfterAddFailed.get(0).type(),
340 is(GroupEvent.Type.GROUP_ADD_FAILED));
341 assertThat(eventsAfterAddFailed.get(1).type(),
342 is(GroupEvent.Type.GROUP_REMOVED));
343 delegate.resetEvents();
344
345 GroupOperation opModify =
346 GroupOperation.createModifyGroupOperation(groupId2,
Jayasree Ghosh2d459852016-07-02 19:06:52 +0530347 INDIRECT,
Ray Milkeyb3c5ce22015-08-10 09:07:36 -0700348 buckets);
349 groupStore.groupOperationFailed(deviceId2, opModify);
350 List<GroupEvent> eventsAfterModifyFailed = delegate.eventsSeen();
351 assertThat(eventsAfterModifyFailed, hasSize(1));
352 assertThat(eventsAfterModifyFailed.get(0).type(),
353 is(GroupEvent.Type.GROUP_UPDATE_FAILED));
354 delegate.resetEvents();
355
356 GroupOperation opDelete =
357 GroupOperation.createDeleteGroupOperation(groupId2,
Jayasree Ghosh2d459852016-07-02 19:06:52 +0530358 INDIRECT);
Ray Milkeyb3c5ce22015-08-10 09:07:36 -0700359 groupStore.groupOperationFailed(deviceId2, opDelete);
360 List<GroupEvent> eventsAfterDeleteFailed = delegate.eventsSeen();
361 assertThat(eventsAfterDeleteFailed, hasSize(1));
362 assertThat(eventsAfterDeleteFailed.get(0).type(),
363 is(GroupEvent.Type.GROUP_REMOVE_FAILED));
364 delegate.resetEvents();
365 }
366
367 /**
368 * Tests extraneous group operations.
369 */
370 @Test
371 public void testExtraneousOperations() {
372 ArrayList<Group> extraneous;
373 groupStore.deviceInitialAuditCompleted(deviceId1, true);
374
375 groupStore.storeGroupDescription(groupDescription1);
376 Group group1 = groupStore.getGroup(deviceId1, groupId1);
377
378 extraneous = Lists.newArrayList(groupStore.getExtraneousGroups(deviceId1));
379 assertThat(extraneous, hasSize(0));
380
381 groupStore.addOrUpdateExtraneousGroupEntry(group1);
382 extraneous = Lists.newArrayList(groupStore.getExtraneousGroups(deviceId1));
383 assertThat(extraneous, hasSize(1));
384
385 groupStore.removeExtraneousGroupEntry(group1);
386 extraneous = Lists.newArrayList(groupStore.getExtraneousGroups(deviceId1));
387 assertThat(extraneous, hasSize(0));
388 }
389
390 /**
391 * Tests updating of group descriptions.
392 */
393 @Test
394 public void testUpdateGroupDescription() {
395
396 GroupBuckets buckets =
Victor Silvadf1eeae2016-08-12 15:28:57 -0300397 new GroupBuckets(ImmutableList.of(failoverGroupBucket, selectGroupBucket));
Ray Milkeyb3c5ce22015-08-10 09:07:36 -0700398
399 groupStore.deviceInitialAuditCompleted(deviceId1, true);
400 groupStore.storeGroupDescription(groupDescription1);
401
402 GroupKey newKey = new DefaultGroupKey("123".getBytes());
403 groupStore.updateGroupDescription(deviceId1,
404 groupKey1,
Jayasree Ghosh2d459852016-07-02 19:06:52 +0530405 ADD,
Ray Milkeyb3c5ce22015-08-10 09:07:36 -0700406 buckets,
407 newKey);
408 Group group1 = groupStore.getGroup(deviceId1, groupId1);
409 assertThat(group1.appCookie(), is(newKey));
410 assertThat(group1.buckets().buckets(), hasSize(2));
Victor Silvadf1eeae2016-08-12 15:28:57 -0300411
412 short weight = 5;
413 GroupBucket selectGroupBucketWithWeight =
414 DefaultGroupBucket.createSelectGroupBucket(treatment, weight);
415 buckets = new GroupBuckets(ImmutableList.of(failoverGroupBucket,
416 selectGroupBucketWithWeight));
417
418 groupStore.updateGroupDescription(deviceId1,
419 newKey,
420 ADD,
421 buckets,
422 newKey);
423
424 group1 = groupStore.getGroup(deviceId1, groupId1);
425 assertThat(group1.appCookie(), is(newKey));
426 assertThat(group1.buckets().buckets(), hasSize(2));
427 for (GroupBucket bucket : group1.buckets().buckets()) {
428 if (bucket.type() == SELECT) {
429 assertEquals(weight, bucket.weight());
430 }
431 }
Victor Silva0282ab82016-11-15 16:30:27 -0300432
433 buckets = new GroupBuckets(ImmutableList.of(selectGroupBucketWithWeight));
434
435 groupStore.updateGroupDescription(deviceId1,
436 newKey,
437 SET,
438 buckets,
439 newKey);
440
441 group1 = groupStore.getGroup(deviceId1, groupId1);
442 assertThat(group1.appCookie(), is(newKey));
443 assertThat(group1.buckets().buckets(), hasSize(1));
444 GroupBucket onlyBucket = group1.buckets().buckets().iterator().next();
445 assertEquals(weight, onlyBucket.weight());
Ray Milkeyb3c5ce22015-08-10 09:07:36 -0700446 }
447
448 @Test
449 public void testEqualsGroupStoreIdMapKey() {
450 DistributedGroupStore.GroupStoreIdMapKey key1 =
451 new DistributedGroupStore.GroupStoreIdMapKey(deviceId1, groupId1);
452 DistributedGroupStore.GroupStoreIdMapKey sameAsKey1 =
453 new DistributedGroupStore.GroupStoreIdMapKey(deviceId1, groupId1);
454 DistributedGroupStore.GroupStoreIdMapKey key2 =
455 new DistributedGroupStore.GroupStoreIdMapKey(deviceId2, groupId1);
456 DistributedGroupStore.GroupStoreIdMapKey key3 =
457 new DistributedGroupStore.GroupStoreIdMapKey(deviceId1, groupId2);
458
459 new EqualsTester()
460 .addEqualityGroup(key1, sameAsKey1)
461 .addEqualityGroup(key2)
462 .addEqualityGroup(key3)
463 .testEquals();
464 }
465
466 @Test
467 public void testEqualsGroupStoreKeyMapKey() {
468 DistributedGroupStore.GroupStoreKeyMapKey key1 =
469 new DistributedGroupStore.GroupStoreKeyMapKey(deviceId1, groupKey1);
470 DistributedGroupStore.GroupStoreKeyMapKey sameAsKey1 =
471 new DistributedGroupStore.GroupStoreKeyMapKey(deviceId1, groupKey1);
472 DistributedGroupStore.GroupStoreKeyMapKey key2 =
473 new DistributedGroupStore.GroupStoreKeyMapKey(deviceId2, groupKey1);
474 DistributedGroupStore.GroupStoreKeyMapKey key3 =
475 new DistributedGroupStore.GroupStoreKeyMapKey(deviceId1, groupKey2);
476
477 new EqualsTester()
478 .addEqualityGroup(key1, sameAsKey1)
479 .addEqualityGroup(key2)
480 .addEqualityGroup(key3)
481 .testEquals();
482 }
483
484 @Test
485 public void testEqualsGroupStoreMapKey() {
486 DistributedGroupStore.GroupStoreMapKey key1 =
487 new DistributedGroupStore.GroupStoreMapKey(deviceId1);
488 DistributedGroupStore.GroupStoreMapKey sameAsKey1 =
489 new DistributedGroupStore.GroupStoreMapKey(deviceId1);
490 DistributedGroupStore.GroupStoreMapKey key2 =
491 new DistributedGroupStore.GroupStoreMapKey(deviceId2);
492 DistributedGroupStore.GroupStoreMapKey key3 =
493 new DistributedGroupStore.GroupStoreMapKey(did("dev3"));
494
495 new EqualsTester()
496 .addEqualityGroup(key1, sameAsKey1)
497 .addEqualityGroup(key2)
498 .addEqualityGroup(key3)
499 .testEquals();
500 }
501}