use of org.onosproject.net.flowobjective.ObjectiveContext in project onos by opennetworkinglab.
the class InOrderFlowObjectiveManager method process.
/**
* Processes given objective on given device.
* Objectives submitted through this method are guaranteed to be executed in order.
*
* @param deviceId Device ID
* @param originalObjective Flow objective to be executed
*/
private void process(DeviceId deviceId, Objective originalObjective) {
// Inject ObjectiveContext such that we can get notified when it is completed
Objective.Builder objBuilder = originalObjective.copy();
Optional<ObjectiveContext> originalContext = originalObjective.context();
ObjectiveContext context = new InOrderObjectiveContext(deviceId, originalContext.orElse(null));
// Preserve Objective.Operation
Objective objective;
switch(originalObjective.op()) {
case ADD:
objective = objBuilder.add(context);
break;
case ADD_TO_EXISTING:
objective = ((NextObjective.Builder) objBuilder).addToExisting(context);
break;
case REMOVE:
objective = objBuilder.remove(context);
break;
case REMOVE_FROM_EXISTING:
objective = ((NextObjective.Builder) objBuilder).removeFromExisting(context);
break;
case MODIFY:
objective = ((NextObjective.Builder) objBuilder).modify(context);
break;
case VERIFY:
objective = ((NextObjective.Builder) objBuilder).verify(context);
break;
default:
log.error("Unknown flow objecitve operation {}", originalObjective.op());
return;
}
enqueue(deviceId, objective);
}
use of org.onosproject.net.flowobjective.ObjectiveContext in project onos by opennetworkinglab.
the class Ofdpa2GroupHandler method addBucketToGroup.
// ////////////////////////////////////
// Group Editing
// ////////////////////////////////////
/**
* Adds a bucket to the top level group of a group-chain, and creates the chain.
* Ensures that bucket being added is not a duplicate, by checking existing
* buckets for the same output port.
*
* @param nextObjective the bucket information for a next group
* @param next the representation of the existing group-chain for this next objective
*/
protected void addBucketToGroup(NextObjective nextObjective, NextGroup next) {
if (nextObjective.type() != NextObjective.Type.HASHED && nextObjective.type() != NextObjective.Type.BROADCAST) {
log.warn("AddBuckets not applied to nextType:{} in dev:{} for next:{}", nextObjective.type(), deviceId, nextObjective.id());
fail(nextObjective, ObjectiveError.UNSUPPORTED);
return;
}
// first check to see if bucket being added is not a duplicate of an
// existing bucket. If it is for an existing output port, then its a
// duplicate.
Set<TrafficTreatment> duplicateBuckets = Sets.newHashSet();
List<Deque<GroupKey>> allActiveKeys = appKryo.deserialize(next.data());
Set<PortNumber> existingPorts = getExistingOutputPorts(allActiveKeys, groupService, deviceId);
Set<TrafficTreatment> nonDuplicateBuckets = Sets.newHashSet();
NextObjective objectiveToAdd;
nextObjective.next().forEach(trafficTreatment -> {
PortNumber portNumber = readOutPortFromTreatment(trafficTreatment);
if (portNumber == null) {
return;
}
if (existingPorts.contains(portNumber)) {
// its possible that portnumbers are same but labels are different
int label = readLabelFromTreatment(trafficTreatment);
if (label == -1) {
duplicateBuckets.add(trafficTreatment);
} else {
List<Integer> existing = existingPortAndLabel(allActiveKeys, groupService, deviceId, portNumber, label);
if (!existing.isEmpty()) {
duplicateBuckets.add(trafficTreatment);
} else {
nonDuplicateBuckets.add(trafficTreatment);
}
}
} else {
nonDuplicateBuckets.add(trafficTreatment);
}
});
if (duplicateBuckets.isEmpty()) {
// use the original objective
objectiveToAdd = nextObjective;
} else if (!nonDuplicateBuckets.isEmpty()) {
// only use the non-duplicate buckets if there are any
log.debug("Some buckets {} already exist in next id {}, duplicate " + "buckets will be ignored.", duplicateBuckets, nextObjective.id());
// new next objective with non duplicate treatments
NextObjective.Builder builder = DefaultNextObjective.builder().withType(nextObjective.type()).withId(nextObjective.id()).withMeta(nextObjective.meta()).fromApp(nextObjective.appId());
nonDuplicateBuckets.forEach(builder::addTreatment);
ObjectiveContext context = nextObjective.context().orElse(null);
objectiveToAdd = builder.addToExisting(context);
} else {
// buckets to add are already there - nothing to do
log.debug("buckets already exist {} in next: {} ..ignoring bucket add", duplicateBuckets, nextObjective.id());
pass(nextObjective);
return;
}
if (nextObjective.type() == NextObjective.Type.HASHED) {
if (isL2Hash(nextObjective)) {
addBucketToL2HashGroup(objectiveToAdd, allActiveKeys);
return;
}
addBucketToEcmpHashGroup(objectiveToAdd, allActiveKeys);
} else if (nextObjective.type() == NextObjective.Type.BROADCAST) {
addBucketToBroadcastGroup(objectiveToAdd, allActiveKeys);
}
}
use of org.onosproject.net.flowobjective.ObjectiveContext in project onos by opennetworkinglab.
the class Dhcp4HandlerImpl method processIgnoreVlanRule.
/**
* Process the ignore rules.
*
* @param deviceId the device id
* @param vlanId the vlan to be ignored
* @param op the operation, ADD to install; REMOVE to uninstall rules
*/
private void processIgnoreVlanRule(DeviceId deviceId, VlanId vlanId, Objective.Operation op) {
AtomicInteger installedCount = new AtomicInteger(DHCP_SELECTORS.size());
DHCP_SELECTORS.forEach(trafficSelector -> {
TrafficSelector selector = DefaultTrafficSelector.builder(trafficSelector).matchVlanId(vlanId).build();
ForwardingObjective.Builder builder = DefaultForwardingObjective.builder().withFlag(ForwardingObjective.Flag.VERSATILE).withSelector(selector).withPriority(IGNORE_CONTROL_PRIORITY).withTreatment(DefaultTrafficTreatment.emptyTreatment()).fromApp(appId);
ObjectiveContext objectiveContext = new ObjectiveContext() {
@Override
public void onSuccess(Objective objective) {
log.info("Ignore rule {} (Vlan id {}, device {}, selector {})", op, vlanId, deviceId, selector);
int countDown = installedCount.decrementAndGet();
if (countDown != 0) {
return;
}
switch(op) {
case ADD:
ignoredVlans.put(deviceId, vlanId);
break;
case REMOVE:
ignoredVlans.remove(deviceId, vlanId);
break;
default:
log.warn("Unsupported objective operation {}", op);
break;
}
}
@Override
public void onError(Objective objective, ObjectiveError error) {
log.warn("Can't {} ignore rule (vlan id {}, selector {}, device {}) due to {}", op, vlanId, selector, deviceId, error);
}
};
ForwardingObjective fwd;
switch(op) {
case ADD:
fwd = builder.add(objectiveContext);
break;
case REMOVE:
fwd = builder.remove(objectiveContext);
break;
default:
log.warn("Unsupported objective operation {}", op);
return;
}
Device device = deviceService.getDevice(deviceId);
if (device == null || !device.is(Pipeliner.class)) {
log.warn("Device {} is not available now, wait until device is available", deviceId);
return;
}
flowObjectiveService.apply(deviceId, fwd);
});
}
use of org.onosproject.net.flowobjective.ObjectiveContext in project onos by opennetworkinglab.
the class Dhcp6HandlerImpl method processIgnoreVlanRule.
/**
* Process the ignore rules.
*
* @param deviceId the device id
* @param vlanId the vlan to be ignored
* @param op the operation, ADD to install; REMOVE to uninstall rules
*/
private void processIgnoreVlanRule(DeviceId deviceId, VlanId vlanId, Objective.Operation op) {
AtomicInteger installedCount = new AtomicInteger(DHCP_SELECTORS.size());
DHCP_SELECTORS.forEach(trafficSelector -> {
TrafficSelector selector = DefaultTrafficSelector.builder(trafficSelector).matchVlanId(vlanId).build();
ForwardingObjective.Builder builder = DefaultForwardingObjective.builder().withFlag(ForwardingObjective.Flag.VERSATILE).withSelector(selector).withPriority(IGNORE_CONTROL_PRIORITY).withTreatment(DefaultTrafficTreatment.emptyTreatment()).fromApp(appId);
ObjectiveContext objectiveContext = new ObjectiveContext() {
@Override
public void onSuccess(Objective objective) {
log.info("Ignore rule {} (Vlan id {}, device {}, selector {})", op, vlanId, deviceId, selector);
int countDown = installedCount.decrementAndGet();
if (countDown != 0) {
return;
}
switch(op) {
case ADD:
ignoredVlans.put(deviceId, vlanId);
break;
case REMOVE:
ignoredVlans.remove(deviceId, vlanId);
break;
default:
log.warn("Unsupported objective operation {}", op);
break;
}
}
@Override
public void onError(Objective objective, ObjectiveError error) {
log.warn("Can't {} ignore rule (vlan id {}, selector {}, device {}) due to {}", op, vlanId, selector, deviceId, error);
}
};
ForwardingObjective fwd;
switch(op) {
case ADD:
fwd = builder.add(objectiveContext);
break;
case REMOVE:
fwd = builder.remove(objectiveContext);
break;
default:
log.warn("Unsupported objective operation {}", op);
return;
}
Device device = deviceService.getDevice(deviceId);
if (device == null || !device.is(Pipeliner.class)) {
log.warn("Device {} is not available now, wait until device is available", deviceId);
return;
}
flowObjectiveService.apply(deviceId, fwd);
});
}
use of org.onosproject.net.flowobjective.ObjectiveContext in project trellis-control by opennetworkinglab.
the class DefaultGroupHandler method processEdgePort.
/**
* Adds or removes a port that has been configured with a vlan to a broadcast group
* for bridging. Should only be called by the instance leading the programming
* for this device.
*
* @param port the port on this device that needs to be added/removed to a bcast group
* @param vlanId the vlan id corresponding to the broadcast domain/group
* @param popVlan indicates if packets should be sent out untagged or not out
* of the port. If true, indicates an access (untagged) or native vlan
* configuration. If false, indicates a trunk (tagged) vlan config.
* @param portUp true if port is enabled, false if disabled
*/
public void processEdgePort(PortNumber port, VlanId vlanId, boolean popVlan, boolean portUp) {
// get the next id for the subnet and edit it.
Integer nextId = getVlanNextObjectiveId(vlanId);
if (nextId == -1) {
if (portUp) {
log.debug("**Creating flooding group for first port enabled in" + " vlan {} on dev {} port {}", vlanId, deviceId, port);
createBcastGroupFromVlan(vlanId, Collections.singleton(port));
} else {
log.warn("Could not find flooding group for subnet {} on dev:{} when" + " removing port:{}", vlanId, deviceId, port);
}
return;
}
log.info("**port{} in device {}: {} Bucket with Port {} to" + " next-id {}", (portUp) ? "UP" : "DOWN", deviceId, (portUp) ? "Adding" : "Removing", port, nextId);
// Create the bucket to be added or removed
TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
if (popVlan) {
tBuilder.popVlan();
}
tBuilder.setOutput(port);
TrafficSelector metadata = DefaultTrafficSelector.builder().matchVlanId(vlanId).build();
NextObjective.Builder nextObjBuilder = DefaultNextObjective.builder().withId(nextId).withType(NextObjective.Type.BROADCAST).fromApp(appId).addTreatment(tBuilder.build()).withMeta(metadata);
ObjectiveContext context = new DefaultObjectiveContext((objective) -> log.debug("port {} successfully {} NextObj {} on {}", port, (portUp) ? "addedTo" : "removedFrom", nextId, deviceId), (objective, error) -> {
log.warn("port {} failed to {} NextObj {} on {}: {}", port, (portUp) ? "addTo" : "removeFrom", nextId, deviceId, error);
srManager.invalidateNextObj(objective.id());
});
NextObjective nextObj = (portUp) ? nextObjBuilder.addToExisting(context) : nextObjBuilder.removeFromExisting(context);
log.debug("edgePort processed: Submited next objective {} in device {}", nextId, deviceId);
flowObjectiveService.next(deviceId, nextObj);
}
Aggregations