use of org.onosproject.segmentrouting.policy.api.Policy in project trellis-control by opennetworkinglab.
the class PolicyManager method removeTrafficMatchInDevice.
// Traffic match removal in a device
private void removeTrafficMatchInDevice(DeviceId deviceId, TrafficMatch trafficMatch) {
if (log.isDebugEnabled()) {
log.debug("Removing traffic match {} associated to policy {}", trafficMatch.trafficMatchId(), trafficMatch.policyId());
}
TrafficMatchKey trafficMatchKey = new TrafficMatchKey(deviceId, trafficMatch.trafficMatchId());
Operation operation = Versioned.valueOrNull(operations.get(trafficMatchKey.toString()));
if (operation == null || operation.objectiveOperation() == null) {
log.warn("There are no ops associated with {}", trafficMatchKey);
operation = Operation.builder().isDone(true).isInstall(false).trafficMatch(trafficMatch).build();
operations.put(trafficMatchKey.toString(), operation);
} else if (!operation.isInstall()) {
if (log.isDebugEnabled()) {
log.debug("There is already an uninstall operation for traffic match {} associated to policy {}" + " for device {}", trafficMatch.trafficMatchId(), trafficMatch.policyId(), deviceId);
}
} else {
ForwardingObjective oldObj = (ForwardingObjective) operation.objectiveOperation();
operation = Operation.builder(operation).isInstall(false).build();
operations.put(trafficMatchKey.toString(), operation);
ForwardingObjective.Builder builder = DefaultForwardingObjective.builder(oldObj);
CompletableFuture<Objective> future = new CompletableFuture<>();
if (log.isDebugEnabled()) {
log.debug("Removing forwarding objectives for dev: {}", deviceId);
}
ObjectiveContext context = new DefaultObjectiveContext((objective) -> {
if (log.isDebugEnabled()) {
log.debug("Forwarding objective for policy {} removed", trafficMatch.policyId());
}
future.complete(objective);
}, (objective, error) -> {
log.warn("Failed to remove forwarding objective for policy {}: {}", trafficMatch.policyId(), error);
future.complete(null);
});
ForwardingObjective serializableObjective = builder.remove();
flowObjectiveService.forward(deviceId, builder.remove(context));
future.whenComplete((objective, ex) -> {
if (ex != null) {
log.error("Exception removing forwarding objective", ex);
} else if (objective != null) {
operations.computeIfPresent(trafficMatchKey.toString(), (k, v) -> {
if (!v.isDone() && !v.isInstall()) {
v.isDone(true);
v.objectiveOperation(serializableObjective);
}
return v;
});
}
});
}
}
use of org.onosproject.segmentrouting.policy.api.Policy in project trellis-control by opennetworkinglab.
the class PolicyManager method installTrafficMatchToDevice.
// Orchestrate traffic match installation according to the type
private void installTrafficMatchToDevice(DeviceId deviceId, TrafficMatch trafficMatch) {
if (log.isDebugEnabled()) {
log.debug("Installing traffic match {} associated to policy {}", trafficMatch.trafficMatchId(), trafficMatch.policyId());
}
TrafficMatchKey trafficMatchKey = new TrafficMatchKey(deviceId, trafficMatch.trafficMatchId());
Operation oldTrafficOperation = Versioned.valueOrNull(operations.get(trafficMatchKey.toString()));
if (oldTrafficOperation != null && oldTrafficOperation.isInstall()) {
if (trafficMatch.equals(oldTrafficOperation.trafficMatch().orElse(null))) {
if (log.isDebugEnabled()) {
log.debug("There is already an install operation for traffic match {} associated to policy {} " + "for device {}", trafficMatch.trafficMatchId(), trafficMatch.policyId(), deviceId);
}
// If we add or submit a trafficMatch multiple times
// We skip the installation and update the state directly
updateTrafficMatch(trafficMatch, true);
return;
} else {
if (log.isDebugEnabled()) {
log.debug("Starts updating traffic match {} associated to policy {} " + "for device {}", trafficMatch.trafficMatchId(), trafficMatch.policyId(), deviceId);
}
}
}
// For the DROP policy we need to set an ACL drop in the fwd objective. The other
// policies require to retrieve the next Id and sets the next step.
PolicyKey policyKey = new PolicyKey(deviceId, trafficMatch.policyId());
Operation policyOperation = Versioned.valueOrNull(operations.get(policyKey.toString()));
if (policyOperation == null || !policyOperation.isDone() || !policyOperation.isInstall() || policyOperation.policy().isEmpty() || (policyOperation.policy().get().policyType() == PolicyType.REDIRECT && policyOperation.objectiveOperation() == null)) {
log.info("Deferring traffic match {} installation on device {}. Policy {} not yet installed", trafficMatch.trafficMatchId(), deviceId, trafficMatch.policyId());
return;
}
// Updates the store and then send the versatile fwd objective to the pipeliner
Operation newTrafficOperation = Operation.builder().isInstall(true).trafficMatch(trafficMatch).build();
operations.put(trafficMatchKey.toString(), newTrafficOperation);
Policy policy = policyOperation.policy().get();
ForwardingObjective.Builder builder = trafficMatchFwdObjective(trafficMatch, policy.policyType());
if (policy.policyType() == PolicyType.DROP) {
// Firstly builds the fwd objective with the wipeDeferred action.
TrafficTreatment dropTreatment = DefaultTrafficTreatment.builder().wipeDeferred().build();
builder.withTreatment(dropTreatment);
} else if (policy.policyType() == PolicyType.REDIRECT) {
// Here we need to set only the next step
builder.nextStep(policyOperation.objectiveOperation().id());
}
// Once, the fwd objective has completed its execution, we update the policiesOps map
CompletableFuture<Objective> addNewFuture = new CompletableFuture<>();
CompletableFuture<Objective> removeOldFuture = new CompletableFuture<>();
if (log.isDebugEnabled()) {
log.debug("Installing forwarding objective for dev: {}", deviceId);
}
ObjectiveContext addNewContext = new DefaultObjectiveContext((objective) -> {
if (log.isDebugEnabled()) {
log.debug("Forwarding objective for policy {} installed", trafficMatch.policyId());
}
addNewFuture.complete(objective);
}, (objective, error) -> {
log.warn("Failed to install forwarding objective for policy {}: {}", trafficMatch.policyId(), error);
addNewFuture.complete(null);
});
ObjectiveContext removeOldContext = new DefaultObjectiveContext((objective) -> {
if (log.isDebugEnabled()) {
log.debug("Old forwarding objective for policy {} removed, update finished", trafficMatch.policyId());
}
removeOldFuture.complete(objective);
}, (objective, error) -> {
log.warn("Failed to remove old forwarding objective for policy {}: {}", trafficMatch.policyId(), error);
removeOldFuture.complete(null);
});
// Context is not serializable
ForwardingObjective serializableObjective = builder.add();
flowObjectiveService.forward(deviceId, builder.add(addNewContext));
addNewFuture.whenComplete((objective, ex) -> {
if (ex != null) {
log.error("Exception installing forwarding objective", ex);
} else if (objective != null) {
// base on priority, selector and metadata change
if (oldTrafficOperation != null && oldTrafficOperation.objectiveOperation() != null && oldTrafficOperation.isInstall() && (oldTrafficOperation.objectiveOperation().priority() != serializableObjective.priority() || !((ForwardingObjective) oldTrafficOperation.objectiveOperation()).selector().equals(serializableObjective.selector()) || !((ForwardingObjective) oldTrafficOperation.objectiveOperation()).meta().equals(serializableObjective.meta()))) {
ForwardingObjective oldFwdObj = (ForwardingObjective) oldTrafficOperation.objectiveOperation();
ForwardingObjective.Builder oldBuilder = DefaultForwardingObjective.builder(oldFwdObj);
flowObjectiveService.forward(deviceId, oldBuilder.remove(removeOldContext));
} else {
operations.computeIfPresent(trafficMatchKey.toString(), (k, v) -> {
if (!v.isDone() && v.isInstall()) {
v.isDone(true);
v.objectiveOperation(serializableObjective);
}
return v;
});
}
}
});
removeOldFuture.whenComplete((objective, ex) -> {
if (ex != null) {
log.error("Exception removing old forwarding objective", ex);
} else if (objective != null) {
operations.computeIfPresent(trafficMatchKey.toString(), (k, v) -> {
if (!v.isDone() && v.isInstall()) {
v.isDone(true);
v.objectiveOperation(serializableObjective);
}
return v;
});
}
});
}
use of org.onosproject.segmentrouting.policy.api.Policy in project trellis-control by opennetworkinglab.
the class PolicyManager method redirectPolicyNextObjective.
private NextObjective.Builder redirectPolicyNextObjective(DeviceId srcDevice, RedirectPolicy redirectPolicy) {
Set<Link> egressLinks = linkService.getDeviceEgressLinks(srcDevice);
Map<ConnectPoint, DeviceId> egressPortsToEnforce = Maps.newHashMap();
List<DeviceId> edgeDevices = getEdgeDeviceIds();
egressLinks.stream().filter(link -> redirectPolicy.spinesToEnforce().contains(link.dst().deviceId()) && !edgeDevices.contains(link.dst().deviceId())).forEach(link -> egressPortsToEnforce.put(link.src(), link.dst().deviceId()));
// No ports no friend
if (egressPortsToEnforce.isEmpty()) {
log.warn("There are no port available for the REDIRECT policy {}", redirectPolicy.policyId());
return null;
}
// We need to add a treatment for each valid egress port. The treatment
// requires to set src and dst mac address and set the egress port. We are
// deliberately not providing the metadata to prevent the programming of
// some tables which are already controlled by SegmentRouting or are unnecessary
int nextId = flowObjectiveService.allocateNextId();
DefaultNextObjective.Builder builder = DefaultNextObjective.builder().withId(nextId).withType(NextObjective.Type.HASHED).fromApp(appId);
MacAddress srcDeviceMac;
try {
srcDeviceMac = getDeviceMacAddress(srcDevice);
} catch (DeviceConfigNotFoundException e) {
log.warn(e.getMessage() + " Aborting installation REDIRECT policy {}", redirectPolicy.policyId());
return null;
}
MacAddress neigborDeviceMac;
TrafficTreatment.Builder tBuilder;
for (Map.Entry<ConnectPoint, DeviceId> entry : egressPortsToEnforce.entrySet()) {
try {
neigborDeviceMac = getDeviceMacAddress(entry.getValue());
} catch (DeviceConfigNotFoundException e) {
log.warn(e.getMessage() + " Aborting installation REDIRECT policy {}", redirectPolicy.policyId());
return null;
}
tBuilder = DefaultTrafficTreatment.builder().setEthSrc(srcDeviceMac).setEthDst(neigborDeviceMac).setOutput(entry.getKey().port());
builder.addTreatment(tBuilder.build());
}
return builder;
}
use of org.onosproject.segmentrouting.policy.api.Policy in project trellis-control by opennetworkinglab.
the class PolicyManager method removePolicyInDevice.
// Remove policy in a device according to the type
private void removePolicyInDevice(DeviceId deviceId, Policy policy) {
PolicyKey policyKey = new PolicyKey(deviceId, policy.policyId());
Operation operation = Versioned.valueOrNull(operations.get(policyKey.toString()));
// Policy might be still in pending or not present anymore
if (operation == null || operation.objectiveOperation() == null) {
log.warn("There are no ops associated with {}", policyKey);
operation = Operation.builder().isDone(true).isInstall(false).policy(policy).build();
operations.put(policyKey.toString(), operation);
} else {
if (log.isDebugEnabled()) {
log.debug("Removing {} policy {} in device {}", policy.policyType(), policy.policyId(), deviceId);
}
Operation.Builder operationBuilder = Operation.builder().isInstall(false).policy(policy);
if (policy.policyType() == PolicyType.DROP) {
operationBuilder.isDone(true);
operations.put(policyKey.toString(), operationBuilder.build());
} else if (policy.policyType() == PolicyType.REDIRECT) {
// REDIRECT has to remove the next objective first
NextObjective oldObj = (NextObjective) operation.objectiveOperation();
operations.put(policyKey.toString(), operationBuilder.build());
NextObjective.Builder builder = oldObj.copy();
CompletableFuture<Objective> future = new CompletableFuture<>();
if (log.isDebugEnabled()) {
log.debug("Removing REDIRECT next objective for dev: {}", deviceId);
}
ObjectiveContext context = new DefaultObjectiveContext((objective) -> {
if (log.isDebugEnabled()) {
log.debug("REDIRECT next objective for policy {} removed in dev: {}", policy.policyId(), deviceId);
}
future.complete(objective);
}, (objective, error) -> {
log.warn("Failed to remove REDIRECT next objective for policy {}: {} in dev: {}", policy.policyId(), error, deviceId);
future.complete(null);
});
NextObjective serializableObjective = builder.remove();
flowObjectiveService.next(deviceId, builder.remove(context));
future.whenComplete((objective, ex) -> {
if (ex != null) {
log.error("Exception Removing REDIRECT next objective", ex);
} else if (objective != null) {
operations.computeIfPresent(policyKey.toString(), (k, v) -> {
if (!v.isDone() && !v.isInstall()) {
v.isDone(true);
v.objectiveOperation(serializableObjective);
}
return v;
});
}
});
}
}
}
use of org.onosproject.segmentrouting.policy.api.Policy in project trellis-control by opennetworkinglab.
the class PolicyManager method installPolicyInDevice.
// Orchestrate policy installation according to the type
private void installPolicyInDevice(DeviceId deviceId, Policy policy) {
if (!SUPPORTED_POLICIES.contains(policy.policyType())) {
log.warn("Policy {} type {} not yet supported", policy.policyId(), policy.policyType());
return;
}
PolicyKey policyKey;
Operation.Builder operation;
if (log.isDebugEnabled()) {
log.debug("Installing {} policy {} for dev: {}", policy.policyType(), policy.policyId(), deviceId);
}
policyKey = new PolicyKey(deviceId, policy.policyId());
// Prevent duplicate installation of the policies. With the current
// implementation is not possible to update a policy since a change
// in the params will create a new policy. Thus, there is no need to
// check the equality like we do for the TM
Operation oldPolicyOp = Versioned.valueOrNull(operations.get(policyKey.toString()));
if (oldPolicyOp != null && oldPolicyOp.isInstall()) {
if (log.isDebugEnabled()) {
log.debug("There is already an install operation for policy {}", policy.policyId());
}
// If we add or submit a policy multiple times
// We skip the installation update the policy state directly
updatePolicy(policy.policyId(), true);
return;
}
operation = Operation.builder().isInstall(true).policy(policy);
// TODO To better handle different policy types consider the abstraction of a compiler (subtypes ?)
if (policy.policyType() == PolicyType.DROP) {
// DROP policies do not need the next objective installation phase
// we can update directly the map and signal the ops as done
operation.isDone(true);
operations.put(policyKey.toString(), operation.build());
} else if (policy.policyType() == PolicyType.REDIRECT) {
// REDIRECT Uses next objective context to update the ops as done when
// it returns successfully. In the other cases leaves the ops as undone
// and the relative policy will remain in pending.
operations.put(policyKey.toString(), operation.build());
NextObjective.Builder builder = redirectPolicyNextObjective(deviceId, (RedirectPolicy) policy);
// Handle error here - leave the operation as undone and pending
if (builder != null) {
CompletableFuture<Objective> future = new CompletableFuture<>();
if (log.isDebugEnabled()) {
log.debug("Installing REDIRECT next objective for dev: {}", deviceId);
}
ObjectiveContext context = new DefaultObjectiveContext((objective) -> {
if (log.isDebugEnabled()) {
log.debug("REDIRECT next objective for policy {} installed in dev: {}", policy.policyId(), deviceId);
}
future.complete(objective);
}, (objective, error) -> {
log.warn("Failed to install REDIRECT next objective for policy {}: {} in dev: {}", policy.policyId(), error, deviceId);
future.complete(null);
});
// Context is not serializable
NextObjective serializableObjective = builder.add();
flowObjectiveService.next(deviceId, builder.add(context));
future.whenComplete((objective, ex) -> {
if (ex != null) {
log.error("Exception installing REDIRECT next objective", ex);
} else if (objective != null) {
operations.computeIfPresent(policyKey.toString(), (k, v) -> {
if (!v.isDone() && v.isInstall()) {
v.isDone(true);
v.objectiveOperation(serializableObjective);
}
return v;
});
}
});
}
}
}
Aggregations