Search in sources :

Example 11 with MacAddress

use of org.onlab.packet.MacAddress in project trellis-control by opennetworkinglab.

the class PolicyGroupHandler method createPolicyGroupChain.

/**
 * Creates policy group chain.
 *
 * @param id unique identifier associated with the policy group
 * @param params a list of policy group params
 * @return policy group identifier
 */
public PolicyGroupIdentifier createPolicyGroupChain(String id, List<PolicyGroupParams> params) {
    List<GroupBucketIdentifier> bucketIds = new ArrayList<>();
    for (PolicyGroupParams param : params) {
        List<PortNumber> ports = param.getPorts();
        if (ports == null) {
            log.warn("createPolicyGroupChain in sw {} with wrong " + "input parameters", deviceId);
            return null;
        }
        int labelStackSize = (param.getLabelStack() != null) ? param.getLabelStack().size() : 0;
        if (labelStackSize > 1) {
            for (PortNumber sp : ports) {
                PolicyGroupIdentifier previousGroupkey = null;
                DeviceId neighbor = portDeviceMap.get(sp);
                for (int idx = 0; idx < param.getLabelStack().size(); idx++) {
                    int label = param.getLabelStack().get(idx);
                    if (idx == (labelStackSize - 1)) {
                        // Innermost Group
                        GroupBucketIdentifier bucketId = new GroupBucketIdentifier(label, previousGroupkey);
                        bucketIds.add(bucketId);
                    } else if (idx == 0) {
                        // Outermost Group
                        List<GroupBucket> outBuckets = new ArrayList<>();
                        GroupBucketIdentifier bucketId = new GroupBucketIdentifier(label, sp);
                        PolicyGroupIdentifier key = new PolicyGroupIdentifier(id, Collections.singletonList(param), Collections.singletonList(bucketId));
                        MacAddress neighborEthDst;
                        try {
                            neighborEthDst = deviceConfig.getDeviceMac(neighbor);
                        } catch (DeviceConfigNotFoundException e) {
                            log.warn(e.getMessage() + " Skipping createPolicyGroupChain for this label.");
                            continue;
                        }
                        TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
                        tBuilder.setOutput(sp).setEthDst(neighborEthDst).setEthSrc(nodeMacAddr).pushMpls().setMpls(MplsLabel.mplsLabel(label));
                        /*outBuckets.add(DefaultGroupBucket.
                                           createSelectGroupBucket(tBuilder.build()));
                            GroupDescription desc = new
                                    DefaultGroupDescription(deviceId,
                                                            GroupDescription.Type.INDIRECT,
                                                            new GroupBuckets(outBuckets));
                            //TODO: BoS*/
                        previousGroupkey = key;
                    // groupService.addGroup(desc);
                    // TODO: Use nextObjective APIs here
                    } else {
                        // Intermediate Groups
                        GroupBucketIdentifier bucketId = new GroupBucketIdentifier(label, previousGroupkey);
                        PolicyGroupIdentifier key = new PolicyGroupIdentifier(id, Collections.singletonList(param), Collections.singletonList(bucketId));
                        // Add to group dependency list
                        dependentGroups.put(previousGroupkey, key);
                        previousGroupkey = key;
                    }
                }
            }
        } else {
            int label = -1;
            if (labelStackSize == 1) {
                label = param.getLabelStack().get(0);
            }
            for (PortNumber sp : ports) {
                GroupBucketIdentifier bucketId = new GroupBucketIdentifier(label, sp);
                bucketIds.add(bucketId);
            }
        }
    }
    PolicyGroupIdentifier innermostGroupkey = null;
    if (!bucketIds.isEmpty()) {
        innermostGroupkey = new PolicyGroupIdentifier(id, params, bucketIds);
        // Add to group dependency list
        boolean fullyResolved = true;
        for (GroupBucketIdentifier bucketId : bucketIds) {
            if (bucketId.type() == BucketOutputType.GROUP) {
                dependentGroups.put(bucketId.outGroup(), innermostGroupkey);
                fullyResolved = false;
            }
        }
        if (fullyResolved) {
            List<GroupBucket> outBuckets = new ArrayList<>();
            for (GroupBucketIdentifier bucketId : bucketIds) {
                DeviceId neighbor = portDeviceMap.get(bucketId.outPort());
                MacAddress neighborEthDst;
                try {
                    neighborEthDst = deviceConfig.getDeviceMac(neighbor);
                } catch (DeviceConfigNotFoundException e) {
                    log.warn(e.getMessage() + " Skipping createPolicyGroupChain for this bucketId.");
                    continue;
                }
                TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
                tBuilder.setOutput(bucketId.outPort()).setEthDst(neighborEthDst).setEthSrc(nodeMacAddr);
                if (bucketId.label() != DestinationSet.NO_EDGE_LABEL) {
                    tBuilder.pushMpls().setMpls(MplsLabel.mplsLabel(bucketId.label()));
                }
            // TODO: BoS
            /*outBuckets.add(DefaultGroupBucket.
                                   createSelectGroupBucket(tBuilder.build()));*/
            }
        /*GroupDescription desc = new
                        DefaultGroupDescription(deviceId,
                                                GroupDescription.Type.SELECT,
                                                new GroupBuckets(outBuckets));
                groupService.addGroup(desc);*/
        // TODO: Use nextObjective APIs here
        }
    }
    return innermostGroupkey;
}
Also used : DeviceId(org.onosproject.net.DeviceId) ArrayList(java.util.ArrayList) MacAddress(org.onlab.packet.MacAddress) TrafficTreatment(org.onosproject.net.flow.TrafficTreatment) DefaultTrafficTreatment(org.onosproject.net.flow.DefaultTrafficTreatment) DeviceConfigNotFoundException(org.onosproject.segmentrouting.config.DeviceConfigNotFoundException) GroupBucket(org.onosproject.net.group.GroupBucket) ArrayList(java.util.ArrayList) List(java.util.List) PortNumber(org.onosproject.net.PortNumber)

Example 12 with MacAddress

use of org.onlab.packet.MacAddress in project trellis-control by opennetworkinglab.

the class RouteHandler method processRouteRemovedInternal.

private void processRouteRemovedInternal(Collection<ResolvedRoute> routes) {
    if (!isReady()) {
        log.info("System is not ready. Skip removing route for {}", routes);
        return;
    }
    log.info("processRouteRemovedInternal. routes={}", routes);
    Set<IpPrefix> allPrefixes = Sets.newHashSet();
    routes.forEach(route -> {
        allPrefixes.add(route.prefix());
    });
    log.debug("RouteRemoved. revokeSubnet {}", allPrefixes);
    // FIXME remove routes more precisely by memorizing the old locations
    srManager.defaultRoutingHandler.revokeSubnet(allPrefixes, null);
    routes.forEach(route -> {
        IpPrefix prefix = route.prefix();
        MacAddress nextHopMac = route.nextHopMac();
        VlanId nextHopVlan = route.nextHopVlan();
        Set<ConnectPoint> locations = srManager.nextHopLocations(route);
        locations.forEach(location -> {
            log.debug("RouteRemoved. removeSubnet {}, {}", location, prefix);
            srManager.deviceConfiguration.removeSubnet(location, prefix);
        // We don't need to call revokeRoute again since revokeSubnet will remove the prefix
        // from all devices, including the ones that next hop attaches to.
        // revokeSubnet will also remove flow on the pair device (if exist) pointing to current location.
        });
    });
}
Also used : IpPrefix(org.onlab.packet.IpPrefix) MacAddress(org.onlab.packet.MacAddress) ConnectPoint(org.onosproject.net.ConnectPoint) VlanId(org.onlab.packet.VlanId)

Example 13 with MacAddress

use of org.onlab.packet.MacAddress in project trellis-control by opennetworkinglab.

the class RouteHandler method processHostMovedEvent.

void processHostMovedEvent(HostEvent event) {
    log.info("processHostMovedEvent {}", event);
    MacAddress hostMac = event.subject().mac();
    VlanId hostVlanId = event.subject().vlan();
    Set<ConnectPoint> prevLocations = event.prevSubject().locations().stream().map(h -> (ConnectPoint) h).collect(Collectors.toSet());
    Set<ConnectPoint> newLocations = event.subject().locations().stream().map(h -> (ConnectPoint) h).collect(Collectors.toSet());
    List<Set<IpPrefix>> batchedSubnets = srManager.deviceConfiguration.getBatchedSubnets(event.subject().id());
    Set<DeviceId> newDeviceIds = newLocations.stream().map(ConnectPoint::deviceId).collect(Collectors.toSet());
    // Set of deviceIDs of the previous locations where the host was connected
    // Used to determine if host moved to different connect points
    // on same device or moved to a different device altogether
    Set<DeviceId> oldDeviceIds = prevLocations.stream().map(ConnectPoint::deviceId).collect(Collectors.toSet());
    // and only when the no. of routes with the host as next-hop is not zero
    if (!batchedSubnets.isEmpty()) {
        // For each new location, if NextObj exists for the host, update with new location ..
        Sets.difference(newLocations, prevLocations).forEach(newLocation -> {
            // NOTE: that we use the nexthop vlanId to retrieve the nextId
            // while the vlanId used to program the L3 unicast chain
            // is derived from the port configuration. In case of
            // a tagged interface we use host vlanId. Host vlan should
            // be part of the tags configured for that port. See the
            // code in DefaultGroupHandler.updateL3UcastGroupBucket
            int nextId = srManager.getMacVlanNextObjectiveId(newLocation.deviceId(), hostMac, hostVlanId, null, false);
            if (nextId != -1) {
                // Update the nextId group bucket
                log.debug("HostMoved. NextId exists, update L3 Ucast Group Bucket {}, {}, {} --> {}", newLocation, hostMac, hostVlanId, nextId);
                srManager.updateMacVlanTreatment(newLocation.deviceId(), hostMac, hostVlanId, newLocation.port(), nextId);
            } else {
                log.debug("HostMoved. NextId does not exist for this location {}, host {}/{}", newLocation, hostMac, hostVlanId);
            }
        });
    }
    batchedSubnets.forEach(subnets -> {
        log.debug("HostMoved. populateSubnet {}, {}", newLocations, subnets);
        srManager.defaultRoutingHandler.populateSubnet(newLocations, subnets);
        subnets.forEach(prefix -> {
            // For each old location
            Sets.difference(prevLocations, newLocations).forEach(prevLocation -> {
                // Otherwise, do not remove and let the adding part update the old flow
                if (newDeviceIds.contains(prevLocation.deviceId())) {
                    return;
                }
                log.debug("HostMoved. removeSubnet {}, {}", prevLocation, prefix);
                srManager.deviceConfiguration.removeSubnet(prevLocation, prefix);
                // Do not remove flow from a device if the route is still reachable via its pair device.
                // If spine exists,
                // populateSubnet above will update the flow to point to its pair device via spine.
                // If spine does not exist,
                // processSingleLeafPair below will update the flow to point to its pair device via pair port.
                DeviceId pairDeviceId = srManager.getPairDeviceId(prevLocation.deviceId()).orElse(null);
                if (newLocations.stream().anyMatch(n -> n.deviceId().equals(pairDeviceId))) {
                    return;
                }
                log.debug("HostMoved. revokeRoute {}, {}, {}, {}", prevLocation, prefix, hostMac, hostVlanId);
                srManager.defaultRoutingHandler.revokeRoute(prevLocation.deviceId(), prefix, hostMac, hostVlanId, prevLocation.port(), false);
            });
            // For each new location, add all new IPs.
            Sets.difference(newLocations, prevLocations).forEach(newLocation -> {
                log.debug("HostMoved. addSubnet {}, {}", newLocation, prefix);
                srManager.deviceConfiguration.addSubnet(newLocation, prefix);
                // its a new connect point, not a move from an existing device, populateRoute
                if (!oldDeviceIds.contains(newLocation.deviceId())) {
                    log.debug("HostMoved. populateRoute {}, {}, {}, {}", newLocation, prefix, hostMac, hostVlanId);
                    srManager.defaultRoutingHandler.populateRoute(newLocation.deviceId(), prefix, hostMac, hostVlanId, newLocation.port(), false);
                }
            });
            newLocations.forEach(location -> {
                processSingleLeafPairIfNeeded(newLocations, location, prefix, hostVlanId);
            });
        });
    });
}
Also used : DeviceConfigNotFoundException(org.onosproject.segmentrouting.config.DeviceConfigNotFoundException) Logger(org.slf4j.Logger) Host(org.onosproject.net.Host) Collection(java.util.Collection) VlanId(org.onlab.packet.VlanId) PortNumber(org.onosproject.net.PortNumber) LoggerFactory(org.slf4j.LoggerFactory) RouteEvent(org.onosproject.routeservice.RouteEvent) Set(java.util.Set) Collectors(java.util.stream.Collectors) Sets(com.google.common.collect.Sets) ConnectPoint(org.onosproject.net.ConnectPoint) Objects(java.util.Objects) List(java.util.List) RouteInfo(org.onosproject.routeservice.RouteInfo) Optional(java.util.Optional) MacAddress(org.onlab.packet.MacAddress) HostEvent(org.onosproject.net.host.HostEvent) ResolvedRoute(org.onosproject.routeservice.ResolvedRoute) DeviceId(org.onosproject.net.DeviceId) IpPrefix(org.onlab.packet.IpPrefix) Set(java.util.Set) DeviceId(org.onosproject.net.DeviceId) MacAddress(org.onlab.packet.MacAddress) ConnectPoint(org.onosproject.net.ConnectPoint) VlanId(org.onlab.packet.VlanId) ConnectPoint(org.onosproject.net.ConnectPoint)

Example 14 with MacAddress

use of org.onlab.packet.MacAddress in project trellis-control by opennetworkinglab.

the class RouteHandler method processSingleLeafPairIfNeeded.

protected boolean processSingleLeafPairIfNeeded(Set<ConnectPoint> locations, ConnectPoint location, IpPrefix prefix, VlanId nextHopVlan) {
    // Special handling for single leaf pair
    if (!srManager.getInfraDeviceIds().isEmpty()) {
        log.debug("Spine found. Skip single leaf pair handling");
        return false;
    }
    Optional<DeviceId> pairDeviceId = srManager.getPairDeviceId(location.deviceId());
    if (pairDeviceId.isEmpty()) {
        log.debug("Pair device of {} not found", location.deviceId());
        return false;
    }
    if (locations.stream().anyMatch(l -> l.deviceId().equals(pairDeviceId.get()))) {
        log.debug("Pair device has a next hop available. Leave it as is.");
        return false;
    }
    Optional<PortNumber> pairRemotePort = srManager.getPairLocalPort(pairDeviceId.get());
    if (pairRemotePort.isEmpty()) {
        log.debug("Pair remote port of {} not found", pairDeviceId.get());
        return false;
    }
    // Use routerMac of the pair device as the next hop
    MacAddress effectiveMac;
    try {
        effectiveMac = srManager.getDeviceMacAddress(location.deviceId());
    } catch (DeviceConfigNotFoundException e) {
        log.warn("Abort populateRoute on pair device {}. routerMac not found", pairDeviceId);
        return false;
    }
    // Since the pairLocalPort is trunk port, use assigned vlan of original port
    // when the host is untagged
    VlanId effectiveVlan = Optional.ofNullable(srManager.getInternalVlanId(location)).orElse(nextHopVlan);
    log.debug("Single leaf pair. populateRoute {}/{}, {}, {}, {}", pairDeviceId, pairRemotePort, prefix, effectiveMac, effectiveVlan);
    srManager.defaultRoutingHandler.populateRoute(pairDeviceId.get(), prefix, effectiveMac, effectiveVlan, pairRemotePort.get(), false);
    return true;
}
Also used : DeviceId(org.onosproject.net.DeviceId) PortNumber(org.onosproject.net.PortNumber) MacAddress(org.onlab.packet.MacAddress) DeviceConfigNotFoundException(org.onosproject.segmentrouting.config.DeviceConfigNotFoundException) VlanId(org.onlab.packet.VlanId)

Example 15 with MacAddress

use of org.onlab.packet.MacAddress in project trellis-control by opennetworkinglab.

the class RouteHandler method processRouteAddedInternal.

/**
 * Internal logic that handles route addition.
 *
 * @param routes collection of routes to be processed
 * @param populateRouteOnly true if we only want to populateRoute but not populateSubnet.
 *                          Set it to true when initializing a device coming up.
 *                          populateSubnet will be done when link comes up later so it is redundant.
 *                          populateRoute still needs to be done for statically configured next hop hosts.
 */
private void processRouteAddedInternal(Collection<ResolvedRoute> routes, boolean populateRouteOnly) {
    if (!isReady()) {
        log.info("System is not ready. Skip adding route for {}", routes);
        return;
    }
    log.info("processRouteAddedInternal. routes={}", routes);
    if (routes.size() > 2) {
        log.info("Route {} has more than two next hops. Do not process route change", routes);
        return;
    }
    if (routes.isEmpty()) {
        log.warn("No resolved route found. Abort processRouteAddedInternal");
        return;
    }
    Set<ConnectPoint> allLocations = Sets.newHashSet();
    Set<IpPrefix> allPrefixes = Sets.newHashSet();
    routes.forEach(route -> {
        allLocations.addAll(srManager.nextHopLocations(route));
        allPrefixes.add(route.prefix());
    });
    log.debug("RouteAdded. populateSubnet {}, {}", allLocations, allPrefixes);
    srManager.defaultRoutingHandler.populateSubnet(allLocations, allPrefixes);
    routes.forEach(route -> {
        IpPrefix prefix = route.prefix();
        MacAddress nextHopMac = route.nextHopMac();
        VlanId nextHopVlan = route.nextHopVlan();
        Set<ConnectPoint> locations = srManager.nextHopLocations(route);
        locations.forEach(location -> {
            log.debug("RouteAdded. addSubnet {}, {}", location, prefix);
            srManager.deviceConfiguration.addSubnet(location, prefix);
            log.debug("RouteAdded populateRoute {}, {}, {}, {}", location, prefix, nextHopMac, nextHopVlan);
            srManager.defaultRoutingHandler.populateRoute(location.deviceId(), prefix, nextHopMac, nextHopVlan, location.port(), false);
            processSingleLeafPairIfNeeded(locations, location, prefix, nextHopVlan);
        });
    });
}
Also used : IpPrefix(org.onlab.packet.IpPrefix) MacAddress(org.onlab.packet.MacAddress) ConnectPoint(org.onosproject.net.ConnectPoint) VlanId(org.onlab.packet.VlanId)

Aggregations

MacAddress (org.onlab.packet.MacAddress)175 VlanId (org.onlab.packet.VlanId)67 IpAddress (org.onlab.packet.IpAddress)65 ConnectPoint (org.onosproject.net.ConnectPoint)55 TrafficTreatment (org.onosproject.net.flow.TrafficTreatment)54 DefaultTrafficTreatment (org.onosproject.net.flow.DefaultTrafficTreatment)53 DeviceId (org.onosproject.net.DeviceId)44 TrafficSelector (org.onosproject.net.flow.TrafficSelector)40 Host (org.onosproject.net.Host)38 DefaultTrafficSelector (org.onosproject.net.flow.DefaultTrafficSelector)36 Set (java.util.Set)33 HostLocation (org.onosproject.net.HostLocation)32 Logger (org.slf4j.Logger)32 Ethernet (org.onlab.packet.Ethernet)31 PortNumber (org.onosproject.net.PortNumber)29 List (java.util.List)27 HostId (org.onosproject.net.HostId)27 Interface (org.onosproject.net.intf.Interface)27 IpPrefix (org.onlab.packet.IpPrefix)26 LoggerFactory (org.slf4j.LoggerFactory)24