use of org.onosproject.segmentrouting.pwaas.L2TunnelHandler.Result in project trellis-control by opennetworkinglab.
the class DefaultL2TunnelHandler method deployPseudowire.
/**
* Adds a single pseudowire.
*
* @param pw The pseudowire to deploy
* @return result of pseudowire deployment
*/
public Result deployPseudowire(L2TunnelDescription pw) {
try {
// take the lock
pwLock.lock();
Result result;
long l2TunnelId;
log.debug("Pseudowire with {} deployment started, check log for any errors in this process!", pw.l2Tunnel().tunnelId());
l2TunnelId = pw.l2Tunnel().tunnelId();
// The tunnel id cannot be 0.
if (l2TunnelId == 0) {
log.warn("Tunnel id id must be > 0 in {}", l2TunnelId);
return Result.WRONG_PARAMETERS.appendError("Tunnel id id must be > 0");
}
result = verifyGlobalValidity(pw);
if (result != SUCCESS) {
log.error("Global validity for pseudowire {} is wrong!", l2TunnelId);
return result;
}
// leafSpinePw determines if this is a leaf-leaf
// or leaf-spine pseudowire
boolean leafSpinePw;
ConnectPoint cp1 = pw.l2TunnelPolicy().cP1();
ConnectPoint cp2 = pw.l2TunnelPolicy().cP2();
try {
// differentiate between leaf-leaf pseudowires and leaf-spine
if (!srManager.deviceConfiguration().isEdgeDevice(cp1.deviceId()) && !srManager.deviceConfiguration().isEdgeDevice(cp2.deviceId())) {
log.error("Can not deploy pseudowire {} from spine to spine!", l2TunnelId);
return Result.WRONG_PARAMETERS.appendError("Can not deploy pseudowire from spine to spine!");
} else if (srManager.deviceConfiguration().isEdgeDevice(cp1.deviceId()) && srManager.deviceConfiguration().isEdgeDevice(cp2.deviceId())) {
leafSpinePw = false;
} else {
leafSpinePw = true;
}
} catch (DeviceConfigNotFoundException e) {
log.error("Device for pseudowire {} connection points does not exist in the configuration", l2TunnelId);
return Result.INTERNAL_ERROR.appendError("Device for pseudowire connection points does not exist in the configuration");
}
// reverse the policy in order for leaf switch to be at CP1
// this will help us for re-using SRLinkWeigher for computing valid paths
L2TunnelPolicy reversedPolicy = reverseL2TunnelPolicy(pw.l2TunnelPolicy());
if (reversedPolicy == null) {
log.error("Error in reversing policy, device configuration was not found for pseudowire {}.", l2TunnelId);
return INTERNAL_ERROR.appendError("Device configuration not found when reversing the policy.");
}
pw.setL2TunnelPolicy(reversedPolicy);
// get path here, need to use the same for fwd and rev direction
List<Link> path = getPath(pw.l2TunnelPolicy().cP1(), pw.l2TunnelPolicy().cP2());
if (path == null || path.isEmpty()) {
log.error("Deploying process : No path between the connection points for pseudowire {}", l2TunnelId);
return PATH_NOT_FOUND.appendError("No path between the connection points for pseudowire!");
}
Link fwdNextHop;
Link revNextHop;
if (!isValidPath(path, leafSpinePw)) {
log.error("Deploying process : Path for pseudowire {} is not valid", l2TunnelId);
return INTERNAL_ERROR.appendError("Internal error : path for pseudowire is not valid!");
}
// oneHope flag is used to determine if we need to
// install transit mpls rules
boolean oneHop = true;
if (path.size() > 1) {
oneHop = false;
}
fwdNextHop = path.get(0);
revNextHop = reverseLink(path.get(path.size() - 1));
pw.l2Tunnel().setPath(path);
pw.l2Tunnel().setTransportVlan(srManager.getPwTransportVlan());
// next hops for next objectives
log.info("Deploying process : Establishing forward direction for pseudowire {}", l2TunnelId);
VlanId egressVlan = determineEgressVlan(pw.l2TunnelPolicy().cP1OuterTag(), pw.l2TunnelPolicy().cP1InnerTag(), pw.l2TunnelPolicy().cP2OuterTag(), pw.l2TunnelPolicy().cP2InnerTag());
result = deployPseudoWireInit(pw.l2Tunnel(), pw.l2TunnelPolicy().cP1(), pw.l2TunnelPolicy().cP2(), FWD, fwdNextHop, oneHop, egressVlan);
if (result != SUCCESS) {
log.error("Deploying process : Error in deploying pseudowire {} initiation for CP1", l2TunnelId);
return Result.INTERNAL_ERROR.appendError("Error in deploying pseudowire initiation for CP1");
}
result = deployPolicy(l2TunnelId, pw.l2TunnelPolicy().cP1(), pw.l2TunnelPolicy().cP1InnerTag(), pw.l2TunnelPolicy().cP1OuterTag(), egressVlan, result.getNextId());
if (result != SUCCESS) {
log.error("Deploying process : Error in deploying pseudowire {} policy for CP1", l2TunnelId);
return Result.INTERNAL_ERROR.appendError("Error in deploying pseudowire policy for CP1");
}
result = deployPseudoWireTerm(pw.l2Tunnel(), pw.l2TunnelPolicy().cP2(), egressVlan, FWD, oneHop);
if (result != SUCCESS) {
log.error("Deploying process : Error in deploying pseudowire {} termination for CP1", l2TunnelId);
return Result.INTERNAL_ERROR.appendError("Error in deploying pseudowire termination for CP1");
}
// We establish the reverse tunnel.
log.info("Deploying process : Establishing reverse direction for pseudowire {}", l2TunnelId);
egressVlan = determineEgressVlan(pw.l2TunnelPolicy().cP2OuterTag(), pw.l2TunnelPolicy().cP2InnerTag(), pw.l2TunnelPolicy().cP1OuterTag(), pw.l2TunnelPolicy().cP1InnerTag());
result = deployPseudoWireInit(pw.l2Tunnel(), pw.l2TunnelPolicy().cP2(), pw.l2TunnelPolicy().cP1(), REV, revNextHop, oneHop, egressVlan);
if (result != SUCCESS) {
log.error("Deploying process : Error in deploying pseudowire {} initiation for CP2", l2TunnelId);
return Result.INTERNAL_ERROR.appendError("Error in deploying pseudowire initiation for CP2");
}
result = deployPolicy(l2TunnelId, pw.l2TunnelPolicy().cP2(), pw.l2TunnelPolicy().cP2InnerTag(), pw.l2TunnelPolicy().cP2OuterTag(), egressVlan, result.getNextId());
if (result != SUCCESS) {
log.error("Deploying process : Error in deploying policy {} for CP2", l2TunnelId);
return Result.INTERNAL_ERROR.appendError("Deploying process : Error in deploying policy for CP2");
}
result = deployPseudoWireTerm(pw.l2Tunnel(), pw.l2TunnelPolicy().cP1(), egressVlan, REV, oneHop);
if (result != SUCCESS) {
log.error("Deploying process : Error in deploying pseudowire {} termination for CP2", l2TunnelId);
return Result.INTERNAL_ERROR.appendError("Error in deploying pseudowire termination for CP2");
}
log.info("Deploying process : Updating relevant information for pseudowire {}", l2TunnelId);
// Populate stores as the final step of the process
l2TunnelStore.put(Long.toString(l2TunnelId), pw.l2Tunnel());
l2PolicyStore.put(Long.toString(l2TunnelId), pw.l2TunnelPolicy());
return Result.SUCCESS;
} catch (StorageException.Timeout e) {
log.error("Can not acquire distributed lock for pseudowire {}!", pw.l2Tunnel().tunnelId());
return Result.INTERNAL_ERROR.appendError("Can not acquire distributed lock!");
} finally {
// release the lock
pwLock.unlock();
}
}
use of org.onosproject.segmentrouting.pwaas.L2TunnelHandler.Result in project trellis-control by opennetworkinglab.
the class DefaultL2TunnelHandler method deployPseudoWireInit.
/**
* Handles the tunnel establishment which consists in
* create the next objectives related to the initiation.
*
* @param l2Tunnel the tunnel to deploy
* @param ingress the ingress connect point
* @param egress the egress connect point
* @param direction the direction of the pw
* @param nextHop next hop of the initiation point
* @param oneHop if this pseudowire has only one link
* @param termVlanId the termination vlan id
* @return the result of the operation
*/
private Result deployPseudoWireInit(L2Tunnel l2Tunnel, ConnectPoint ingress, ConnectPoint egress, Direction direction, Link nextHop, boolean oneHop, VlanId termVlanId) {
log.debug("Started deploying init next objectives for pseudowire {} for tunnel {} -> {}.", l2Tunnel.tunnelId(), ingress, egress);
if (nextHop == null) {
log.warn("No path between ingress and egress connection points for tunnel {}", l2Tunnel.tunnelId());
return WRONG_PARAMETERS;
}
// We create the next objective without the metadata
// context and id. We check if it already exists in the
// store. If not we store as it is in the store.
NextObjective.Builder nextObjectiveBuilder = createNextObjective(INITIATION, nextHop.src(), nextHop.dst(), l2Tunnel, egress.deviceId(), oneHop, termVlanId);
if (nextObjectiveBuilder == null) {
return INTERNAL_ERROR;
}
// We set the metadata. We will use this metadata
// to inform the driver we are doing a l2 tunnel.
TrafficSelector metadata = DefaultTrafficSelector.builder().matchTunnelId(l2Tunnel.tunnelId()).build();
nextObjectiveBuilder.withMeta(metadata);
int nextId = srManager.flowObjectiveService.allocateNextId();
if (nextId < 0) {
log.warn("Not able to allocate a next id for initiation");
return INTERNAL_ERROR;
}
nextObjectiveBuilder.withId(nextId);
String key = generateKey(l2Tunnel.tunnelId(), direction);
l2InitiationNextObjStore.put(key, nextObjectiveBuilder.add());
ObjectiveContext context = new DefaultObjectiveContext((objective) -> log.debug("Initiation l2 tunnel rule for {} populated", l2Tunnel.tunnelId()), (objective, error) -> {
log.warn("Failed to populate Initiation l2 tunnel rule for {}: {}", l2Tunnel.tunnelId(), error);
srManager.invalidateNextObj(objective.id());
});
NextObjective nextObjective = nextObjectiveBuilder.add(context);
srManager.flowObjectiveService.next(ingress.deviceId(), nextObjective);
log.debug("Initiation next objective for {} not found. Creating new NextObj with id={}", l2Tunnel.tunnelId(), nextObjective.id());
Result result = SUCCESS;
result.setNextId(nextObjective.id());
return result;
}
use of org.onosproject.segmentrouting.pwaas.L2TunnelHandler.Result in project trellis-control by opennetworkinglab.
the class DefaultL2TunnelHandler method tearDown.
@Override
@Deprecated
public void tearDown(Set<L2TunnelDescription> pwToRemove) {
for (L2TunnelDescription currentL2Tunnel : pwToRemove) {
long tunnelId = currentL2Tunnel.l2TunnelPolicy().tunnelId();
log.info("Removing pseudowire {}", tunnelId);
Result result = tearDownPseudowire(tunnelId);
if (result != Result.SUCCESS) {
log.error("Could not remove pseudowire {}!", tunnelId);
}
}
}
use of org.onosproject.segmentrouting.pwaas.L2TunnelHandler.Result in project trellis-control by opennetworkinglab.
the class DefaultL2TunnelHandler method deployPseudoWireTerm.
/**
* Handles the tunnel termination, which consists in the creation
* of a forwarding objective and a next objective.
*
* @param l2Tunnel the tunnel to terminate
* @param egress the egress point
* @param egressVlan the expected vlan at egress
* @param direction the direction
* @return the result of the operation
*/
private Result deployPseudoWireTerm(L2Tunnel l2Tunnel, ConnectPoint egress, VlanId egressVlan, Direction direction, boolean oneHop) {
log.debug("Started deploying termination objectives for pseudowire {} , direction {}.", l2Tunnel.tunnelId(), direction == FWD ? "forward" : "reverse");
// We create the group relative to the termination.
NextObjective.Builder nextObjectiveBuilder = createNextObjective(TERMINATION, egress, null, l2Tunnel, egress.deviceId(), oneHop, egressVlan);
if (nextObjectiveBuilder == null) {
return INTERNAL_ERROR;
}
TrafficSelector metadata = DefaultTrafficSelector.builder().matchVlanId(egressVlan).build();
nextObjectiveBuilder.withMeta(metadata);
int nextId = srManager.flowObjectiveService.allocateNextId();
if (nextId < 0) {
log.warn("Not able to allocate a next id for initiation");
return INTERNAL_ERROR;
}
nextObjectiveBuilder.withId(nextId);
String key = generateKey(l2Tunnel.tunnelId(), direction);
l2TerminationNextObjStore.put(key, nextObjectiveBuilder.add());
ObjectiveContext context = new DefaultObjectiveContext((objective) -> log.debug("Termination l2 tunnel rule for {} populated", l2Tunnel.tunnelId()), (objective, error) -> {
log.warn("Failed to populate termination l2 tunnel rule for {}: {}", l2Tunnel.tunnelId(), error);
srManager.invalidateNextObj(objective.id());
});
NextObjective nextObjective = nextObjectiveBuilder.add(context);
srManager.flowObjectiveService.next(egress.deviceId(), nextObjective);
log.debug("Termination next objective for {} not found. Creating new NextObj with id={}", l2Tunnel.tunnelId(), nextObjective.id());
// We create the flow relative to the termination.
ForwardingObjective.Builder fwdBuilder = createTermFwdObjective(l2Tunnel.pwLabel(), l2Tunnel.tunnelId(), egress.port(), nextObjective.id());
context = new DefaultObjectiveContext((objective) -> log.debug("FwdObj for tunnel termination {} populated", l2Tunnel.tunnelId()), (objective, error) -> log.warn("Failed to populate fwdrObj" + " for tunnel termination {} : {}", l2Tunnel.tunnelId(), error));
srManager.flowObjectiveService.forward(egress.deviceId(), fwdBuilder.add(context));
log.debug("Creating new FwdObj for termination NextObj with id={} for tunnel {}", nextId, l2Tunnel.tunnelId());
return SUCCESS;
}
use of org.onosproject.segmentrouting.pwaas.L2TunnelHandler.Result in project trellis-control by opennetworkinglab.
the class DefaultL2TunnelHandler method tearDownConnectionPoints.
/**
* Tears down connection points of pseudowires. We can either tear down both connection points,
* or each one of them.
*
* @param l2TunnelId The tunnel id for this pseudowire.
* @param tearDownFirst Boolean, true if we want to tear down cp1
* @param tearDownSecond Boolean, true if we want to tear down cp2
* @param pending Boolean, if true remove only pseudowire from pending stores since no flows/groups
* in the network, else remove flows/groups in the devices also.
* @return Result of tearing down the pseudowire, SUCCESS if everything was ok
* a descriptive error otherwise.
*/
private Result tearDownConnectionPoints(long l2TunnelId, boolean tearDownFirst, boolean tearDownSecond, boolean pending) {
Result res;
CompletableFuture<ObjectiveError> fwdInitNextFuture = new CompletableFuture<>();
CompletableFuture<ObjectiveError> fwdTermNextFuture = new CompletableFuture<>();
CompletableFuture<ObjectiveError> revInitNextFuture = new CompletableFuture<>();
CompletableFuture<ObjectiveError> revTermNextFuture = new CompletableFuture<>();
if (l2TunnelId == 0) {
log.error("Removal process : Tunnel id cannot be 0");
return Result.WRONG_PARAMETERS.appendError("Pseudowire id can not be 0.");
}
res = checkIfPwExists(l2TunnelId, pending);
if (res != Result.SUCCESS) {
return res;
}
// remove and get the tunnel and the policy from the appropriate store
// if null, return error.
Versioned<L2Tunnel> l2TunnelVersioned = pending ? pendingL2TunnelStore.remove(Long.toString(l2TunnelId)) : l2TunnelStore.remove(Long.toString(l2TunnelId));
Versioned<L2TunnelPolicy> l2TunnelPolicyVersioned = pending ? pendingL2PolicyStore.remove(Long.toString(l2TunnelId)) : l2PolicyStore.remove(Long.toString(l2TunnelId));
if ((l2TunnelVersioned == null) || (l2TunnelPolicyVersioned == null)) {
log.warn("Removal process : Policy and/or tunnel missing for tunnel id {}", l2TunnelId);
return Result.INTERNAL_ERROR.appendError("Policy and/or tunnel missing for pseudowire!");
}
L2TunnelDescription pwToRemove = new DefaultL2TunnelDescription(l2TunnelVersioned.value(), l2TunnelPolicyVersioned.value());
if (pending) {
// in pending state
return Result.SUCCESS;
}
// remove flows/groups involving with this pseudowire
if (tearDownFirst) {
log.info("Removal process : Tearing down forward direction of pseudowire {}", l2TunnelId);
VlanId egressVlan = determineEgressVlan(pwToRemove.l2TunnelPolicy().cP1OuterTag(), pwToRemove.l2TunnelPolicy().cP1InnerTag(), pwToRemove.l2TunnelPolicy().cP2OuterTag(), pwToRemove.l2TunnelPolicy().cP2InnerTag());
deletePolicy(l2TunnelId, pwToRemove.l2TunnelPolicy().cP1(), pwToRemove.l2TunnelPolicy().cP1InnerTag(), pwToRemove.l2TunnelPolicy().cP1OuterTag(), egressVlan, fwdInitNextFuture, FWD);
fwdInitNextFuture.thenAcceptAsync(status -> {
if (status == null) {
// Finally we will tear down the pseudo wire.
tearDownPseudoWireInit(l2TunnelId, pwToRemove.l2TunnelPolicy().cP1(), fwdTermNextFuture, FWD);
}
});
fwdTermNextFuture.thenAcceptAsync(status -> {
if (status == null) {
tearDownPseudoWireTerm(pwToRemove.l2Tunnel(), pwToRemove.l2TunnelPolicy().cP2(), null, FWD);
}
});
}
if (tearDownSecond) {
log.info("Removal process : Tearing down reverse direction of pseudowire {}", l2TunnelId);
VlanId egressVlan = determineEgressVlan(pwToRemove.l2TunnelPolicy().cP2OuterTag(), pwToRemove.l2TunnelPolicy().cP2InnerTag(), pwToRemove.l2TunnelPolicy().cP1OuterTag(), pwToRemove.l2TunnelPolicy().cP1InnerTag());
// We do the same operations on the reverse side.
deletePolicy(l2TunnelId, pwToRemove.l2TunnelPolicy().cP2(), pwToRemove.l2TunnelPolicy().cP2InnerTag(), pwToRemove.l2TunnelPolicy().cP2OuterTag(), egressVlan, revInitNextFuture, REV);
revInitNextFuture.thenAcceptAsync(status -> {
if (status == null) {
tearDownPseudoWireInit(l2TunnelId, pwToRemove.l2TunnelPolicy().cP2(), revTermNextFuture, REV);
}
});
revTermNextFuture.thenAcceptAsync(status -> {
if (status == null) {
tearDownPseudoWireTerm(pwToRemove.l2Tunnel(), pwToRemove.l2TunnelPolicy().cP1(), null, REV);
}
});
}
return Result.SUCCESS;
}
Aggregations