use of org.onosproject.segmentrouting.grouphandler.DestinationSet in project trellis-control by opennetworkinglab.
the class RoutingRulePopulator method getMplsForwardingObjective.
/**
* Returns a Forwarding Objective builder for the MPLS rule that references
* the desired Next Objective. Creates a DestinationSet that allows the
* groupHandler to create or find the required next objective.
*
* @param targetSw the target sw
* @param nextHops the set of next hops
* @param phpRequired true if penultimate-hop-popping is required
* @param isBos true if matched label is bottom-of-stack
* @param meta metadata for creating next objective
* @param routerIp the router ip representing the destination switch
* @param destSw the destination sw
* @return the mpls forwarding objective builder
*/
private ForwardingObjective.Builder getMplsForwardingObjective(DeviceId targetSw, Set<DeviceId> nextHops, boolean phpRequired, boolean isBos, TrafficSelector meta, IpAddress routerIp, int segmentId, DeviceId destSw) {
ForwardingObjective.Builder fwdBuilder = DefaultForwardingObjective.builder().withFlag(ForwardingObjective.Flag.SPECIFIC);
TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
DestinationSet ds = null;
DestinationSet.DestinationSetType dstType = null;
boolean simple = false;
if (phpRequired) {
// php case - pop should always be flow-action
log.debug("getMplsForwardingObjective: php required");
tbuilder.deferred().copyTtlIn();
if (isBos) {
if (routerIp.isIp4()) {
tbuilder.deferred().popMpls(EthType.EtherType.IPV4.ethType());
} else {
tbuilder.deferred().popMpls(EthType.EtherType.IPV6.ethType());
}
tbuilder.decNwTtl();
// standard case -> BoS == True; pop results in IP packet and forwarding
// is via an ECMP group
ds = DestinationSet.createTypePopBos(destSw);
} else {
tbuilder.deferred().popMpls(EthType.EtherType.MPLS_UNICAST.ethType()).decMplsTtl();
// double-label case -> BoS == False, pop results in MPLS packet
// depending on configuration we can ECMP this packet or choose one output
ds = DestinationSet.createTypePopNotBos(destSw);
if (!srManager.getMplsEcmp()) {
simple = true;
}
}
} else {
// swap with self case - SR CONTINUE
log.debug("getMplsForwardingObjective: swap with self");
tbuilder.deferred().decMplsTtl();
// swap results in MPLS packet with same BoS bit regardless of bit value
// depending on configuration we can ECMP this packet or choose one output
// differentiate here between swap with not bos or swap with bos
ds = isBos ? DestinationSet.createTypeSwapBos(segmentId, destSw) : DestinationSet.createTypeSwapNotBos(segmentId, destSw);
if (!srManager.getMplsEcmp()) {
simple = true;
}
}
fwdBuilder.withTreatment(tbuilder.build());
log.debug("Trying to get a nextObjId for mpls rule on device:{} to ds:{}", targetSw, ds);
DefaultGroupHandler gh = srManager.getGroupHandler(targetSw);
if (gh == null) {
log.warn("getNextObjectiveId query - groupHandler for device {} " + "not found", targetSw);
return null;
}
Map<DeviceId, Set<DeviceId>> dstNextHops = new HashMap<>();
dstNextHops.put(destSw, nextHops);
int nextId = gh.getNextObjectiveId(ds, dstNextHops, meta, simple);
if (nextId <= 0) {
log.warn("No next objective in {} for ds: {}", targetSw, ds);
return null;
} else {
log.debug("nextObjId found:{} for mpls rule on device:{} to ds:{}", nextId, targetSw, ds);
}
fwdBuilder.nextStep(nextId);
return fwdBuilder;
}
use of org.onosproject.segmentrouting.grouphandler.DestinationSet 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.DestinationSet in project trellis-control by opennetworkinglab.
the class TunnelHandler method createGroupsForTunnel.
private int createGroupsForTunnel(Tunnel tunnel) {
Set<Integer> portNumbers;
final int groupError = -1;
DeviceId deviceId = config.getDeviceId(tunnel.labelIds().get(0));
if (deviceId == null) {
log.warn("No device found for SID {}", tunnel.labelIds().get(0));
return groupError;
} else if (groupHandlerMap.get(deviceId) == null) {
log.warn("group handler not found for {}", deviceId);
return groupError;
}
Set<DeviceId> deviceIds = new HashSet<>();
int sid = tunnel.labelIds().get(1);
if (config.isAdjacencySid(deviceId, sid)) {
portNumbers = config.getPortsForAdjacencySid(deviceId, sid);
for (Link link : linkService.getDeviceEgressLinks(deviceId)) {
for (Integer port : portNumbers) {
if (link.src().port().toLong() == port) {
deviceIds.add(link.dst().deviceId());
}
}
}
} else {
deviceIds.add(config.getDeviceId(sid));
}
// For these NeighborSet isMpls is meaningless.
// TODO : Revisit this, the code and also the type
DestinationSet ns = DestinationSet.createTypePushBos(tunnel.labelIds().get(2), DeviceId.NONE);
// should not remove the group.
if (groupHandlerMap.get(deviceId).hasNextObjectiveId(ns)) {
tunnel.allowToRemoveGroup(false);
} else {
tunnel.allowToRemoveGroup(true);
}
return groupHandlerMap.get(deviceId).getNextObjectiveId(ns, null, null, true);
}
Aggregations