use of org.onosproject.net.flow.criteria.EthCriterion in project onos by opennetworkinglab.
the class Ofdpa3Pipeline 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;
boolean removeDoubleTagged = true;
if (filteringObjective.meta().writeMetadata() != null) {
removeDoubleTagged = shouldRemoveDoubleTagged(filteringObjective.meta().writeMetadata());
}
log.info("HERE , removeDoubleTagged {}", removeDoubleTagged);
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(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())) {
// if metadata instruction not null and not removeDoubleTagged move on.
if ((filteringObjective.meta().writeMetadata() != null) && (!removeDoubleTagged)) {
log.info("Skipping removal of tmac rule for device {}", deviceId);
continue;
} else {
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);
// if context is remove, table is vlan_1 and removeDoubleTagged is false, continue.
if (flowRule.table().equals(IndexTableId.of(VLAN_TABLE)) && !removeDoubleTagged && !install) {
log.info("Skipping removal of vlan table rule for now!");
continue;
}
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.EthCriterion 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.EthCriterion 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.EthCriterion 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.EthCriterion in project onos by opennetworkinglab.
the class IntentCodecTest method decodePointToPointIntent.
/**
* Tests the point to point intent JSON codec.
*
* @throws IOException if JSON processing fails
*/
@Test
public void decodePointToPointIntent() throws IOException {
JsonCodec<Intent> intentCodec = context.codec(Intent.class);
assertThat(intentCodec, notNullValue());
Intent intent = getIntent("PointToPointIntent.json", intentCodec);
assertThat(intent, notNullValue());
assertThat(intent, instanceOf(PointToPointIntent.class));
PointToPointIntent pointIntent = (PointToPointIntent) intent;
assertThat(pointIntent.priority(), is(55));
assertThat(pointIntent.filteredIngressPoint().connectPoint().deviceId(), is(did("0000000000000001")));
assertThat(pointIntent.filteredIngressPoint().connectPoint().port(), is(PortNumber.portNumber(1)));
assertThat(pointIntent.filteredEgressPoint().connectPoint().deviceId(), is(did("0000000000000007")));
assertThat(pointIntent.filteredEgressPoint().connectPoint().port(), is(PortNumber.portNumber(2)));
assertThat(pointIntent.constraints(), hasSize(1));
assertThat(pointIntent.selector(), notNullValue());
assertThat(pointIntent.selector().criteria(), hasSize(1));
Criterion criterion1 = pointIntent.selector().criteria().iterator().next();
assertThat(criterion1, instanceOf(EthCriterion.class));
EthCriterion ethCriterion = (EthCriterion) criterion1;
assertThat(ethCriterion.mac().toString(), is("11:22:33:44:55:66"));
assertThat(ethCriterion.type().name(), is("ETH_DST"));
assertThat(pointIntent.treatment(), notNullValue());
assertThat(pointIntent.treatment().allInstructions(), hasSize(1));
Instruction instruction1 = pointIntent.treatment().allInstructions().iterator().next();
assertThat(instruction1, instanceOf(ModEtherInstruction.class));
ModEtherInstruction ethInstruction = (ModEtherInstruction) instruction1;
assertThat(ethInstruction.mac().toString(), is("22:33:44:55:66:77"));
assertThat(ethInstruction.type().toString(), is("L2MODIFICATION"));
assertThat(ethInstruction.subtype().toString(), is("ETH_SRC"));
}
Aggregations