use of org.onosproject.net.flow.FlowRuleOperations 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.FlowRuleOperations in project onos by opennetworkinglab.
the class OvsOfdpaPipeline method initTableMiss.
/**
* Install table-miss flow entry.
*
* If treatment exists, use it directly.
* Else if treatment does not exist but nextTable > 0, transit to next table.
* Else apply empty treatment.
*
* @param thisTable this table ID
* @param nextTable next table ID
* @param treatment traffic treatment to apply.
*/
private void initTableMiss(int thisTable, int nextTable, TrafficTreatment treatment) {
FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
TrafficSelector selector = DefaultTrafficSelector.builder().build();
if (treatment == null) {
TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
if (nextTable > 0) {
tBuilder.transition(nextTable);
}
treatment = tBuilder.build();
}
FlowRule rule = DefaultFlowRule.builder().forDevice(deviceId).withSelector(selector).withTreatment(treatment).withPriority(LOWEST_PRIORITY).fromApp(driverId).makePermanent().forTable(thisTable).build();
ops = ops.add(rule);
flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
@Override
public void onSuccess(FlowRuleOperations ops) {
log.info("Initialized table {} on {}", thisTable, deviceId);
}
@Override
public void onError(FlowRuleOperations ops) {
log.warn("Failed to initialize table {} on {}", thisTable, deviceId);
}
}));
}
use of org.onosproject.net.flow.FlowRuleOperations in project onos by opennetworkinglab.
the class OvsOfdpaPipeline method initPuntTable.
/**
* Install lldp/bbdp matching rules at table PUNT_TABLE
* that forward traffic to controller.
*/
private void initPuntTable() {
FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
TrafficTreatment treatment = DefaultTrafficTreatment.builder().punt().build();
// Add punt rule for LLDP and BDDP
TrafficSelector.Builder lldpSelector = DefaultTrafficSelector.builder();
lldpSelector.matchEthType(EthType.EtherType.LLDP.ethType().toShort());
FlowRule lldpRule = DefaultFlowRule.builder().forDevice(deviceId).withSelector(lldpSelector.build()).withTreatment(treatment).withPriority(HIGHEST_PRIORITY).fromApp(driverId).makePermanent().forTable(PUNT_TABLE).build();
ops = ops.add(lldpRule);
TrafficSelector.Builder bbdpSelector = DefaultTrafficSelector.builder();
bbdpSelector.matchEthType(EthType.EtherType.BDDP.ethType().toShort());
FlowRule bbdpRule = DefaultFlowRule.builder().forDevice(deviceId).withSelector(bbdpSelector.build()).withTreatment(treatment).withPriority(HIGHEST_PRIORITY).fromApp(driverId).makePermanent().forTable(PUNT_TABLE).build();
ops.add(bbdpRule);
flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
@Override
public void onSuccess(FlowRuleOperations ops) {
log.info("Initialized table {} on {}", PUNT_TABLE, deviceId);
}
@Override
public void onError(FlowRuleOperations ops) {
log.warn("Failed to initialize table {} on {}", PUNT_TABLE, deviceId);
}
}));
}
use of org.onosproject.net.flow.FlowRuleOperations in project onos by opennetworkinglab.
the class FlowRuleIntentInstaller method reallocate.
private void reallocate(IntentOperationContext<FlowRuleIntent> context) {
Optional<IntentData> toUninstall = context.toUninstall();
Optional<IntentData> toInstall = context.toInstall();
// TODO: Update the Intent store with this information
toInstall.get().setState(REALLOCATING);
store.write(toInstall.get());
List<FlowRuleIntent> uninstallIntents = Lists.newArrayList(context.intentsToUninstall());
List<FlowRuleIntent> installIntents = Lists.newArrayList(context.intentsToInstall());
FlowRuleOperations.Builder firstStageOperationsBuilder = FlowRuleOperations.builder();
List<FlowRule> secondStageFlowRules = Lists.newArrayList();
FlowRuleOperations.Builder thirdStageOperationsBuilder = FlowRuleOperations.builder();
FlowRuleOperations.Builder finalStageOperationsBuilder = FlowRuleOperations.builder();
prepareReallocation(uninstallIntents, installIntents, firstStageOperationsBuilder, secondStageFlowRules, thirdStageOperationsBuilder, finalStageOperationsBuilder);
trackIntentResources(toUninstall.get(), uninstallIntents, REMOVE);
trackIntentResources(toInstall.get(), installIntents, ADD);
CountDownLatch stageCompleteLatch = new CountDownLatch(1);
FlowRuleOperations firstStageOperations = firstStageOperationsBuilder.build(new StageOperation(context, stageCompleteLatch));
flowRuleService.apply(firstStageOperations);
try {
stageCompleteLatch.await(nonDisruptiveInstallationWaitingTime, TimeUnit.SECONDS);
if (isReallocationStageFailed) {
log.error("Reallocation FAILED in stage one: the following FlowRuleOperations are not executed {}", firstStageOperations);
return;
} else {
log.debug("Reallocation stage one completed");
}
} catch (Exception e) {
log.warn("Latch exception in the reallocation stage one");
}
for (FlowRule flowRule : secondStageFlowRules) {
stageCompleteLatch = new CountDownLatch(1);
FlowRuleOperations operations = FlowRuleOperations.builder().newStage().remove(flowRule).build(new StageOperation(context, stageCompleteLatch));
nonDisruptiveIntentInstaller.schedule(new NonDisruptiveInstallation(operations), nonDisruptiveInstallationWaitingTime, TimeUnit.SECONDS);
try {
stageCompleteLatch.await(nonDisruptiveInstallationWaitingTime, TimeUnit.SECONDS);
if (isReallocationStageFailed) {
log.error("Reallocation FAILED in stage two: " + "the following FlowRuleOperations are not executed {}", operations);
return;
} else {
log.debug("Reallocation stage two completed");
}
} catch (Exception e) {
log.warn("Latch exception in the reallocation stage two");
}
}
stageCompleteLatch = new CountDownLatch(1);
FlowRuleOperations thirdStageOperations = thirdStageOperationsBuilder.build(new StageOperation(context, stageCompleteLatch));
nonDisruptiveIntentInstaller.schedule(new NonDisruptiveInstallation(thirdStageOperations), nonDisruptiveInstallationWaitingTime, TimeUnit.SECONDS);
try {
stageCompleteLatch.await(nonDisruptiveInstallationWaitingTime, TimeUnit.SECONDS);
if (isReallocationStageFailed) {
log.error("Reallocation FAILED in stage three: " + "the following FlowRuleOperations are not executed {}", thirdStageOperations);
return;
} else {
log.debug("Reallocation stage three completed");
}
} catch (Exception e) {
log.warn("Latch exception in the reallocation stage three");
}
FlowRuleOperationsContext flowRuleOperationsContext = new FlowRuleOperationsContext() {
@Override
public void onSuccess(FlowRuleOperations ops) {
intentInstallCoordinator.intentInstallSuccess(context);
log.info("Non-disruptive reallocation completed for intent {}", toInstall.get().key());
}
@Override
public void onError(FlowRuleOperations ops) {
intentInstallCoordinator.intentInstallFailed(context);
}
};
FlowRuleOperations finalStageOperations = finalStageOperationsBuilder.build(flowRuleOperationsContext);
flowRuleService.apply(finalStageOperations);
}
use of org.onosproject.net.flow.FlowRuleOperations in project onos by opennetworkinglab.
the class FlowRuleIntentInstaller method apply.
@Override
public void apply(IntentOperationContext<FlowRuleIntent> context) {
Optional<IntentData> toUninstall = context.toUninstall();
Optional<IntentData> toInstall = context.toInstall();
if (toInstall.isPresent() && toUninstall.isPresent()) {
Intent intentToInstall = toInstall.get().intent();
if (requireNonDisruptive(intentToInstall) && INSTALLED.equals(toUninstall.get().state())) {
reallocate(context);
return;
}
}
if (!toInstall.isPresent() && !toUninstall.isPresent()) {
// Nothing to do.
intentInstallCoordinator.intentInstallSuccess(context);
return;
}
List<FlowRuleIntent> uninstallIntents = context.intentsToUninstall();
List<FlowRuleIntent> installIntents = context.intentsToInstall();
List<FlowRule> flowRulesToUninstall;
List<FlowRule> flowRulesToInstall;
if (toUninstall.isPresent()) {
// Remove tracked resource from both Intent and installable Intents.
trackIntentResources(toUninstall.get(), uninstallIntents, REMOVE);
// Retrieves all flow rules from all flow rule Intents.
flowRulesToUninstall = uninstallIntents.stream().map(FlowRuleIntent::flowRules).flatMap(Collection::stream).filter(flowRule -> flowRuleService.getFlowEntry(flowRule) != null).collect(Collectors.toList());
} else {
// No flow rules to be uninstalled.
flowRulesToUninstall = Collections.emptyList();
}
if (toInstall.isPresent()) {
// Track resource from both Intent and installable Intents.
trackIntentResources(toInstall.get(), installIntents, ADD);
// Retrieves all flow rules from all flow rule Intents.
flowRulesToInstall = installIntents.stream().map(FlowRuleIntent::flowRules).flatMap(Collection::stream).collect(Collectors.toList());
} else {
// No flow rules to be installed.
flowRulesToInstall = Collections.emptyList();
}
List<FlowRule> flowRuleToModify;
List<FlowRule> dontTouch;
// If both uninstall/install list contained equal (=match conditions are equal) FlowRules,
// omit it from remove list, since it will/should be overwritten by install
flowRuleToModify = flowRulesToInstall.stream().filter(flowRule -> flowRulesToUninstall.stream().anyMatch(flowRule::equals)).collect(Collectors.toList());
// If both contained exactMatch-ing FlowRules, remove from both list,
// since it will result in no-op.
dontTouch = flowRulesToInstall.stream().filter(flowRule -> flowRulesToUninstall.stream().anyMatch(flowRule::exactMatch)).collect(Collectors.toList());
flowRulesToUninstall.removeAll(flowRuleToModify);
flowRulesToUninstall.removeAll(dontTouch);
flowRulesToInstall.removeAll(flowRuleToModify);
flowRulesToInstall.removeAll(dontTouch);
flowRuleToModify.removeAll(dontTouch);
if (flowRulesToInstall.isEmpty() && flowRulesToUninstall.isEmpty() && flowRuleToModify.isEmpty()) {
// There is no flow rules to install/uninstall
intentInstallCoordinator.intentInstallSuccess(context);
return;
}
FlowRuleOperations.Builder builder = FlowRuleOperations.builder();
// Add flows
flowRulesToInstall.forEach(builder::add);
// Modify flows
flowRuleToModify.forEach(builder::modify);
// Remove flows
flowRulesToUninstall.forEach(builder::remove);
FlowRuleOperationsContext flowRuleOperationsContext = new FlowRuleOperationsContext() {
@Override
public void onSuccess(FlowRuleOperations ops) {
intentInstallCoordinator.intentInstallSuccess(context);
}
@Override
public void onError(FlowRuleOperations ops) {
intentInstallCoordinator.intentInstallFailed(context);
}
};
FlowRuleOperations operations = builder.build(flowRuleOperationsContext);
log.debug("applying intent {} -> {} with {} rules: {}", toUninstall.map(x -> x.key().toString()).orElse("<empty>"), toInstall.map(x -> x.key().toString()).orElse("<empty>"), operations.stages().stream().mapToLong(Set::size).sum(), operations.stages());
flowRuleService.apply(operations);
}
Aggregations