use of org.onosproject.net.flowobjective.DefaultNextTreatment in project onos by opennetworkinglab.
the class Ofdpa2GroupHandler method prepareL2UnfilteredGroup.
private List<GroupInfo> prepareL2UnfilteredGroup(NextObjective nextObj) {
ImmutableList.Builder<GroupInfo> groupInfoBuilder = ImmutableList.builder();
// break up broadcast next objective to multiple groups
Collection<TrafficTreatment> treatments = nextObj.nextTreatments().stream().filter(nt -> nt.type() == NextTreatment.Type.TREATMENT).map(nt -> ((DefaultNextTreatment) nt).treatment()).collect(Collectors.toSet());
Collection<Integer> nextIds = nextObj.nextTreatments().stream().filter(nt -> nt.type() == NextTreatment.Type.ID).map(nt -> ((IdNextTreatment) nt).nextId()).collect(Collectors.toSet());
// Each treatment is converted to an L2 unfiltered group
treatments.forEach(treatment -> {
TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
// Extract port information
PortNumber port = treatment.allInstructions().stream().map(instr -> (Instructions.OutputInstruction) instr).map(instr -> instr.port()).findFirst().orElse(null);
if (port == null) {
log.debug("Skip bucket without output instruction");
return;
}
tBuilder.setOutput(port);
if (requireAllowVlanTransition()) {
tBuilder.extension(new OfdpaSetAllowVlanTranslation(Ofdpa3AllowVlanTranslationType.ALLOW), deviceId);
}
// Build L2UG
int l2ugk = l2UnfilteredGroupKey(deviceId, port.toLong());
final GroupKey l2UnfilterGroupKey = new DefaultGroupKey(appKryo.serialize(l2ugk));
int l2UnfilteredGroupId = L2_UNFILTERED_TYPE | ((int) port.toLong() & FOUR_NIBBLE_MASK);
GroupBucket l2UnfilteredGroupBucket = DefaultGroupBucket.createIndirectGroupBucket(tBuilder.build());
GroupDescription l2UnfilteredGroupDesc = new DefaultGroupDescription(deviceId, GroupDescription.Type.INDIRECT, new GroupBuckets(Collections.singletonList(l2UnfilteredGroupBucket)), l2UnfilterGroupKey, l2UnfilteredGroupId, nextObj.appId());
log.debug("Trying L2-Unfiltered: device:{} gid:{} gkey:{} nextid:{}", deviceId, Integer.toHexString(l2UnfilteredGroupId), l2UnfilterGroupKey, nextObj.id());
groupInfoBuilder.add(new GroupInfo(l2UnfilteredGroupDesc, l2UnfilteredGroupDesc));
});
// Save the current count
int counts = groupInfoBuilder.build().size();
// Lookup each nextId in the store and obtain the group information
nextIds.forEach(nextId -> {
NextGroup nextGroup = flowObjectiveStore.getNextGroup(nextId);
if (nextGroup != null) {
List<Deque<GroupKey>> allActiveKeys = appKryo.deserialize(nextGroup.data());
GroupKey topGroupKey = allActiveKeys.get(0).getFirst();
GroupDescription groupDesc = groupService.getGroup(deviceId, topGroupKey);
if (groupDesc != null) {
log.debug("Trying L2-Hash device:{} gid:{}, gkey:{}, nextid:{}", deviceId, Integer.toHexString(((Group) groupDesc).id().id()), topGroupKey, nextId);
groupInfoBuilder.add(new GroupInfo(groupDesc, groupDesc));
} else {
log.error("Not found L2-Hash device:{}, gkey:{}, nextid:{}", deviceId, topGroupKey, nextId);
}
} else {
log.error("Not found NextGroup device:{}, nextid:{}", deviceId, nextId);
}
});
// Compare the size before and after to detect problems during the creation
ImmutableList<GroupInfo> groupInfos = groupInfoBuilder.build();
return (counts + nextIds.size()) == groupInfos.size() ? groupInfos : ImmutableList.of();
}
use of org.onosproject.net.flowobjective.DefaultNextTreatment in project fabric-tna by stratum.
the class NextObjectiveTranslator method selectGroup.
private int selectGroup(NextObjective obj, ObjectiveTranslation.Builder resultBuilder) throws FabricPipelinerException {
final PiTableId hashedTableId = P4InfoConstants.FABRIC_INGRESS_NEXT_HASHED;
final List<DefaultNextTreatment> defaultNextTreatments = defaultNextTreatments(obj.nextTreatments(), true);
final List<TrafficTreatment> piTreatments = Lists.newArrayList();
for (DefaultNextTreatment t : defaultNextTreatments) {
// Map treatment to PI...
piTreatments.add(mapTreatmentToPiIfNeeded(t.treatment(), hashedTableId));
// ...and handle egress if necessary.
handleEgress(obj, t.treatment(), resultBuilder, false);
}
final List<GroupBucket> bucketList = piTreatments.stream().map(DefaultGroupBucket::createSelectGroupBucket).collect(Collectors.toList());
final int groupId = obj.id();
final PiGroupKey groupKey = (PiGroupKey) getGroupKey(obj);
resultBuilder.addGroup(new DefaultGroupDescription(deviceId, GroupDescription.Type.SELECT, new GroupBuckets(bucketList), groupKey, groupId, obj.appId()));
return groupId;
}
use of org.onosproject.net.flowobjective.DefaultNextTreatment in project fabric-tna by stratum.
the class NextObjectiveTranslator method nextVlan.
private void nextVlan(NextObjective obj, ObjectiveTranslation.Builder resultBuilder) throws FabricPipelinerException {
// We expect NextObjective treatments to contain one or two VLAN instructions.
// If two, this treatment should be mapped to an action for double-vlan push.
// In fabric.p4, mapping next IDs to VLAN IDs is done by a direct table (next_vlan),
// for this reason, we also make sure that all treatments in the NextObjective
// have exactly the same VLAN instructions, as they will be mapped to a single action
// Try to extract VLAN instructions in the treatment,
// later we check if we support multiple VLAN termination.
final List<List<ModVlanIdInstruction>> vlanInstructions = defaultNextTreatments(obj.nextTreatments(), false).stream().map(defaultNextTreatment -> l2Instructions(defaultNextTreatment.treatment(), VLAN_ID).stream().map(v -> (ModVlanIdInstruction) v).collect(Collectors.toList())).filter(l -> !l.isEmpty()).collect(Collectors.toList());
final VlanIdCriterion vlanIdCriterion = obj.meta() == null ? null : (VlanIdCriterion) criterion(obj.meta().criteria(), Criterion.Type.VLAN_VID);
final List<VlanId> vlanIdList;
if (vlanInstructions.isEmpty() && vlanIdCriterion == null) {
// No VLAN_ID to apply.
return;
}
if (!vlanInstructions.isEmpty()) {
// Give priority to what found in the instructions.
// Expect the same VLAN ID (or two VLAN IDs in the same order) for all instructions.
final Set<List<VlanId>> vlanIds = vlanInstructions.stream().map(l -> l.stream().map(ModVlanIdInstruction::vlanId).collect(Collectors.toList())).collect(Collectors.toSet());
if (obj.nextTreatments().size() != vlanInstructions.size() || vlanIds.size() != 1) {
throw new FabricPipelinerException("Inconsistent VLAN_ID instructions, cannot process " + "next_vlan rule. It is required that all " + "treatments have the same VLAN_ID instructions.");
}
vlanIdList = vlanIds.iterator().next();
} else {
// Use the value in meta.
// FIXME: there should be no need to generate a next_vlan rule for
// the value found in meta. Meta describes the fields that were
// expected to be matched in previous pipeline stages, i.e.
// existing packet fields. But, for some reason, if we remove this
// rule, traffic is not forwarded at spines. We might need to look
// at the way default VLANs are handled in fabric.p4.
vlanIdList = List.of(vlanIdCriterion.vlanId());
}
final TrafficSelector selector = nextIdSelector(obj.id());
final TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();
vlanIdList.forEach(treatmentBuilder::setVlanId);
final TrafficTreatment treatment = treatmentBuilder.build();
resultBuilder.addFlowRule(flowRule(obj, P4InfoConstants.FABRIC_INGRESS_PRE_NEXT_NEXT_VLAN, selector, treatment));
}
Aggregations