blob: 90e878e446cf0f6a21c8f130cee5acfe334d6587 [file] [log] [blame]
tom95329eb2014-10-06 08:40:06 -07001package org.onlab.onos.net.intent.impl;
2
3import com.google.common.collect.HashMultimap;
4import com.google.common.collect.SetMultimap;
5import org.apache.felix.scr.annotations.Activate;
6import org.apache.felix.scr.annotations.Component;
7import org.apache.felix.scr.annotations.Deactivate;
8import org.apache.felix.scr.annotations.Reference;
9import org.apache.felix.scr.annotations.ReferenceCardinality;
10import org.apache.felix.scr.annotations.Service;
11import org.onlab.onos.event.Event;
12import org.onlab.onos.net.Link;
13import org.onlab.onos.net.LinkKey;
Thomas Vachuskab97cf282014-10-20 23:31:12 -070014import org.onlab.onos.net.NetworkResource;
tom95329eb2014-10-06 08:40:06 -070015import org.onlab.onos.net.intent.IntentId;
16import org.onlab.onos.net.link.LinkEvent;
17import org.onlab.onos.net.topology.TopologyEvent;
18import org.onlab.onos.net.topology.TopologyListener;
19import org.onlab.onos.net.topology.TopologyService;
20import org.slf4j.Logger;
21
22import java.util.Collection;
tom85258ee2014-10-07 00:10:02 -070023import java.util.HashSet;
24import java.util.Set;
tom95329eb2014-10-06 08:40:06 -070025import java.util.concurrent.ExecutorService;
26
27import static com.google.common.base.Preconditions.checkArgument;
28import static com.google.common.base.Preconditions.checkNotNull;
29import static com.google.common.collect.Multimaps.synchronizedSetMultimap;
30import static java.util.concurrent.Executors.newSingleThreadExecutor;
Yuta HIGUCHI18ab8a92014-10-13 11:16:19 -070031import static org.onlab.onos.net.LinkKey.linkKey;
Thomas Vachuskab97cf282014-10-20 23:31:12 -070032import static org.onlab.onos.net.link.LinkEvent.Type.LINK_REMOVED;
tom95329eb2014-10-06 08:40:06 -070033import static org.onlab.util.Tools.namedThreads;
34import static org.slf4j.LoggerFactory.getLogger;
35
36/**
37 * Entity responsible for tracking installed flows and for monitoring topology
38 * events to determine what flows are affected by topology changes.
39 */
40@Component
41@Service
tom85258ee2014-10-07 00:10:02 -070042public class ObjectiveTracker implements ObjectiveTrackerService {
tom95329eb2014-10-06 08:40:06 -070043
44 private final Logger log = getLogger(getClass());
45
46 private final SetMultimap<LinkKey, IntentId> intentsByLink =
47 synchronizedSetMultimap(HashMultimap.<LinkKey, IntentId>create());
48
49 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
50 protected TopologyService topologyService;
51
52 private ExecutorService executorService =
53 newSingleThreadExecutor(namedThreads("onos-flowtracker"));
54
55 private TopologyListener listener = new InternalTopologyListener();
56 private TopologyChangeDelegate delegate;
57
58 @Activate
59 public void activate() {
60 topologyService.addListener(listener);
61 log.info("Started");
62 }
63
64 @Deactivate
65 public void deactivate() {
66 topologyService.removeListener(listener);
67 log.info("Stopped");
68 }
69
70 @Override
71 public void setDelegate(TopologyChangeDelegate delegate) {
72 checkNotNull(delegate, "Delegate cannot be null");
73 checkArgument(this.delegate == null || this.delegate == delegate,
74 "Another delegate already set");
75 this.delegate = delegate;
76 }
77
78 @Override
79 public void unsetDelegate(TopologyChangeDelegate delegate) {
80 checkArgument(this.delegate == delegate, "Not the current delegate");
81 this.delegate = null;
82 }
83
84 @Override
Thomas Vachuskab97cf282014-10-20 23:31:12 -070085 public void addTrackedResources(IntentId intentId,
86 Collection<NetworkResource> resources) {
87 for (NetworkResource resource : resources) {
88 if (resource instanceof Link) {
89 intentsByLink.put(linkKey((Link) resource), intentId);
90 }
tom95329eb2014-10-06 08:40:06 -070091 }
92 }
93
94 @Override
Thomas Vachuskab97cf282014-10-20 23:31:12 -070095 public void removeTrackedResources(IntentId intentId,
96 Collection<NetworkResource> resources) {
97 for (NetworkResource resource : resources) {
98 if (resource instanceof Link) {
99 intentsByLink.remove(linkKey((Link) resource), intentId);
100 }
tom95329eb2014-10-06 08:40:06 -0700101 }
102 }
103
104 // Internal re-actor to topology change events.
105 private class InternalTopologyListener implements TopologyListener {
106 @Override
107 public void event(TopologyEvent event) {
108 executorService.execute(new TopologyChangeHandler(event));
109 }
110 }
111
112 // Re-dispatcher of topology change events.
113 private class TopologyChangeHandler implements Runnable {
114
115 private final TopologyEvent event;
116
117 TopologyChangeHandler(TopologyEvent event) {
118 this.event = event;
119 }
120
121 @Override
122 public void run() {
123 if (event.reasons() == null) {
tom1dd08e42014-10-07 11:40:00 -0700124 delegate.triggerCompile(new HashSet<IntentId>(), true);
tom85258ee2014-10-07 00:10:02 -0700125
tom95329eb2014-10-06 08:40:06 -0700126 } else {
tom85258ee2014-10-07 00:10:02 -0700127 Set<IntentId> toBeRecompiled = new HashSet<>();
128 boolean recompileOnly = true;
129
130 // Scan through the list of reasons and keep accruing all
131 // intents that need to be recompiled.
tom95329eb2014-10-06 08:40:06 -0700132 for (Event reason : event.reasons()) {
133 if (reason instanceof LinkEvent) {
134 LinkEvent linkEvent = (LinkEvent) reason;
tom85258ee2014-10-07 00:10:02 -0700135 if (linkEvent.type() == LINK_REMOVED) {
Yuta HIGUCHI18ab8a92014-10-13 11:16:19 -0700136 Set<IntentId> intentIds = intentsByLink.get(linkKey(linkEvent.subject()));
tom85258ee2014-10-07 00:10:02 -0700137 toBeRecompiled.addAll(intentIds);
138 }
139 recompileOnly = recompileOnly && linkEvent.type() == LINK_REMOVED;
tom95329eb2014-10-06 08:40:06 -0700140 }
141 }
tom85258ee2014-10-07 00:10:02 -0700142
143 delegate.triggerCompile(toBeRecompiled, !recompileOnly);
tom95329eb2014-10-06 08:40:06 -0700144 }
145 }
146 }
147
148}