use of org.onosproject.net.flow.criteria.VlanIdCriterion in project onos by opennetworkinglab.
the class ForwardingObjectiveTranslator method bridgingRule.
private void bridgingRule(ForwardingObjective obj, Set<Criterion> criteriaWithMeta, ObjectiveTranslation.Builder resultBuilder, boolean broadcast) throws FabricPipelinerException {
final VlanIdCriterion vlanIdCriterion = (VlanIdCriterion) criterionNotNull(criteriaWithMeta, Criterion.Type.VLAN_VID);
final TrafficSelector.Builder selector = DefaultTrafficSelector.builder().add(vlanIdCriterion);
if (!broadcast) {
final EthCriterion ethDstCriterion = (EthCriterion) criterionNotNull(obj.selector(), Criterion.Type.ETH_DST);
selector.matchEthDstMasked(ethDstCriterion.mac(), MacAddress.EXACT_MASK);
}
resultBuilder.addFlowRule(flowRule(obj, FabricConstants.FABRIC_INGRESS_FORWARDING_BRIDGING, selector.build()));
}
use of org.onosproject.net.flow.criteria.VlanIdCriterion 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.flow.criteria.VlanIdCriterion in project onos by opennetworkinglab.
the class LinkCollectionCompiler method forwardingTreatment.
/**
* Compares tag type between ingress and egress point and generate
* treatment for egress point of intent.
*
* @param ingress ingress selector for the intent
* @param egress egress selector for the intent
* @param ethType the ethertype to use in mpls_pop
* @return Builder of TrafficTreatment
*/
private TrafficTreatment forwardingTreatment(TrafficSelector ingress, TrafficSelector egress, EthType ethType) {
if (ingress.equals(egress)) {
return DefaultTrafficTreatment.emptyTreatment();
}
TrafficTreatment.Builder builder = DefaultTrafficTreatment.builder();
/*
* "null" means there is no tag for the port
* Tag criterion will be null if port is normal connection point
*/
Criterion ingressTagCriterion = getTagCriterion(ingress);
Criterion egressTagCriterion = getTagCriterion(egress);
if (ingressTagCriterion.type() != egressTagCriterion.type()) {
/*
* Tag type of ingress port and egress port are different.
* Need to remove tag from ingress, then add new tag for egress.
* Remove nothing if ingress port use VXLAN or there is no tag
* on ingress port.
*/
switch(ingressTagCriterion.type()) {
case VLAN_VID:
builder.popVlan();
break;
case MPLS_LABEL:
if (copyTtl) {
builder.copyTtlIn();
}
builder.popMpls(ethType);
break;
default:
break;
}
/*
* Push new tag for egress port.
*/
switch(egressTagCriterion.type()) {
case VLAN_VID:
builder.pushVlan();
break;
case MPLS_LABEL:
builder.pushMpls();
if (copyTtl) {
builder.copyTtlOut();
}
break;
default:
break;
}
}
switch(egressTagCriterion.type()) {
case VLAN_VID:
VlanIdCriterion vlanIdCriterion = (VlanIdCriterion) egressTagCriterion;
builder.setVlanId(vlanIdCriterion.vlanId());
break;
case MPLS_LABEL:
MplsCriterion mplsCriterion = (MplsCriterion) egressTagCriterion;
builder.setMpls(mplsCriterion.label());
break;
case TUNNEL_ID:
TunnelIdCriterion tunnelIdCriterion = (TunnelIdCriterion) egressTagCriterion;
builder.setTunnelId(tunnelIdCriterion.tunnelId());
break;
default:
break;
}
return builder.build();
}
use of org.onosproject.net.flow.criteria.VlanIdCriterion in project onos by opennetworkinglab.
the class LinkCollectionCompiler method orderedEgressPoints.
/**
* Helper method to order the egress ports according to a
* specified criteria. The idea is to generate first the actions
* for the egress ports which are similar to the specified criteria
* then the others. In this way we can mitigate the problems related
* to the chain of actions and we can optimize also the number of
* actions.
*
* @param orderCriteria the ordering criteria
* @param pointsToOrder the egress points to order
* @return a list of port ordered
*/
private List<FilteredConnectPoint> orderedEgressPoints(TrafficSelector orderCriteria, List<FilteredConnectPoint> pointsToOrder) {
/*
* We are interested only to the labels. The idea is to order
* by the tags.
*
*/
Criterion vlanIdCriterion = orderCriteria.getCriterion(VLAN_VID);
Criterion mplsLabelCriterion = orderCriteria.getCriterion(MPLS_LABEL);
/*
* We collect all the untagged points.
*
*/
List<FilteredConnectPoint> untaggedEgressPoints = pointsToOrder.stream().filter(pointToOrder -> {
TrafficSelector selector = pointToOrder.trafficSelector();
return selector.getCriterion(VLAN_VID) == null && selector.getCriterion(MPLS_LABEL) == null;
}).collect(Collectors.toList());
/*
* We collect all the vlan points.
*/
List<FilteredConnectPoint> vlanEgressPoints = pointsToOrder.stream().filter(pointToOrder -> {
TrafficSelector selector = pointToOrder.trafficSelector();
return selector.getCriterion(VLAN_VID) != null && selector.getCriterion(MPLS_LABEL) == null;
}).collect(Collectors.toList());
/*
* We collect all the mpls points.
*/
List<FilteredConnectPoint> mplsEgressPoints = pointsToOrder.stream().filter(pointToOrder -> {
TrafficSelector selector = pointToOrder.trafficSelector();
return selector.getCriterion(VLAN_VID) == null && selector.getCriterion(MPLS_LABEL) != null;
}).collect(Collectors.toList());
/*
* We create the final list of ports.
*/
List<FilteredConnectPoint> orderedList = Lists.newArrayList();
/*
* The ordering criteria is vlan id. First we add the vlan
* ports. Then the others.
*/
if (vlanIdCriterion != null && mplsLabelCriterion == null) {
orderedList.addAll(vlanEgressPoints);
orderedList.addAll(untaggedEgressPoints);
orderedList.addAll(mplsEgressPoints);
return orderedList;
}
/*
* The ordering criteria is mpls label. First we add the mpls
* ports. Then the others.
*/
if (vlanIdCriterion == null && mplsLabelCriterion != null) {
orderedList.addAll(mplsEgressPoints);
orderedList.addAll(untaggedEgressPoints);
orderedList.addAll(vlanEgressPoints);
return orderedList;
}
/*
* The ordering criteria is untagged. First we add the untagged
* ports. Then the others.
*/
if (vlanIdCriterion == null) {
orderedList.addAll(untaggedEgressPoints);
orderedList.addAll(vlanEgressPoints);
orderedList.addAll(mplsEgressPoints);
return orderedList;
}
/*
* Unhandled scenario.
*/
orderedList.addAll(vlanEgressPoints);
orderedList.addAll(mplsEgressPoints);
orderedList.addAll(untaggedEgressPoints);
return orderedList;
}
use of org.onosproject.net.flow.criteria.VlanIdCriterion in project onos by opennetworkinglab.
the class PathCompiler method manageVlanEncap.
/**
* Creates the flow rules for the path intent using VLAN
* encapsulation.
*
* @param creator the flowrules creator
* @param flows the list of flows to fill
* @param devices the devices on the path
* @param intent the PathIntent to compile
*/
private void manageVlanEncap(PathCompilerCreateFlow<T> creator, List<T> flows, List<DeviceId> devices, PathIntent intent) {
Set<Link> linksSet = Sets.newConcurrentHashSet();
for (int i = 1; i <= intent.path().links().size() - 2; i++) {
linksSet.add(intent.path().links().get(i));
}
Map<LinkKey, Identifier<?>> vlanIds = labelAllocator.assignLabelToLinks(linksSet, intent.key(), EncapsulationType.VLAN);
Iterator<Link> links = intent.path().links().iterator();
Link srcLink = links.next();
Link link = links.next();
// Ingress traffic
VlanId vlanId = (VlanId) vlanIds.get(linkKey(link));
if (vlanId == null) {
throw new IntentCompilationException(ERROR_VLAN + link);
}
VlanId prevVlanId = vlanId;
Optional<VlanIdCriterion> vlanCriterion = intent.selector().criteria().stream().filter(criterion -> criterion.type() == Criterion.Type.VLAN_VID).map(criterion -> (VlanIdCriterion) criterion).findAny();
// Push VLAN if selector does not include VLAN
TrafficTreatment.Builder treatBuilder = DefaultTrafficTreatment.builder();
if (!vlanCriterion.isPresent()) {
treatBuilder.pushVlan();
}
// Tag the traffic with the new encapsulation VLAN
treatBuilder.setVlanId(vlanId);
creator.createFlow(intent.selector(), treatBuilder.build(), srcLink.dst(), link.src(), intent.priority(), true, flows, devices);
ConnectPoint prev = link.dst();
while (links.hasNext()) {
link = links.next();
if (links.hasNext()) {
// Transit traffic
VlanId egressVlanId = (VlanId) vlanIds.get(linkKey(link));
if (egressVlanId == null) {
throw new IntentCompilationException(ERROR_VLAN + link);
}
TrafficSelector transitSelector = DefaultTrafficSelector.builder().matchInPort(prev.port()).matchVlanId(prevVlanId).build();
TrafficTreatment.Builder transitTreat = DefaultTrafficTreatment.builder();
// Set the new vlanId only if the previous one is different
if (!prevVlanId.equals(egressVlanId)) {
transitTreat.setVlanId(egressVlanId);
}
creator.createFlow(transitSelector, transitTreat.build(), prev, link.src(), intent.priority(), true, flows, devices);
/* For the next hop we have to remember
* the previous egress VLAN id and the egress
* node
*/
prevVlanId = egressVlanId;
prev = link.dst();
} else {
// Egress traffic
TrafficSelector egressSelector = DefaultTrafficSelector.builder().matchInPort(prev.port()).matchVlanId(prevVlanId).build();
TrafficTreatment.Builder egressTreat = DefaultTrafficTreatment.builder(intent.treatment());
Optional<L2ModificationInstruction.ModVlanIdInstruction> modVlanIdInstruction = intent.treatment().allInstructions().stream().filter(instruction -> instruction instanceof L2ModificationInstruction.ModVlanIdInstruction).map(x -> (L2ModificationInstruction.ModVlanIdInstruction) x).findAny();
Optional<L2ModificationInstruction.ModVlanHeaderInstruction> popVlanInstruction = intent.treatment().allInstructions().stream().filter(instruction -> instruction instanceof L2ModificationInstruction.ModVlanHeaderInstruction).map(x -> (L2ModificationInstruction.ModVlanHeaderInstruction) x).findAny();
if (!modVlanIdInstruction.isPresent() && !popVlanInstruction.isPresent()) {
if (vlanCriterion.isPresent()) {
egressTreat.setVlanId(vlanCriterion.get().vlanId());
} else {
egressTreat.popVlan();
}
}
creator.createFlow(egressSelector, egressTreat.build(), prev, link.src(), intent.priority(), true, flows, devices);
}
}
}
Aggregations