Added support for clone session on fabric.p4
Now on ACL table in fabric.p4 you can clone a packet to the CPU using the clone session.
Change-Id: Ic21f948cffe553e32e7b2fe1f7af49b6a387fffb
diff --git a/pipelines/fabric/src/main/java/org/onosproject/pipelines/fabric/FabricConstants.java b/pipelines/fabric/src/main/java/org/onosproject/pipelines/fabric/FabricConstants.java
index eb927ad..f1bb185 100644
--- a/pipelines/fabric/src/main/java/org/onosproject/pipelines/fabric/FabricConstants.java
+++ b/pipelines/fabric/src/main/java/org/onosproject/pipelines/fabric/FabricConstants.java
@@ -223,6 +223,8 @@
PiActionId.of("FabricEgress.process_int_main.process_int_transit.init_metadata");
public static final PiActionId FABRIC_INGRESS_ACL_DROP =
PiActionId.of("FabricIngress.acl.drop");
+ public static final PiActionId FABRIC_INGRESS_ACL_SET_CLONE_SESSION_ID =
+ PiActionId.of("FabricIngress.acl.set_clone_session_id");
public static final PiActionId FABRIC_INGRESS_BNG_INGRESS_UPSTREAM_PUNT_TO_CPU =
PiActionId.of("FabricIngress.bng_ingress.upstream.punt_to_cpu");
public static final PiActionId FABRIC_INGRESS_BNG_INGRESS_UPSTREAM_SET_LINE =
@@ -276,8 +278,6 @@
public static final PiActionId NOP = PiActionId.of("nop");
public static final PiActionId FABRIC_INGRESS_NEXT_OUTPUT_SIMPLE =
PiActionId.of("FabricIngress.next.output_simple");
- public static final PiActionId FABRIC_INGRESS_ACL_CLONE_TO_CPU =
- PiActionId.of("FabricIngress.acl.clone_to_cpu");
public static final PiActionId FABRIC_INGRESS_FILTERING_DENY =
PiActionId.of("FabricIngress.filtering.deny");
public static final PiActionId FABRIC_INGRESS_NEXT_SET_MCAST_GROUP_ID =
@@ -298,6 +298,8 @@
public static final PiActionParamId S1U_SGW_ADDR =
PiActionParamId.of("s1u_sgw_addr");
public static final PiActionParamId SMAC = PiActionParamId.of("smac");
+ public static final PiActionParamId CLONE_ID =
+ PiActionParamId.of("clone_id");
public static final PiActionParamId VLAN_ID = PiActionParamId.of("vlan_id");
public static final PiActionParamId LABEL = PiActionParamId.of("label");
public static final PiActionParamId SRC_IP = PiActionParamId.of("src_ip");
diff --git a/pipelines/fabric/src/main/java/org/onosproject/pipelines/fabric/FabricTreatmentInterpreter.java b/pipelines/fabric/src/main/java/org/onosproject/pipelines/fabric/FabricTreatmentInterpreter.java
index bca8424..b7ee4c5 100644
--- a/pipelines/fabric/src/main/java/org/onosproject/pipelines/fabric/FabricTreatmentInterpreter.java
+++ b/pipelines/fabric/src/main/java/org/onosproject/pipelines/fabric/FabricTreatmentInterpreter.java
@@ -42,7 +42,6 @@
import static org.onosproject.net.flow.instructions.L2ModificationInstruction.L2SubType.VLAN_POP;
import static org.onosproject.pipelines.fabric.FabricUtils.instruction;
import static org.onosproject.pipelines.fabric.FabricUtils.l2Instruction;
-import static org.onosproject.pipelines.fabric.FabricUtils.outputPort;
/**
* Treatment translation logic.
@@ -193,23 +192,12 @@
if (isNoAction(treatment)) {
return nop(tableId);
}
+ treatmentException(
+ tableId, treatment,
+ "unsupported treatment");
- final PortNumber outPort = outputPort(treatment);
- if (outPort == null
- || !outPort.equals(PortNumber.CONTROLLER)
- || treatment.allInstructions().size() > 1) {
- treatmentException(
- tableId, treatment,
- "supports only punt/clone to CPU actions");
- }
-
- final PiActionId actionId = treatment.clearedDeferred()
- ? FabricConstants.FABRIC_INGRESS_ACL_PUNT_TO_CPU
- : FabricConstants.FABRIC_INGRESS_ACL_CLONE_TO_CPU;
-
- return PiAction.builder()
- .withId(actionId)
- .build();
+ // This function will never return null
+ return null;
}
diff --git a/pipelines/fabric/src/main/java/org/onosproject/pipelines/fabric/pipeliner/ForwardingObjectiveTranslator.java b/pipelines/fabric/src/main/java/org/onosproject/pipelines/fabric/pipeliner/ForwardingObjectiveTranslator.java
index 5647d26..066af7d 100644
--- a/pipelines/fabric/src/main/java/org/onosproject/pipelines/fabric/pipeliner/ForwardingObjectiveTranslator.java
+++ b/pipelines/fabric/src/main/java/org/onosproject/pipelines/fabric/pipeliner/ForwardingObjectiveTranslator.java
@@ -18,11 +18,14 @@
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
+import org.onosproject.core.ApplicationId;
import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.FlowRule;
@@ -34,7 +37,14 @@
import org.onosproject.net.flow.criteria.MplsCriterion;
import org.onosproject.net.flow.criteria.VlanIdCriterion;
import org.onosproject.net.flowobjective.ForwardingObjective;
+import org.onosproject.net.flowobjective.Objective;
import org.onosproject.net.flowobjective.ObjectiveError;
+import org.onosproject.net.group.DefaultGroupDescription;
+import org.onosproject.net.group.GroupBucket;
+import org.onosproject.net.group.GroupBuckets;
+import org.onosproject.net.group.DefaultGroupKey;
+import org.onosproject.net.group.GroupDescription;
+import org.onosproject.net.group.GroupKey;
import org.onosproject.net.pi.model.PiActionId;
import org.onosproject.net.pi.model.PiTableId;
import org.onosproject.net.pi.runtime.PiAction;
@@ -49,6 +59,9 @@
import static java.lang.String.format;
import static org.onosproject.pipelines.fabric.FabricUtils.criterionNotNull;
+import static org.onosproject.pipelines.fabric.FabricUtils.outputPort;
+import static org.onosproject.net.group.DefaultGroupBucket.createCloneGroupBucket;
+
/**
* ObjectiveTranslator implementation ForwardingObjective.
@@ -56,6 +69,8 @@
class ForwardingObjectiveTranslator
extends AbstractObjectiveTranslator<ForwardingObjective> {
+ //FIXME: Max number supported by PI
+ static final int CLONE_TO_CPU_ID = 511;
private static final List<String> DEFAULT_ROUTE_PREFIXES = Lists.newArrayList(
"0.0.0.0/1", "128.0.0.0/1");
@@ -245,11 +260,64 @@
private void aclRule(ForwardingObjective obj,
ObjectiveTranslation.Builder resultBuilder)
throws FabricPipelinerException {
+ if (obj.nextId() == null && obj.treatment() != null) {
+ final TrafficTreatment treatment = obj.treatment();
+ final PortNumber outPort = outputPort(treatment);
+ if (outPort != null
+ && outPort.equals(PortNumber.CONTROLLER)
+ && treatment.allInstructions().size() == 1) {
+ final PiAction aclAction;
+ if (treatment.clearedDeferred()) {
+ aclAction = PiAction.builder()
+ .withId(FabricConstants.FABRIC_INGRESS_ACL_PUNT_TO_CPU)
+ .build();
+ } else {
+ // Action is SET_CLONE_SESSION_ID
+ if (obj.op() == Objective.Operation.ADD) {
+ // Action is ADD, create clone group
+ final DefaultGroupDescription cloneGroup =
+ createCloneGroup(obj.appId(),
+ CLONE_TO_CPU_ID,
+ outPort);
+ resultBuilder.addGroup(cloneGroup);
+ }
+ aclAction = PiAction.builder()
+ .withId(FabricConstants.FABRIC_INGRESS_ACL_SET_CLONE_SESSION_ID)
+ .withParameter(new PiActionParam(
+ FabricConstants.CLONE_ID, CLONE_TO_CPU_ID))
+ .build();
+ }
+ final TrafficTreatment piTreatment = DefaultTrafficTreatment.builder()
+ .piTableAction(aclAction)
+ .build();
+ resultBuilder.addFlowRule(flowRule(
+ obj, FabricConstants.FABRIC_INGRESS_ACL_ACL, obj.selector(), piTreatment));
+ return;
+ }
+ }
resultBuilder.addFlowRule(flowRule(
obj, FabricConstants.FABRIC_INGRESS_ACL_ACL, obj.selector()));
}
+ private DefaultGroupDescription createCloneGroup(
+ ApplicationId appId,
+ int cloneSessionId,
+ PortNumber outPort) {
+ final GroupKey groupKey = new DefaultGroupKey(
+ FabricPipeliner.KRYO.serialize(cloneSessionId));
+
+ final List<GroupBucket> bucketList = ImmutableList.of(
+ createCloneGroupBucket(DefaultTrafficTreatment.builder()
+ .setOutput(outPort)
+ .build()));
+ final DefaultGroupDescription cloneGroup = new DefaultGroupDescription(
+ deviceId, GroupDescription.Type.CLONE,
+ new GroupBuckets(bucketList),
+ groupKey, cloneSessionId, appId);
+ return cloneGroup;
+ }
+
private FlowRule flowRule(
ForwardingObjective obj, PiTableId tableId, TrafficSelector selector)
throws FabricPipelinerException {
diff --git a/pipelines/fabric/src/main/java/org/onosproject/pipelines/fabric/pipeliner/NextObjectiveTranslator.java b/pipelines/fabric/src/main/java/org/onosproject/pipelines/fabric/pipeliner/NextObjectiveTranslator.java
index 2c2fd77..ec1c64b 100644
--- a/pipelines/fabric/src/main/java/org/onosproject/pipelines/fabric/pipeliner/NextObjectiveTranslator.java
+++ b/pipelines/fabric/src/main/java/org/onosproject/pipelines/fabric/pipeliner/NextObjectiveTranslator.java
@@ -436,15 +436,6 @@
.map(p -> DefaultTrafficTreatment.builder().setOutput(p).build())
.map(DefaultGroupBucket::createAllGroupBucket)
.collect(Collectors.toList());
- // FIXME: remove once support for clone sessions is available
- // Right now we add a CPU port to all multicast groups. The egress
- // pipeline is expected to drop replicated packets to the CPU if a clone
- // was not requested in the ingress pipeline.
- bucketList.add(
- DefaultGroupBucket.createAllGroupBucket(
- DefaultTrafficTreatment.builder()
- .setOutput(PortNumber.CONTROLLER)
- .build()));
final int groupId = obj.id();
// Use DefaultGroupKey instead of PiGroupKey as we don't have any