helenyrwu
Committed by Helen Wu

Group event indicating failover of previously used live port

Change-Id: I32749b38d5e4fab93fa97bbf6587bd0dc91db88c
...@@ -56,6 +56,13 @@ public class GroupEvent extends AbstractEvent<GroupEvent.Type, Group> { ...@@ -56,6 +56,13 @@ public class GroupEvent extends AbstractEvent<GroupEvent.Type, Group> {
56 */ 56 */
57 GROUP_UPDATE_FAILED, 57 GROUP_UPDATE_FAILED,
58 58
59 + /**
60 + * Signifies change in the first live bucket in failover group
61 + * (i.e. change in which bucket is in use).
62 + * Only to be used with failover Group.
63 + */
64 + GROUP_BUCKET_FAILOVER,
65 +
59 // internal event between Manager <-> Store 66 // internal event between Manager <-> Store
60 67
61 /* 68 /*
......
...@@ -41,7 +41,12 @@ public interface GroupProviderService extends ProviderService<GroupProvider> { ...@@ -41,7 +41,12 @@ public interface GroupProviderService extends ProviderService<GroupProvider> {
41 * @param deviceId device identifier 41 * @param deviceId device identifier
42 * @param groupEntries collection of group entries as seen in data plane 42 * @param groupEntries collection of group entries as seen in data plane
43 */ 43 */
44 - void pushGroupMetrics(DeviceId deviceId, 44 + void pushGroupMetrics(DeviceId deviceId, Collection<Group> groupEntries);
45 - Collection<Group> groupEntries);
46 45
46 + /**
47 + * Notifies store of group failovers.
48 + *
49 + * @param failoverGroups failover groups in which a failover has occurred
50 + */
51 + void notifyOfFailovers(Collection<Group> failoverGroups);
47 } 52 }
......
...@@ -179,4 +179,9 @@ public interface GroupStore extends Store<GroupEvent, GroupStoreDelegate> { ...@@ -179,4 +179,9 @@ public interface GroupStore extends Store<GroupEvent, GroupStoreDelegate> {
179 * @param groupEntries the group entries as received from southbound 179 * @param groupEntries the group entries as received from southbound
180 */ 180 */
181 void pushGroupMetrics(DeviceId deviceId, Collection<Group> groupEntries); 181 void pushGroupMetrics(DeviceId deviceId, Collection<Group> groupEntries);
182 +
183 + /**
184 + * Indicates failover within a failover group.
185 + */
186 + void notifyOfFailovers(Collection<Group> failoverGroups);
182 } 187 }
......
...@@ -646,6 +646,17 @@ public class SimpleGroupStore ...@@ -646,6 +646,17 @@ public class SimpleGroupStore
646 } 646 }
647 } 647 }
648 648
649 + @Override
650 + public void notifyOfFailovers(Collection<Group> failoverGroups) {
651 + List<GroupEvent> failoverEvents = new ArrayList<>();
652 + failoverGroups.forEach(group -> {
653 + if (group.type() == Group.Type.FAILOVER) {
654 + failoverEvents.add(new GroupEvent(GroupEvent.Type.GROUP_BUCKET_FAILOVER, group));
655 + }
656 + });
657 + notifyDelegate(failoverEvents);
658 + }
659 +
649 private void groupMissing(Group group) { 660 private void groupMissing(Group group) {
650 switch (group.state()) { 661 switch (group.state()) {
651 case PENDING_DELETE: 662 case PENDING_DELETE:
......
...@@ -324,9 +324,9 @@ public class GroupManager ...@@ -324,9 +324,9 @@ public class GroupManager
324 case GROUP_ADD_FAILED: 324 case GROUP_ADD_FAILED:
325 case GROUP_UPDATE_FAILED: 325 case GROUP_UPDATE_FAILED:
326 case GROUP_REMOVE_FAILED: 326 case GROUP_REMOVE_FAILED:
327 + case GROUP_BUCKET_FAILOVER:
327 post(event); 328 post(event);
328 break; 329 break;
329 -
330 default: 330 default:
331 break; 331 break;
332 } 332 }
...@@ -353,6 +353,11 @@ public class GroupManager ...@@ -353,6 +353,11 @@ public class GroupManager
353 checkValidity(); 353 checkValidity();
354 store.pushGroupMetrics(deviceId, groupEntries); 354 store.pushGroupMetrics(deviceId, groupEntries);
355 } 355 }
356 +
357 + @Override
358 + public void notifyOfFailovers(Collection<Group> failoverGroups) {
359 + store.notifyOfFailovers(failoverGroups);
360 + }
356 } 361 }
357 362
358 private class InternalDeviceListener implements DeviceListener { 363 private class InternalDeviceListener implements DeviceListener {
...@@ -378,4 +383,5 @@ public class GroupManager ...@@ -378,4 +383,5 @@ public class GroupManager
378 } 383 }
379 } 384 }
380 } 385 }
386 +
381 } 387 }
......
...@@ -1312,6 +1312,17 @@ public class DistributedGroupStore ...@@ -1312,6 +1312,17 @@ public class DistributedGroupStore
1312 } 1312 }
1313 } 1313 }
1314 1314
1315 + @Override
1316 + public void notifyOfFailovers(Collection<Group> failoverGroups) {
1317 + List<GroupEvent> failoverEvents = new ArrayList<>();
1318 + failoverGroups.forEach(group -> {
1319 + if (group.type() == Group.Type.FAILOVER) {
1320 + failoverEvents.add(new GroupEvent(GroupEvent.Type.GROUP_BUCKET_FAILOVER, group));
1321 + }
1322 + });
1323 + notifyDelegate(failoverEvents);
1324 + }
1325 +
1315 private void garbageCollect(DeviceId deviceId, 1326 private void garbageCollect(DeviceId deviceId,
1316 Set<Group> southboundGroupEntries, 1327 Set<Group> southboundGroupEntries,
1317 Set<StoredGroupEntry> storedGroupEntries) { 1328 Set<StoredGroupEntry> storedGroupEntries) {
......
...@@ -18,7 +18,10 @@ package org.onosproject.provider.of.group.impl; ...@@ -18,7 +18,10 @@ package org.onosproject.provider.of.group.impl;
18 18
19 import static org.slf4j.LoggerFactory.getLogger; 19 import static org.slf4j.LoggerFactory.getLogger;
20 20
21 +import java.util.ArrayList;
21 import java.util.Collection; 22 import java.util.Collection;
23 +import java.util.Iterator;
24 +import java.util.List;
22 import java.util.Map; 25 import java.util.Map;
23 import java.util.Optional; 26 import java.util.Optional;
24 import java.util.concurrent.atomic.AtomicLong; 27 import java.util.concurrent.atomic.AtomicLong;
...@@ -31,9 +34,12 @@ import org.apache.felix.scr.annotations.ReferenceCardinality; ...@@ -31,9 +34,12 @@ import org.apache.felix.scr.annotations.ReferenceCardinality;
31 import org.onosproject.core.DefaultGroupId; 34 import org.onosproject.core.DefaultGroupId;
32 import org.onosproject.core.GroupId; 35 import org.onosproject.core.GroupId;
33 import org.onosproject.net.DeviceId; 36 import org.onosproject.net.DeviceId;
37 +import org.onosproject.net.PortNumber;
38 +import org.onosproject.net.device.DeviceService;
34 import org.onosproject.net.driver.DriverService; 39 import org.onosproject.net.driver.DriverService;
35 import org.onosproject.net.group.DefaultGroup; 40 import org.onosproject.net.group.DefaultGroup;
36 import org.onosproject.net.group.Group; 41 import org.onosproject.net.group.Group;
42 +import org.onosproject.net.group.GroupBucket;
37 import org.onosproject.net.group.GroupBuckets; 43 import org.onosproject.net.group.GroupBuckets;
38 import org.onosproject.net.group.GroupDescription; 44 import org.onosproject.net.group.GroupDescription;
39 import org.onosproject.net.group.GroupOperation; 45 import org.onosproject.net.group.GroupOperation;
...@@ -42,6 +48,7 @@ import org.onosproject.net.group.GroupOperations; ...@@ -42,6 +48,7 @@ import org.onosproject.net.group.GroupOperations;
42 import org.onosproject.net.group.GroupProvider; 48 import org.onosproject.net.group.GroupProvider;
43 import org.onosproject.net.group.GroupProviderRegistry; 49 import org.onosproject.net.group.GroupProviderRegistry;
44 import org.onosproject.net.group.GroupProviderService; 50 import org.onosproject.net.group.GroupProviderService;
51 +import org.onosproject.net.group.GroupService;
45 import org.onosproject.net.group.StoredGroupBucketEntry; 52 import org.onosproject.net.group.StoredGroupBucketEntry;
46 import org.onosproject.net.provider.AbstractProvider; 53 import org.onosproject.net.provider.AbstractProvider;
47 import org.onosproject.net.provider.ProviderId; 54 import org.onosproject.net.provider.ProviderId;
...@@ -62,6 +69,7 @@ import org.projectfloodlight.openflow.protocol.OFGroupStatsEntry; ...@@ -62,6 +69,7 @@ import org.projectfloodlight.openflow.protocol.OFGroupStatsEntry;
62 import org.projectfloodlight.openflow.protocol.OFGroupStatsReply; 69 import org.projectfloodlight.openflow.protocol.OFGroupStatsReply;
63 import org.projectfloodlight.openflow.protocol.OFGroupType; 70 import org.projectfloodlight.openflow.protocol.OFGroupType;
64 import org.projectfloodlight.openflow.protocol.OFMessage; 71 import org.projectfloodlight.openflow.protocol.OFMessage;
72 +import org.projectfloodlight.openflow.protocol.OFPortDesc;
65 import org.projectfloodlight.openflow.protocol.OFPortStatus; 73 import org.projectfloodlight.openflow.protocol.OFPortStatus;
66 import org.projectfloodlight.openflow.protocol.OFStatsReply; 74 import org.projectfloodlight.openflow.protocol.OFStatsReply;
67 import org.projectfloodlight.openflow.protocol.OFStatsType; 75 import org.projectfloodlight.openflow.protocol.OFStatsType;
...@@ -88,6 +96,12 @@ public class OpenFlowGroupProvider extends AbstractProvider implements GroupProv ...@@ -88,6 +96,12 @@ public class OpenFlowGroupProvider extends AbstractProvider implements GroupProv
88 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 96 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
89 protected DriverService driverService; 97 protected DriverService driverService;
90 98
99 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
100 + protected DeviceService deviceService;
101 +
102 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
103 + protected GroupService groupService;
104 +
91 private GroupProviderService providerService; 105 private GroupProviderService providerService;
92 106
93 static final int POLL_INTERVAL = 10; 107 static final int POLL_INTERVAL = 10;
...@@ -389,6 +403,7 @@ public class OpenFlowGroupProvider extends AbstractProvider implements GroupProv ...@@ -389,6 +403,7 @@ public class OpenFlowGroupProvider extends AbstractProvider implements GroupProv
389 403
390 @Override 404 @Override
391 public void portChanged(Dpid dpid, OFPortStatus status) { 405 public void portChanged(Dpid dpid, OFPortStatus status) {
406 + providerService.notifyOfFailovers(checkFailoverGroups(dpid, status));
392 } 407 }
393 408
394 @Override 409 @Override
...@@ -396,4 +411,58 @@ public class OpenFlowGroupProvider extends AbstractProvider implements GroupProv ...@@ -396,4 +411,58 @@ public class OpenFlowGroupProvider extends AbstractProvider implements GroupProv
396 } 411 }
397 } 412 }
398 413
414 + /**
415 + * Builds a list of failover Groups whose primary live bucket failed over
416 + * (i.e. bucket in use has changed).
417 + *
418 + * @param dpid DPID of switch whose port's status changed
419 + * @param status new status of port
420 + * @return list of groups whose primary live bucket failed over
421 + */
422 + private List<Group> checkFailoverGroups(Dpid dpid, OFPortStatus status) {
423 + List<Group> groupList = new ArrayList<>();
424 + OFPortDesc desc = status.getDesc();
425 + PortNumber portNumber = PortNumber.portNumber(desc.getPortNo().getPortNumber());
426 + DeviceId id = DeviceId.deviceId(Dpid.uri(dpid));
427 + if (desc.isEnabled()) {
428 + return groupList;
429 + }
430 + Iterator<Group> iterator = groupService.getGroups(id).iterator();
431 + while (iterator.hasNext()) {
432 + Group group = iterator.next();
433 + if (group.type() == GroupDescription.Type.FAILOVER &&
434 + checkFailoverGroup(group, id, portNumber)) {
435 + groupList.add(group);
436 + }
437 + }
438 + return groupList;
439 + }
440 +
441 + /**
442 + * Checks whether the first live port in the failover group's bucket
443 + * has failed over.
444 + *
445 + * @param group failover group to be checked for failover
446 + * @param id device ID of switch whose port's status changed
447 + * @param portNumber port number of port that was disabled
448 + * @return whether the failover group experienced failover
449 + */
450 + private boolean checkFailoverGroup(Group group, DeviceId id,
451 + PortNumber portNumber) {
452 + boolean portReached = false;
453 + boolean portEnabled = false;
454 + Iterator<GroupBucket> bIterator = group.buckets().buckets().iterator();
455 + GroupBucket bucket;
456 + while (bIterator.hasNext() && !portReached) {
457 + bucket = bIterator.next();
458 + if (deviceService.getPort(id, bucket.watchPort()).isEnabled()) {
459 + portEnabled = true;
460 + }
461 + if (bucket.watchPort().equals(portNumber)) {
462 + portReached = true;
463 + }
464 + }
465 + return portReached && !portEnabled;
466 + }
467 +
399 } 468 }
......
...@@ -201,6 +201,10 @@ public class OpenFlowGroupProviderTest { ...@@ -201,6 +201,10 @@ public class OpenFlowGroupProviderTest {
201 this.groups = groupEntries; 201 this.groups = groupEntries;
202 } 202 }
203 203
204 + @Override
205 + public void notifyOfFailovers(Collection<Group> groups) {
206 + }
207 +
204 public Collection<Group> getGroupEntries() { 208 public Collection<Group> getGroupEntries() {
205 return groups; 209 return groups;
206 } 210 }
......