blob: 238c4d07156eafd657489ffc57ba5bdb25e76881 [file] [log] [blame]
tombe988312014-09-19 18:38:47 -07001package org.onlab.onos.net.flow.impl;
alshabib57044ba2014-09-16 15:58:01 -07002
alshabib5c370ff2014-09-18 10:12:14 -07003import static com.google.common.base.Preconditions.checkNotNull;
alshabib57044ba2014-09-16 15:58:01 -07004import static org.slf4j.LoggerFactory.getLogger;
5
alshabiba7f7ca82014-09-22 11:41:23 -07006import java.util.Iterator;
Ayaka Koshibe08eabaa2014-09-17 14:59:25 -07007import 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;
alshabib57044ba2014-09-16 15:58:01 -070029import org.onlab.onos.net.provider.AbstractProviderRegistry;
30import org.onlab.onos.net.provider.AbstractProviderService;
31import org.slf4j.Logger;
32
alshabiba7f7ca82014-09-22 11:41:23 -070033import com.google.common.collect.Lists;
34
tome4729872014-09-23 00:37:37 -070035/**
36 * Provides implementation of the flow NB & SB APIs.
37 */
alshabib57044ba2014-09-16 15:58:01 -070038@Component(immediate = true)
39@Service
tom202175a2014-09-19 19:00:11 -070040public class FlowRuleManager
alshabiba7f7ca82014-09-22 11:41:23 -070041extends AbstractProviderRegistry<FlowRuleProvider, FlowRuleProviderService>
42implements FlowRuleService, FlowRuleProviderRegistry {
alshabib57044ba2014-09-16 15:58:01 -070043
Ayaka Koshibe08eabaa2014-09-17 14:59:25 -070044 public static final String FLOW_RULE_NULL = "FlowRule cannot be null";
alshabib57044ba2014-09-16 15:58:01 -070045 private final Logger log = getLogger(getClass());
46
47 private final AbstractListenerRegistry<FlowRuleEvent, FlowRuleListener>
alshabiba7f7ca82014-09-22 11:41:23 -070048 listenerRegistry = new AbstractListenerRegistry<>();
alshabib57044ba2014-09-16 15:58:01 -070049
tombe988312014-09-19 18:38:47 -070050 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
51 protected FlowRuleStore store;
Ayaka Koshibe08eabaa2014-09-17 14:59:25 -070052
alshabib57044ba2014-09-16 15:58:01 -070053 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070054 protected EventDeliveryService eventDispatcher;
alshabib57044ba2014-09-16 15:58:01 -070055
56 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070057 protected DeviceService deviceService;
alshabib57044ba2014-09-16 15:58:01 -070058
59 @Activate
60 public void activate() {
61 eventDispatcher.addSink(FlowRuleEvent.class, listenerRegistry);
62 log.info("Started");
63 }
64
65 @Deactivate
66 public void deactivate() {
67 eventDispatcher.removeSink(FlowRuleEvent.class);
68 log.info("Stopped");
69 }
70
71 @Override
Ayaka Koshibed4e53e12014-09-18 14:24:55 -070072 public Iterable<FlowRule> getFlowEntries(DeviceId deviceId) {
Ayaka Koshibe08eabaa2014-09-17 14:59:25 -070073 return store.getFlowEntries(deviceId);
alshabib57044ba2014-09-16 15:58:01 -070074 }
75
76 @Override
alshabib219ebaa2014-09-22 15:41:24 -070077 public void applyFlowRules(FlowRule... flowRules) {
alshabib57044ba2014-09-16 15:58:01 -070078 for (int i = 0; i < flowRules.length; i++) {
alshabiba68eb962014-09-24 20:34:13 -070079 FlowRule f = flowRules[i];
alshabib57044ba2014-09-16 15:58:01 -070080 final Device device = deviceService.getDevice(f.deviceId());
81 final FlowRuleProvider frp = getProvider(device.providerId());
alshabib219ebaa2014-09-22 15:41:24 -070082 store.storeFlowRule(f);
alshabib57044ba2014-09-16 15:58:01 -070083 frp.applyFlowRule(f);
84 }
alshabib57044ba2014-09-16 15:58:01 -070085 }
86
87 @Override
88 public void removeFlowRules(FlowRule... flowRules) {
alshabibbb8b1282014-09-22 17:00:18 -070089 FlowRule f;
alshabiba68eb962014-09-24 20:34:13 -070090 FlowRuleProvider frp;
91 Device device;
alshabib57044ba2014-09-16 15:58:01 -070092 for (int i = 0; i < flowRules.length; i++) {
alshabiba68eb962014-09-24 20:34:13 -070093 f = flowRules[i];
94 device = deviceService.getDevice(f.deviceId());
95 frp = getProvider(device.providerId());
alshabib219ebaa2014-09-22 15:41:24 -070096 store.deleteFlowRule(f);
alshabib57044ba2014-09-16 15:58:01 -070097 frp.removeFlowRule(f);
98 }
alshabiba68eb962014-09-24 20:34:13 -070099 }
alshabib57044ba2014-09-16 15:58:01 -0700100
alshabiba68eb962014-09-24 20:34:13 -0700101 @Override
102 public void removeFlowRulesById(ApplicationId id) {
103 Iterable<FlowRule> rules = getFlowRulesById(id);
104 FlowRuleProvider frp;
105 Device device;
106 for (FlowRule f : rules) {
107 store.deleteFlowRule(f);
108 device = deviceService.getDevice(f.deviceId());
109 frp = getProvider(device.providerId());
110 frp.removeRulesById(id, f);
111 }
112 }
113
114 @Override
115 public Iterable<FlowRule> getFlowRulesById(ApplicationId id) {
116 return store.getFlowEntriesByAppId(id);
alshabib57044ba2014-09-16 15:58:01 -0700117 }
118
119 @Override
120 public void addListener(FlowRuleListener listener) {
121 listenerRegistry.addListener(listener);
122 }
123
124 @Override
125 public void removeListener(FlowRuleListener listener) {
126 listenerRegistry.removeListener(listener);
127 }
128
129 @Override
130 protected FlowRuleProviderService createProviderService(
131 FlowRuleProvider provider) {
132 return new InternalFlowRuleProviderService(provider);
133 }
134
135 private class InternalFlowRuleProviderService
alshabiba7f7ca82014-09-22 11:41:23 -0700136 extends AbstractProviderService<FlowRuleProvider>
137 implements FlowRuleProviderService {
alshabib57044ba2014-09-16 15:58:01 -0700138
139 protected InternalFlowRuleProviderService(FlowRuleProvider provider) {
140 super(provider);
141 }
142
143 @Override
144 public void flowRemoved(FlowRule flowRule) {
Ayaka Koshibe08eabaa2014-09-17 14:59:25 -0700145 checkNotNull(flowRule, FLOW_RULE_NULL);
146 checkValidity();
alshabiba68eb962014-09-24 20:34:13 -0700147 FlowRule stored = store.getFlowRule(flowRule);
148 if (stored == null) {
149 log.debug("Rule already evicted from store: {}", flowRule);
150 return;
151 }
152 Device device = deviceService.getDevice(flowRule.deviceId());
153 FlowRuleProvider frp = getProvider(device.providerId());
154 FlowRuleEvent event = null;
155 switch (stored.state()) {
156 case ADDED:
157 case PENDING_ADD:
158 frp.applyFlowRule(flowRule);
159 break;
160 case PENDING_REMOVE:
161 case REMOVED:
162 event = store.removeFlowRule(flowRule);
163 break;
164 default:
165 break;
alshabib57044ba2014-09-16 15:58:01 -0700166
alshabiba68eb962014-09-24 20:34:13 -0700167 }
Ayaka Koshibe08eabaa2014-09-17 14:59:25 -0700168 if (event != null) {
169 log.debug("Flow {} removed", flowRule);
170 post(event);
171 }
alshabib57044ba2014-09-16 15:58:01 -0700172 }
173
174 @Override
175 public void flowMissing(FlowRule flowRule) {
Ayaka Koshibe08eabaa2014-09-17 14:59:25 -0700176 checkNotNull(flowRule, FLOW_RULE_NULL);
177 checkValidity();
alshabiba68eb962014-09-24 20:34:13 -0700178 Device device = deviceService.getDevice(flowRule.deviceId());
179 FlowRuleProvider frp = getProvider(device.providerId());
180 switch (flowRule.state()) {
181 case PENDING_REMOVE:
182 case REMOVED:
183 store.removeFlowRule(flowRule);
184 frp.removeFlowRule(flowRule);
185 break;
186 case ADDED:
187 case PENDING_ADD:
188 frp.applyFlowRule(flowRule);
189 break;
190 default:
191 log.debug("Flow {} has not been installed.", flowRule);
192 }
193
alshabib57044ba2014-09-16 15:58:01 -0700194
195 }
196
197 @Override
alshabib219ebaa2014-09-22 15:41:24 -0700198 public void extraneousFlow(FlowRule flowRule) {
199 checkNotNull(flowRule, FLOW_RULE_NULL);
200 checkValidity();
alshabiba68eb962014-09-24 20:34:13 -0700201 removeFlowRules(flowRule);
alshabib54ce5892014-09-23 17:50:51 -0700202 log.debug("Flow {} is on switch but not in store.", flowRule);
alshabib219ebaa2014-09-22 15:41:24 -0700203 }
204
205 @Override
alshabib57044ba2014-09-16 15:58:01 -0700206 public void flowAdded(FlowRule flowRule) {
Ayaka Koshibe08eabaa2014-09-17 14:59:25 -0700207 checkNotNull(flowRule, FLOW_RULE_NULL);
208 checkValidity();
alshabib57044ba2014-09-16 15:58:01 -0700209
Ayaka Koshibe08eabaa2014-09-17 14:59:25 -0700210 FlowRuleEvent event = store.addOrUpdateFlowRule(flowRule);
211 if (event == null) {
alshabib219ebaa2014-09-22 15:41:24 -0700212 log.debug("No flow store event generated.");
Ayaka Koshibe08eabaa2014-09-17 14:59:25 -0700213 } else {
alshabib219ebaa2014-09-22 15:41:24 -0700214 log.debug("Flow {} {}", flowRule, event.type());
Ayaka Koshibe08eabaa2014-09-17 14:59:25 -0700215 post(event);
216 }
alshabib219ebaa2014-09-22 15:41:24 -0700217
alshabib57044ba2014-09-16 15:58:01 -0700218 }
219
Ayaka Koshibe08eabaa2014-09-17 14:59:25 -0700220 // Posts the specified event to the local event dispatcher.
221 private void post(FlowRuleEvent event) {
222 if (event != null) {
223 eventDispatcher.post(event);
224 }
225 }
alshabib5c370ff2014-09-18 10:12:14 -0700226
227 @Override
alshabiba7f7ca82014-09-22 11:41:23 -0700228 public void pushFlowMetrics(DeviceId deviceId, Iterable<FlowRule> flowEntries) {
229 List<FlowRule> storedRules = Lists.newLinkedList(store.getFlowEntries(deviceId));
alshabibbb8b1282014-09-22 17:00:18 -0700230
231 Iterator<FlowRule> switchRulesIterator = flowEntries.iterator();
alshabiba7f7ca82014-09-22 11:41:23 -0700232
233 while (switchRulesIterator.hasNext()) {
234 FlowRule rule = switchRulesIterator.next();
235 if (storedRules.remove(rule)) {
alshabib219ebaa2014-09-22 15:41:24 -0700236 // we both have the rule, let's update some info then.
alshabiba7f7ca82014-09-22 11:41:23 -0700237 flowAdded(rule);
238 } else {
alshabib219ebaa2014-09-22 15:41:24 -0700239 // the device has a rule the store does not have
240 extraneousFlow(rule);
alshabiba7f7ca82014-09-22 11:41:23 -0700241 }
242 }
243 for (FlowRule rule : storedRules) {
alshabib54ce5892014-09-23 17:50:51 -0700244
alshabiba7f7ca82014-09-22 11:41:23 -0700245 // there are rules in the store that aren't on the switch
246 flowMissing(rule);
alshabib54ce5892014-09-23 17:50:51 -0700247
alshabiba7f7ca82014-09-22 11:41:23 -0700248 }
alshabib5c370ff2014-09-18 10:12:14 -0700249 }
alshabib57044ba2014-09-16 15:58:01 -0700250 }
251
252}