use of org.onosproject.segmentrouting.config.DeviceConfigNotFoundException 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.config.DeviceConfigNotFoundException in project trellis-control by opennetworkinglab.
the class DefaultL2TunnelHandler method isValidPath.
/**
* Returns true if path is valid according to the current logic.
* For example : leaf to spine pseudowires can be either leaf-spine or
* leaf-spine-spine. However, in the configuration we might specify spine device
* first which will result in spine-spine-leaf. If leafSpinePw == true we have one of these
* two cases and need to provision for them.
*
* If we have a leaf to leaf pseudowire then all the intermediate devices must
* be spines. However, in case of paired switches we can have two leafs interconnected
* with each other directly.
*
* @param path the chosen path
* @param leafSpinePw if it is a leaf to spine pseudowire
* @return True if path size is valid, false otherwise.
*/
private boolean isValidPath(List<Link> path, boolean leafSpinePw) {
log.debug("Checking path validity for pseudowire.");
List<DeviceId> devices = getDevicesOnPath(path);
if (devices.size() < 2) {
log.error("Path size for pseudowire should be greater than 1!");
return false;
}
try {
if (leafSpinePw) {
// can either be leaf-spine-spine or leaf-spine
// first device is leaf, all other must be spines
log.debug("Devices on path are {} for leaf to spine pseudowire", devices);
// if first device is a leaf then all other must be spines
if (srManager.deviceConfiguration().isEdgeDevice(devices.get(0))) {
devices.remove(0);
for (DeviceId devId : devices) {
log.debug("Device {} should be a spine!", devId);
if (srManager.deviceConfiguration().isEdgeDevice(devId)) {
return false;
}
}
} else {
// all other devices must be spines
if (!srManager.deviceConfiguration().isEdgeDevice(devices.get(devices.size() - 1))) {
return false;
}
devices.remove(devices.size() - 1);
for (DeviceId devId : devices) {
log.debug("Device {} should be a spine!", devId);
if (srManager.deviceConfiguration().isEdgeDevice(devId)) {
return false;
}
}
}
} else {
// can either be leaf-leaf (paired leafs) / leaf-spine-leaf
// or leaf-spine-spine-leaf
log.debug("Devices on path are {} for leaf to leaf pseudowire", devices);
// check first device, needs to be a leaf
if (!srManager.deviceConfiguration().isEdgeDevice(devices.get(0))) {
return false;
}
// check last device, needs to be a leaf
if (!srManager.deviceConfiguration().isEdgeDevice(devices.get(devices.size() - 1))) {
return false;
}
// remove these devices, rest must all be spines
devices.remove(0);
devices.remove(devices.size() - 1);
for (DeviceId devId : devices) {
log.debug("Device {} should be a spine!", devId);
if (srManager.deviceConfiguration().isEdgeDevice(devId)) {
return false;
}
}
}
} catch (DeviceConfigNotFoundException e) {
log.error("Device not found in configuration : {}", e);
return false;
}
return true;
}
use of org.onosproject.segmentrouting.config.DeviceConfigNotFoundException in project trellis-control by opennetworkinglab.
the class DefaultL2TunnelHandler method createNextObjective.
/**
* Creates the next objective according to a given
* pipeline. We don't set the next id and we don't
* create the final meta to check if we are re-using
* the same next objective for different tunnels.
*
* @param pipeline the pipeline to support
* @param srcCp the source port
* @param dstCp the destination port
* @param l2Tunnel the tunnel to support
* @param egressId the egress device id
* @param oneHop if the pw only has one hop, push only pw label
* @param termVlanId the outer vlan id of the packet exiting a termination point
* @return the next objective to support the pipeline
*/
private NextObjective.Builder createNextObjective(Pipeline pipeline, ConnectPoint srcCp, ConnectPoint dstCp, L2Tunnel l2Tunnel, DeviceId egressId, boolean oneHop, VlanId termVlanId) {
log.debug("Creating {} next objective for pseudowire {}.", pipeline == TERMINATION ? "termination" : "inititation");
NextObjective.Builder nextObjBuilder;
TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();
if (pipeline == INITIATION) {
nextObjBuilder = DefaultNextObjective.builder().withType(NextObjective.Type.SIMPLE).fromApp(srManager.appId());
// be different -1.
if (l2Tunnel.pwLabel().toInt() == MplsLabel.MAX_MPLS) {
log.error("Pw label not configured");
return null;
}
treatmentBuilder.pushMpls();
treatmentBuilder.setMpls(l2Tunnel.pwLabel());
treatmentBuilder.setMplsBos(true);
treatmentBuilder.copyTtlOut();
// If the inter-co label is present we have to set the label.
if (l2Tunnel.interCoLabel().toInt() != MplsLabel.MAX_MPLS) {
treatmentBuilder.pushMpls();
treatmentBuilder.setMpls(l2Tunnel.interCoLabel());
treatmentBuilder.setMplsBos(false);
treatmentBuilder.copyTtlOut();
}
// if not oneHop install transit mpls labels also
if (!oneHop) {
// We retrieve the sr label from the config
// specific for pseudowire traffic
// using the egress leaf device id.
MplsLabel srLabel;
try {
srLabel = MplsLabel.mplsLabel(srManager.deviceConfiguration().getPWRoutingLabel(egressId));
} catch (DeviceConfigNotFoundException e) {
log.error("Sr label for pw traffic not configured");
return null;
}
treatmentBuilder.pushMpls();
treatmentBuilder.setMpls(srLabel);
treatmentBuilder.setMplsBos(false);
treatmentBuilder.copyTtlOut();
}
// We have to rewrite the src and dst mac address.
MacAddress ingressMac;
try {
ingressMac = srManager.deviceConfiguration().getDeviceMac(srcCp.deviceId());
} catch (DeviceConfigNotFoundException e) {
log.error("Was not able to find the ingress mac");
return null;
}
treatmentBuilder.setEthSrc(ingressMac);
MacAddress neighborMac;
try {
neighborMac = srManager.deviceConfiguration().getDeviceMac(dstCp.deviceId());
} catch (DeviceConfigNotFoundException e) {
log.error("Was not able to find the neighbor mac");
return null;
}
treatmentBuilder.setEthDst(neighborMac);
// set the appropriate transport vlan from tunnel information
treatmentBuilder.setVlanId(l2Tunnel.transportVlan());
} else {
// We create the next objective which
// will be a simple l2 group.
nextObjBuilder = DefaultNextObjective.builder().withType(NextObjective.Type.SIMPLE).fromApp(srManager.appId());
// for termination point we use the outer vlan of the
// encapsulated packet for the vlan
treatmentBuilder.setVlanId(termVlanId);
}
treatmentBuilder.setOutput(srcCp.port());
nextObjBuilder.addTreatment(treatmentBuilder.build());
return nextObjBuilder;
}
use of org.onosproject.segmentrouting.config.DeviceConfigNotFoundException in project trellis-control by opennetworkinglab.
the class DefaultGroupHandler method getMacVlanNextObjectiveId.
/**
* Returns the next objective of type simple associated with the mac/vlan on the
* device, given the treatment. Different treatments to the same mac/vlan result
* in different next objectives. If no such objective exists, this method
* creates one (if requested) and returns the id. Optionally metadata can be passed in for
* the creation of the objective. Typically this is used for L2 and L3 forwarding
* to compute nodes and containers/VMs on the compute nodes directly attached
* to the switch.
*
* @param macAddr the mac addr for the simple next objective
* @param vlanId the vlan for the simple next objective
* @param port port with which to create the Next Obj.
* @param createIfMissing true if a next object should be created if not found
* @return int if found or created, -1 if there are errors during the
* creation of the next objective.
*/
public int getMacVlanNextObjectiveId(MacAddress macAddr, VlanId vlanId, PortNumber port, boolean createIfMissing) {
Integer nextId = macVlanNextObjStore.get(new MacVlanNextObjectiveStoreKey(deviceId, macAddr, vlanId));
if (nextId != null) {
return nextId;
}
log.debug("getMacVlanNextObjectiveId in device {}: Next objective id " + "not found for host : {}/{} .. {}", deviceId, macAddr, vlanId, (createIfMissing) ? "creating" : "aborting");
if (!createIfMissing) {
return -1;
}
MacAddress deviceMac;
try {
deviceMac = deviceConfig.getDeviceMac(deviceId);
} catch (DeviceConfigNotFoundException e) {
log.warn(e.getMessage() + " in getMacVlanNextObjectiveId");
return -1;
}
// since we are creating now, port cannot be null
if (port == null) {
log.debug("getMacVlanNextObjectiveId : port information cannot be null " + "for device {}, host {}/{}", deviceId, macAddr, vlanId);
return -1;
}
TrafficSelector.Builder meta = DefaultTrafficSelector.builder();
TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
treatment.deferred().setEthDst(macAddr).setEthSrc(deviceMac).setOutput(port);
ConnectPoint connectPoint = new ConnectPoint(deviceId, port);
VlanId untaggedVlan = srManager.interfaceService.getUntaggedVlanId(connectPoint);
Set<VlanId> taggedVlans = srManager.interfaceService.getTaggedVlanId(connectPoint);
VlanId nativeVlan = srManager.interfaceService.getNativeVlanId(connectPoint);
// Adjust the meta according to VLAN configuration
if (taggedVlans.contains(vlanId)) {
meta.matchVlanId(vlanId);
treatment.setVlanId(vlanId);
} else if (vlanId.equals(VlanId.NONE)) {
if (untaggedVlan != null) {
meta.matchVlanId(untaggedVlan);
treatment.popVlan();
} else if (nativeVlan != null) {
meta.matchVlanId(nativeVlan);
treatment.popVlan();
} else {
log.warn("Untagged nexthop {}/{} is not allowed on {} without untagged or native vlan", macAddr, vlanId, connectPoint);
return -1;
}
} else {
log.warn("Tagged nexthop {}/{} is not allowed on {} without VLAN listed" + " in tagged vlan", macAddr, vlanId, connectPoint);
return -1;
}
/* create missing next objective */
nextId = createGroupFromMacVlan(macAddr, vlanId, treatment.build(), meta.build());
if (nextId == null) {
log.warn("getMacVlanNextObjectiveId: unable to create next obj" + "for dev:{} host:{}/{}", deviceId, macAddr, vlanId);
return -1;
}
return nextId;
}
use of org.onosproject.segmentrouting.config.DeviceConfigNotFoundException in project trellis-control by opennetworkinglab.
the class RoutingRulePopulator method populateIpRulesForRouter.
/**
* Populates IP flow rules for a set of IP prefix in the target device.
* The prefix are reachable via destination device(s).
*
* @param targetSw target device ID to set the rules
* @param subnets the set of IP prefix
* @param destSw1 destination switch where the prefixes are reachable
* @param destSw2 paired destination switch if one exists for the subnets/prefixes.
* Should be null if there is no paired destination switch (by config)
* or if the given prefixes are reachable only via destSw1
* @param nextHops map of destination switches and their next-hops.
* Should only contain destination switches that are
* actually meant to be routed to. If destSw2 is null, there
* should not be an entry for destSw2 in this map.
* @return true if all rules are set successfully, false otherwise
*/
private boolean populateIpRulesForRouter(DeviceId targetSw, Set<IpPrefix> subnets, DeviceId destSw1, DeviceId destSw2, Map<DeviceId, Set<DeviceId>> nextHops) {
// pre-compute the needed information
int segmentIdIPv41, segmentIdIPv42 = -1;
int segmentIdIPv61, segmentIdIPv62 = -1;
TrafficTreatment treatment = null;
DestinationSet dsIPv4, dsIPv6;
TrafficSelector metaIpv4Selector, metaIpv6Selector = null;
int nextIdIPv4, nextIdIPv6, nextId;
TrafficSelector selector;
// start with MPLS SIDs
try {
segmentIdIPv41 = config.getIPv4SegmentId(destSw1);
segmentIdIPv61 = config.getIPv6SegmentId(destSw1);
if (destSw2 != null) {
segmentIdIPv42 = config.getIPv4SegmentId(destSw2);
segmentIdIPv62 = config.getIPv6SegmentId(destSw2);
}
} catch (DeviceConfigNotFoundException e) {
log.warn(e.getMessage() + " Aborting populateIpRuleForRouter.");
return false;
}
// build the IPv4 and IPv6 destination set
if (destSw2 == null) {
// single dst - create destination set based on next-hop
// If the next hop is the same as the final destination, then MPLS
// label is not set.
Set<DeviceId> nhd1 = nextHops.get(destSw1);
if (nhd1.size() == 1 && nhd1.iterator().next().equals(destSw1)) {
dsIPv4 = DestinationSet.createTypePushNone(destSw1);
dsIPv6 = DestinationSet.createTypePushNone(destSw1);
treatment = DefaultTrafficTreatment.builder().immediate().decNwTtl().build();
} else {
dsIPv4 = DestinationSet.createTypePushBos(segmentIdIPv41, destSw1);
dsIPv6 = DestinationSet.createTypePushBos(segmentIdIPv61, destSw1);
}
} else {
// dst pair - IP rules for dst-pairs are always from other edge nodes
// the destination set needs to have both destinations, even if there
// are no next hops to one of them
dsIPv4 = DestinationSet.createTypePushBos(segmentIdIPv41, destSw1, segmentIdIPv42, destSw2);
dsIPv6 = DestinationSet.createTypePushBos(segmentIdIPv61, destSw1, segmentIdIPv62, destSw2);
}
// setup metadata to pass to nextObjective - indicate the vlan on egress
// if needed by the switch pipeline. Since neighbor sets are always to
// other neighboring routers, there is no subnet assigned on those ports.
metaIpv4Selector = buildIpv4Selector().matchVlanId(srManager.getDefaultInternalVlan()).build();
metaIpv6Selector = buildIpv6Selector().matchVlanId(srManager.getDefaultInternalVlan()).build();
// get the group handler of the target switch
DefaultGroupHandler grpHandler = srManager.getGroupHandler(targetSw);
if (grpHandler == null) {
log.warn("populateIPRuleForRouter: groupHandler for device {} " + "not found", targetSw);
return false;
}
// get next id
nextIdIPv4 = grpHandler.getNextObjectiveId(dsIPv4, nextHops, metaIpv4Selector, false);
if (nextIdIPv4 <= 0) {
log.warn("No next objective in {} for ds: {}", targetSw, dsIPv4);
return false;
}
nextIdIPv6 = grpHandler.getNextObjectiveId(dsIPv6, nextHops, metaIpv6Selector, false);
if (nextIdIPv6 <= 0) {
log.warn("No next objective in {} for ds: {}", targetSw, dsIPv6);
return false;
}
// build all the flow rules and send to the device
for (IpPrefix subnet : subnets) {
selector = buildIpSelectorFromIpPrefix(subnet).build();
if (subnet.isIp4()) {
nextId = nextIdIPv4;
} else {
nextId = nextIdIPv6;
}
ForwardingObjective.Builder fwdBuilder = DefaultForwardingObjective.builder().fromApp(srManager.appId).makePermanent().nextStep(nextId).withSelector(selector).withPriority(getPriorityFromPrefix(subnet)).withFlag(ForwardingObjective.Flag.SPECIFIC);
if (treatment != null) {
fwdBuilder.withTreatment(treatment);
}
log.debug("Installing {} forwarding objective for router IP/subnet {} " + "in switch {} with nextId: {}", subnet.isIp4() ? "IPv4" : "IPv6", subnet, targetSw, nextId);
ObjectiveContext context = new DefaultObjectiveContext((objective) -> log.debug("IP rule for router {} populated in dev:{}", subnet, targetSw), (objective, error) -> log.warn("Failed to populate IP rule for router {}: {} in dev:{}", subnet, error, targetSw));
srManager.flowObjectiveService.forward(targetSw, fwdBuilder.add(context));
}
rulePopulationCounter.addAndGet(subnets.size());
return true;
}
Aggregations