[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
This commit is contained in:
pierventre 2021-08-03 18:05:42 +02:00
parent 29b4f22e8b
commit 121ea29ece
3 changed files with 56 additions and 4 deletions

View File

@ -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();

View File

@ -51,6 +51,7 @@ public class P4RuntimeGroupProgrammable
final List<GroupOperation> 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);
}

View File

@ -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<DefaultNextTreatment> 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<DefaultNextTreatment> defaultNextTreatments(
Collection<NextTreatment> nextTreatments, boolean strict)
throws FabricPipelinerException {