Skip to content

Commit f51d0c1

Browse files
committed
Support in fabric pipeliner for pushing double VLAN tag in Next obj
- Small modification to better support pop and route - To support route and push we expect to receive a Next Objective with two VLAN_ID - Added capability to check if the pipeline support double VLAN termination Change-Id: I8bfbf61ccd838a069121e5ab4a804f695a446bac
1 parent 9a49968 commit f51d0c1

File tree

13 files changed

+343
-40
lines changed

13 files changed

+343
-40
lines changed

pipelines/fabric/src/main/java/org/onosproject/pipelines/fabric/AbstractFabricHandlerBehavior.java

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,21 +30,48 @@
3030
/**
3131
* Abstract implementation of HandlerBehaviour for the fabric pipeconf
3232
* behaviors.
33+
* <p>
34+
* All sub-classes must implement a default constructor, used by the abstract
35+
* projectable model (i.e., {@link org.onosproject.net.Device#as(Class)}.
3336
*/
34-
public class AbstractFabricHandlerBehavior extends AbstractHandlerBehaviour {
37+
public abstract class AbstractFabricHandlerBehavior extends AbstractHandlerBehaviour {
3538

3639
protected final Logger log = getLogger(getClass());
3740

3841
protected FabricCapabilities capabilities;
3942

43+
/**
44+
* Creates a new instance of this behavior with the given capabilities.
45+
* Note: this constructor should be invoked only by other classes of this
46+
* package that can retrieve capabilities on their own.
47+
* <p>
48+
* When using the abstract projectable model (i.e., {@link
49+
* org.onosproject.net.Device#as(Class)}, capabilities will be set by the
50+
* driver manager when calling {@link #setHandler(DriverHandler)})
51+
*
52+
* @param capabilities capabilities
53+
*/
54+
protected AbstractFabricHandlerBehavior(FabricCapabilities capabilities) {
55+
this.capabilities = capabilities;
56+
}
57+
58+
/**
59+
* Create a new instance of this behaviour. Used by the abstract projectable
60+
* model (i.e., {@link org.onosproject.net.Device#as(Class)}.
61+
*/
62+
public AbstractFabricHandlerBehavior() {
63+
// Do nothing
64+
}
65+
4066
@Override
4167
public void setHandler(DriverHandler handler) {
4268
super.setHandler(handler);
4369
final PiPipeconfService pipeconfService = handler().get(PiPipeconfService.class);
44-
setCapabilities(handler().data().deviceId(), pipeconfService);
70+
setCapabilitiesFromHandler(handler().data().deviceId(), pipeconfService);
4571
}
4672

47-
private void setCapabilities(DeviceId deviceId, PiPipeconfService pipeconfService) {
73+
private void setCapabilitiesFromHandler(
74+
DeviceId deviceId, PiPipeconfService pipeconfService) {
4875
checkNotNull(deviceId);
4976
checkNotNull(pipeconfService);
5077
// Get pipeconf capabilities.

pipelines/fabric/src/main/java/org/onosproject/pipelines/fabric/FabricCapabilities.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,4 +76,14 @@ public Optional<Integer> cpuPort() {
7676
return Optional.empty();
7777
}
7878
}
79+
80+
public boolean supportDoubleVlanTerm() {
81+
if (pipeconf.pipelineModel()
82+
.table(FabricConstants.FABRIC_INGRESS_NEXT_NEXT_VLAN).isPresent()) {
83+
return pipeconf.pipelineModel().table(FabricConstants.FABRIC_INGRESS_NEXT_NEXT_VLAN)
84+
.get().action(FabricConstants.FABRIC_INGRESS_NEXT_SET_DOUBLE_VLAN)
85+
.isPresent();
86+
}
87+
return false;
88+
}
7989
}

pipelines/fabric/src/main/java/org/onosproject/pipelines/fabric/FabricIntProgrammable.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,23 @@ public class FabricIntProgrammable extends AbstractFabricHandlerBehavior
8686
private DeviceId deviceId;
8787
private ApplicationId appId;
8888

89+
/**
90+
* Creates a new instance of this behavior with the given capabilities.
91+
*
92+
* @param capabilities capabilities
93+
*/
94+
protected FabricIntProgrammable(FabricCapabilities capabilities) {
95+
super(capabilities);
96+
}
97+
98+
/**
99+
* Create a new instance of this behaviour. Used by the abstract projectable
100+
* model (i.e., {@link org.onosproject.net.Device#as(Class)}.
101+
*/
102+
public FabricIntProgrammable() {
103+
super();
104+
}
105+
89106
private boolean setupBehaviour() {
90107
deviceId = this.data().deviceId();
91108
flowRuleService = handler().get(FlowRuleService.class);

pipelines/fabric/src/main/java/org/onosproject/pipelines/fabric/FabricInterpreter.java

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import org.onosproject.net.Port;
2828
import org.onosproject.net.PortNumber;
2929
import org.onosproject.net.device.DeviceService;
30+
import org.onosproject.net.driver.DriverHandler;
3031
import org.onosproject.net.flow.TrafficTreatment;
3132
import org.onosproject.net.flow.criteria.Criterion;
3233
import org.onosproject.net.flow.instructions.Instructions;
@@ -116,6 +117,36 @@ public class FabricInterpreter extends AbstractFabricHandlerBehavior
116117
.put(FabricConstants.FABRIC_INGRESS_FORWARDING_ROUTING_V4, NOP)
117118
.build();
118119

120+
private FabricTreatmentInterpreter treatmentInterpreter;
121+
122+
/**
123+
* Creates a new instance of this behavior with the given capabilities.
124+
*
125+
* @param capabilities capabilities
126+
*/
127+
public FabricInterpreter(FabricCapabilities capabilities) {
128+
super(capabilities);
129+
instantiateTreatmentInterpreter();
130+
}
131+
132+
/**
133+
* Create a new instance of this behaviour. Used by the abstract projectable
134+
* model (i.e., {@link org.onosproject.net.Device#as(Class)}.
135+
*/
136+
public FabricInterpreter() {
137+
super();
138+
}
139+
140+
private void instantiateTreatmentInterpreter() {
141+
this.treatmentInterpreter = new FabricTreatmentInterpreter(this.capabilities);
142+
}
143+
144+
@Override
145+
public void setHandler(DriverHandler handler) {
146+
super.setHandler(handler);
147+
instantiateTreatmentInterpreter();
148+
}
149+
119150
@Override
120151
public Optional<PiMatchFieldId> mapCriterionType(Criterion.Type type) {
121152
return Optional.ofNullable(CRITERION_MAP.get(type));
@@ -132,15 +163,15 @@ public Optional<PiTableId> mapFlowRuleTableId(int flowRuleTableId) {
132163
public PiAction mapTreatment(TrafficTreatment treatment, PiTableId piTableId)
133164
throws PiInterpreterException {
134165
if (FILTERING_CTRL_TBLS.contains(piTableId)) {
135-
return FabricTreatmentInterpreter.mapFilteringTreatment(treatment, piTableId);
166+
return treatmentInterpreter.mapFilteringTreatment(treatment, piTableId);
136167
} else if (FORWARDING_CTRL_TBLS.contains(piTableId)) {
137-
return FabricTreatmentInterpreter.mapForwardingTreatment(treatment, piTableId);
168+
return treatmentInterpreter.mapForwardingTreatment(treatment, piTableId);
138169
} else if (ACL_CTRL_TBLS.contains(piTableId)) {
139-
return FabricTreatmentInterpreter.mapAclTreatment(treatment, piTableId);
170+
return treatmentInterpreter.mapAclTreatment(treatment, piTableId);
140171
} else if (NEXT_CTRL_TBLS.contains(piTableId)) {
141-
return FabricTreatmentInterpreter.mapNextTreatment(treatment, piTableId);
172+
return treatmentInterpreter.mapNextTreatment(treatment, piTableId);
142173
} else if (E_NEXT_CTRL_TBLS.contains(piTableId)) {
143-
return FabricTreatmentInterpreter.mapEgressNextTreatment(treatment, piTableId);
174+
return treatmentInterpreter.mapEgressNextTreatment(treatment, piTableId);
144175
} else {
145176
throw new PiInterpreterException(format(
146177
"Treatment mapping not supported for table '%s'", piTableId));

pipelines/fabric/src/main/java/org/onosproject/pipelines/fabric/FabricTreatmentInterpreter.java

Lines changed: 48 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@
3232
import org.onosproject.net.pi.runtime.PiAction;
3333
import org.onosproject.net.pi.runtime.PiActionParam;
3434

35+
import java.util.List;
36+
import java.util.stream.Collectors;
37+
3538
import static java.lang.String.format;
3639
import static org.onosproject.net.flow.instructions.Instruction.Type.OUTPUT;
3740
import static org.onosproject.net.flow.instructions.L2ModificationInstruction.L2SubType.ETH_DST;
@@ -42,12 +45,14 @@
4245
import static org.onosproject.net.flow.instructions.L2ModificationInstruction.L2SubType.VLAN_POP;
4346
import static org.onosproject.pipelines.fabric.FabricUtils.instruction;
4447
import static org.onosproject.pipelines.fabric.FabricUtils.l2Instruction;
48+
import static org.onosproject.pipelines.fabric.FabricUtils.l2Instructions;
4549

4650
/**
4751
* Treatment translation logic.
4852
*/
4953
final class FabricTreatmentInterpreter {
5054

55+
private final FabricCapabilities capabilities;
5156
private static final ImmutableMap<PiTableId, PiActionId> NOP_ACTIONS =
5257
ImmutableMap.<PiTableId, PiActionId>builder()
5358
.put(FabricConstants.FABRIC_INGRESS_FILTERING_INGRESS_PORT_VLAN,
@@ -60,8 +65,9 @@ final class FabricTreatmentInterpreter {
6065
FabricConstants.FABRIC_EGRESS_EGRESS_NEXT_POP_VLAN)
6166
.build();
6267

63-
private FabricTreatmentInterpreter() {
64-
// Hide default constructor
68+
69+
FabricTreatmentInterpreter(FabricCapabilities capabilities) {
70+
this.capabilities = capabilities;
6571
}
6672

6773
static PiAction mapFilteringTreatment(TrafficTreatment treatment, PiTableId tableId)
@@ -73,7 +79,8 @@ static PiAction mapFilteringTreatment(TrafficTreatment treatment, PiTableId tabl
7379
tableException(tableId);
7480
}
7581

76-
if (isNoAction(treatment)) {
82+
// VLAN_POP action is equivalent to the permit action (VLANs pop is done anyway)
83+
if (isNoAction(treatment) || isFilteringPopAction(treatment)) {
7784
// Permit action if table is ingress_port_vlan;
7885
return nop(tableId);
7986
}
@@ -99,7 +106,7 @@ static PiAction mapForwardingTreatment(TrafficTreatment treatment, PiTableId tab
99106
return null;
100107
}
101108

102-
static PiAction mapNextTreatment(TrafficTreatment treatment, PiTableId tableId)
109+
PiAction mapNextTreatment(TrafficTreatment treatment, PiTableId tableId)
103110
throws PiInterpreterException {
104111
if (tableId == FabricConstants.FABRIC_INGRESS_NEXT_NEXT_VLAN) {
105112
return mapNextVlanTreatment(treatment, tableId);
@@ -114,16 +121,29 @@ static PiAction mapNextTreatment(TrafficTreatment treatment, PiTableId tableId)
114121
"Treatment mapping not supported for table '%s'", tableId));
115122
}
116123

117-
private static PiAction mapNextVlanTreatment(TrafficTreatment treatment, PiTableId tableId)
124+
private PiAction mapNextVlanTreatment(TrafficTreatment treatment, PiTableId tableId)
118125
throws PiInterpreterException {
119-
final ModVlanIdInstruction modVlanIdInst = (ModVlanIdInstruction)
120-
l2InstructionOrFail(treatment, VLAN_ID, tableId);
121-
return PiAction.builder()
122-
.withId(FabricConstants.FABRIC_INGRESS_NEXT_SET_VLAN)
123-
.withParameter(new PiActionParam(
124-
FabricConstants.VLAN_ID,
125-
modVlanIdInst.vlanId().toShort()))
126-
.build();
126+
final List<ModVlanIdInstruction> modVlanIdInst = l2InstructionsOrFail(treatment, VLAN_ID, tableId)
127+
.stream().map(i -> (ModVlanIdInstruction) i).collect(Collectors.toList());
128+
if (modVlanIdInst.size() == 1) {
129+
return PiAction.builder().withId(FabricConstants.FABRIC_INGRESS_NEXT_SET_VLAN)
130+
.withParameter(new PiActionParam(
131+
FabricConstants.VLAN_ID,
132+
modVlanIdInst.get(0).vlanId().toShort()))
133+
.build();
134+
}
135+
if (modVlanIdInst.size() == 2 && capabilities.supportDoubleVlanTerm()) {
136+
return PiAction.builder()
137+
.withId(FabricConstants.FABRIC_INGRESS_NEXT_SET_DOUBLE_VLAN)
138+
.withParameter(new PiActionParam(
139+
FabricConstants.INNER_VLAN_ID,
140+
modVlanIdInst.get(0).vlanId().toShort()))
141+
.withParameter(new PiActionParam(
142+
FabricConstants.OUTER_VLAN_ID,
143+
modVlanIdInst.get(1).vlanId().toShort()))
144+
.build();
145+
}
146+
throw new PiInterpreterException("Too many VLAN instructions");
127147
}
128148

129149
private static PiAction mapNextHashedOrSimpleTreatment(
@@ -223,6 +243,10 @@ private static boolean isNoAction(TrafficTreatment treatment) {
223243
treatment.allInstructions().isEmpty();
224244
}
225245

246+
private static boolean isFilteringPopAction(TrafficTreatment treatment) {
247+
return l2Instruction(treatment, VLAN_POP) != null;
248+
}
249+
226250
private static Instruction l2InstructionOrFail(
227251
TrafficTreatment treatment,
228252
L2ModificationInstruction.L2SubType subType, PiTableId tableId)
@@ -234,6 +258,17 @@ private static Instruction l2InstructionOrFail(
234258
return inst;
235259
}
236260

261+
private static List<L2ModificationInstruction> l2InstructionsOrFail(
262+
TrafficTreatment treatment,
263+
L2ModificationInstruction.L2SubType subType, PiTableId tableId)
264+
throws PiInterpreterException {
265+
final List<L2ModificationInstruction> inst = l2Instructions(treatment, subType);
266+
if (inst == null || inst.isEmpty()) {
267+
treatmentException(tableId, treatment, format("missing %s instruction", subType));
268+
}
269+
return inst;
270+
}
271+
237272
private static Instruction instructionOrFail(
238273
TrafficTreatment treatment, Instruction.Type type, PiTableId tableId)
239274
throws PiInterpreterException {

pipelines/fabric/src/main/java/org/onosproject/pipelines/fabric/FabricUtils.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
import org.onosproject.net.flowobjective.NextTreatment;
2828

2929
import java.util.Collection;
30+
import java.util.List;
31+
import java.util.stream.Collectors;
3032

3133
import static com.google.common.base.Preconditions.checkNotNull;
3234
import static java.lang.String.format;
@@ -77,6 +79,15 @@ public static L2ModificationInstruction l2Instruction(
7779
.findFirst().orElse(null);
7880
}
7981

82+
public static List<L2ModificationInstruction> l2Instructions(
83+
TrafficTreatment treatment, L2ModificationInstruction.L2SubType subType) {
84+
return treatment.allInstructions().stream()
85+
.filter(i -> i.type().equals(Instruction.Type.L2MODIFICATION))
86+
.map(i -> (L2ModificationInstruction) i)
87+
.filter(i -> i.subtype().equals(subType))
88+
.collect(Collectors.toList());
89+
}
90+
8091
public static Instructions.OutputInstruction outputInstruction(TrafficTreatment treatment) {
8192
return instruction(treatment, Instruction.Type.OUTPUT);
8293
}

pipelines/fabric/src/main/java/org/onosproject/pipelines/fabric/pipeliner/AbstractObjectiveTranslator.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,12 @@ abstract class AbstractObjectiveTranslator<T extends Objective> {
4646
protected final FabricCapabilities capabilities;
4747
protected final DeviceId deviceId;
4848

49-
private final PiPipelineInterpreter interpreter = new FabricInterpreter();
49+
private final PiPipelineInterpreter interpreter;
5050

5151
AbstractObjectiveTranslator(DeviceId deviceId, FabricCapabilities capabilities) {
5252
this.deviceId = checkNotNull(deviceId);
5353
this.capabilities = checkNotNull(capabilities);
54+
this.interpreter = new FabricInterpreter(capabilities);
5455
}
5556

5657
public ObjectiveTranslation translate(T obj) {

pipelines/fabric/src/main/java/org/onosproject/pipelines/fabric/pipeliner/FabricPipeliner.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import org.onosproject.net.group.GroupDescription;
3939
import org.onosproject.net.group.GroupService;
4040
import org.onosproject.pipelines.fabric.AbstractFabricHandlerBehavior;
41+
import org.onosproject.pipelines.fabric.FabricCapabilities;
4142
import org.onosproject.store.serializers.KryoNamespaces;
4243
import org.slf4j.Logger;
4344

@@ -78,6 +79,23 @@ public class FabricPipeliner extends AbstractFabricHandlerBehavior
7879

7980
private final ExecutorService callbackExecutor = SharedExecutors.getPoolThreadExecutor();
8081

82+
/**
83+
* Creates a new instance of this behavior with the given capabilities.
84+
*
85+
* @param capabilities capabilities
86+
*/
87+
public FabricPipeliner(FabricCapabilities capabilities) {
88+
super(capabilities);
89+
}
90+
91+
/**
92+
* Create a new instance of this behaviour. Used by the abstract projectable
93+
* model (i.e., {@link org.onosproject.net.Device#as(Class)}.
94+
*/
95+
public FabricPipeliner() {
96+
super();
97+
}
98+
8199
@Override
82100
public void init(DeviceId deviceId, PipelinerContext context) {
83101
this.deviceId = deviceId;

0 commit comments

Comments
 (0)