use of org.onosproject.segmentrouting.grouphandler.DefaultGroupHandler 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;
}
use of org.onosproject.segmentrouting.grouphandler.DefaultGroupHandler in project trellis-control by opennetworkinglab.
the class RoutingRulePopulator method revokeDoubleTaggedRoute.
/**
* Revokes IP rules for a route that has double-tagged next hop.
*
* @param deviceId device ID of the device that next hop attaches to
* @param prefix IP prefix of the route
* @param hostMac MAC address of the next hop
* @param innerVlan inner Vlan ID of the next hop
* @param outerVlan outer Vlan ID of the next hop
* @param outerTpid outer TPID of the next hop
* @param outPort port where the next hop attaches to
*/
void revokeDoubleTaggedRoute(DeviceId deviceId, IpPrefix prefix, MacAddress hostMac, VlanId innerVlan, VlanId outerVlan, EthType outerTpid, PortNumber outPort) {
ForwardingObjective.Builder fwdBuilder;
log.debug("Revoking direct routing entry for double-tagged host route {} at {}:{}", prefix, deviceId, outPort);
try {
fwdBuilder = routingFwdObjBuilder(deviceId, prefix, hostMac, outerVlan, outPort, innerVlan, outerTpid, true, true);
} catch (DeviceConfigNotFoundException e) {
log.error(e.getMessage() + " Aborting revokeDoubleTaggedRoute");
return;
}
if (fwdBuilder == null) {
log.error("Aborting double-tagged host routing table entry due to error for dev:{} route:{}", deviceId, prefix);
return;
}
int nextId = fwdBuilder.remove().nextId();
DefaultObjectiveContext context = new DefaultObjectiveContext(objective -> {
log.debug("Direct routing rule for double-tagged host route {} revoked. nextId={}", prefix, nextId);
// Try to remove next objective as well
ImmutablePair<TrafficTreatment, TrafficSelector> treatmentAndMeta;
try {
treatmentAndMeta = getTreatmentAndMeta(deviceId, hostMac, outerVlan, outPort, innerVlan, outerTpid);
} catch (DeviceConfigNotFoundException e) {
log.error(e.getMessage() + " Aborting revokeDoubleTaggedRoute");
return;
}
if (treatmentAndMeta == null) {
// Warning log will come from getTreatmentAndMeta method
return;
}
DefaultGroupHandler groupHandler = srManager.getGroupHandler(deviceId);
if (groupHandler == null) {
log.warn("Failed to revoke direct routing rule for double-tagged host route {}: " + "group handler not found for {}", prefix, deviceId);
return;
}
groupHandler.removeGroupFromPort(outPort, treatmentAndMeta.getLeft(), treatmentAndMeta.getRight());
}, (objective, error) -> log.warn("Failed to revoke direct routing rule for double-tagged host route {}: {}", prefix, error));
srManager.flowObjectiveService.forward(deviceId, fwdBuilder.remove(context));
}
use of org.onosproject.segmentrouting.grouphandler.DefaultGroupHandler in project trellis-control by opennetworkinglab.
the class RoutingRulePopulator method updateFwdObj.
/**
* Update Forwarding objective for each host and IP address connected to given port.
* And create corresponding Simple Next objective if it does not exist.
* Applied only when populating Forwarding objective
* @param deviceId switch ID to set the rule
* @param portNumber port number
* @param prefix IP prefix of the route
* @param hostMac MAC address of the next hop
* @param vlanId Vlan ID of the port
* @param popVlan true to pop vlan tag in TrafficTreatment
* @param install true to populate the forwarding objective, false to revoke
* @return a completable future that completes when the fwdobj completes. In case of removal,
* the completable future completes when also the nextobj completes.
*/
CompletableFuture<Objective> updateFwdObj(DeviceId deviceId, PortNumber portNumber, IpPrefix prefix, MacAddress hostMac, VlanId vlanId, boolean popVlan, boolean install) {
ForwardingObjective.Builder fob;
TrafficSelector.Builder sbuilder = buildIpSelectorFromIpPrefix(prefix);
MacAddress deviceMac;
try {
deviceMac = config.getDeviceMac(deviceId);
} catch (DeviceConfigNotFoundException e) {
log.warn(e.getMessage() + " Aborting updateFwdObj.");
return CompletableFuture.completedFuture(null);
}
TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
tbuilder.deferred().setEthDst(hostMac).setEthSrc(deviceMac).setOutput(portNumber);
TrafficSelector.Builder mbuilder = DefaultTrafficSelector.builder();
if (!popVlan) {
mbuilder.matchVlanId(vlanId);
tbuilder.setVlanId(vlanId);
} else {
mbuilder.matchVlanId(vlanId);
tbuilder.popVlan();
}
// if the objective is to revoke an existing rule, and for some reason
// the next-objective does not exist, then a new one should not be created
int portNextObjId = srManager.getPortNextObjectiveId(deviceId, portNumber, tbuilder.build(), mbuilder.build(), install);
CompletableFuture<Objective> future = new CompletableFuture<>();
if (portNextObjId == -1) {
// Warning log will come from getPortNextObjective method
return CompletableFuture.completedFuture(null);
}
fob = DefaultForwardingObjective.builder().withSelector(sbuilder.build()).nextStep(portNextObjId).fromApp(srManager.appId).makePermanent().withPriority(getPriorityFromPrefix(prefix)).withFlag(ForwardingObjective.Flag.SPECIFIC);
ObjectiveContext context = new DefaultObjectiveContext((objective) -> {
log.debug("IP rule for route {} {}", prefix, install ? "installed" : "revoked");
future.complete(objective);
}, (objective, error) -> {
log.warn("Failed to {} IP rule for route {}: {}", install ? "install" : "revoke", prefix, error);
future.complete(null);
});
srManager.flowObjectiveService.forward(deviceId, install ? fob.add(context) : fob.remove(context));
if (!install) {
if (!srManager.getVlanPortMap(deviceId).containsKey(vlanId) || !srManager.getVlanPortMap(deviceId).get(vlanId).contains(portNumber)) {
DefaultGroupHandler grpHandler = srManager.getGroupHandler(deviceId);
if (grpHandler == null) {
log.warn("updateFwdObj: groupHandler for device {} not found", deviceId);
} else {
// Before moving forward we have to be sure flow has been removed;
try {
future.get();
} catch (InterruptedException | ExecutionException e) {
log.warn("Exception caught when executing IP rule removal for route {}", prefix);
}
// Flow future has been already consumed (normally or exceptionally)
return grpHandler.removeGroupFromPort(portNumber, tbuilder.build(), mbuilder.build());
}
}
}
return future;
}
use of org.onosproject.segmentrouting.grouphandler.DefaultGroupHandler in project trellis-control by opennetworkinglab.
the class SegmentRoutingManager method processDeviceRemoved.
private void processDeviceRemoved(Device device) {
dsNextObjStore.entrySet().stream().filter(entry -> entry.getKey().deviceId().equals(device.id())).forEach(entry -> dsNextObjStore.remove(entry.getKey()));
vlanNextObjStore.entrySet().stream().filter(entry -> entry.getKey().deviceId().equals(device.id())).forEach(entry -> vlanNextObjStore.remove(entry.getKey()));
macVlanNextObjStore.entrySet().stream().filter(entry -> entry.getKey().deviceId().equals(device.id())).forEach(entry -> macVlanNextObjStore.remove(entry.getKey()));
portNextObjStore.entrySet().stream().filter(entry -> entry.getKey().deviceId().equals(device.id())).forEach(entry -> portNextObjStore.remove(entry.getKey()));
linkHandler.processDeviceRemoved(device);
DefaultGroupHandler gh = groupHandlerMap.remove(device.id());
if (gh != null) {
gh.shutdown();
}
// Note that a switch going down is associated with all of its links
// going down as well, but it is treated as a single switch down event
// while the link-downs are ignored. We cannot rely on the ordering of
// events - i.e we cannot expect all link-downs to come before the
// switch down - so we purge all seen-links for the switch before
// handling route-path changes for the switch-down
defaultRoutingHandler.populateRoutingRulesForLinkStatusChange(null, null, device.id(), true);
defaultRoutingHandler.purgeEcmpGraph(device.id());
// Removes routes having as target the device down
defaultRoutingHandler.purgeSeenBeforeRoutes(device.id());
// Cleanup all internal groupHandler stores for this device. Should be
// done after all rerouting or rehashing has been completed
groupHandlerMap.entrySet().forEach(entry -> entry.getValue().cleanUpForNeighborDown(device.id()));
phasedRecoveryService.reset(device.id());
// the purgeOnDisconnection device property.
if (deviceConfiguration.isConfigured(device.id())) {
flowObjectiveService.purgeAll(device.id(), appId);
}
}
use of org.onosproject.segmentrouting.grouphandler.DefaultGroupHandler in project trellis-control by opennetworkinglab.
the class SegmentRoutingManager method processEdgePort.
private void processEdgePort(DeviceId deviceId, Port port, VlanId vlanId, boolean popVlan) {
boolean portUp = port.isEnabled();
if (portUp) {
log.info("Device:EdgePort {}:{} is enabled in vlan: {}", deviceId, port.number(), vlanId);
hostEventExecutor.execute(() -> hostHandler.processPortUp(new ConnectPoint(deviceId, port.number())));
} else {
log.info("Device:EdgePort {}:{} is disabled in vlan: {}", deviceId, port.number(), vlanId);
}
DefaultGroupHandler groupHandler = groupHandlerMap.get(deviceId);
if (groupHandler != null) {
groupHandler.processEdgePort(port.number(), vlanId, popVlan, portUp);
} else {
log.warn("Group handler not found for dev:{}. Not handling edge port" + " {} event for port:{}", deviceId, (portUp) ? "UP" : "DOWN", port.number());
}
}
Aggregations