blob: a815f693f5811eb2e3e32b3d06f201aeb14ea0f5 [file] [log] [blame]
alshabib1cc04f72014-09-16 16:09:58 -07001package org.onlab.onos.provider.of.flow.impl;
2
alshabib7911a052014-10-16 17:49:37 -07003import com.google.common.collect.ArrayListMultimap;
4import com.google.common.collect.Lists;
5import com.google.common.collect.Maps;
6import com.google.common.collect.Multimap;
alshabib1cc04f72014-09-16 16:09:58 -07007import org.apache.felix.scr.annotations.Activate;
8import org.apache.felix.scr.annotations.Component;
9import org.apache.felix.scr.annotations.Deactivate;
10import org.apache.felix.scr.annotations.Reference;
11import org.apache.felix.scr.annotations.ReferenceCardinality;
alshabiba68eb962014-09-24 20:34:13 -070012import org.onlab.onos.ApplicationId;
alshabiba7f7ca82014-09-22 11:41:23 -070013import org.onlab.onos.net.DeviceId;
alshabib193525b2014-10-08 18:58:03 -070014import org.onlab.onos.net.flow.CompletedBatchOperation;
15import org.onlab.onos.net.flow.DefaultFlowEntry;
alshabib1c319ff2014-10-04 20:29:09 -070016import org.onlab.onos.net.flow.FlowEntry;
alshabib1cc04f72014-09-16 16:09:58 -070017import org.onlab.onos.net.flow.FlowRule;
alshabib902d41b2014-10-07 16:52:05 -070018import org.onlab.onos.net.flow.FlowRuleBatchEntry;
alshabib193525b2014-10-08 18:58:03 -070019import org.onlab.onos.net.flow.FlowRuleBatchEntry.FlowRuleOperation;
alshabib1cc04f72014-09-16 16:09:58 -070020import org.onlab.onos.net.flow.FlowRuleProvider;
21import org.onlab.onos.net.flow.FlowRuleProviderRegistry;
22import org.onlab.onos.net.flow.FlowRuleProviderService;
alshabib902d41b2014-10-07 16:52:05 -070023import org.onlab.onos.net.intent.BatchOperation;
alshabib1cc04f72014-09-16 16:09:58 -070024import org.onlab.onos.net.provider.AbstractProvider;
25import org.onlab.onos.net.provider.ProviderId;
26import org.onlab.onos.net.topology.TopologyService;
tom9c94c5b2014-09-17 13:14:42 -070027import org.onlab.onos.openflow.controller.Dpid;
28import org.onlab.onos.openflow.controller.OpenFlowController;
alshabibeec3a062014-09-17 18:01:26 -070029import org.onlab.onos.openflow.controller.OpenFlowEventListener;
tom9c94c5b2014-09-17 13:14:42 -070030import org.onlab.onos.openflow.controller.OpenFlowSwitch;
alshabibce4e5782014-09-17 14:56:42 -070031import org.onlab.onos.openflow.controller.OpenFlowSwitchListener;
Ayaka Koshibeab91cc42014-09-25 10:20:52 -070032import org.onlab.onos.openflow.controller.RoleState;
alshabib19fdc122014-10-03 11:38:19 -070033import org.projectfloodlight.openflow.protocol.OFActionType;
alshabib902d41b2014-10-07 16:52:05 -070034import org.projectfloodlight.openflow.protocol.OFBarrierRequest;
35import org.projectfloodlight.openflow.protocol.OFErrorMsg;
alshabib193525b2014-10-08 18:58:03 -070036import org.projectfloodlight.openflow.protocol.OFFlowMod;
alshabib8f1cf4a2014-09-17 14:44:48 -070037import org.projectfloodlight.openflow.protocol.OFFlowRemoved;
alshabib5c370ff2014-09-18 10:12:14 -070038import org.projectfloodlight.openflow.protocol.OFFlowStatsEntry;
39import org.projectfloodlight.openflow.protocol.OFFlowStatsReply;
alshabib19fdc122014-10-03 11:38:19 -070040import org.projectfloodlight.openflow.protocol.OFInstructionType;
alshabib8f1cf4a2014-09-17 14:44:48 -070041import org.projectfloodlight.openflow.protocol.OFMessage;
42import org.projectfloodlight.openflow.protocol.OFPortStatus;
alshabib5c370ff2014-09-18 10:12:14 -070043import org.projectfloodlight.openflow.protocol.OFStatsReply;
alshabib54ce5892014-09-23 17:50:51 -070044import org.projectfloodlight.openflow.protocol.OFStatsReplyFlags;
alshabib5c370ff2014-09-18 10:12:14 -070045import org.projectfloodlight.openflow.protocol.OFStatsType;
alshabib19fdc122014-10-03 11:38:19 -070046import org.projectfloodlight.openflow.protocol.OFVersion;
47import org.projectfloodlight.openflow.protocol.action.OFAction;
48import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
alshabib193525b2014-10-08 18:58:03 -070049import org.projectfloodlight.openflow.protocol.errormsg.OFBadActionErrorMsg;
50import org.projectfloodlight.openflow.protocol.errormsg.OFBadInstructionErrorMsg;
51import org.projectfloodlight.openflow.protocol.errormsg.OFBadMatchErrorMsg;
52import org.projectfloodlight.openflow.protocol.errormsg.OFBadRequestErrorMsg;
53import org.projectfloodlight.openflow.protocol.errormsg.OFFlowModFailedErrorMsg;
alshabib19fdc122014-10-03 11:38:19 -070054import org.projectfloodlight.openflow.protocol.instruction.OFInstruction;
55import org.projectfloodlight.openflow.protocol.instruction.OFInstructionApplyActions;
56import org.projectfloodlight.openflow.types.OFPort;
alshabib902d41b2014-10-07 16:52:05 -070057import org.projectfloodlight.openflow.types.U32;
alshabib1cc04f72014-09-16 16:09:58 -070058import org.slf4j.Logger;
59
alshabib7911a052014-10-16 17:49:37 -070060import java.util.HashMap;
61import java.util.HashSet;
62import java.util.List;
63import java.util.Map;
64import java.util.Set;
65import java.util.concurrent.ConcurrentHashMap;
66import java.util.concurrent.CountDownLatch;
67import java.util.concurrent.ExecutionException;
68import java.util.concurrent.Future;
69import java.util.concurrent.TimeUnit;
70import java.util.concurrent.TimeoutException;
71import java.util.concurrent.atomic.AtomicBoolean;
72
73import static org.slf4j.LoggerFactory.getLogger;
alshabibeec3a062014-09-17 18:01:26 -070074
alshabib1cc04f72014-09-16 16:09:58 -070075/**
76 * Provider which uses an OpenFlow controller to detect network
77 * end-station hosts.
78 */
79@Component(immediate = true)
80public class OpenFlowRuleProvider extends AbstractProvider implements FlowRuleProvider {
81
alshabib193525b2014-10-08 18:58:03 -070082 enum BatchState { STARTED, FINISHED, CANCELLED };
83
alshabib1cc04f72014-09-16 16:09:58 -070084 private final Logger log = getLogger(getClass());
85
86 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
87 protected FlowRuleProviderRegistry providerRegistry;
88
89 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
90 protected OpenFlowController controller;
91
92 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
93 protected TopologyService topologyService;
94
95 private FlowRuleProviderService providerService;
96
alshabibeec3a062014-09-17 18:01:26 -070097 private final InternalFlowProvider listener = new InternalFlowProvider();
98
alshabib902d41b2014-10-07 16:52:05 -070099 private final Map<Long, InstallationFuture> pendingFutures =
100 new ConcurrentHashMap<Long, InstallationFuture>();
101
alshabib193525b2014-10-08 18:58:03 -0700102 private final Map<Long, InstallationFuture> pendingFMs =
103 new ConcurrentHashMap<Long, InstallationFuture>();
104
alshabib1cc04f72014-09-16 16:09:58 -0700105 /**
106 * Creates an OpenFlow host provider.
107 */
108 public OpenFlowRuleProvider() {
tom7e02cda2014-09-18 12:05:46 -0700109 super(new ProviderId("of", "org.onlab.onos.provider.openflow"));
alshabib1cc04f72014-09-16 16:09:58 -0700110 }
111
112 @Activate
113 public void activate() {
114 providerService = providerRegistry.register(this);
alshabibeec3a062014-09-17 18:01:26 -0700115 controller.addListener(listener);
116 controller.addEventListener(listener);
alshabib1cc04f72014-09-16 16:09:58 -0700117 log.info("Started");
118 }
119
120 @Deactivate
121 public void deactivate() {
122 providerRegistry.unregister(this);
123 providerService = null;
124
125 log.info("Stopped");
126 }
127 @Override
128 public void applyFlowRule(FlowRule... flowRules) {
alshabib35edb1a2014-09-16 17:44:44 -0700129 for (int i = 0; i < flowRules.length; i++) {
130 applyRule(flowRules[i]);
131 }
alshabib1cc04f72014-09-16 16:09:58 -0700132 }
133
alshabib35edb1a2014-09-16 17:44:44 -0700134 private void applyRule(FlowRule flowRule) {
135 OpenFlowSwitch sw = controller.getSwitch(Dpid.dpid(flowRule.deviceId().uri()));
alshabib902d41b2014-10-07 16:52:05 -0700136 sw.sendMsg(new FlowModBuilder(flowRule, sw.factory()).buildFlowAdd());
alshabib35edb1a2014-09-16 17:44:44 -0700137 }
138
alshabib35edb1a2014-09-16 17:44:44 -0700139
alshabib35edb1a2014-09-16 17:44:44 -0700140
alshabib1cc04f72014-09-16 16:09:58 -0700141 @Override
142 public void removeFlowRule(FlowRule... flowRules) {
alshabib219ebaa2014-09-22 15:41:24 -0700143 for (int i = 0; i < flowRules.length; i++) {
144 removeRule(flowRules[i]);
145 }
alshabib1cc04f72014-09-16 16:09:58 -0700146
147 }
148
alshabib219ebaa2014-09-22 15:41:24 -0700149 private void removeRule(FlowRule flowRule) {
150 OpenFlowSwitch sw = controller.getSwitch(Dpid.dpid(flowRule.deviceId().uri()));
151 sw.sendMsg(new FlowModBuilder(flowRule, sw.factory()).buildFlowDel());
152 }
153
alshabiba68eb962014-09-24 20:34:13 -0700154 @Override
155 public void removeRulesById(ApplicationId id, FlowRule... flowRules) {
156 // TODO: optimize using the ApplicationId
157 removeFlowRule(flowRules);
158 }
159
alshabib193525b2014-10-08 18:58:03 -0700160 @Override
161 public Future<CompletedBatchOperation> executeBatch(BatchOperation<FlowRuleBatchEntry> batch) {
162 final Set<Dpid> sws = new HashSet<Dpid>();
163 final Map<Long, FlowRuleBatchEntry> fmXids = new HashMap<Long, FlowRuleBatchEntry>();
164 OFFlowMod mod = null;
165 for (FlowRuleBatchEntry fbe : batch.getOperations()) {
166 FlowRule flowRule = fbe.getTarget();
167 OpenFlowSwitch sw = controller.getSwitch(Dpid.dpid(flowRule.deviceId().uri()));
alshabib7911a052014-10-16 17:49:37 -0700168 if (sw == null) {
169 log.warn("WTF {}", flowRule.deviceId());
170 }
alshabib193525b2014-10-08 18:58:03 -0700171 sws.add(new Dpid(sw.getId()));
172 FlowModBuilder builder = new FlowModBuilder(flowRule, sw.factory());
173 switch (fbe.getOperator()) {
174 case ADD:
175 mod = builder.buildFlowAdd();
176 break;
177 case REMOVE:
178 mod = builder.buildFlowDel();
179 break;
180 case MODIFY:
181 mod = builder.buildFlowMod();
182 break;
183 default:
184 log.error("Unsupported batch operation {}", fbe.getOperator());
185 }
186 if (mod != null) {
187 sw.sendMsg(mod);
188 fmXids.put(mod.getXid(), fbe);
189 } else {
190 log.error("Conversion of flowrule {} failed.", flowRule);
191 }
alshabib219ebaa2014-09-22 15:41:24 -0700192
alshabib193525b2014-10-08 18:58:03 -0700193 }
194 InstallationFuture installation = new InstallationFuture(sws, fmXids);
195 for (Long xid : fmXids.keySet()) {
196 pendingFMs.put(xid, installation);
197 }
198 pendingFutures.put(U32.f(batch.hashCode()), installation);
199 installation.verify(batch.hashCode());
200 return installation;
201 }
202
203
alshabib8f1cf4a2014-09-17 14:44:48 -0700204 private class InternalFlowProvider
205 implements OpenFlowSwitchListener, OpenFlowEventListener {
206
alshabibeec3a062014-09-17 18:01:26 -0700207 private final Map<Dpid, FlowStatsCollector> collectors = Maps.newHashMap();
alshabib1c319ff2014-10-04 20:29:09 -0700208 private final Multimap<DeviceId, FlowEntry> completeEntries =
alshabib54ce5892014-09-23 17:50:51 -0700209 ArrayListMultimap.create();
alshabib8f1cf4a2014-09-17 14:44:48 -0700210
211 @Override
212 public void switchAdded(Dpid dpid) {
alshabibba5ac482014-10-02 17:15:20 -0700213 FlowStatsCollector fsc = new FlowStatsCollector(controller.getSwitch(dpid), POLL_INTERVAL);
alshabibeec3a062014-09-17 18:01:26 -0700214 fsc.start();
215 collectors.put(dpid, fsc);
alshabib8f1cf4a2014-09-17 14:44:48 -0700216 }
217
218 @Override
219 public void switchRemoved(Dpid dpid) {
alshabibeec3a062014-09-17 18:01:26 -0700220 collectors.remove(dpid).stop();
alshabib8f1cf4a2014-09-17 14:44:48 -0700221 }
222
223 @Override
224 public void portChanged(Dpid dpid, OFPortStatus status) {
225 //TODO: Decide whether to evict flows internal store.
226 }
227
228 @Override
229 public void handleMessage(Dpid dpid, OFMessage msg) {
alshabib902d41b2014-10-07 16:52:05 -0700230 InstallationFuture future = null;
alshabib8f1cf4a2014-09-17 14:44:48 -0700231 switch (msg.getType()) {
232 case FLOW_REMOVED:
233 OFFlowRemoved removed = (OFFlowRemoved) msg;
alshabib6b5cfec2014-09-18 17:42:18 -0700234
alshabib1c319ff2014-10-04 20:29:09 -0700235 FlowEntry fr = new FlowEntryBuilder(dpid, removed).build();
alshabib8f1cf4a2014-09-17 14:44:48 -0700236 providerService.flowRemoved(fr);
237 break;
238 case STATS_REPLY:
alshabib97044902014-09-18 14:52:16 -0700239 pushFlowMetrics(dpid, (OFStatsReply) msg);
alshabibeec3a062014-09-17 18:01:26 -0700240 break;
alshabib8f1cf4a2014-09-17 14:44:48 -0700241 case BARRIER_REPLY:
alshabib902d41b2014-10-07 16:52:05 -0700242 future = pendingFutures.get(msg.getXid());
243 if (future != null) {
244 future.satisfyRequirement(dpid);
245 }
246 break;
alshabib8f1cf4a2014-09-17 14:44:48 -0700247 case ERROR:
alshabib193525b2014-10-08 18:58:03 -0700248 future = pendingFMs.get(msg.getXid());
alshabib902d41b2014-10-07 16:52:05 -0700249 if (future != null) {
250 future.fail((OFErrorMsg) msg, dpid);
251 }
252 break;
alshabib8f1cf4a2014-09-17 14:44:48 -0700253 default:
alshabib6eb438a2014-10-01 16:39:37 -0700254 log.debug("Unhandled message type: {}", msg.getType());
alshabib8f1cf4a2014-09-17 14:44:48 -0700255 }
256
257 }
258
Ayaka Koshibeab91cc42014-09-25 10:20:52 -0700259 @Override
alshabib193525b2014-10-08 18:58:03 -0700260 public void roleAssertFailed(Dpid dpid, RoleState role) {}
Ayaka Koshibeab91cc42014-09-25 10:20:52 -0700261
alshabib54ce5892014-09-23 17:50:51 -0700262 private synchronized void pushFlowMetrics(Dpid dpid, OFStatsReply stats) {
alshabib5c370ff2014-09-18 10:12:14 -0700263 if (stats.getStatsType() != OFStatsType.FLOW) {
264 return;
265 }
alshabib54ce5892014-09-23 17:50:51 -0700266 DeviceId did = DeviceId.deviceId(Dpid.uri(dpid));
alshabib5c370ff2014-09-18 10:12:14 -0700267 final OFFlowStatsReply replies = (OFFlowStatsReply) stats;
alshabib54ce5892014-09-23 17:50:51 -0700268 //final List<FlowRule> entries = Lists.newLinkedList();
269
alshabib5c370ff2014-09-18 10:12:14 -0700270 for (OFFlowStatsEntry reply : replies.getEntries()) {
alshabib19fdc122014-10-03 11:38:19 -0700271 if (!tableMissRule(dpid, reply)) {
alshabib1c319ff2014-10-04 20:29:09 -0700272 completeEntries.put(did, new FlowEntryBuilder(dpid, reply).build());
alshabib19fdc122014-10-03 11:38:19 -0700273 }
alshabib5c370ff2014-09-18 10:12:14 -0700274 }
alshabib54ce5892014-09-23 17:50:51 -0700275
276 if (!stats.getFlags().contains(OFStatsReplyFlags.REPLY_MORE)) {
277 log.debug("sending flowstats to core {}", completeEntries.get(did));
278 providerService.pushFlowMetrics(did, completeEntries.get(did));
279 completeEntries.removeAll(did);
280 }
alshabib5c370ff2014-09-18 10:12:14 -0700281 }
282
alshabib19fdc122014-10-03 11:38:19 -0700283 private boolean tableMissRule(Dpid dpid, OFFlowStatsEntry reply) {
alshabib19fdc122014-10-03 11:38:19 -0700284 if (reply.getVersion().equals(OFVersion.OF_10) ||
285 reply.getMatch().getMatchFields().iterator().hasNext()) {
286 return false;
287 }
288 for (OFInstruction ins : reply.getInstructions()) {
289 if (ins.getType() == OFInstructionType.APPLY_ACTIONS) {
290 OFInstructionApplyActions apply = (OFInstructionApplyActions) ins;
291 List<OFAction> acts = apply.getActions();
292 for (OFAction act : acts) {
293 if (act.getType() == OFActionType.OUTPUT) {
294 OFActionOutput out = (OFActionOutput) act;
295 if (out.getPort() == OFPort.CONTROLLER) {
296 return true;
297 }
298 }
299 }
300 }
301 }
302 return false;
303 }
alshabib8f1cf4a2014-09-17 14:44:48 -0700304 }
alshabib1cc04f72014-09-16 16:09:58 -0700305
alshabib193525b2014-10-08 18:58:03 -0700306 private class InstallationFuture implements Future<CompletedBatchOperation> {
alshabib902d41b2014-10-07 16:52:05 -0700307
308 private final Set<Dpid> sws;
309 private final AtomicBoolean ok = new AtomicBoolean(true);
alshabib193525b2014-10-08 18:58:03 -0700310 private final Map<Long, FlowRuleBatchEntry> fms;
311
alshabib902d41b2014-10-07 16:52:05 -0700312 private final List<FlowEntry> offendingFlowMods = Lists.newLinkedList();
313
314 private final CountDownLatch countDownLatch;
alshabib193525b2014-10-08 18:58:03 -0700315 private Integer pendingXid;
316 private BatchState state;
alshabib902d41b2014-10-07 16:52:05 -0700317
alshabib193525b2014-10-08 18:58:03 -0700318 public InstallationFuture(Set<Dpid> sws, Map<Long, FlowRuleBatchEntry> fmXids) {
319 this.state = BatchState.STARTED;
alshabib902d41b2014-10-07 16:52:05 -0700320 this.sws = sws;
alshabib193525b2014-10-08 18:58:03 -0700321 this.fms = fmXids;
alshabib902d41b2014-10-07 16:52:05 -0700322 countDownLatch = new CountDownLatch(sws.size());
323 }
324
325 public void fail(OFErrorMsg msg, Dpid dpid) {
326 ok.set(false);
alshabib7911a052014-10-16 17:49:37 -0700327 removeRequirement(dpid);
alshabib193525b2014-10-08 18:58:03 -0700328 FlowEntry fe = null;
329 FlowRuleBatchEntry fbe = fms.get(msg.getXid());
330 FlowRule offending = fbe.getTarget();
alshabib902d41b2014-10-07 16:52:05 -0700331 //TODO handle specific error msgs
alshabib902d41b2014-10-07 16:52:05 -0700332 switch (msg.getErrType()) {
333 case BAD_ACTION:
alshabib193525b2014-10-08 18:58:03 -0700334 OFBadActionErrorMsg bad = (OFBadActionErrorMsg) msg;
335 fe = new DefaultFlowEntry(offending, bad.getErrType().ordinal(),
336 bad.getCode().ordinal());
alshabib902d41b2014-10-07 16:52:05 -0700337 break;
338 case BAD_INSTRUCTION:
alshabib193525b2014-10-08 18:58:03 -0700339 OFBadInstructionErrorMsg badins = (OFBadInstructionErrorMsg) msg;
340 fe = new DefaultFlowEntry(offending, badins.getErrType().ordinal(),
341 badins.getCode().ordinal());
alshabib902d41b2014-10-07 16:52:05 -0700342 break;
343 case BAD_MATCH:
alshabib193525b2014-10-08 18:58:03 -0700344 OFBadMatchErrorMsg badMatch = (OFBadMatchErrorMsg) msg;
345 fe = new DefaultFlowEntry(offending, badMatch.getErrType().ordinal(),
346 badMatch.getCode().ordinal());
alshabib902d41b2014-10-07 16:52:05 -0700347 break;
348 case BAD_REQUEST:
alshabib193525b2014-10-08 18:58:03 -0700349 OFBadRequestErrorMsg badReq = (OFBadRequestErrorMsg) msg;
350 fe = new DefaultFlowEntry(offending, badReq.getErrType().ordinal(),
351 badReq.getCode().ordinal());
alshabib902d41b2014-10-07 16:52:05 -0700352 break;
353 case FLOW_MOD_FAILED:
alshabib193525b2014-10-08 18:58:03 -0700354 OFFlowModFailedErrorMsg fmFail = (OFFlowModFailedErrorMsg) msg;
355 fe = new DefaultFlowEntry(offending, fmFail.getErrType().ordinal(),
356 fmFail.getCode().ordinal());
alshabib902d41b2014-10-07 16:52:05 -0700357 break;
alshabib193525b2014-10-08 18:58:03 -0700358 case EXPERIMENTER:
alshabib902d41b2014-10-07 16:52:05 -0700359 case GROUP_MOD_FAILED:
alshabib902d41b2014-10-07 16:52:05 -0700360 case HELLO_FAILED:
alshabib902d41b2014-10-07 16:52:05 -0700361 case METER_MOD_FAILED:
alshabib902d41b2014-10-07 16:52:05 -0700362 case PORT_MOD_FAILED:
alshabib902d41b2014-10-07 16:52:05 -0700363 case QUEUE_OP_FAILED:
alshabib902d41b2014-10-07 16:52:05 -0700364 case ROLE_REQUEST_FAILED:
alshabib902d41b2014-10-07 16:52:05 -0700365 case SWITCH_CONFIG_FAILED:
alshabib902d41b2014-10-07 16:52:05 -0700366 case TABLE_FEATURES_FAILED:
alshabib902d41b2014-10-07 16:52:05 -0700367 case TABLE_MOD_FAILED:
alshabib193525b2014-10-08 18:58:03 -0700368 fe = new DefaultFlowEntry(offending, msg.getErrType().ordinal(), 0);
alshabib902d41b2014-10-07 16:52:05 -0700369 break;
370 default:
alshabib193525b2014-10-08 18:58:03 -0700371 log.error("Unknown error type {}", msg.getErrType());
alshabib902d41b2014-10-07 16:52:05 -0700372
373 }
alshabib193525b2014-10-08 18:58:03 -0700374 offendingFlowMods.add(fe);
alshabib902d41b2014-10-07 16:52:05 -0700375
376 }
377
alshabib193525b2014-10-08 18:58:03 -0700378
alshabib902d41b2014-10-07 16:52:05 -0700379 public void satisfyRequirement(Dpid dpid) {
380 log.warn("Satisfaction from switch {}", dpid);
alshabib7911a052014-10-16 17:49:37 -0700381 removeRequirement(dpid);
alshabib902d41b2014-10-07 16:52:05 -0700382 }
383
alshabib193525b2014-10-08 18:58:03 -0700384
alshabib902d41b2014-10-07 16:52:05 -0700385 public void verify(Integer id) {
alshabib193525b2014-10-08 18:58:03 -0700386 pendingXid = id;
alshabib902d41b2014-10-07 16:52:05 -0700387 for (Dpid dpid : sws) {
388 OpenFlowSwitch sw = controller.getSwitch(dpid);
389 OFBarrierRequest.Builder builder = sw.factory()
390 .buildBarrierRequest()
391 .setXid(id);
392 sw.sendMsg(builder.build());
393 }
alshabib902d41b2014-10-07 16:52:05 -0700394 }
395
396 @Override
397 public boolean cancel(boolean mayInterruptIfRunning) {
alshabib7911a052014-10-16 17:49:37 -0700398 ok.set(false);
alshabib193525b2014-10-08 18:58:03 -0700399 this.state = BatchState.CANCELLED;
400 cleanUp();
401 for (FlowRuleBatchEntry fbe : fms.values()) {
402 if (fbe.getOperator() == FlowRuleOperation.ADD ||
403 fbe.getOperator() == FlowRuleOperation.MODIFY) {
404 removeFlowRule(fbe.getTarget());
405 } else if (fbe.getOperator() == FlowRuleOperation.REMOVE) {
406 applyRule(fbe.getTarget());
407 }
408
409 }
410 return isCancelled();
alshabib902d41b2014-10-07 16:52:05 -0700411 }
412
413 @Override
414 public boolean isCancelled() {
alshabib193525b2014-10-08 18:58:03 -0700415 return this.state == BatchState.CANCELLED;
alshabib902d41b2014-10-07 16:52:05 -0700416 }
417
418 @Override
419 public boolean isDone() {
alshabib193525b2014-10-08 18:58:03 -0700420 return this.state == BatchState.FINISHED;
alshabib902d41b2014-10-07 16:52:05 -0700421 }
422
423 @Override
alshabib193525b2014-10-08 18:58:03 -0700424 public CompletedBatchOperation get() throws InterruptedException, ExecutionException {
alshabib902d41b2014-10-07 16:52:05 -0700425 countDownLatch.await();
alshabib193525b2014-10-08 18:58:03 -0700426 this.state = BatchState.FINISHED;
427 return new CompletedBatchOperation(ok.get(), offendingFlowMods);
alshabib902d41b2014-10-07 16:52:05 -0700428 }
429
430 @Override
alshabib193525b2014-10-08 18:58:03 -0700431 public CompletedBatchOperation get(long timeout, TimeUnit unit)
alshabib902d41b2014-10-07 16:52:05 -0700432 throws InterruptedException, ExecutionException,
433 TimeoutException {
alshabib26834582014-10-08 20:15:46 -0700434 if (countDownLatch.await(timeout, unit)) {
alshabib7911a052014-10-16 17:49:37 -0700435
alshabib26834582014-10-08 20:15:46 -0700436 this.state = BatchState.FINISHED;
437 return new CompletedBatchOperation(ok.get(), offendingFlowMods);
438 }
439 throw new TimeoutException();
alshabib193525b2014-10-08 18:58:03 -0700440 }
441
442 private void cleanUp() {
alshabib7911a052014-10-16 17:49:37 -0700443 if (isDone() || isCancelled()) {
alshabib193525b2014-10-08 18:58:03 -0700444 pendingFutures.remove(pendingXid);
445 for (Long xid : fms.keySet()) {
446 pendingFMs.remove(xid);
447 }
448 }
alshabib902d41b2014-10-07 16:52:05 -0700449 }
450
alshabib7911a052014-10-16 17:49:37 -0700451 private void removeRequirement(Dpid dpid) {
452 countDownLatch.countDown();
453 sws.remove(dpid);
454 cleanUp();
455 }
456
alshabib902d41b2014-10-07 16:52:05 -0700457 }
alshabiba68eb962014-09-24 20:34:13 -0700458
alshabib1cc04f72014-09-16 16:09:58 -0700459}