use of org.onosproject.net.Link in project trellis-control by opennetworkinglab.
the class McastHandler method initInternal.
private void initInternal() {
srManager.multicastRouteService.getRoutes().forEach(mcastRoute -> {
lastMcastChange.set(Instant.now());
log.debug("Init group {}", mcastRoute.group());
if (!mcastUtils.isLeader(mcastRoute.group())) {
log.debug("Skip {} due to lack of leadership", mcastRoute.group());
return;
}
McastRouteData mcastRouteData = srManager.multicastRouteService.routeData(mcastRoute);
// For each source process the mcast tree
srManager.multicastRouteService.sources(mcastRoute).forEach(source -> {
McastPathStoreKey pathStoreKey = new McastPathStoreKey(mcastRoute.group(), source);
Collection<? extends List<Link>> storedPaths = Versioned.valueOrElse(mcastPathStore.get(pathStoreKey), Lists.newArrayList());
Map<ConnectPoint, List<ConnectPoint>> mcastPaths = buildMcastPaths(storedPaths, mcastRoute.group(), source);
// Get all the sinks and process them
Set<ConnectPoint> sinks = processSinksToBeAdded(source, mcastRoute.group(), mcastRouteData.sinks());
// Filter out all the working sinks, we do not want to move them
// TODO we need a better way to distinguish flows coming from different sources
sinks = sinks.stream().filter(sink -> !mcastPaths.containsKey(sink) || !isSinkForSource(mcastRoute.group(), sink, source)).collect(Collectors.toSet());
if (sinks.isEmpty()) {
log.debug("Skip {} for source {} nothing to do", mcastRoute.group(), source);
return;
}
Map<ConnectPoint, List<Path>> mcasTree = mcastUtils.computeSinkMcastTree(mcastRoute.group(), source.deviceId(), sinks);
mcasTree.forEach((sink, paths) -> processSinkAddedInternal(source, sink, mcastRoute.group(), null));
});
});
}
use of org.onosproject.net.Link in project trellis-control by opennetworkinglab.
the class DefaultGroupHandler method retryHash.
/**
* Checks all groups in the src-device of link for neighbor sets that include
* the dst-device of link, and edits the hash groups according to link up
* or down. Should only be called by the instance leading the programming of
* the src-switch of link. Typically used when there are no route-path
* changes due to the link up or down, as the ECMPspg does not change.
*
* @param link the infrastructure link that has gone down or come up
* @param linkDown true if link has gone down
* @param firstTime true if link has come up for the first time i.e a link
* not seen-before
*/
public void retryHash(Link link, boolean linkDown, boolean firstTime) {
MacAddress neighborMac;
try {
neighborMac = deviceConfig.getDeviceMac(link.dst().deviceId());
} catch (DeviceConfigNotFoundException e) {
log.warn(e.getMessage() + " Aborting retryHash.");
return;
}
// find all the destinationSets related to link
Set<DestinationSetNextObjectiveStoreKey> dsKeySet = dsNextObjStore.entrySet().stream().filter(entry -> entry.getKey().deviceId().equals(deviceId)).filter(entry -> !entry.getKey().destinationSet().notBos() || (entry.getKey().destinationSet().notBos() && srManager.getMplsEcmp())).filter(entry -> !entry.getKey().destinationSet().swap() || (entry.getKey().destinationSet().swap() && srManager.getMplsEcmp())).filter(entry -> entry.getValue().containsNextHop(link.dst().deviceId())).map(entry -> entry.getKey()).collect(Collectors.toSet());
log.debug("retryHash: dsNextObjStore contents for linkSrc {} -> linkDst {}: {}", deviceId, link.dst().deviceId(), dsKeySet);
for (DestinationSetNextObjectiveStoreKey dsKey : dsKeySet) {
NextNeighbors nextHops = dsNextObjStore.get(dsKey);
if (nextHops == null) {
log.warn("retryHash in device {}, but global store has no record " + "for dsKey:{}", deviceId, dsKey);
continue;
}
int nextId = nextHops.nextId();
Set<DeviceId> dstSet = nextHops.getDstForNextHop(link.dst().deviceId());
if (!linkDown) {
List<PortLabel> pl = Lists.newArrayList();
if (firstTime) {
// to the same hash group are avoided by the driver.
for (PortNumber p : devicePortMap.get(link.dst().deviceId())) {
dstSet.forEach(dst -> {
int edgeLabel = dsKey.destinationSet().getEdgeLabel(dst);
pl.add(new PortLabel(p, edgeLabel, popVlanInHashGroup(dsKey.destinationSet())));
});
}
addToHashedNextObjective(pl, neighborMac, nextId);
} else {
// handle only the port that came up
dstSet.forEach(dst -> {
int edgeLabel = dsKey.destinationSet().getEdgeLabel(dst);
pl.add(new PortLabel(link.src().port(), edgeLabel, popVlanInHashGroup(dsKey.destinationSet())));
});
addToHashedNextObjective(pl, neighborMac, nextId);
}
} else {
// linkdown
List<PortLabel> pl = Lists.newArrayList();
dstSet.forEach(dst -> {
int edgeLabel = dsKey.destinationSet().getEdgeLabel(dst);
pl.add(new PortLabel(link.src().port(), edgeLabel, popVlanInHashGroup(dsKey.destinationSet())));
});
removeFromHashedNextObjective(pl, neighborMac, nextId);
}
}
}
use of org.onosproject.net.Link in project trellis-control by opennetworkinglab.
the class LinkHandler method updateHostPorts.
/**
* Administratively enables or disables edge ports if the link that was
* added or removed was the only uplink port from an edge device. Edge ports
* that belong to dual-homed hosts are always processed. In addition,
* single-homed host ports are optionally processed depending on the
* singleHomedDown property.
*
* @param link the link to be processed
* @param added true if link was added, false if link was removed
*/
private void updateHostPorts(Link link, boolean added) {
// Topology has only a single pair of leaves
if (srManager.getInfraDeviceIds().isEmpty()) {
log.debug("No spine configured. Not updating edge port for {} {}", link, added ? "add" : "remove");
return;
}
DeviceConfiguration devConfig = srManager.deviceConfiguration;
if (added) {
try {
if (!devConfig.isEdgeDevice(link.src().deviceId()) || devConfig.isEdgeDevice(link.dst().deviceId())) {
return;
}
} catch (DeviceConfigNotFoundException e) {
log.warn("Unable to determine if link is a valid uplink" + e.getMessage());
}
// re-enable previously disabled ports on this edge-device if any
Set<PortNumber> p = downedPortStore.remove(link.src().deviceId());
if (p != null) {
log.warn("Link src {} --> dst {} added is an edge-device uplink, " + "enabling dual homed ports if any: {}", link.src().deviceId(), link.dst().deviceId(), (p.isEmpty()) ? "no ports" : p);
p.forEach(pnum -> srManager.deviceAdminService.changePortState(link.src().deviceId(), pnum, true));
}
} else {
// If the device does not have a pair device - skip
DeviceId dev = link.src().deviceId();
if (getPairDeviceIdOrNull(dev) == null) {
log.info("Device {} does not have pair device " + "not disabling access port", dev);
return;
}
// Verify if last uplink
if (!lastUplink(link)) {
return;
}
// find dual homed hosts on this dev to disable
Set<PortNumber> dp = srManager.hostHandler.getDualHomedHostPorts(dev);
log.warn("Link src {} --> dst {} removed was the last uplink, " + "disabling dual homed ports: {}", dev, link.dst().deviceId(), (dp.isEmpty()) ? "no ports" : dp);
dp.forEach(pnum -> srManager.deviceAdminService.changePortState(dev, pnum, false));
if (srManager.singleHomedDown) {
// get all configured ports and down them if they haven't already
// been downed
srManager.deviceService.getPorts(dev).stream().filter(p -> p.isEnabled() && !dp.contains(p.number())).filter(p -> srManager.interfaceService.isConfigured(new ConnectPoint(dev, p.number()))).filter(p -> !srManager.deviceConfiguration.isPairLocalPort(dev, p.number())).forEach(p -> {
log.warn("Last uplink gone src {} -> dst {} .. removing " + "configured port {}", p.number());
srManager.deviceAdminService.changePortState(dev, p.number(), false);
dp.add(p.number());
});
}
if (!dp.isEmpty()) {
// update global store
Set<PortNumber> p = downedPortStore.get(dev);
if (p == null) {
p = dp;
} else {
p.addAll(dp);
}
downedPortStore.put(link.src().deviceId(), p);
}
}
}
use of org.onosproject.net.Link in project trellis-control by opennetworkinglab.
the class LinkHandler method getBidiComponentLinks.
/**
* Returns the component unidirectional links of a declared bidirectional
* link, by consulting the seen-links store. Caller is responsible for
* previously verifying bidirectionality. Returned list may be empty if
* errors are encountered.
*
* @param link the declared bidirectional link
* @return list of component unidirectional links
*/
List<Link> getBidiComponentLinks(Link link) {
Link reverseLink = getReverseLink(link);
List<Link> componentLinks;
if (reverseLink == null) {
// really should not happen if link is bidi
log.error("cannot find reverse link for given link: {} ... is it " + "bi-directional?", link);
componentLinks = ImmutableList.of();
} else {
componentLinks = ImmutableList.of(reverseLink, link);
}
return componentLinks;
}
use of org.onosproject.net.Link in project trellis-control by opennetworkinglab.
the class LinkHandler method isBidirectionalLinkDown.
/**
* Returns true if the link being queried is a bidirectional link that is
* down. A bidi-link is defined as a component unidirectional link, whose
* reverse link - i.e the component unidirectional link in the reverse
* direction - has been seen before and is down. It is necessary for the
* reverse-link to have been previously seen.
*
* @param link the infrastructure (unidirectional) link being queried
* @return true if another unidirectional link exists in the reverse
* direction, has been seen-before and is down
*/
boolean isBidirectionalLinkDown(Link link) {
// cannot call linkService as link may be gone
Link reverseLink = getReverseLink(link);
if (reverseLink == null) {
log.warn("Query for bidi-link down but reverse-link not found " + "for link {}", link);
return false;
}
Boolean result = seenLinks.get(reverseLink);
if (result == null) {
return false;
}
// if reverse link is seen UP (true), then its not bidi yet
return !result.booleanValue();
}
Aggregations