blob: 53a49b6502ead16ad0777c04d591d4edc5cc449c [file] [log] [blame]
Thomas Vachuska781d18b2014-10-27 10:31:25 -07001/*
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07002 * Copyright 2014 Open Networking Laboratory
Thomas Vachuska781d18b2014-10-27 10:31:25 -07003 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07004 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
Thomas Vachuska781d18b2014-10-27 10:31:25 -07007 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07008 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
Thomas Vachuska781d18b2014-10-27 10:31:25 -070015 */
alshabib1cc04f72014-09-16 16:09:58 -070016package org.onlab.onos.provider.of.flow.impl;
17
Jonathan Hart11096402014-10-20 17:31:49 -070018import static org.slf4j.LoggerFactory.getLogger;
19
20import java.util.Collections;
21import java.util.HashMap;
22import java.util.List;
23import java.util.Map;
24import java.util.Set;
25import java.util.concurrent.ConcurrentHashMap;
26import java.util.concurrent.CountDownLatch;
27import java.util.concurrent.ExecutionException;
Madan Jampani117aaae2014-10-23 10:04:05 -070028import java.util.concurrent.Executor;
Jonathan Hart11096402014-10-20 17:31:49 -070029import java.util.concurrent.TimeUnit;
30import java.util.concurrent.TimeoutException;
31import java.util.concurrent.atomic.AtomicBoolean;
32
alshabib1cc04f72014-09-16 16:09:58 -070033import org.apache.felix.scr.annotations.Activate;
34import org.apache.felix.scr.annotations.Component;
35import org.apache.felix.scr.annotations.Deactivate;
36import org.apache.felix.scr.annotations.Reference;
37import org.apache.felix.scr.annotations.ReferenceCardinality;
Thomas Vachuskae0f804a2014-10-27 23:40:48 -070038import org.onlab.onos.core.ApplicationId;
alshabiba7f7ca82014-09-22 11:41:23 -070039import org.onlab.onos.net.DeviceId;
Jonathan Hart86e59352014-10-22 10:42:16 -070040import org.onlab.onos.net.flow.BatchOperation;
alshabib193525b2014-10-08 18:58:03 -070041import org.onlab.onos.net.flow.CompletedBatchOperation;
42import org.onlab.onos.net.flow.DefaultFlowEntry;
alshabib1c319ff2014-10-04 20:29:09 -070043import org.onlab.onos.net.flow.FlowEntry;
alshabib1cc04f72014-09-16 16:09:58 -070044import org.onlab.onos.net.flow.FlowRule;
alshabib902d41b2014-10-07 16:52:05 -070045import org.onlab.onos.net.flow.FlowRuleBatchEntry;
alshabib193525b2014-10-08 18:58:03 -070046import org.onlab.onos.net.flow.FlowRuleBatchEntry.FlowRuleOperation;
alshabib1cc04f72014-09-16 16:09:58 -070047import org.onlab.onos.net.flow.FlowRuleProvider;
48import org.onlab.onos.net.flow.FlowRuleProviderRegistry;
49import org.onlab.onos.net.flow.FlowRuleProviderService;
50import org.onlab.onos.net.provider.AbstractProvider;
51import org.onlab.onos.net.provider.ProviderId;
52import org.onlab.onos.net.topology.TopologyService;
tom9c94c5b2014-09-17 13:14:42 -070053import org.onlab.onos.openflow.controller.Dpid;
54import org.onlab.onos.openflow.controller.OpenFlowController;
alshabibeec3a062014-09-17 18:01:26 -070055import org.onlab.onos.openflow.controller.OpenFlowEventListener;
tom9c94c5b2014-09-17 13:14:42 -070056import org.onlab.onos.openflow.controller.OpenFlowSwitch;
alshabibce4e5782014-09-17 14:56:42 -070057import org.onlab.onos.openflow.controller.OpenFlowSwitchListener;
Ayaka Koshibeab91cc42014-09-25 10:20:52 -070058import org.onlab.onos.openflow.controller.RoleState;
alshabib19fdc122014-10-03 11:38:19 -070059import org.projectfloodlight.openflow.protocol.OFActionType;
alshabib902d41b2014-10-07 16:52:05 -070060import org.projectfloodlight.openflow.protocol.OFBarrierRequest;
61import org.projectfloodlight.openflow.protocol.OFErrorMsg;
alshabib193525b2014-10-08 18:58:03 -070062import org.projectfloodlight.openflow.protocol.OFFlowMod;
alshabib8f1cf4a2014-09-17 14:44:48 -070063import org.projectfloodlight.openflow.protocol.OFFlowRemoved;
alshabib5c370ff2014-09-18 10:12:14 -070064import org.projectfloodlight.openflow.protocol.OFFlowStatsEntry;
65import org.projectfloodlight.openflow.protocol.OFFlowStatsReply;
alshabib19fdc122014-10-03 11:38:19 -070066import org.projectfloodlight.openflow.protocol.OFInstructionType;
alshabib8f1cf4a2014-09-17 14:44:48 -070067import org.projectfloodlight.openflow.protocol.OFMessage;
68import org.projectfloodlight.openflow.protocol.OFPortStatus;
alshabib5c370ff2014-09-18 10:12:14 -070069import org.projectfloodlight.openflow.protocol.OFStatsReply;
alshabib54ce5892014-09-23 17:50:51 -070070import org.projectfloodlight.openflow.protocol.OFStatsReplyFlags;
alshabib5c370ff2014-09-18 10:12:14 -070071import org.projectfloodlight.openflow.protocol.OFStatsType;
alshabib19fdc122014-10-03 11:38:19 -070072import org.projectfloodlight.openflow.protocol.OFVersion;
73import org.projectfloodlight.openflow.protocol.action.OFAction;
74import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
alshabib193525b2014-10-08 18:58:03 -070075import org.projectfloodlight.openflow.protocol.errormsg.OFBadActionErrorMsg;
76import org.projectfloodlight.openflow.protocol.errormsg.OFBadInstructionErrorMsg;
77import org.projectfloodlight.openflow.protocol.errormsg.OFBadMatchErrorMsg;
78import org.projectfloodlight.openflow.protocol.errormsg.OFBadRequestErrorMsg;
79import org.projectfloodlight.openflow.protocol.errormsg.OFFlowModFailedErrorMsg;
alshabib19fdc122014-10-03 11:38:19 -070080import org.projectfloodlight.openflow.protocol.instruction.OFInstruction;
81import org.projectfloodlight.openflow.protocol.instruction.OFInstructionApplyActions;
82import org.projectfloodlight.openflow.types.OFPort;
alshabib902d41b2014-10-07 16:52:05 -070083import org.projectfloodlight.openflow.types.U32;
alshabib1cc04f72014-09-16 16:09:58 -070084import org.slf4j.Logger;
85
Jonathan Hart11096402014-10-20 17:31:49 -070086import com.google.common.collect.ArrayListMultimap;
Jonathan Hart11096402014-10-20 17:31:49 -070087import com.google.common.collect.Maps;
88import com.google.common.collect.Multimap;
Madan Jampani117aaae2014-10-23 10:04:05 -070089import com.google.common.collect.Sets;
90import com.google.common.util.concurrent.ExecutionList;
91import com.google.common.util.concurrent.ListenableFuture;
alshabibeec3a062014-09-17 18:01:26 -070092
alshabib1cc04f72014-09-16 16:09:58 -070093/**
94 * Provider which uses an OpenFlow controller to detect network
95 * end-station hosts.
96 */
97@Component(immediate = true)
98public class OpenFlowRuleProvider extends AbstractProvider implements FlowRuleProvider {
99
alshabib193525b2014-10-08 18:58:03 -0700100 enum BatchState { STARTED, FINISHED, CANCELLED };
101
alshabib1cc04f72014-09-16 16:09:58 -0700102 private final Logger log = getLogger(getClass());
103
104 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
105 protected FlowRuleProviderRegistry providerRegistry;
106
107 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
108 protected OpenFlowController controller;
109
110 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
111 protected TopologyService topologyService;
112
113 private FlowRuleProviderService providerService;
114
alshabibeec3a062014-09-17 18:01:26 -0700115 private final InternalFlowProvider listener = new InternalFlowProvider();
116
Madan Jampani117aaae2014-10-23 10:04:05 -0700117 // FIXME: This should be an expiring map to ensure futures that don't have
118 // a future eventually get garbage collected.
alshabib902d41b2014-10-07 16:52:05 -0700119 private final Map<Long, InstallationFuture> pendingFutures =
120 new ConcurrentHashMap<Long, InstallationFuture>();
121
alshabib193525b2014-10-08 18:58:03 -0700122 private final Map<Long, InstallationFuture> pendingFMs =
123 new ConcurrentHashMap<Long, InstallationFuture>();
124
alshabib3d643ec2014-10-22 18:33:00 -0700125 private final Map<Dpid, FlowStatsCollector> collectors = Maps.newHashMap();
126
alshabib1cc04f72014-09-16 16:09:58 -0700127 /**
128 * Creates an OpenFlow host provider.
129 */
130 public OpenFlowRuleProvider() {
tom7e02cda2014-09-18 12:05:46 -0700131 super(new ProviderId("of", "org.onlab.onos.provider.openflow"));
alshabib1cc04f72014-09-16 16:09:58 -0700132 }
133
134 @Activate
135 public void activate() {
136 providerService = providerRegistry.register(this);
alshabibeec3a062014-09-17 18:01:26 -0700137 controller.addListener(listener);
138 controller.addEventListener(listener);
alshabib3d643ec2014-10-22 18:33:00 -0700139
140 for (OpenFlowSwitch sw : controller.getSwitches()) {
141 FlowStatsCollector fsc = new FlowStatsCollector(sw, POLL_INTERVAL);
142 fsc.start();
143 collectors.put(new Dpid(sw.getId()), fsc);
144 }
145
146
alshabib1cc04f72014-09-16 16:09:58 -0700147 log.info("Started");
148 }
149
150 @Deactivate
151 public void deactivate() {
152 providerRegistry.unregister(this);
153 providerService = null;
154
155 log.info("Stopped");
156 }
157 @Override
158 public void applyFlowRule(FlowRule... flowRules) {
alshabib35edb1a2014-09-16 17:44:44 -0700159 for (int i = 0; i < flowRules.length; i++) {
160 applyRule(flowRules[i]);
161 }
alshabib1cc04f72014-09-16 16:09:58 -0700162 }
163
alshabib35edb1a2014-09-16 17:44:44 -0700164 private void applyRule(FlowRule flowRule) {
165 OpenFlowSwitch sw = controller.getSwitch(Dpid.dpid(flowRule.deviceId().uri()));
Jonathan Hart86e59352014-10-22 10:42:16 -0700166 sw.sendMsg(FlowModBuilder.builder(flowRule, sw.factory()).buildFlowAdd());
alshabib35edb1a2014-09-16 17:44:44 -0700167 }
168
alshabib35edb1a2014-09-16 17:44:44 -0700169
alshabib35edb1a2014-09-16 17:44:44 -0700170
alshabib1cc04f72014-09-16 16:09:58 -0700171 @Override
172 public void removeFlowRule(FlowRule... flowRules) {
alshabib219ebaa2014-09-22 15:41:24 -0700173 for (int i = 0; i < flowRules.length; i++) {
174 removeRule(flowRules[i]);
175 }
alshabib1cc04f72014-09-16 16:09:58 -0700176
177 }
178
alshabib219ebaa2014-09-22 15:41:24 -0700179 private void removeRule(FlowRule flowRule) {
180 OpenFlowSwitch sw = controller.getSwitch(Dpid.dpid(flowRule.deviceId().uri()));
Jonathan Hart86e59352014-10-22 10:42:16 -0700181 sw.sendMsg(FlowModBuilder.builder(flowRule, sw.factory()).buildFlowDel());
alshabib219ebaa2014-09-22 15:41:24 -0700182 }
183
alshabiba68eb962014-09-24 20:34:13 -0700184 @Override
185 public void removeRulesById(ApplicationId id, FlowRule... flowRules) {
186 // TODO: optimize using the ApplicationId
187 removeFlowRule(flowRules);
188 }
189
alshabib193525b2014-10-08 18:58:03 -0700190 @Override
Madan Jampani117aaae2014-10-23 10:04:05 -0700191 public ListenableFuture<CompletedBatchOperation> executeBatch(BatchOperation<FlowRuleBatchEntry> batch) {
Jonathan Hart11096402014-10-20 17:31:49 -0700192 final Set<Dpid> sws =
193 Collections.newSetFromMap(new ConcurrentHashMap<Dpid, Boolean>());
alshabib193525b2014-10-08 18:58:03 -0700194 final Map<Long, FlowRuleBatchEntry> fmXids = new HashMap<Long, FlowRuleBatchEntry>();
195 OFFlowMod mod = null;
196 for (FlowRuleBatchEntry fbe : batch.getOperations()) {
197 FlowRule flowRule = fbe.getTarget();
198 OpenFlowSwitch sw = controller.getSwitch(Dpid.dpid(flowRule.deviceId().uri()));
alshabib7911a052014-10-16 17:49:37 -0700199 if (sw == null) {
alshabib3effd042014-10-17 12:00:31 -0700200 /*
201 * if a switch we are supposed to install to is gone then
202 * cancel (ie. rollback) the work that has been done so far
203 * and return the associated future.
204 */
205 InstallationFuture failed = new InstallationFuture(sws, fmXids);
206 failed.cancel(true);
207 return failed;
alshabib7911a052014-10-16 17:49:37 -0700208 }
alshabib193525b2014-10-08 18:58:03 -0700209 sws.add(new Dpid(sw.getId()));
Jonathan Hart86e59352014-10-22 10:42:16 -0700210 FlowModBuilder builder = FlowModBuilder.builder(flowRule, sw.factory());
alshabib193525b2014-10-08 18:58:03 -0700211 switch (fbe.getOperator()) {
212 case ADD:
213 mod = builder.buildFlowAdd();
214 break;
215 case REMOVE:
216 mod = builder.buildFlowDel();
217 break;
218 case MODIFY:
219 mod = builder.buildFlowMod();
220 break;
221 default:
222 log.error("Unsupported batch operation {}", fbe.getOperator());
223 }
224 if (mod != null) {
225 sw.sendMsg(mod);
226 fmXids.put(mod.getXid(), fbe);
227 } else {
228 log.error("Conversion of flowrule {} failed.", flowRule);
229 }
alshabib219ebaa2014-09-22 15:41:24 -0700230
alshabib193525b2014-10-08 18:58:03 -0700231 }
232 InstallationFuture installation = new InstallationFuture(sws, fmXids);
233 for (Long xid : fmXids.keySet()) {
234 pendingFMs.put(xid, installation);
235 }
236 pendingFutures.put(U32.f(batch.hashCode()), installation);
alshabibdfc7afb2014-10-21 20:13:27 -0700237 installation.verify(U32.f(batch.hashCode()));
alshabib193525b2014-10-08 18:58:03 -0700238 return installation;
239 }
240
241
alshabib8f1cf4a2014-09-17 14:44:48 -0700242 private class InternalFlowProvider
243 implements OpenFlowSwitchListener, OpenFlowEventListener {
244
alshabib3d643ec2014-10-22 18:33:00 -0700245
alshabib1c319ff2014-10-04 20:29:09 -0700246 private final Multimap<DeviceId, FlowEntry> completeEntries =
alshabib54ce5892014-09-23 17:50:51 -0700247 ArrayListMultimap.create();
alshabib8f1cf4a2014-09-17 14:44:48 -0700248
249 @Override
250 public void switchAdded(Dpid dpid) {
alshabibba5ac482014-10-02 17:15:20 -0700251 FlowStatsCollector fsc = new FlowStatsCollector(controller.getSwitch(dpid), POLL_INTERVAL);
alshabibeec3a062014-09-17 18:01:26 -0700252 fsc.start();
253 collectors.put(dpid, fsc);
alshabib8f1cf4a2014-09-17 14:44:48 -0700254 }
255
256 @Override
257 public void switchRemoved(Dpid dpid) {
alshabibdfc7afb2014-10-21 20:13:27 -0700258 FlowStatsCollector collector = collectors.remove(dpid);
259 if (collector != null) {
260 collector.stop();
261 }
alshabib8f1cf4a2014-09-17 14:44:48 -0700262 }
263
264 @Override
Ayaka Koshibe38594c22014-10-22 13:36:12 -0700265 public void switchChanged(Dpid dpid) {
266 }
267
268 @Override
alshabib8f1cf4a2014-09-17 14:44:48 -0700269 public void portChanged(Dpid dpid, OFPortStatus status) {
270 //TODO: Decide whether to evict flows internal store.
271 }
272
273 @Override
274 public void handleMessage(Dpid dpid, OFMessage msg) {
alshabib902d41b2014-10-07 16:52:05 -0700275 InstallationFuture future = null;
alshabib8f1cf4a2014-09-17 14:44:48 -0700276 switch (msg.getType()) {
277 case FLOW_REMOVED:
278 OFFlowRemoved removed = (OFFlowRemoved) msg;
alshabib6b5cfec2014-09-18 17:42:18 -0700279
alshabib1c319ff2014-10-04 20:29:09 -0700280 FlowEntry fr = new FlowEntryBuilder(dpid, removed).build();
alshabib8f1cf4a2014-09-17 14:44:48 -0700281 providerService.flowRemoved(fr);
282 break;
283 case STATS_REPLY:
alshabib97044902014-09-18 14:52:16 -0700284 pushFlowMetrics(dpid, (OFStatsReply) msg);
alshabibeec3a062014-09-17 18:01:26 -0700285 break;
alshabib8f1cf4a2014-09-17 14:44:48 -0700286 case BARRIER_REPLY:
alshabib902d41b2014-10-07 16:52:05 -0700287 future = pendingFutures.get(msg.getXid());
288 if (future != null) {
289 future.satisfyRequirement(dpid);
290 }
291 break;
alshabib8f1cf4a2014-09-17 14:44:48 -0700292 case ERROR:
alshabib193525b2014-10-08 18:58:03 -0700293 future = pendingFMs.get(msg.getXid());
alshabib902d41b2014-10-07 16:52:05 -0700294 if (future != null) {
295 future.fail((OFErrorMsg) msg, dpid);
296 }
297 break;
alshabib8f1cf4a2014-09-17 14:44:48 -0700298 default:
alshabib6eb438a2014-10-01 16:39:37 -0700299 log.debug("Unhandled message type: {}", msg.getType());
alshabib8f1cf4a2014-09-17 14:44:48 -0700300 }
301
302 }
303
Ayaka Koshibeab91cc42014-09-25 10:20:52 -0700304 @Override
alshabib193525b2014-10-08 18:58:03 -0700305 public void roleAssertFailed(Dpid dpid, RoleState role) {}
Ayaka Koshibeab91cc42014-09-25 10:20:52 -0700306
alshabib54ce5892014-09-23 17:50:51 -0700307 private synchronized void pushFlowMetrics(Dpid dpid, OFStatsReply stats) {
alshabib5c370ff2014-09-18 10:12:14 -0700308 if (stats.getStatsType() != OFStatsType.FLOW) {
309 return;
310 }
alshabib54ce5892014-09-23 17:50:51 -0700311 DeviceId did = DeviceId.deviceId(Dpid.uri(dpid));
alshabib5c370ff2014-09-18 10:12:14 -0700312 final OFFlowStatsReply replies = (OFFlowStatsReply) stats;
alshabib54ce5892014-09-23 17:50:51 -0700313 //final List<FlowRule> entries = Lists.newLinkedList();
314
alshabib5c370ff2014-09-18 10:12:14 -0700315 for (OFFlowStatsEntry reply : replies.getEntries()) {
alshabib19fdc122014-10-03 11:38:19 -0700316 if (!tableMissRule(dpid, reply)) {
alshabib1c319ff2014-10-04 20:29:09 -0700317 completeEntries.put(did, new FlowEntryBuilder(dpid, reply).build());
alshabib19fdc122014-10-03 11:38:19 -0700318 }
alshabib5c370ff2014-09-18 10:12:14 -0700319 }
alshabib54ce5892014-09-23 17:50:51 -0700320
321 if (!stats.getFlags().contains(OFStatsReplyFlags.REPLY_MORE)) {
322 log.debug("sending flowstats to core {}", completeEntries.get(did));
323 providerService.pushFlowMetrics(did, completeEntries.get(did));
324 completeEntries.removeAll(did);
325 }
alshabib5c370ff2014-09-18 10:12:14 -0700326 }
327
alshabib19fdc122014-10-03 11:38:19 -0700328 private boolean tableMissRule(Dpid dpid, OFFlowStatsEntry reply) {
alshabib19fdc122014-10-03 11:38:19 -0700329 if (reply.getVersion().equals(OFVersion.OF_10) ||
330 reply.getMatch().getMatchFields().iterator().hasNext()) {
331 return false;
332 }
333 for (OFInstruction ins : reply.getInstructions()) {
334 if (ins.getType() == OFInstructionType.APPLY_ACTIONS) {
335 OFInstructionApplyActions apply = (OFInstructionApplyActions) ins;
336 List<OFAction> acts = apply.getActions();
337 for (OFAction act : acts) {
338 if (act.getType() == OFActionType.OUTPUT) {
339 OFActionOutput out = (OFActionOutput) act;
340 if (out.getPort() == OFPort.CONTROLLER) {
341 return true;
342 }
343 }
344 }
345 }
346 }
347 return false;
348 }
Ayaka Koshibe38594c22014-10-22 13:36:12 -0700349
alshabib8f1cf4a2014-09-17 14:44:48 -0700350 }
alshabib1cc04f72014-09-16 16:09:58 -0700351
Madan Jampani117aaae2014-10-23 10:04:05 -0700352 private class InstallationFuture implements ListenableFuture<CompletedBatchOperation> {
alshabib902d41b2014-10-07 16:52:05 -0700353
354 private final Set<Dpid> sws;
355 private final AtomicBoolean ok = new AtomicBoolean(true);
alshabib193525b2014-10-08 18:58:03 -0700356 private final Map<Long, FlowRuleBatchEntry> fms;
357
Madan Jampani117aaae2014-10-23 10:04:05 -0700358 private final Set<FlowEntry> offendingFlowMods = Sets.newHashSet();
alshabib902d41b2014-10-07 16:52:05 -0700359
360 private final CountDownLatch countDownLatch;
alshabibdfc7afb2014-10-21 20:13:27 -0700361 private Long pendingXid;
alshabib193525b2014-10-08 18:58:03 -0700362 private BatchState state;
alshabib902d41b2014-10-07 16:52:05 -0700363
Madan Jampani117aaae2014-10-23 10:04:05 -0700364 private final ExecutionList executionList = new ExecutionList();
365
alshabib193525b2014-10-08 18:58:03 -0700366 public InstallationFuture(Set<Dpid> sws, Map<Long, FlowRuleBatchEntry> fmXids) {
367 this.state = BatchState.STARTED;
alshabib902d41b2014-10-07 16:52:05 -0700368 this.sws = sws;
alshabib193525b2014-10-08 18:58:03 -0700369 this.fms = fmXids;
alshabib902d41b2014-10-07 16:52:05 -0700370 countDownLatch = new CountDownLatch(sws.size());
371 }
372
373 public void fail(OFErrorMsg msg, Dpid dpid) {
Madan Jampani117aaae2014-10-23 10:04:05 -0700374
alshabib902d41b2014-10-07 16:52:05 -0700375 ok.set(false);
alshabib7911a052014-10-16 17:49:37 -0700376 removeRequirement(dpid);
alshabib193525b2014-10-08 18:58:03 -0700377 FlowEntry fe = null;
378 FlowRuleBatchEntry fbe = fms.get(msg.getXid());
379 FlowRule offending = fbe.getTarget();
alshabib902d41b2014-10-07 16:52:05 -0700380 //TODO handle specific error msgs
alshabib902d41b2014-10-07 16:52:05 -0700381 switch (msg.getErrType()) {
382 case BAD_ACTION:
alshabib193525b2014-10-08 18:58:03 -0700383 OFBadActionErrorMsg bad = (OFBadActionErrorMsg) msg;
384 fe = new DefaultFlowEntry(offending, bad.getErrType().ordinal(),
385 bad.getCode().ordinal());
alshabib902d41b2014-10-07 16:52:05 -0700386 break;
387 case BAD_INSTRUCTION:
alshabib193525b2014-10-08 18:58:03 -0700388 OFBadInstructionErrorMsg badins = (OFBadInstructionErrorMsg) msg;
389 fe = new DefaultFlowEntry(offending, badins.getErrType().ordinal(),
390 badins.getCode().ordinal());
alshabib902d41b2014-10-07 16:52:05 -0700391 break;
392 case BAD_MATCH:
alshabib193525b2014-10-08 18:58:03 -0700393 OFBadMatchErrorMsg badMatch = (OFBadMatchErrorMsg) msg;
394 fe = new DefaultFlowEntry(offending, badMatch.getErrType().ordinal(),
395 badMatch.getCode().ordinal());
alshabib902d41b2014-10-07 16:52:05 -0700396 break;
397 case BAD_REQUEST:
alshabib193525b2014-10-08 18:58:03 -0700398 OFBadRequestErrorMsg badReq = (OFBadRequestErrorMsg) msg;
399 fe = new DefaultFlowEntry(offending, badReq.getErrType().ordinal(),
400 badReq.getCode().ordinal());
alshabib902d41b2014-10-07 16:52:05 -0700401 break;
402 case FLOW_MOD_FAILED:
alshabib193525b2014-10-08 18:58:03 -0700403 OFFlowModFailedErrorMsg fmFail = (OFFlowModFailedErrorMsg) msg;
404 fe = new DefaultFlowEntry(offending, fmFail.getErrType().ordinal(),
405 fmFail.getCode().ordinal());
alshabib902d41b2014-10-07 16:52:05 -0700406 break;
alshabib193525b2014-10-08 18:58:03 -0700407 case EXPERIMENTER:
alshabib902d41b2014-10-07 16:52:05 -0700408 case GROUP_MOD_FAILED:
alshabib902d41b2014-10-07 16:52:05 -0700409 case HELLO_FAILED:
alshabib902d41b2014-10-07 16:52:05 -0700410 case METER_MOD_FAILED:
alshabib902d41b2014-10-07 16:52:05 -0700411 case PORT_MOD_FAILED:
alshabib902d41b2014-10-07 16:52:05 -0700412 case QUEUE_OP_FAILED:
alshabib902d41b2014-10-07 16:52:05 -0700413 case ROLE_REQUEST_FAILED:
alshabib902d41b2014-10-07 16:52:05 -0700414 case SWITCH_CONFIG_FAILED:
alshabib902d41b2014-10-07 16:52:05 -0700415 case TABLE_FEATURES_FAILED:
alshabib902d41b2014-10-07 16:52:05 -0700416 case TABLE_MOD_FAILED:
alshabib193525b2014-10-08 18:58:03 -0700417 fe = new DefaultFlowEntry(offending, msg.getErrType().ordinal(), 0);
alshabib902d41b2014-10-07 16:52:05 -0700418 break;
419 default:
alshabib193525b2014-10-08 18:58:03 -0700420 log.error("Unknown error type {}", msg.getErrType());
alshabib902d41b2014-10-07 16:52:05 -0700421
422 }
alshabib193525b2014-10-08 18:58:03 -0700423 offendingFlowMods.add(fe);
alshabib902d41b2014-10-07 16:52:05 -0700424
425 }
426
alshabib193525b2014-10-08 18:58:03 -0700427
alshabib902d41b2014-10-07 16:52:05 -0700428 public void satisfyRequirement(Dpid dpid) {
alshabib3effd042014-10-17 12:00:31 -0700429 log.debug("Satisfaction from switch {}", dpid);
alshabib7911a052014-10-16 17:49:37 -0700430 removeRequirement(dpid);
alshabib902d41b2014-10-07 16:52:05 -0700431 }
432
alshabib193525b2014-10-08 18:58:03 -0700433
alshabibdfc7afb2014-10-21 20:13:27 -0700434 public void verify(Long id) {
alshabib193525b2014-10-08 18:58:03 -0700435 pendingXid = id;
alshabib902d41b2014-10-07 16:52:05 -0700436 for (Dpid dpid : sws) {
437 OpenFlowSwitch sw = controller.getSwitch(dpid);
438 OFBarrierRequest.Builder builder = sw.factory()
439 .buildBarrierRequest()
440 .setXid(id);
441 sw.sendMsg(builder.build());
442 }
alshabib902d41b2014-10-07 16:52:05 -0700443 }
444
445 @Override
446 public boolean cancel(boolean mayInterruptIfRunning) {
Madan Jampani117aaae2014-10-23 10:04:05 -0700447 if (isDone()) {
448 return false;
449 }
alshabib7911a052014-10-16 17:49:37 -0700450 ok.set(false);
alshabib193525b2014-10-08 18:58:03 -0700451 this.state = BatchState.CANCELLED;
452 cleanUp();
453 for (FlowRuleBatchEntry fbe : fms.values()) {
454 if (fbe.getOperator() == FlowRuleOperation.ADD ||
455 fbe.getOperator() == FlowRuleOperation.MODIFY) {
456 removeFlowRule(fbe.getTarget());
457 } else if (fbe.getOperator() == FlowRuleOperation.REMOVE) {
458 applyRule(fbe.getTarget());
459 }
460
461 }
Madan Jampani117aaae2014-10-23 10:04:05 -0700462 invokeCallbacks();
463 return true;
alshabib902d41b2014-10-07 16:52:05 -0700464 }
465
466 @Override
467 public boolean isCancelled() {
alshabib193525b2014-10-08 18:58:03 -0700468 return this.state == BatchState.CANCELLED;
alshabib902d41b2014-10-07 16:52:05 -0700469 }
470
471 @Override
472 public boolean isDone() {
Madan Jampani117aaae2014-10-23 10:04:05 -0700473 return this.state == BatchState.FINISHED || isCancelled();
alshabib902d41b2014-10-07 16:52:05 -0700474 }
475
476 @Override
alshabib193525b2014-10-08 18:58:03 -0700477 public CompletedBatchOperation get() throws InterruptedException, ExecutionException {
alshabib902d41b2014-10-07 16:52:05 -0700478 countDownLatch.await();
alshabib193525b2014-10-08 18:58:03 -0700479 this.state = BatchState.FINISHED;
Madan Jampani117aaae2014-10-23 10:04:05 -0700480 CompletedBatchOperation result = new CompletedBatchOperation(ok.get(), offendingFlowMods);
481 return result;
alshabib902d41b2014-10-07 16:52:05 -0700482 }
483
484 @Override
alshabib193525b2014-10-08 18:58:03 -0700485 public CompletedBatchOperation get(long timeout, TimeUnit unit)
alshabib902d41b2014-10-07 16:52:05 -0700486 throws InterruptedException, ExecutionException,
487 TimeoutException {
alshabib26834582014-10-08 20:15:46 -0700488 if (countDownLatch.await(timeout, unit)) {
489 this.state = BatchState.FINISHED;
Madan Jampani117aaae2014-10-23 10:04:05 -0700490 CompletedBatchOperation result = new CompletedBatchOperation(ok.get(), offendingFlowMods);
491 return result;
alshabib26834582014-10-08 20:15:46 -0700492 }
493 throw new TimeoutException();
alshabib193525b2014-10-08 18:58:03 -0700494 }
495
496 private void cleanUp() {
alshabib7911a052014-10-16 17:49:37 -0700497 if (isDone() || isCancelled()) {
alshabibdfc7afb2014-10-21 20:13:27 -0700498 if (pendingXid != null) {
499 pendingFutures.remove(pendingXid);
500 }
alshabib193525b2014-10-08 18:58:03 -0700501 for (Long xid : fms.keySet()) {
502 pendingFMs.remove(xid);
503 }
504 }
alshabib902d41b2014-10-07 16:52:05 -0700505 }
506
alshabib7911a052014-10-16 17:49:37 -0700507 private void removeRequirement(Dpid dpid) {
508 countDownLatch.countDown();
Madan Jampani117aaae2014-10-23 10:04:05 -0700509 if (countDownLatch.getCount() == 0) {
510 invokeCallbacks();
511 }
alshabib7911a052014-10-16 17:49:37 -0700512 sws.remove(dpid);
513 cleanUp();
514 }
515
Madan Jampani117aaae2014-10-23 10:04:05 -0700516 @Override
517 public void addListener(Runnable runnable, Executor executor) {
518 executionList.add(runnable, executor);
519 }
520
521 private void invokeCallbacks() {
522 executionList.execute();
523 }
alshabib902d41b2014-10-07 16:52:05 -0700524 }
alshabiba68eb962014-09-24 20:34:13 -0700525
alshabib1cc04f72014-09-16 16:09:58 -0700526}