use of org.onosproject.net.flow.criteria.Criterion in project onos by opennetworkinglab.
the class Ofdpa2Pipeline method processFilter.
// ////////////////////////////////////
// Flow handling
// ////////////////////////////////////
/**
* As per OFDPA 2.0 TTP, filtering of VLAN ids and MAC addresses (for routing)
* configured on switch ports happen in different tables.
*
* @param filt the filtering objective
* @param install indicates whether to add or remove the objective
* @param applicationId the application that sent this objective
*/
protected void processFilter(FilteringObjective filt, boolean install, ApplicationId applicationId) {
// This driver only processes filtering criteria defined with switch
// ports as the key
PortCriterion portCriterion = null;
EthCriterion ethCriterion = null;
VlanIdCriterion vidCriterion = null;
if (!filt.key().equals(Criteria.dummy()) && filt.key().type() == Criterion.Type.IN_PORT) {
portCriterion = (PortCriterion) filt.key();
}
if (portCriterion == null) {
log.debug("No IN_PORT defined in filtering objective from app: {}", applicationId);
} else {
log.debug("Received filtering objective for dev/port: {}/{}", deviceId, portCriterion.port());
}
// convert filtering conditions for switch-intfs into flowrules
FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
for (Criterion criterion : filt.conditions()) {
switch(criterion.type()) {
case ETH_DST:
case ETH_DST_MASKED:
ethCriterion = (EthCriterion) criterion;
break;
case VLAN_VID:
vidCriterion = (VlanIdCriterion) criterion;
break;
default:
log.warn("Unsupported filter {}", criterion);
fail(filt, ObjectiveError.UNSUPPORTED);
return;
}
}
VlanId assignedVlan = null;
if (vidCriterion != null) {
// Use the VLAN in criterion if metadata is not present and the traffic is tagged
if (!vidCriterion.vlanId().equals(VlanId.NONE)) {
assignedVlan = vidCriterion.vlanId();
}
// If the meta VLAN is present let's update the assigned vlan
if (filt.meta() != null) {
VlanId metaVlan = readVlanFromTreatment(filt.meta());
if (metaVlan != null) {
assignedVlan = metaVlan;
}
}
if (assignedVlan == null) {
log.error("Driver fails to extract VLAN information. " + "Not processing VLAN filters on device {}.", deviceId);
log.debug("VLAN ID in criterion={}, metadata={}", readVlanFromTreatment(filt.meta()), vidCriterion.vlanId());
fail(filt, ObjectiveError.BADPARAMS);
return;
}
}
if (ethCriterion == null || ethCriterion.mac().equals(NONE)) {
// NOTE: it is possible that a filtering objective only has vidCriterion
log.debug("filtering objective missing dstMac, won't program TMAC table");
} else {
MacAddress unicastMac = readEthDstFromTreatment(filt.meta());
List<List<FlowRule>> allStages = processEthDstFilter(portCriterion, ethCriterion, vidCriterion, assignedVlan, unicastMac, applicationId);
for (List<FlowRule> flowRules : allStages) {
log.trace("Starting a new flow rule stage for TMAC table flow");
ops.newStage();
for (FlowRule flowRule : flowRules) {
log.trace("{} flow rule in TMAC table: {} for dev: {}", (install) ? "adding" : "removing", flowRule, deviceId);
if (install) {
ops = ops.add(flowRule);
} else {
// same VLAN on this device if TMAC doesn't support matching on in_port.
if (filt.meta() != null && filt.meta().clearedDeferred()) {
// TMac mcast does not match on the input port - we have to remove it
// only if this is the last port
FlowRule rule = buildTmacRuleForMcastFromUnicast(flowRule, applicationId);
// IPv6 or IPv4 tmac rule
if (rule != null) {
// Add first the mcast rule and then open a new stage for the unicast
ops = ops.remove(rule);
ops.newStage();
}
ops = ops.remove(flowRule);
} else if (matchInPortTmacTable()) {
ops = ops.remove(flowRule);
} else {
log.debug("Abort TMAC flow removal on {}. " + "Some other ports still share this TMAC flow", deviceId);
}
}
}
}
}
if (vidCriterion == null) {
// NOTE: it is possible that a filtering objective only has ethCriterion
log.info("filtering objective missing VLAN, cannot program VLAN Table");
} else {
List<List<FlowRule>> allStages = processVlanIdFilter(portCriterion, vidCriterion, assignedVlan, applicationId, install);
for (List<FlowRule> flowRules : allStages) {
log.trace("Starting a new flow rule stage for VLAN table flow");
ops.newStage();
for (FlowRule flowRule : flowRules) {
log.trace("{} flow rules in VLAN table: {} for dev: {}", (install) ? "adding" : "removing", flowRule, deviceId);
ops = install ? ops.add(flowRule) : ops.remove(flowRule);
}
}
}
// apply filtering flow rules
flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
@Override
public void onSuccess(FlowRuleOperations ops) {
log.debug("Applied {} filtering rules in device {}", ops.stages().get(0).size(), deviceId);
pass(filt);
}
@Override
public void onError(FlowRuleOperations ops) {
log.info("Failed to apply all filtering rules in dev {}", deviceId);
fail(filt, ObjectiveError.FLOWINSTALLATIONFAILED);
}
}));
}
use of org.onosproject.net.flow.criteria.Criterion in project onos by opennetworkinglab.
the class Ofdpa3Pipeline method processFilter.
@Override
protected void processFilter(FilteringObjective filteringObjective, boolean install, ApplicationId applicationId) {
// Check if filter is intended for pseudowire
boolean isPw = isPseudowire(filteringObjective);
if (isPw) {
FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
PortCriterion portCriterion;
VlanIdCriterion innerVlanIdCriterion = null;
for (Criterion criterion : filteringObjective.conditions()) {
if (criterion.type() == INNER_VLAN_VID) {
innerVlanIdCriterion = (VlanIdCriterion) criterion;
break;
}
}
VlanIdCriterion outerVlanIdCriterion = null;
// We extract the expected port criterion in the key.
portCriterion = (PortCriterion) filteringObjective.key();
// We extract the outer vlan id criterion.
for (Criterion criterion : filteringObjective.conditions()) {
if (criterion.type() == VLAN_VID) {
outerVlanIdCriterion = (VlanIdCriterion) criterion;
break;
}
}
// We extract the tunnel id.
long tunnelId;
VlanId egressVlan;
if (filteringObjective.meta() != null && filteringObjective.meta().allInstructions().size() != 2) {
log.warn("Bad filtering objective from app: {}. Not" + "processing filtering objective", applicationId);
fail(filteringObjective, ObjectiveError.BADPARAMS);
return;
} else if (filteringObjective.meta() != null && filteringObjective.meta().allInstructions().size() == 2 && filteringObjective.meta().allInstructions().get(0).type() == L2MODIFICATION && filteringObjective.meta().allInstructions().get(1).type() == L2MODIFICATION) {
L2ModificationInstruction l2instruction = (L2ModificationInstruction) filteringObjective.meta().allInstructions().get(0);
if (l2instruction.subtype() != L2SubType.TUNNEL_ID) {
log.warn("Bad filtering objective from app: {}. Not" + "processing filtering objective", applicationId);
fail(filteringObjective, ObjectiveError.BADPARAMS);
return;
} else {
tunnelId = ((ModTunnelIdInstruction) l2instruction).tunnelId();
}
L2ModificationInstruction vlanInstruction = (L2ModificationInstruction) filteringObjective.meta().allInstructions().get(1);
if (vlanInstruction.subtype() != L2SubType.VLAN_ID) {
log.warn("Bad filtering objective from app: {}. Not" + "processing filtering objective", applicationId);
fail(filteringObjective, ObjectiveError.BADPARAMS);
return;
} else {
egressVlan = ((L2ModificationInstruction.ModVlanIdInstruction) vlanInstruction).vlanId();
}
} else {
log.warn("Bad filtering objective from app: {}. Not" + "processing filtering objective", applicationId);
fail(filteringObjective, ObjectiveError.BADPARAMS);
return;
}
// Mpls tunnel ids according to the OFDPA manual have to be
// in the range [2^17-1, 2^16].
tunnelId = MPLS_TUNNEL_ID_BASE | tunnelId;
// Sanity check for the filtering objective.
if (portCriterion == null || outerVlanIdCriterion == null || tunnelId > MPLS_TUNNEL_ID_MAX) {
log.warn("Bad filtering objective from app: {}. Not" + "processing filtering objective", applicationId);
fail(filteringObjective, ObjectiveError.BADPARAMS);
return;
}
// 0x0000XXXX is UNI interface.
if (portCriterion.port().toLong() > MPLS_UNI_PORT_MAX) {
log.error("Filtering Objective invalid logical port {}", portCriterion.port().toLong());
fail(filteringObjective, ObjectiveError.BADPARAMS);
return;
}
// We create the flows.
List<FlowRule> pwRules = processPwFilter(portCriterion, innerVlanIdCriterion, outerVlanIdCriterion, tunnelId, applicationId, egressVlan);
// We tag the flow for adding or for removing.
for (FlowRule pwRule : pwRules) {
log.debug("adding filtering rule in VLAN tables: {} for dev: {}", pwRule, deviceId);
ops = install ? ops.add(pwRule) : ops.remove(pwRule);
}
// We push the filtering rules for the pw.
flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
@Override
public void onSuccess(FlowRuleOperations ops) {
log.info("Applied {} filtering rules in device {}", ops.stages().get(0).size(), deviceId);
pass(filteringObjective);
}
@Override
public void onError(FlowRuleOperations ops) {
log.info("Failed to apply all filtering rules in dev {}", deviceId);
fail(filteringObjective, ObjectiveError.FLOWINSTALLATIONFAILED);
}
}));
} else if (isDoubleTagged(filteringObjective)) {
processDoubleTaggedFilter(filteringObjective, install, applicationId);
} else {
// If it is not a pseudo wire flow or double-tagged filter, we fall back
// to the OFDPA 2.0 pipeline.
super.processFilter(filteringObjective, install, applicationId);
}
}
use of org.onosproject.net.flow.criteria.Criterion in project onos by opennetworkinglab.
the class OvsOfdpaPipeline method processDoubleTaggedFilter.
/**
* Configure filtering rules of outer and inner VLAN IDs, and a MAC address.
* Filtering happens in three tables (VLAN_TABLE, VLAN_1_TABLE, TMAC_TABLE).
*
* @param filteringObjective the filtering objective
* @param install true to add, false to remove
* @param applicationId for application programming this filter
*/
private void processDoubleTaggedFilter(FilteringObjective filteringObjective, boolean install, ApplicationId applicationId) {
PortCriterion portCriterion = null;
EthCriterion ethCriterion = null;
VlanIdCriterion innervidCriterion = null;
VlanIdCriterion outerVidCriterion = null;
boolean popVlan = false;
TrafficTreatment meta = filteringObjective.meta();
if (!filteringObjective.key().equals(Criteria.dummy()) && filteringObjective.key().type() == Criterion.Type.IN_PORT) {
portCriterion = (PortCriterion) filteringObjective.key();
}
if (portCriterion == null) {
log.warn("No IN_PORT defined in filtering objective from app: {}" + "Failed to program VLAN tables.", applicationId);
return;
} else {
log.debug("Received filtering objective for dev/port: {}/{}", deviceId, portCriterion.port());
}
// meta should have only one instruction, popVlan.
if (meta != null && meta.allInstructions().size() == 1) {
L2ModificationInstruction l2Inst = (L2ModificationInstruction) meta.allInstructions().get(0);
if (l2Inst.subtype().equals(L2ModificationInstruction.L2SubType.VLAN_POP)) {
popVlan = true;
} else {
log.warn("Filtering objective can have only VLAN_POP instruction.");
return;
}
} else {
log.warn("Filtering objective should have one instruction.");
return;
}
FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
for (Criterion criterion : filteringObjective.conditions()) {
switch(criterion.type()) {
case ETH_DST:
case ETH_DST_MASKED:
ethCriterion = (EthCriterion) criterion;
break;
case VLAN_VID:
outerVidCriterion = (VlanIdCriterion) criterion;
break;
case INNER_VLAN_VID:
innervidCriterion = (VlanIdCriterion) criterion;
break;
default:
log.warn("Unsupported filter {}", criterion);
fail(filteringObjective, ObjectiveError.UNSUPPORTED);
return;
}
}
if (innervidCriterion == null || outerVidCriterion == null) {
log.warn("filtering objective should have two vidCriterion.");
return;
}
if (ethCriterion == null || ethCriterion.mac().equals(NONE)) {
// NOTE: it is possible that a filtering objective only has vidCriterion
log.warn("filtering objective missing dstMac, cannot program TMAC table");
return;
} else {
MacAddress unicastMac = readEthDstFromTreatment(filteringObjective.meta());
List<List<FlowRule>> allStages = processEthDstFilter(portCriterion, ethCriterion, innervidCriterion, innervidCriterion.vlanId(), unicastMac, applicationId);
for (List<FlowRule> flowRules : allStages) {
log.trace("Starting a new flow rule stage for TMAC table flow");
ops.newStage();
for (FlowRule flowRule : flowRules) {
log.trace("{} flow rules in TMAC table: {} for dev: {}", (install) ? "adding" : "removing", flowRules, deviceId);
if (install) {
ops = ops.add(flowRule);
} else {
// same VLAN on this device if TMAC doesn't support matching on in_port.
if (matchInPortTmacTable() || (filteringObjective.meta() != null && filteringObjective.meta().clearedDeferred())) {
ops = ops.remove(flowRule);
} else {
log.debug("Abort TMAC flow removal on {}. Some other ports still share this TMAC flow");
}
}
}
}
}
List<FlowRule> rules;
rules = processDoubleVlanIdFilter(portCriterion, innervidCriterion, outerVidCriterion, popVlan, applicationId);
for (FlowRule flowRule : rules) {
log.trace("{} flow rule in VLAN table: {} for dev: {}", (install) ? "adding" : "removing", flowRule, deviceId);
ops = install ? ops.add(flowRule) : ops.remove(flowRule);
}
// apply filtering flow rules
flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
@Override
public void onSuccess(FlowRuleOperations ops) {
log.debug("Applied {} filtering rules in device {}", ops.stages().get(0).size(), deviceId);
pass(filteringObjective);
}
@Override
public void onError(FlowRuleOperations ops) {
log.info("Failed to apply all filtering rules in dev {}", deviceId);
fail(filteringObjective, ObjectiveError.FLOWINSTALLATIONFAILED);
}
}));
}
use of org.onosproject.net.flow.criteria.Criterion in project onos by opennetworkinglab.
the class OfdpaPipelineTraceable method handleVlanToController.
// If the initial packet comes tagged with a Vlan we output it with that to ONOS.
// If ONOS applied a vlan we remove it.
// TODO Candidate for an AbstractBehavior implementation
private void handleVlanToController(PipelineTraceableHitChain currentHitChain, TrafficSelector initialPacket) {
VlanIdCriterion initialVid = (VlanIdCriterion) initialPacket.getCriterion(Criterion.Type.VLAN_VID);
VlanIdCriterion finalVid = (VlanIdCriterion) currentHitChain.egressPacket().packet().getCriterion(Criterion.Type.VLAN_VID);
if (initialVid != null && !initialVid.equals(finalVid) && initialVid.vlanId().equals(VlanId.NONE)) {
Set<Criterion> finalCriteria = new HashSet<>(currentHitChain.egressPacket().packet().criteria());
// removing the final vlanId
finalCriteria.remove(finalVid);
TrafficSelector.Builder packetUpdated = DefaultTrafficSelector.builder();
finalCriteria.forEach(packetUpdated::add);
// Initial was none so we set it to that
packetUpdated.add(Criteria.matchVlanId(VlanId.NONE));
// Update final packet
currentHitChain.setEgressPacket(new PipelineTraceablePacket(packetUpdated.build()));
}
}
use of org.onosproject.net.flow.criteria.Criterion in project onos by opennetworkinglab.
the class LinkCollectionIntentFlowObjectiveCompiler method buildFilteringObjective.
private FilteringObjective buildFilteringObjective(LinkCollectionIntent intent, TrafficSelector selector, DeviceId deviceId, PortNumber inPort) {
FilteringObjective.Builder builder = DefaultFilteringObjective.builder();
builder.fromApp(appId).permit().makePermanent().withPriority(intent.priority());
Criterion inPortCriterion = selector.getCriterion(Criterion.Type.IN_PORT);
if (inPortCriterion != null) {
builder.withKey(inPortCriterion);
}
FilteredConnectPoint ingressPoint = intent.filteredIngressPoints().stream().filter(fcp -> fcp.connectPoint().equals(new ConnectPoint(deviceId, inPort))).filter(fcp -> selector.criteria().containsAll(fcp.trafficSelector().criteria())).findFirst().orElse(null);
AtomicBoolean emptyCondition = new AtomicBoolean(true);
if (ingressPoint != null) {
// ingress point, use criterion of it
ingressPoint.trafficSelector().criteria().forEach(criterion -> {
builder.addCondition(criterion);
emptyCondition.set(false);
});
if (emptyCondition.get()) {
return null;
}
return builder.add();
}
Optional<EncapsulationConstraint> encapConstraint = this.getIntentEncapConstraint(intent);
if (encapConstraint.isPresent() && !encapConstraint.get().encapType().equals(EncapsulationType.NONE)) {
// encapsulation enabled, use encapsulation label and tag.
EncapsulationConstraint encap = encapConstraint.get();
switch(encap.encapType()) {
case VLAN:
builder.addCondition(selector.getCriterion(Criterion.Type.VLAN_VID));
emptyCondition.set(false);
break;
case MPLS:
builder.addCondition(selector.getCriterion(Criterion.Type.MPLS_LABEL));
emptyCondition.set(false);
break;
default:
log.warn("No filtering rule found because of unknown encapsulation type.");
break;
}
} else {
// encapsulation not enabled, check if the treatment applied to the ingress or not
if (intent.applyTreatmentOnEgress()) {
// filtering criterion will be changed on egress point, use
// criterion of ingress point
ingressPoint = intent.filteredIngressPoints().stream().findFirst().orElse(null);
if (ingressPoint == null) {
log.warn("No filtering rule found because no ingress point in the Intent");
} else {
ingressPoint.trafficSelector().criteria().stream().filter(criterion -> !criterion.type().equals(Criterion.Type.IN_PORT)).forEach(criterion -> {
builder.addCondition(criterion);
emptyCondition.set(false);
});
}
} else {
// filtering criterion will be changed on ingress point, use
// criterion of egress point
FilteredConnectPoint egressPoint = intent.filteredEgressPoints().stream().findFirst().orElse(null);
if (egressPoint == null) {
log.warn("No filtering rule found because no egress point in the Intent");
} else {
egressPoint.trafficSelector().criteria().stream().filter(criterion -> !criterion.type().equals(Criterion.Type.IN_PORT)).forEach(criterion -> {
builder.addCondition(criterion);
emptyCondition.set(false);
});
}
}
}
if (emptyCondition.get()) {
return null;
}
return builder.add();
}
Aggregations