Group event indicating failover of previously used live port
Change-Id: I32749b38d5e4fab93fa97bbf6587bd0dc91db88c
diff --git a/core/api/src/main/java/org/onosproject/net/group/GroupEvent.java b/core/api/src/main/java/org/onosproject/net/group/GroupEvent.java
index 23aa97b..24d3221 100644
--- a/core/api/src/main/java/org/onosproject/net/group/GroupEvent.java
+++ b/core/api/src/main/java/org/onosproject/net/group/GroupEvent.java
@@ -56,6 +56,13 @@
*/
GROUP_UPDATE_FAILED,
+ /**
+ * Signifies change in the first live bucket in failover group
+ * (i.e. change in which bucket is in use).
+ * Only to be used with failover Group.
+ */
+ GROUP_BUCKET_FAILOVER,
+
// internal event between Manager <-> Store
/*
diff --git a/core/api/src/main/java/org/onosproject/net/group/GroupProviderService.java b/core/api/src/main/java/org/onosproject/net/group/GroupProviderService.java
index ce99680..0a826bb 100644
--- a/core/api/src/main/java/org/onosproject/net/group/GroupProviderService.java
+++ b/core/api/src/main/java/org/onosproject/net/group/GroupProviderService.java
@@ -41,7 +41,12 @@
* @param deviceId device identifier
* @param groupEntries collection of group entries as seen in data plane
*/
- void pushGroupMetrics(DeviceId deviceId,
- Collection<Group> groupEntries);
+ void pushGroupMetrics(DeviceId deviceId, Collection<Group> groupEntries);
+ /**
+ * Notifies store of group failovers.
+ *
+ * @param failoverGroups failover groups in which a failover has occurred
+ */
+ void notifyOfFailovers(Collection<Group> failoverGroups);
}
diff --git a/core/api/src/main/java/org/onosproject/net/group/GroupStore.java b/core/api/src/main/java/org/onosproject/net/group/GroupStore.java
index 3b29d61..d2dd992 100644
--- a/core/api/src/main/java/org/onosproject/net/group/GroupStore.java
+++ b/core/api/src/main/java/org/onosproject/net/group/GroupStore.java
@@ -179,4 +179,9 @@
* @param groupEntries the group entries as received from southbound
*/
void pushGroupMetrics(DeviceId deviceId, Collection<Group> groupEntries);
+
+ /**
+ * Indicates failover within a failover group.
+ */
+ void notifyOfFailovers(Collection<Group> failoverGroups);
}
diff --git a/core/common/src/test/java/org/onosproject/store/trivial/SimpleGroupStore.java b/core/common/src/test/java/org/onosproject/store/trivial/SimpleGroupStore.java
index 6e03b2b..9727c90 100644
--- a/core/common/src/test/java/org/onosproject/store/trivial/SimpleGroupStore.java
+++ b/core/common/src/test/java/org/onosproject/store/trivial/SimpleGroupStore.java
@@ -646,6 +646,17 @@
}
}
+ @Override
+ public void notifyOfFailovers(Collection<Group> failoverGroups) {
+ List<GroupEvent> failoverEvents = new ArrayList<>();
+ failoverGroups.forEach(group -> {
+ if (group.type() == Group.Type.FAILOVER) {
+ failoverEvents.add(new GroupEvent(GroupEvent.Type.GROUP_BUCKET_FAILOVER, group));
+ }
+ });
+ notifyDelegate(failoverEvents);
+ }
+
private void groupMissing(Group group) {
switch (group.state()) {
case PENDING_DELETE:
diff --git a/core/net/src/main/java/org/onosproject/net/group/impl/GroupManager.java b/core/net/src/main/java/org/onosproject/net/group/impl/GroupManager.java
index 1150d05..2e4a375 100644
--- a/core/net/src/main/java/org/onosproject/net/group/impl/GroupManager.java
+++ b/core/net/src/main/java/org/onosproject/net/group/impl/GroupManager.java
@@ -324,9 +324,9 @@
case GROUP_ADD_FAILED:
case GROUP_UPDATE_FAILED:
case GROUP_REMOVE_FAILED:
+ case GROUP_BUCKET_FAILOVER:
post(event);
break;
-
default:
break;
}
@@ -353,6 +353,11 @@
checkValidity();
store.pushGroupMetrics(deviceId, groupEntries);
}
+
+ @Override
+ public void notifyOfFailovers(Collection<Group> failoverGroups) {
+ store.notifyOfFailovers(failoverGroups);
+ }
}
private class InternalDeviceListener implements DeviceListener {
@@ -378,4 +383,5 @@
}
}
}
+
}
diff --git a/core/store/dist/src/main/java/org/onosproject/store/group/impl/DistributedGroupStore.java b/core/store/dist/src/main/java/org/onosproject/store/group/impl/DistributedGroupStore.java
index afdec73..1f9387e 100644
--- a/core/store/dist/src/main/java/org/onosproject/store/group/impl/DistributedGroupStore.java
+++ b/core/store/dist/src/main/java/org/onosproject/store/group/impl/DistributedGroupStore.java
@@ -1312,6 +1312,17 @@
}
}
+ @Override
+ public void notifyOfFailovers(Collection<Group> failoverGroups) {
+ List<GroupEvent> failoverEvents = new ArrayList<>();
+ failoverGroups.forEach(group -> {
+ if (group.type() == Group.Type.FAILOVER) {
+ failoverEvents.add(new GroupEvent(GroupEvent.Type.GROUP_BUCKET_FAILOVER, group));
+ }
+ });
+ notifyDelegate(failoverEvents);
+ }
+
private void garbageCollect(DeviceId deviceId,
Set<Group> southboundGroupEntries,
Set<StoredGroupEntry> storedGroupEntries) {
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;
+ }
+
}
diff --git a/providers/openflow/group/src/test/java/org/onosproject/provider/of/group/impl/OpenFlowGroupProviderTest.java b/providers/openflow/group/src/test/java/org/onosproject/provider/of/group/impl/OpenFlowGroupProviderTest.java
index ff08f72..cc2cd39 100644
--- a/providers/openflow/group/src/test/java/org/onosproject/provider/of/group/impl/OpenFlowGroupProviderTest.java
+++ b/providers/openflow/group/src/test/java/org/onosproject/provider/of/group/impl/OpenFlowGroupProviderTest.java
@@ -201,6 +201,10 @@
this.groups = groupEntries;
}
+ @Override
+ public void notifyOfFailovers(Collection<Group> groups) {
+ }
+
public Collection<Group> getGroupEntries() {
return groups;
}