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