blob: 58a590f7861e7ce43f8cba1d3bbf2de49491b182 [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 */
Pavlin Radoslavov6bfaea62013-12-03 14:55:57 -080028public class 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 Radoslavov7d4a40e2013-10-27 23:39:40 -070081 // - flowPath.flowPathUserState()
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070082 // - flowPath.flowPathFlags()
83 // - flowPath.dataPath().srcPort()
84 // - flowPath.dataPath().dstPort()
85 // - flowPath.matchSrcMac()
86 // - flowPath.matchDstMac()
87 // - flowPath.matchEthernetFrameType()
88 // - flowPath.matchVlanId()
89 // - flowPath.matchVlanPriority()
90 // - flowPath.matchSrcIPv4Net()
91 // - flowPath.matchDstIPv4Net()
92 // - flowPath.matchIpProto()
93 // - flowPath.matchIpToS()
94 // - flowPath.matchSrcTcpUdpPort()
95 // - flowPath.matchDstTcpUdpPort()
96 // - flowPath.flowEntryActions()
97 //
98 flowObj.setInstallerId(flowPath.installerId().toString());
Pavlin Radoslavovd28cf7c2013-10-26 11:27:43 -070099 flowObj.setFlowPathType(flowPath.flowPathType().toString());
Pavlin Radoslavov7d4a40e2013-10-27 23:39:40 -0700100 flowObj.setFlowPathUserState(flowPath.flowPathUserState().toString());
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700101 flowObj.setFlowPathFlags(flowPath.flowPathFlags().flags());
102 flowObj.setSrcSwitch(flowPath.dataPath().srcPort().dpid().toString());
103 flowObj.setSrcPort(flowPath.dataPath().srcPort().port().value());
104 flowObj.setDstSwitch(flowPath.dataPath().dstPort().dpid().toString());
105 flowObj.setDstPort(flowPath.dataPath().dstPort().port().value());
106 if (flowPath.flowEntryMatch().matchSrcMac()) {
107 flowObj.setMatchSrcMac(flowPath.flowEntryMatch().srcMac().toString());
108 }
109 if (flowPath.flowEntryMatch().matchDstMac()) {
110 flowObj.setMatchDstMac(flowPath.flowEntryMatch().dstMac().toString());
111 }
112 if (flowPath.flowEntryMatch().matchEthernetFrameType()) {
113 flowObj.setMatchEthernetFrameType(flowPath.flowEntryMatch().ethernetFrameType());
114 }
115 if (flowPath.flowEntryMatch().matchVlanId()) {
116 flowObj.setMatchVlanId(flowPath.flowEntryMatch().vlanId());
117 }
118 if (flowPath.flowEntryMatch().matchVlanPriority()) {
119 flowObj.setMatchVlanPriority(flowPath.flowEntryMatch().vlanPriority());
120 }
121 if (flowPath.flowEntryMatch().matchSrcIPv4Net()) {
122 flowObj.setMatchSrcIPv4Net(flowPath.flowEntryMatch().srcIPv4Net().toString());
123 }
124 if (flowPath.flowEntryMatch().matchDstIPv4Net()) {
125 flowObj.setMatchDstIPv4Net(flowPath.flowEntryMatch().dstIPv4Net().toString());
126 }
127 if (flowPath.flowEntryMatch().matchIpProto()) {
128 flowObj.setMatchIpProto(flowPath.flowEntryMatch().ipProto());
129 }
130 if (flowPath.flowEntryMatch().matchIpToS()) {
131 flowObj.setMatchIpToS(flowPath.flowEntryMatch().ipToS());
132 }
133 if (flowPath.flowEntryMatch().matchSrcTcpUdpPort()) {
134 flowObj.setMatchSrcTcpUdpPort(flowPath.flowEntryMatch().srcTcpUdpPort());
135 }
136 if (flowPath.flowEntryMatch().matchDstTcpUdpPort()) {
137 flowObj.setMatchDstTcpUdpPort(flowPath.flowEntryMatch().dstTcpUdpPort());
138 }
139 if (! flowPath.flowEntryActions().actions().isEmpty()) {
140 flowObj.setActions(flowPath.flowEntryActions().toString());
141 }
Pavlin Radoslavovbcc86ef2013-10-26 12:06:25 -0700142 flowObj.setDataPathSummary(flowPath.dataPath().dataPathSummary());
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700143
144 if (found)
Pavlin Radoslavov7d4a40e2013-10-27 23:39:40 -0700145 flowObj.setFlowPathUserState("FP_USER_MODIFY");
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700146 else
Pavlin Radoslavov7d4a40e2013-10-27 23:39:40 -0700147 flowObj.setFlowPathUserState("FP_USER_ADD");
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700148
149 // Flow edges:
150 // HeadFE
151
152
153 //
154 // Flow Entries:
155 // flowPath.dataPath().flowEntries()
156 //
157 for (FlowEntry flowEntry : flowPath.dataPath().flowEntries()) {
158 if (addFlowEntry(flowManager, dbHandler, flowObj, flowEntry) == null) {
159 dbHandler.rollback();
160 return false;
161 }
162 }
163 dbHandler.commit();
164
165 //
166 // TODO: We need a proper Flow ID allocation mechanism.
167 //
168 flowId.setValue(flowPath.flowId().value());
169
170 return true;
171 }
172
173 /**
174 * Add a flow entry to the Network MAP.
175 *
176 * @param flowManager the Flow Manager to use.
177 * @param dbHandler the Graph Database handler to use.
178 * @param flowObj the corresponding Flow Path object for the Flow Entry.
179 * @param flowEntry the Flow Entry to install.
180 * @return the added Flow Entry object on success, otherwise null.
181 */
182 static IFlowEntry addFlowEntry(FlowManager flowManager,
183 GraphDBOperation dbHandler,
184 IFlowPath flowObj,
185 FlowEntry flowEntry) {
186 // Flow edges
187 // HeadFE (TODO)
188
189 //
190 // Assign the FlowEntry ID.
191 //
Pavlin Radoslavov9243f702013-11-25 18:10:10 -0800192 if (! flowEntry.isValidFlowEntryId()) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700193 long id = flowManager.getNextFlowEntryId();
194 flowEntry.setFlowEntryId(new FlowEntryId(id));
195 }
196
197 IFlowEntry flowEntryObj = null;
198 boolean found = false;
199 try {
200 if ((flowEntryObj =
201 dbHandler.searchFlowEntry(flowEntry.flowEntryId())) != null) {
202 found = true;
203 } else {
204 flowEntryObj = dbHandler.newFlowEntry();
205 }
206 } catch (Exception e) {
207 log.error(":addFlow FlowEntryId:{} failed",
208 flowEntry.flowEntryId().toString());
209 return null;
210 }
211 if (flowEntryObj == null) {
212 log.error(":addFlow FlowEntryId:{} failed: FlowEntry object not created",
213 flowEntry.flowEntryId().toString());
214 return null;
215 }
216
217 //
218 // Set the Flow Entry key:
219 // - flowEntry.flowEntryId()
220 //
221 flowEntryObj.setFlowEntryId(flowEntry.flowEntryId().toString());
222 flowEntryObj.setType("flow_entry");
223
224 //
225 // Set the Flow Entry Edges and attributes:
226 // - Switch edge
227 // - InPort edge
228 // - OutPort edge
229 //
230 // - flowEntry.dpid()
231 // - flowEntry.flowEntryUserState()
232 // - flowEntry.flowEntrySwitchState()
233 // - flowEntry.flowEntryErrorState()
234 // - flowEntry.matchInPort()
235 // - flowEntry.matchSrcMac()
236 // - flowEntry.matchDstMac()
237 // - flowEntry.matchEthernetFrameType()
238 // - flowEntry.matchVlanId()
239 // - flowEntry.matchVlanPriority()
240 // - flowEntry.matchSrcIPv4Net()
241 // - flowEntry.matchDstIPv4Net()
242 // - flowEntry.matchIpProto()
243 // - flowEntry.matchIpToS()
244 // - flowEntry.matchSrcTcpUdpPort()
245 // - flowEntry.matchDstTcpUdpPort()
246 // - flowEntry.actionOutputPort()
247 // - flowEntry.actions()
248 //
249 ISwitchObject sw = dbHandler.searchSwitch(flowEntry.dpid().toString());
250 flowEntryObj.setSwitchDpid(flowEntry.dpid().toString());
251 flowEntryObj.setSwitch(sw);
252 if (flowEntry.flowEntryMatch().matchInPort()) {
253 IPortObject inport =
254 dbHandler.searchPort(flowEntry.dpid().toString(),
255 flowEntry.flowEntryMatch().inPort().value());
256 flowEntryObj.setMatchInPort(flowEntry.flowEntryMatch().inPort().value());
257 flowEntryObj.setInPort(inport);
258 }
259 if (flowEntry.flowEntryMatch().matchSrcMac()) {
260 flowEntryObj.setMatchSrcMac(flowEntry.flowEntryMatch().srcMac().toString());
261 }
262 if (flowEntry.flowEntryMatch().matchDstMac()) {
263 flowEntryObj.setMatchDstMac(flowEntry.flowEntryMatch().dstMac().toString());
264 }
265 if (flowEntry.flowEntryMatch().matchEthernetFrameType()) {
266 flowEntryObj.setMatchEthernetFrameType(flowEntry.flowEntryMatch().ethernetFrameType());
267 }
268 if (flowEntry.flowEntryMatch().matchVlanId()) {
269 flowEntryObj.setMatchVlanId(flowEntry.flowEntryMatch().vlanId());
270 }
271 if (flowEntry.flowEntryMatch().matchVlanPriority()) {
272 flowEntryObj.setMatchVlanPriority(flowEntry.flowEntryMatch().vlanPriority());
273 }
274 if (flowEntry.flowEntryMatch().matchSrcIPv4Net()) {
275 flowEntryObj.setMatchSrcIPv4Net(flowEntry.flowEntryMatch().srcIPv4Net().toString());
276 }
277 if (flowEntry.flowEntryMatch().matchDstIPv4Net()) {
278 flowEntryObj.setMatchDstIPv4Net(flowEntry.flowEntryMatch().dstIPv4Net().toString());
279 }
280 if (flowEntry.flowEntryMatch().matchIpProto()) {
281 flowEntryObj.setMatchIpProto(flowEntry.flowEntryMatch().ipProto());
282 }
283 if (flowEntry.flowEntryMatch().matchIpToS()) {
284 flowEntryObj.setMatchIpToS(flowEntry.flowEntryMatch().ipToS());
285 }
286 if (flowEntry.flowEntryMatch().matchSrcTcpUdpPort()) {
287 flowEntryObj.setMatchSrcTcpUdpPort(flowEntry.flowEntryMatch().srcTcpUdpPort());
288 }
289 if (flowEntry.flowEntryMatch().matchDstTcpUdpPort()) {
290 flowEntryObj.setMatchDstTcpUdpPort(flowEntry.flowEntryMatch().dstTcpUdpPort());
291 }
292
293 for (FlowEntryAction fa : flowEntry.flowEntryActions().actions()) {
294 if (fa.actionOutput() != null) {
295 IPortObject outport =
296 dbHandler.searchPort(flowEntry.dpid().toString(),
297 fa.actionOutput().port().value());
298 flowEntryObj.setActionOutputPort(fa.actionOutput().port().value());
299 flowEntryObj.setOutPort(outport);
300 }
301 }
302 if (! flowEntry.flowEntryActions().isEmpty()) {
303 flowEntryObj.setActions(flowEntry.flowEntryActions().toString());
304 }
305
306 // TODO: Hacks with hard-coded state names!
307 if (found)
308 flowEntryObj.setUserState("FE_USER_MODIFY");
309 else
310 flowEntryObj.setUserState("FE_USER_ADD");
Pavlin Radoslavovebc8b192013-10-29 15:35:35 -0700311 flowEntryObj.setSwitchState(flowEntry.flowEntrySwitchState().toString());
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700312 //
313 // TODO: Take care of the FlowEntryErrorState.
314 //
315
316 // Flow Entries edges:
317 // Flow
318 // NextFE (TODO)
319 if (! found) {
320 flowObj.addFlowEntry(flowEntryObj);
321 flowEntryObj.setFlow(flowObj);
322 }
323
324 return flowEntryObj;
325 }
326
327 /**
Pavlin Radoslavov7407ab52013-11-01 22:19:00 -0700328 * Delete a flow entry from the Network MAP.
329 *
330 * @param dbHandler the Graph Database handler to use.
331 * @param flowObj the corresponding Flow Path object for the Flow Entry.
332 * @param flowEntry the Flow Entry to delete.
333 * @return true on success, otherwise false.
334 */
335 static boolean deleteFlowEntry(GraphDBOperation dbHandler,
336 IFlowPath flowObj,
337 FlowEntry flowEntry) {
338 IFlowEntry flowEntryObj = null;
339 try {
340 flowEntryObj = dbHandler.searchFlowEntry(flowEntry.flowEntryId());
341 } catch (Exception e) {
342 log.error(":deleteFlowEntry FlowEntryId:{} failed",
343 flowEntry.flowEntryId().toString());
344 return false;
345 }
346 //
347 // TODO: Don't print an error for now, because multiple controller
348 // instances might be deleting the same flow entry.
349 //
350 /*
351 if (flowEntryObj == null) {
352 log.error(":deleteFlowEntry FlowEntryId:{} failed: FlowEntry object not found",
353 flowEntry.flowEntryId().toString());
354 return false;
355 }
356 */
357 if (flowEntryObj == null)
358 return true;
359
360 flowObj.removeFlowEntry(flowEntryObj);
361 dbHandler.removeFlowEntry(flowEntryObj);
362 return true;
363 }
364
365 /**
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700366 * Delete all previously added flows.
367 *
368 * @param dbHandler the Graph Database handler to use.
369 * @return true on success, otherwise false.
370 */
371 static boolean deleteAllFlows(GraphDBOperation dbHandler) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700372 List<FlowId> allFlowIds = new LinkedList<FlowId>();
373
374 // Get all Flow IDs
375 Iterable<IFlowPath> allFlowPaths = dbHandler.getAllFlowPaths();
376 for (IFlowPath flowPathObj : allFlowPaths) {
377 if (flowPathObj == null)
378 continue;
379 String flowIdStr = flowPathObj.getFlowId();
380 if (flowIdStr == null)
381 continue;
382 FlowId flowId = new FlowId(flowIdStr);
383 allFlowIds.add(flowId);
384 }
385
Pavlin Radoslavovf2a52652013-11-22 12:35:42 -0800386 // Delete all flows one-by-one
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700387 for (FlowId flowId : allFlowIds) {
Pavlin Radoslavovf2a52652013-11-22 12:35:42 -0800388 deleteFlow(dbHandler, flowId);
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700389 }
390
391 return true;
392 }
393
394 /**
Pavlin Radoslavovf2a52652013-11-22 12:35:42 -0800395 * Delete a previously added flow.
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700396 *
397 * @param dbHandler the Graph Database handler to use.
Pavlin Radoslavovf2a52652013-11-22 12:35:42 -0800398 * @param flowId the Flow ID of the flow to delete.
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700399 * @return true on success, otherwise false.
400 */
Pavlin Radoslavovf2a52652013-11-22 12:35:42 -0800401 static boolean deleteFlow(GraphDBOperation dbHandler, FlowId flowId) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700402 IFlowPath flowObj = null;
403 try {
404 flowObj = dbHandler.searchFlowPath(flowId);
405 } catch (Exception e) {
406 // TODO: handle exceptions
407 dbHandler.rollback();
Pavlin Radoslavovf2a52652013-11-22 12:35:42 -0800408 log.error(":deleteFlow FlowId:{} failed", flowId.toString());
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700409 return false;
410 }
411 if (flowObj == null) {
412 dbHandler.commit();
413 return true; // OK: No such flow
414 }
415
416 //
417 // Remove all Flow Entries
418 //
419 Iterable<IFlowEntry> flowEntries = flowObj.getFlowEntries();
420 for (IFlowEntry flowEntryObj : flowEntries) {
421 flowObj.removeFlowEntry(flowEntryObj);
422 dbHandler.removeFlowEntry(flowEntryObj);
423 }
424 // Remove the Flow itself
425 dbHandler.removeFlowPath(flowObj);
426 dbHandler.commit();
427
428 return true;
429 }
430
431 /**
432 * Get a previously added flow.
433 *
434 * @param dbHandler the Graph Database handler to use.
435 * @param flowId the Flow ID of the flow to get.
436 * @return the Flow Path if found, otherwise null.
437 */
438 static FlowPath getFlow(GraphDBOperation dbHandler, FlowId flowId) {
439 IFlowPath flowObj = null;
440 try {
441 flowObj = dbHandler.searchFlowPath(flowId);
442 } catch (Exception e) {
443 // TODO: handle exceptions
444 dbHandler.rollback();
445 log.error(":getFlow FlowId:{} failed", flowId.toString());
446 return null;
447 }
448 if (flowObj == null) {
449 dbHandler.commit();
450 return null; // Flow not found
451 }
452
453 //
454 // Extract the Flow state
455 //
456 FlowPath flowPath = extractFlowPath(flowObj);
457 dbHandler.commit();
458
459 return flowPath;
460 }
461
462 /**
463 * Get all installed flows by all installers.
464 *
465 * @param dbHandler the Graph Database handler to use.
466 * @return the Flow Paths if found, otherwise null.
467 */
468 static ArrayList<FlowPath> getAllFlows(GraphDBOperation dbHandler) {
469 Iterable<IFlowPath> flowPathsObj = null;
470 ArrayList<FlowPath> flowPaths = new ArrayList<FlowPath>();
471
472 try {
473 flowPathsObj = dbHandler.getAllFlowPaths();
474 } catch (Exception e) {
475 // TODO: handle exceptions
476 dbHandler.rollback();
477 log.error(":getAllFlowPaths failed");
478 return flowPaths;
479 }
480 if ((flowPathsObj == null) || (flowPathsObj.iterator().hasNext() == false)) {
481 dbHandler.commit();
482 return flowPaths; // No Flows found
483 }
484
485 for (IFlowPath flowObj : flowPathsObj) {
486 //
487 // Extract the Flow state
488 //
489 FlowPath flowPath = extractFlowPath(flowObj);
490 if (flowPath != null)
491 flowPaths.add(flowPath);
492 }
493
494 dbHandler.commit();
495
496 return flowPaths;
497 }
498
499 /**
500 * Get all previously added flows by a specific installer for a given
501 * data path endpoints.
502 *
503 * @param dbHandler the Graph Database handler to use.
504 * @param installerId the Caller ID of the installer of the flow to get.
505 * @param dataPathEndpoints the data path endpoints of the flow to get.
506 * @return the Flow Paths if found, otherwise null.
507 */
508 static ArrayList<FlowPath> getAllFlows(GraphDBOperation dbHandler,
509 CallerId installerId,
510 DataPathEndpoints dataPathEndpoints) {
511 //
512 // TODO: The implementation below is not optimal:
513 // We fetch all flows, and then return only the subset that match
514 // the query conditions.
515 // We should use the appropriate Titan/Gremlin query to filter-out
516 // the flows as appropriate.
517 //
518 ArrayList<FlowPath> allFlows = getAllFlows(dbHandler);
519 ArrayList<FlowPath> flowPaths = new ArrayList<FlowPath>();
520
521 if (allFlows == null)
522 return flowPaths;
523
524 for (FlowPath flow : allFlows) {
525 //
526 // TODO: String-based comparison is sub-optimal.
527 // We are using it for now to save us the extra work of
528 // implementing the "equals()" and "hashCode()" methods.
529 //
530 if (! flow.installerId().toString().equals(installerId.toString()))
531 continue;
532 if (! flow.dataPath().srcPort().toString().equals(dataPathEndpoints.srcPort().toString())) {
533 continue;
534 }
535 if (! flow.dataPath().dstPort().toString().equals(dataPathEndpoints.dstPort().toString())) {
536 continue;
537 }
538 flowPaths.add(flow);
539 }
540
541 return flowPaths;
542 }
543
544 /**
545 * Get all installed flows by all installers for given data path endpoints.
546 *
547 * @param dbHandler the Graph Database handler to use.
548 * @param dataPathEndpoints the data path endpoints of the flows to get.
549 * @return the Flow Paths if found, otherwise null.
550 */
551 static ArrayList<FlowPath> getAllFlows(GraphDBOperation dbHandler,
552 DataPathEndpoints dataPathEndpoints) {
553 //
554 // TODO: The implementation below is not optimal:
555 // We fetch all flows, and then return only the subset that match
556 // the query conditions.
557 // We should use the appropriate Titan/Gremlin query to filter-out
558 // the flows as appropriate.
559 //
560 ArrayList<FlowPath> flowPaths = new ArrayList<FlowPath>();
561 ArrayList<FlowPath> allFlows = getAllFlows(dbHandler);
562
563 if (allFlows == null)
564 return flowPaths;
565
566 for (FlowPath flow : allFlows) {
567 //
568 // TODO: String-based comparison is sub-optimal.
569 // We are using it for now to save us the extra work of
570 // implementing the "equals()" and "hashCode()" methods.
571 //
572 if (! flow.dataPath().srcPort().toString().equals(dataPathEndpoints.srcPort().toString())) {
573 continue;
574 }
575 if (! flow.dataPath().dstPort().toString().equals(dataPathEndpoints.dstPort().toString())) {
576 continue;
577 }
578 flowPaths.add(flow);
579 }
580
581 return flowPaths;
582 }
583
584 /**
585 * Get summary of all installed flows by all installers in a given range.
586 *
587 * @param dbHandler the Graph Database handler to use.
588 * @param flowId the Flow ID of the first flow in the flow range to get.
589 * @param maxFlows the maximum number of flows to be returned.
590 * @return the Flow Paths if found, otherwise null.
591 */
Pavlin Radoslavov4ef6ba22013-11-22 19:32:58 -0800592 static ArrayList<FlowPath> getAllFlowsSummary(GraphDBOperation dbHandler,
593 FlowId flowId,
594 int maxFlows) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700595 //
596 // TODO: The implementation below is not optimal:
597 // We fetch all flows, and then return only the subset that match
598 // the query conditions.
599 // We should use the appropriate Titan/Gremlin query to filter-out
600 // the flows as appropriate.
601 //
Pavlin Radoslavov4ef6ba22013-11-22 19:32:58 -0800602 ArrayList<FlowPath> flowPaths = getAllFlowsWithDataPathSummary(dbHandler);
603 Collections.sort(flowPaths);
604 return flowPaths;
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700605 }
606
607 /**
Pavlin Radoslavov4ef6ba22013-11-22 19:32:58 -0800608 * Get all Flows information, with Data Path summary for the Flow Entries.
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700609 *
610 * @param dbHandler the Graph Database handler to use.
Pavlin Radoslavov4ef6ba22013-11-22 19:32:58 -0800611 * @return all Flows information, with Data Path summary for the Flow
612 * Entries.
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700613 */
Pavlin Radoslavov4ef6ba22013-11-22 19:32:58 -0800614 static ArrayList<FlowPath> getAllFlowsWithDataPathSummary(GraphDBOperation dbHandler) {
615 ArrayList<FlowPath> flowPaths = getAllFlows(dbHandler);
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700616
Pavlin Radoslavov4ef6ba22013-11-22 19:32:58 -0800617 // Truncate each Flow Path and Flow Entry
618 for (FlowPath flowPath : flowPaths) {
619 flowPath.setFlowEntryMatch(null);
620 flowPath.setFlowEntryActions(null);
621 for (FlowEntry flowEntry : flowPath.flowEntries()) {
622 flowEntry.setFlowEntryMatch(null);
623 flowEntry.setFlowEntryActions(null);
624 }
625 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700626
Pavlin Radoslavov4ef6ba22013-11-22 19:32:58 -0800627 return flowPaths;
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700628 }
629
630 /**
631 * Extract Flow Path State from a Titan Database Object @ref IFlowPath.
632 *
633 * @param flowObj the object to extract the Flow Path State from.
634 * @return the extracted Flow Path State.
635 */
636 private static FlowPath extractFlowPath(IFlowPath flowObj) {
637 //
638 // Extract the Flow state
639 //
640 String flowIdStr = flowObj.getFlowId();
641 String installerIdStr = flowObj.getInstallerId();
Pavlin Radoslavovd28cf7c2013-10-26 11:27:43 -0700642 String flowPathType = flowObj.getFlowPathType();
Pavlin Radoslavov7d4a40e2013-10-27 23:39:40 -0700643 String flowPathUserState = flowObj.getFlowPathUserState();
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700644 Long flowPathFlags = flowObj.getFlowPathFlags();
645 String srcSwitchStr = flowObj.getSrcSwitch();
646 Short srcPortShort = flowObj.getSrcPort();
647 String dstSwitchStr = flowObj.getDstSwitch();
648 Short dstPortShort = flowObj.getDstPort();
649
650 if ((flowIdStr == null) ||
651 (installerIdStr == null) ||
Pavlin Radoslavovd28cf7c2013-10-26 11:27:43 -0700652 (flowPathType == null) ||
Pavlin Radoslavov7d4a40e2013-10-27 23:39:40 -0700653 (flowPathUserState == null) ||
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700654 (flowPathFlags == null) ||
655 (srcSwitchStr == null) ||
656 (srcPortShort == null) ||
657 (dstSwitchStr == null) ||
658 (dstPortShort == null)) {
659 // TODO: A work-around, becauuse of some bogus database objects
660 return null;
661 }
662
663 FlowPath flowPath = new FlowPath();
664 flowPath.setFlowId(new FlowId(flowIdStr));
665 flowPath.setInstallerId(new CallerId(installerIdStr));
Pavlin Radoslavovd28cf7c2013-10-26 11:27:43 -0700666 flowPath.setFlowPathType(FlowPathType.valueOf(flowPathType));
Pavlin Radoslavov7d4a40e2013-10-27 23:39:40 -0700667 flowPath.setFlowPathUserState(FlowPathUserState.valueOf(flowPathUserState));
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700668 flowPath.setFlowPathFlags(new FlowPathFlags(flowPathFlags));
669 flowPath.dataPath().srcPort().setDpid(new Dpid(srcSwitchStr));
670 flowPath.dataPath().srcPort().setPort(new Port(srcPortShort));
671 flowPath.dataPath().dstPort().setDpid(new Dpid(dstSwitchStr));
672 flowPath.dataPath().dstPort().setPort(new Port(dstPortShort));
673 //
674 // Extract the match conditions common for all Flow Entries
675 //
676 {
677 FlowEntryMatch match = new FlowEntryMatch();
678 String matchSrcMac = flowObj.getMatchSrcMac();
679 if (matchSrcMac != null)
680 match.enableSrcMac(MACAddress.valueOf(matchSrcMac));
681 String matchDstMac = flowObj.getMatchDstMac();
682 if (matchDstMac != null)
683 match.enableDstMac(MACAddress.valueOf(matchDstMac));
684 Short matchEthernetFrameType = flowObj.getMatchEthernetFrameType();
685 if (matchEthernetFrameType != null)
686 match.enableEthernetFrameType(matchEthernetFrameType);
687 Short matchVlanId = flowObj.getMatchVlanId();
688 if (matchVlanId != null)
689 match.enableVlanId(matchVlanId);
690 Byte matchVlanPriority = flowObj.getMatchVlanPriority();
691 if (matchVlanPriority != null)
692 match.enableVlanPriority(matchVlanPriority);
693 String matchSrcIPv4Net = flowObj.getMatchSrcIPv4Net();
694 if (matchSrcIPv4Net != null)
695 match.enableSrcIPv4Net(new IPv4Net(matchSrcIPv4Net));
696 String matchDstIPv4Net = flowObj.getMatchDstIPv4Net();
697 if (matchDstIPv4Net != null)
698 match.enableDstIPv4Net(new IPv4Net(matchDstIPv4Net));
699 Byte matchIpProto = flowObj.getMatchIpProto();
700 if (matchIpProto != null)
701 match.enableIpProto(matchIpProto);
702 Byte matchIpToS = flowObj.getMatchIpToS();
703 if (matchIpToS != null)
704 match.enableIpToS(matchIpToS);
705 Short matchSrcTcpUdpPort = flowObj.getMatchSrcTcpUdpPort();
706 if (matchSrcTcpUdpPort != null)
707 match.enableSrcTcpUdpPort(matchSrcTcpUdpPort);
708 Short matchDstTcpUdpPort = flowObj.getMatchDstTcpUdpPort();
709 if (matchDstTcpUdpPort != null)
710 match.enableDstTcpUdpPort(matchDstTcpUdpPort);
711
712 flowPath.setFlowEntryMatch(match);
713 }
714 //
715 // Extract the actions for the first Flow Entry
716 //
717 {
718 String actionsStr = flowObj.getActions();
719 if (actionsStr != null) {
720 FlowEntryActions flowEntryActions = new FlowEntryActions(actionsStr);
721 flowPath.setFlowEntryActions(flowEntryActions);
722 }
723 }
724
725 //
726 // Extract all Flow Entries
727 //
728 Iterable<IFlowEntry> flowEntries = flowObj.getFlowEntries();
729 for (IFlowEntry flowEntryObj : flowEntries) {
730 FlowEntry flowEntry = extractFlowEntry(flowEntryObj);
731 if (flowEntry == null)
732 continue;
733 flowPath.dataPath().flowEntries().add(flowEntry);
734 }
735
736 return flowPath;
737 }
738
739 /**
740 * Extract Flow Entry State from a Titan Database Object @ref IFlowEntry.
741 *
742 * @param flowEntryObj the object to extract the Flow Entry State from.
743 * @return the extracted Flow Entry State.
744 */
Brian O'Connora8e49802013-10-30 20:49:59 -0700745 public static FlowEntry extractFlowEntry(IFlowEntry flowEntryObj) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700746 String flowEntryIdStr = flowEntryObj.getFlowEntryId();
747 String switchDpidStr = flowEntryObj.getSwitchDpid();
748 String userState = flowEntryObj.getUserState();
749 String switchState = flowEntryObj.getSwitchState();
750
751 if ((flowEntryIdStr == null) ||
752 (switchDpidStr == null) ||
753 (userState == null) ||
754 (switchState == null)) {
Brian O'Connora8e49802013-10-30 20:49:59 -0700755 // TODO: A work-around, because of some bogus database objects
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700756 return null;
757 }
758
759 FlowEntry flowEntry = new FlowEntry();
760 flowEntry.setFlowEntryId(new FlowEntryId(flowEntryIdStr));
761 flowEntry.setDpid(new Dpid(switchDpidStr));
762
763 //
764 // Extract the match conditions
765 //
766 FlowEntryMatch match = new FlowEntryMatch();
767 Short matchInPort = flowEntryObj.getMatchInPort();
768 if (matchInPort != null)
769 match.enableInPort(new Port(matchInPort));
770 String matchSrcMac = flowEntryObj.getMatchSrcMac();
771 if (matchSrcMac != null)
772 match.enableSrcMac(MACAddress.valueOf(matchSrcMac));
773 String matchDstMac = flowEntryObj.getMatchDstMac();
774 if (matchDstMac != null)
775 match.enableDstMac(MACAddress.valueOf(matchDstMac));
776 Short matchEthernetFrameType = flowEntryObj.getMatchEthernetFrameType();
777 if (matchEthernetFrameType != null)
778 match.enableEthernetFrameType(matchEthernetFrameType);
779 Short matchVlanId = flowEntryObj.getMatchVlanId();
780 if (matchVlanId != null)
781 match.enableVlanId(matchVlanId);
782 Byte matchVlanPriority = flowEntryObj.getMatchVlanPriority();
783 if (matchVlanPriority != null)
784 match.enableVlanPriority(matchVlanPriority);
785 String matchSrcIPv4Net = flowEntryObj.getMatchSrcIPv4Net();
786 if (matchSrcIPv4Net != null)
787 match.enableSrcIPv4Net(new IPv4Net(matchSrcIPv4Net));
788 String matchDstIPv4Net = flowEntryObj.getMatchDstIPv4Net();
789 if (matchDstIPv4Net != null)
790 match.enableDstIPv4Net(new IPv4Net(matchDstIPv4Net));
791 Byte matchIpProto = flowEntryObj.getMatchIpProto();
792 if (matchIpProto != null)
793 match.enableIpProto(matchIpProto);
794 Byte matchIpToS = flowEntryObj.getMatchIpToS();
795 if (matchIpToS != null)
796 match.enableIpToS(matchIpToS);
797 Short matchSrcTcpUdpPort = flowEntryObj.getMatchSrcTcpUdpPort();
798 if (matchSrcTcpUdpPort != null)
799 match.enableSrcTcpUdpPort(matchSrcTcpUdpPort);
800 Short matchDstTcpUdpPort = flowEntryObj.getMatchDstTcpUdpPort();
801 if (matchDstTcpUdpPort != null)
802 match.enableDstTcpUdpPort(matchDstTcpUdpPort);
803 flowEntry.setFlowEntryMatch(match);
804
805 //
806 // Extract the actions
807 //
808 FlowEntryActions actions = new FlowEntryActions();
809 String actionsStr = flowEntryObj.getActions();
810 if (actionsStr != null)
811 actions = new FlowEntryActions(actionsStr);
812 flowEntry.setFlowEntryActions(actions);
813 flowEntry.setFlowEntryUserState(FlowEntryUserState.valueOf(userState));
814 flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.valueOf(switchState));
815 //
816 // TODO: Take care of FlowEntryErrorState.
817 //
818 return flowEntry;
819 }
820}