From 121ea29ece6bfa638d34f3f1d4b7d14f6af0c756 Mon Sep 17 00:00:00 2001 From: pierventre Date: Tue, 3 Aug 2021 18:05:42 +0200 Subject: [PATCH] [SDFAB-379] Optimize the resource usage of the L3 unicast groups This is achieved by translating SIMPLE next objective into INDIRECT groups. By default SELECT groups are always used which has as side effect the creation of action profile groups with the maxGroupSize derived from the action profile model. Instead, PiGroupTranslator sets always to 1 the maxGroupSize of action profile groups derived from a INDIRECT groups which allows us to achieve a better scale for target devices pre-allocating memory according to the maxGroupSize. Change-Id: I7079a99ca9a7474eafae7f258da06770453b05f9 --- .../net/pi/impl/PiGroupTranslatorImpl.java | 5 +- .../p4runtime/P4RuntimeGroupProgrammable.java | 2 +- .../pipeliner/NextObjectiveTranslator.java | 53 ++++++++++++++++++- 3 files changed, 56 insertions(+), 4 deletions(-) diff --git a/core/net/src/main/java/org/onosproject/net/pi/impl/PiGroupTranslatorImpl.java b/core/net/src/main/java/org/onosproject/net/pi/impl/PiGroupTranslatorImpl.java index e06f54ea35..4bf4330f39 100644 --- a/core/net/src/main/java/org/onosproject/net/pi/impl/PiGroupTranslatorImpl.java +++ b/core/net/src/main/java/org/onosproject/net/pi/impl/PiGroupTranslatorImpl.java @@ -173,7 +173,10 @@ final class PiGroupTranslatorImpl { .withAction((PiAction) tableAction) .build(); - piActionGroupBuilder.addMember(member, bucket.weight()); + // NOTE Indirect groups have weight set to -1 which is not supported + // by P4RT - setting to 1 to avoid problems with the p4rt server. + final int weight = group.type() == GroupDescription.Type.INDIRECT ? 1 : bucket.weight(); + piActionGroupBuilder.addMember(member, weight); } return piActionGroupBuilder.build(); diff --git a/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeGroupProgrammable.java b/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeGroupProgrammable.java index f38b504760..80da11ddda 100644 --- a/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeGroupProgrammable.java +++ b/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeGroupProgrammable.java @@ -51,6 +51,7 @@ public class P4RuntimeGroupProgrammable final List preGroups = Lists.newArrayList(); groupOps.operations().forEach(op -> { switch (op.groupType()) { + case INDIRECT: case SELECT: actionGroups.add(op); break; @@ -59,7 +60,6 @@ public class P4RuntimeGroupProgrammable preGroups.add(op); break; case FAILOVER: - case INDIRECT: default: log.warn("{} group type not supported [{}]", op.groupType(), op); } diff --git a/pipelines/fabric/impl/src/main/java/org/onosproject/pipelines/fabric/impl/behaviour/pipeliner/NextObjectiveTranslator.java b/pipelines/fabric/impl/src/main/java/org/onosproject/pipelines/fabric/impl/behaviour/pipeliner/NextObjectiveTranslator.java index 47b7ef6d14..037e5dd587 100644 --- a/pipelines/fabric/impl/src/main/java/org/onosproject/pipelines/fabric/impl/behaviour/pipeliner/NextObjectiveTranslator.java +++ b/pipelines/fabric/impl/src/main/java/org/onosproject/pipelines/fabric/impl/behaviour/pipeliner/NextObjectiveTranslator.java @@ -53,6 +53,7 @@ import org.onosproject.pipelines.fabric.FabricConstants; import org.onosproject.pipelines.fabric.impl.behaviour.FabricUtils; import java.util.Collection; +import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.Set; @@ -268,8 +269,18 @@ class NextObjectiveTranslator return; } - // Updated result builder with hashed group. - final int groupId = selectGroup(obj, resultBuilder); + // Updated result builder with hashed group or indirect group + // use indirect group allow us to optimize the resource in those + // devices that preallocate memory based on the maxGroupSize + final int groupId; + if (obj.type() == NextObjective.Type.HASHED) { + groupId = selectGroup(obj, resultBuilder); + } else if (obj.type() == NextObjective.Type.SIMPLE) { + groupId = indirectGroup(obj, resultBuilder); + } else { + throw new FabricPipelinerException("Cannot translate BROADCAST next objective" + + "into hashedNext actions"); + } if (isGroupModifyOp(obj) || obj.op() == Objective.Operation.VERIFY) { // No changes to flow rules. @@ -505,6 +516,44 @@ class NextObjectiveTranslator return groupId; } + private int indirectGroup(NextObjective obj, + ObjectiveTranslation.Builder resultBuilder) + throws FabricPipelinerException { + + if (isGroupModifyOp(obj)) { + throw new FabricPipelinerException("Simple next objective does not support" + + "*_TO_EXISTING operations"); + } + + final PiTableId hashedTableId = FabricConstants.FABRIC_INGRESS_NEXT_HASHED; + final List defaultNextTreatments = + defaultNextTreatments(obj.nextTreatments(), true); + + if (defaultNextTreatments.size() != 1) { + throw new FabricPipelinerException("Simple next objective must have a single" + + " treatment"); + } + + final TrafficTreatment piTreatment; + final DefaultNextTreatment defaultNextTreatment = defaultNextTreatments.get(0); + piTreatment = mapTreatmentToPiIfNeeded(defaultNextTreatment.treatment(), hashedTableId); + handleEgress(obj, defaultNextTreatment.treatment(), resultBuilder, false); + final GroupBucket groupBucket = DefaultGroupBucket.createIndirectGroupBucket(piTreatment); + + final int groupId = obj.id(); + final PiGroupKey groupKey = (PiGroupKey) getGroupKey(obj); + + resultBuilder.addGroup(new DefaultGroupDescription( + deviceId, + GroupDescription.Type.INDIRECT, + new GroupBuckets(Collections.singletonList(groupBucket)), + groupKey, + groupId, + obj.appId())); + + return groupId; + } + private List defaultNextTreatments( Collection nextTreatments, boolean strict) throws FabricPipelinerException {