blob: a6f5ebbd5e6b598d47606388e0e832d0ae9d67fe [file] [log] [blame]
tombe988312014-09-19 18:38:47 -07001package org.onlab.onos.net.flow.impl;
alshabib57044ba2014-09-16 15:58:01 -07002
alshabibbb42cad2014-09-25 11:43:05 -07003import static com.google.common.base.Preconditions.checkNotNull;
4import static org.slf4j.LoggerFactory.getLogger;
5
6import java.util.Iterator;
7import java.util.List;
8
alshabib57044ba2014-09-16 15:58:01 -07009import org.apache.felix.scr.annotations.Activate;
10import org.apache.felix.scr.annotations.Component;
11import org.apache.felix.scr.annotations.Deactivate;
12import org.apache.felix.scr.annotations.Reference;
13import org.apache.felix.scr.annotations.ReferenceCardinality;
14import org.apache.felix.scr.annotations.Service;
alshabiba68eb962014-09-24 20:34:13 -070015import org.onlab.onos.ApplicationId;
alshabib57044ba2014-09-16 15:58:01 -070016import org.onlab.onos.event.AbstractListenerRegistry;
17import org.onlab.onos.event.EventDeliveryService;
18import org.onlab.onos.net.Device;
19import org.onlab.onos.net.DeviceId;
20import org.onlab.onos.net.device.DeviceService;
alshabib57044ba2014-09-16 15:58:01 -070021import org.onlab.onos.net.flow.FlowRule;
22import org.onlab.onos.net.flow.FlowRuleEvent;
23import org.onlab.onos.net.flow.FlowRuleListener;
24import org.onlab.onos.net.flow.FlowRuleProvider;
25import org.onlab.onos.net.flow.FlowRuleProviderRegistry;
26import org.onlab.onos.net.flow.FlowRuleProviderService;
27import org.onlab.onos.net.flow.FlowRuleService;
tombe988312014-09-19 18:38:47 -070028import org.onlab.onos.net.flow.FlowRuleStore;
tomc78acee2014-09-24 15:16:55 -070029import org.onlab.onos.net.flow.FlowRuleStoreDelegate;
alshabib57044ba2014-09-16 15:58:01 -070030import org.onlab.onos.net.provider.AbstractProviderRegistry;
31import org.onlab.onos.net.provider.AbstractProviderService;
32import org.slf4j.Logger;
33
alshabibbb42cad2014-09-25 11:43:05 -070034import com.google.common.collect.Lists;
alshabiba7f7ca82014-09-22 11:41:23 -070035
tome4729872014-09-23 00:37:37 -070036/**
37 * Provides implementation of the flow NB & SB APIs.
38 */
alshabib57044ba2014-09-16 15:58:01 -070039@Component(immediate = true)
40@Service
tom202175a2014-09-19 19:00:11 -070041public class FlowRuleManager
alshabiba7f7ca82014-09-22 11:41:23 -070042extends AbstractProviderRegistry<FlowRuleProvider, FlowRuleProviderService>
43implements FlowRuleService, FlowRuleProviderRegistry {
alshabib57044ba2014-09-16 15:58:01 -070044
Ayaka Koshibe08eabaa2014-09-17 14:59:25 -070045 public static final String FLOW_RULE_NULL = "FlowRule cannot be null";
alshabib57044ba2014-09-16 15:58:01 -070046 private final Logger log = getLogger(getClass());
47
48 private final AbstractListenerRegistry<FlowRuleEvent, FlowRuleListener>
alshabiba7f7ca82014-09-22 11:41:23 -070049 listenerRegistry = new AbstractListenerRegistry<>();
alshabib57044ba2014-09-16 15:58:01 -070050
alshabibbb42cad2014-09-25 11:43:05 -070051 private final FlowRuleStoreDelegate delegate = new InternalStoreDelegate();
tomc78acee2014-09-24 15:16:55 -070052
tombe988312014-09-19 18:38:47 -070053 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
54 protected FlowRuleStore store;
Ayaka Koshibe08eabaa2014-09-17 14:59:25 -070055
alshabib57044ba2014-09-16 15:58:01 -070056 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070057 protected EventDeliveryService eventDispatcher;
alshabib57044ba2014-09-16 15:58:01 -070058
59 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070060 protected DeviceService deviceService;
alshabib57044ba2014-09-16 15:58:01 -070061
62 @Activate
63 public void activate() {
tomc78acee2014-09-24 15:16:55 -070064 store.setDelegate(delegate);
alshabib57044ba2014-09-16 15:58:01 -070065 eventDispatcher.addSink(FlowRuleEvent.class, listenerRegistry);
66 log.info("Started");
67 }
68
69 @Deactivate
70 public void deactivate() {
tomc78acee2014-09-24 15:16:55 -070071 store.unsetDelegate(delegate);
alshabib57044ba2014-09-16 15:58:01 -070072 eventDispatcher.removeSink(FlowRuleEvent.class);
73 log.info("Stopped");
74 }
75
76 @Override
Ayaka Koshibed4e53e12014-09-18 14:24:55 -070077 public Iterable<FlowRule> getFlowEntries(DeviceId deviceId) {
Ayaka Koshibe08eabaa2014-09-17 14:59:25 -070078 return store.getFlowEntries(deviceId);
alshabib57044ba2014-09-16 15:58:01 -070079 }
80
81 @Override
alshabib219ebaa2014-09-22 15:41:24 -070082 public void applyFlowRules(FlowRule... flowRules) {
alshabib57044ba2014-09-16 15:58:01 -070083 for (int i = 0; i < flowRules.length; i++) {
alshabiba68eb962014-09-24 20:34:13 -070084 FlowRule f = flowRules[i];
alshabib57044ba2014-09-16 15:58:01 -070085 final Device device = deviceService.getDevice(f.deviceId());
86 final FlowRuleProvider frp = getProvider(device.providerId());
alshabib219ebaa2014-09-22 15:41:24 -070087 store.storeFlowRule(f);
alshabib57044ba2014-09-16 15:58:01 -070088 frp.applyFlowRule(f);
89 }
alshabib57044ba2014-09-16 15:58:01 -070090 }
91
92 @Override
93 public void removeFlowRules(FlowRule... flowRules) {
alshabibbb8b1282014-09-22 17:00:18 -070094 FlowRule f;
alshabiba68eb962014-09-24 20:34:13 -070095 FlowRuleProvider frp;
96 Device device;
alshabib57044ba2014-09-16 15:58:01 -070097 for (int i = 0; i < flowRules.length; i++) {
alshabiba68eb962014-09-24 20:34:13 -070098 f = flowRules[i];
99 device = deviceService.getDevice(f.deviceId());
100 frp = getProvider(device.providerId());
alshabib219ebaa2014-09-22 15:41:24 -0700101 store.deleteFlowRule(f);
alshabib57044ba2014-09-16 15:58:01 -0700102 frp.removeFlowRule(f);
103 }
alshabiba68eb962014-09-24 20:34:13 -0700104 }
alshabib57044ba2014-09-16 15:58:01 -0700105
alshabiba68eb962014-09-24 20:34:13 -0700106 @Override
107 public void removeFlowRulesById(ApplicationId id) {
108 Iterable<FlowRule> rules = getFlowRulesById(id);
109 FlowRuleProvider frp;
110 Device device;
alshabibbb42cad2014-09-25 11:43:05 -0700111
alshabiba68eb962014-09-24 20:34:13 -0700112 for (FlowRule f : rules) {
113 store.deleteFlowRule(f);
114 device = deviceService.getDevice(f.deviceId());
115 frp = getProvider(device.providerId());
116 frp.removeRulesById(id, f);
117 }
118 }
119
120 @Override
121 public Iterable<FlowRule> getFlowRulesById(ApplicationId id) {
122 return store.getFlowEntriesByAppId(id);
alshabib57044ba2014-09-16 15:58:01 -0700123 }
124
125 @Override
126 public void addListener(FlowRuleListener listener) {
127 listenerRegistry.addListener(listener);
128 }
129
130 @Override
131 public void removeListener(FlowRuleListener listener) {
132 listenerRegistry.removeListener(listener);
133 }
134
135 @Override
136 protected FlowRuleProviderService createProviderService(
137 FlowRuleProvider provider) {
138 return new InternalFlowRuleProviderService(provider);
139 }
140
141 private class InternalFlowRuleProviderService
alshabiba7f7ca82014-09-22 11:41:23 -0700142 extends AbstractProviderService<FlowRuleProvider>
143 implements FlowRuleProviderService {
alshabib57044ba2014-09-16 15:58:01 -0700144
145 protected InternalFlowRuleProviderService(FlowRuleProvider provider) {
146 super(provider);
147 }
148
149 @Override
150 public void flowRemoved(FlowRule flowRule) {
Ayaka Koshibe08eabaa2014-09-17 14:59:25 -0700151 checkNotNull(flowRule, FLOW_RULE_NULL);
152 checkValidity();
alshabiba68eb962014-09-24 20:34:13 -0700153 FlowRule stored = store.getFlowRule(flowRule);
154 if (stored == null) {
155 log.debug("Rule already evicted from store: {}", flowRule);
156 return;
157 }
158 Device device = deviceService.getDevice(flowRule.deviceId());
159 FlowRuleProvider frp = getProvider(device.providerId());
160 FlowRuleEvent event = null;
161 switch (stored.state()) {
162 case ADDED:
163 case PENDING_ADD:
alshabib6eb438a2014-10-01 16:39:37 -0700164 if (flowRule.expired()) {
165 event = store.removeFlowRule(flowRule);
166 } else {
167 frp.applyFlowRule(stored);
168 }
alshabiba68eb962014-09-24 20:34:13 -0700169 break;
170 case PENDING_REMOVE:
171 case REMOVED:
172 event = store.removeFlowRule(flowRule);
173 break;
174 default:
175 break;
alshabib57044ba2014-09-16 15:58:01 -0700176
alshabiba68eb962014-09-24 20:34:13 -0700177 }
Ayaka Koshibe08eabaa2014-09-17 14:59:25 -0700178 if (event != null) {
179 log.debug("Flow {} removed", flowRule);
180 post(event);
181 }
alshabib57044ba2014-09-16 15:58:01 -0700182 }
183
184 @Override
185 public void flowMissing(FlowRule flowRule) {
Ayaka Koshibe08eabaa2014-09-17 14:59:25 -0700186 checkNotNull(flowRule, FLOW_RULE_NULL);
187 checkValidity();
alshabiba68eb962014-09-24 20:34:13 -0700188 Device device = deviceService.getDevice(flowRule.deviceId());
189 FlowRuleProvider frp = getProvider(device.providerId());
alshabibbb42cad2014-09-25 11:43:05 -0700190 FlowRuleEvent event = null;
alshabiba68eb962014-09-24 20:34:13 -0700191 switch (flowRule.state()) {
192 case PENDING_REMOVE:
193 case REMOVED:
alshabibbb42cad2014-09-25 11:43:05 -0700194 event = store.removeFlowRule(flowRule);
alshabiba68eb962014-09-24 20:34:13 -0700195 frp.removeFlowRule(flowRule);
196 break;
197 case ADDED:
198 case PENDING_ADD:
199 frp.applyFlowRule(flowRule);
200 break;
201 default:
202 log.debug("Flow {} has not been installed.", flowRule);
203 }
204
alshabibbb42cad2014-09-25 11:43:05 -0700205 if (event != null) {
206 log.debug("Flow {} removed", flowRule);
207 post(event);
208 }
alshabib57044ba2014-09-16 15:58:01 -0700209
210 }
211
212 @Override
alshabib219ebaa2014-09-22 15:41:24 -0700213 public void extraneousFlow(FlowRule flowRule) {
214 checkNotNull(flowRule, FLOW_RULE_NULL);
215 checkValidity();
alshabiba68eb962014-09-24 20:34:13 -0700216 removeFlowRules(flowRule);
alshabib54ce5892014-09-23 17:50:51 -0700217 log.debug("Flow {} is on switch but not in store.", flowRule);
alshabib219ebaa2014-09-22 15:41:24 -0700218 }
219
220 @Override
alshabib57044ba2014-09-16 15:58:01 -0700221 public void flowAdded(FlowRule flowRule) {
Ayaka Koshibe08eabaa2014-09-17 14:59:25 -0700222 checkNotNull(flowRule, FLOW_RULE_NULL);
223 checkValidity();
alshabib57044ba2014-09-16 15:58:01 -0700224
Ayaka Koshibe08eabaa2014-09-17 14:59:25 -0700225 FlowRuleEvent event = store.addOrUpdateFlowRule(flowRule);
226 if (event == null) {
alshabib219ebaa2014-09-22 15:41:24 -0700227 log.debug("No flow store event generated.");
Ayaka Koshibe08eabaa2014-09-17 14:59:25 -0700228 } else {
alshabib219ebaa2014-09-22 15:41:24 -0700229 log.debug("Flow {} {}", flowRule, event.type());
Ayaka Koshibe08eabaa2014-09-17 14:59:25 -0700230 post(event);
231 }
alshabib219ebaa2014-09-22 15:41:24 -0700232
alshabib57044ba2014-09-16 15:58:01 -0700233 }
234
Ayaka Koshibe08eabaa2014-09-17 14:59:25 -0700235 // Posts the specified event to the local event dispatcher.
236 private void post(FlowRuleEvent event) {
237 if (event != null) {
238 eventDispatcher.post(event);
239 }
240 }
alshabib5c370ff2014-09-18 10:12:14 -0700241
242 @Override
alshabiba7f7ca82014-09-22 11:41:23 -0700243 public void pushFlowMetrics(DeviceId deviceId, Iterable<FlowRule> flowEntries) {
244 List<FlowRule> storedRules = Lists.newLinkedList(store.getFlowEntries(deviceId));
alshabibbb8b1282014-09-22 17:00:18 -0700245
246 Iterator<FlowRule> switchRulesIterator = flowEntries.iterator();
alshabiba7f7ca82014-09-22 11:41:23 -0700247
248 while (switchRulesIterator.hasNext()) {
249 FlowRule rule = switchRulesIterator.next();
250 if (storedRules.remove(rule)) {
alshabib219ebaa2014-09-22 15:41:24 -0700251 // we both have the rule, let's update some info then.
alshabiba7f7ca82014-09-22 11:41:23 -0700252 flowAdded(rule);
253 } else {
alshabib219ebaa2014-09-22 15:41:24 -0700254 // the device has a rule the store does not have
255 extraneousFlow(rule);
alshabiba7f7ca82014-09-22 11:41:23 -0700256 }
257 }
258 for (FlowRule rule : storedRules) {
259 // there are rules in the store that aren't on the switch
260 flowMissing(rule);
alshabib54ce5892014-09-23 17:50:51 -0700261
alshabiba7f7ca82014-09-22 11:41:23 -0700262 }
alshabib5c370ff2014-09-18 10:12:14 -0700263 }
alshabib57044ba2014-09-16 15:58:01 -0700264 }
265
tomc78acee2014-09-24 15:16:55 -0700266 // Store delegate to re-post events emitted from the store.
267 private class InternalStoreDelegate implements FlowRuleStoreDelegate {
268 @Override
269 public void notify(FlowRuleEvent event) {
270 eventDispatcher.post(event);
271 }
272 }
alshabib57044ba2014-09-16 15:58:01 -0700273}