blob: 533652043fa19a60633c0e99cca12396d63d9e4d [file] [log] [blame]
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -07001package net.onrc.onos.ofcontroller.flowmanager;
2
3import java.io.PrintWriter;
4import java.io.StringWriter;
5import java.util.ArrayList;
6import java.util.Collections;
7import java.util.Comparator;
8import java.util.LinkedList;
9import java.util.List;
10import java.util.concurrent.ConcurrentLinkedQueue;
11
12import net.floodlightcontroller.util.MACAddress;
13
14import net.onrc.onos.graph.GraphDBOperation;
15
16import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowEntry;
17import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowPath;
18import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IPortObject;
19import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.ISwitchObject;
20import net.onrc.onos.ofcontroller.util.*;
21
22import org.slf4j.Logger;
23import org.slf4j.LoggerFactory;
24
25/**
26 * Class for performing Flow-related operations on the Database.
27 */
28class FlowDatabaseOperation {
Yuta HIGUCHI6ac8d182013-10-22 15:24:56 -070029 private final static Logger log = LoggerFactory.getLogger(FlowDatabaseOperation.class);
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070030
31 /**
32 * Add a flow.
33 *
34 * @param flowManager the Flow Manager to use.
35 * @param dbHandler the Graph Database handler to use.
36 * @param flowPath the Flow Path to install.
37 * @param flowId the return-by-reference Flow ID as assigned internally.
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070038 * @return true on success, otherwise false.
39 */
40 static boolean addFlow(FlowManager flowManager,
41 GraphDBOperation dbHandler,
Pavlin Radoslavovbcc86ef2013-10-26 12:06:25 -070042 FlowPath flowPath, FlowId flowId) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070043 IFlowPath flowObj = null;
44 boolean found = false;
45 try {
46 if ((flowObj = dbHandler.searchFlowPath(flowPath.flowId())) != null) {
47 found = true;
48 } else {
49 flowObj = dbHandler.newFlowPath();
50 }
51 } catch (Exception e) {
52 dbHandler.rollback();
53
54 StringWriter sw = new StringWriter();
55 e.printStackTrace(new PrintWriter(sw));
56 String stacktrace = sw.toString();
57
58 log.error(":addFlow FlowId:{} failed: {}",
59 flowPath.flowId().toString(),
60 stacktrace);
61 return false;
62 }
63 if (flowObj == null) {
64 log.error(":addFlow FlowId:{} failed: Flow object not created",
65 flowPath.flowId().toString());
66 dbHandler.rollback();
67 return false;
68 }
69
70 //
71 // Set the Flow key:
72 // - flowId
73 //
74 flowObj.setFlowId(flowPath.flowId().toString());
75 flowObj.setType("flow");
76
77 //
78 // Set the Flow attributes:
79 // - flowPath.installerId()
Pavlin Radoslavovd28cf7c2013-10-26 11:27:43 -070080 // - flowPath.flowPathType()
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070081 // - flowPath.flowPathFlags()
82 // - flowPath.dataPath().srcPort()
83 // - flowPath.dataPath().dstPort()
84 // - flowPath.matchSrcMac()
85 // - flowPath.matchDstMac()
86 // - flowPath.matchEthernetFrameType()
87 // - flowPath.matchVlanId()
88 // - flowPath.matchVlanPriority()
89 // - flowPath.matchSrcIPv4Net()
90 // - flowPath.matchDstIPv4Net()
91 // - flowPath.matchIpProto()
92 // - flowPath.matchIpToS()
93 // - flowPath.matchSrcTcpUdpPort()
94 // - flowPath.matchDstTcpUdpPort()
95 // - flowPath.flowEntryActions()
96 //
97 flowObj.setInstallerId(flowPath.installerId().toString());
Pavlin Radoslavovd28cf7c2013-10-26 11:27:43 -070098 flowObj.setFlowPathType(flowPath.flowPathType().toString());
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070099 flowObj.setFlowPathFlags(flowPath.flowPathFlags().flags());
100 flowObj.setSrcSwitch(flowPath.dataPath().srcPort().dpid().toString());
101 flowObj.setSrcPort(flowPath.dataPath().srcPort().port().value());
102 flowObj.setDstSwitch(flowPath.dataPath().dstPort().dpid().toString());
103 flowObj.setDstPort(flowPath.dataPath().dstPort().port().value());
104 if (flowPath.flowEntryMatch().matchSrcMac()) {
105 flowObj.setMatchSrcMac(flowPath.flowEntryMatch().srcMac().toString());
106 }
107 if (flowPath.flowEntryMatch().matchDstMac()) {
108 flowObj.setMatchDstMac(flowPath.flowEntryMatch().dstMac().toString());
109 }
110 if (flowPath.flowEntryMatch().matchEthernetFrameType()) {
111 flowObj.setMatchEthernetFrameType(flowPath.flowEntryMatch().ethernetFrameType());
112 }
113 if (flowPath.flowEntryMatch().matchVlanId()) {
114 flowObj.setMatchVlanId(flowPath.flowEntryMatch().vlanId());
115 }
116 if (flowPath.flowEntryMatch().matchVlanPriority()) {
117 flowObj.setMatchVlanPriority(flowPath.flowEntryMatch().vlanPriority());
118 }
119 if (flowPath.flowEntryMatch().matchSrcIPv4Net()) {
120 flowObj.setMatchSrcIPv4Net(flowPath.flowEntryMatch().srcIPv4Net().toString());
121 }
122 if (flowPath.flowEntryMatch().matchDstIPv4Net()) {
123 flowObj.setMatchDstIPv4Net(flowPath.flowEntryMatch().dstIPv4Net().toString());
124 }
125 if (flowPath.flowEntryMatch().matchIpProto()) {
126 flowObj.setMatchIpProto(flowPath.flowEntryMatch().ipProto());
127 }
128 if (flowPath.flowEntryMatch().matchIpToS()) {
129 flowObj.setMatchIpToS(flowPath.flowEntryMatch().ipToS());
130 }
131 if (flowPath.flowEntryMatch().matchSrcTcpUdpPort()) {
132 flowObj.setMatchSrcTcpUdpPort(flowPath.flowEntryMatch().srcTcpUdpPort());
133 }
134 if (flowPath.flowEntryMatch().matchDstTcpUdpPort()) {
135 flowObj.setMatchDstTcpUdpPort(flowPath.flowEntryMatch().dstTcpUdpPort());
136 }
137 if (! flowPath.flowEntryActions().actions().isEmpty()) {
138 flowObj.setActions(flowPath.flowEntryActions().toString());
139 }
Pavlin Radoslavovbcc86ef2013-10-26 12:06:25 -0700140 flowObj.setDataPathSummary(flowPath.dataPath().dataPathSummary());
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700141
142 if (found)
143 flowObj.setUserState("FE_USER_MODIFY");
144 else
145 flowObj.setUserState("FE_USER_ADD");
146
147 // Flow edges:
148 // HeadFE
149
150
151 //
152 // Flow Entries:
153 // flowPath.dataPath().flowEntries()
154 //
155 for (FlowEntry flowEntry : flowPath.dataPath().flowEntries()) {
156 if (addFlowEntry(flowManager, dbHandler, flowObj, flowEntry) == null) {
157 dbHandler.rollback();
158 return false;
159 }
160 }
161 dbHandler.commit();
162
163 //
164 // TODO: We need a proper Flow ID allocation mechanism.
165 //
166 flowId.setValue(flowPath.flowId().value());
167
168 return true;
169 }
170
171 /**
172 * Add a flow entry to the Network MAP.
173 *
174 * @param flowManager the Flow Manager to use.
175 * @param dbHandler the Graph Database handler to use.
176 * @param flowObj the corresponding Flow Path object for the Flow Entry.
177 * @param flowEntry the Flow Entry to install.
178 * @return the added Flow Entry object on success, otherwise null.
179 */
180 static IFlowEntry addFlowEntry(FlowManager flowManager,
181 GraphDBOperation dbHandler,
182 IFlowPath flowObj,
183 FlowEntry flowEntry) {
184 // Flow edges
185 // HeadFE (TODO)
186
187 //
188 // Assign the FlowEntry ID.
189 //
190 if ((flowEntry.flowEntryId() == null) ||
191 (flowEntry.flowEntryId().value() == 0)) {
192 long id = flowManager.getNextFlowEntryId();
193 flowEntry.setFlowEntryId(new FlowEntryId(id));
194 }
195
196 IFlowEntry flowEntryObj = null;
197 boolean found = false;
198 try {
199 if ((flowEntryObj =
200 dbHandler.searchFlowEntry(flowEntry.flowEntryId())) != null) {
201 found = true;
202 } else {
203 flowEntryObj = dbHandler.newFlowEntry();
204 }
205 } catch (Exception e) {
206 log.error(":addFlow FlowEntryId:{} failed",
207 flowEntry.flowEntryId().toString());
208 return null;
209 }
210 if (flowEntryObj == null) {
211 log.error(":addFlow FlowEntryId:{} failed: FlowEntry object not created",
212 flowEntry.flowEntryId().toString());
213 return null;
214 }
215
216 //
217 // Set the Flow Entry key:
218 // - flowEntry.flowEntryId()
219 //
220 flowEntryObj.setFlowEntryId(flowEntry.flowEntryId().toString());
221 flowEntryObj.setType("flow_entry");
222
223 //
224 // Set the Flow Entry Edges and attributes:
225 // - Switch edge
226 // - InPort edge
227 // - OutPort edge
228 //
229 // - flowEntry.dpid()
230 // - flowEntry.flowEntryUserState()
231 // - flowEntry.flowEntrySwitchState()
232 // - flowEntry.flowEntryErrorState()
233 // - flowEntry.matchInPort()
234 // - flowEntry.matchSrcMac()
235 // - flowEntry.matchDstMac()
236 // - flowEntry.matchEthernetFrameType()
237 // - flowEntry.matchVlanId()
238 // - flowEntry.matchVlanPriority()
239 // - flowEntry.matchSrcIPv4Net()
240 // - flowEntry.matchDstIPv4Net()
241 // - flowEntry.matchIpProto()
242 // - flowEntry.matchIpToS()
243 // - flowEntry.matchSrcTcpUdpPort()
244 // - flowEntry.matchDstTcpUdpPort()
245 // - flowEntry.actionOutputPort()
246 // - flowEntry.actions()
247 //
248 ISwitchObject sw = dbHandler.searchSwitch(flowEntry.dpid().toString());
249 flowEntryObj.setSwitchDpid(flowEntry.dpid().toString());
250 flowEntryObj.setSwitch(sw);
251 if (flowEntry.flowEntryMatch().matchInPort()) {
252 IPortObject inport =
253 dbHandler.searchPort(flowEntry.dpid().toString(),
254 flowEntry.flowEntryMatch().inPort().value());
255 flowEntryObj.setMatchInPort(flowEntry.flowEntryMatch().inPort().value());
256 flowEntryObj.setInPort(inport);
257 }
258 if (flowEntry.flowEntryMatch().matchSrcMac()) {
259 flowEntryObj.setMatchSrcMac(flowEntry.flowEntryMatch().srcMac().toString());
260 }
261 if (flowEntry.flowEntryMatch().matchDstMac()) {
262 flowEntryObj.setMatchDstMac(flowEntry.flowEntryMatch().dstMac().toString());
263 }
264 if (flowEntry.flowEntryMatch().matchEthernetFrameType()) {
265 flowEntryObj.setMatchEthernetFrameType(flowEntry.flowEntryMatch().ethernetFrameType());
266 }
267 if (flowEntry.flowEntryMatch().matchVlanId()) {
268 flowEntryObj.setMatchVlanId(flowEntry.flowEntryMatch().vlanId());
269 }
270 if (flowEntry.flowEntryMatch().matchVlanPriority()) {
271 flowEntryObj.setMatchVlanPriority(flowEntry.flowEntryMatch().vlanPriority());
272 }
273 if (flowEntry.flowEntryMatch().matchSrcIPv4Net()) {
274 flowEntryObj.setMatchSrcIPv4Net(flowEntry.flowEntryMatch().srcIPv4Net().toString());
275 }
276 if (flowEntry.flowEntryMatch().matchDstIPv4Net()) {
277 flowEntryObj.setMatchDstIPv4Net(flowEntry.flowEntryMatch().dstIPv4Net().toString());
278 }
279 if (flowEntry.flowEntryMatch().matchIpProto()) {
280 flowEntryObj.setMatchIpProto(flowEntry.flowEntryMatch().ipProto());
281 }
282 if (flowEntry.flowEntryMatch().matchIpToS()) {
283 flowEntryObj.setMatchIpToS(flowEntry.flowEntryMatch().ipToS());
284 }
285 if (flowEntry.flowEntryMatch().matchSrcTcpUdpPort()) {
286 flowEntryObj.setMatchSrcTcpUdpPort(flowEntry.flowEntryMatch().srcTcpUdpPort());
287 }
288 if (flowEntry.flowEntryMatch().matchDstTcpUdpPort()) {
289 flowEntryObj.setMatchDstTcpUdpPort(flowEntry.flowEntryMatch().dstTcpUdpPort());
290 }
291
292 for (FlowEntryAction fa : flowEntry.flowEntryActions().actions()) {
293 if (fa.actionOutput() != null) {
294 IPortObject outport =
295 dbHandler.searchPort(flowEntry.dpid().toString(),
296 fa.actionOutput().port().value());
297 flowEntryObj.setActionOutputPort(fa.actionOutput().port().value());
298 flowEntryObj.setOutPort(outport);
299 }
300 }
301 if (! flowEntry.flowEntryActions().isEmpty()) {
302 flowEntryObj.setActions(flowEntry.flowEntryActions().toString());
303 }
304
305 // TODO: Hacks with hard-coded state names!
306 if (found)
307 flowEntryObj.setUserState("FE_USER_MODIFY");
308 else
309 flowEntryObj.setUserState("FE_USER_ADD");
310 flowEntryObj.setSwitchState("FE_SWITCH_NOT_UPDATED");
311 //
312 // TODO: Take care of the FlowEntryErrorState.
313 //
314
315 // Flow Entries edges:
316 // Flow
317 // NextFE (TODO)
318 if (! found) {
319 flowObj.addFlowEntry(flowEntryObj);
320 flowEntryObj.setFlow(flowObj);
321 }
322
323 return flowEntryObj;
324 }
325
326 /**
327 * Delete all previously added flows.
328 *
329 * @param dbHandler the Graph Database handler to use.
330 * @return true on success, otherwise false.
331 */
332 static boolean deleteAllFlows(GraphDBOperation dbHandler) {
333 final ConcurrentLinkedQueue<FlowId> concurrentAllFlowIds =
334 new ConcurrentLinkedQueue<FlowId>();
335
336 // Get all Flow IDs
337 Iterable<IFlowPath> allFlowPaths = dbHandler.getAllFlowPaths();
338 for (IFlowPath flowPathObj : allFlowPaths) {
339 if (flowPathObj == null)
340 continue;
341 String flowIdStr = flowPathObj.getFlowId();
342 if (flowIdStr == null)
343 continue;
344 FlowId flowId = new FlowId(flowIdStr);
345 concurrentAllFlowIds.add(flowId);
346 }
347
348 // Delete all flows one-by-one
349 for (FlowId flowId : concurrentAllFlowIds)
350 deleteFlow(dbHandler, flowId);
351
352 /*
353 * TODO: A faster mechanism to delete the Flow Paths by using
354 * a number of threads. Commented-out for now.
355 */
356 /*
357 //
358 // Create the threads to delete the Flow Paths
359 //
360 List<Thread> threads = new LinkedList<Thread>();
361 for (int i = 0; i < 10; i++) {
362 Thread thread = new Thread(new Runnable() {
363 @Override
364 public void run() {
365 while (true) {
366 FlowId flowId = concurrentAllFlowIds.poll();
367 if (flowId == null)
368 return;
369 deleteFlow(dbHandler, flowId);
370 }
371 }}, "Delete All Flow Paths");
372 threads.add(thread);
373 }
374
375 // Start processing
376 for (Thread thread : threads) {
377 thread.start();
378 }
379
380 // Wait for all threads to complete
381 for (Thread thread : threads) {
382 try {
383 thread.join();
384 } catch (InterruptedException e) {
385 log.debug("Exception waiting for a thread to delete a Flow Path: ", e);
386 }
387 }
388 */
389
390 return true;
391 }
392
393 /**
394 * Delete a previously added flow.
395 *
396 * @param dbHandler the Graph Database handler to use.
397 * @param flowId the Flow ID of the flow to delete.
398 * @return true on success, otherwise false.
399 */
400 static boolean deleteFlow(GraphDBOperation dbHandler, FlowId flowId) {
401 IFlowPath flowObj = null;
402 //
403 // We just mark the entries for deletion,
404 // and let the switches remove each individual entry after
405 // it has been removed from the switches.
406 //
407 try {
408 flowObj = dbHandler.searchFlowPath(flowId);
409 } catch (Exception e) {
410 // TODO: handle exceptions
411 dbHandler.rollback();
412 log.error(":deleteFlow FlowId:{} failed", flowId.toString());
413 return false;
414 }
415 if (flowObj == null) {
416 dbHandler.commit();
417 return true; // OK: No such flow
418 }
419
420 //
421 // Find and mark for deletion all Flow Entries,
422 // and the Flow itself.
423 //
424 flowObj.setUserState("FE_USER_DELETE");
425 Iterable<IFlowEntry> flowEntries = flowObj.getFlowEntries();
426 boolean empty = true; // TODO: an ugly hack
427 for (IFlowEntry flowEntryObj : flowEntries) {
428 empty = false;
429 // flowObj.removeFlowEntry(flowEntryObj);
430 // conn.utils().removeFlowEntry(conn, flowEntryObj);
431 flowEntryObj.setUserState("FE_USER_DELETE");
432 flowEntryObj.setSwitchState("FE_SWITCH_NOT_UPDATED");
433 }
434 // Remove from the database empty flows
435 if (empty)
436 dbHandler.removeFlowPath(flowObj);
437 dbHandler.commit();
438
439 return true;
440 }
441
442 /**
443 * Clear the state for all previously added flows.
444 *
445 * @param dbHandler the Graph Database handler to use.
446 * @return true on success, otherwise false.
447 */
448 static boolean clearAllFlows(GraphDBOperation dbHandler) {
449 List<FlowId> allFlowIds = new LinkedList<FlowId>();
450
451 // Get all Flow IDs
452 Iterable<IFlowPath> allFlowPaths = dbHandler.getAllFlowPaths();
453 for (IFlowPath flowPathObj : allFlowPaths) {
454 if (flowPathObj == null)
455 continue;
456 String flowIdStr = flowPathObj.getFlowId();
457 if (flowIdStr == null)
458 continue;
459 FlowId flowId = new FlowId(flowIdStr);
460 allFlowIds.add(flowId);
461 }
462
463 // Clear all flows one-by-one
464 for (FlowId flowId : allFlowIds) {
465 clearFlow(dbHandler, flowId);
466 }
467
468 return true;
469 }
470
471 /**
472 * Clear the state for a previously added flow.
473 *
474 * @param dbHandler the Graph Database handler to use.
475 * @param flowId the Flow ID of the flow to clear.
476 * @return true on success, otherwise false.
477 */
478 static boolean clearFlow(GraphDBOperation dbHandler, FlowId flowId) {
479 IFlowPath flowObj = null;
480 try {
481 flowObj = dbHandler.searchFlowPath(flowId);
482 } catch (Exception e) {
483 // TODO: handle exceptions
484 dbHandler.rollback();
485 log.error(":clearFlow FlowId:{} failed", flowId.toString());
486 return false;
487 }
488 if (flowObj == null) {
489 dbHandler.commit();
490 return true; // OK: No such flow
491 }
492
493 //
494 // Remove all Flow Entries
495 //
496 Iterable<IFlowEntry> flowEntries = flowObj.getFlowEntries();
497 for (IFlowEntry flowEntryObj : flowEntries) {
498 flowObj.removeFlowEntry(flowEntryObj);
499 dbHandler.removeFlowEntry(flowEntryObj);
500 }
501 // Remove the Flow itself
502 dbHandler.removeFlowPath(flowObj);
503 dbHandler.commit();
504
505 return true;
506 }
507
508 /**
509 * Get a previously added flow.
510 *
511 * @param dbHandler the Graph Database handler to use.
512 * @param flowId the Flow ID of the flow to get.
513 * @return the Flow Path if found, otherwise null.
514 */
515 static FlowPath getFlow(GraphDBOperation dbHandler, FlowId flowId) {
516 IFlowPath flowObj = null;
517 try {
518 flowObj = dbHandler.searchFlowPath(flowId);
519 } catch (Exception e) {
520 // TODO: handle exceptions
521 dbHandler.rollback();
522 log.error(":getFlow FlowId:{} failed", flowId.toString());
523 return null;
524 }
525 if (flowObj == null) {
526 dbHandler.commit();
527 return null; // Flow not found
528 }
529
530 //
531 // Extract the Flow state
532 //
533 FlowPath flowPath = extractFlowPath(flowObj);
534 dbHandler.commit();
535
536 return flowPath;
537 }
538
539 /**
540 * Get all installed flows by all installers.
541 *
542 * @param dbHandler the Graph Database handler to use.
543 * @return the Flow Paths if found, otherwise null.
544 */
545 static ArrayList<FlowPath> getAllFlows(GraphDBOperation dbHandler) {
546 Iterable<IFlowPath> flowPathsObj = null;
547 ArrayList<FlowPath> flowPaths = new ArrayList<FlowPath>();
548
549 try {
550 flowPathsObj = dbHandler.getAllFlowPaths();
551 } catch (Exception e) {
552 // TODO: handle exceptions
553 dbHandler.rollback();
554 log.error(":getAllFlowPaths failed");
555 return flowPaths;
556 }
557 if ((flowPathsObj == null) || (flowPathsObj.iterator().hasNext() == false)) {
558 dbHandler.commit();
559 return flowPaths; // No Flows found
560 }
561
562 for (IFlowPath flowObj : flowPathsObj) {
563 //
564 // Extract the Flow state
565 //
566 FlowPath flowPath = extractFlowPath(flowObj);
567 if (flowPath != null)
568 flowPaths.add(flowPath);
569 }
570
571 dbHandler.commit();
572
573 return flowPaths;
574 }
575
576 /**
577 * Get all previously added flows by a specific installer for a given
578 * data path endpoints.
579 *
580 * @param dbHandler the Graph Database handler to use.
581 * @param installerId the Caller ID of the installer of the flow to get.
582 * @param dataPathEndpoints the data path endpoints of the flow to get.
583 * @return the Flow Paths if found, otherwise null.
584 */
585 static ArrayList<FlowPath> getAllFlows(GraphDBOperation dbHandler,
586 CallerId installerId,
587 DataPathEndpoints dataPathEndpoints) {
588 //
589 // TODO: The implementation below is not optimal:
590 // We fetch all flows, and then return only the subset that match
591 // the query conditions.
592 // We should use the appropriate Titan/Gremlin query to filter-out
593 // the flows as appropriate.
594 //
595 ArrayList<FlowPath> allFlows = getAllFlows(dbHandler);
596 ArrayList<FlowPath> flowPaths = new ArrayList<FlowPath>();
597
598 if (allFlows == null)
599 return flowPaths;
600
601 for (FlowPath flow : allFlows) {
602 //
603 // TODO: String-based comparison is sub-optimal.
604 // We are using it for now to save us the extra work of
605 // implementing the "equals()" and "hashCode()" methods.
606 //
607 if (! flow.installerId().toString().equals(installerId.toString()))
608 continue;
609 if (! flow.dataPath().srcPort().toString().equals(dataPathEndpoints.srcPort().toString())) {
610 continue;
611 }
612 if (! flow.dataPath().dstPort().toString().equals(dataPathEndpoints.dstPort().toString())) {
613 continue;
614 }
615 flowPaths.add(flow);
616 }
617
618 return flowPaths;
619 }
620
621 /**
622 * Get all installed flows by all installers for given data path endpoints.
623 *
624 * @param dbHandler the Graph Database handler to use.
625 * @param dataPathEndpoints the data path endpoints of the flows to get.
626 * @return the Flow Paths if found, otherwise null.
627 */
628 static ArrayList<FlowPath> getAllFlows(GraphDBOperation dbHandler,
629 DataPathEndpoints dataPathEndpoints) {
630 //
631 // TODO: The implementation below is not optimal:
632 // We fetch all flows, and then return only the subset that match
633 // the query conditions.
634 // We should use the appropriate Titan/Gremlin query to filter-out
635 // the flows as appropriate.
636 //
637 ArrayList<FlowPath> flowPaths = new ArrayList<FlowPath>();
638 ArrayList<FlowPath> allFlows = getAllFlows(dbHandler);
639
640 if (allFlows == null)
641 return flowPaths;
642
643 for (FlowPath flow : allFlows) {
644 //
645 // TODO: String-based comparison is sub-optimal.
646 // We are using it for now to save us the extra work of
647 // implementing the "equals()" and "hashCode()" methods.
648 //
649 if (! flow.dataPath().srcPort().toString().equals(dataPathEndpoints.srcPort().toString())) {
650 continue;
651 }
652 if (! flow.dataPath().dstPort().toString().equals(dataPathEndpoints.dstPort().toString())) {
653 continue;
654 }
655 flowPaths.add(flow);
656 }
657
658 return flowPaths;
659 }
660
661 /**
662 * Get summary of all installed flows by all installers in a given range.
663 *
664 * @param dbHandler the Graph Database handler to use.
665 * @param flowId the Flow ID of the first flow in the flow range to get.
666 * @param maxFlows the maximum number of flows to be returned.
667 * @return the Flow Paths if found, otherwise null.
668 */
669 static ArrayList<IFlowPath> getAllFlowsSummary(GraphDBOperation dbHandler,
670 FlowId flowId,
671 int maxFlows) {
672 //
673 // TODO: The implementation below is not optimal:
674 // We fetch all flows, and then return only the subset that match
675 // the query conditions.
676 // We should use the appropriate Titan/Gremlin query to filter-out
677 // the flows as appropriate.
678 //
679 ArrayList<IFlowPath> flowPathsWithoutFlowEntries =
680 getAllFlowsWithoutFlowEntries(dbHandler);
681
682 Collections.sort(flowPathsWithoutFlowEntries,
683 new Comparator<IFlowPath>() {
684 @Override
685 public int compare(IFlowPath first, IFlowPath second) {
686 long result =
687 new FlowId(first.getFlowId()).value()
688 - new FlowId(second.getFlowId()).value();
689 if (result > 0) {
690 return 1;
691 } else if (result < 0) {
692 return -1;
693 } else {
694 return 0;
695 }
696 }
697 }
698 );
699
700 return flowPathsWithoutFlowEntries;
701 }
702
703 /**
704 * Get all Flows information, without the associated Flow Entries.
705 *
706 * @param dbHandler the Graph Database handler to use.
707 * @return all Flows information, without the associated Flow Entries.
708 */
709 static ArrayList<IFlowPath> getAllFlowsWithoutFlowEntries(GraphDBOperation dbHandler) {
710 Iterable<IFlowPath> flowPathsObj = null;
711 ArrayList<IFlowPath> flowPathsObjArray = new ArrayList<IFlowPath>();
712
713 // TODO: Remove this op.commit() flow, because it is not needed?
714 dbHandler.commit();
715
716 try {
717 flowPathsObj = dbHandler.getAllFlowPaths();
718 } catch (Exception e) {
719 // TODO: handle exceptions
720 dbHandler.rollback();
721 log.error(":getAllFlowPaths failed");
722 return flowPathsObjArray; // No Flows found
723 }
724 if ((flowPathsObj == null) || (flowPathsObj.iterator().hasNext() == false)) {
725 return flowPathsObjArray; // No Flows found
726 }
727
728 for (IFlowPath flowObj : flowPathsObj)
729 flowPathsObjArray.add(flowObj);
730
731 // conn.endTx(Transaction.COMMIT);
732
733 return flowPathsObjArray;
734 }
735
736 /**
737 * Extract Flow Path State from a Titan Database Object @ref IFlowPath.
738 *
739 * @param flowObj the object to extract the Flow Path State from.
740 * @return the extracted Flow Path State.
741 */
742 private static FlowPath extractFlowPath(IFlowPath flowObj) {
743 //
744 // Extract the Flow state
745 //
746 String flowIdStr = flowObj.getFlowId();
747 String installerIdStr = flowObj.getInstallerId();
Pavlin Radoslavovd28cf7c2013-10-26 11:27:43 -0700748 String flowPathType = flowObj.getFlowPathType();
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700749 Long flowPathFlags = flowObj.getFlowPathFlags();
750 String srcSwitchStr = flowObj.getSrcSwitch();
751 Short srcPortShort = flowObj.getSrcPort();
752 String dstSwitchStr = flowObj.getDstSwitch();
753 Short dstPortShort = flowObj.getDstPort();
754
755 if ((flowIdStr == null) ||
756 (installerIdStr == null) ||
Pavlin Radoslavovd28cf7c2013-10-26 11:27:43 -0700757 (flowPathType == null) ||
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700758 (flowPathFlags == null) ||
759 (srcSwitchStr == null) ||
760 (srcPortShort == null) ||
761 (dstSwitchStr == null) ||
762 (dstPortShort == null)) {
763 // TODO: A work-around, becauuse of some bogus database objects
764 return null;
765 }
766
767 FlowPath flowPath = new FlowPath();
768 flowPath.setFlowId(new FlowId(flowIdStr));
769 flowPath.setInstallerId(new CallerId(installerIdStr));
Pavlin Radoslavovd28cf7c2013-10-26 11:27:43 -0700770 flowPath.setFlowPathType(FlowPathType.valueOf(flowPathType));
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700771 flowPath.setFlowPathFlags(new FlowPathFlags(flowPathFlags));
772 flowPath.dataPath().srcPort().setDpid(new Dpid(srcSwitchStr));
773 flowPath.dataPath().srcPort().setPort(new Port(srcPortShort));
774 flowPath.dataPath().dstPort().setDpid(new Dpid(dstSwitchStr));
775 flowPath.dataPath().dstPort().setPort(new Port(dstPortShort));
776 //
777 // Extract the match conditions common for all Flow Entries
778 //
779 {
780 FlowEntryMatch match = new FlowEntryMatch();
781 String matchSrcMac = flowObj.getMatchSrcMac();
782 if (matchSrcMac != null)
783 match.enableSrcMac(MACAddress.valueOf(matchSrcMac));
784 String matchDstMac = flowObj.getMatchDstMac();
785 if (matchDstMac != null)
786 match.enableDstMac(MACAddress.valueOf(matchDstMac));
787 Short matchEthernetFrameType = flowObj.getMatchEthernetFrameType();
788 if (matchEthernetFrameType != null)
789 match.enableEthernetFrameType(matchEthernetFrameType);
790 Short matchVlanId = flowObj.getMatchVlanId();
791 if (matchVlanId != null)
792 match.enableVlanId(matchVlanId);
793 Byte matchVlanPriority = flowObj.getMatchVlanPriority();
794 if (matchVlanPriority != null)
795 match.enableVlanPriority(matchVlanPriority);
796 String matchSrcIPv4Net = flowObj.getMatchSrcIPv4Net();
797 if (matchSrcIPv4Net != null)
798 match.enableSrcIPv4Net(new IPv4Net(matchSrcIPv4Net));
799 String matchDstIPv4Net = flowObj.getMatchDstIPv4Net();
800 if (matchDstIPv4Net != null)
801 match.enableDstIPv4Net(new IPv4Net(matchDstIPv4Net));
802 Byte matchIpProto = flowObj.getMatchIpProto();
803 if (matchIpProto != null)
804 match.enableIpProto(matchIpProto);
805 Byte matchIpToS = flowObj.getMatchIpToS();
806 if (matchIpToS != null)
807 match.enableIpToS(matchIpToS);
808 Short matchSrcTcpUdpPort = flowObj.getMatchSrcTcpUdpPort();
809 if (matchSrcTcpUdpPort != null)
810 match.enableSrcTcpUdpPort(matchSrcTcpUdpPort);
811 Short matchDstTcpUdpPort = flowObj.getMatchDstTcpUdpPort();
812 if (matchDstTcpUdpPort != null)
813 match.enableDstTcpUdpPort(matchDstTcpUdpPort);
814
815 flowPath.setFlowEntryMatch(match);
816 }
817 //
818 // Extract the actions for the first Flow Entry
819 //
820 {
821 String actionsStr = flowObj.getActions();
822 if (actionsStr != null) {
823 FlowEntryActions flowEntryActions = new FlowEntryActions(actionsStr);
824 flowPath.setFlowEntryActions(flowEntryActions);
825 }
826 }
827
828 //
829 // Extract all Flow Entries
830 //
831 Iterable<IFlowEntry> flowEntries = flowObj.getFlowEntries();
832 for (IFlowEntry flowEntryObj : flowEntries) {
833 FlowEntry flowEntry = extractFlowEntry(flowEntryObj);
834 if (flowEntry == null)
835 continue;
836 flowPath.dataPath().flowEntries().add(flowEntry);
837 }
838
839 return flowPath;
840 }
841
842 /**
843 * Extract Flow Entry State from a Titan Database Object @ref IFlowEntry.
844 *
845 * @param flowEntryObj the object to extract the Flow Entry State from.
846 * @return the extracted Flow Entry State.
847 */
848 private static FlowEntry extractFlowEntry(IFlowEntry flowEntryObj) {
849 String flowEntryIdStr = flowEntryObj.getFlowEntryId();
850 String switchDpidStr = flowEntryObj.getSwitchDpid();
851 String userState = flowEntryObj.getUserState();
852 String switchState = flowEntryObj.getSwitchState();
853
854 if ((flowEntryIdStr == null) ||
855 (switchDpidStr == null) ||
856 (userState == null) ||
857 (switchState == null)) {
858 // TODO: A work-around, becauuse of some bogus database objects
859 return null;
860 }
861
862 FlowEntry flowEntry = new FlowEntry();
863 flowEntry.setFlowEntryId(new FlowEntryId(flowEntryIdStr));
864 flowEntry.setDpid(new Dpid(switchDpidStr));
865
866 //
867 // Extract the match conditions
868 //
869 FlowEntryMatch match = new FlowEntryMatch();
870 Short matchInPort = flowEntryObj.getMatchInPort();
871 if (matchInPort != null)
872 match.enableInPort(new Port(matchInPort));
873 String matchSrcMac = flowEntryObj.getMatchSrcMac();
874 if (matchSrcMac != null)
875 match.enableSrcMac(MACAddress.valueOf(matchSrcMac));
876 String matchDstMac = flowEntryObj.getMatchDstMac();
877 if (matchDstMac != null)
878 match.enableDstMac(MACAddress.valueOf(matchDstMac));
879 Short matchEthernetFrameType = flowEntryObj.getMatchEthernetFrameType();
880 if (matchEthernetFrameType != null)
881 match.enableEthernetFrameType(matchEthernetFrameType);
882 Short matchVlanId = flowEntryObj.getMatchVlanId();
883 if (matchVlanId != null)
884 match.enableVlanId(matchVlanId);
885 Byte matchVlanPriority = flowEntryObj.getMatchVlanPriority();
886 if (matchVlanPriority != null)
887 match.enableVlanPriority(matchVlanPriority);
888 String matchSrcIPv4Net = flowEntryObj.getMatchSrcIPv4Net();
889 if (matchSrcIPv4Net != null)
890 match.enableSrcIPv4Net(new IPv4Net(matchSrcIPv4Net));
891 String matchDstIPv4Net = flowEntryObj.getMatchDstIPv4Net();
892 if (matchDstIPv4Net != null)
893 match.enableDstIPv4Net(new IPv4Net(matchDstIPv4Net));
894 Byte matchIpProto = flowEntryObj.getMatchIpProto();
895 if (matchIpProto != null)
896 match.enableIpProto(matchIpProto);
897 Byte matchIpToS = flowEntryObj.getMatchIpToS();
898 if (matchIpToS != null)
899 match.enableIpToS(matchIpToS);
900 Short matchSrcTcpUdpPort = flowEntryObj.getMatchSrcTcpUdpPort();
901 if (matchSrcTcpUdpPort != null)
902 match.enableSrcTcpUdpPort(matchSrcTcpUdpPort);
903 Short matchDstTcpUdpPort = flowEntryObj.getMatchDstTcpUdpPort();
904 if (matchDstTcpUdpPort != null)
905 match.enableDstTcpUdpPort(matchDstTcpUdpPort);
906 flowEntry.setFlowEntryMatch(match);
907
908 //
909 // Extract the actions
910 //
911 FlowEntryActions actions = new FlowEntryActions();
912 String actionsStr = flowEntryObj.getActions();
913 if (actionsStr != null)
914 actions = new FlowEntryActions(actionsStr);
915 flowEntry.setFlowEntryActions(actions);
916 flowEntry.setFlowEntryUserState(FlowEntryUserState.valueOf(userState));
917 flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.valueOf(switchState));
918 //
919 // TODO: Take care of FlowEntryErrorState.
920 //
921 return flowEntry;
922 }
923}