blob: 8f4a5c75f636396e13b5acbd84b44de9014a1d5b [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;
22import java.util.concurrent.ExecutorService;
23
24import static com.google.common.base.Preconditions.checkArgument;
25import static com.google.common.base.Preconditions.checkNotNull;
26import static com.google.common.collect.Multimaps.synchronizedSetMultimap;
27import static java.util.concurrent.Executors.newSingleThreadExecutor;
28import static org.onlab.util.Tools.namedThreads;
29import static org.slf4j.LoggerFactory.getLogger;
30
31/**
32 * Entity responsible for tracking installed flows and for monitoring topology
33 * events to determine what flows are affected by topology changes.
34 */
35@Component
36@Service
37public class FlowTracker implements FlowTrackerService {
38
39 private final Logger log = getLogger(getClass());
40
41 private final SetMultimap<LinkKey, IntentId> intentsByLink =
42 synchronizedSetMultimap(HashMultimap.<LinkKey, IntentId>create());
43
44 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
45 protected TopologyService topologyService;
46
47 private ExecutorService executorService =
48 newSingleThreadExecutor(namedThreads("onos-flowtracker"));
49
50 private TopologyListener listener = new InternalTopologyListener();
51 private TopologyChangeDelegate delegate;
52
53 @Activate
54 public void activate() {
55 topologyService.addListener(listener);
56 log.info("Started");
57 }
58
59 @Deactivate
60 public void deactivate() {
61 topologyService.removeListener(listener);
62 log.info("Stopped");
63 }
64
65 @Override
66 public void setDelegate(TopologyChangeDelegate delegate) {
67 checkNotNull(delegate, "Delegate cannot be null");
68 checkArgument(this.delegate == null || this.delegate == delegate,
69 "Another delegate already set");
70 this.delegate = delegate;
71 }
72
73 @Override
74 public void unsetDelegate(TopologyChangeDelegate delegate) {
75 checkArgument(this.delegate == delegate, "Not the current delegate");
76 this.delegate = null;
77 }
78
79 @Override
80 public void addTrackedResources(IntentId intentId, Collection<Link> resources) {
81 for (Link link : resources) {
82 intentsByLink.put(new LinkKey(link), intentId);
83 }
84 }
85
86 @Override
87 public void removeTrackedResources(IntentId intentId, Collection<Link> resources) {
88 for (Link link : resources) {
89 intentsByLink.remove(new LinkKey(link), intentId);
90 }
91 }
92
93 // Internal re-actor to topology change events.
94 private class InternalTopologyListener implements TopologyListener {
95 @Override
96 public void event(TopologyEvent event) {
97 executorService.execute(new TopologyChangeHandler(event));
98 }
99 }
100
101 // Re-dispatcher of topology change events.
102 private class TopologyChangeHandler implements Runnable {
103
104 private final TopologyEvent event;
105
106 TopologyChangeHandler(TopologyEvent event) {
107 this.event = event;
108 }
109
110 @Override
111 public void run() {
112 if (event.reasons() == null) {
113 delegate.bumpIntents(intentsByLink.values());
114 } else {
115 for (Event reason : event.reasons()) {
116 if (reason instanceof LinkEvent) {
117 LinkEvent linkEvent = (LinkEvent) reason;
118 if (linkEvent.type() == LinkEvent.Type.LINK_ADDED ||
119 linkEvent.type() == LinkEvent.Type.LINK_UPDATED) {
120 delegate.bumpIntents(intentsByLink.get(new LinkKey(linkEvent.subject())));
121 } else if (linkEvent.type() == LinkEvent.Type.LINK_REMOVED) {
122 delegate.failIntents(intentsByLink.get(new LinkKey(linkEvent.subject())));
123 }
124 }
125 }
126 }
127 }
128 }
129
130}