Committed by
Gerrit Code Review
[ONOS-5169] GroupStore: properly add updated buckets
Adding buckets to group was ignoring the addition of groups with different weights because they had the same treatment and type. We'll now update such groupbuckets with the desired new parameters. Change-Id: I5f102c5fd78912844883c897bd858ee282f3cc12
Showing
6 changed files
with
142 additions
and
27 deletions
... | @@ -235,6 +235,13 @@ public final class DefaultGroupBucket implements GroupBucket, StoredGroupBucketE | ... | @@ -235,6 +235,13 @@ public final class DefaultGroupBucket implements GroupBucket, StoredGroupBucketE |
235 | } | 235 | } |
236 | 236 | ||
237 | @Override | 237 | @Override |
238 | + public boolean hasSameParameters(GroupBucket other) { | ||
239 | + return weight == other.weight() && | ||
240 | + Objects.equals(watchPort, other.watchPort()) && | ||
241 | + Objects.equals(watchGroup, other.watchGroup()); | ||
242 | + } | ||
243 | + | ||
244 | + @Override | ||
238 | public String toString() { | 245 | public String toString() { |
239 | return toStringHelper(this) | 246 | return toStringHelper(this) |
240 | .add("type", type) | 247 | .add("type", type) | ... | ... |
... | @@ -77,4 +77,12 @@ public interface GroupBucket { | ... | @@ -77,4 +77,12 @@ public interface GroupBucket { |
77 | * @return number of bytes | 77 | * @return number of bytes |
78 | */ | 78 | */ |
79 | long bytes(); | 79 | long bytes(); |
80 | + | ||
81 | + /** | ||
82 | + * Returns whether the given GroupBucket has the same parameters (weight, | ||
83 | + * watchPort and watchGroup) as this. | ||
84 | + * | ||
85 | + * @param other GroupBucket to compare | ||
86 | + */ | ||
87 | + boolean hasSameParameters(GroupBucket other); | ||
80 | } | 88 | } | ... | ... |
... | @@ -321,32 +321,50 @@ public class SimpleGroupStore | ... | @@ -321,32 +321,50 @@ public class SimpleGroupStore |
321 | private List<GroupBucket> getUpdatedBucketList(Group oldGroup, | 321 | private List<GroupBucket> getUpdatedBucketList(Group oldGroup, |
322 | UpdateType type, | 322 | UpdateType type, |
323 | GroupBuckets buckets) { | 323 | GroupBuckets buckets) { |
324 | - GroupBuckets oldBuckets = oldGroup.buckets(); | 324 | + List<GroupBucket> oldBuckets = oldGroup.buckets().buckets(); |
325 | - List<GroupBucket> newBucketList = new ArrayList<>(oldBuckets.buckets()); | 325 | + List<GroupBucket> updatedBucketList = new ArrayList<>(); |
326 | boolean groupDescUpdated = false; | 326 | boolean groupDescUpdated = false; |
327 | 327 | ||
328 | if (type == UpdateType.ADD) { | 328 | if (type == UpdateType.ADD) { |
329 | - // Check if the any of the new buckets are part of | 329 | + List<GroupBucket> newBuckets = buckets.buckets(); |
330 | - // the old bucket list | 330 | + |
331 | - for (GroupBucket addBucket:buckets.buckets()) { | 331 | + // Add old buckets that will not be updated and check if any will be updated. |
332 | - if (!newBucketList.contains(addBucket)) { | 332 | + for (GroupBucket oldBucket : oldBuckets) { |
333 | - newBucketList.add(addBucket); | 333 | + int newBucketIndex = newBuckets.indexOf(oldBucket); |
334 | + | ||
335 | + if (newBucketIndex != -1) { | ||
336 | + GroupBucket newBucket = newBuckets.get(newBucketIndex); | ||
337 | + if (!newBucket.hasSameParameters(oldBucket)) { | ||
338 | + // Bucket will be updated | ||
334 | groupDescUpdated = true; | 339 | groupDescUpdated = true; |
335 | } | 340 | } |
341 | + } else { | ||
342 | + // Old bucket will remain the same - add it. | ||
343 | + updatedBucketList.add(oldBucket); | ||
344 | + } | ||
345 | + } | ||
346 | + | ||
347 | + // Add all new buckets | ||
348 | + updatedBucketList.addAll(newBuckets); | ||
349 | + if (!oldBuckets.containsAll(newBuckets)) { | ||
350 | + groupDescUpdated = true; | ||
336 | } | 351 | } |
352 | + | ||
337 | } else if (type == UpdateType.REMOVE) { | 353 | } else if (type == UpdateType.REMOVE) { |
338 | - // Check if the to be removed buckets are part of the | 354 | + List<GroupBucket> bucketsToRemove = buckets.buckets(); |
339 | - // old bucket list | 355 | + |
340 | - for (GroupBucket removeBucket:buckets.buckets()) { | 356 | + // Check which old buckets should remain |
341 | - if (newBucketList.contains(removeBucket)) { | 357 | + for (GroupBucket oldBucket : oldBuckets) { |
342 | - newBucketList.remove(removeBucket); | 358 | + if (!bucketsToRemove.contains(oldBucket)) { |
359 | + updatedBucketList.add(oldBucket); | ||
360 | + } else { | ||
343 | groupDescUpdated = true; | 361 | groupDescUpdated = true; |
344 | } | 362 | } |
345 | } | 363 | } |
346 | } | 364 | } |
347 | 365 | ||
348 | if (groupDescUpdated) { | 366 | if (groupDescUpdated) { |
349 | - return newBucketList; | 367 | + return updatedBucketList; |
350 | } else { | 368 | } else { |
351 | return null; | 369 | return null; |
352 | } | 370 | } | ... | ... |
... | @@ -130,6 +130,18 @@ public class SimpleGroupStoreTest { | ... | @@ -130,6 +130,18 @@ public class SimpleGroupStoreTest { |
130 | } else if (expectedEvent == GroupEvent.Type.GROUP_UPDATE_REQUESTED) { | 130 | } else if (expectedEvent == GroupEvent.Type.GROUP_UPDATE_REQUESTED) { |
131 | assertEquals(Group.GroupState.PENDING_UPDATE, | 131 | assertEquals(Group.GroupState.PENDING_UPDATE, |
132 | event.subject().state()); | 132 | event.subject().state()); |
133 | + for (GroupBucket bucket:event.subject().buckets().buckets()) { | ||
134 | + Optional<GroupBucket> matched = createdBuckets.buckets() | ||
135 | + .stream() | ||
136 | + .filter((expected) -> expected.equals(bucket)) | ||
137 | + .findFirst(); | ||
138 | + assertEquals(matched.get().weight(), | ||
139 | + bucket.weight()); | ||
140 | + assertEquals(matched.get().watchGroup(), | ||
141 | + bucket.watchGroup()); | ||
142 | + assertEquals(matched.get().watchPort(), | ||
143 | + bucket.watchPort()); | ||
144 | + } | ||
133 | } else if (expectedEvent == GroupEvent.Type.GROUP_REMOVE_REQUESTED) { | 145 | } else if (expectedEvent == GroupEvent.Type.GROUP_REMOVE_REQUESTED) { |
134 | assertEquals(Group.GroupState.PENDING_DELETE, | 146 | assertEquals(Group.GroupState.PENDING_DELETE, |
135 | event.subject().state()); | 147 | event.subject().state()); |
... | @@ -342,6 +354,36 @@ public class SimpleGroupStoreTest { | ... | @@ -342,6 +354,36 @@ public class SimpleGroupStoreTest { |
342 | toAddGroupBuckets, | 354 | toAddGroupBuckets, |
343 | addKey); | 355 | addKey); |
344 | simpleGroupStore.unsetDelegate(updateGroupDescDelegate); | 356 | simpleGroupStore.unsetDelegate(updateGroupDescDelegate); |
357 | + | ||
358 | + short weight = 5; | ||
359 | + toAddBuckets = new ArrayList<>(); | ||
360 | + for (PortNumber portNumber: newOutPorts) { | ||
361 | + TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder(); | ||
362 | + tBuilder.setOutput(portNumber) | ||
363 | + .setEthDst(MacAddress.valueOf("00:00:00:00:00:03")) | ||
364 | + .setEthSrc(MacAddress.valueOf("00:00:00:00:00:01")) | ||
365 | + .pushMpls() | ||
366 | + .setMpls(MplsLabel.mplsLabel(106)); | ||
367 | + toAddBuckets.add(DefaultGroupBucket.createSelectGroupBucket( | ||
368 | + tBuilder.build(), weight)); | ||
369 | + } | ||
370 | + | ||
371 | + toAddGroupBuckets = new GroupBuckets(toAddBuckets); | ||
372 | + buckets = new ArrayList<>(); | ||
373 | + buckets.addAll(existingGroup.buckets().buckets()); | ||
374 | + buckets.addAll(toAddBuckets); | ||
375 | + updatedGroupBuckets = new GroupBuckets(buckets); | ||
376 | + updateGroupDescDelegate = | ||
377 | + new InternalGroupStoreDelegate(addKey, | ||
378 | + updatedGroupBuckets, | ||
379 | + GroupEvent.Type.GROUP_UPDATE_REQUESTED); | ||
380 | + simpleGroupStore.setDelegate(updateGroupDescDelegate); | ||
381 | + simpleGroupStore.updateGroupDescription(D1, | ||
382 | + addKey, | ||
383 | + UpdateType.ADD, | ||
384 | + toAddGroupBuckets, | ||
385 | + addKey); | ||
386 | + simpleGroupStore.unsetDelegate(updateGroupDescDelegate); | ||
345 | } | 387 | } |
346 | 388 | ||
347 | // Testing updateGroupDescription for REMOVE operation from northbound | 389 | // Testing updateGroupDescription for REMOVE operation from northbound | ... | ... |
... | @@ -719,32 +719,50 @@ public class DistributedGroupStore | ... | @@ -719,32 +719,50 @@ public class DistributedGroupStore |
719 | private List<GroupBucket> getUpdatedBucketList(Group oldGroup, | 719 | private List<GroupBucket> getUpdatedBucketList(Group oldGroup, |
720 | UpdateType type, | 720 | UpdateType type, |
721 | GroupBuckets buckets) { | 721 | GroupBuckets buckets) { |
722 | - GroupBuckets oldBuckets = oldGroup.buckets(); | 722 | + List<GroupBucket> oldBuckets = oldGroup.buckets().buckets(); |
723 | - List<GroupBucket> newBucketList = new ArrayList<>(oldBuckets.buckets()); | 723 | + List<GroupBucket> updatedBucketList = new ArrayList<>(); |
724 | boolean groupDescUpdated = false; | 724 | boolean groupDescUpdated = false; |
725 | 725 | ||
726 | if (type == UpdateType.ADD) { | 726 | if (type == UpdateType.ADD) { |
727 | - // Check if the any of the new buckets are part of | 727 | + List<GroupBucket> newBuckets = buckets.buckets(); |
728 | - // the old bucket list | 728 | + |
729 | - for (GroupBucket addBucket : buckets.buckets()) { | 729 | + // Add old buckets that will not be updated and check if any will be updated. |
730 | - if (!newBucketList.contains(addBucket)) { | 730 | + for (GroupBucket oldBucket : oldBuckets) { |
731 | - newBucketList.add(addBucket); | 731 | + int newBucketIndex = newBuckets.indexOf(oldBucket); |
732 | + | ||
733 | + if (newBucketIndex != -1) { | ||
734 | + GroupBucket newBucket = newBuckets.get(newBucketIndex); | ||
735 | + if (!newBucket.hasSameParameters(oldBucket)) { | ||
736 | + // Bucket will be updated | ||
732 | groupDescUpdated = true; | 737 | groupDescUpdated = true; |
733 | } | 738 | } |
739 | + } else { | ||
740 | + // Old bucket will remain the same - add it. | ||
741 | + updatedBucketList.add(oldBucket); | ||
742 | + } | ||
743 | + } | ||
744 | + | ||
745 | + // Add all new buckets | ||
746 | + updatedBucketList.addAll(newBuckets); | ||
747 | + if (!oldBuckets.containsAll(newBuckets)) { | ||
748 | + groupDescUpdated = true; | ||
734 | } | 749 | } |
750 | + | ||
735 | } else if (type == UpdateType.REMOVE) { | 751 | } else if (type == UpdateType.REMOVE) { |
736 | - // Check if the to be removed buckets are part of the | 752 | + List<GroupBucket> bucketsToRemove = buckets.buckets(); |
737 | - // old bucket list | 753 | + |
738 | - for (GroupBucket removeBucket : buckets.buckets()) { | 754 | + // Check which old buckets should remain |
739 | - if (newBucketList.contains(removeBucket)) { | 755 | + for (GroupBucket oldBucket : oldBuckets) { |
740 | - newBucketList.remove(removeBucket); | 756 | + if (!bucketsToRemove.contains(oldBucket)) { |
757 | + updatedBucketList.add(oldBucket); | ||
758 | + } else { | ||
741 | groupDescUpdated = true; | 759 | groupDescUpdated = true; |
742 | } | 760 | } |
743 | } | 761 | } |
744 | } | 762 | } |
745 | 763 | ||
746 | if (groupDescUpdated) { | 764 | if (groupDescUpdated) { |
747 | - return newBucketList; | 765 | + return updatedBucketList; |
748 | } else { | 766 | } else { |
749 | return null; | 767 | return null; |
750 | } | 768 | } | ... | ... |
... | @@ -60,6 +60,7 @@ import static org.hamcrest.Matchers.instanceOf; | ... | @@ -60,6 +60,7 @@ import static org.hamcrest.Matchers.instanceOf; |
60 | import static org.hamcrest.Matchers.is; | 60 | import static org.hamcrest.Matchers.is; |
61 | import static org.hamcrest.Matchers.notNullValue; | 61 | import static org.hamcrest.Matchers.notNullValue; |
62 | import static org.hamcrest.Matchers.nullValue; | 62 | import static org.hamcrest.Matchers.nullValue; |
63 | +import static org.junit.Assert.assertEquals; | ||
63 | import static org.onosproject.net.NetTestTools.APP_ID; | 64 | import static org.onosproject.net.NetTestTools.APP_ID; |
64 | import static org.onosproject.net.NetTestTools.did; | 65 | import static org.onosproject.net.NetTestTools.did; |
65 | import static org.onosproject.net.group.GroupDescription.Type.*; | 66 | import static org.onosproject.net.group.GroupDescription.Type.*; |
... | @@ -390,7 +391,7 @@ public class DistributedGroupStoreTest { | ... | @@ -390,7 +391,7 @@ public class DistributedGroupStoreTest { |
390 | public void testUpdateGroupDescription() { | 391 | public void testUpdateGroupDescription() { |
391 | 392 | ||
392 | GroupBuckets buckets = | 393 | GroupBuckets buckets = |
393 | - new GroupBuckets(ImmutableList.of(failoverGroupBucket)); | 394 | + new GroupBuckets(ImmutableList.of(failoverGroupBucket, selectGroupBucket)); |
394 | 395 | ||
395 | groupStore.deviceInitialAuditCompleted(deviceId1, true); | 396 | groupStore.deviceInitialAuditCompleted(deviceId1, true); |
396 | groupStore.storeGroupDescription(groupDescription1); | 397 | groupStore.storeGroupDescription(groupDescription1); |
... | @@ -404,6 +405,27 @@ public class DistributedGroupStoreTest { | ... | @@ -404,6 +405,27 @@ public class DistributedGroupStoreTest { |
404 | Group group1 = groupStore.getGroup(deviceId1, groupId1); | 405 | Group group1 = groupStore.getGroup(deviceId1, groupId1); |
405 | assertThat(group1.appCookie(), is(newKey)); | 406 | assertThat(group1.appCookie(), is(newKey)); |
406 | assertThat(group1.buckets().buckets(), hasSize(2)); | 407 | assertThat(group1.buckets().buckets(), hasSize(2)); |
408 | + | ||
409 | + short weight = 5; | ||
410 | + GroupBucket selectGroupBucketWithWeight = | ||
411 | + DefaultGroupBucket.createSelectGroupBucket(treatment, weight); | ||
412 | + buckets = new GroupBuckets(ImmutableList.of(failoverGroupBucket, | ||
413 | + selectGroupBucketWithWeight)); | ||
414 | + | ||
415 | + groupStore.updateGroupDescription(deviceId1, | ||
416 | + newKey, | ||
417 | + ADD, | ||
418 | + buckets, | ||
419 | + newKey); | ||
420 | + | ||
421 | + group1 = groupStore.getGroup(deviceId1, groupId1); | ||
422 | + assertThat(group1.appCookie(), is(newKey)); | ||
423 | + assertThat(group1.buckets().buckets(), hasSize(2)); | ||
424 | + for (GroupBucket bucket : group1.buckets().buckets()) { | ||
425 | + if (bucket.type() == SELECT) { | ||
426 | + assertEquals(weight, bucket.weight()); | ||
427 | + } | ||
428 | + } | ||
407 | } | 429 | } |
408 | 430 | ||
409 | @Test | 431 | @Test | ... | ... |
-
Please register or login to post a comment