[ONOS-7242] Support MPLS by fabric.p4 pipeliner
Change-Id: I56a8f266e6d0afe5ad6737b8d0e399758fb75378
diff --git a/pipelines/fabric/src/test/java/org/onosproject/pipelines/fabric/FabricInterpreterTest.java b/pipelines/fabric/src/test/java/org/onosproject/pipelines/fabric/FabricInterpreterTest.java
index 76bd030..fdda55f 100644
--- a/pipelines/fabric/src/test/java/org/onosproject/pipelines/fabric/FabricInterpreterTest.java
+++ b/pipelines/fabric/src/test/java/org/onosproject/pipelines/fabric/FabricInterpreterTest.java
@@ -20,6 +20,7 @@
import org.junit.Before;
import org.junit.Test;
import org.onlab.packet.MacAddress;
+import org.onlab.packet.MplsLabel;
import org.onlab.packet.VlanId;
import org.onlab.util.ImmutableByteSequence;
import org.onosproject.net.PortNumber;
@@ -38,6 +39,7 @@
private static final PortNumber PORT_1 = PortNumber.portNumber(1);
private static final MacAddress SRC_MAC = MacAddress.valueOf("00:00:00:00:00:01");
private static final MacAddress DST_MAC = MacAddress.valueOf("00:00:00:00:00:02");
+ private static final MplsLabel MPLS_10 = MplsLabel.mplsLabel(10);
private FabricInterpreter interpreter;
@@ -198,4 +200,33 @@
assertEquals(expectedAction, mappedAction);
}
+
+ @Test
+ public void testMplsRoutingTreatment() throws Exception {
+ TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+ .setEthDst(DST_MAC)
+ .setEthSrc(SRC_MAC)
+ .pushMpls()
+ .copyTtlOut()
+ .setMpls(MPLS_10)
+ .setOutput(PORT_1)
+ .build();
+ PiAction mappedAction = interpreter.mapTreatment(treatment,
+ FabricConstants.TBL_HASHED_ID);
+ short portNumVal = (short) PORT_1.toLong();
+ PiActionParam ethSrcParam = new PiActionParam(FabricConstants.ACT_PRM_SMAC_ID,
+ ImmutableByteSequence.copyFrom(SRC_MAC.toBytes()));
+ PiActionParam ethDstParam = new PiActionParam(FabricConstants.ACT_PRM_DMAC_ID,
+ ImmutableByteSequence.copyFrom(DST_MAC.toBytes()));
+ PiActionParam portParam = new PiActionParam(FabricConstants.ACT_PRM_PORT_NUM_ID,
+ ImmutableByteSequence.copyFrom(portNumVal));
+ ImmutableByteSequence mplsVal =
+ ImmutableByteSequence.fit(ImmutableByteSequence.copyFrom(MPLS_10.toInt()), 20);
+ PiActionParam mplsParam = new PiActionParam(FabricConstants.ACT_PRM_LABEL_ID, mplsVal);
+ PiAction expectedAction = PiAction.builder()
+ .withId(FabricConstants.ACT_MPLS_ROUTING_V4_ID)
+ .withParameters(ImmutableList.of(ethSrcParam, ethDstParam, portParam, mplsParam))
+ .build();
+ assertEquals(expectedAction, mappedAction);
+ }
}
diff --git a/pipelines/fabric/src/test/java/org/onosproject/pipelines/fabric/pipeliner/FabricForwardingPipelineTest.java b/pipelines/fabric/src/test/java/org/onosproject/pipelines/fabric/pipeliner/FabricForwardingPipelineTest.java
index 0332e63..1602c58 100644
--- a/pipelines/fabric/src/test/java/org/onosproject/pipelines/fabric/pipeliner/FabricForwardingPipelineTest.java
+++ b/pipelines/fabric/src/test/java/org/onosproject/pipelines/fabric/pipeliner/FabricForwardingPipelineTest.java
@@ -210,13 +210,46 @@
}
@Test
- @Ignore
public void testMpls() {
+ TrafficSelector selector = DefaultTrafficSelector.builder()
+ .matchEthType(Ethernet.MPLS_UNICAST)
+ .matchMplsLabel(MPLS_10)
+ .matchMplsBos(true)
+ .build();
+ TrafficSelector expectedSelector = DefaultTrafficSelector.builder()
+ .matchMplsLabel(MPLS_10)
+ .build();
+ PiActionParam nextIdParam = new PiActionParam(FabricConstants.ACT_PRM_NEXT_ID_ID,
+ ImmutableByteSequence.copyFrom(NEXT_ID_1.byteValue()));
+ PiAction setNextIdAction = PiAction.builder()
+ .withId(FabricConstants.ACT_POP_MPLS_AND_NEXT_ID)
+ .withParameter(nextIdParam)
+ .build();
+ TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+ .piTableAction(setNextIdAction)
+ .build();
+ testSpecificForward(FabricConstants.TBL_MPLS_ID, expectedSelector, selector, NEXT_ID_1, treatment);
}
private void testSpecificForward(PiTableId expectedTableId, TrafficSelector expectedSelector,
TrafficSelector selector, Integer nextId) {
+ PiActionParam nextIdParam = new PiActionParam(FabricConstants.ACT_PRM_NEXT_ID_ID,
+ ImmutableByteSequence.copyFrom(nextId.byteValue()));
+ PiAction setNextIdAction = PiAction.builder()
+ .withId(FabricConstants.ACT_SET_NEXT_ID_ID)
+ .withParameter(nextIdParam)
+ .build();
+ TrafficTreatment setNextIdTreatment = DefaultTrafficTreatment.builder()
+ .piTableAction(setNextIdAction)
+ .build();
+
+ testSpecificForward(expectedTableId, expectedSelector, selector, nextId, setNextIdTreatment);
+
+ }
+
+ private void testSpecificForward(PiTableId expectedTableId, TrafficSelector expectedSelector,
+ TrafficSelector selector, Integer nextId, TrafficTreatment treatment) {
ForwardingObjective fwd = DefaultForwardingObjective.builder()
.withSelector(selector)
.withPriority(PRIORITY)
@@ -234,15 +267,6 @@
assertTrue(groupsInstalled.isEmpty());
FlowRule actualFlowRule = flowRulesInstalled.get(0);
- PiActionParam nextIdParam = new PiActionParam(FabricConstants.ACT_PRM_NEXT_ID_ID,
- ImmutableByteSequence.copyFrom(nextId.byteValue()));
- PiAction setNextIdAction = PiAction.builder()
- .withId(FabricConstants.ACT_SET_NEXT_ID_ID)
- .withParameter(nextIdParam)
- .build();
- TrafficTreatment setNextIdTreatment = DefaultTrafficTreatment.builder()
- .piTableAction(setNextIdAction)
- .build();
FlowRule expectedFlowRule = DefaultFlowRule.builder()
.forDevice(DEVICE_ID)
@@ -250,7 +274,7 @@
.withPriority(PRIORITY)
.makePermanent()
.withSelector(expectedSelector)
- .withTreatment(setNextIdTreatment)
+ .withTreatment(treatment)
.fromApp(APP_ID)
.build();
diff --git a/pipelines/fabric/src/test/java/org/onosproject/pipelines/fabric/pipeliner/FabricNextPipelinerTest.java b/pipelines/fabric/src/test/java/org/onosproject/pipelines/fabric/pipeliner/FabricNextPipelinerTest.java
index 3fe196b..8493ca6 100644
--- a/pipelines/fabric/src/test/java/org/onosproject/pipelines/fabric/pipeliner/FabricNextPipelinerTest.java
+++ b/pipelines/fabric/src/test/java/org/onosproject/pipelines/fabric/pipeliner/FabricNextPipelinerTest.java
@@ -16,6 +16,7 @@
package org.onosproject.pipelines.fabric.pipeliner;
+import com.google.common.collect.ImmutableList;
import org.junit.Ignore;
import org.junit.Test;
import org.onlab.util.ImmutableByteSequence;
@@ -28,15 +29,24 @@
import org.onosproject.net.flow.criteria.PiCriterion;
import org.onosproject.net.flowobjective.DefaultNextObjective;
import org.onosproject.net.flowobjective.NextObjective;
+import org.onosproject.net.group.DefaultGroupBucket;
+import org.onosproject.net.group.DefaultGroupDescription;
+import org.onosproject.net.group.GroupBucket;
+import org.onosproject.net.group.GroupBuckets;
import org.onosproject.net.group.GroupDescription;
import org.onosproject.net.pi.runtime.PiAction;
+import org.onosproject.net.pi.runtime.PiActionGroupId;
import org.onosproject.net.pi.runtime.PiActionParam;
+import org.onosproject.net.pi.runtime.PiGroupKey;
import org.onosproject.pipelines.fabric.FabricConstants;
import java.util.List;
+import java.util.stream.Collectors;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
+import static org.onosproject.pipelines.fabric.FabricConstants.ACT_PRF_ECMP_SELECTOR_ID;
+import static org.onosproject.pipelines.fabric.FabricConstants.TBL_HASHED_ID;
/**
* Test cases for fabric.p4 pipeline next control block.
@@ -96,20 +106,39 @@
assertEquals(2, flowRulesInstalled.size());
assertTrue(groupsInstalled.isEmpty());
- FlowRule actualFlowRule;
- FlowRule expectedFlowRule;
+ verifyNextIdMapping(flowRulesInstalled.get(0), NEXT_TYPE_SIMPLE);
- // Next id mapping table
- actualFlowRule = flowRulesInstalled.get(0);
- byte[] nextIdVal = new byte[]{NEXT_ID_1.byteValue()};
+ // Simple table
PiCriterion nextIdCriterion = PiCriterion.builder()
- .matchExact(FabricConstants.HF_FABRIC_METADATA_NEXT_ID_ID, nextIdVal)
+ .matchExact(FabricConstants.HF_FABRIC_METADATA_NEXT_ID_ID, NEXT_ID_1)
+ .build();
+ TrafficSelector nextIdSelector = DefaultTrafficSelector.builder()
+ .matchPi(nextIdCriterion)
+ .build();
+ FlowRule actualFlowRule = flowRulesInstalled.get(1);
+ FlowRule expectedFlowRule = DefaultFlowRule.builder()
+ .forDevice(DEVICE_ID)
+ .fromApp(APP_ID)
+ .makePermanent()
+ // FIXME: currently next objective doesn't support priority, ignore this
+ .withPriority(0)
+ .forTable(FabricConstants.TBL_SIMPLE_ID)
+ .withSelector(nextIdSelector)
+ .withTreatment(treatment)
+ .build();
+ assertTrue(expectedFlowRule.exactMatch(actualFlowRule));
+ }
+
+ private void verifyNextIdMapping(FlowRule flowRule, byte nextType) {
+ FlowRule expectedFlowRule;
+ PiCriterion nextIdCriterion = PiCriterion.builder()
+ .matchExact(FabricConstants.HF_FABRIC_METADATA_NEXT_ID_ID, NEXT_ID_1)
.build();
TrafficSelector nextIdSelector = DefaultTrafficSelector.builder()
.matchPi(nextIdCriterion)
.build();
PiActionParam setNextToSimpleParam = new PiActionParam(FabricConstants.ACT_PRM_NEXT_TYPE_ID,
- ImmutableByteSequence.copyFrom(NEXT_TYPE_SIMPLE));
+ ImmutableByteSequence.copyFrom(nextType));
PiAction setNextToSimpleAction = PiAction.builder()
.withId(FabricConstants.ACT_SET_NEXT_TYPE_ID)
.withParameter(setNextToSimpleParam)
@@ -127,29 +156,87 @@
.withSelector(nextIdSelector)
.withTreatment(setNextTypeTreatment)
.build();
- assertTrue(expectedFlowRule.exactMatch(actualFlowRule));
-
- // Simple table
- actualFlowRule = flowRulesInstalled.get(1);
- expectedFlowRule = DefaultFlowRule.builder()
- .forDevice(DEVICE_ID)
- .fromApp(APP_ID)
- .makePermanent()
- // FIXME: currently next objective doesn't support priority, ignore this
- .withPriority(0)
- .forTable(FabricConstants.TBL_SIMPLE_ID)
- .withSelector(nextIdSelector)
- .withTreatment(treatment)
- .build();
- assertTrue(expectedFlowRule.exactMatch(actualFlowRule));
+ assertTrue(expectedFlowRule.exactMatch(flowRule));
}
/**
* Test program ecmp output group for Hashed table.
*/
@Test
- @Ignore
- public void testHashedOutput() {
+ public void testHashedOutput() throws Exception {
+ TrafficTreatment treatment1 = DefaultTrafficTreatment.builder()
+ .setEthSrc(ROUTER_MAC)
+ .setEthDst(HOST_MAC)
+ .setOutput(PORT_1)
+ .build();
+ TrafficTreatment treatment2 = DefaultTrafficTreatment.builder()
+ .setEthSrc(ROUTER_MAC)
+ .setEthDst(HOST_MAC)
+ .setOutput(PORT_2)
+ .build();
+
+ NextObjective nextObjective = DefaultNextObjective.builder()
+ .withId(NEXT_ID_1)
+ .withPriority(PRIORITY)
+ .addTreatment(treatment1)
+ .addTreatment(treatment2)
+ .withType(NextObjective.Type.HASHED)
+ .makePermanent()
+ .fromApp(APP_ID)
+ .add();
+
+ PipelinerTranslationResult result = pipeliner.pipelinerNext.next(nextObjective);
+
+ // Should generates 2 flows and 1 group
+ List<FlowRule> flowRulesInstalled = (List<FlowRule>) result.flowRules();
+ List<GroupDescription> groupsInstalled = (List<GroupDescription>) result.groups();
+ assertEquals(2, flowRulesInstalled.size());
+ assertEquals(1, groupsInstalled.size());
+
+ verifyNextIdMapping(flowRulesInstalled.get(0), NEXT_TYPE_HASHED);
+
+ // Hashed table
+ PiCriterion nextIdCriterion = PiCriterion.builder()
+ .matchExact(FabricConstants.HF_FABRIC_METADATA_NEXT_ID_ID, NEXT_ID_1)
+ .build();
+ TrafficSelector nextIdSelector = DefaultTrafficSelector.builder()
+ .matchPi(nextIdCriterion)
+ .build();
+ PiActionGroupId actionGroupId = PiActionGroupId.of(NEXT_ID_1);
+ TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+ .piTableAction(actionGroupId)
+ .build();
+ FlowRule actualFlowRule = flowRulesInstalled.get(1);
+ FlowRule expectedFlowRule = DefaultFlowRule.builder()
+ .forDevice(DEVICE_ID)
+ .fromApp(APP_ID)
+ .makePermanent()
+ // FIXME: currently next objective doesn't support priority, ignore this
+ .withPriority(0)
+ .forTable(TBL_HASHED_ID)
+ .withSelector(nextIdSelector)
+ .withTreatment(treatment)
+ .build();
+ assertTrue(expectedFlowRule.exactMatch(actualFlowRule));
+
+ // Group
+ GroupDescription actualGroup = groupsInstalled.get(0);
+ List<TrafficTreatment> treatments = ImmutableList.of(treatment1, treatment2);
+
+ List<GroupBucket> buckets = treatments.stream()
+ .map(DefaultGroupBucket::createSelectGroupBucket)
+ .collect(Collectors.toList());
+ GroupBuckets groupBuckets = new GroupBuckets(buckets);
+ PiGroupKey groupKey = new PiGroupKey(TBL_HASHED_ID, ACT_PRF_ECMP_SELECTOR_ID, NEXT_ID_1);
+ GroupDescription expectedGroup = new DefaultGroupDescription(
+ DEVICE_ID,
+ GroupDescription.Type.SELECT,
+ groupBuckets,
+ groupKey,
+ NEXT_ID_1,
+ APP_ID
+ );
+ assertEquals(expectedGroup, actualGroup);
}
diff --git a/pipelines/fabric/src/test/java/org/onosproject/pipelines/fabric/pipeliner/FabricPipelinerTest.java b/pipelines/fabric/src/test/java/org/onosproject/pipelines/fabric/pipeliner/FabricPipelinerTest.java
index 30610ed..fb92bf9 100644
--- a/pipelines/fabric/src/test/java/org/onosproject/pipelines/fabric/pipeliner/FabricPipelinerTest.java
+++ b/pipelines/fabric/src/test/java/org/onosproject/pipelines/fabric/pipeliner/FabricPipelinerTest.java
@@ -29,6 +29,7 @@
import org.onosproject.net.behaviour.PipelinerContext;
import org.onosproject.net.flow.criteria.PiCriterion;
import org.onosproject.pipelines.fabric.FabricConstants;
+import org.onosproject.pipelines.fabric.FabricInterpreter;
import static org.easymock.EasyMock.createNiceMock;
import static org.easymock.EasyMock.expect;
@@ -39,6 +40,7 @@
static final DeviceId DEVICE_ID = DeviceId.deviceId("device:bmv2:11");
static final int PRIORITY = 100;
static final PortNumber PORT_1 = PortNumber.portNumber(1);
+ static final PortNumber PORT_2 = PortNumber.portNumber(2);
static final VlanId VLAN_100 = VlanId.vlanId("100");
static final MacAddress HOST_MAC = MacAddress.valueOf("00:00:00:00:00:01");
static final MacAddress ROUTER_MAC = MacAddress.valueOf("00:00:00:00:02:01");
@@ -71,6 +73,7 @@
.build();
FabricPipeliner pipeliner;
+ FabricInterpreter interpreter;
@Before
public void setup() {
@@ -82,5 +85,6 @@
replay(serviceDirectory, pipelinerContext);
pipeliner.init(DEVICE_ID, pipelinerContext);
+ interpreter = new FabricInterpreter();
}
}
diff --git a/pipelines/fabric/src/test/java/org/onosproject/pipelines/fabric/pipeliner/ForwardingFunctionTypeTest.java b/pipelines/fabric/src/test/java/org/onosproject/pipelines/fabric/pipeliner/ForwardingFunctionTypeTest.java
index 44ec9bc..5e77906 100644
--- a/pipelines/fabric/src/test/java/org/onosproject/pipelines/fabric/pipeliner/ForwardingFunctionTypeTest.java
+++ b/pipelines/fabric/src/test/java/org/onosproject/pipelines/fabric/pipeliner/ForwardingFunctionTypeTest.java
@@ -106,7 +106,6 @@
}
@Test
- @Ignore
public void testMplsUnicast() {
selector = DefaultTrafficSelector.builder()
.matchEthType(Ethernet.MPLS_UNICAST)