blob: 4a21add45621c4a37a48a54dad7ca75c665efd42 [file] [log] [blame]
alshabib1cc04f72014-09-16 16:09:58 -07001package org.onlab.onos.provider.of.flow.impl;
2
Jonathan Hart11096402014-10-20 17:31:49 -07003import static org.slf4j.LoggerFactory.getLogger;
4
5import java.util.Collections;
6import java.util.HashMap;
7import java.util.List;
8import java.util.Map;
9import java.util.Set;
10import java.util.concurrent.ConcurrentHashMap;
11import java.util.concurrent.CountDownLatch;
12import java.util.concurrent.ExecutionException;
13import java.util.concurrent.Future;
14import java.util.concurrent.TimeUnit;
15import java.util.concurrent.TimeoutException;
16import java.util.concurrent.atomic.AtomicBoolean;
17
alshabib1cc04f72014-09-16 16:09:58 -070018import org.apache.felix.scr.annotations.Activate;
19import org.apache.felix.scr.annotations.Component;
20import org.apache.felix.scr.annotations.Deactivate;
21import org.apache.felix.scr.annotations.Reference;
22import org.apache.felix.scr.annotations.ReferenceCardinality;
alshabiba68eb962014-09-24 20:34:13 -070023import org.onlab.onos.ApplicationId;
alshabiba7f7ca82014-09-22 11:41:23 -070024import org.onlab.onos.net.DeviceId;
alshabib193525b2014-10-08 18:58:03 -070025import org.onlab.onos.net.flow.CompletedBatchOperation;
26import org.onlab.onos.net.flow.DefaultFlowEntry;
alshabib1c319ff2014-10-04 20:29:09 -070027import org.onlab.onos.net.flow.FlowEntry;
alshabib1cc04f72014-09-16 16:09:58 -070028import org.onlab.onos.net.flow.FlowRule;
alshabib902d41b2014-10-07 16:52:05 -070029import org.onlab.onos.net.flow.FlowRuleBatchEntry;
alshabib193525b2014-10-08 18:58:03 -070030import org.onlab.onos.net.flow.FlowRuleBatchEntry.FlowRuleOperation;
alshabib1cc04f72014-09-16 16:09:58 -070031import org.onlab.onos.net.flow.FlowRuleProvider;
32import org.onlab.onos.net.flow.FlowRuleProviderRegistry;
33import org.onlab.onos.net.flow.FlowRuleProviderService;
alshabib902d41b2014-10-07 16:52:05 -070034import org.onlab.onos.net.intent.BatchOperation;
alshabib1cc04f72014-09-16 16:09:58 -070035import org.onlab.onos.net.provider.AbstractProvider;
36import org.onlab.onos.net.provider.ProviderId;
37import org.onlab.onos.net.topology.TopologyService;
tom9c94c5b2014-09-17 13:14:42 -070038import org.onlab.onos.openflow.controller.Dpid;
39import org.onlab.onos.openflow.controller.OpenFlowController;
alshabibeec3a062014-09-17 18:01:26 -070040import org.onlab.onos.openflow.controller.OpenFlowEventListener;
tom9c94c5b2014-09-17 13:14:42 -070041import org.onlab.onos.openflow.controller.OpenFlowSwitch;
alshabibce4e5782014-09-17 14:56:42 -070042import org.onlab.onos.openflow.controller.OpenFlowSwitchListener;
Ayaka Koshibeab91cc42014-09-25 10:20:52 -070043import org.onlab.onos.openflow.controller.RoleState;
alshabib19fdc122014-10-03 11:38:19 -070044import org.projectfloodlight.openflow.protocol.OFActionType;
alshabib902d41b2014-10-07 16:52:05 -070045import org.projectfloodlight.openflow.protocol.OFBarrierRequest;
46import org.projectfloodlight.openflow.protocol.OFErrorMsg;
alshabib193525b2014-10-08 18:58:03 -070047import org.projectfloodlight.openflow.protocol.OFFlowMod;
alshabib8f1cf4a2014-09-17 14:44:48 -070048import org.projectfloodlight.openflow.protocol.OFFlowRemoved;
alshabib5c370ff2014-09-18 10:12:14 -070049import org.projectfloodlight.openflow.protocol.OFFlowStatsEntry;
50import org.projectfloodlight.openflow.protocol.OFFlowStatsReply;
alshabib19fdc122014-10-03 11:38:19 -070051import org.projectfloodlight.openflow.protocol.OFInstructionType;
alshabib8f1cf4a2014-09-17 14:44:48 -070052import org.projectfloodlight.openflow.protocol.OFMessage;
53import org.projectfloodlight.openflow.protocol.OFPortStatus;
alshabib5c370ff2014-09-18 10:12:14 -070054import org.projectfloodlight.openflow.protocol.OFStatsReply;
alshabib54ce5892014-09-23 17:50:51 -070055import org.projectfloodlight.openflow.protocol.OFStatsReplyFlags;
alshabib5c370ff2014-09-18 10:12:14 -070056import org.projectfloodlight.openflow.protocol.OFStatsType;
alshabib19fdc122014-10-03 11:38:19 -070057import org.projectfloodlight.openflow.protocol.OFVersion;
58import org.projectfloodlight.openflow.protocol.action.OFAction;
59import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
alshabib193525b2014-10-08 18:58:03 -070060import org.projectfloodlight.openflow.protocol.errormsg.OFBadActionErrorMsg;
61import org.projectfloodlight.openflow.protocol.errormsg.OFBadInstructionErrorMsg;
62import org.projectfloodlight.openflow.protocol.errormsg.OFBadMatchErrorMsg;
63import org.projectfloodlight.openflow.protocol.errormsg.OFBadRequestErrorMsg;
64import org.projectfloodlight.openflow.protocol.errormsg.OFFlowModFailedErrorMsg;
alshabib19fdc122014-10-03 11:38:19 -070065import org.projectfloodlight.openflow.protocol.instruction.OFInstruction;
66import org.projectfloodlight.openflow.protocol.instruction.OFInstructionApplyActions;
67import org.projectfloodlight.openflow.types.OFPort;
alshabib902d41b2014-10-07 16:52:05 -070068import org.projectfloodlight.openflow.types.U32;
alshabib1cc04f72014-09-16 16:09:58 -070069import org.slf4j.Logger;
70
Jonathan Hart11096402014-10-20 17:31:49 -070071import com.google.common.collect.ArrayListMultimap;
72import com.google.common.collect.Lists;
73import com.google.common.collect.Maps;
74import com.google.common.collect.Multimap;
alshabibeec3a062014-09-17 18:01:26 -070075
alshabib1cc04f72014-09-16 16:09:58 -070076/**
77 * Provider which uses an OpenFlow controller to detect network
78 * end-station hosts.
79 */
80@Component(immediate = true)
81public class OpenFlowRuleProvider extends AbstractProvider implements FlowRuleProvider {
82
alshabib193525b2014-10-08 18:58:03 -070083 enum BatchState { STARTED, FINISHED, CANCELLED };
84
alshabib1cc04f72014-09-16 16:09:58 -070085 private final Logger log = getLogger(getClass());
86
87 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
88 protected FlowRuleProviderRegistry providerRegistry;
89
90 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
91 protected OpenFlowController controller;
92
93 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
94 protected TopologyService topologyService;
95
96 private FlowRuleProviderService providerService;
97
alshabibeec3a062014-09-17 18:01:26 -070098 private final InternalFlowProvider listener = new InternalFlowProvider();
99
alshabib902d41b2014-10-07 16:52:05 -0700100 private final Map<Long, InstallationFuture> pendingFutures =
101 new ConcurrentHashMap<Long, InstallationFuture>();
102
alshabib193525b2014-10-08 18:58:03 -0700103 private final Map<Long, InstallationFuture> pendingFMs =
104 new ConcurrentHashMap<Long, InstallationFuture>();
105
alshabib3d643ec2014-10-22 18:33:00 -0700106 private final Map<Dpid, FlowStatsCollector> collectors = Maps.newHashMap();
107
alshabib1cc04f72014-09-16 16:09:58 -0700108 /**
109 * Creates an OpenFlow host provider.
110 */
111 public OpenFlowRuleProvider() {
tom7e02cda2014-09-18 12:05:46 -0700112 super(new ProviderId("of", "org.onlab.onos.provider.openflow"));
alshabib1cc04f72014-09-16 16:09:58 -0700113 }
114
115 @Activate
116 public void activate() {
117 providerService = providerRegistry.register(this);
alshabibeec3a062014-09-17 18:01:26 -0700118 controller.addListener(listener);
119 controller.addEventListener(listener);
alshabib3d643ec2014-10-22 18:33:00 -0700120
121 for (OpenFlowSwitch sw : controller.getSwitches()) {
122 FlowStatsCollector fsc = new FlowStatsCollector(sw, POLL_INTERVAL);
123 fsc.start();
124 collectors.put(new Dpid(sw.getId()), fsc);
125 }
126
127
alshabib1cc04f72014-09-16 16:09:58 -0700128 log.info("Started");
129 }
130
131 @Deactivate
132 public void deactivate() {
133 providerRegistry.unregister(this);
134 providerService = null;
135
136 log.info("Stopped");
137 }
138 @Override
139 public void applyFlowRule(FlowRule... flowRules) {
alshabib35edb1a2014-09-16 17:44:44 -0700140 for (int i = 0; i < flowRules.length; i++) {
141 applyRule(flowRules[i]);
142 }
alshabib1cc04f72014-09-16 16:09:58 -0700143 }
144
alshabib35edb1a2014-09-16 17:44:44 -0700145 private void applyRule(FlowRule flowRule) {
146 OpenFlowSwitch sw = controller.getSwitch(Dpid.dpid(flowRule.deviceId().uri()));
alshabib902d41b2014-10-07 16:52:05 -0700147 sw.sendMsg(new FlowModBuilder(flowRule, sw.factory()).buildFlowAdd());
alshabib35edb1a2014-09-16 17:44:44 -0700148 }
149
alshabib35edb1a2014-09-16 17:44:44 -0700150
alshabib35edb1a2014-09-16 17:44:44 -0700151
alshabib1cc04f72014-09-16 16:09:58 -0700152 @Override
153 public void removeFlowRule(FlowRule... flowRules) {
alshabib219ebaa2014-09-22 15:41:24 -0700154 for (int i = 0; i < flowRules.length; i++) {
155 removeRule(flowRules[i]);
156 }
alshabib1cc04f72014-09-16 16:09:58 -0700157
158 }
159
alshabib219ebaa2014-09-22 15:41:24 -0700160 private void removeRule(FlowRule flowRule) {
161 OpenFlowSwitch sw = controller.getSwitch(Dpid.dpid(flowRule.deviceId().uri()));
162 sw.sendMsg(new FlowModBuilder(flowRule, sw.factory()).buildFlowDel());
163 }
164
alshabiba68eb962014-09-24 20:34:13 -0700165 @Override
166 public void removeRulesById(ApplicationId id, FlowRule... flowRules) {
167 // TODO: optimize using the ApplicationId
168 removeFlowRule(flowRules);
169 }
170
alshabib193525b2014-10-08 18:58:03 -0700171 @Override
172 public Future<CompletedBatchOperation> executeBatch(BatchOperation<FlowRuleBatchEntry> batch) {
Jonathan Hart11096402014-10-20 17:31:49 -0700173 final Set<Dpid> sws =
174 Collections.newSetFromMap(new ConcurrentHashMap<Dpid, Boolean>());
alshabib193525b2014-10-08 18:58:03 -0700175 final Map<Long, FlowRuleBatchEntry> fmXids = new HashMap<Long, FlowRuleBatchEntry>();
176 OFFlowMod mod = null;
177 for (FlowRuleBatchEntry fbe : batch.getOperations()) {
178 FlowRule flowRule = fbe.getTarget();
179 OpenFlowSwitch sw = controller.getSwitch(Dpid.dpid(flowRule.deviceId().uri()));
alshabib7911a052014-10-16 17:49:37 -0700180 if (sw == null) {
alshabib3effd042014-10-17 12:00:31 -0700181 /*
182 * if a switch we are supposed to install to is gone then
183 * cancel (ie. rollback) the work that has been done so far
184 * and return the associated future.
185 */
186 InstallationFuture failed = new InstallationFuture(sws, fmXids);
187 failed.cancel(true);
188 return failed;
alshabib7911a052014-10-16 17:49:37 -0700189 }
alshabib193525b2014-10-08 18:58:03 -0700190 sws.add(new Dpid(sw.getId()));
191 FlowModBuilder builder = new FlowModBuilder(flowRule, sw.factory());
192 switch (fbe.getOperator()) {
193 case ADD:
194 mod = builder.buildFlowAdd();
195 break;
196 case REMOVE:
197 mod = builder.buildFlowDel();
198 break;
199 case MODIFY:
200 mod = builder.buildFlowMod();
201 break;
202 default:
203 log.error("Unsupported batch operation {}", fbe.getOperator());
204 }
205 if (mod != null) {
206 sw.sendMsg(mod);
207 fmXids.put(mod.getXid(), fbe);
208 } else {
209 log.error("Conversion of flowrule {} failed.", flowRule);
210 }
alshabib219ebaa2014-09-22 15:41:24 -0700211
alshabib193525b2014-10-08 18:58:03 -0700212 }
213 InstallationFuture installation = new InstallationFuture(sws, fmXids);
214 for (Long xid : fmXids.keySet()) {
215 pendingFMs.put(xid, installation);
216 }
217 pendingFutures.put(U32.f(batch.hashCode()), installation);
alshabibdfc7afb2014-10-21 20:13:27 -0700218 installation.verify(U32.f(batch.hashCode()));
alshabib193525b2014-10-08 18:58:03 -0700219 return installation;
220 }
221
222
alshabib8f1cf4a2014-09-17 14:44:48 -0700223 private class InternalFlowProvider
224 implements OpenFlowSwitchListener, OpenFlowEventListener {
225
alshabib3d643ec2014-10-22 18:33:00 -0700226
alshabib1c319ff2014-10-04 20:29:09 -0700227 private final Multimap<DeviceId, FlowEntry> completeEntries =
alshabib54ce5892014-09-23 17:50:51 -0700228 ArrayListMultimap.create();
alshabib8f1cf4a2014-09-17 14:44:48 -0700229
230 @Override
231 public void switchAdded(Dpid dpid) {
alshabibba5ac482014-10-02 17:15:20 -0700232 FlowStatsCollector fsc = new FlowStatsCollector(controller.getSwitch(dpid), POLL_INTERVAL);
alshabibeec3a062014-09-17 18:01:26 -0700233 fsc.start();
234 collectors.put(dpid, fsc);
alshabib8f1cf4a2014-09-17 14:44:48 -0700235 }
236
237 @Override
238 public void switchRemoved(Dpid dpid) {
alshabibdfc7afb2014-10-21 20:13:27 -0700239 FlowStatsCollector collector = collectors.remove(dpid);
240 if (collector != null) {
241 collector.stop();
242 }
alshabib8f1cf4a2014-09-17 14:44:48 -0700243 }
244
245 @Override
246 public void portChanged(Dpid dpid, OFPortStatus status) {
247 //TODO: Decide whether to evict flows internal store.
248 }
249
250 @Override
251 public void handleMessage(Dpid dpid, OFMessage msg) {
alshabib902d41b2014-10-07 16:52:05 -0700252 InstallationFuture future = null;
alshabib8f1cf4a2014-09-17 14:44:48 -0700253 switch (msg.getType()) {
254 case FLOW_REMOVED:
255 OFFlowRemoved removed = (OFFlowRemoved) msg;
alshabib6b5cfec2014-09-18 17:42:18 -0700256
alshabib1c319ff2014-10-04 20:29:09 -0700257 FlowEntry fr = new FlowEntryBuilder(dpid, removed).build();
alshabib8f1cf4a2014-09-17 14:44:48 -0700258 providerService.flowRemoved(fr);
259 break;
260 case STATS_REPLY:
alshabib97044902014-09-18 14:52:16 -0700261 pushFlowMetrics(dpid, (OFStatsReply) msg);
alshabibeec3a062014-09-17 18:01:26 -0700262 break;
alshabib8f1cf4a2014-09-17 14:44:48 -0700263 case BARRIER_REPLY:
alshabib902d41b2014-10-07 16:52:05 -0700264 future = pendingFutures.get(msg.getXid());
265 if (future != null) {
266 future.satisfyRequirement(dpid);
267 }
268 break;
alshabib8f1cf4a2014-09-17 14:44:48 -0700269 case ERROR:
alshabib193525b2014-10-08 18:58:03 -0700270 future = pendingFMs.get(msg.getXid());
alshabib902d41b2014-10-07 16:52:05 -0700271 if (future != null) {
272 future.fail((OFErrorMsg) msg, dpid);
273 }
274 break;
alshabib8f1cf4a2014-09-17 14:44:48 -0700275 default:
alshabib6eb438a2014-10-01 16:39:37 -0700276 log.debug("Unhandled message type: {}", msg.getType());
alshabib8f1cf4a2014-09-17 14:44:48 -0700277 }
278
279 }
280
Ayaka Koshibeab91cc42014-09-25 10:20:52 -0700281 @Override
alshabib193525b2014-10-08 18:58:03 -0700282 public void roleAssertFailed(Dpid dpid, RoleState role) {}
Ayaka Koshibeab91cc42014-09-25 10:20:52 -0700283
alshabib54ce5892014-09-23 17:50:51 -0700284 private synchronized void pushFlowMetrics(Dpid dpid, OFStatsReply stats) {
alshabib5c370ff2014-09-18 10:12:14 -0700285 if (stats.getStatsType() != OFStatsType.FLOW) {
286 return;
287 }
alshabib54ce5892014-09-23 17:50:51 -0700288 DeviceId did = DeviceId.deviceId(Dpid.uri(dpid));
alshabib5c370ff2014-09-18 10:12:14 -0700289 final OFFlowStatsReply replies = (OFFlowStatsReply) stats;
alshabib54ce5892014-09-23 17:50:51 -0700290 //final List<FlowRule> entries = Lists.newLinkedList();
291
alshabib5c370ff2014-09-18 10:12:14 -0700292 for (OFFlowStatsEntry reply : replies.getEntries()) {
alshabib19fdc122014-10-03 11:38:19 -0700293 if (!tableMissRule(dpid, reply)) {
alshabib1c319ff2014-10-04 20:29:09 -0700294 completeEntries.put(did, new FlowEntryBuilder(dpid, reply).build());
alshabib19fdc122014-10-03 11:38:19 -0700295 }
alshabib5c370ff2014-09-18 10:12:14 -0700296 }
alshabib54ce5892014-09-23 17:50:51 -0700297
298 if (!stats.getFlags().contains(OFStatsReplyFlags.REPLY_MORE)) {
299 log.debug("sending flowstats to core {}", completeEntries.get(did));
300 providerService.pushFlowMetrics(did, completeEntries.get(did));
301 completeEntries.removeAll(did);
302 }
alshabib5c370ff2014-09-18 10:12:14 -0700303 }
304
alshabib19fdc122014-10-03 11:38:19 -0700305 private boolean tableMissRule(Dpid dpid, OFFlowStatsEntry reply) {
alshabib19fdc122014-10-03 11:38:19 -0700306 if (reply.getVersion().equals(OFVersion.OF_10) ||
307 reply.getMatch().getMatchFields().iterator().hasNext()) {
308 return false;
309 }
310 for (OFInstruction ins : reply.getInstructions()) {
311 if (ins.getType() == OFInstructionType.APPLY_ACTIONS) {
312 OFInstructionApplyActions apply = (OFInstructionApplyActions) ins;
313 List<OFAction> acts = apply.getActions();
314 for (OFAction act : acts) {
315 if (act.getType() == OFActionType.OUTPUT) {
316 OFActionOutput out = (OFActionOutput) act;
317 if (out.getPort() == OFPort.CONTROLLER) {
318 return true;
319 }
320 }
321 }
322 }
323 }
324 return false;
325 }
alshabib8f1cf4a2014-09-17 14:44:48 -0700326 }
alshabib1cc04f72014-09-16 16:09:58 -0700327
alshabib193525b2014-10-08 18:58:03 -0700328 private class InstallationFuture implements Future<CompletedBatchOperation> {
alshabib902d41b2014-10-07 16:52:05 -0700329
330 private final Set<Dpid> sws;
331 private final AtomicBoolean ok = new AtomicBoolean(true);
alshabib193525b2014-10-08 18:58:03 -0700332 private final Map<Long, FlowRuleBatchEntry> fms;
333
alshabib902d41b2014-10-07 16:52:05 -0700334 private final List<FlowEntry> offendingFlowMods = Lists.newLinkedList();
335
336 private final CountDownLatch countDownLatch;
alshabibdfc7afb2014-10-21 20:13:27 -0700337 private Long pendingXid;
alshabib193525b2014-10-08 18:58:03 -0700338 private BatchState state;
alshabib902d41b2014-10-07 16:52:05 -0700339
alshabib193525b2014-10-08 18:58:03 -0700340 public InstallationFuture(Set<Dpid> sws, Map<Long, FlowRuleBatchEntry> fmXids) {
341 this.state = BatchState.STARTED;
alshabib902d41b2014-10-07 16:52:05 -0700342 this.sws = sws;
alshabib193525b2014-10-08 18:58:03 -0700343 this.fms = fmXids;
alshabib902d41b2014-10-07 16:52:05 -0700344 countDownLatch = new CountDownLatch(sws.size());
345 }
346
347 public void fail(OFErrorMsg msg, Dpid dpid) {
348 ok.set(false);
alshabib7911a052014-10-16 17:49:37 -0700349 removeRequirement(dpid);
alshabib193525b2014-10-08 18:58:03 -0700350 FlowEntry fe = null;
351 FlowRuleBatchEntry fbe = fms.get(msg.getXid());
352 FlowRule offending = fbe.getTarget();
alshabib902d41b2014-10-07 16:52:05 -0700353 //TODO handle specific error msgs
alshabib902d41b2014-10-07 16:52:05 -0700354 switch (msg.getErrType()) {
355 case BAD_ACTION:
alshabib193525b2014-10-08 18:58:03 -0700356 OFBadActionErrorMsg bad = (OFBadActionErrorMsg) msg;
357 fe = new DefaultFlowEntry(offending, bad.getErrType().ordinal(),
358 bad.getCode().ordinal());
alshabib902d41b2014-10-07 16:52:05 -0700359 break;
360 case BAD_INSTRUCTION:
alshabib193525b2014-10-08 18:58:03 -0700361 OFBadInstructionErrorMsg badins = (OFBadInstructionErrorMsg) msg;
362 fe = new DefaultFlowEntry(offending, badins.getErrType().ordinal(),
363 badins.getCode().ordinal());
alshabib902d41b2014-10-07 16:52:05 -0700364 break;
365 case BAD_MATCH:
alshabib193525b2014-10-08 18:58:03 -0700366 OFBadMatchErrorMsg badMatch = (OFBadMatchErrorMsg) msg;
367 fe = new DefaultFlowEntry(offending, badMatch.getErrType().ordinal(),
368 badMatch.getCode().ordinal());
alshabib902d41b2014-10-07 16:52:05 -0700369 break;
370 case BAD_REQUEST:
alshabib193525b2014-10-08 18:58:03 -0700371 OFBadRequestErrorMsg badReq = (OFBadRequestErrorMsg) msg;
372 fe = new DefaultFlowEntry(offending, badReq.getErrType().ordinal(),
373 badReq.getCode().ordinal());
alshabib902d41b2014-10-07 16:52:05 -0700374 break;
375 case FLOW_MOD_FAILED:
alshabib193525b2014-10-08 18:58:03 -0700376 OFFlowModFailedErrorMsg fmFail = (OFFlowModFailedErrorMsg) msg;
377 fe = new DefaultFlowEntry(offending, fmFail.getErrType().ordinal(),
378 fmFail.getCode().ordinal());
alshabib902d41b2014-10-07 16:52:05 -0700379 break;
alshabib193525b2014-10-08 18:58:03 -0700380 case EXPERIMENTER:
alshabib902d41b2014-10-07 16:52:05 -0700381 case GROUP_MOD_FAILED:
alshabib902d41b2014-10-07 16:52:05 -0700382 case HELLO_FAILED:
alshabib902d41b2014-10-07 16:52:05 -0700383 case METER_MOD_FAILED:
alshabib902d41b2014-10-07 16:52:05 -0700384 case PORT_MOD_FAILED:
alshabib902d41b2014-10-07 16:52:05 -0700385 case QUEUE_OP_FAILED:
alshabib902d41b2014-10-07 16:52:05 -0700386 case ROLE_REQUEST_FAILED:
alshabib902d41b2014-10-07 16:52:05 -0700387 case SWITCH_CONFIG_FAILED:
alshabib902d41b2014-10-07 16:52:05 -0700388 case TABLE_FEATURES_FAILED:
alshabib902d41b2014-10-07 16:52:05 -0700389 case TABLE_MOD_FAILED:
alshabib193525b2014-10-08 18:58:03 -0700390 fe = new DefaultFlowEntry(offending, msg.getErrType().ordinal(), 0);
alshabib902d41b2014-10-07 16:52:05 -0700391 break;
392 default:
alshabib193525b2014-10-08 18:58:03 -0700393 log.error("Unknown error type {}", msg.getErrType());
alshabib902d41b2014-10-07 16:52:05 -0700394
395 }
alshabib193525b2014-10-08 18:58:03 -0700396 offendingFlowMods.add(fe);
alshabib902d41b2014-10-07 16:52:05 -0700397
398 }
399
alshabib193525b2014-10-08 18:58:03 -0700400
alshabib902d41b2014-10-07 16:52:05 -0700401 public void satisfyRequirement(Dpid dpid) {
alshabib3effd042014-10-17 12:00:31 -0700402 log.debug("Satisfaction from switch {}", dpid);
alshabib7911a052014-10-16 17:49:37 -0700403 removeRequirement(dpid);
alshabib902d41b2014-10-07 16:52:05 -0700404 }
405
alshabib193525b2014-10-08 18:58:03 -0700406
alshabibdfc7afb2014-10-21 20:13:27 -0700407 public void verify(Long id) {
alshabib193525b2014-10-08 18:58:03 -0700408 pendingXid = id;
alshabib902d41b2014-10-07 16:52:05 -0700409 for (Dpid dpid : sws) {
410 OpenFlowSwitch sw = controller.getSwitch(dpid);
411 OFBarrierRequest.Builder builder = sw.factory()
412 .buildBarrierRequest()
413 .setXid(id);
414 sw.sendMsg(builder.build());
415 }
alshabib902d41b2014-10-07 16:52:05 -0700416 }
417
418 @Override
419 public boolean cancel(boolean mayInterruptIfRunning) {
alshabib7911a052014-10-16 17:49:37 -0700420 ok.set(false);
alshabib193525b2014-10-08 18:58:03 -0700421 this.state = BatchState.CANCELLED;
422 cleanUp();
423 for (FlowRuleBatchEntry fbe : fms.values()) {
424 if (fbe.getOperator() == FlowRuleOperation.ADD ||
425 fbe.getOperator() == FlowRuleOperation.MODIFY) {
426 removeFlowRule(fbe.getTarget());
427 } else if (fbe.getOperator() == FlowRuleOperation.REMOVE) {
428 applyRule(fbe.getTarget());
429 }
430
431 }
432 return isCancelled();
alshabib902d41b2014-10-07 16:52:05 -0700433 }
434
435 @Override
436 public boolean isCancelled() {
alshabib193525b2014-10-08 18:58:03 -0700437 return this.state == BatchState.CANCELLED;
alshabib902d41b2014-10-07 16:52:05 -0700438 }
439
440 @Override
441 public boolean isDone() {
alshabib193525b2014-10-08 18:58:03 -0700442 return this.state == BatchState.FINISHED;
alshabib902d41b2014-10-07 16:52:05 -0700443 }
444
445 @Override
alshabib193525b2014-10-08 18:58:03 -0700446 public CompletedBatchOperation get() throws InterruptedException, ExecutionException {
alshabib902d41b2014-10-07 16:52:05 -0700447 countDownLatch.await();
alshabib193525b2014-10-08 18:58:03 -0700448 this.state = BatchState.FINISHED;
449 return new CompletedBatchOperation(ok.get(), offendingFlowMods);
alshabib902d41b2014-10-07 16:52:05 -0700450 }
451
452 @Override
alshabib193525b2014-10-08 18:58:03 -0700453 public CompletedBatchOperation get(long timeout, TimeUnit unit)
alshabib902d41b2014-10-07 16:52:05 -0700454 throws InterruptedException, ExecutionException,
455 TimeoutException {
alshabib26834582014-10-08 20:15:46 -0700456 if (countDownLatch.await(timeout, unit)) {
457 this.state = BatchState.FINISHED;
458 return new CompletedBatchOperation(ok.get(), offendingFlowMods);
459 }
460 throw new TimeoutException();
alshabib193525b2014-10-08 18:58:03 -0700461 }
462
463 private void cleanUp() {
alshabib7911a052014-10-16 17:49:37 -0700464 if (isDone() || isCancelled()) {
alshabibdfc7afb2014-10-21 20:13:27 -0700465 if (pendingXid != null) {
466 pendingFutures.remove(pendingXid);
467 }
alshabib193525b2014-10-08 18:58:03 -0700468 for (Long xid : fms.keySet()) {
469 pendingFMs.remove(xid);
470 }
471 }
alshabib902d41b2014-10-07 16:52:05 -0700472 }
473
alshabib7911a052014-10-16 17:49:37 -0700474 private void removeRequirement(Dpid dpid) {
475 countDownLatch.countDown();
476 sws.remove(dpid);
477 cleanUp();
478 }
479
alshabib902d41b2014-10-07 16:52:05 -0700480 }
alshabiba68eb962014-09-24 20:34:13 -0700481
alshabib1cc04f72014-09-16 16:09:58 -0700482}