use of org.onosproject.net.flow.criteria.VlanIdCriterion 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.VlanIdCriterion in project onos by opennetworkinglab.
the class Ofdpa2Pipeline method processEthDstSpecific.
/**
* Handles forwarding rules to the L2 bridging table. Flow actions are not
* allowed in the bridging table - instead we use L2 Interface group or
* L2 flood group
*
* @param fwd the forwarding objective
* @return A collection of flow rules, or an empty set
*/
protected Collection<FlowRule> processEthDstSpecific(ForwardingObjective fwd) {
List<FlowRule> rules = new ArrayList<>();
// Build filtered selector
TrafficSelector selector = fwd.selector();
EthCriterion ethCriterion = (EthCriterion) selector.getCriterion(Criterion.Type.ETH_DST);
VlanIdCriterion vlanIdCriterion = (VlanIdCriterion) selector.getCriterion(Criterion.Type.VLAN_VID);
if (vlanIdCriterion == null) {
log.warn("Forwarding objective for bridging requires vlan. Not " + "installing fwd:{} in dev:{}", fwd.id(), deviceId);
fail(fwd, ObjectiveError.BADPARAMS);
return Collections.emptySet();
}
TrafficSelector.Builder filteredSelectorBuilder = DefaultTrafficSelector.builder();
if (!ethCriterion.mac().equals(NONE) && !ethCriterion.mac().equals(BROADCAST)) {
filteredSelectorBuilder.matchEthDst(ethCriterion.mac());
log.debug("processing L2 forwarding objective:{} -> next:{} in dev:{}", fwd.id(), fwd.nextId(), deviceId);
} else {
// Use wildcard DST_MAC if the MacAddress is None or Broadcast
log.debug("processing L2 Broadcast forwarding objective:{} -> next:{} " + "in dev:{} for vlan:{}", fwd.id(), fwd.nextId(), deviceId, vlanIdCriterion.vlanId());
}
if (requireVlanExtensions()) {
OfdpaMatchVlanVid ofdpaMatchVlanVid = new OfdpaMatchVlanVid(vlanIdCriterion.vlanId());
filteredSelectorBuilder.extension(ofdpaMatchVlanVid, deviceId);
} else {
filteredSelectorBuilder.matchVlanId(vlanIdCriterion.vlanId());
}
TrafficSelector filteredSelector = filteredSelectorBuilder.build();
if (fwd.treatment() != null) {
log.warn("Ignoring traffic treatment in fwd rule {} meant for L2 table" + "for dev:{}. Expecting only nextId", fwd.id(), deviceId);
}
TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();
if (fwd.nextId() != null) {
NextGroup next = getGroupForNextObjective(fwd.nextId());
if (next != null) {
List<Deque<GroupKey>> gkeys = appKryo.deserialize(next.data());
// we only need the top level group's key to point the flow to it
Group group = groupService.getGroup(deviceId, gkeys.get(0).peekFirst());
if (group != null) {
treatmentBuilder.deferred().group(group.id());
} else {
log.warn("Group with key:{} for next-id:{} not found in dev:{}", gkeys.get(0).peekFirst(), fwd.nextId(), deviceId);
fail(fwd, ObjectiveError.GROUPMISSING);
return Collections.emptySet();
}
}
}
treatmentBuilder.immediate().transition(ACL_TABLE);
TrafficTreatment filteredTreatment = treatmentBuilder.build();
// Build bridging table entries
FlowRule.Builder flowRuleBuilder = DefaultFlowRule.builder();
flowRuleBuilder.fromApp(fwd.appId()).withPriority(fwd.priority()).forDevice(deviceId).withSelector(filteredSelector).withTreatment(filteredTreatment).forTable(BRIDGING_TABLE);
if (fwd.permanent()) {
flowRuleBuilder.makePermanent();
} else {
flowRuleBuilder.makeTemporary(fwd.timeout());
}
rules.add(flowRuleBuilder.build());
return rules;
}
use of org.onosproject.net.flow.criteria.VlanIdCriterion in project onos by opennetworkinglab.
the class Ofdpa2Pipeline method processVersatile.
/**
* In the OF-DPA 2.0 pipeline, versatile forwarding objectives go to the
* ACL table.
* @param fwd the forwarding objective of type 'versatile'
* @return a collection of flow rules to be sent to the switch. An empty
* collection may be returned if there is a problem in processing
* the flow rule
*/
protected Collection<FlowRule> processVersatile(ForwardingObjective fwd) {
log.debug("Processing versatile forwarding objective:{} in dev:{}", fwd.id(), deviceId);
List<FlowRule> flowRules = new ArrayList<>();
final AtomicBoolean ethTypeUsed = new AtomicBoolean(false);
if (fwd.nextId() == null && fwd.treatment() == null) {
log.error("Forwarding objective {} from {} must contain " + "nextId or Treatment", fwd.selector(), fwd.appId());
fail(fwd, ObjectiveError.BADPARAMS);
return Collections.emptySet();
}
TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
fwd.selector().criteria().forEach(criterion -> {
if (criterion instanceof VlanIdCriterion) {
VlanId vlanId = ((VlanIdCriterion) criterion).vlanId();
// match untagged packets this way in the ACL table.
if (vlanId.equals(VlanId.NONE)) {
return;
}
if (requireVlanExtensions()) {
OfdpaMatchVlanVid ofdpaMatchVlanVid = new OfdpaMatchVlanVid(vlanId);
sbuilder.extension(ofdpaMatchVlanVid, deviceId);
} else {
sbuilder.matchVlanId(vlanId);
}
} else if (criterion instanceof Icmpv6TypeCriterion) {
byte icmpv6Type = (byte) ((Icmpv6TypeCriterion) criterion).icmpv6Type();
sbuilder.matchIcmpv6Type(icmpv6Type);
} else if (criterion instanceof Icmpv6CodeCriterion) {
byte icmpv6Code = (byte) ((Icmpv6CodeCriterion) criterion).icmpv6Code();
sbuilder.matchIcmpv6Type(icmpv6Code);
} else if (criterion instanceof TcpPortCriterion || criterion instanceof UdpPortCriterion) {
// We need to revisit this if L4 dst port is used for other purpose in the future.
if (!supportIpv6L4Dst() && isIpv6(fwd.selector())) {
switch(criterion.type()) {
case UDP_DST:
case UDP_DST_MASKED:
case TCP_DST:
case TCP_DST_MASKED:
break;
default:
sbuilder.add(criterion);
}
} else {
sbuilder.add(criterion);
}
} else if (criterion instanceof EthTypeCriterion) {
sbuilder.add(criterion);
ethTypeUsed.set(true);
} else {
sbuilder.add(criterion);
}
});
TrafficTreatment.Builder ttBuilder = versatileTreatmentBuilder(fwd);
if (ttBuilder == null) {
return Collections.emptySet();
}
FlowRule.Builder ruleBuilder = DefaultFlowRule.builder().fromApp(fwd.appId()).withPriority(fwd.priority()).forDevice(deviceId).withSelector(sbuilder.build()).withTreatment(ttBuilder.build()).makePermanent().forTable(ACL_TABLE);
flowRules.add(ruleBuilder.build());
if (!ethTypeUsed.get() && requireEthType()) {
log.debug("{} doesn't match on ethType but requireEthType is true, adding complementary ACL flow.", sbuilder.toString());
sbuilder.matchEthType(Ethernet.TYPE_IPV6);
FlowRule.Builder ethTypeRuleBuilder = DefaultFlowRule.builder().fromApp(fwd.appId()).withPriority(fwd.priority()).forDevice(deviceId).withSelector(sbuilder.build()).withTreatment(ttBuilder.build()).makePermanent().forTable(ACL_TABLE);
flowRules.add(ethTypeRuleBuilder.build());
}
return flowRules;
}
use of org.onosproject.net.flow.criteria.VlanIdCriterion 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.VlanIdCriterion 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);
}
}
Aggregations