use of org.onosproject.net.flow.criteria.VlanIdCriterion in project onos by opennetworkinglab.
the class SpringOpenTTP method processEthDstSpecificObjective.
protected Collection<FlowRule> processEthDstSpecificObjective(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);
TrafficSelector.Builder filteredSelectorBuilder = DefaultTrafficSelector.builder();
// Do not match MacAddress for subnet broadcast entry
if (!ethCriterion.mac().equals(MacAddress.NONE)) {
filteredSelectorBuilder.matchEthDst(ethCriterion.mac());
log.debug("processing L2 forwarding objective:{} in dev:{}", fwd.id(), deviceId);
} else {
log.debug("processing L2 Broadcast forwarding objective:{} " + "in dev:{} for vlan:{}", fwd.id(), deviceId, vlanIdCriterion.vlanId());
}
filteredSelectorBuilder.matchVlanId(vlanIdCriterion.vlanId());
TrafficSelector filteredSelector = filteredSelectorBuilder.build();
// Build filtered treatment
TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();
if (fwd.treatment() != null) {
treatmentBuilder.deferred();
fwd.treatment().allInstructions().forEach(treatmentBuilder::add);
}
if (fwd.nextId() != null) {
NextGroup next = flowObjectiveStore.getNextGroup(fwd.nextId());
if (next != null) {
SpringOpenGroup soGrp = appKryo.deserialize(next.data());
if (soGrp.dummy) {
log.debug("Adding {} flow-actions for fwd. obj. {} " + "in dev: {}", soGrp.treatment.allInstructions().size(), fwd.id(), deviceId);
for (Instruction ins : soGrp.treatment.allInstructions()) {
treatmentBuilder.deferred().add(ins);
}
} else {
GroupKey key = soGrp.key;
Group group = groupService.getGroup(deviceId, key);
if (group == null) {
log.warn("The group left!");
fail(fwd, ObjectiveError.GROUPMISSING);
return Collections.emptySet();
}
treatmentBuilder.deferred().group(group.id());
log.debug("Adding OUTGROUP action to group:{} for fwd. obj. {} " + "in dev: {}", group.id(), fwd.id(), deviceId);
}
}
}
treatmentBuilder.immediate().transition(aclTableId);
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(dstMacTableId);
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 SpringOpenTTP method processFilter.
private void processFilter(FilteringObjective filt, boolean install, ApplicationId applicationId) {
// ports as the key
if (filt.key().equals(Criteria.dummy()) || filt.key().type() != Criterion.Type.IN_PORT) {
log.warn("No key defined in filtering objective from app: {}. Not" + "processing filtering objective", applicationId);
fail(filt, ObjectiveError.UNKNOWN);
return;
}
EthCriterion ethCriterion = null;
VlanIdCriterion vlanIdCriterion = null;
// convert filtering conditions for switch-intfs into flowrules
FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
for (Criterion criterion : filt.conditions()) {
if (criterion.type() == Criterion.Type.ETH_DST) {
ethCriterion = (EthCriterion) criterion;
} else if (criterion.type() == Criterion.Type.VLAN_VID) {
vlanIdCriterion = (VlanIdCriterion) criterion;
} else if (criterion.type() == Criterion.Type.IPV4_DST) {
log.debug("driver does not process IP filtering rules as it " + "sends all misses in the IP table to the controller");
} else {
log.warn("Driver does not currently process filtering condition" + " of type: {}", criterion.type());
fail(filt, ObjectiveError.UNSUPPORTED);
}
}
VlanId assignedVlan = null;
VlanId modifiedVlan = null;
VlanId pushedVlan = null;
boolean pushVlan = false;
boolean popVlan = false;
if (vlanIdCriterion != null) {
if (filt.meta() != null) {
for (Instruction i : filt.meta().allInstructions()) {
if (i instanceof L2ModificationInstruction) {
if (((L2ModificationInstruction) i).subtype().equals(L2ModificationInstruction.L2SubType.VLAN_PUSH)) {
pushVlan = true;
} else if (((L2ModificationInstruction) i).subtype().equals(L2ModificationInstruction.L2SubType.VLAN_POP)) {
if (modifiedVlan != null) {
log.error("Pop tag is not allowed after modify VLAN operation " + "in filtering objective", deviceId);
fail(filt, ObjectiveError.BADPARAMS);
return;
}
popVlan = true;
}
}
if (i instanceof ModVlanIdInstruction) {
if (pushVlan && vlanIdCriterion.vlanId() != VlanId.NONE) {
// Modify VLAN should not appear after pushing a new tag
if (pushedVlan != null) {
log.error("Modify VLAN not allowed after push tag operation " + "in filtering objective", deviceId);
fail(filt, ObjectiveError.BADPARAMS);
return;
}
pushedVlan = ((ModVlanIdInstruction) i).vlanId();
} else if (vlanIdCriterion.vlanId() == VlanId.NONE) {
// For untagged packets the pushed VLAN ID will be saved in assignedVlan
// just to ensure the driver works as designed for the fabric use case
assignedVlan = ((ModVlanIdInstruction) i).vlanId();
} else {
// For tagged packets modifiedVlan will contain the modified value of existing tag
if (modifiedVlan != null) {
log.error("Driver does not allow multiple modify VLAN operations " + "in the same filtering objective", deviceId);
fail(filt, ObjectiveError.BADPARAMS);
return;
}
modifiedVlan = ((ModVlanIdInstruction) i).vlanId();
}
}
}
}
// For VLAN cross-connect packets, use the configured VLAN unless there is an explicitly provided VLAN ID
if (vlanIdCriterion.vlanId() != VlanId.NONE) {
if (assignedVlan == null) {
assignedVlan = vlanIdCriterion.vlanId();
}
// For untagged packets, assign a VLAN ID
} else {
if (filt.meta() == null) {
log.error("Missing metadata in filtering objective required " + "for vlan assignment in dev {}", deviceId);
fail(filt, ObjectiveError.BADPARAMS);
return;
}
if (assignedVlan == null) {
log.error("Driver requires an assigned vlan-id to tag incoming " + "untagged packets. Not processing vlan filters on " + "device {}", deviceId);
fail(filt, ObjectiveError.BADPARAMS);
return;
}
}
if (pushVlan && popVlan) {
log.error("Cannot push and pop vlan in the same filtering objective");
fail(filt, ObjectiveError.BADPARAMS);
return;
}
if (popVlan && vlanIdCriterion.vlanId() == VlanId.NONE) {
log.error("Cannot pop vlan for untagged packets");
fail(filt, ObjectiveError.BADPARAMS);
return;
}
if ((pushVlan && pushedVlan == null) && vlanIdCriterion.vlanId() != VlanId.NONE) {
log.error("No VLAN ID provided for push tag operation");
fail(filt, ObjectiveError.BADPARAMS);
return;
}
}
if (ethCriterion == null) {
log.debug("filtering objective missing dstMac, cannot program TMAC table");
} else {
for (FlowRule tmacRule : processEthDstFilter(ethCriterion, vlanIdCriterion, filt, assignedVlan, applicationId)) {
log.debug("adding MAC filtering rules in TMAC table: {} for dev: {}", tmacRule, deviceId);
ops = install ? ops.add(tmacRule) : ops.remove(tmacRule);
}
}
if (vlanIdCriterion == null) {
log.debug("filtering objective missing VLAN ID criterion, " + "cannot program VLAN Table");
} else {
for (FlowRule vlanRule : processVlanIdFilter(vlanIdCriterion, filt, assignedVlan, modifiedVlan, pushedVlan, pushVlan, popVlan, applicationId)) {
log.debug("adding VLAN filtering rule in VLAN table: {} for dev: {}", vlanRule, deviceId);
ops = install ? ops.add(vlanRule) : ops.remove(vlanRule);
}
}
// apply filtering flow rules
flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
@Override
public void onSuccess(FlowRuleOperations ops) {
pass(filt);
log.debug("Provisioned tables in {} with fitering " + "rules", deviceId);
}
@Override
public void onError(FlowRuleOperations ops) {
fail(filt, ObjectiveError.FLOWINSTALLATIONFAILED);
log.warn("Failed to provision tables in {} with " + "fitering rules", deviceId);
}
}));
}
use of org.onosproject.net.flow.criteria.VlanIdCriterion in project onos by opennetworkinglab.
the class CentecV350Pipeline method processFilter.
private void processFilter(FilteringObjective filt, boolean install, ApplicationId applicationId) {
PortCriterion p;
if (!filt.key().equals(Criteria.dummy()) && filt.key().type() == Criterion.Type.IN_PORT) {
p = (PortCriterion) filt.key();
} else {
log.warn("No key defined in filtering objective from app: {}. Not" + "processing filtering objective", applicationId);
fail(filt, ObjectiveError.UNKNOWN);
return;
}
// Convert filtering conditions for switch-intfs into flow rules.
FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
for (Criterion c : filt.conditions()) {
// Here we do a trick to install 2 flow rules to MAC_TABLE and ROUTE_TABLE.
if (c.type() == Criterion.Type.ETH_DST) {
EthCriterion e = (EthCriterion) c;
// Install TMAC flow rule.
log.debug("adding rule for Termination MAC in Filter Table: {}", e.mac());
TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
selector.matchEthDst(e.mac());
// Add IPv4 matching explicitly since we will redirect it to ROUTE Table
// through MAC table.
selector.matchEthType(Ethernet.TYPE_IPV4);
treatment.transition(MAC_TABLE);
FlowRule rule = DefaultFlowRule.builder().forDevice(deviceId).withSelector(selector.build()).withTreatment(treatment.build()).withPriority(FILTER_TABLE_TMAC_PRIORITY).fromApp(applicationId).makePermanent().forTable(FILTER_TABLE).build();
ops = install ? ops.add(rule) : ops.remove(rule);
// Must install another rule to direct the IPv4 packets that hit TMAC to
// Route table.
log.debug("adding rule for Termination MAC in MAC Table: {}", e.mac());
selector = DefaultTrafficSelector.builder();
treatment = DefaultTrafficTreatment.builder();
selector.matchEthDst(e.mac());
// MAC_Table must have metadata matching configured, use the default metadata.
selector.matchMetadata(DEFAULT_METADATA);
treatment.transition(ROUTE_TABLE);
rule = DefaultFlowRule.builder().forDevice(deviceId).withSelector(selector.build()).withTreatment(treatment.build()).withPriority(MAC_TABLE_PRIORITY).fromApp(applicationId).makePermanent().forTable(MAC_TABLE).build();
ops = install ? ops.add(rule) : ops.remove(rule);
} else if (c.type() == Criterion.Type.VLAN_VID) {
VlanIdCriterion v = (VlanIdCriterion) c;
log.debug("adding rule for VLAN: {}", v.vlanId());
TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
selector.matchVlanId(v.vlanId());
selector.matchInPort(p.port());
// Although the accepted packets will be sent to filter table, we must
// explicitly set goto_table instruction here.
treatment.writeMetadata(DEFAULT_METADATA, DEFAULT_METADATA_MASK);
// set default metadata written by PORT_VLAN Table.
treatment.transition(FILTER_TABLE);
// We do not support strip vlan here, treatment.deferred().popVlan();
// PORT_VLAN table only accept 0xffff priority since it does exact match only.
FlowRule rule = DefaultFlowRule.builder().forDevice(deviceId).withSelector(selector.build()).withTreatment(treatment.build()).withPriority(PORT_VLAN_TABLE_PRIORITY).fromApp(applicationId).makePermanent().forTable(PORT_VLAN_TABLE).build();
ops = install ? ops.add(rule) : ops.remove(rule);
} else if (c.type() == Criterion.Type.IPV4_DST) {
IPCriterion ipaddr = (IPCriterion) c;
log.debug("adding IP filtering rules in FILTER table: {}", ipaddr.ip());
TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
selector.matchEthType(Ethernet.TYPE_IPV4);
// router IPs to the controller
selector.matchIPDst(ipaddr.ip());
treatment.setOutput(PortNumber.CONTROLLER);
FlowRule rule = DefaultFlowRule.builder().forDevice(deviceId).withSelector(selector.build()).withTreatment(treatment.build()).withPriority(FILTER_TABLE_CONTROLLER_PRIORITY).fromApp(applicationId).makePermanent().forTable(FILTER_TABLE).build();
ops = install ? ops.add(rule) : ops.remove(rule);
} else {
log.warn("Driver does not currently process filtering condition" + " of type: {}", c.type());
fail(filt, ObjectiveError.UNSUPPORTED);
}
}
// apply filtering flow rules
flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
@Override
public void onSuccess(FlowRuleOperations ops) {
pass(filt);
log.info("Applied filtering rules");
}
@Override
public void onError(FlowRuleOperations ops) {
fail(filt, ObjectiveError.FLOWINSTALLATIONFAILED);
log.info("Failed to apply filtering rules");
}
}));
}
use of org.onosproject.net.flow.criteria.VlanIdCriterion in project fabric-tna by stratum.
the class NextObjectiveTranslator method egressVlan.
private void egressVlan(PortNumber outPort, NextObjective obj, Instruction popVlanInst, ObjectiveTranslation.Builder resultBuilder) throws FabricPipelinerException {
final VlanIdCriterion vlanIdCriterion = (VlanIdCriterion) criterion(obj.meta(), Criterion.Type.VLAN_VID);
final PiCriterion egressVlanTableMatch = PiCriterion.builder().matchExact(P4InfoConstants.HDR_EG_PORT, outPort.toLong()).build();
final TrafficSelector selector = DefaultTrafficSelector.builder().matchPi(egressVlanTableMatch).matchVlanId(vlanIdCriterion.vlanId()).build();
final TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();
if (popVlanInst == null) {
treatmentBuilder.pushVlan();
} else {
treatmentBuilder.popVlan();
}
resultBuilder.addFlowRule(flowRule(obj, P4InfoConstants.FABRIC_EGRESS_EGRESS_NEXT_EGRESS_VLAN, selector, treatmentBuilder.build()));
}
use of org.onosproject.net.flow.criteria.VlanIdCriterion 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