Search in sources :

Example 1 with SOURCES_REMOVED

use of org.onosproject.mcast.api.McastEvent.Type.SOURCES_REMOVED in project trellis-control by opennetworkinglab.

the class McastHandler method processSourcesRemovedInternal.

/**
 * Process the SOURCES_REMOVED event.
 *
 * @param sourcesToBeRemoved the source connect points to be removed
 * @param remainingSources the remainig source connect points
 * @param mcastIp the group address
 * @param sinks the sinks connect points
 */
private void processSourcesRemovedInternal(Set<ConnectPoint> sourcesToBeRemoved, Set<ConnectPoint> remainingSources, IpAddress mcastIp, Map<HostId, Set<ConnectPoint>> sinks) {
    lastMcastChange.set(Instant.now());
    log.info("Processing sources removed {} for group {}", sourcesToBeRemoved, mcastIp);
    if (!mcastUtils.isLeader(mcastIp)) {
        log.debug("Skip {} due to lack of leadership", mcastIp);
        return;
    }
    if (remainingSources.isEmpty()) {
        log.debug("There are no more sources for {}", mcastIp);
        processRouteRemovedInternal(sourcesToBeRemoved, mcastIp);
        return;
    }
    // Let's heal the trees
    Set<Link> notAffectedLinks = Sets.newHashSet();
    Map<ConnectPoint, Set<Link>> affectedLinks = Maps.newHashMap();
    Map<ConnectPoint, Set<ConnectPoint>> candidateSinks = Maps.newHashMap();
    Set<ConnectPoint> totalSources = Sets.newHashSet(sourcesToBeRemoved);
    totalSources.addAll(remainingSources);
    // Calculate all the links used by the sources and the current sinks
    totalSources.forEach(source -> {
        Set<ConnectPoint> currentSinks = sinks.values().stream().flatMap(Collection::stream).filter(sink -> isSinkForSource(mcastIp, sink, source)).collect(Collectors.toSet());
        candidateSinks.put(source, currentSinks);
        McastPathStoreKey pathStoreKey = new McastPathStoreKey(mcastIp, source);
        Collection<? extends List<Link>> storedPaths = Versioned.valueOrElse(mcastPathStore.get(pathStoreKey), Lists.newArrayList());
        currentSinks.forEach(currentSink -> {
            Optional<? extends List<Link>> currentPath = mcastUtils.getStoredPath(currentSink.deviceId(), storedPaths);
            if (currentPath.isPresent()) {
                if (!sourcesToBeRemoved.contains(source)) {
                    notAffectedLinks.addAll(currentPath.get());
                } else {
                    affectedLinks.compute(source, (k, v) -> {
                        v = v == null ? Sets.newHashSet() : v;
                        v.addAll(currentPath.get());
                        return v;
                    });
                }
            }
        });
    });
    // Clean transit links
    affectedLinks.forEach((source, currentCandidateLinks) -> {
        Set<Link> linksToBeRemoved = Sets.difference(currentCandidateLinks, notAffectedLinks).immutableCopy();
        if (!linksToBeRemoved.isEmpty()) {
            currentCandidateLinks.forEach(link -> {
                DeviceId srcLink = link.src().deviceId();
                // Remove ports only on links to be removed
                if (linksToBeRemoved.contains(link)) {
                    removePortFromDevice(link.src().deviceId(), link.src().port(), mcastIp, mcastUtils.assignedVlan(srcLink.equals(source.deviceId()) ? source : null));
                }
                // Remove role on the candidate links
                mcastRoleStore.remove(new McastRoleStoreKey(mcastIp, srcLink, source));
            });
        }
    });
    // Clean ingress and egress
    sourcesToBeRemoved.forEach(source -> {
        Set<ConnectPoint> currentSinks = candidateSinks.get(source);
        McastPathStoreKey pathStoreKey = new McastPathStoreKey(mcastIp, source);
        currentSinks.forEach(currentSink -> {
            VlanId assignedVlan = mcastUtils.assignedVlan(source.deviceId().equals(currentSink.deviceId()) ? source : null);
            // Sinks co-located with the source
            if (source.deviceId().equals(currentSink.deviceId())) {
                if (source.port().equals(currentSink.port())) {
                    log.warn("Skip {} since sink {} is on the same port of source {}. Abort", mcastIp, currentSink, source);
                    return;
                }
                // We need to check against the other sources and if it is
                // necessary remove the port from the device - no overlap
                Set<VlanId> otherVlans = remainingSources.stream().filter(remainingSource -> remainingSource.deviceId().equals(source.deviceId()) && candidateSinks.get(remainingSource).contains(currentSink)).map(remainingSource -> mcastUtils.assignedVlan(remainingSource.deviceId().equals(currentSink.deviceId()) ? remainingSource : null)).collect(Collectors.toSet());
                if (!otherVlans.contains(assignedVlan)) {
                    removePortFromDevice(currentSink.deviceId(), currentSink.port(), mcastIp, assignedVlan);
                }
                mcastRoleStore.remove(new McastRoleStoreKey(mcastIp, currentSink.deviceId(), source));
                return;
            }
            Set<VlanId> otherVlans = remainingSources.stream().filter(remainingSource -> candidateSinks.get(remainingSource).contains(currentSink)).map(remainingSource -> mcastUtils.assignedVlan(remainingSource.deviceId().equals(currentSink.deviceId()) ? remainingSource : null)).collect(Collectors.toSet());
            // Sinks on other leaves
            if (!otherVlans.contains(assignedVlan)) {
                removePortFromDevice(currentSink.deviceId(), currentSink.port(), mcastIp, assignedVlan);
            }
            mcastRoleStore.remove(new McastRoleStoreKey(mcastIp, currentSink.deviceId(), source));
        });
        // Clean the mcast paths
        mcastPathStore.removeAll(pathStoreKey);
    });
}
Also used : ConsistentMap(org.onosproject.store.service.ConsistentMap) CoreService(org.onosproject.core.CoreService) PortNumber(org.onosproject.net.PortNumber) LoggerFactory(org.slf4j.LoggerFactory) Tools.groupedThreads(org.onlab.util.Tools.groupedThreads) ForwardingObjective(org.onosproject.net.flowobjective.ForwardingObjective) ConsistentMultimap(org.onosproject.store.service.ConsistentMultimap) Link(org.onosproject.net.Link) SINKS_REMOVED(org.onosproject.mcast.api.McastEvent.Type.SINKS_REMOVED) ConnectPoint(org.onosproject.net.ConnectPoint) HashMultimap(com.google.common.collect.HashMultimap) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Executors.newScheduledThreadPool(java.util.concurrent.Executors.newScheduledThreadPool) McastEvent(org.onosproject.mcast.api.McastEvent) Port(org.onosproject.net.Port) Map(java.util.Map) ApplicationId(org.onosproject.core.ApplicationId) NextObjective(org.onosproject.net.flowobjective.NextObjective) SOURCES_ADDED(org.onosproject.mcast.api.McastEvent.Type.SOURCES_ADDED) INGRESS(org.onosproject.segmentrouting.mcast.McastRole.INGRESS) KryoNamespaces(org.onosproject.store.serializers.KryoNamespaces) SOURCES_REMOVED(org.onosproject.mcast.api.McastEvent.Type.SOURCES_REMOVED) Objects(com.google.common.base.Objects) ROUTE_ADDED(org.onosproject.mcast.api.McastEvent.Type.ROUTE_ADDED) NodeId(org.onosproject.cluster.NodeId) Serializer(org.onosproject.store.service.Serializer) ImmutableSet(com.google.common.collect.ImmutableSet) Device(org.onosproject.net.Device) Collection(java.util.Collection) Set(java.util.Set) Instant(java.time.Instant) Collectors(java.util.stream.Collectors) Sets(com.google.common.collect.Sets) SINKS_ADDED(org.onosproject.mcast.api.McastEvent.Type.SINKS_ADDED) Versioned(org.onosproject.store.service.Versioned) List(java.util.List) ObjectiveContext(org.onosproject.net.flowobjective.ObjectiveContext) Entry(java.util.Map.Entry) Optional(java.util.Optional) Path(org.onosproject.net.Path) DeviceId(org.onosproject.net.DeviceId) McastRouteUpdate(org.onosproject.mcast.api.McastRouteUpdate) ROUTE_REMOVED(org.onosproject.mcast.api.McastEvent.Type.ROUTE_REMOVED) Multimap(com.google.common.collect.Multimap) KryoNamespace(org.onlab.util.KryoNamespace) AtomicReference(java.util.concurrent.atomic.AtomicReference) Lists(com.google.common.collect.Lists) TRANSIT(org.onosproject.segmentrouting.mcast.McastRole.TRANSIT) ScheduledExecutorService(java.util.concurrent.ScheduledExecutorService) HostId(org.onosproject.net.HostId) DefaultObjectiveContext(org.onosproject.net.flowobjective.DefaultObjectiveContext) IpAddress(org.onlab.packet.IpAddress) SegmentRoutingManager(org.onosproject.segmentrouting.SegmentRoutingManager) McastRouteData(org.onosproject.mcast.api.McastRouteData) Logger(org.slf4j.Logger) EGRESS(org.onosproject.segmentrouting.mcast.McastRole.EGRESS) Iterator(java.util.Iterator) VlanId(org.onlab.packet.VlanId) Maps(com.google.common.collect.Maps) McastRoute(org.onosproject.mcast.api.McastRoute) TimeUnit(java.util.concurrent.TimeUnit) DistributedSet(org.onosproject.store.service.DistributedSet) Comparator(java.util.Comparator) Collections(java.util.Collections) ImmutableSet(com.google.common.collect.ImmutableSet) Set(java.util.Set) DistributedSet(org.onosproject.store.service.DistributedSet) DeviceId(org.onosproject.net.DeviceId) ConnectPoint(org.onosproject.net.ConnectPoint) Collection(java.util.Collection) Link(org.onosproject.net.Link) VlanId(org.onlab.packet.VlanId)

Aggregations

Objects (com.google.common.base.Objects)1 HashMultimap (com.google.common.collect.HashMultimap)1 ImmutableSet (com.google.common.collect.ImmutableSet)1 Lists (com.google.common.collect.Lists)1 Maps (com.google.common.collect.Maps)1 Multimap (com.google.common.collect.Multimap)1 Sets (com.google.common.collect.Sets)1 Instant (java.time.Instant)1 Collection (java.util.Collection)1 Collections (java.util.Collections)1 Comparator (java.util.Comparator)1 Iterator (java.util.Iterator)1 List (java.util.List)1 Map (java.util.Map)1 Entry (java.util.Map.Entry)1 Optional (java.util.Optional)1 Set (java.util.Set)1 Executors.newScheduledThreadPool (java.util.concurrent.Executors.newScheduledThreadPool)1 ScheduledExecutorService (java.util.concurrent.ScheduledExecutorService)1 TimeUnit (java.util.concurrent.TimeUnit)1