blob: 05860f604c1dd4c3eea888b64f3879bdcb22c6f8 [file] [log] [blame]
Thomas Vachuska781d18b2014-10-27 10:31:25 -07001/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
alshabib1cc04f72014-09-16 16:09:58 -070019package org.onlab.onos.provider.of.flow.impl;
20
Jonathan Hart11096402014-10-20 17:31:49 -070021import static org.slf4j.LoggerFactory.getLogger;
22
23import java.util.Collections;
24import java.util.HashMap;
25import java.util.List;
26import java.util.Map;
27import java.util.Set;
28import java.util.concurrent.ConcurrentHashMap;
29import java.util.concurrent.CountDownLatch;
30import java.util.concurrent.ExecutionException;
Madan Jampani117aaae2014-10-23 10:04:05 -070031import java.util.concurrent.Executor;
Jonathan Hart11096402014-10-20 17:31:49 -070032import java.util.concurrent.TimeUnit;
33import java.util.concurrent.TimeoutException;
34import java.util.concurrent.atomic.AtomicBoolean;
35
alshabib1cc04f72014-09-16 16:09:58 -070036import org.apache.felix.scr.annotations.Activate;
37import org.apache.felix.scr.annotations.Component;
38import org.apache.felix.scr.annotations.Deactivate;
39import org.apache.felix.scr.annotations.Reference;
40import org.apache.felix.scr.annotations.ReferenceCardinality;
Thomas Vachuskae0f804a2014-10-27 23:40:48 -070041import org.onlab.onos.core.ApplicationId;
alshabiba7f7ca82014-09-22 11:41:23 -070042import org.onlab.onos.net.DeviceId;
Jonathan Hart86e59352014-10-22 10:42:16 -070043import org.onlab.onos.net.flow.BatchOperation;
alshabib193525b2014-10-08 18:58:03 -070044import org.onlab.onos.net.flow.CompletedBatchOperation;
45import org.onlab.onos.net.flow.DefaultFlowEntry;
alshabib1c319ff2014-10-04 20:29:09 -070046import org.onlab.onos.net.flow.FlowEntry;
alshabib1cc04f72014-09-16 16:09:58 -070047import org.onlab.onos.net.flow.FlowRule;
alshabib902d41b2014-10-07 16:52:05 -070048import org.onlab.onos.net.flow.FlowRuleBatchEntry;
alshabib193525b2014-10-08 18:58:03 -070049import org.onlab.onos.net.flow.FlowRuleBatchEntry.FlowRuleOperation;
alshabib1cc04f72014-09-16 16:09:58 -070050import org.onlab.onos.net.flow.FlowRuleProvider;
51import org.onlab.onos.net.flow.FlowRuleProviderRegistry;
52import org.onlab.onos.net.flow.FlowRuleProviderService;
53import org.onlab.onos.net.provider.AbstractProvider;
54import org.onlab.onos.net.provider.ProviderId;
55import org.onlab.onos.net.topology.TopologyService;
tom9c94c5b2014-09-17 13:14:42 -070056import org.onlab.onos.openflow.controller.Dpid;
57import org.onlab.onos.openflow.controller.OpenFlowController;
alshabibeec3a062014-09-17 18:01:26 -070058import org.onlab.onos.openflow.controller.OpenFlowEventListener;
tom9c94c5b2014-09-17 13:14:42 -070059import org.onlab.onos.openflow.controller.OpenFlowSwitch;
alshabibce4e5782014-09-17 14:56:42 -070060import org.onlab.onos.openflow.controller.OpenFlowSwitchListener;
Ayaka Koshibeab91cc42014-09-25 10:20:52 -070061import org.onlab.onos.openflow.controller.RoleState;
alshabib19fdc122014-10-03 11:38:19 -070062import org.projectfloodlight.openflow.protocol.OFActionType;
alshabib902d41b2014-10-07 16:52:05 -070063import org.projectfloodlight.openflow.protocol.OFBarrierRequest;
64import org.projectfloodlight.openflow.protocol.OFErrorMsg;
alshabib193525b2014-10-08 18:58:03 -070065import org.projectfloodlight.openflow.protocol.OFFlowMod;
alshabib8f1cf4a2014-09-17 14:44:48 -070066import org.projectfloodlight.openflow.protocol.OFFlowRemoved;
alshabib5c370ff2014-09-18 10:12:14 -070067import org.projectfloodlight.openflow.protocol.OFFlowStatsEntry;
68import org.projectfloodlight.openflow.protocol.OFFlowStatsReply;
alshabib19fdc122014-10-03 11:38:19 -070069import org.projectfloodlight.openflow.protocol.OFInstructionType;
alshabib8f1cf4a2014-09-17 14:44:48 -070070import org.projectfloodlight.openflow.protocol.OFMessage;
71import org.projectfloodlight.openflow.protocol.OFPortStatus;
alshabib5c370ff2014-09-18 10:12:14 -070072import org.projectfloodlight.openflow.protocol.OFStatsReply;
alshabib54ce5892014-09-23 17:50:51 -070073import org.projectfloodlight.openflow.protocol.OFStatsReplyFlags;
alshabib5c370ff2014-09-18 10:12:14 -070074import org.projectfloodlight.openflow.protocol.OFStatsType;
alshabib19fdc122014-10-03 11:38:19 -070075import org.projectfloodlight.openflow.protocol.OFVersion;
76import org.projectfloodlight.openflow.protocol.action.OFAction;
77import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
alshabib193525b2014-10-08 18:58:03 -070078import org.projectfloodlight.openflow.protocol.errormsg.OFBadActionErrorMsg;
79import org.projectfloodlight.openflow.protocol.errormsg.OFBadInstructionErrorMsg;
80import org.projectfloodlight.openflow.protocol.errormsg.OFBadMatchErrorMsg;
81import org.projectfloodlight.openflow.protocol.errormsg.OFBadRequestErrorMsg;
82import org.projectfloodlight.openflow.protocol.errormsg.OFFlowModFailedErrorMsg;
alshabib19fdc122014-10-03 11:38:19 -070083import org.projectfloodlight.openflow.protocol.instruction.OFInstruction;
84import org.projectfloodlight.openflow.protocol.instruction.OFInstructionApplyActions;
85import org.projectfloodlight.openflow.types.OFPort;
alshabib902d41b2014-10-07 16:52:05 -070086import org.projectfloodlight.openflow.types.U32;
alshabib1cc04f72014-09-16 16:09:58 -070087import org.slf4j.Logger;
88
Jonathan Hart11096402014-10-20 17:31:49 -070089import com.google.common.collect.ArrayListMultimap;
Jonathan Hart11096402014-10-20 17:31:49 -070090import com.google.common.collect.Maps;
91import com.google.common.collect.Multimap;
Madan Jampani117aaae2014-10-23 10:04:05 -070092import com.google.common.collect.Sets;
93import com.google.common.util.concurrent.ExecutionList;
94import com.google.common.util.concurrent.ListenableFuture;
alshabibeec3a062014-09-17 18:01:26 -070095
alshabib1cc04f72014-09-16 16:09:58 -070096/**
97 * Provider which uses an OpenFlow controller to detect network
98 * end-station hosts.
99 */
100@Component(immediate = true)
101public class OpenFlowRuleProvider extends AbstractProvider implements FlowRuleProvider {
102
alshabib193525b2014-10-08 18:58:03 -0700103 enum BatchState { STARTED, FINISHED, CANCELLED };
104
alshabib1cc04f72014-09-16 16:09:58 -0700105 private final Logger log = getLogger(getClass());
106
107 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
108 protected FlowRuleProviderRegistry providerRegistry;
109
110 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
111 protected OpenFlowController controller;
112
113 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
114 protected TopologyService topologyService;
115
116 private FlowRuleProviderService providerService;
117
alshabibeec3a062014-09-17 18:01:26 -0700118 private final InternalFlowProvider listener = new InternalFlowProvider();
119
Madan Jampani117aaae2014-10-23 10:04:05 -0700120 // FIXME: This should be an expiring map to ensure futures that don't have
121 // a future eventually get garbage collected.
alshabib902d41b2014-10-07 16:52:05 -0700122 private final Map<Long, InstallationFuture> pendingFutures =
123 new ConcurrentHashMap<Long, InstallationFuture>();
124
alshabib193525b2014-10-08 18:58:03 -0700125 private final Map<Long, InstallationFuture> pendingFMs =
126 new ConcurrentHashMap<Long, InstallationFuture>();
127
alshabib3d643ec2014-10-22 18:33:00 -0700128 private final Map<Dpid, FlowStatsCollector> collectors = Maps.newHashMap();
129
alshabib1cc04f72014-09-16 16:09:58 -0700130 /**
131 * Creates an OpenFlow host provider.
132 */
133 public OpenFlowRuleProvider() {
tom7e02cda2014-09-18 12:05:46 -0700134 super(new ProviderId("of", "org.onlab.onos.provider.openflow"));
alshabib1cc04f72014-09-16 16:09:58 -0700135 }
136
137 @Activate
138 public void activate() {
139 providerService = providerRegistry.register(this);
alshabibeec3a062014-09-17 18:01:26 -0700140 controller.addListener(listener);
141 controller.addEventListener(listener);
alshabib3d643ec2014-10-22 18:33:00 -0700142
143 for (OpenFlowSwitch sw : controller.getSwitches()) {
144 FlowStatsCollector fsc = new FlowStatsCollector(sw, POLL_INTERVAL);
145 fsc.start();
146 collectors.put(new Dpid(sw.getId()), fsc);
147 }
148
149
alshabib1cc04f72014-09-16 16:09:58 -0700150 log.info("Started");
151 }
152
153 @Deactivate
154 public void deactivate() {
155 providerRegistry.unregister(this);
156 providerService = null;
157
158 log.info("Stopped");
159 }
160 @Override
161 public void applyFlowRule(FlowRule... flowRules) {
alshabib35edb1a2014-09-16 17:44:44 -0700162 for (int i = 0; i < flowRules.length; i++) {
163 applyRule(flowRules[i]);
164 }
alshabib1cc04f72014-09-16 16:09:58 -0700165 }
166
alshabib35edb1a2014-09-16 17:44:44 -0700167 private void applyRule(FlowRule flowRule) {
168 OpenFlowSwitch sw = controller.getSwitch(Dpid.dpid(flowRule.deviceId().uri()));
Jonathan Hart86e59352014-10-22 10:42:16 -0700169 sw.sendMsg(FlowModBuilder.builder(flowRule, sw.factory()).buildFlowAdd());
alshabib35edb1a2014-09-16 17:44:44 -0700170 }
171
alshabib35edb1a2014-09-16 17:44:44 -0700172
alshabib35edb1a2014-09-16 17:44:44 -0700173
alshabib1cc04f72014-09-16 16:09:58 -0700174 @Override
175 public void removeFlowRule(FlowRule... flowRules) {
alshabib219ebaa2014-09-22 15:41:24 -0700176 for (int i = 0; i < flowRules.length; i++) {
177 removeRule(flowRules[i]);
178 }
alshabib1cc04f72014-09-16 16:09:58 -0700179
180 }
181
alshabib219ebaa2014-09-22 15:41:24 -0700182 private void removeRule(FlowRule flowRule) {
183 OpenFlowSwitch sw = controller.getSwitch(Dpid.dpid(flowRule.deviceId().uri()));
Jonathan Hart86e59352014-10-22 10:42:16 -0700184 sw.sendMsg(FlowModBuilder.builder(flowRule, sw.factory()).buildFlowDel());
alshabib219ebaa2014-09-22 15:41:24 -0700185 }
186
alshabiba68eb962014-09-24 20:34:13 -0700187 @Override
188 public void removeRulesById(ApplicationId id, FlowRule... flowRules) {
189 // TODO: optimize using the ApplicationId
190 removeFlowRule(flowRules);
191 }
192
alshabib193525b2014-10-08 18:58:03 -0700193 @Override
Madan Jampani117aaae2014-10-23 10:04:05 -0700194 public ListenableFuture<CompletedBatchOperation> executeBatch(BatchOperation<FlowRuleBatchEntry> batch) {
Jonathan Hart11096402014-10-20 17:31:49 -0700195 final Set<Dpid> sws =
196 Collections.newSetFromMap(new ConcurrentHashMap<Dpid, Boolean>());
alshabib193525b2014-10-08 18:58:03 -0700197 final Map<Long, FlowRuleBatchEntry> fmXids = new HashMap<Long, FlowRuleBatchEntry>();
198 OFFlowMod mod = null;
199 for (FlowRuleBatchEntry fbe : batch.getOperations()) {
200 FlowRule flowRule = fbe.getTarget();
201 OpenFlowSwitch sw = controller.getSwitch(Dpid.dpid(flowRule.deviceId().uri()));
alshabib7911a052014-10-16 17:49:37 -0700202 if (sw == null) {
alshabib3effd042014-10-17 12:00:31 -0700203 /*
204 * if a switch we are supposed to install to is gone then
205 * cancel (ie. rollback) the work that has been done so far
206 * and return the associated future.
207 */
208 InstallationFuture failed = new InstallationFuture(sws, fmXids);
209 failed.cancel(true);
210 return failed;
alshabib7911a052014-10-16 17:49:37 -0700211 }
alshabib193525b2014-10-08 18:58:03 -0700212 sws.add(new Dpid(sw.getId()));
Jonathan Hart86e59352014-10-22 10:42:16 -0700213 FlowModBuilder builder = FlowModBuilder.builder(flowRule, sw.factory());
alshabib193525b2014-10-08 18:58:03 -0700214 switch (fbe.getOperator()) {
215 case ADD:
216 mod = builder.buildFlowAdd();
217 break;
218 case REMOVE:
219 mod = builder.buildFlowDel();
220 break;
221 case MODIFY:
222 mod = builder.buildFlowMod();
223 break;
224 default:
225 log.error("Unsupported batch operation {}", fbe.getOperator());
226 }
227 if (mod != null) {
228 sw.sendMsg(mod);
229 fmXids.put(mod.getXid(), fbe);
230 } else {
231 log.error("Conversion of flowrule {} failed.", flowRule);
232 }
alshabib219ebaa2014-09-22 15:41:24 -0700233
alshabib193525b2014-10-08 18:58:03 -0700234 }
235 InstallationFuture installation = new InstallationFuture(sws, fmXids);
236 for (Long xid : fmXids.keySet()) {
237 pendingFMs.put(xid, installation);
238 }
239 pendingFutures.put(U32.f(batch.hashCode()), installation);
alshabibdfc7afb2014-10-21 20:13:27 -0700240 installation.verify(U32.f(batch.hashCode()));
alshabib193525b2014-10-08 18:58:03 -0700241 return installation;
242 }
243
244
alshabib8f1cf4a2014-09-17 14:44:48 -0700245 private class InternalFlowProvider
246 implements OpenFlowSwitchListener, OpenFlowEventListener {
247
alshabib3d643ec2014-10-22 18:33:00 -0700248
alshabib1c319ff2014-10-04 20:29:09 -0700249 private final Multimap<DeviceId, FlowEntry> completeEntries =
alshabib54ce5892014-09-23 17:50:51 -0700250 ArrayListMultimap.create();
alshabib8f1cf4a2014-09-17 14:44:48 -0700251
252 @Override
253 public void switchAdded(Dpid dpid) {
alshabibba5ac482014-10-02 17:15:20 -0700254 FlowStatsCollector fsc = new FlowStatsCollector(controller.getSwitch(dpid), POLL_INTERVAL);
alshabibeec3a062014-09-17 18:01:26 -0700255 fsc.start();
256 collectors.put(dpid, fsc);
alshabib8f1cf4a2014-09-17 14:44:48 -0700257 }
258
259 @Override
260 public void switchRemoved(Dpid dpid) {
alshabibdfc7afb2014-10-21 20:13:27 -0700261 FlowStatsCollector collector = collectors.remove(dpid);
262 if (collector != null) {
263 collector.stop();
264 }
alshabib8f1cf4a2014-09-17 14:44:48 -0700265 }
266
267 @Override
Ayaka Koshibe38594c22014-10-22 13:36:12 -0700268 public void switchChanged(Dpid dpid) {
269 }
270
271 @Override
alshabib8f1cf4a2014-09-17 14:44:48 -0700272 public void portChanged(Dpid dpid, OFPortStatus status) {
273 //TODO: Decide whether to evict flows internal store.
274 }
275
276 @Override
277 public void handleMessage(Dpid dpid, OFMessage msg) {
alshabib902d41b2014-10-07 16:52:05 -0700278 InstallationFuture future = null;
alshabib8f1cf4a2014-09-17 14:44:48 -0700279 switch (msg.getType()) {
280 case FLOW_REMOVED:
281 OFFlowRemoved removed = (OFFlowRemoved) msg;
alshabib6b5cfec2014-09-18 17:42:18 -0700282
alshabib1c319ff2014-10-04 20:29:09 -0700283 FlowEntry fr = new FlowEntryBuilder(dpid, removed).build();
alshabib8f1cf4a2014-09-17 14:44:48 -0700284 providerService.flowRemoved(fr);
285 break;
286 case STATS_REPLY:
alshabib97044902014-09-18 14:52:16 -0700287 pushFlowMetrics(dpid, (OFStatsReply) msg);
alshabibeec3a062014-09-17 18:01:26 -0700288 break;
alshabib8f1cf4a2014-09-17 14:44:48 -0700289 case BARRIER_REPLY:
alshabib902d41b2014-10-07 16:52:05 -0700290 future = pendingFutures.get(msg.getXid());
291 if (future != null) {
292 future.satisfyRequirement(dpid);
293 }
294 break;
alshabib8f1cf4a2014-09-17 14:44:48 -0700295 case ERROR:
alshabib193525b2014-10-08 18:58:03 -0700296 future = pendingFMs.get(msg.getXid());
alshabib902d41b2014-10-07 16:52:05 -0700297 if (future != null) {
298 future.fail((OFErrorMsg) msg, dpid);
299 }
300 break;
alshabib8f1cf4a2014-09-17 14:44:48 -0700301 default:
alshabib6eb438a2014-10-01 16:39:37 -0700302 log.debug("Unhandled message type: {}", msg.getType());
alshabib8f1cf4a2014-09-17 14:44:48 -0700303 }
304
305 }
306
Ayaka Koshibeab91cc42014-09-25 10:20:52 -0700307 @Override
alshabib193525b2014-10-08 18:58:03 -0700308 public void roleAssertFailed(Dpid dpid, RoleState role) {}
Ayaka Koshibeab91cc42014-09-25 10:20:52 -0700309
alshabib54ce5892014-09-23 17:50:51 -0700310 private synchronized void pushFlowMetrics(Dpid dpid, OFStatsReply stats) {
alshabib5c370ff2014-09-18 10:12:14 -0700311 if (stats.getStatsType() != OFStatsType.FLOW) {
312 return;
313 }
alshabib54ce5892014-09-23 17:50:51 -0700314 DeviceId did = DeviceId.deviceId(Dpid.uri(dpid));
alshabib5c370ff2014-09-18 10:12:14 -0700315 final OFFlowStatsReply replies = (OFFlowStatsReply) stats;
alshabib54ce5892014-09-23 17:50:51 -0700316 //final List<FlowRule> entries = Lists.newLinkedList();
317
alshabib5c370ff2014-09-18 10:12:14 -0700318 for (OFFlowStatsEntry reply : replies.getEntries()) {
alshabib19fdc122014-10-03 11:38:19 -0700319 if (!tableMissRule(dpid, reply)) {
alshabib1c319ff2014-10-04 20:29:09 -0700320 completeEntries.put(did, new FlowEntryBuilder(dpid, reply).build());
alshabib19fdc122014-10-03 11:38:19 -0700321 }
alshabib5c370ff2014-09-18 10:12:14 -0700322 }
alshabib54ce5892014-09-23 17:50:51 -0700323
324 if (!stats.getFlags().contains(OFStatsReplyFlags.REPLY_MORE)) {
325 log.debug("sending flowstats to core {}", completeEntries.get(did));
326 providerService.pushFlowMetrics(did, completeEntries.get(did));
327 completeEntries.removeAll(did);
328 }
alshabib5c370ff2014-09-18 10:12:14 -0700329 }
330
alshabib19fdc122014-10-03 11:38:19 -0700331 private boolean tableMissRule(Dpid dpid, OFFlowStatsEntry reply) {
alshabib19fdc122014-10-03 11:38:19 -0700332 if (reply.getVersion().equals(OFVersion.OF_10) ||
333 reply.getMatch().getMatchFields().iterator().hasNext()) {
334 return false;
335 }
336 for (OFInstruction ins : reply.getInstructions()) {
337 if (ins.getType() == OFInstructionType.APPLY_ACTIONS) {
338 OFInstructionApplyActions apply = (OFInstructionApplyActions) ins;
339 List<OFAction> acts = apply.getActions();
340 for (OFAction act : acts) {
341 if (act.getType() == OFActionType.OUTPUT) {
342 OFActionOutput out = (OFActionOutput) act;
343 if (out.getPort() == OFPort.CONTROLLER) {
344 return true;
345 }
346 }
347 }
348 }
349 }
350 return false;
351 }
Ayaka Koshibe38594c22014-10-22 13:36:12 -0700352
alshabib8f1cf4a2014-09-17 14:44:48 -0700353 }
alshabib1cc04f72014-09-16 16:09:58 -0700354
Madan Jampani117aaae2014-10-23 10:04:05 -0700355 private class InstallationFuture implements ListenableFuture<CompletedBatchOperation> {
alshabib902d41b2014-10-07 16:52:05 -0700356
357 private final Set<Dpid> sws;
358 private final AtomicBoolean ok = new AtomicBoolean(true);
alshabib193525b2014-10-08 18:58:03 -0700359 private final Map<Long, FlowRuleBatchEntry> fms;
360
Madan Jampani117aaae2014-10-23 10:04:05 -0700361 private final Set<FlowEntry> offendingFlowMods = Sets.newHashSet();
alshabib902d41b2014-10-07 16:52:05 -0700362
363 private final CountDownLatch countDownLatch;
alshabibdfc7afb2014-10-21 20:13:27 -0700364 private Long pendingXid;
alshabib193525b2014-10-08 18:58:03 -0700365 private BatchState state;
alshabib902d41b2014-10-07 16:52:05 -0700366
Madan Jampani117aaae2014-10-23 10:04:05 -0700367 private final ExecutionList executionList = new ExecutionList();
368
alshabib193525b2014-10-08 18:58:03 -0700369 public InstallationFuture(Set<Dpid> sws, Map<Long, FlowRuleBatchEntry> fmXids) {
370 this.state = BatchState.STARTED;
alshabib902d41b2014-10-07 16:52:05 -0700371 this.sws = sws;
alshabib193525b2014-10-08 18:58:03 -0700372 this.fms = fmXids;
alshabib902d41b2014-10-07 16:52:05 -0700373 countDownLatch = new CountDownLatch(sws.size());
374 }
375
376 public void fail(OFErrorMsg msg, Dpid dpid) {
Madan Jampani117aaae2014-10-23 10:04:05 -0700377
alshabib902d41b2014-10-07 16:52:05 -0700378 ok.set(false);
alshabib7911a052014-10-16 17:49:37 -0700379 removeRequirement(dpid);
alshabib193525b2014-10-08 18:58:03 -0700380 FlowEntry fe = null;
381 FlowRuleBatchEntry fbe = fms.get(msg.getXid());
382 FlowRule offending = fbe.getTarget();
alshabib902d41b2014-10-07 16:52:05 -0700383 //TODO handle specific error msgs
alshabib902d41b2014-10-07 16:52:05 -0700384 switch (msg.getErrType()) {
385 case BAD_ACTION:
alshabib193525b2014-10-08 18:58:03 -0700386 OFBadActionErrorMsg bad = (OFBadActionErrorMsg) msg;
387 fe = new DefaultFlowEntry(offending, bad.getErrType().ordinal(),
388 bad.getCode().ordinal());
alshabib902d41b2014-10-07 16:52:05 -0700389 break;
390 case BAD_INSTRUCTION:
alshabib193525b2014-10-08 18:58:03 -0700391 OFBadInstructionErrorMsg badins = (OFBadInstructionErrorMsg) msg;
392 fe = new DefaultFlowEntry(offending, badins.getErrType().ordinal(),
393 badins.getCode().ordinal());
alshabib902d41b2014-10-07 16:52:05 -0700394 break;
395 case BAD_MATCH:
alshabib193525b2014-10-08 18:58:03 -0700396 OFBadMatchErrorMsg badMatch = (OFBadMatchErrorMsg) msg;
397 fe = new DefaultFlowEntry(offending, badMatch.getErrType().ordinal(),
398 badMatch.getCode().ordinal());
alshabib902d41b2014-10-07 16:52:05 -0700399 break;
400 case BAD_REQUEST:
alshabib193525b2014-10-08 18:58:03 -0700401 OFBadRequestErrorMsg badReq = (OFBadRequestErrorMsg) msg;
402 fe = new DefaultFlowEntry(offending, badReq.getErrType().ordinal(),
403 badReq.getCode().ordinal());
alshabib902d41b2014-10-07 16:52:05 -0700404 break;
405 case FLOW_MOD_FAILED:
alshabib193525b2014-10-08 18:58:03 -0700406 OFFlowModFailedErrorMsg fmFail = (OFFlowModFailedErrorMsg) msg;
407 fe = new DefaultFlowEntry(offending, fmFail.getErrType().ordinal(),
408 fmFail.getCode().ordinal());
alshabib902d41b2014-10-07 16:52:05 -0700409 break;
alshabib193525b2014-10-08 18:58:03 -0700410 case EXPERIMENTER:
alshabib902d41b2014-10-07 16:52:05 -0700411 case GROUP_MOD_FAILED:
alshabib902d41b2014-10-07 16:52:05 -0700412 case HELLO_FAILED:
alshabib902d41b2014-10-07 16:52:05 -0700413 case METER_MOD_FAILED:
alshabib902d41b2014-10-07 16:52:05 -0700414 case PORT_MOD_FAILED:
alshabib902d41b2014-10-07 16:52:05 -0700415 case QUEUE_OP_FAILED:
alshabib902d41b2014-10-07 16:52:05 -0700416 case ROLE_REQUEST_FAILED:
alshabib902d41b2014-10-07 16:52:05 -0700417 case SWITCH_CONFIG_FAILED:
alshabib902d41b2014-10-07 16:52:05 -0700418 case TABLE_FEATURES_FAILED:
alshabib902d41b2014-10-07 16:52:05 -0700419 case TABLE_MOD_FAILED:
alshabib193525b2014-10-08 18:58:03 -0700420 fe = new DefaultFlowEntry(offending, msg.getErrType().ordinal(), 0);
alshabib902d41b2014-10-07 16:52:05 -0700421 break;
422 default:
alshabib193525b2014-10-08 18:58:03 -0700423 log.error("Unknown error type {}", msg.getErrType());
alshabib902d41b2014-10-07 16:52:05 -0700424
425 }
alshabib193525b2014-10-08 18:58:03 -0700426 offendingFlowMods.add(fe);
alshabib902d41b2014-10-07 16:52:05 -0700427
428 }
429
alshabib193525b2014-10-08 18:58:03 -0700430
alshabib902d41b2014-10-07 16:52:05 -0700431 public void satisfyRequirement(Dpid dpid) {
alshabib3effd042014-10-17 12:00:31 -0700432 log.debug("Satisfaction from switch {}", dpid);
alshabib7911a052014-10-16 17:49:37 -0700433 removeRequirement(dpid);
alshabib902d41b2014-10-07 16:52:05 -0700434 }
435
alshabib193525b2014-10-08 18:58:03 -0700436
alshabibdfc7afb2014-10-21 20:13:27 -0700437 public void verify(Long id) {
alshabib193525b2014-10-08 18:58:03 -0700438 pendingXid = id;
alshabib902d41b2014-10-07 16:52:05 -0700439 for (Dpid dpid : sws) {
440 OpenFlowSwitch sw = controller.getSwitch(dpid);
441 OFBarrierRequest.Builder builder = sw.factory()
442 .buildBarrierRequest()
443 .setXid(id);
444 sw.sendMsg(builder.build());
445 }
alshabib902d41b2014-10-07 16:52:05 -0700446 }
447
448 @Override
449 public boolean cancel(boolean mayInterruptIfRunning) {
Madan Jampani117aaae2014-10-23 10:04:05 -0700450 if (isDone()) {
451 return false;
452 }
alshabib7911a052014-10-16 17:49:37 -0700453 ok.set(false);
alshabib193525b2014-10-08 18:58:03 -0700454 this.state = BatchState.CANCELLED;
455 cleanUp();
456 for (FlowRuleBatchEntry fbe : fms.values()) {
457 if (fbe.getOperator() == FlowRuleOperation.ADD ||
458 fbe.getOperator() == FlowRuleOperation.MODIFY) {
459 removeFlowRule(fbe.getTarget());
460 } else if (fbe.getOperator() == FlowRuleOperation.REMOVE) {
461 applyRule(fbe.getTarget());
462 }
463
464 }
Madan Jampani117aaae2014-10-23 10:04:05 -0700465 invokeCallbacks();
466 return true;
alshabib902d41b2014-10-07 16:52:05 -0700467 }
468
469 @Override
470 public boolean isCancelled() {
alshabib193525b2014-10-08 18:58:03 -0700471 return this.state == BatchState.CANCELLED;
alshabib902d41b2014-10-07 16:52:05 -0700472 }
473
474 @Override
475 public boolean isDone() {
Madan Jampani117aaae2014-10-23 10:04:05 -0700476 return this.state == BatchState.FINISHED || isCancelled();
alshabib902d41b2014-10-07 16:52:05 -0700477 }
478
479 @Override
alshabib193525b2014-10-08 18:58:03 -0700480 public CompletedBatchOperation get() throws InterruptedException, ExecutionException {
alshabib902d41b2014-10-07 16:52:05 -0700481 countDownLatch.await();
alshabib193525b2014-10-08 18:58:03 -0700482 this.state = BatchState.FINISHED;
Madan Jampani117aaae2014-10-23 10:04:05 -0700483 CompletedBatchOperation result = new CompletedBatchOperation(ok.get(), offendingFlowMods);
484 return result;
alshabib902d41b2014-10-07 16:52:05 -0700485 }
486
487 @Override
alshabib193525b2014-10-08 18:58:03 -0700488 public CompletedBatchOperation get(long timeout, TimeUnit unit)
alshabib902d41b2014-10-07 16:52:05 -0700489 throws InterruptedException, ExecutionException,
490 TimeoutException {
alshabib26834582014-10-08 20:15:46 -0700491 if (countDownLatch.await(timeout, unit)) {
492 this.state = BatchState.FINISHED;
Madan Jampani117aaae2014-10-23 10:04:05 -0700493 CompletedBatchOperation result = new CompletedBatchOperation(ok.get(), offendingFlowMods);
494 return result;
alshabib26834582014-10-08 20:15:46 -0700495 }
496 throw new TimeoutException();
alshabib193525b2014-10-08 18:58:03 -0700497 }
498
499 private void cleanUp() {
alshabib7911a052014-10-16 17:49:37 -0700500 if (isDone() || isCancelled()) {
alshabibdfc7afb2014-10-21 20:13:27 -0700501 if (pendingXid != null) {
502 pendingFutures.remove(pendingXid);
503 }
alshabib193525b2014-10-08 18:58:03 -0700504 for (Long xid : fms.keySet()) {
505 pendingFMs.remove(xid);
506 }
507 }
alshabib902d41b2014-10-07 16:52:05 -0700508 }
509
alshabib7911a052014-10-16 17:49:37 -0700510 private void removeRequirement(Dpid dpid) {
511 countDownLatch.countDown();
Madan Jampani117aaae2014-10-23 10:04:05 -0700512 if (countDownLatch.getCount() == 0) {
513 invokeCallbacks();
514 }
alshabib7911a052014-10-16 17:49:37 -0700515 sws.remove(dpid);
516 cleanUp();
517 }
518
Madan Jampani117aaae2014-10-23 10:04:05 -0700519 @Override
520 public void addListener(Runnable runnable, Executor executor) {
521 executionList.add(runnable, executor);
522 }
523
524 private void invokeCallbacks() {
525 executionList.execute();
526 }
alshabib902d41b2014-10-07 16:52:05 -0700527 }
alshabiba68eb962014-09-24 20:34:13 -0700528
alshabib1cc04f72014-09-16 16:09:58 -0700529}