blob: c310ed93dfb8cfc686dbd5e0f181af0b4f87514d [file] [log] [blame]
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -08001package net.floodlightcontroller.flowcache;
2
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -08003import java.io.IOException;
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -08004import java.util.ArrayList;
5import java.util.Collection;
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -08006import java.util.EnumSet;
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -08007import java.util.HashMap;
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -08008import java.util.List;
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -08009import java.util.Map;
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -080010import java.util.concurrent.Executors;
11import java.util.concurrent.ScheduledExecutorService;
12import java.util.concurrent.ScheduledFuture;
13import java.util.concurrent.TimeUnit;
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -080014
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -080015import net.floodlightcontroller.core.IFloodlightProviderService;
16import net.floodlightcontroller.core.INetMapStorage;
17import net.floodlightcontroller.core.INetMapTopologyObjects.IFlowEntry;
18import net.floodlightcontroller.core.INetMapTopologyObjects.IFlowPath;
19import net.floodlightcontroller.core.IOFSwitch;
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -080020import net.floodlightcontroller.core.module.FloodlightModuleContext;
21import net.floodlightcontroller.core.module.FloodlightModuleException;
22import net.floodlightcontroller.core.module.IFloodlightModule;
23import net.floodlightcontroller.core.module.IFloodlightService;
24import net.floodlightcontroller.flowcache.IFlowService;
25import net.floodlightcontroller.flowcache.web.FlowWebRoutable;
26import net.floodlightcontroller.restserver.IRestApiService;
27import net.floodlightcontroller.util.CallerId;
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -080028import net.floodlightcontroller.util.DataPath;
29import net.floodlightcontroller.util.Dpid;
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -080030import net.floodlightcontroller.util.DataPathEndpoints;
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -080031import net.floodlightcontroller.util.FlowEntry;
32import net.floodlightcontroller.util.FlowEntryId;
33import net.floodlightcontroller.util.FlowEntrySwitchState;
34import net.floodlightcontroller.util.FlowEntryUserState;
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -080035import net.floodlightcontroller.util.FlowId;
36import net.floodlightcontroller.util.FlowPath;
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -080037import net.floodlightcontroller.util.OFMessageDamper;
38import net.floodlightcontroller.util.Port;
39import net.onrc.onos.util.GraphDBConnection;
40import net.onrc.onos.util.GraphDBConnection.Transaction;
41
42import org.openflow.protocol.OFFlowMod;
43import org.openflow.protocol.OFMatch;
44import org.openflow.protocol.OFPacketOut;
45import org.openflow.protocol.OFType;
46import org.openflow.protocol.action.OFAction;
47import org.openflow.protocol.action.OFActionOutput;
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -080048
49import org.slf4j.Logger;
50import org.slf4j.LoggerFactory;
51
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -080052public class FlowManager implements IFloodlightModule, IFlowService, INetMapStorage {
53
54 public GraphDBConnection conn;
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -080055
56 protected IRestApiService restApi;
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -080057 protected IFloodlightProviderService floodlightProvider;
58
59 protected OFMessageDamper messageDamper;
60
61 protected static int OFMESSAGE_DAMPER_CAPACITY = 50000; // TODO: find sweet spot
62 protected static int OFMESSAGE_DAMPER_TIMEOUT = 250; // ms
63 public static short FLOWMOD_DEFAULT_IDLE_TIMEOUT = 0; // infinity
64 public static short FLOWMOD_DEFAULT_HARD_TIMEOUT = 0; // infinite
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -080065
66 /** The logger. */
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -080067 private static Logger log = LoggerFactory.getLogger(FlowManager.class);
68
69 // The periodic task(s)
70 private final ScheduledExecutorService scheduler =
71 Executors.newScheduledThreadPool(1);
72 final Runnable reader = new Runnable() {
73 public void run() {
74 // log.debug("Reading Flow Entries from the Network Map...");
75 if (floodlightProvider == null) {
76 log.debug("FloodlightProvider service not found!");
77 return;
78 }
79
80 Map<Long, IOFSwitch> mySwitches = floodlightProvider.getSwitches();
81
82 // Fetch all Flow Entries
83 Iterable<IFlowEntry> flowEntries = conn.utils().getAllFlowEntries(conn);
84 for (IFlowEntry flowEntryObj : flowEntries) {
85 FlowEntryId flowEntryId =
86 new FlowEntryId(flowEntryObj.getFlowEntryId());
87 String userState = flowEntryObj.getUserState();
88 String switchState = flowEntryObj.getSwitchState();
89
90 log.debug("Found Flow Entry {}: ", flowEntryId.toString());
91 log.debug("User State {}:", userState);
92 log.debug("Switch State {}:", switchState);
93
94 if (! switchState.equals("FE_SWITCH_NOT_UPDATED")) {
95 // Ignore the entry: nothing to do
96 continue;
97 }
98
99 Dpid dpid = new Dpid(flowEntryObj.getSwitchDpid());
100 IOFSwitch mySwitch = mySwitches.get(dpid.value());
101 if (mySwitch == null) {
102 log.debug("Flow Entry ignored: not my switch");
103 continue;
104 }
105
106 //
107 // Create the Open Flow Flow Modification Entry to push
108 //
109 OFFlowMod fm =
110 (OFFlowMod) floodlightProvider.getOFMessageFactory()
111 .getMessage(OFType.FLOW_MOD);
112 long cookie = flowEntryId.value();
113
114 short flowModCommand = OFFlowMod.OFPFC_ADD;
115 if (userState.equals("FE_USER_ADD")) {
116 flowModCommand = OFFlowMod.OFPFC_ADD;
117 } else if (userState.equals("FE_USER_MODIFY")) {
118 flowModCommand = OFFlowMod.OFPFC_MODIFY_STRICT;
119 } else if (userState.equals("FE_USER_DELETE")) {
120 flowModCommand = OFFlowMod.OFPFC_DELETE_STRICT;
121 } else {
122 // Unknown user state. Ignore the entry
123 continue;
124 }
125
126 OFMatch match = new OFMatch();
127 match.setInputPort(flowEntryObj.getInPort());
128
129 OFActionOutput action = new OFActionOutput();
130 action.setMaxLength((short)0xffff);
131 action.setPort(flowEntryObj.getOutPort());
132 List<OFAction> actions = new ArrayList<OFAction>();
133 actions.add(action);
134
135 fm.setIdleTimeout(FLOWMOD_DEFAULT_IDLE_TIMEOUT)
136 .setHardTimeout(FLOWMOD_DEFAULT_HARD_TIMEOUT)
137 .setBufferId(OFPacketOut.BUFFER_ID_NONE)
138 .setCookie(cookie)
139 .setCommand(flowModCommand)
140 .setMatch(match)
141 .setActions(actions)
142 .setLengthU(OFFlowMod.MINIMUM_LENGTH+OFActionOutput.MINIMUM_LENGTH);
143 //
144 // TODO: Set the following flag
145 // fm.setFlags(OFFlowMod.OFPFF_SEND_FLOW_REM);
146 // See method ForwardingBase::pushRoute()
147 //
148 try {
149 messageDamper.write(mySwitch, fm, null);
150 mySwitch.flush();
151 flowEntryObj.setSwitchState("FE_SWITCH_UPDATED");
152 if (userState.equals("FE_USER_DELETE")) {
153 // Delete the entry
154 IFlowPath flowObj = null;
155 flowObj = conn.utils().getFlowPathByFlowEntry(conn,
156 flowEntryObj);
157 if (flowObj != null)
158 log.debug("Found FlowPath to be deleted");
159 else
160 log.debug("Did not find FlowPath to be deleted");
161 flowObj.removeFlowEntry(flowEntryObj);
162 conn.utils().removeFlowEntry(conn, flowEntryObj);
163
164 // Test whether the last flow entry
165 Iterable<IFlowEntry> tmpflowEntries =
166 flowObj.getFlowEntries();
167 boolean found = false;
168 for (IFlowEntry tmpflowEntryObj : tmpflowEntries) {
169 found = true;
170 break;
171 }
172 if (! found) {
173 // Remove the Flow Path as well
174 conn.utils().removeFlowPath(conn, flowObj);
175 }
176 }
177 } catch (IOException e) {
178 log.error("Failure writing flow mod from network map", e);
179 }
180 }
181 conn.endTx(Transaction.COMMIT);
182 }
183 };
184 final ScheduledFuture<?> readerHandle =
185 scheduler.scheduleAtFixedRate(reader, 3, 3, TimeUnit.SECONDS);
186
187 @Override
188 public void init(String conf) {
189 conn = GraphDBConnection.getInstance(conf);
190 }
191
192 public void finalize() {
193 close();
194 }
195
196 @Override
197 public void close() {
198 conn.close();
199 }
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800200
201 @Override
202 public Collection<Class<? extends IFloodlightService>> getModuleServices() {
203 Collection<Class<? extends IFloodlightService>> l =
204 new ArrayList<Class<? extends IFloodlightService>>();
205 l.add(IFlowService.class);
206 return l;
207 }
208
209 @Override
210 public Map<Class<? extends IFloodlightService>, IFloodlightService>
211 getServiceImpls() {
212 Map<Class<? extends IFloodlightService>,
213 IFloodlightService> m =
214 new HashMap<Class<? extends IFloodlightService>,
215 IFloodlightService>();
216 m.put(IFlowService.class, this);
217 return m;
218 }
219
220 @Override
221 public Collection<Class<? extends IFloodlightService>>
222 getModuleDependencies() {
223 Collection<Class<? extends IFloodlightService>> l =
224 new ArrayList<Class<? extends IFloodlightService>>();
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -0800225 l.add(IFloodlightProviderService.class);
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800226 l.add(IRestApiService.class);
227 return l;
228 }
229
230 @Override
231 public void init(FloodlightModuleContext context)
232 throws FloodlightModuleException {
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -0800233 floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800234 restApi = context.getServiceImpl(IRestApiService.class);
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -0800235 messageDamper = new OFMessageDamper(OFMESSAGE_DAMPER_CAPACITY,
236 EnumSet.of(OFType.FLOW_MOD),
237 OFMESSAGE_DAMPER_TIMEOUT);
238 // TODO: An ugly hack!
239 String conf = "/tmp/cassandra.titan";
240 this.init(conf);
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800241 }
242
243 @Override
244 public void startUp(FloodlightModuleContext context) {
245 restApi.addRestletRoutable(new FlowWebRoutable());
246 }
247
248 /**
249 * Add a flow.
250 *
251 * Internally, ONOS will automatically register the installer for
252 * receiving Flow Path Notifications for that path.
253 *
254 * @param flowPath the Flow Path to install.
255 * @param flowId the return-by-reference Flow ID as assigned internally.
256 * @return true on success, otherwise false.
257 */
258 @Override
259 public boolean addFlow(FlowPath flowPath, FlowId flowId) {
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -0800260
261 //
262 // Assign the FlowEntry IDs
263 // TODO: This is an ugly hack!
264 // The Flow Entry IDs are set to 1000*FlowId + Index
265 //
266 int i = 1;
267 for (FlowEntry flowEntry : flowPath.dataPath().flowEntries()) {
268 long id = flowPath.flowId().value() * 1000 + i;
269 ++i;
270 flowEntry.setFlowEntryId(new FlowEntryId(id));
271 }
272
273 IFlowPath flowObj = null;
274 try {
275 if ((flowObj = conn.utils().searchFlowPath(conn, flowPath.flowId()))
276 != null) {
277 log.debug("Adding FlowPath with FlowId {}: found existing FlowPath",
278 flowPath.flowId().toString());
279 } else {
280 flowObj = conn.utils().newFlowPath(conn);
281 log.debug("Adding FlowPath with FlowId {}: creating new FlowPath",
282 flowPath.flowId().toString());
283 }
284 } catch (Exception e) {
285 // TODO: handle exceptions
286 conn.endTx(Transaction.ROLLBACK);
287 log.error(":addFlow FlowId:{} failed",
288 flowPath.flowId().toString());
289 }
290 if (flowObj == null)
291 return false;
292
293 //
294 // Set the Flow key:
295 // - flowId
296 //
297 flowObj.setFlowId(flowPath.flowId().toString());
298 flowObj.setType("flow");
299
300 //
301 // Set the Flow attributes:
302 // - flowPath.installerId()
303 // - flowPath.dataPath().srcPort()
304 // - flowPath.dataPath().dstPort()
305 //
306 flowObj.setInstallerId(flowPath.installerId().toString());
307 flowObj.setSrcSwitch(flowPath.dataPath().srcPort().dpid().toString());
308 flowObj.setSrcPort(flowPath.dataPath().srcPort().port().value());
309 flowObj.setDstSwitch(flowPath.dataPath().dstPort().dpid().toString());
310 flowObj.setDstPort(flowPath.dataPath().dstPort().port().value());
311
312 // Flow edges:
313 // HeadFE
314
315
316 //
317 // Flow Entries:
318 // flowPath.dataPath().flowEntries()
319 //
320 for (FlowEntry flowEntry : flowPath.dataPath().flowEntries()) {
321 IFlowEntry flowEntryObj = null;
322 boolean found = false;
323 try {
324 if ((flowEntryObj = conn.utils().searchFlowEntry(conn, flowEntry.flowEntryId())) != null) {
325 log.debug("Adding FlowEntry with FlowEntryId {}: found existing FlowEntry",
326 flowEntry.flowEntryId().toString());
327 found = true;
328 } else {
329 flowEntryObj = conn.utils().newFlowEntry(conn);
330 log.debug("Adding FlowEntry with FlowEntryId {}: creating new FlowEntry",
331 flowEntry.flowEntryId().toString());
332 }
333 } catch (Exception e) {
334 // TODO: handle exceptions
335 conn.endTx(Transaction.ROLLBACK);
336 log.error(":addFlow FlowEntryId:{} failed",
337 flowEntry.flowEntryId().toString());
338 }
339 if (flowEntryObj == null)
340 return false;
341
342 //
343 // Set the Flow Entry key:
344 // - flowEntry.flowEntryId()
345 //
346 flowEntryObj.setFlowEntryId(flowEntry.flowEntryId().toString());
347 flowEntryObj.setType("flow_entry");
348
349 //
350 // Set the Flow Entry attributes:
351 // - flowEntry.flowEntryMatch()
352 // - flowEntry.flowEntryActions()
353 // - flowEntry.dpid()
354 // - flowEntry.inPort()
355 // - flowEntry.outPort()
356 // - flowEntry.flowEntryUserState()
357 // - flowEntry.flowEntrySwitchState()
358 // - flowEntry.flowEntryErrorState()
359 //
360 flowEntryObj.setSwitchDpid(flowEntry.dpid().toString());
361 flowEntryObj.setInPort(flowEntry.inPort().value());
362 flowEntryObj.setOutPort(flowEntry.outPort().value());
363 // TODO: Hacks with hard-coded state names!
364 if (found)
365 flowEntryObj.setUserState("FE_USER_MODIFY");
366 else
367 flowEntryObj.setUserState("FE_USER_ADD");
368 flowEntryObj.setSwitchState("FE_SWITCH_NOT_UPDATED");
369 //
370 // TODO: Take care of the FlowEntryMatch, FlowEntryActions,
371 // and FlowEntryErrorState.
372 //
373
374 // Flow Entries edges:
375 // Flow
376 // NextFE
377 // InPort
378 // OutPort
379 // Switch
380 if (! found)
381 flowObj.addFlowEntry(flowEntryObj);
382 }
383 conn.endTx(Transaction.COMMIT);
384
385 //
386 // TODO: We need a proper Flow ID allocation mechanism.
387 //
388 flowId.setValue(flowPath.flowId().value());
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800389 return true;
390 }
391
392 /**
393 * Delete a previously added flow.
394 *
395 * @param flowId the Flow ID of the flow to delete.
396 * @return true on success, otherwise false.
397 */
398 @Override
399 public boolean deleteFlow(FlowId flowId) {
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -0800400 IFlowPath flowObj = null;
401 //
402 // We just mark the entries for deletion,
403 // and let the switches remove each individual entry after
404 // it has been removed from the switches.
405 //
406 try {
407 if ((flowObj = conn.utils().searchFlowPath(conn, flowId))
408 != null) {
409 log.debug("Deleting FlowPath with FlowId {}: found existing FlowPath",
410 flowId.toString());
411 } else {
412 log.debug("Deleting FlowPath with FlowId {}: FlowPath not found",
413 flowId.toString());
414 }
415 } catch (Exception e) {
416 // TODO: handle exceptions
417 conn.endTx(Transaction.ROLLBACK);
418 log.error(":deleteFlow FlowId:{} failed", flowId.toString());
419 }
420 if (flowObj == null)
421 return true; // OK: No such flow
422
423 //
424 // Find and mark for deletion all Flow Entries
425 //
426 Iterable<IFlowEntry> flowEntries = flowObj.getFlowEntries();
427 boolean empty = true; // TODO: an ugly hack
428 for (IFlowEntry flowEntryObj : flowEntries) {
429 empty = false;
430 // flowObj.removeFlowEntry(flowEntryObj);
431 // conn.utils().removeFlowEntry(conn, flowEntryObj);
432 flowEntryObj.setUserState("FE_USER_DELETE");
433 flowEntryObj.setSwitchState("FE_SWITCH_NOT_UPDATED");
434 }
435 // Remove from the database empty flows
436 if (empty)
437 conn.utils().removeFlowPath(conn, flowObj);
438 conn.endTx(Transaction.COMMIT);
439
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800440 return true;
441 }
442
443 /**
444 * Get a previously added flow.
445 *
446 * @param flowId the Flow ID of the flow to get.
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -0800447 * @return the Flow Path if found, otherwise null.
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800448 */
449 @Override
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -0800450 public FlowPath getFlow(FlowId flowId) {
451 IFlowPath flowObj = null;
452 try {
453 if ((flowObj = conn.utils().searchFlowPath(conn, flowId))
454 != null) {
455 log.debug("Get FlowPath with FlowId {}: found existing FlowPath",
456 flowId.toString());
457 } else {
458 log.debug("Get FlowPath with FlowId {}: FlowPath not found",
459 flowId.toString());
460 }
461 } catch (Exception e) {
462 // TODO: handle exceptions
463 conn.endTx(Transaction.ROLLBACK);
464 log.error(":getFlow FlowId:{} failed", flowId.toString());
465 }
466 if (flowObj == null)
467 return null; // Flow not found
468
469 //
470 // Extract the Flow state
471 //
Pavlin Radoslavov706df052013-03-06 10:49:07 -0800472 FlowPath flowPath = extractFlowPath(flowObj);
473 conn.endTx(Transaction.COMMIT);
474
475 return flowPath;
476 }
477
478 /**
479 * Get all previously added flows by a specific installer for a given
480 * data path endpoints.
481 *
482 * @param installerId the Caller ID of the installer of the flow to get.
483 * @param dataPathEndpoints the data path endpoints of the flow to get.
484 * @return the Flow Paths if found, otherwise null.
485 */
486 @Override
487 public ArrayList<FlowPath> getAllFlows(CallerId installerId,
488 DataPathEndpoints dataPathEndpoints) {
489 //
490 // TODO: The implementation below is not optimal:
491 // We fetch all flows, and then return only the subset that match
492 // the query conditions.
493 // We should use the appropriate Titan/Gremlin query to filter-out
494 // the flows as appropriate.
495 //
496 ArrayList<FlowPath> allFlows = getAllFlows();
497
498 if (allFlows == null) {
499 log.debug("Get FlowPaths for installerId{} and dataPathEndpoints{}: no FlowPaths found", installerId, dataPathEndpoints);
500 return null;
501 }
502
503 ArrayList<FlowPath> flowPaths = new ArrayList<FlowPath>();
504 for (FlowPath flow : allFlows) {
505 //
506 // TODO: String-based comparison is sub-optimal.
507 // We are using it for now to save us the extra work of
508 // implementing the "equals()" and "haskCode()" methods.
509 //
510 if (! flow.installerId().toString().equals(installerId.toString()))
511 continue;
512 if (! flow.dataPath().srcPort().toString().equals(dataPathEndpoints.srcPort().toString())) {
513 continue;
514 }
515 if (! flow.dataPath().dstPort().toString().equals(dataPathEndpoints.dstPort().toString())) {
516 continue;
517 }
518 flowPaths.add(flow);
519 }
520
521 if (flowPaths.isEmpty()) {
522 log.debug("Get FlowPaths for installerId{} and dataPathEndpoints{}: no FlowPaths found", installerId, dataPathEndpoints);
523 flowPaths = null;
524 } else {
525 log.debug("Get FlowPaths for installerId{} and dataPathEndpoints{}: FlowPaths are found", installerId, dataPathEndpoints);
526 }
527
528 return flowPaths;
529 }
530
531 /**
532 * Get all installed flows by all installers for given data path endpoints.
533 *
534 * @param dataPathEndpoints the data path endpoints of the flows to get.
535 * @return the Flow Paths if found, otherwise null.
536 */
537 @Override
538 public ArrayList<FlowPath> getAllFlows(DataPathEndpoints dataPathEndpoints) {
539 //
540 // TODO: The implementation below is not optimal:
541 // We fetch all flows, and then return only the subset that match
542 // the query conditions.
543 // We should use the appropriate Titan/Gremlin query to filter-out
544 // the flows as appropriate.
545 //
546 ArrayList<FlowPath> allFlows = getAllFlows();
547
548 if (allFlows == null) {
549 log.debug("Get FlowPaths for dataPathEndpoints{}: no FlowPaths found", dataPathEndpoints);
550 return null;
551 }
552
553 ArrayList<FlowPath> flowPaths = new ArrayList<FlowPath>();
554 for (FlowPath flow : allFlows) {
555 //
556 // TODO: String-based comparison is sub-optimal.
557 // We are using it for now to save us the extra work of
558 // implementing the "equals()" and "haskCode()" methods.
559 //
560 if (! flow.dataPath().srcPort().toString().equals(dataPathEndpoints.srcPort().toString())) {
561 continue;
562 }
563 if (! flow.dataPath().dstPort().toString().equals(dataPathEndpoints.dstPort().toString())) {
564 continue;
565 }
566 flowPaths.add(flow);
567 }
568
569 if (flowPaths.isEmpty()) {
570 log.debug("Get FlowPaths for dataPathEndpoints{}: no FlowPaths found", dataPathEndpoints);
571 flowPaths = null;
572 } else {
573 log.debug("Get FlowPaths for dataPathEndpoints{}: FlowPaths are found", dataPathEndpoints);
574 }
575
576 return flowPaths;
577 }
578
579 /**
580 * Get all installed flows by all installers.
581 *
582 * @return the Flow Paths if found, otherwise null.
583 */
584 @Override
585 public ArrayList<FlowPath> getAllFlows() {
586 Iterable<IFlowPath> flowPathsObj = null;
587
588 try {
589 if ((flowPathsObj = conn.utils().getAllFlowPaths(conn)) != null) {
590 log.debug("Get all FlowPaths: found FlowPaths");
591 } else {
592 log.debug("Get all FlowPaths: no FlowPaths found");
593 }
594 } catch (Exception e) {
595 // TODO: handle exceptions
596 conn.endTx(Transaction.ROLLBACK);
597 log.error(":getAllFlowPaths failed");
598 }
599 if ((flowPathsObj == null) || (flowPathsObj.iterator().hasNext() == false))
600 return null; // No Flows found
601
602 ArrayList<FlowPath> flowPaths = new ArrayList<FlowPath>();
603 for (IFlowPath flowObj : flowPathsObj) {
604 //
605 // Extract the Flow state
606 //
607 FlowPath flowPath = extractFlowPath(flowObj);
608 flowPaths.add(flowPath);
609 }
610
611 conn.endTx(Transaction.COMMIT);
612
613 return flowPaths;
614 }
615
616 /**
617 * Extract Flow Path State from a Titan Database Object @ref IFlowPath.
618 *
619 * @param flowObj the object to extract the Flow Path State from.
620 * @return the extracted Flow Path State.
621 */
622 private FlowPath extractFlowPath(IFlowPath flowObj) {
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -0800623 FlowPath flowPath = new FlowPath();
Pavlin Radoslavov706df052013-03-06 10:49:07 -0800624
625 //
626 // Extract the Flow state
627 //
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -0800628 flowPath.setFlowId(new FlowId(flowObj.getFlowId()));
629 flowPath.setInstallerId(new CallerId(flowObj.getInstallerId()));
630 flowPath.dataPath().srcPort().setDpid(new Dpid(flowObj.getSrcSwitch()));
631 flowPath.dataPath().srcPort().setPort(new Port(flowObj.getSrcPort()));
632 flowPath.dataPath().dstPort().setDpid(new Dpid(flowObj.getDstSwitch()));
633 flowPath.dataPath().dstPort().setPort(new Port(flowObj.getDstPort()));
634
635 //
636 // Extract all Flow Entries
637 //
638 Iterable<IFlowEntry> flowEntries = flowObj.getFlowEntries();
639 for (IFlowEntry flowEntryObj : flowEntries) {
640 FlowEntry flowEntry = new FlowEntry();
641 flowEntry.setFlowEntryId(new FlowEntryId(flowEntryObj.getFlowEntryId()));
642 flowEntry.setDpid(new Dpid(flowEntryObj.getSwitchDpid()));
643 flowEntry.setInPort(new Port(flowEntryObj.getInPort()));
644 flowEntry.setOutPort(new Port(flowEntryObj.getOutPort()));
645 String userState = flowEntryObj.getUserState();
646 flowEntry.setFlowEntryUserState(FlowEntryUserState.valueOf(userState));
647 String switchState = flowEntryObj.getSwitchState();
648 flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.valueOf(switchState));
649 //
650 // TODO: Take care of the FlowEntryMatch, FlowEntryActions,
651 // and FlowEntryErrorState.
652 //
653 flowPath.dataPath().flowEntries().add(flowEntry);
654 }
Pavlin Radoslavovb6f53542013-03-01 16:02:14 -0800655
656 return flowPath;
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800657 }
Pavlin Radoslavov9e5344c2013-02-18 09:58:30 -0800658}