ONOS-7898 Action profile group/member refactoring
Also includes:
- New abstract P4Runtime codec implementation. Currently used for action
profile members/groups encoding/deconding, the plan is to handle all
other codecs via this.
- Improved read requests in P4RuntimeClientImpl
- Removed handling of max group size in P4Runtime driver. Instead, added
modified group translator to specify a max group size by using
information from the pipeline model.
Change-Id: I684bae0184d683bb448ba19863c561f9848479d2
diff --git a/core/api/src/main/java/org/onosproject/net/pi/runtime/PiActionProfileGroup.java b/core/api/src/main/java/org/onosproject/net/pi/runtime/PiActionProfileGroup.java
index 96168b9..f86e70c 100644
--- a/core/api/src/main/java/org/onosproject/net/pi/runtime/PiActionProfileGroup.java
+++ b/core/api/src/main/java/org/onosproject/net/pi/runtime/PiActionProfileGroup.java
@@ -19,13 +19,15 @@
import com.google.common.annotations.Beta;
import com.google.common.base.MoreObjects;
import com.google.common.base.Objects;
-import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import org.onosproject.net.pi.model.PiActionProfileId;
import java.util.Collection;
import java.util.Map;
+import java.util.Optional;
+import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
/**
@@ -34,70 +36,96 @@
@Beta
public final class PiActionProfileGroup implements PiEntity {
- private final PiActionProfileGroupId id;
- private final ImmutableSet<PiActionProfileMember> members;
private final PiActionProfileId actionProfileId;
+ private final PiActionProfileGroupId groupId;
+ private final ImmutableMap<PiActionProfileMemberId, WeightedMember> members;
+ private final int maxSize;
- private PiActionProfileGroup(PiActionProfileGroupId id,
- ImmutableSet<PiActionProfileMember> members,
- PiActionProfileId actionProfileId) {
- this.id = id;
+ private PiActionProfileGroup(PiActionProfileGroupId groupId,
+ ImmutableMap<PiActionProfileMemberId, WeightedMember> members,
+ PiActionProfileId actionProfileId,
+ int maxSize) {
+ this.groupId = groupId;
this.members = members;
this.actionProfileId = actionProfileId;
+ this.maxSize = maxSize;
}
/**
- * Returns the identifier of this action profile group.
+ * Returns the ID of this action profile group.
*
- * @return action profile group identifier
+ * @return action profile group ID
*/
public PiActionProfileGroupId id() {
- return id;
+ return groupId;
}
/**
- * Returns the members of this action profile group.
+ * Returns the list of member references of this action profile group.
*
* @return collection of action profile members.
*/
- public Collection<PiActionProfileMember> members() {
- return members;
+ public Collection<WeightedMember> members() {
+ return members.values();
}
/**
- * Gets identifier of the action profile.
+ * Returns the group member identified by the given action profile member
+ * ID, if present.
*
- * @return action profile id
+ * @param memberId action profile member ID
+ * @return optional group member
*/
- public PiActionProfileId actionProfileId() {
+ public Optional<WeightedMember> member(PiActionProfileMemberId memberId) {
+ return Optional.of(members.get(memberId));
+ }
+
+ /**
+ * Returns the maximum number of members that this group can hold. 0
+ * signifies that a limit is not set.
+ *
+ * @return maximum number of members that this group can hold
+ */
+ public int maxSize() {
+ return maxSize;
+ }
+
+ /**
+ * Returns the ID of the action profile where this group belong.
+ *
+ * @return action profile ID
+ */
+ public PiActionProfileId actionProfile() {
return actionProfileId;
}
@Override
- public boolean equals(Object o) {
- if (this == o) {
+ public boolean equals(Object obj) {
+ if (this == obj) {
return true;
}
- if (o == null || !(o instanceof PiActionProfileGroup)) {
+ if (obj == null || getClass() != obj.getClass()) {
return false;
}
- PiActionProfileGroup that = (PiActionProfileGroup) o;
- return Objects.equal(id, that.id) &&
- Objects.equal(members, that.members) &&
- Objects.equal(actionProfileId, that.actionProfileId);
+ final PiActionProfileGroup other = (PiActionProfileGroup) obj;
+ return Objects.equal(this.groupId, other.groupId)
+ && Objects.equal(this.members, other.members)
+ && Objects.equal(this.maxSize, other.maxSize)
+ && Objects.equal(this.actionProfileId, other.actionProfileId);
}
@Override
public int hashCode() {
- return Objects.hashCode(id, members);
+ return Objects.hashCode(groupId, members, maxSize, actionProfileId);
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
- .add("groupId", id)
+ .add("actionProfile", actionProfileId)
+ .add("id", groupId)
.add("members", members)
- .add("piActionProfileId", actionProfileId)
+ .add("maxSize", maxSize)
.toString();
}
@@ -120,55 +148,115 @@
*/
public static final class Builder {
- private PiActionProfileGroupId id;
- private Map<PiActionProfileMemberId, PiActionProfileMember> members = Maps.newHashMap();
- private PiActionProfileId piActionProfileId;
+ private PiActionProfileGroupId groupId;
+ private Map<PiActionProfileMemberId, WeightedMember> members = Maps.newHashMap();
+ private PiActionProfileId actionProfileId;
+ private int maxSize;
private Builder() {
// hides constructor.
}
/**
- * Sets the identifier of this action profile group.
+ * Sets the ID of this action profile group.
*
- * @param id action profile group identifier
+ * @param id action profile group ID
* @return this
*/
public Builder withId(PiActionProfileGroupId id) {
- this.id = id;
+ this.groupId = id;
return this;
}
/**
- * Adds one member to this action profile group.
+ * Adds one member to this action profile.
*
- * @param member action profile member
+ * @param member member to add
* @return this
*/
- public Builder addMember(PiActionProfileMember member) {
+ public Builder addMember(WeightedMember member) {
+ checkNotNull(member);
members.put(member.id(), member);
return this;
}
/**
- * Adds many members to this action profile group.
+ * Adds one member to this action profile group with default weight.
*
- * @param members action profile members
+ * @param memberId ID of the action profile member to add
* @return this
*/
- public Builder addMembers(Collection<PiActionProfileMember> members) {
- members.forEach(this::addMember);
+ public Builder addMember(PiActionProfileMemberId memberId) {
+ addMember(new WeightedMember(memberId, WeightedMember.DEFAULT_WEIGHT));
return this;
}
/**
- * Sets the identifier of the action profile.
+ * Adds one member to this action profile group with default weight.
*
- * @param piActionProfileId the identifier of the action profile
+ * @param memberInstance the action profile member instance to add
+ * @return this
+ */
+ public Builder addMember(PiActionProfileMember memberInstance) {
+ addMember(new WeightedMember(memberInstance, WeightedMember.DEFAULT_WEIGHT));
+ return this;
+ }
+
+ /**
+ * Adds all members to this action profile group with default weight.
+ *
+ * @param memberInstances the action profile member instance to add
+ * @return this
+ */
+ public Builder addMembers(Iterable<PiActionProfileMember> memberInstances) {
+ memberInstances.forEach(this::addMember);
+ return this;
+ }
+
+ /**
+ * Adds one member to this action profile group with the given weight.
+ *
+ * @param memberId ID of the action profile member to add
+ * @param weight weight
+ * @return this
+ */
+ public Builder addMember(PiActionProfileMemberId memberId, int weight) {
+ addMember(new WeightedMember(memberId, weight));
+ return this;
+ }
+
+ /**
+ * Adds one member to this action profile group with the given weight.
+ *
+ * @param memberInstance the action profile member instance to add
+ * @param weight weight
+ * @return this
+ */
+ public Builder addMember(PiActionProfileMember memberInstance, int weight) {
+ addMember(new WeightedMember(memberInstance, weight));
+ return this;
+ }
+
+ /**
+ * Sets the ID of the action profile.
+ *
+ * @param piActionProfileId the ID of the action profile
* @return this
*/
public Builder withActionProfileId(PiActionProfileId piActionProfileId) {
- this.piActionProfileId = piActionProfileId;
+ this.actionProfileId = piActionProfileId;
+ return this;
+ }
+
+ /**
+ * Sets the maximum number of members that this group can hold.
+ *
+ * @param maxSize maximum number of members that this group can hold
+ * @return this
+ */
+ public Builder withMaxSize(int maxSize) {
+ checkArgument(maxSize >= 0, "maxSize cannot be negative");
+ this.maxSize = maxSize;
return this;
}
@@ -178,10 +266,119 @@
* @return action profile group
*/
public PiActionProfileGroup build() {
- checkNotNull(id);
- checkNotNull(piActionProfileId);
+ checkNotNull(groupId);
+ checkNotNull(actionProfileId);
+ checkArgument(maxSize == 0 || members.size() <= maxSize,
+ "The number of members cannot exceed maxSize");
+ final boolean validActionProfileId = members.isEmpty() || members.values()
+ .stream().allMatch(m -> m.instance() == null || m.instance()
+ .actionProfile().equals(actionProfileId));
+ checkArgument(
+ validActionProfileId,
+ "The members' action profile ID must match the group one");
return new PiActionProfileGroup(
- id, ImmutableSet.copyOf(members.values()), piActionProfileId);
+ groupId, ImmutableMap.copyOf(members), actionProfileId, maxSize);
+ }
+ }
+
+ /**
+ * Weighted reference to an action profile member as used in an action
+ * profile group.
+ */
+ public static final class WeightedMember {
+
+ public static final int DEFAULT_WEIGHT = 1;
+
+ private final PiActionProfileMemberId memberId;
+ private final int weight;
+ private final PiActionProfileMember memberInstance;
+
+ /**
+ * Creates a new reference for the given action profile member ID and
+ * weight.
+ *
+ * @param memberId action profile member ID
+ * @param weight weight
+ */
+ public WeightedMember(PiActionProfileMemberId memberId, int weight) {
+ checkNotNull(memberId);
+ this.memberId = memberId;
+ this.weight = weight;
+ this.memberInstance = null;
+ }
+
+ /**
+ * Creates a new reference from the given action profile member instance
+ * and weight. This constructor should be used when performing one-shot
+ * group programming (see {@link #instance()}).
+ *
+ * @param memberInstance action profile member instance
+ * @param weight weight
+ */
+ public WeightedMember(PiActionProfileMember memberInstance, int weight) {
+ checkNotNull(memberInstance);
+ this.memberId = memberInstance.id();
+ this.weight = weight;
+ this.memberInstance = memberInstance;
+ }
+
+ /**
+ * Returns the ID of the action profile member.
+ *
+ * @return action profile member ID
+ */
+ public PiActionProfileMemberId id() {
+ return memberId;
+ }
+
+ /**
+ * Returns the weight of this group member.
+ *
+ * @return weight
+ */
+ public int weight() {
+ return weight;
+ }
+
+ /**
+ * If present, returns the instance of the action profile member pointed
+ * by this reference, otherwise returns null. This method is provided as
+ * a convenient way to perform one-shot group programming, and as such
+ * is meaningful only when performing write operations to a device. In
+ * other words, when reading groups from a device only the member
+ * reference should be returned and not the actual instance, hence this
+ * method should return null.
+ *
+ * @return action profile member instance, or null
+ */
+ public PiActionProfileMember instance() {
+ return memberInstance;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(memberId, weight);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+ final WeightedMember other = (WeightedMember) obj;
+ return Objects.equal(this.memberId, other.memberId)
+ && Objects.equal(this.weight, other.weight);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("memberId", memberId)
+ .add("weight", weight)
+ .toString();
}
}
}