ONOS-7797 Support adding an arbitrary number of members to an existing P4Runtime group
Change-Id: I7b9ed589ca15957ee1b2780934a6da8e998bace3
diff --git a/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeActionGroupProgrammable.java b/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeActionGroupProgrammable.java
index 5ee965d..fd2ef27 100644
--- a/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeActionGroupProgrammable.java
+++ b/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeActionGroupProgrammable.java
@@ -26,6 +26,7 @@
import org.onosproject.drivers.p4runtime.mirror.P4RuntimeActionProfileMemberMirror;
import org.onosproject.drivers.p4runtime.mirror.P4RuntimeGroupMirror;
import org.onosproject.drivers.p4runtime.mirror.TimedEntry;
+import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.DeviceId;
import org.onosproject.net.group.DefaultGroup;
import org.onosproject.net.group.DefaultGroupDescription;
@@ -76,6 +77,7 @@
// the ONOS store.
private static final String READ_ACTION_GROUPS_FROM_MIRROR = "actionGroupReadFromMirror";
private static final boolean DEFAULT_READ_ACTION_GROUPS_FROM_MIRROR = false;
+ private static final String MAX_MEM_SIZE = "maxMemSize";
protected GroupStore groupStore;
private P4RuntimeGroupMirror groupMirror;
@@ -84,6 +86,7 @@
// Needed to synchronize operations over the same group.
private static final Striped<Lock> STRIPED_LOCKS = Striped.lock(30);
+ private static final int GROUP_MEMBERS_BUFFER_SIZE = 3;
@Override
protected boolean setupBehaviour() {
@@ -342,20 +345,40 @@
}
private boolean applyGroup(PiActionGroup group, PiActionGroupHandle handle) {
- final P4RuntimeClient.WriteOperationType opType =
+ final int currentMemberSize = group.members().size();
+ if (groupMirror.get(handle) != null) {
+ String maxMemSize = "";
+ if (groupMirror.annotations(handle) != null &&
+ groupMirror.annotations(handle).value(MAX_MEM_SIZE) != null) {
+ maxMemSize = groupMirror.annotations(handle).value(MAX_MEM_SIZE);
+ }
+ if (maxMemSize == "" || currentMemberSize > Integer.parseInt(maxMemSize)) {
+ deleteGroup(group, handle);
+ }
+ }
+
+ P4RuntimeClient.WriteOperationType opType =
groupMirror.get(handle) == null ? INSERT : MODIFY;
+ int currentMaxMemberSize = opType == INSERT ? (currentMemberSize + GROUP_MEMBERS_BUFFER_SIZE) : 0;
+
final boolean success = getFutureWithDeadline(
- client.writeActionGroup(group, opType, pipeconf),
+ client.writeActionGroup(group, opType, pipeconf, currentMaxMemberSize),
"performing action profile group " + opType, false);
if (success) {
groupMirror.put(handle, group);
+ if (opType == INSERT) {
+ groupMirror.putAnnotations(handle, DefaultAnnotations
+ .builder()
+ .set(MAX_MEM_SIZE, Integer.toString(currentMaxMemberSize))
+ .build());
+ }
}
return success;
}
private boolean deleteGroup(PiActionGroup group, PiActionGroupHandle handle) {
final boolean success = getFutureWithDeadline(
- client.writeActionGroup(group, DELETE, pipeconf),
+ client.writeActionGroup(group, DELETE, pipeconf, 0),
"performing action profile group " + DELETE, false);
if (success) {
groupMirror.remove(handle);
diff --git a/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/mirror/AbstractDistributedP4RuntimeMirror.java b/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/mirror/AbstractDistributedP4RuntimeMirror.java
index 9230547..fc982be 100644
--- a/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/mirror/AbstractDistributedP4RuntimeMirror.java
+++ b/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/mirror/AbstractDistributedP4RuntimeMirror.java
@@ -25,6 +25,7 @@
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.onlab.util.KryoNamespace;
import org.onlab.util.SharedExecutors;
+import org.onosproject.net.Annotations;
import org.onosproject.net.DeviceId;
import org.onosproject.net.pi.runtime.PiEntity;
import org.onosproject.net.pi.runtime.PiHandle;
@@ -69,6 +70,8 @@
private EventuallyConsistentMap<H, TimedEntry<E>> mirrorMap;
+ private EventuallyConsistentMap<H, Annotations> annotationsMap;
+
private final PiPipeconfWatchdogListener pipeconfListener =
new InternalPipeconfWatchdogListener();
@@ -80,6 +83,14 @@
.withSerializer(storeSerializer())
.withTimestampProvider((k, v) -> new WallClockTimestamp())
.build();
+
+ annotationsMap = storageService
+ .<H, Annotations>eventuallyConsistentMapBuilder()
+ .withName(mapName() + "-annotations")
+ .withSerializer(storeSerializer())
+ .withTimestampProvider((k, v) -> new WallClockTimestamp())
+ .build();
+
pipeconfWatchdogService.addListener(pipeconfListener);
log.info("Started");
}
@@ -132,6 +143,20 @@
public void remove(H handle) {
checkNotNull(handle);
mirrorMap.remove(handle);
+ annotationsMap.remove(handle);
+ }
+
+ @Override
+ public void putAnnotations(H handle, Annotations annotations) {
+ checkNotNull(handle);
+ checkNotNull(annotations);
+ annotationsMap.put(handle, annotations);
+ }
+
+ @Override
+ public Annotations annotations(H handle) {
+ checkNotNull(handle);
+ return annotationsMap.get(handle);
}
@Override
@@ -190,7 +215,7 @@
private void removeAll(DeviceId deviceId) {
checkNotNull(deviceId);
Collection<H> handles = getHandlesForDevice(deviceId);
- handles.forEach(mirrorMap::remove);
+ handles.forEach(this::remove);
}
public class InternalPipeconfWatchdogListener implements PiPipeconfWatchdogListener {
diff --git a/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/mirror/P4RuntimeMirror.java b/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/mirror/P4RuntimeMirror.java
index d1c9cdd..51b31aa 100644
--- a/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/mirror/P4RuntimeMirror.java
+++ b/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/mirror/P4RuntimeMirror.java
@@ -17,6 +17,7 @@
package org.onosproject.drivers.p4runtime.mirror;
import com.google.common.annotations.Beta;
+import org.onosproject.net.Annotations;
import org.onosproject.net.DeviceId;
import org.onosproject.net.pi.runtime.PiEntity;
import org.onosproject.net.pi.runtime.PiHandle;
@@ -74,6 +75,23 @@
void remove(H handle);
/**
+ * Stores the given annotations associating it to the given handle.
+ *
+ * @param handle handle
+ * @param annotations entry
+ */
+ void putAnnotations(H handle, Annotations annotations);
+
+ /**
+ * Returns annotations associated to the given handle, if present, otherwise
+ * null.
+ *
+ * @param handle handle
+ * @return PI table annotations
+ */
+ Annotations annotations(H handle);
+
+ /**
* Synchronizes the state of the given device ID with the given handle map.
*
* @param deviceId device ID