Group event indicating failover of previously used live port
Change-Id: I32749b38d5e4fab93fa97bbf6587bd0dc91db88c
diff --git a/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/OpenFlowGroupProvider.java b/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/OpenFlowGroupProvider.java
index 83100f4..159b7dd 100644
--- a/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/OpenFlowGroupProvider.java
+++ b/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/OpenFlowGroupProvider.java
@@ -18,7 +18,10 @@
import static org.slf4j.LoggerFactory.getLogger;
+import java.util.ArrayList;
import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicLong;
@@ -31,9 +34,12 @@
import org.onosproject.core.DefaultGroupId;
import org.onosproject.core.GroupId;
import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.device.DeviceService;
import org.onosproject.net.driver.DriverService;
import org.onosproject.net.group.DefaultGroup;
import org.onosproject.net.group.Group;
+import org.onosproject.net.group.GroupBucket;
import org.onosproject.net.group.GroupBuckets;
import org.onosproject.net.group.GroupDescription;
import org.onosproject.net.group.GroupOperation;
@@ -42,6 +48,7 @@
import org.onosproject.net.group.GroupProvider;
import org.onosproject.net.group.GroupProviderRegistry;
import org.onosproject.net.group.GroupProviderService;
+import org.onosproject.net.group.GroupService;
import org.onosproject.net.group.StoredGroupBucketEntry;
import org.onosproject.net.provider.AbstractProvider;
import org.onosproject.net.provider.ProviderId;
@@ -62,6 +69,7 @@
import org.projectfloodlight.openflow.protocol.OFGroupStatsReply;
import org.projectfloodlight.openflow.protocol.OFGroupType;
import org.projectfloodlight.openflow.protocol.OFMessage;
+import org.projectfloodlight.openflow.protocol.OFPortDesc;
import org.projectfloodlight.openflow.protocol.OFPortStatus;
import org.projectfloodlight.openflow.protocol.OFStatsReply;
import org.projectfloodlight.openflow.protocol.OFStatsType;
@@ -88,6 +96,12 @@
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected DriverService driverService;
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected DeviceService deviceService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected GroupService groupService;
+
private GroupProviderService providerService;
static final int POLL_INTERVAL = 10;
@@ -389,6 +403,7 @@
@Override
public void portChanged(Dpid dpid, OFPortStatus status) {
+ providerService.notifyOfFailovers(checkFailoverGroups(dpid, status));
}
@Override
@@ -396,4 +411,58 @@
}
}
+ /**
+ * Builds a list of failover Groups whose primary live bucket failed over
+ * (i.e. bucket in use has changed).
+ *
+ * @param dpid DPID of switch whose port's status changed
+ * @param status new status of port
+ * @return list of groups whose primary live bucket failed over
+ */
+ private List<Group> checkFailoverGroups(Dpid dpid, OFPortStatus status) {
+ List<Group> groupList = new ArrayList<>();
+ OFPortDesc desc = status.getDesc();
+ PortNumber portNumber = PortNumber.portNumber(desc.getPortNo().getPortNumber());
+ DeviceId id = DeviceId.deviceId(Dpid.uri(dpid));
+ if (desc.isEnabled()) {
+ return groupList;
+ }
+ Iterator<Group> iterator = groupService.getGroups(id).iterator();
+ while (iterator.hasNext()) {
+ Group group = iterator.next();
+ if (group.type() == GroupDescription.Type.FAILOVER &&
+ checkFailoverGroup(group, id, portNumber)) {
+ groupList.add(group);
+ }
+ }
+ return groupList;
+ }
+
+ /**
+ * Checks whether the first live port in the failover group's bucket
+ * has failed over.
+ *
+ * @param group failover group to be checked for failover
+ * @param id device ID of switch whose port's status changed
+ * @param portNumber port number of port that was disabled
+ * @return whether the failover group experienced failover
+ */
+ private boolean checkFailoverGroup(Group group, DeviceId id,
+ PortNumber portNumber) {
+ boolean portReached = false;
+ boolean portEnabled = false;
+ Iterator<GroupBucket> bIterator = group.buckets().buckets().iterator();
+ GroupBucket bucket;
+ while (bIterator.hasNext() && !portReached) {
+ bucket = bIterator.next();
+ if (deviceService.getPort(id, bucket.watchPort()).isEnabled()) {
+ portEnabled = true;
+ }
+ if (bucket.watchPort().equals(portNumber)) {
+ portReached = true;
+ }
+ }
+ return portReached && !portEnabled;
+ }
+
}