blob: 7ba4e2691837aed2fe7fb7ad152abefbcff1a312 [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;
14import org.onlab.onos.net.intent.IntentId;
15import org.onlab.onos.net.link.LinkEvent;
16import org.onlab.onos.net.topology.TopologyEvent;
17import org.onlab.onos.net.topology.TopologyListener;
18import org.onlab.onos.net.topology.TopologyService;
19import org.slf4j.Logger;
20
21import java.util.Collection;
tom85258ee2014-10-07 00:10:02 -070022import java.util.HashSet;
23import java.util.Set;
tom95329eb2014-10-06 08:40:06 -070024import java.util.concurrent.ExecutorService;
25
26import static com.google.common.base.Preconditions.checkArgument;
27import static com.google.common.base.Preconditions.checkNotNull;
28import static com.google.common.collect.Multimaps.synchronizedSetMultimap;
29import static java.util.concurrent.Executors.newSingleThreadExecutor;
tom85258ee2014-10-07 00:10:02 -070030import static org.onlab.onos.net.link.LinkEvent.Type.LINK_REMOVED;
Yuta HIGUCHI18ab8a92014-10-13 11:16:19 -070031import static org.onlab.onos.net.LinkKey.linkKey;
tom95329eb2014-10-06 08:40:06 -070032import static org.onlab.util.Tools.namedThreads;
33import static org.slf4j.LoggerFactory.getLogger;
34
35/**
36 * Entity responsible for tracking installed flows and for monitoring topology
37 * events to determine what flows are affected by topology changes.
38 */
39@Component
40@Service
tom85258ee2014-10-07 00:10:02 -070041public class ObjectiveTracker implements ObjectiveTrackerService {
tom95329eb2014-10-06 08:40:06 -070042
43 private final Logger log = getLogger(getClass());
44
45 private final SetMultimap<LinkKey, IntentId> intentsByLink =
46 synchronizedSetMultimap(HashMultimap.<LinkKey, IntentId>create());
47
48 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
49 protected TopologyService topologyService;
50
51 private ExecutorService executorService =
52 newSingleThreadExecutor(namedThreads("onos-flowtracker"));
53
54 private TopologyListener listener = new InternalTopologyListener();
55 private TopologyChangeDelegate delegate;
56
57 @Activate
58 public void activate() {
59 topologyService.addListener(listener);
60 log.info("Started");
61 }
62
63 @Deactivate
64 public void deactivate() {
65 topologyService.removeListener(listener);
66 log.info("Stopped");
67 }
68
69 @Override
70 public void setDelegate(TopologyChangeDelegate delegate) {
71 checkNotNull(delegate, "Delegate cannot be null");
72 checkArgument(this.delegate == null || this.delegate == delegate,
73 "Another delegate already set");
74 this.delegate = delegate;
75 }
76
77 @Override
78 public void unsetDelegate(TopologyChangeDelegate delegate) {
79 checkArgument(this.delegate == delegate, "Not the current delegate");
80 this.delegate = null;
81 }
82
83 @Override
84 public void addTrackedResources(IntentId intentId, Collection<Link> resources) {
85 for (Link link : resources) {
Yuta HIGUCHI18ab8a92014-10-13 11:16:19 -070086 intentsByLink.put(linkKey(link), intentId);
tom95329eb2014-10-06 08:40:06 -070087 }
88 }
89
90 @Override
91 public void removeTrackedResources(IntentId intentId, Collection<Link> resources) {
92 for (Link link : resources) {
Yuta HIGUCHI18ab8a92014-10-13 11:16:19 -070093 intentsByLink.remove(linkKey(link), intentId);
tom95329eb2014-10-06 08:40:06 -070094 }
95 }
96
97 // Internal re-actor to topology change events.
98 private class InternalTopologyListener implements TopologyListener {
99 @Override
100 public void event(TopologyEvent event) {
101 executorService.execute(new TopologyChangeHandler(event));
102 }
103 }
104
105 // Re-dispatcher of topology change events.
106 private class TopologyChangeHandler implements Runnable {
107
108 private final TopologyEvent event;
109
110 TopologyChangeHandler(TopologyEvent event) {
111 this.event = event;
112 }
113
114 @Override
115 public void run() {
116 if (event.reasons() == null) {
tom1dd08e42014-10-07 11:40:00 -0700117 delegate.triggerCompile(new HashSet<IntentId>(), true);
tom85258ee2014-10-07 00:10:02 -0700118
tom95329eb2014-10-06 08:40:06 -0700119 } else {
tom85258ee2014-10-07 00:10:02 -0700120 Set<IntentId> toBeRecompiled = new HashSet<>();
121 boolean recompileOnly = true;
122
123 // Scan through the list of reasons and keep accruing all
124 // intents that need to be recompiled.
tom95329eb2014-10-06 08:40:06 -0700125 for (Event reason : event.reasons()) {
126 if (reason instanceof LinkEvent) {
127 LinkEvent linkEvent = (LinkEvent) reason;
tom85258ee2014-10-07 00:10:02 -0700128 if (linkEvent.type() == LINK_REMOVED) {
Yuta HIGUCHI18ab8a92014-10-13 11:16:19 -0700129 Set<IntentId> intentIds = intentsByLink.get(linkKey(linkEvent.subject()));
tom85258ee2014-10-07 00:10:02 -0700130 toBeRecompiled.addAll(intentIds);
131 }
132 recompileOnly = recompileOnly && linkEvent.type() == LINK_REMOVED;
tom95329eb2014-10-06 08:40:06 -0700133 }
134 }
tom85258ee2014-10-07 00:10:02 -0700135
136 delegate.triggerCompile(toBeRecompiled, !recompileOnly);
tom95329eb2014-10-06 08:40:06 -0700137 }
138 }
139 }
140
141}