blob: 4e67bf55b99f875b31e84d026fed964c0415a248 [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;
yoshitomob292c622013-11-23 14:35:58 -080013import net.onrc.onos.graph.DBOperation;
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070014
15import net.onrc.onos.graph.GraphDBOperation;
16
17import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowEntry;
18import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowPath;
19import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IPortObject;
20import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.ISwitchObject;
21import net.onrc.onos.ofcontroller.util.*;
22
23import org.slf4j.Logger;
24import org.slf4j.LoggerFactory;
25
26/**
27 * Class for performing Flow-related operations on the Database.
28 */
29class FlowDatabaseOperation {
Yuta HIGUCHI6ac8d182013-10-22 15:24:56 -070030 private final static Logger log = LoggerFactory.getLogger(FlowDatabaseOperation.class);
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070031
32 /**
33 * Add a flow.
34 *
35 * @param flowManager the Flow Manager to use.
36 * @param dbHandler the Graph Database handler to use.
37 * @param flowPath the Flow Path to install.
38 * @param flowId the return-by-reference Flow ID as assigned internally.
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070039 * @return true on success, otherwise false.
40 */
41 static boolean addFlow(FlowManager flowManager,
yoshitomob292c622013-11-23 14:35:58 -080042 DBOperation dbHandler,
Pavlin Radoslavovbcc86ef2013-10-26 12:06:25 -070043 FlowPath flowPath, FlowId flowId) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070044 IFlowPath flowObj = null;
45 boolean found = false;
46 try {
47 if ((flowObj = dbHandler.searchFlowPath(flowPath.flowId())) != null) {
48 found = true;
49 } else {
50 flowObj = dbHandler.newFlowPath();
51 }
52 } catch (Exception e) {
53 dbHandler.rollback();
54
55 StringWriter sw = new StringWriter();
56 e.printStackTrace(new PrintWriter(sw));
57 String stacktrace = sw.toString();
58
59 log.error(":addFlow FlowId:{} failed: {}",
60 flowPath.flowId().toString(),
61 stacktrace);
62 return false;
63 }
64 if (flowObj == null) {
65 log.error(":addFlow FlowId:{} failed: Flow object not created",
66 flowPath.flowId().toString());
67 dbHandler.rollback();
68 return false;
69 }
70
71 //
72 // Set the Flow key:
73 // - flowId
74 //
75 flowObj.setFlowId(flowPath.flowId().toString());
76 flowObj.setType("flow");
77
78 //
79 // Set the Flow attributes:
80 // - flowPath.installerId()
Pavlin Radoslavovd28cf7c2013-10-26 11:27:43 -070081 // - flowPath.flowPathType()
Pavlin Radoslavov7d4a40e2013-10-27 23:39:40 -070082 // - flowPath.flowPathUserState()
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070083 // - 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());
Pavlin Radoslavovd28cf7c2013-10-26 11:27:43 -0700100 flowObj.setFlowPathType(flowPath.flowPathType().toString());
Pavlin Radoslavov7d4a40e2013-10-27 23:39:40 -0700101 flowObj.setFlowPathUserState(flowPath.flowPathUserState().toString());
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700102 flowObj.setFlowPathFlags(flowPath.flowPathFlags().flags());
103 flowObj.setSrcSwitch(flowPath.dataPath().srcPort().dpid().toString());
104 flowObj.setSrcPort(flowPath.dataPath().srcPort().port().value());
105 flowObj.setDstSwitch(flowPath.dataPath().dstPort().dpid().toString());
106 flowObj.setDstPort(flowPath.dataPath().dstPort().port().value());
107 if (flowPath.flowEntryMatch().matchSrcMac()) {
108 flowObj.setMatchSrcMac(flowPath.flowEntryMatch().srcMac().toString());
109 }
110 if (flowPath.flowEntryMatch().matchDstMac()) {
111 flowObj.setMatchDstMac(flowPath.flowEntryMatch().dstMac().toString());
112 }
113 if (flowPath.flowEntryMatch().matchEthernetFrameType()) {
114 flowObj.setMatchEthernetFrameType(flowPath.flowEntryMatch().ethernetFrameType());
115 }
116 if (flowPath.flowEntryMatch().matchVlanId()) {
117 flowObj.setMatchVlanId(flowPath.flowEntryMatch().vlanId());
118 }
119 if (flowPath.flowEntryMatch().matchVlanPriority()) {
120 flowObj.setMatchVlanPriority(flowPath.flowEntryMatch().vlanPriority());
121 }
122 if (flowPath.flowEntryMatch().matchSrcIPv4Net()) {
123 flowObj.setMatchSrcIPv4Net(flowPath.flowEntryMatch().srcIPv4Net().toString());
124 }
125 if (flowPath.flowEntryMatch().matchDstIPv4Net()) {
126 flowObj.setMatchDstIPv4Net(flowPath.flowEntryMatch().dstIPv4Net().toString());
127 }
128 if (flowPath.flowEntryMatch().matchIpProto()) {
129 flowObj.setMatchIpProto(flowPath.flowEntryMatch().ipProto());
130 }
131 if (flowPath.flowEntryMatch().matchIpToS()) {
132 flowObj.setMatchIpToS(flowPath.flowEntryMatch().ipToS());
133 }
134 if (flowPath.flowEntryMatch().matchSrcTcpUdpPort()) {
135 flowObj.setMatchSrcTcpUdpPort(flowPath.flowEntryMatch().srcTcpUdpPort());
136 }
137 if (flowPath.flowEntryMatch().matchDstTcpUdpPort()) {
138 flowObj.setMatchDstTcpUdpPort(flowPath.flowEntryMatch().dstTcpUdpPort());
139 }
140 if (! flowPath.flowEntryActions().actions().isEmpty()) {
141 flowObj.setActions(flowPath.flowEntryActions().toString());
142 }
Pavlin Radoslavovbcc86ef2013-10-26 12:06:25 -0700143 flowObj.setDataPathSummary(flowPath.dataPath().dataPathSummary());
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700144
145 if (found)
Pavlin Radoslavov7d4a40e2013-10-27 23:39:40 -0700146 flowObj.setFlowPathUserState("FP_USER_MODIFY");
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700147 else
Pavlin Radoslavov7d4a40e2013-10-27 23:39:40 -0700148 flowObj.setFlowPathUserState("FP_USER_ADD");
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700149
150 // Flow edges:
151 // HeadFE
152
153
154 //
155 // Flow Entries:
156 // flowPath.dataPath().flowEntries()
157 //
158 for (FlowEntry flowEntry : flowPath.dataPath().flowEntries()) {
159 if (addFlowEntry(flowManager, dbHandler, flowObj, flowEntry) == null) {
160 dbHandler.rollback();
161 return false;
162 }
163 }
164 dbHandler.commit();
165
166 //
167 // TODO: We need a proper Flow ID allocation mechanism.
168 //
169 flowId.setValue(flowPath.flowId().value());
170
171 return true;
172 }
173
174 /**
175 * Add a flow entry to the Network MAP.
176 *
177 * @param flowManager the Flow Manager to use.
178 * @param dbHandler the Graph Database handler to use.
179 * @param flowObj the corresponding Flow Path object for the Flow Entry.
180 * @param flowEntry the Flow Entry to install.
181 * @return the added Flow Entry object on success, otherwise null.
182 */
183 static IFlowEntry addFlowEntry(FlowManager flowManager,
yoshitomob292c622013-11-23 14:35:58 -0800184 DBOperation dbHandler,
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700185 IFlowPath flowObj,
186 FlowEntry flowEntry) {
187 // Flow edges
188 // HeadFE (TODO)
189
190 //
191 // Assign the FlowEntry ID.
192 //
193 if ((flowEntry.flowEntryId() == null) ||
194 (flowEntry.flowEntryId().value() == 0)) {
195 long id = flowManager.getNextFlowEntryId();
196 flowEntry.setFlowEntryId(new FlowEntryId(id));
197 }
198
199 IFlowEntry flowEntryObj = null;
200 boolean found = false;
201 try {
202 if ((flowEntryObj =
203 dbHandler.searchFlowEntry(flowEntry.flowEntryId())) != null) {
204 found = true;
205 } else {
206 flowEntryObj = dbHandler.newFlowEntry();
207 }
208 } catch (Exception e) {
209 log.error(":addFlow FlowEntryId:{} failed",
210 flowEntry.flowEntryId().toString());
211 return null;
212 }
213 if (flowEntryObj == null) {
214 log.error(":addFlow FlowEntryId:{} failed: FlowEntry object not created",
215 flowEntry.flowEntryId().toString());
216 return null;
217 }
218
219 //
220 // Set the Flow Entry key:
221 // - flowEntry.flowEntryId()
222 //
223 flowEntryObj.setFlowEntryId(flowEntry.flowEntryId().toString());
224 flowEntryObj.setType("flow_entry");
225
226 //
227 // Set the Flow Entry Edges and attributes:
228 // - Switch edge
229 // - InPort edge
230 // - OutPort edge
231 //
232 // - flowEntry.dpid()
233 // - flowEntry.flowEntryUserState()
234 // - flowEntry.flowEntrySwitchState()
235 // - flowEntry.flowEntryErrorState()
236 // - flowEntry.matchInPort()
237 // - flowEntry.matchSrcMac()
238 // - flowEntry.matchDstMac()
239 // - flowEntry.matchEthernetFrameType()
240 // - flowEntry.matchVlanId()
241 // - flowEntry.matchVlanPriority()
242 // - flowEntry.matchSrcIPv4Net()
243 // - flowEntry.matchDstIPv4Net()
244 // - flowEntry.matchIpProto()
245 // - flowEntry.matchIpToS()
246 // - flowEntry.matchSrcTcpUdpPort()
247 // - flowEntry.matchDstTcpUdpPort()
248 // - flowEntry.actionOutputPort()
249 // - flowEntry.actions()
250 //
251 ISwitchObject sw = dbHandler.searchSwitch(flowEntry.dpid().toString());
252 flowEntryObj.setSwitchDpid(flowEntry.dpid().toString());
253 flowEntryObj.setSwitch(sw);
254 if (flowEntry.flowEntryMatch().matchInPort()) {
255 IPortObject inport =
256 dbHandler.searchPort(flowEntry.dpid().toString(),
257 flowEntry.flowEntryMatch().inPort().value());
258 flowEntryObj.setMatchInPort(flowEntry.flowEntryMatch().inPort().value());
259 flowEntryObj.setInPort(inport);
260 }
261 if (flowEntry.flowEntryMatch().matchSrcMac()) {
262 flowEntryObj.setMatchSrcMac(flowEntry.flowEntryMatch().srcMac().toString());
263 }
264 if (flowEntry.flowEntryMatch().matchDstMac()) {
265 flowEntryObj.setMatchDstMac(flowEntry.flowEntryMatch().dstMac().toString());
266 }
267 if (flowEntry.flowEntryMatch().matchEthernetFrameType()) {
268 flowEntryObj.setMatchEthernetFrameType(flowEntry.flowEntryMatch().ethernetFrameType());
269 }
270 if (flowEntry.flowEntryMatch().matchVlanId()) {
271 flowEntryObj.setMatchVlanId(flowEntry.flowEntryMatch().vlanId());
272 }
273 if (flowEntry.flowEntryMatch().matchVlanPriority()) {
274 flowEntryObj.setMatchVlanPriority(flowEntry.flowEntryMatch().vlanPriority());
275 }
276 if (flowEntry.flowEntryMatch().matchSrcIPv4Net()) {
277 flowEntryObj.setMatchSrcIPv4Net(flowEntry.flowEntryMatch().srcIPv4Net().toString());
278 }
279 if (flowEntry.flowEntryMatch().matchDstIPv4Net()) {
280 flowEntryObj.setMatchDstIPv4Net(flowEntry.flowEntryMatch().dstIPv4Net().toString());
281 }
282 if (flowEntry.flowEntryMatch().matchIpProto()) {
283 flowEntryObj.setMatchIpProto(flowEntry.flowEntryMatch().ipProto());
284 }
285 if (flowEntry.flowEntryMatch().matchIpToS()) {
286 flowEntryObj.setMatchIpToS(flowEntry.flowEntryMatch().ipToS());
287 }
288 if (flowEntry.flowEntryMatch().matchSrcTcpUdpPort()) {
289 flowEntryObj.setMatchSrcTcpUdpPort(flowEntry.flowEntryMatch().srcTcpUdpPort());
290 }
291 if (flowEntry.flowEntryMatch().matchDstTcpUdpPort()) {
292 flowEntryObj.setMatchDstTcpUdpPort(flowEntry.flowEntryMatch().dstTcpUdpPort());
293 }
294
295 for (FlowEntryAction fa : flowEntry.flowEntryActions().actions()) {
296 if (fa.actionOutput() != null) {
297 IPortObject outport =
298 dbHandler.searchPort(flowEntry.dpid().toString(),
299 fa.actionOutput().port().value());
300 flowEntryObj.setActionOutputPort(fa.actionOutput().port().value());
301 flowEntryObj.setOutPort(outport);
302 }
303 }
304 if (! flowEntry.flowEntryActions().isEmpty()) {
305 flowEntryObj.setActions(flowEntry.flowEntryActions().toString());
306 }
307
308 // TODO: Hacks with hard-coded state names!
309 if (found)
310 flowEntryObj.setUserState("FE_USER_MODIFY");
311 else
312 flowEntryObj.setUserState("FE_USER_ADD");
Pavlin Radoslavovebc8b192013-10-29 15:35:35 -0700313 flowEntryObj.setSwitchState(flowEntry.flowEntrySwitchState().toString());
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700314 //
315 // TODO: Take care of the FlowEntryErrorState.
316 //
317
318 // Flow Entries edges:
319 // Flow
320 // NextFE (TODO)
321 if (! found) {
322 flowObj.addFlowEntry(flowEntryObj);
323 flowEntryObj.setFlow(flowObj);
324 }
325
326 return flowEntryObj;
327 }
328
329 /**
Pavlin Radoslavov7407ab52013-11-01 22:19:00 -0700330 * Delete a flow entry from the Network MAP.
331 *
332 * @param dbHandler the Graph Database handler to use.
333 * @param flowObj the corresponding Flow Path object for the Flow Entry.
334 * @param flowEntry the Flow Entry to delete.
335 * @return true on success, otherwise false.
336 */
yoshitomob292c622013-11-23 14:35:58 -0800337 static boolean deleteFlowEntry(DBOperation dbHandler,
Pavlin Radoslavov7407ab52013-11-01 22:19:00 -0700338 IFlowPath flowObj,
339 FlowEntry flowEntry) {
340 IFlowEntry flowEntryObj = null;
341 try {
342 flowEntryObj = dbHandler.searchFlowEntry(flowEntry.flowEntryId());
343 } catch (Exception e) {
344 log.error(":deleteFlowEntry FlowEntryId:{} failed",
345 flowEntry.flowEntryId().toString());
346 return false;
347 }
348 //
349 // TODO: Don't print an error for now, because multiple controller
350 // instances might be deleting the same flow entry.
351 //
352 /*
353 if (flowEntryObj == null) {
354 log.error(":deleteFlowEntry FlowEntryId:{} failed: FlowEntry object not found",
355 flowEntry.flowEntryId().toString());
356 return false;
357 }
358 */
359 if (flowEntryObj == null)
360 return true;
361
362 flowObj.removeFlowEntry(flowEntryObj);
363 dbHandler.removeFlowEntry(flowEntryObj);
364 return true;
365 }
366
367 /**
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700368 * Delete all previously added flows.
369 *
370 * @param dbHandler the Graph Database handler to use.
371 * @return true on success, otherwise false.
372 */
yoshitomob292c622013-11-23 14:35:58 -0800373 static boolean deleteAllFlows(DBOperation dbHandler) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700374 List<FlowId> allFlowIds = new LinkedList<FlowId>();
375
376 // Get all Flow IDs
377 Iterable<IFlowPath> allFlowPaths = dbHandler.getAllFlowPaths();
378 for (IFlowPath flowPathObj : allFlowPaths) {
379 if (flowPathObj == null)
380 continue;
381 String flowIdStr = flowPathObj.getFlowId();
382 if (flowIdStr == null)
383 continue;
384 FlowId flowId = new FlowId(flowIdStr);
385 allFlowIds.add(flowId);
386 }
387
Pavlin Radoslavovf2a52652013-11-22 12:35:42 -0800388 // Delete all flows one-by-one
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700389 for (FlowId flowId : allFlowIds) {
Pavlin Radoslavovf2a52652013-11-22 12:35:42 -0800390 deleteFlow(dbHandler, flowId);
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700391 }
392
393 return true;
394 }
395
396 /**
Pavlin Radoslavovf2a52652013-11-22 12:35:42 -0800397 * Delete a previously added flow.
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700398 *
399 * @param dbHandler the Graph Database handler to use.
Pavlin Radoslavovf2a52652013-11-22 12:35:42 -0800400 * @param flowId the Flow ID of the flow to delete.
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700401 * @return true on success, otherwise false.
402 */
yoshitomob292c622013-11-23 14:35:58 -0800403 static boolean deleteFlow(DBOperation dbHandler, FlowId flowId) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700404 IFlowPath flowObj = null;
405 try {
406 flowObj = dbHandler.searchFlowPath(flowId);
407 } catch (Exception e) {
408 // TODO: handle exceptions
409 dbHandler.rollback();
Pavlin Radoslavovf2a52652013-11-22 12:35:42 -0800410 log.error(":deleteFlow FlowId:{} failed", flowId.toString());
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700411 return false;
412 }
413 if (flowObj == null) {
414 dbHandler.commit();
415 return true; // OK: No such flow
416 }
417
418 //
419 // Remove all Flow Entries
420 //
421 Iterable<IFlowEntry> flowEntries = flowObj.getFlowEntries();
422 for (IFlowEntry flowEntryObj : flowEntries) {
423 flowObj.removeFlowEntry(flowEntryObj);
424 dbHandler.removeFlowEntry(flowEntryObj);
425 }
426 // Remove the Flow itself
427 dbHandler.removeFlowPath(flowObj);
428 dbHandler.commit();
429
430 return true;
431 }
432
433 /**
434 * Get a previously added flow.
435 *
436 * @param dbHandler the Graph Database handler to use.
437 * @param flowId the Flow ID of the flow to get.
438 * @return the Flow Path if found, otherwise null.
439 */
yoshitomob292c622013-11-23 14:35:58 -0800440 static FlowPath getFlow(DBOperation dbHandler, FlowId flowId) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700441 IFlowPath flowObj = null;
442 try {
443 flowObj = dbHandler.searchFlowPath(flowId);
444 } catch (Exception e) {
445 // TODO: handle exceptions
446 dbHandler.rollback();
447 log.error(":getFlow FlowId:{} failed", flowId.toString());
448 return null;
449 }
450 if (flowObj == null) {
451 dbHandler.commit();
452 return null; // Flow not found
453 }
454
455 //
456 // Extract the Flow state
457 //
458 FlowPath flowPath = extractFlowPath(flowObj);
459 dbHandler.commit();
460
461 return flowPath;
462 }
463
464 /**
465 * Get all installed flows by all installers.
466 *
467 * @param dbHandler the Graph Database handler to use.
468 * @return the Flow Paths if found, otherwise null.
469 */
yoshitomob292c622013-11-23 14:35:58 -0800470 static ArrayList<FlowPath> getAllFlows(DBOperation dbHandler) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700471 Iterable<IFlowPath> flowPathsObj = null;
472 ArrayList<FlowPath> flowPaths = new ArrayList<FlowPath>();
473
474 try {
475 flowPathsObj = dbHandler.getAllFlowPaths();
476 } catch (Exception e) {
477 // TODO: handle exceptions
478 dbHandler.rollback();
479 log.error(":getAllFlowPaths failed");
480 return flowPaths;
481 }
482 if ((flowPathsObj == null) || (flowPathsObj.iterator().hasNext() == false)) {
483 dbHandler.commit();
484 return flowPaths; // No Flows found
485 }
486
487 for (IFlowPath flowObj : flowPathsObj) {
488 //
489 // Extract the Flow state
490 //
491 FlowPath flowPath = extractFlowPath(flowObj);
492 if (flowPath != null)
493 flowPaths.add(flowPath);
494 }
495
496 dbHandler.commit();
497
498 return flowPaths;
499 }
500
501 /**
502 * Get all previously added flows by a specific installer for a given
503 * data path endpoints.
504 *
505 * @param dbHandler the Graph Database handler to use.
506 * @param installerId the Caller ID of the installer of the flow to get.
507 * @param dataPathEndpoints the data path endpoints of the flow to get.
508 * @return the Flow Paths if found, otherwise null.
509 */
yoshitomob292c622013-11-23 14:35:58 -0800510 static ArrayList<FlowPath> getAllFlows(DBOperation dbHandler,
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700511 CallerId installerId,
512 DataPathEndpoints dataPathEndpoints) {
513 //
514 // TODO: The implementation below is not optimal:
515 // We fetch all flows, and then return only the subset that match
516 // the query conditions.
517 // We should use the appropriate Titan/Gremlin query to filter-out
518 // the flows as appropriate.
519 //
520 ArrayList<FlowPath> allFlows = getAllFlows(dbHandler);
521 ArrayList<FlowPath> flowPaths = new ArrayList<FlowPath>();
522
523 if (allFlows == null)
524 return flowPaths;
525
526 for (FlowPath flow : allFlows) {
527 //
528 // TODO: String-based comparison is sub-optimal.
529 // We are using it for now to save us the extra work of
530 // implementing the "equals()" and "hashCode()" methods.
531 //
532 if (! flow.installerId().toString().equals(installerId.toString()))
533 continue;
534 if (! flow.dataPath().srcPort().toString().equals(dataPathEndpoints.srcPort().toString())) {
535 continue;
536 }
537 if (! flow.dataPath().dstPort().toString().equals(dataPathEndpoints.dstPort().toString())) {
538 continue;
539 }
540 flowPaths.add(flow);
541 }
542
543 return flowPaths;
544 }
545
546 /**
547 * Get all installed flows by all installers for given data path endpoints.
548 *
549 * @param dbHandler the Graph Database handler to use.
550 * @param dataPathEndpoints the data path endpoints of the flows to get.
551 * @return the Flow Paths if found, otherwise null.
552 */
yoshitomob292c622013-11-23 14:35:58 -0800553 static ArrayList<FlowPath> getAllFlows(DBOperation dbHandler,
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700554 DataPathEndpoints dataPathEndpoints) {
555 //
556 // TODO: The implementation below is not optimal:
557 // We fetch all flows, and then return only the subset that match
558 // the query conditions.
559 // We should use the appropriate Titan/Gremlin query to filter-out
560 // the flows as appropriate.
561 //
562 ArrayList<FlowPath> flowPaths = new ArrayList<FlowPath>();
563 ArrayList<FlowPath> allFlows = getAllFlows(dbHandler);
564
565 if (allFlows == null)
566 return flowPaths;
567
568 for (FlowPath flow : allFlows) {
569 //
570 // TODO: String-based comparison is sub-optimal.
571 // We are using it for now to save us the extra work of
572 // implementing the "equals()" and "hashCode()" methods.
573 //
574 if (! flow.dataPath().srcPort().toString().equals(dataPathEndpoints.srcPort().toString())) {
575 continue;
576 }
577 if (! flow.dataPath().dstPort().toString().equals(dataPathEndpoints.dstPort().toString())) {
578 continue;
579 }
580 flowPaths.add(flow);
581 }
582
583 return flowPaths;
584 }
585
586 /**
587 * Get summary of all installed flows by all installers in a given range.
588 *
589 * @param dbHandler the Graph Database handler to use.
590 * @param flowId the Flow ID of the first flow in the flow range to get.
591 * @param maxFlows the maximum number of flows to be returned.
592 * @return the Flow Paths if found, otherwise null.
593 */
yoshitomob292c622013-11-23 14:35:58 -0800594 static ArrayList<IFlowPath> getAllFlowsSummary(DBOperation dbHandler,
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700595 FlowId flowId,
596 int maxFlows) {
597 //
598 // TODO: The implementation below is not optimal:
599 // We fetch all flows, and then return only the subset that match
600 // the query conditions.
601 // We should use the appropriate Titan/Gremlin query to filter-out
602 // the flows as appropriate.
603 //
604 ArrayList<IFlowPath> flowPathsWithoutFlowEntries =
605 getAllFlowsWithoutFlowEntries(dbHandler);
606
607 Collections.sort(flowPathsWithoutFlowEntries,
608 new Comparator<IFlowPath>() {
609 @Override
610 public int compare(IFlowPath first, IFlowPath second) {
611 long result =
612 new FlowId(first.getFlowId()).value()
613 - new FlowId(second.getFlowId()).value();
614 if (result > 0) {
615 return 1;
616 } else if (result < 0) {
617 return -1;
618 } else {
619 return 0;
620 }
621 }
622 }
623 );
624
625 return flowPathsWithoutFlowEntries;
626 }
627
628 /**
629 * Get all Flows information, without the associated Flow Entries.
630 *
631 * @param dbHandler the Graph Database handler to use.
632 * @return all Flows information, without the associated Flow Entries.
633 */
yoshitomob292c622013-11-23 14:35:58 -0800634 static ArrayList<IFlowPath> getAllFlowsWithoutFlowEntries(DBOperation dbHandler) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700635 Iterable<IFlowPath> flowPathsObj = null;
636 ArrayList<IFlowPath> flowPathsObjArray = new ArrayList<IFlowPath>();
637
638 // TODO: Remove this op.commit() flow, because it is not needed?
639 dbHandler.commit();
640
641 try {
642 flowPathsObj = dbHandler.getAllFlowPaths();
643 } catch (Exception e) {
644 // TODO: handle exceptions
645 dbHandler.rollback();
646 log.error(":getAllFlowPaths failed");
647 return flowPathsObjArray; // No Flows found
648 }
649 if ((flowPathsObj == null) || (flowPathsObj.iterator().hasNext() == false)) {
650 return flowPathsObjArray; // No Flows found
651 }
652
653 for (IFlowPath flowObj : flowPathsObj)
654 flowPathsObjArray.add(flowObj);
655
656 // conn.endTx(Transaction.COMMIT);
657
658 return flowPathsObjArray;
659 }
660
661 /**
662 * Extract Flow Path State from a Titan Database Object @ref IFlowPath.
663 *
664 * @param flowObj the object to extract the Flow Path State from.
665 * @return the extracted Flow Path State.
666 */
667 private static FlowPath extractFlowPath(IFlowPath flowObj) {
668 //
669 // Extract the Flow state
670 //
671 String flowIdStr = flowObj.getFlowId();
672 String installerIdStr = flowObj.getInstallerId();
Pavlin Radoslavovd28cf7c2013-10-26 11:27:43 -0700673 String flowPathType = flowObj.getFlowPathType();
Pavlin Radoslavov7d4a40e2013-10-27 23:39:40 -0700674 String flowPathUserState = flowObj.getFlowPathUserState();
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700675 Long flowPathFlags = flowObj.getFlowPathFlags();
676 String srcSwitchStr = flowObj.getSrcSwitch();
677 Short srcPortShort = flowObj.getSrcPort();
678 String dstSwitchStr = flowObj.getDstSwitch();
679 Short dstPortShort = flowObj.getDstPort();
680
681 if ((flowIdStr == null) ||
682 (installerIdStr == null) ||
Pavlin Radoslavovd28cf7c2013-10-26 11:27:43 -0700683 (flowPathType == null) ||
Pavlin Radoslavov7d4a40e2013-10-27 23:39:40 -0700684 (flowPathUserState == null) ||
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700685 (flowPathFlags == null) ||
686 (srcSwitchStr == null) ||
687 (srcPortShort == null) ||
688 (dstSwitchStr == null) ||
689 (dstPortShort == null)) {
690 // TODO: A work-around, becauuse of some bogus database objects
691 return null;
692 }
693
694 FlowPath flowPath = new FlowPath();
695 flowPath.setFlowId(new FlowId(flowIdStr));
696 flowPath.setInstallerId(new CallerId(installerIdStr));
Pavlin Radoslavovd28cf7c2013-10-26 11:27:43 -0700697 flowPath.setFlowPathType(FlowPathType.valueOf(flowPathType));
Pavlin Radoslavov7d4a40e2013-10-27 23:39:40 -0700698 flowPath.setFlowPathUserState(FlowPathUserState.valueOf(flowPathUserState));
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700699 flowPath.setFlowPathFlags(new FlowPathFlags(flowPathFlags));
700 flowPath.dataPath().srcPort().setDpid(new Dpid(srcSwitchStr));
701 flowPath.dataPath().srcPort().setPort(new Port(srcPortShort));
702 flowPath.dataPath().dstPort().setDpid(new Dpid(dstSwitchStr));
703 flowPath.dataPath().dstPort().setPort(new Port(dstPortShort));
704 //
705 // Extract the match conditions common for all Flow Entries
706 //
707 {
708 FlowEntryMatch match = new FlowEntryMatch();
709 String matchSrcMac = flowObj.getMatchSrcMac();
710 if (matchSrcMac != null)
711 match.enableSrcMac(MACAddress.valueOf(matchSrcMac));
712 String matchDstMac = flowObj.getMatchDstMac();
713 if (matchDstMac != null)
714 match.enableDstMac(MACAddress.valueOf(matchDstMac));
715 Short matchEthernetFrameType = flowObj.getMatchEthernetFrameType();
716 if (matchEthernetFrameType != null)
717 match.enableEthernetFrameType(matchEthernetFrameType);
718 Short matchVlanId = flowObj.getMatchVlanId();
719 if (matchVlanId != null)
720 match.enableVlanId(matchVlanId);
721 Byte matchVlanPriority = flowObj.getMatchVlanPriority();
722 if (matchVlanPriority != null)
723 match.enableVlanPriority(matchVlanPriority);
724 String matchSrcIPv4Net = flowObj.getMatchSrcIPv4Net();
725 if (matchSrcIPv4Net != null)
726 match.enableSrcIPv4Net(new IPv4Net(matchSrcIPv4Net));
727 String matchDstIPv4Net = flowObj.getMatchDstIPv4Net();
728 if (matchDstIPv4Net != null)
729 match.enableDstIPv4Net(new IPv4Net(matchDstIPv4Net));
730 Byte matchIpProto = flowObj.getMatchIpProto();
731 if (matchIpProto != null)
732 match.enableIpProto(matchIpProto);
733 Byte matchIpToS = flowObj.getMatchIpToS();
734 if (matchIpToS != null)
735 match.enableIpToS(matchIpToS);
736 Short matchSrcTcpUdpPort = flowObj.getMatchSrcTcpUdpPort();
737 if (matchSrcTcpUdpPort != null)
738 match.enableSrcTcpUdpPort(matchSrcTcpUdpPort);
739 Short matchDstTcpUdpPort = flowObj.getMatchDstTcpUdpPort();
740 if (matchDstTcpUdpPort != null)
741 match.enableDstTcpUdpPort(matchDstTcpUdpPort);
742
743 flowPath.setFlowEntryMatch(match);
744 }
745 //
746 // Extract the actions for the first Flow Entry
747 //
748 {
749 String actionsStr = flowObj.getActions();
750 if (actionsStr != null) {
751 FlowEntryActions flowEntryActions = new FlowEntryActions(actionsStr);
752 flowPath.setFlowEntryActions(flowEntryActions);
753 }
754 }
755
756 //
757 // Extract all Flow Entries
758 //
759 Iterable<IFlowEntry> flowEntries = flowObj.getFlowEntries();
760 for (IFlowEntry flowEntryObj : flowEntries) {
761 FlowEntry flowEntry = extractFlowEntry(flowEntryObj);
762 if (flowEntry == null)
763 continue;
764 flowPath.dataPath().flowEntries().add(flowEntry);
765 }
766
767 return flowPath;
768 }
769
770 /**
771 * Extract Flow Entry State from a Titan Database Object @ref IFlowEntry.
772 *
773 * @param flowEntryObj the object to extract the Flow Entry State from.
774 * @return the extracted Flow Entry State.
775 */
Brian O'Connora8e49802013-10-30 20:49:59 -0700776 public static FlowEntry extractFlowEntry(IFlowEntry flowEntryObj) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700777 String flowEntryIdStr = flowEntryObj.getFlowEntryId();
778 String switchDpidStr = flowEntryObj.getSwitchDpid();
779 String userState = flowEntryObj.getUserState();
780 String switchState = flowEntryObj.getSwitchState();
781
782 if ((flowEntryIdStr == null) ||
783 (switchDpidStr == null) ||
784 (userState == null) ||
785 (switchState == null)) {
Brian O'Connora8e49802013-10-30 20:49:59 -0700786 // TODO: A work-around, because of some bogus database objects
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700787 return null;
788 }
789
790 FlowEntry flowEntry = new FlowEntry();
791 flowEntry.setFlowEntryId(new FlowEntryId(flowEntryIdStr));
792 flowEntry.setDpid(new Dpid(switchDpidStr));
793
794 //
795 // Extract the match conditions
796 //
797 FlowEntryMatch match = new FlowEntryMatch();
798 Short matchInPort = flowEntryObj.getMatchInPort();
799 if (matchInPort != null)
800 match.enableInPort(new Port(matchInPort));
801 String matchSrcMac = flowEntryObj.getMatchSrcMac();
802 if (matchSrcMac != null)
803 match.enableSrcMac(MACAddress.valueOf(matchSrcMac));
804 String matchDstMac = flowEntryObj.getMatchDstMac();
805 if (matchDstMac != null)
806 match.enableDstMac(MACAddress.valueOf(matchDstMac));
807 Short matchEthernetFrameType = flowEntryObj.getMatchEthernetFrameType();
808 if (matchEthernetFrameType != null)
809 match.enableEthernetFrameType(matchEthernetFrameType);
810 Short matchVlanId = flowEntryObj.getMatchVlanId();
811 if (matchVlanId != null)
812 match.enableVlanId(matchVlanId);
813 Byte matchVlanPriority = flowEntryObj.getMatchVlanPriority();
814 if (matchVlanPriority != null)
815 match.enableVlanPriority(matchVlanPriority);
816 String matchSrcIPv4Net = flowEntryObj.getMatchSrcIPv4Net();
817 if (matchSrcIPv4Net != null)
818 match.enableSrcIPv4Net(new IPv4Net(matchSrcIPv4Net));
819 String matchDstIPv4Net = flowEntryObj.getMatchDstIPv4Net();
820 if (matchDstIPv4Net != null)
821 match.enableDstIPv4Net(new IPv4Net(matchDstIPv4Net));
822 Byte matchIpProto = flowEntryObj.getMatchIpProto();
823 if (matchIpProto != null)
824 match.enableIpProto(matchIpProto);
825 Byte matchIpToS = flowEntryObj.getMatchIpToS();
826 if (matchIpToS != null)
827 match.enableIpToS(matchIpToS);
828 Short matchSrcTcpUdpPort = flowEntryObj.getMatchSrcTcpUdpPort();
829 if (matchSrcTcpUdpPort != null)
830 match.enableSrcTcpUdpPort(matchSrcTcpUdpPort);
831 Short matchDstTcpUdpPort = flowEntryObj.getMatchDstTcpUdpPort();
832 if (matchDstTcpUdpPort != null)
833 match.enableDstTcpUdpPort(matchDstTcpUdpPort);
834 flowEntry.setFlowEntryMatch(match);
835
836 //
837 // Extract the actions
838 //
839 FlowEntryActions actions = new FlowEntryActions();
840 String actionsStr = flowEntryObj.getActions();
841 if (actionsStr != null)
842 actions = new FlowEntryActions(actionsStr);
843 flowEntry.setFlowEntryActions(actions);
844 flowEntry.setFlowEntryUserState(FlowEntryUserState.valueOf(userState));
845 flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.valueOf(switchState));
846 //
847 // TODO: Take care of FlowEntryErrorState.
848 //
849 return flowEntry;
850 }
851}