blob: 2da09fe11a806620bb847f42ecc19a99de580a82 [file] [log] [blame]
alshabib1cc04f72014-09-16 16:09:58 -07001package org.onlab.onos.provider.of.flow.impl;
2
3import static org.slf4j.LoggerFactory.getLogger;
4
alshabib193525b2014-10-08 18:58:03 -07005import java.util.HashMap;
alshabib902d41b2014-10-07 16:52:05 -07006import java.util.HashSet;
alshabib19fdc122014-10-03 11:38:19 -07007import java.util.List;
alshabibeec3a062014-09-17 18:01:26 -07008import java.util.Map;
alshabib902d41b2014-10-07 16:52:05 -07009import 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;
alshabibeec3a062014-09-17 18:01:26 -070017
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
alshabib54ce5892014-09-23 17:50:51 -070071import com.google.common.collect.ArrayListMultimap;
alshabib902d41b2014-10-07 16:52:05 -070072import com.google.common.collect.Lists;
alshabib5c370ff2014-09-18 10:12:14 -070073import com.google.common.collect.Maps;
alshabib54ce5892014-09-23 17:50:51 -070074import 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
alshabib1cc04f72014-09-16 16:09:58 -0700106 /**
107 * Creates an OpenFlow host provider.
108 */
109 public OpenFlowRuleProvider() {
tom7e02cda2014-09-18 12:05:46 -0700110 super(new ProviderId("of", "org.onlab.onos.provider.openflow"));
alshabib1cc04f72014-09-16 16:09:58 -0700111 }
112
113 @Activate
114 public void activate() {
115 providerService = providerRegistry.register(this);
alshabibeec3a062014-09-17 18:01:26 -0700116 controller.addListener(listener);
117 controller.addEventListener(listener);
alshabib1cc04f72014-09-16 16:09:58 -0700118 log.info("Started");
119 }
120
121 @Deactivate
122 public void deactivate() {
123 providerRegistry.unregister(this);
124 providerService = null;
125
126 log.info("Stopped");
127 }
128 @Override
129 public void applyFlowRule(FlowRule... flowRules) {
alshabib35edb1a2014-09-16 17:44:44 -0700130 for (int i = 0; i < flowRules.length; i++) {
131 applyRule(flowRules[i]);
132 }
alshabib1cc04f72014-09-16 16:09:58 -0700133 }
134
alshabib35edb1a2014-09-16 17:44:44 -0700135 private void applyRule(FlowRule flowRule) {
136 OpenFlowSwitch sw = controller.getSwitch(Dpid.dpid(flowRule.deviceId().uri()));
alshabib902d41b2014-10-07 16:52:05 -0700137 sw.sendMsg(new FlowModBuilder(flowRule, sw.factory()).buildFlowAdd());
alshabib35edb1a2014-09-16 17:44:44 -0700138 }
139
alshabib35edb1a2014-09-16 17:44:44 -0700140
alshabib35edb1a2014-09-16 17:44:44 -0700141
alshabib1cc04f72014-09-16 16:09:58 -0700142 @Override
143 public void removeFlowRule(FlowRule... flowRules) {
alshabib219ebaa2014-09-22 15:41:24 -0700144 for (int i = 0; i < flowRules.length; i++) {
145 removeRule(flowRules[i]);
146 }
alshabib1cc04f72014-09-16 16:09:58 -0700147
148 }
149
alshabib219ebaa2014-09-22 15:41:24 -0700150 private void removeRule(FlowRule flowRule) {
151 OpenFlowSwitch sw = controller.getSwitch(Dpid.dpid(flowRule.deviceId().uri()));
152 sw.sendMsg(new FlowModBuilder(flowRule, sw.factory()).buildFlowDel());
153 }
154
alshabiba68eb962014-09-24 20:34:13 -0700155 @Override
156 public void removeRulesById(ApplicationId id, FlowRule... flowRules) {
157 // TODO: optimize using the ApplicationId
158 removeFlowRule(flowRules);
159 }
160
alshabib193525b2014-10-08 18:58:03 -0700161 @Override
162 public Future<CompletedBatchOperation> executeBatch(BatchOperation<FlowRuleBatchEntry> batch) {
163 final Set<Dpid> sws = new HashSet<Dpid>();
164 final Map<Long, FlowRuleBatchEntry> fmXids = new HashMap<Long, FlowRuleBatchEntry>();
165 OFFlowMod mod = null;
166 for (FlowRuleBatchEntry fbe : batch.getOperations()) {
167 FlowRule flowRule = fbe.getTarget();
168 OpenFlowSwitch sw = controller.getSwitch(Dpid.dpid(flowRule.deviceId().uri()));
169 sws.add(new Dpid(sw.getId()));
170 FlowModBuilder builder = new FlowModBuilder(flowRule, sw.factory());
171 switch (fbe.getOperator()) {
172 case ADD:
173 mod = builder.buildFlowAdd();
174 break;
175 case REMOVE:
176 mod = builder.buildFlowDel();
177 break;
178 case MODIFY:
179 mod = builder.buildFlowMod();
180 break;
181 default:
182 log.error("Unsupported batch operation {}", fbe.getOperator());
183 }
184 if (mod != null) {
185 sw.sendMsg(mod);
186 fmXids.put(mod.getXid(), fbe);
187 } else {
188 log.error("Conversion of flowrule {} failed.", flowRule);
189 }
alshabib219ebaa2014-09-22 15:41:24 -0700190
alshabib193525b2014-10-08 18:58:03 -0700191 }
192 InstallationFuture installation = new InstallationFuture(sws, fmXids);
193 for (Long xid : fmXids.keySet()) {
194 pendingFMs.put(xid, installation);
195 }
196 pendingFutures.put(U32.f(batch.hashCode()), installation);
197 installation.verify(batch.hashCode());
198 return installation;
199 }
200
201
alshabib8f1cf4a2014-09-17 14:44:48 -0700202 private class InternalFlowProvider
203 implements OpenFlowSwitchListener, OpenFlowEventListener {
204
alshabibeec3a062014-09-17 18:01:26 -0700205 private final Map<Dpid, FlowStatsCollector> collectors = Maps.newHashMap();
alshabib1c319ff2014-10-04 20:29:09 -0700206 private final Multimap<DeviceId, FlowEntry> completeEntries =
alshabib54ce5892014-09-23 17:50:51 -0700207 ArrayListMultimap.create();
alshabib8f1cf4a2014-09-17 14:44:48 -0700208
209 @Override
210 public void switchAdded(Dpid dpid) {
alshabibba5ac482014-10-02 17:15:20 -0700211 FlowStatsCollector fsc = new FlowStatsCollector(controller.getSwitch(dpid), POLL_INTERVAL);
alshabibeec3a062014-09-17 18:01:26 -0700212 fsc.start();
213 collectors.put(dpid, fsc);
alshabib8f1cf4a2014-09-17 14:44:48 -0700214 }
215
216 @Override
217 public void switchRemoved(Dpid dpid) {
alshabibeec3a062014-09-17 18:01:26 -0700218 collectors.remove(dpid).stop();
alshabib8f1cf4a2014-09-17 14:44:48 -0700219 }
220
221 @Override
222 public void portChanged(Dpid dpid, OFPortStatus status) {
223 //TODO: Decide whether to evict flows internal store.
224 }
225
226 @Override
227 public void handleMessage(Dpid dpid, OFMessage msg) {
alshabib902d41b2014-10-07 16:52:05 -0700228 InstallationFuture future = null;
alshabib8f1cf4a2014-09-17 14:44:48 -0700229 switch (msg.getType()) {
230 case FLOW_REMOVED:
231 OFFlowRemoved removed = (OFFlowRemoved) msg;
alshabib6b5cfec2014-09-18 17:42:18 -0700232
alshabib1c319ff2014-10-04 20:29:09 -0700233 FlowEntry fr = new FlowEntryBuilder(dpid, removed).build();
alshabib8f1cf4a2014-09-17 14:44:48 -0700234 providerService.flowRemoved(fr);
235 break;
236 case STATS_REPLY:
alshabib97044902014-09-18 14:52:16 -0700237 pushFlowMetrics(dpid, (OFStatsReply) msg);
alshabibeec3a062014-09-17 18:01:26 -0700238 break;
alshabib8f1cf4a2014-09-17 14:44:48 -0700239 case BARRIER_REPLY:
alshabib902d41b2014-10-07 16:52:05 -0700240 future = pendingFutures.get(msg.getXid());
241 if (future != null) {
242 future.satisfyRequirement(dpid);
243 }
244 break;
alshabib8f1cf4a2014-09-17 14:44:48 -0700245 case ERROR:
alshabib193525b2014-10-08 18:58:03 -0700246 future = pendingFMs.get(msg.getXid());
alshabib902d41b2014-10-07 16:52:05 -0700247 if (future != null) {
248 future.fail((OFErrorMsg) msg, dpid);
249 }
250 break;
alshabib8f1cf4a2014-09-17 14:44:48 -0700251 default:
alshabib6eb438a2014-10-01 16:39:37 -0700252 log.debug("Unhandled message type: {}", msg.getType());
alshabib8f1cf4a2014-09-17 14:44:48 -0700253 }
254
255 }
256
Ayaka Koshibeab91cc42014-09-25 10:20:52 -0700257 @Override
alshabib193525b2014-10-08 18:58:03 -0700258 public void roleAssertFailed(Dpid dpid, RoleState role) {}
Ayaka Koshibeab91cc42014-09-25 10:20:52 -0700259
alshabib54ce5892014-09-23 17:50:51 -0700260 private synchronized void pushFlowMetrics(Dpid dpid, OFStatsReply stats) {
alshabib5c370ff2014-09-18 10:12:14 -0700261 if (stats.getStatsType() != OFStatsType.FLOW) {
262 return;
263 }
alshabib54ce5892014-09-23 17:50:51 -0700264 DeviceId did = DeviceId.deviceId(Dpid.uri(dpid));
alshabib5c370ff2014-09-18 10:12:14 -0700265 final OFFlowStatsReply replies = (OFFlowStatsReply) stats;
alshabib54ce5892014-09-23 17:50:51 -0700266 //final List<FlowRule> entries = Lists.newLinkedList();
267
alshabib5c370ff2014-09-18 10:12:14 -0700268 for (OFFlowStatsEntry reply : replies.getEntries()) {
alshabib19fdc122014-10-03 11:38:19 -0700269 if (!tableMissRule(dpid, reply)) {
alshabib1c319ff2014-10-04 20:29:09 -0700270 completeEntries.put(did, new FlowEntryBuilder(dpid, reply).build());
alshabib19fdc122014-10-03 11:38:19 -0700271 }
alshabib5c370ff2014-09-18 10:12:14 -0700272 }
alshabib54ce5892014-09-23 17:50:51 -0700273
274 if (!stats.getFlags().contains(OFStatsReplyFlags.REPLY_MORE)) {
275 log.debug("sending flowstats to core {}", completeEntries.get(did));
276 providerService.pushFlowMetrics(did, completeEntries.get(did));
277 completeEntries.removeAll(did);
278 }
alshabib5c370ff2014-09-18 10:12:14 -0700279 }
280
alshabib19fdc122014-10-03 11:38:19 -0700281 private boolean tableMissRule(Dpid dpid, OFFlowStatsEntry reply) {
alshabib19fdc122014-10-03 11:38:19 -0700282 if (reply.getVersion().equals(OFVersion.OF_10) ||
283 reply.getMatch().getMatchFields().iterator().hasNext()) {
284 return false;
285 }
286 for (OFInstruction ins : reply.getInstructions()) {
287 if (ins.getType() == OFInstructionType.APPLY_ACTIONS) {
288 OFInstructionApplyActions apply = (OFInstructionApplyActions) ins;
289 List<OFAction> acts = apply.getActions();
290 for (OFAction act : acts) {
291 if (act.getType() == OFActionType.OUTPUT) {
292 OFActionOutput out = (OFActionOutput) act;
293 if (out.getPort() == OFPort.CONTROLLER) {
294 return true;
295 }
296 }
297 }
298 }
299 }
300 return false;
301 }
alshabib8f1cf4a2014-09-17 14:44:48 -0700302 }
alshabib1cc04f72014-09-16 16:09:58 -0700303
alshabib193525b2014-10-08 18:58:03 -0700304 private class InstallationFuture implements Future<CompletedBatchOperation> {
alshabib902d41b2014-10-07 16:52:05 -0700305
306 private final Set<Dpid> sws;
307 private final AtomicBoolean ok = new AtomicBoolean(true);
alshabib193525b2014-10-08 18:58:03 -0700308 private final Map<Long, FlowRuleBatchEntry> fms;
309
alshabib902d41b2014-10-07 16:52:05 -0700310 private final List<FlowEntry> offendingFlowMods = Lists.newLinkedList();
311
312 private final CountDownLatch countDownLatch;
alshabib193525b2014-10-08 18:58:03 -0700313 private Integer pendingXid;
314 private BatchState state;
alshabib902d41b2014-10-07 16:52:05 -0700315
alshabib193525b2014-10-08 18:58:03 -0700316 public InstallationFuture(Set<Dpid> sws, Map<Long, FlowRuleBatchEntry> fmXids) {
317 this.state = BatchState.STARTED;
alshabib902d41b2014-10-07 16:52:05 -0700318 this.sws = sws;
alshabib193525b2014-10-08 18:58:03 -0700319 this.fms = fmXids;
alshabib902d41b2014-10-07 16:52:05 -0700320 countDownLatch = new CountDownLatch(sws.size());
321 }
322
323 public void fail(OFErrorMsg msg, Dpid dpid) {
324 ok.set(false);
alshabib193525b2014-10-08 18:58:03 -0700325 FlowEntry fe = null;
326 FlowRuleBatchEntry fbe = fms.get(msg.getXid());
327 FlowRule offending = fbe.getTarget();
alshabib902d41b2014-10-07 16:52:05 -0700328 //TODO handle specific error msgs
alshabib902d41b2014-10-07 16:52:05 -0700329 switch (msg.getErrType()) {
330 case BAD_ACTION:
alshabib193525b2014-10-08 18:58:03 -0700331 OFBadActionErrorMsg bad = (OFBadActionErrorMsg) msg;
332 fe = new DefaultFlowEntry(offending, bad.getErrType().ordinal(),
333 bad.getCode().ordinal());
alshabib902d41b2014-10-07 16:52:05 -0700334 break;
335 case BAD_INSTRUCTION:
alshabib193525b2014-10-08 18:58:03 -0700336 OFBadInstructionErrorMsg badins = (OFBadInstructionErrorMsg) msg;
337 fe = new DefaultFlowEntry(offending, badins.getErrType().ordinal(),
338 badins.getCode().ordinal());
alshabib902d41b2014-10-07 16:52:05 -0700339 break;
340 case BAD_MATCH:
alshabib193525b2014-10-08 18:58:03 -0700341 OFBadMatchErrorMsg badMatch = (OFBadMatchErrorMsg) msg;
342 fe = new DefaultFlowEntry(offending, badMatch.getErrType().ordinal(),
343 badMatch.getCode().ordinal());
alshabib902d41b2014-10-07 16:52:05 -0700344 break;
345 case BAD_REQUEST:
alshabib193525b2014-10-08 18:58:03 -0700346 OFBadRequestErrorMsg badReq = (OFBadRequestErrorMsg) msg;
347 fe = new DefaultFlowEntry(offending, badReq.getErrType().ordinal(),
348 badReq.getCode().ordinal());
alshabib902d41b2014-10-07 16:52:05 -0700349 break;
350 case FLOW_MOD_FAILED:
alshabib193525b2014-10-08 18:58:03 -0700351 OFFlowModFailedErrorMsg fmFail = (OFFlowModFailedErrorMsg) msg;
352 fe = new DefaultFlowEntry(offending, fmFail.getErrType().ordinal(),
353 fmFail.getCode().ordinal());
alshabib902d41b2014-10-07 16:52:05 -0700354 break;
alshabib193525b2014-10-08 18:58:03 -0700355 case EXPERIMENTER:
alshabib902d41b2014-10-07 16:52:05 -0700356 case GROUP_MOD_FAILED:
alshabib902d41b2014-10-07 16:52:05 -0700357 case HELLO_FAILED:
alshabib902d41b2014-10-07 16:52:05 -0700358 case METER_MOD_FAILED:
alshabib902d41b2014-10-07 16:52:05 -0700359 case PORT_MOD_FAILED:
alshabib902d41b2014-10-07 16:52:05 -0700360 case QUEUE_OP_FAILED:
alshabib902d41b2014-10-07 16:52:05 -0700361 case ROLE_REQUEST_FAILED:
alshabib902d41b2014-10-07 16:52:05 -0700362 case SWITCH_CONFIG_FAILED:
alshabib902d41b2014-10-07 16:52:05 -0700363 case TABLE_FEATURES_FAILED:
alshabib902d41b2014-10-07 16:52:05 -0700364 case TABLE_MOD_FAILED:
alshabib193525b2014-10-08 18:58:03 -0700365 fe = new DefaultFlowEntry(offending, msg.getErrType().ordinal(), 0);
alshabib902d41b2014-10-07 16:52:05 -0700366 break;
367 default:
alshabib193525b2014-10-08 18:58:03 -0700368 log.error("Unknown error type {}", msg.getErrType());
alshabib902d41b2014-10-07 16:52:05 -0700369
370 }
alshabib193525b2014-10-08 18:58:03 -0700371 offendingFlowMods.add(fe);
alshabib902d41b2014-10-07 16:52:05 -0700372
373 }
374
alshabib193525b2014-10-08 18:58:03 -0700375
alshabib902d41b2014-10-07 16:52:05 -0700376 public void satisfyRequirement(Dpid dpid) {
377 log.warn("Satisfaction from switch {}", dpid);
alshabib193525b2014-10-08 18:58:03 -0700378 sws.remove(dpid);
alshabib902d41b2014-10-07 16:52:05 -0700379 countDownLatch.countDown();
alshabib193525b2014-10-08 18:58:03 -0700380 cleanUp();
381
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) {
alshabib193525b2014-10-08 18:58:03 -0700398 this.state = BatchState.CANCELLED;
399 cleanUp();
400 for (FlowRuleBatchEntry fbe : fms.values()) {
401 if (fbe.getOperator() == FlowRuleOperation.ADD ||
402 fbe.getOperator() == FlowRuleOperation.MODIFY) {
403 removeFlowRule(fbe.getTarget());
404 } else if (fbe.getOperator() == FlowRuleOperation.REMOVE) {
405 applyRule(fbe.getTarget());
406 }
407
408 }
409 return isCancelled();
alshabib902d41b2014-10-07 16:52:05 -0700410 }
411
412 @Override
413 public boolean isCancelled() {
alshabib193525b2014-10-08 18:58:03 -0700414 return this.state == BatchState.CANCELLED;
alshabib902d41b2014-10-07 16:52:05 -0700415 }
416
417 @Override
418 public boolean isDone() {
alshabib193525b2014-10-08 18:58:03 -0700419 return this.state == BatchState.FINISHED;
alshabib902d41b2014-10-07 16:52:05 -0700420 }
421
422 @Override
alshabib193525b2014-10-08 18:58:03 -0700423 public CompletedBatchOperation get() throws InterruptedException, ExecutionException {
alshabib902d41b2014-10-07 16:52:05 -0700424 countDownLatch.await();
alshabib193525b2014-10-08 18:58:03 -0700425 this.state = BatchState.FINISHED;
426 return new CompletedBatchOperation(ok.get(), offendingFlowMods);
alshabib902d41b2014-10-07 16:52:05 -0700427 }
428
429 @Override
alshabib193525b2014-10-08 18:58:03 -0700430 public CompletedBatchOperation get(long timeout, TimeUnit unit)
alshabib902d41b2014-10-07 16:52:05 -0700431 throws InterruptedException, ExecutionException,
432 TimeoutException {
433 countDownLatch.await(timeout, unit);
alshabib193525b2014-10-08 18:58:03 -0700434 this.state = BatchState.FINISHED;
435 return new CompletedBatchOperation(ok.get(), offendingFlowMods);
436 }
437
438 private void cleanUp() {
439 if (sws.isEmpty()) {
440 pendingFutures.remove(pendingXid);
441 for (Long xid : fms.keySet()) {
442 pendingFMs.remove(xid);
443 }
444 }
alshabib902d41b2014-10-07 16:52:05 -0700445 }
446
447 }
alshabiba68eb962014-09-24 20:34:13 -0700448
alshabib1cc04f72014-09-16 16:09:58 -0700449}