use of org.onosproject.segmentrouting.xconnect.api.XconnectEndpoint in project trellis-control by opennetworkinglab.
the class XconnectManager method populateNext.
/**
* Populates next objectives for given XConnect.
*
* @param key XConnect store key
* @param endpoints XConnect endpoints
* @return next id
*/
private int populateNext(XconnectKey key, Set<XconnectEndpoint> endpoints) {
int nextId = Versioned.valueOrElse(xconnectNextObjStore.get(key), -1);
if (nextId != -1) {
log.debug("NextObj for {} found, id={}", key, nextId);
return nextId;
} else {
NextObjective.Builder nextObjBuilder = nextObjBuilder(key, endpoints);
if (nextObjBuilder == null) {
log.warn("Fail to populate {}: {}", key, ERROR_NEXT_OBJ_BUILDER);
return -1;
}
ObjectiveContext nextContext = new DefaultObjectiveContext(// To serialize this with kryo
(Serializable & Consumer<Objective>) (objective) -> log.debug("XConnect NextObj for {} added", key), (Serializable & BiConsumer<Objective, ObjectiveError>) (objective, error) -> {
log.warn("Failed to add XConnect NextObj for {}: {}", key, error);
srService.invalidateNextObj(objective.id());
});
NextObjective nextObj = nextObjBuilder.add(nextContext);
flowObjectiveService.next(key.deviceId(), nextObj);
xconnectNextObjStore.put(key, nextObj.id());
log.debug("NextObj for {} not found. Creating new NextObj with id={}", key, nextObj.id());
return nextObj.id();
}
}
use of org.onosproject.segmentrouting.xconnect.api.XconnectEndpoint in project trellis-control by opennetworkinglab.
the class XconnectManager method updateXConnect.
/**
* Updates XConnect groups and flows for given key.
*
* @param key XConnect key
* @param prevEndpoints previous XConnect endpoints
* @param endpoints new XConnect endpoints
*/
private void updateXConnect(XconnectKey key, Set<XconnectEndpoint> prevEndpoints, Set<XconnectEndpoint> endpoints) {
if (!srService.shouldProgram(key.deviceId())) {
log.debug("Abort updating XConnect {}: {}", key, ERROR_NOT_LEADER);
return;
}
// NOTE: ACL flow doesn't include port information. No need to update it.
// Pair port is built-in and thus not going to change. No need to update it.
// remove old filter
prevEndpoints.stream().filter(prevEndpoint -> !endpoints.contains(prevEndpoint)).forEach(prevEndpoint -> revokeFilter(key, ImmutableSet.of(prevEndpoint)));
// install new filter
endpoints.stream().filter(endpoint -> !prevEndpoints.contains(endpoint)).forEach(endpoint -> populateFilter(key, ImmutableSet.of(endpoint)));
CompletableFuture<ObjectiveError> fwdFuture = new CompletableFuture<>();
CompletableFuture<ObjectiveError> nextFuture = new CompletableFuture<>();
int nextId = Versioned.valueOrElse(xconnectNextObjStore.get(key), -1);
if (nextId != -1) {
revokeFwd(key, nextId, fwdFuture);
fwdFuture.thenAcceptAsync(fwdStatus -> {
if (fwdStatus == null) {
log.debug("Fwd removed. Now remove group {}", key);
revokeNext(key, prevEndpoints, nextId, nextFuture);
}
});
nextFuture.thenAcceptAsync(nextStatus -> {
if (nextStatus == null) {
log.debug("Installing new group and flow for {}", key);
int newNextId = populateNext(key, endpoints);
if (newNextId == -1) {
log.warn("Fail to updateXConnect {}: {}", key, ERROR_NEXT_ID);
return;
}
populateFwd(key, newNextId);
}
});
} else {
log.warn("NextObj for {} does not exist in the store.", key);
}
}
use of org.onosproject.segmentrouting.xconnect.api.XconnectEndpoint in project trellis-control by opennetworkinglab.
the class XconnectManager method revokeFilter.
/**
* Revokes filtering objectives for given XConnect.
*
* @param key XConnect store key
* @param endpoints XConnect endpoints
*/
private void revokeFilter(XconnectKey key, Set<XconnectEndpoint> endpoints) {
// FIXME Improve the logic
// If port load balancer is not involved, use filtered port. Otherwise, use unfiltered port.
// The purpose is to make sure existing XConnect logic can still work on a configured port.
boolean filtered = endpoints.stream().map(ep -> getNextTreatment(key.deviceId(), ep, false)).allMatch(t -> t.type().equals(NextTreatment.Type.TREATMENT));
endpoints.stream().map(ep -> getPhysicalPorts(key.deviceId(), ep)).flatMap(Set::stream).forEach(port -> {
FilteringObjective.Builder filtObjBuilder = filterObjBuilder(key, port, filtered);
ObjectiveContext context = new DefaultObjectiveContext((objective) -> log.debug("XConnect FilterObj for {} on port {} revoked", key, port), (objective, error) -> log.warn("Failed to revoke XConnect FilterObj for {} on port {}: {}", key, port, error));
flowObjectiveService.filter(key.deviceId(), filtObjBuilder.remove(context));
});
}
use of org.onosproject.segmentrouting.xconnect.api.XconnectEndpoint in project trellis-control by opennetworkinglab.
the class XconnectManager method addOrUpdateXconnect.
@Override
public void addOrUpdateXconnect(DeviceId deviceId, VlanId vlanId, Set<XconnectEndpoint> endpoints) {
log.info("Adding or updating xconnect. deviceId={}, vlanId={}, endpoints={}", deviceId, vlanId, endpoints);
SegmentRoutingDeviceConfig config = cfgService.getConfig(deviceId, SegmentRoutingDeviceConfig.class);
List<PortNumber> devicePorts = deviceService.getPorts(deviceId).stream().map(Port::number).collect(Collectors.toList());
if (!config.isEdgeRouter()) {
throw new IllegalArgumentException(ERROR_NOT_EDGE_ROUTER);
} else {
Iterator<XconnectEndpoint> itr = endpoints.iterator();
while (itr.hasNext()) {
XconnectEndpoint ep = itr.next();
// Note: we don't validate an endpoint with LOAD_BALANCER type
if (ep.type() != XconnectEndpoint.Type.PORT) {
continue;
}
if (!devicePorts.contains(((XconnectPortEndpoint) ep).port())) {
throw new IllegalArgumentException(ERROR_PORT_NOT_RANGE);
}
}
}
final XconnectKey key = new XconnectKey(deviceId, vlanId);
xconnectStore.put(key, endpoints);
}
use of org.onosproject.segmentrouting.xconnect.api.XconnectEndpoint in project trellis-control by opennetworkinglab.
the class XconnectManager method nextObjBuilder.
/**
* Creates a next objective builder for XConnect with given nextId.
*
* @param key XConnect key
* @param endpoints XConnect endpoints
* @param nextId next objective id
* @return next objective builder
*/
private NextObjective.Builder nextObjBuilder(XconnectKey key, Set<XconnectEndpoint> endpoints, int nextId) {
TrafficSelector metadata = DefaultTrafficSelector.builder().matchVlanId(key.vlanId()).build();
NextObjective.Builder nextObjBuilder = DefaultNextObjective.builder().withId(nextId).withType(NextObjective.Type.BROADCAST).fromApp(appId).withMeta(metadata);
for (XconnectEndpoint endpoint : endpoints) {
NextTreatment nextTreatment = getNextTreatment(key.deviceId(), endpoint, true);
if (nextTreatment == null) {
// If a PortLoadBalancer is used in the XConnect - putting on hold
if (endpoint.type() == XconnectEndpoint.Type.LOAD_BALANCER) {
log.warn("Unable to create nextObj. PortLoadBalancer not ready");
String portLoadBalancerKey = String.valueOf(((XconnectLoadBalancerEndpoint) endpoint).key());
portLoadBalancerCache.asMap().putIfAbsent(new PortLoadBalancerId(key.deviceId(), Integer.parseInt(portLoadBalancerKey)), key);
} else {
log.warn("Unable to create nextObj. Null NextTreatment");
}
return null;
}
nextObjBuilder.addTreatment(nextTreatment);
}
return nextObjBuilder;
}
Aggregations