use of org.onosproject.net.flowobjective.DefaultNextTreatment in project onos by opennetworkinglab.
the class NextObjectiveTranslator method defaultNextTreatments.
private List<DefaultNextTreatment> defaultNextTreatments(Collection<NextTreatment> nextTreatments, boolean strict) throws FabricPipelinerException {
final List<DefaultNextTreatment> defaultNextTreatments = Lists.newArrayList();
final List<NextTreatment> unsupportedNextTreatments = Lists.newArrayList();
for (NextTreatment n : nextTreatments) {
if (n.type() == NextTreatment.Type.TREATMENT) {
defaultNextTreatments.add((DefaultNextTreatment) n);
} else {
unsupportedNextTreatments.add(n);
}
}
if (strict && !unsupportedNextTreatments.isEmpty()) {
throw new FabricPipelinerException(format("Unsupported NextTreatments: %s", unsupportedNextTreatments));
}
return defaultNextTreatments;
}
use of org.onosproject.net.flowobjective.DefaultNextTreatment in project onos by opennetworkinglab.
the class NextObjectiveTranslator method xconnectNext.
private void xconnectNext(NextObjective obj, ObjectiveTranslation.Builder resultBuilder) throws FabricPipelinerException {
final Collection<DefaultNextTreatment> defaultNextTreatments = defaultNextTreatments(obj.nextTreatments(), true);
final List<PortNumber> outPorts = defaultNextTreatments.stream().map(DefaultNextTreatment::treatment).map(FabricUtils::outputPort).filter(Objects::nonNull).collect(Collectors.toList());
if (outPorts.size() != 2) {
throw new FabricPipelinerException(format("Handling XCONNECT with %d treatments (ports), but expected is 2", defaultNextTreatments.size()), ObjectiveError.UNSUPPORTED);
}
final PortNumber port1 = outPorts.get(0);
final PortNumber port2 = outPorts.get(1);
final TrafficSelector selector1 = nextIdSelectorBuilder(obj.id()).matchInPort(port1).build();
final TrafficTreatment treatment1 = DefaultTrafficTreatment.builder().setOutput(port2).build();
final TrafficSelector selector2 = nextIdSelectorBuilder(obj.id()).matchInPort(port2).build();
final TrafficTreatment treatment2 = DefaultTrafficTreatment.builder().setOutput(port1).build();
resultBuilder.addFlowRule(flowRule(obj, FabricConstants.FABRIC_INGRESS_NEXT_XCONNECT, selector1, treatment1));
resultBuilder.addFlowRule(flowRule(obj, FabricConstants.FABRIC_INGRESS_NEXT_XCONNECT, selector2, treatment2));
}
use of org.onosproject.net.flowobjective.DefaultNextTreatment in project onos by opennetworkinglab.
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.stream().forEach(vlanId -> treatmentBuilder.setVlanId(vlanId));
final TrafficTreatment treatment = treatmentBuilder.build();
resultBuilder.addFlowRule(flowRule(obj, FabricConstants.FABRIC_INGRESS_PRE_NEXT_NEXT_VLAN, selector, treatment));
}
use of org.onosproject.net.flowobjective.DefaultNextTreatment in project onos by opennetworkinglab.
the class NextObjectiveTranslator method nextMpls.
private void nextMpls(NextObjective obj, ObjectiveTranslation.Builder resultBuilder) throws FabricPipelinerException {
// Next objective can contain only one mpls push and one mpls label
// instruction. Pipeliner does not support other configurations.
final List<List<ModMplsLabelInstruction>> mplsInstructions = defaultNextTreatments(obj.nextTreatments(), false).stream().map(defaultNextTreatment -> l2Instructions(defaultNextTreatment.treatment(), MPLS_LABEL).stream().map(v -> (ModMplsLabelInstruction) v).collect(Collectors.toList())).filter(l -> !l.isEmpty()).collect(Collectors.toList());
if (mplsInstructions.isEmpty()) {
// No need to apply next mpls table
return;
}
// We expect one mpls label for each treatment and the label has to be the same
final Set<MplsLabel> mplsLabels = mplsInstructions.stream().flatMap(Collection::stream).map(ModMplsLabelInstruction::label).collect(Collectors.toSet());
if (obj.nextTreatments().size() != mplsInstructions.size() || mplsLabels.size() != 1) {
throw new FabricPipelinerException("Inconsistent MPLS_LABEL instructions, cannot process " + "next_mpls rule. It is required that all " + "treatments have the same MPLS_LABEL instructions.");
}
final TrafficSelector selector = nextIdSelector(obj.id());
final TrafficTreatment treatment = DefaultTrafficTreatment.builder().setMpls(mplsLabels.iterator().next()).build();
resultBuilder.addFlowRule(flowRule(obj, FabricConstants.FABRIC_INGRESS_PRE_NEXT_NEXT_MPLS, selector, treatment));
}
use of org.onosproject.net.flowobjective.DefaultNextTreatment in project onos by opennetworkinglab.
the class NextObjectiveCodec method encode.
@Override
public ObjectNode encode(NextObjective nextObjective, CodecContext context) {
checkNotNull(nextObjective, NOT_NULL_MESSAGE);
final JsonCodec<TrafficTreatment> trafficTreatmentCodec = context.codec(TrafficTreatment.class);
final JsonCodec<TrafficSelector> trafficSelectorCodec = context.codec(TrafficSelector.class);
// encode common properties
ObjectiveCodecHelper och = new ObjectiveCodecHelper();
ObjectNode result = och.encode(nextObjective, context);
// encode id
result.put(ID, nextObjective.id());
// encode type
result.put(TYPE, nextObjective.type().toString());
// encode operation
result.put(OPERATION, nextObjective.op().toString());
// encode treatments
ArrayNode treatments = context.mapper().createArrayNode();
nextObjective.nextTreatments().forEach(nt -> {
if (nt.type().equals(NextTreatment.Type.TREATMENT)) {
TrafficTreatment tt = ((DefaultNextTreatment) nt).treatment();
ObjectNode treatmentJson = trafficTreatmentCodec.encode(tt, context);
treatmentJson.put(WEIGHT, nt.weight());
treatments.add(treatmentJson);
}
});
result.set(TREATMENTS, treatments);
// encode meta
if (nextObjective.meta() != null) {
ObjectNode trafficSelectorNode = trafficSelectorCodec.encode(nextObjective.meta(), context);
result.set(META, trafficSelectorNode);
}
return result;
}
Aggregations