ONOS-7402 Broadcast objective type support by FabricNextPipeliner.

Change-Id: I08b544a82e257091a079648c07b1dc6fb72c9ab9
This commit is contained in:
Esin Karaman 2018-01-26 11:52:28 +00:00 committed by Carmelo Cascone
parent ba4b5ec3c5
commit 24fda8acfd
2 changed files with 177 additions and 2 deletions

View File

@ -17,6 +17,7 @@
package org.onosproject.pipelines.fabric.pipeliner;
import org.onlab.packet.VlanId;
import org.onlab.util.ImmutableByteSequence;
import org.onosproject.net.DeviceId;
import org.onosproject.net.PortNumber;
import org.onosproject.net.driver.Driver;
@ -37,10 +38,14 @@ import org.onosproject.net.flowobjective.Objective;
import org.onosproject.net.flowobjective.ObjectiveError;
import org.onosproject.net.group.DefaultGroupBucket;
import org.onosproject.net.group.DefaultGroupDescription;
import org.onosproject.net.group.DefaultGroupKey;
import org.onosproject.net.group.GroupBucket;
import org.onosproject.net.group.GroupBuckets;
import org.onosproject.net.group.GroupDescription;
import org.onosproject.net.group.GroupKey;
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 org.slf4j.Logger;
@ -77,6 +82,9 @@ public class FabricNextPipeliner {
case HASHED:
processHashedNext(nextObjective, resultBuilder);
break;
case BROADCAST:
processBroadcastNext(nextObjective, resultBuilder);
break;
default:
log.warn("Unsupported next type {}", nextObjective);
resultBuilder.setError(ObjectiveError.UNSUPPORTED);
@ -292,4 +300,62 @@ public class FabricNextPipeliner {
.matchPi(nextIdCriterion)
.build();
}
private void processBroadcastNext(NextObjective next, PipelinerTranslationResult.Builder resultBuilder) {
int groupId = next.id();
List<GroupBucket> bucketList = next.next().stream()
.filter(treatment -> treatment != null)
.map(DefaultGroupBucket::createAllGroupBucket)
.collect(Collectors.toList());
if (bucketList.size() != next.next().size()) {
// some action not converted
// set error
log.warn("Expected bucket size {}, got {}", next.next().size(), bucketList.size());
resultBuilder.setError(ObjectiveError.BADPARAMS);
return;
}
GroupBuckets buckets = new GroupBuckets(bucketList);
//Used DefaultGroupKey instead of PiGroupKey
//as we don't have any action profile to apply to the groups of ALL type
GroupKey groupKey = new DefaultGroupKey(FabricPipeliner.KRYO.serialize(groupId));
resultBuilder.addGroup(new DefaultGroupDescription(deviceId,
GroupDescription.Type.ALL,
buckets,
groupKey,
groupId,
next.appId()));
//flow rule
TrafficSelector selector = buildNextIdSelector(next.id());
PiActionParam groupIdParam = new PiActionParam(FabricConstants.GID,
ImmutableByteSequence.copyFrom(groupId));
PiAction setMcGroupAction = PiAction.builder()
.withId(FabricConstants.FABRIC_INGRESS_NEXT_SET_MCAST_GROUP)
.withParameter(groupIdParam)
.build();
TrafficTreatment treatment = DefaultTrafficTreatment.builder()
.piTableAction(setMcGroupAction)
.build();
resultBuilder.addFlowRule(DefaultFlowRule.builder()
.withSelector(selector)
.withTreatment(treatment)
.forTable(FabricConstants.FABRIC_INGRESS_NEXT_MULTICAST)
.makePermanent()
.withPriority(next.priority())
.forDevice(deviceId)
.fromApp(next.appId())
.build());
// Egress VLAN handling
next.next().forEach(trafficTreatment -> {
PortNumber outputPort = getOutputPort(trafficTreatment);
if (includesPopVlanInst(trafficTreatment) && outputPort != null) {
processVlanPopRule(outputPort, next, resultBuilder);
}
});
}
}

View File

@ -17,8 +17,8 @@
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;
import org.onosproject.net.flow.DefaultFlowRule;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
@ -30,10 +30,14 @@ 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.DefaultGroupKey;
import org.onosproject.net.group.GroupBucket;
import org.onosproject.net.group.GroupBuckets;
import org.onosproject.net.group.GroupDescription;
import org.onosproject.net.group.GroupKey;
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;
@ -257,8 +261,113 @@ public class FabricNextPipelinerTest extends FabricPipelinerTest {
* Test program output group for Broadcast table.
*/
@Test
@Ignore
public void testBroadcastOutput() {
TrafficTreatment treatment1 = DefaultTrafficTreatment.builder()
.setOutput(PORT_1)
.build();
TrafficTreatment treatment2 = DefaultTrafficTreatment.builder()
.popVlan()
.setOutput(PORT_2)
.build();
NextObjective nextObjective = DefaultNextObjective.builder()
.withId(NEXT_ID_1)
.withPriority(PRIORITY)
.addTreatment(treatment1)
.addTreatment(treatment2)
.withMeta(VLAN_META)
.withType(NextObjective.Type.BROADCAST)
.makePermanent()
.fromApp(APP_ID)
.add();
PipelinerTranslationResult result = pipeliner.pipelinerNext.next(nextObjective);
// Should generate 1 flow, 1 group and 2 buckets in it
List<FlowRule> flowRulesInstalled = (List<FlowRule>) result.flowRules();
List<GroupDescription> groupsInstalled = (List<GroupDescription>) result.groups();
assertEquals(3, flowRulesInstalled.size());
assertEquals(1, groupsInstalled.size());
assertEquals(2, groupsInstalled.get(0).buckets().buckets().size());
//create the expected flow rule
PiCriterion nextIdCriterion = PiCriterion.builder()
.matchExact(FabricConstants.FABRIC_METADATA_NEXT_ID, NEXT_ID_1)
.build();
TrafficSelector nextIdSelector = DefaultTrafficSelector.builder()
.matchPi(nextIdCriterion)
.build();
PiActionParam groupIdParam = new PiActionParam(FabricConstants.GID,
ImmutableByteSequence.copyFrom(NEXT_ID_1));
PiAction setMcGroupAction = PiAction.builder()
.withId(FabricConstants.FABRIC_INGRESS_NEXT_SET_MCAST_GROUP)
.withParameter(groupIdParam)
.build();
TrafficTreatment treatment = DefaultTrafficTreatment.builder()
.piTableAction(setMcGroupAction)
.build();
FlowRule expectedFlowRule = DefaultFlowRule.builder()
.forDevice(DEVICE_ID)
.fromApp(APP_ID)
.makePermanent()
.withPriority(nextObjective.priority())
.forTable(FabricConstants.FABRIC_INGRESS_NEXT_MULTICAST)
.withSelector(nextIdSelector)
.withTreatment(treatment)
.build();
// VLAN meta table
FlowRule vmFlowRule = flowRulesInstalled.get(0);
assertTrue(vmFlowRule.exactMatch(vlanMetaFlowRule));
FlowRule actualFlowRule = flowRulesInstalled.get(1);
assertTrue(expectedFlowRule.exactMatch(actualFlowRule));
//prepare expected egress rule for the egress vlan pipeline
PiCriterion egressVlanTableMatch = PiCriterion.builder()
.matchExact(FabricConstants.STANDARD_METADATA_EGRESS_PORT,
(short) PORT_2.toLong())
.build();
TrafficSelector selectorForEgressVlan = DefaultTrafficSelector.builder()
.matchPi(egressVlanTableMatch)
.matchVlanId(VLAN_100)
.build();
TrafficTreatment treatmentForEgressVlan = DefaultTrafficTreatment.builder()
.popVlan()
.build();
FlowRule expectedEgressVlanRule = DefaultFlowRule.builder()
.withSelector(selectorForEgressVlan)
.withTreatment(treatmentForEgressVlan)
.forTable(FabricConstants.FABRIC_EGRESS_EGRESS_NEXT_EGRESS_VLAN)
.makePermanent()
.withPriority(nextObjective.priority())
.forDevice(DEVICE_ID)
.fromApp(APP_ID)
.build();
//egress vlan table
FlowRule actualEgressVlanFlowRule = flowRulesInstalled.get(2);
assertTrue(expectedEgressVlanRule.exactMatch(actualEgressVlanFlowRule));
//create the expected group
GroupDescription actualGroup = groupsInstalled.get(0);
List<TrafficTreatment> treatments = ImmutableList.of(treatment1, treatment2);
List<GroupBucket> buckets = treatments.stream()
.map(DefaultGroupBucket::createAllGroupBucket)
.collect(Collectors.toList());
GroupBuckets groupBuckets = new GroupBuckets(buckets);
GroupKey groupKey = new DefaultGroupKey(FabricPipeliner.KRYO.serialize(NEXT_ID_1));
GroupDescription expectedGroup = new DefaultGroupDescription(
DEVICE_ID,
GroupDescription.Type.ALL,
groupBuckets,
groupKey,
NEXT_ID_1,
APP_ID
);
assertEquals(expectedGroup, actualGroup);
}
}