blob: 3d7cdc7688f17d4482644ca39c5271f4c8fb3d21 [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;
Pavlin Radoslavovf3f23bb2014-01-10 13:02:33 -08006import java.util.Collection;
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -07007import java.util.LinkedList;
8import java.util.List;
Pavlin Radoslavov16b761d2014-01-08 09:47:14 -08009import java.util.Map;
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070010
Pavlin Radoslavov16b761d2014-01-08 09:47:14 -080011import net.floodlightcontroller.core.IOFSwitch;
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070012import 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 {
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -080029 static private boolean enableOnrc2014MeasurementsFlows = true;
30
Yuta HIGUCHI6ac8d182013-10-22 15:24:56 -070031 private final static Logger log = LoggerFactory.getLogger(FlowDatabaseOperation.class);
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070032
33 /**
34 * Add a flow.
35 *
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070036 * @param dbHandler the Graph Database handler to use.
37 * @param flowPath the Flow Path to install.
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070038 * @return true on success, otherwise false.
39 */
Pavlin Radoslavov051abb42013-12-05 17:24:50 -080040 static boolean addFlow(GraphDBOperation dbHandler, FlowPath flowPath) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070041 IFlowPath flowObj = null;
42 boolean found = false;
43 try {
44 if ((flowObj = dbHandler.searchFlowPath(flowPath.flowId())) != null) {
45 found = true;
46 } else {
47 flowObj = dbHandler.newFlowPath();
48 }
49 } catch (Exception e) {
50 dbHandler.rollback();
51
52 StringWriter sw = new StringWriter();
53 e.printStackTrace(new PrintWriter(sw));
54 String stacktrace = sw.toString();
55
56 log.error(":addFlow FlowId:{} failed: {}",
Yuta HIGUCHI5302ddf2014-01-06 12:53:35 -080057 flowPath.flowId(),
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070058 stacktrace);
59 return false;
60 }
61 if (flowObj == null) {
62 log.error(":addFlow FlowId:{} failed: Flow object not created",
Yuta HIGUCHI5302ddf2014-01-06 12:53:35 -080063 flowPath.flowId());
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070064 dbHandler.rollback();
65 return false;
66 }
67
68 //
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -080069 // Remove the old Flow Entries
70 //
71 if (found) {
72 Iterable<IFlowEntry> flowEntries = flowObj.getFlowEntries();
73 LinkedList<IFlowEntry> deleteFlowEntries =
74 new LinkedList<IFlowEntry>();
75 for (IFlowEntry flowEntryObj : flowEntries)
76 deleteFlowEntries.add(flowEntryObj);
77 for (IFlowEntry flowEntryObj : deleteFlowEntries) {
78 flowObj.removeFlowEntry(flowEntryObj);
79 dbHandler.removeFlowEntry(flowEntryObj);
80 }
81 }
82
83 //
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070084 // Set the Flow key:
85 // - flowId
86 //
87 flowObj.setFlowId(flowPath.flowId().toString());
88 flowObj.setType("flow");
89
90 //
91 // Set the Flow attributes:
92 // - flowPath.installerId()
Pavlin Radoslavovd28cf7c2013-10-26 11:27:43 -070093 // - flowPath.flowPathType()
Pavlin Radoslavov7d4a40e2013-10-27 23:39:40 -070094 // - flowPath.flowPathUserState()
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070095 // - flowPath.flowPathFlags()
Pavlin Radoslavov5139c0b2013-12-09 18:04:53 -080096 // - flowPath.idleTimeout()
97 // - flowPath.hardTimeout()
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070098 // - flowPath.dataPath().srcPort()
99 // - flowPath.dataPath().dstPort()
100 // - flowPath.matchSrcMac()
101 // - flowPath.matchDstMac()
102 // - flowPath.matchEthernetFrameType()
103 // - flowPath.matchVlanId()
104 // - flowPath.matchVlanPriority()
105 // - flowPath.matchSrcIPv4Net()
106 // - flowPath.matchDstIPv4Net()
107 // - flowPath.matchIpProto()
108 // - flowPath.matchIpToS()
109 // - flowPath.matchSrcTcpUdpPort()
110 // - flowPath.matchDstTcpUdpPort()
111 // - flowPath.flowEntryActions()
112 //
113 flowObj.setInstallerId(flowPath.installerId().toString());
Pavlin Radoslavovd28cf7c2013-10-26 11:27:43 -0700114 flowObj.setFlowPathType(flowPath.flowPathType().toString());
Pavlin Radoslavov7d4a40e2013-10-27 23:39:40 -0700115 flowObj.setFlowPathUserState(flowPath.flowPathUserState().toString());
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700116 flowObj.setFlowPathFlags(flowPath.flowPathFlags().flags());
Pavlin Radoslavov5139c0b2013-12-09 18:04:53 -0800117 flowObj.setIdleTimeout(flowPath.idleTimeout());
118 flowObj.setHardTimeout(flowPath.hardTimeout());
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700119 flowObj.setSrcSwitch(flowPath.dataPath().srcPort().dpid().toString());
120 flowObj.setSrcPort(flowPath.dataPath().srcPort().port().value());
121 flowObj.setDstSwitch(flowPath.dataPath().dstPort().dpid().toString());
122 flowObj.setDstPort(flowPath.dataPath().dstPort().port().value());
123 if (flowPath.flowEntryMatch().matchSrcMac()) {
124 flowObj.setMatchSrcMac(flowPath.flowEntryMatch().srcMac().toString());
125 }
126 if (flowPath.flowEntryMatch().matchDstMac()) {
127 flowObj.setMatchDstMac(flowPath.flowEntryMatch().dstMac().toString());
128 }
129 if (flowPath.flowEntryMatch().matchEthernetFrameType()) {
130 flowObj.setMatchEthernetFrameType(flowPath.flowEntryMatch().ethernetFrameType());
131 }
132 if (flowPath.flowEntryMatch().matchVlanId()) {
133 flowObj.setMatchVlanId(flowPath.flowEntryMatch().vlanId());
134 }
135 if (flowPath.flowEntryMatch().matchVlanPriority()) {
136 flowObj.setMatchVlanPriority(flowPath.flowEntryMatch().vlanPriority());
137 }
138 if (flowPath.flowEntryMatch().matchSrcIPv4Net()) {
139 flowObj.setMatchSrcIPv4Net(flowPath.flowEntryMatch().srcIPv4Net().toString());
140 }
141 if (flowPath.flowEntryMatch().matchDstIPv4Net()) {
142 flowObj.setMatchDstIPv4Net(flowPath.flowEntryMatch().dstIPv4Net().toString());
143 }
144 if (flowPath.flowEntryMatch().matchIpProto()) {
145 flowObj.setMatchIpProto(flowPath.flowEntryMatch().ipProto());
146 }
147 if (flowPath.flowEntryMatch().matchIpToS()) {
148 flowObj.setMatchIpToS(flowPath.flowEntryMatch().ipToS());
149 }
150 if (flowPath.flowEntryMatch().matchSrcTcpUdpPort()) {
151 flowObj.setMatchSrcTcpUdpPort(flowPath.flowEntryMatch().srcTcpUdpPort());
152 }
153 if (flowPath.flowEntryMatch().matchDstTcpUdpPort()) {
154 flowObj.setMatchDstTcpUdpPort(flowPath.flowEntryMatch().dstTcpUdpPort());
155 }
156 if (! flowPath.flowEntryActions().actions().isEmpty()) {
157 flowObj.setActions(flowPath.flowEntryActions().toString());
158 }
Pavlin Radoslavovbcc86ef2013-10-26 12:06:25 -0700159 flowObj.setDataPathSummary(flowPath.dataPath().dataPathSummary());
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700160
161 if (found)
Pavlin Radoslavov7d4a40e2013-10-27 23:39:40 -0700162 flowObj.setFlowPathUserState("FP_USER_MODIFY");
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700163 else
Pavlin Radoslavov7d4a40e2013-10-27 23:39:40 -0700164 flowObj.setFlowPathUserState("FP_USER_ADD");
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700165
166 // Flow edges:
167 // HeadFE
168
169
170 //
171 // Flow Entries:
172 // flowPath.dataPath().flowEntries()
173 //
174 for (FlowEntry flowEntry : flowPath.dataPath().flowEntries()) {
Pavlin Radoslavov7847db72014-01-10 11:35:21 -0800175 // TODO: not needed?
176 /*
Pavlin Radoslavov909da3c2014-01-09 04:04:33 -0800177 if (! enableOnrc2014MeasurementsFlows) {
178 if (flowEntry.flowEntryUserState() == FlowEntryUserState.FE_USER_DELETE)
179 continue; // Skip: all Flow Entries were deleted earlier
180 }
Pavlin Radoslavov7847db72014-01-10 11:35:21 -0800181 */
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800182
Pavlin Radoslavov67bf7622013-12-04 12:28:23 -0800183 if (addFlowEntry(dbHandler, flowObj, flowEntry) == null) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700184 dbHandler.rollback();
185 return false;
186 }
187 }
188 dbHandler.commit();
189
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700190 return true;
191 }
192
193 /**
194 * Add a flow entry to the Network MAP.
195 *
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700196 * @param dbHandler the Graph Database handler to use.
197 * @param flowObj the corresponding Flow Path object for the Flow Entry.
198 * @param flowEntry the Flow Entry to install.
199 * @return the added Flow Entry object on success, otherwise null.
200 */
Pavlin Radoslavov67bf7622013-12-04 12:28:23 -0800201 static IFlowEntry addFlowEntry(GraphDBOperation dbHandler,
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700202 IFlowPath flowObj,
203 FlowEntry flowEntry) {
204 // Flow edges
205 // HeadFE (TODO)
206
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700207 IFlowEntry flowEntryObj = null;
208 boolean found = false;
209 try {
210 if ((flowEntryObj =
211 dbHandler.searchFlowEntry(flowEntry.flowEntryId())) != null) {
212 found = true;
213 } else {
214 flowEntryObj = dbHandler.newFlowEntry();
215 }
216 } catch (Exception e) {
217 log.error(":addFlow FlowEntryId:{} failed",
Yuta HIGUCHI5302ddf2014-01-06 12:53:35 -0800218 flowEntry.flowEntryId());
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700219 return null;
220 }
221 if (flowEntryObj == null) {
222 log.error(":addFlow FlowEntryId:{} failed: FlowEntry object not created",
Yuta HIGUCHI5302ddf2014-01-06 12:53:35 -0800223 flowEntry.flowEntryId());
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700224 return null;
225 }
226
227 //
228 // Set the Flow Entry key:
229 // - flowEntry.flowEntryId()
230 //
231 flowEntryObj.setFlowEntryId(flowEntry.flowEntryId().toString());
232 flowEntryObj.setType("flow_entry");
233
234 //
235 // Set the Flow Entry Edges and attributes:
236 // - Switch edge
237 // - InPort edge
238 // - OutPort edge
239 //
Pavlin Radoslavov5139c0b2013-12-09 18:04:53 -0800240 // - flowEntry.idleTimeout()
241 // - flowEntry.hardTimeout()
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700242 // - flowEntry.dpid()
243 // - flowEntry.flowEntryUserState()
244 // - flowEntry.flowEntrySwitchState()
245 // - flowEntry.flowEntryErrorState()
246 // - flowEntry.matchInPort()
247 // - flowEntry.matchSrcMac()
248 // - flowEntry.matchDstMac()
249 // - flowEntry.matchEthernetFrameType()
250 // - flowEntry.matchVlanId()
251 // - flowEntry.matchVlanPriority()
252 // - flowEntry.matchSrcIPv4Net()
253 // - flowEntry.matchDstIPv4Net()
254 // - flowEntry.matchIpProto()
255 // - flowEntry.matchIpToS()
256 // - flowEntry.matchSrcTcpUdpPort()
257 // - flowEntry.matchDstTcpUdpPort()
258 // - flowEntry.actionOutputPort()
259 // - flowEntry.actions()
260 //
261 ISwitchObject sw = dbHandler.searchSwitch(flowEntry.dpid().toString());
Pavlin Radoslavov5139c0b2013-12-09 18:04:53 -0800262 flowEntryObj.setIdleTimeout(flowEntry.idleTimeout());
263 flowEntryObj.setHardTimeout(flowEntry.hardTimeout());
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700264 flowEntryObj.setSwitchDpid(flowEntry.dpid().toString());
265 flowEntryObj.setSwitch(sw);
266 if (flowEntry.flowEntryMatch().matchInPort()) {
Jonathan Hart5b3ad192013-12-06 17:34:46 -0800267 IPortObject inport =
268 dbHandler.searchPort(flowEntry.dpid().toString(),
269 flowEntry.flowEntryMatch().inPort().value());
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700270 flowEntryObj.setMatchInPort(flowEntry.flowEntryMatch().inPort().value());
Jonathan Hart5b3ad192013-12-06 17:34:46 -0800271 flowEntryObj.setInPort(inport);
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700272 }
273 if (flowEntry.flowEntryMatch().matchSrcMac()) {
274 flowEntryObj.setMatchSrcMac(flowEntry.flowEntryMatch().srcMac().toString());
275 }
276 if (flowEntry.flowEntryMatch().matchDstMac()) {
277 flowEntryObj.setMatchDstMac(flowEntry.flowEntryMatch().dstMac().toString());
278 }
279 if (flowEntry.flowEntryMatch().matchEthernetFrameType()) {
280 flowEntryObj.setMatchEthernetFrameType(flowEntry.flowEntryMatch().ethernetFrameType());
281 }
282 if (flowEntry.flowEntryMatch().matchVlanId()) {
283 flowEntryObj.setMatchVlanId(flowEntry.flowEntryMatch().vlanId());
284 }
285 if (flowEntry.flowEntryMatch().matchVlanPriority()) {
286 flowEntryObj.setMatchVlanPriority(flowEntry.flowEntryMatch().vlanPriority());
287 }
288 if (flowEntry.flowEntryMatch().matchSrcIPv4Net()) {
289 flowEntryObj.setMatchSrcIPv4Net(flowEntry.flowEntryMatch().srcIPv4Net().toString());
290 }
291 if (flowEntry.flowEntryMatch().matchDstIPv4Net()) {
292 flowEntryObj.setMatchDstIPv4Net(flowEntry.flowEntryMatch().dstIPv4Net().toString());
293 }
294 if (flowEntry.flowEntryMatch().matchIpProto()) {
295 flowEntryObj.setMatchIpProto(flowEntry.flowEntryMatch().ipProto());
296 }
297 if (flowEntry.flowEntryMatch().matchIpToS()) {
298 flowEntryObj.setMatchIpToS(flowEntry.flowEntryMatch().ipToS());
299 }
300 if (flowEntry.flowEntryMatch().matchSrcTcpUdpPort()) {
301 flowEntryObj.setMatchSrcTcpUdpPort(flowEntry.flowEntryMatch().srcTcpUdpPort());
302 }
303 if (flowEntry.flowEntryMatch().matchDstTcpUdpPort()) {
304 flowEntryObj.setMatchDstTcpUdpPort(flowEntry.flowEntryMatch().dstTcpUdpPort());
305 }
306
307 for (FlowEntryAction fa : flowEntry.flowEntryActions().actions()) {
308 if (fa.actionOutput() != null) {
Jonathan Hart5b3ad192013-12-06 17:34:46 -0800309 IPortObject outport =
310 dbHandler.searchPort(flowEntry.dpid().toString(),
311 fa.actionOutput().port().value());
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700312 flowEntryObj.setActionOutputPort(fa.actionOutput().port().value());
Jonathan Hart5b3ad192013-12-06 17:34:46 -0800313 flowEntryObj.setOutPort(outport);
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700314 }
315 }
316 if (! flowEntry.flowEntryActions().isEmpty()) {
317 flowEntryObj.setActions(flowEntry.flowEntryActions().toString());
318 }
319
320 // TODO: Hacks with hard-coded state names!
Pavlin Radoslavov9fde9b22014-01-09 14:03:52 -0800321 if (enableOnrc2014MeasurementsFlows) {
322 flowEntryObj.setUserState(flowEntry.flowEntryUserState().toString());
323 } else {
324 if (found)
325 flowEntryObj.setUserState("FE_USER_MODIFY");
326 else
327 flowEntryObj.setUserState("FE_USER_ADD");
328 }
Pavlin Radoslavovebc8b192013-10-29 15:35:35 -0700329 flowEntryObj.setSwitchState(flowEntry.flowEntrySwitchState().toString());
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700330 //
331 // TODO: Take care of the FlowEntryErrorState.
332 //
333
334 // Flow Entries edges:
335 // Flow
336 // NextFE (TODO)
337 if (! found) {
338 flowObj.addFlowEntry(flowEntryObj);
339 flowEntryObj.setFlow(flowObj);
340 }
341
342 return flowEntryObj;
343 }
344
345 /**
Pavlin Radoslavov7407ab52013-11-01 22:19:00 -0700346 * Delete a flow entry from the Network MAP.
347 *
348 * @param dbHandler the Graph Database handler to use.
349 * @param flowObj the corresponding Flow Path object for the Flow Entry.
350 * @param flowEntry the Flow Entry to delete.
351 * @return true on success, otherwise false.
352 */
353 static boolean deleteFlowEntry(GraphDBOperation dbHandler,
354 IFlowPath flowObj,
355 FlowEntry flowEntry) {
356 IFlowEntry flowEntryObj = null;
357 try {
358 flowEntryObj = dbHandler.searchFlowEntry(flowEntry.flowEntryId());
359 } catch (Exception e) {
360 log.error(":deleteFlowEntry FlowEntryId:{} failed",
Yuta HIGUCHI5302ddf2014-01-06 12:53:35 -0800361 flowEntry.flowEntryId());
Pavlin Radoslavov7407ab52013-11-01 22:19:00 -0700362 return false;
363 }
364 //
365 // TODO: Don't print an error for now, because multiple controller
366 // instances might be deleting the same flow entry.
367 //
368 /*
369 if (flowEntryObj == null) {
370 log.error(":deleteFlowEntry FlowEntryId:{} failed: FlowEntry object not found",
Yuta HIGUCHI5302ddf2014-01-06 12:53:35 -0800371 flowEntry.flowEntryId());
Pavlin Radoslavov7407ab52013-11-01 22:19:00 -0700372 return false;
373 }
374 */
375 if (flowEntryObj == null)
376 return true;
377
378 flowObj.removeFlowEntry(flowEntryObj);
379 dbHandler.removeFlowEntry(flowEntryObj);
380 return true;
381 }
382
383 /**
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700384 * Delete all previously added flows.
385 *
386 * @param dbHandler the Graph Database handler to use.
387 * @return true on success, otherwise false.
388 */
389 static boolean deleteAllFlows(GraphDBOperation dbHandler) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700390 List<FlowId> allFlowIds = new LinkedList<FlowId>();
391
392 // Get all Flow IDs
393 Iterable<IFlowPath> allFlowPaths = dbHandler.getAllFlowPaths();
394 for (IFlowPath flowPathObj : allFlowPaths) {
395 if (flowPathObj == null)
396 continue;
397 String flowIdStr = flowPathObj.getFlowId();
398 if (flowIdStr == null)
399 continue;
400 FlowId flowId = new FlowId(flowIdStr);
401 allFlowIds.add(flowId);
402 }
403
Pavlin Radoslavovf2a52652013-11-22 12:35:42 -0800404 // Delete all flows one-by-one
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700405 for (FlowId flowId : allFlowIds) {
Pavlin Radoslavovf2a52652013-11-22 12:35:42 -0800406 deleteFlow(dbHandler, flowId);
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700407 }
408
409 return true;
410 }
411
412 /**
Pavlin Radoslavovf2a52652013-11-22 12:35:42 -0800413 * Delete a previously added flow.
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700414 *
415 * @param dbHandler the Graph Database handler to use.
Pavlin Radoslavovf2a52652013-11-22 12:35:42 -0800416 * @param flowId the Flow ID of the flow to delete.
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700417 * @return true on success, otherwise false.
418 */
Pavlin Radoslavovf2a52652013-11-22 12:35:42 -0800419 static boolean deleteFlow(GraphDBOperation dbHandler, FlowId flowId) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700420 IFlowPath flowObj = null;
421 try {
422 flowObj = dbHandler.searchFlowPath(flowId);
423 } catch (Exception e) {
424 // TODO: handle exceptions
425 dbHandler.rollback();
Yuta HIGUCHI5302ddf2014-01-06 12:53:35 -0800426 log.error(":deleteFlow FlowId:{} failed", flowId);
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700427 return false;
428 }
429 if (flowObj == null) {
430 dbHandler.commit();
431 return true; // OK: No such flow
432 }
433
434 //
435 // Remove all Flow Entries
436 //
437 Iterable<IFlowEntry> flowEntries = flowObj.getFlowEntries();
438 for (IFlowEntry flowEntryObj : flowEntries) {
439 flowObj.removeFlowEntry(flowEntryObj);
440 dbHandler.removeFlowEntry(flowEntryObj);
441 }
442 // Remove the Flow itself
443 dbHandler.removeFlowPath(flowObj);
444 dbHandler.commit();
445
446 return true;
447 }
448
449 /**
450 * Get a previously added flow.
451 *
452 * @param dbHandler the Graph Database handler to use.
453 * @param flowId the Flow ID of the flow to get.
454 * @return the Flow Path if found, otherwise null.
455 */
456 static FlowPath getFlow(GraphDBOperation dbHandler, FlowId flowId) {
457 IFlowPath flowObj = null;
458 try {
459 flowObj = dbHandler.searchFlowPath(flowId);
460 } catch (Exception e) {
461 // TODO: handle exceptions
462 dbHandler.rollback();
Yuta HIGUCHI5302ddf2014-01-06 12:53:35 -0800463 log.error(":getFlow FlowId:{} failed", flowId);
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700464 return null;
465 }
466 if (flowObj == null) {
467 dbHandler.commit();
468 return null; // Flow not found
469 }
470
471 //
472 // Extract the Flow state
473 //
474 FlowPath flowPath = extractFlowPath(flowObj);
475 dbHandler.commit();
476
477 return flowPath;
478 }
479
480 /**
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800481 * Get a previously added flow entry.
482 *
483 * @param dbHandler the Graph Database handler to use.
484 * @param flowEntryId the Flow Entry ID of the flow entry to get.
485 * @return the Flow Entry if found, otherwise null.
486 */
487 static FlowEntry getFlowEntry(GraphDBOperation dbHandler,
488 FlowEntryId flowEntryId) {
489 IFlowEntry flowEntryObj = null;
490 try {
491 flowEntryObj = dbHandler.searchFlowEntry(flowEntryId);
492 } catch (Exception e) {
493 // TODO: handle exceptions
494 dbHandler.rollback();
495 log.error(":getFlowEntry FlowEntryId:{} failed", flowEntryId);
496 return null;
497 }
498 if (flowEntryObj == null) {
499 dbHandler.commit();
500 return null; // Flow not found
501 }
502
503 //
504 // Extract the Flow Entry state
505 //
506 FlowEntry flowEntry = extractFlowEntry(flowEntryObj);
507 dbHandler.commit();
508
509 return flowEntry;
510 }
511
512 /**
Pavlin Radoslavov8252fee2014-01-07 17:24:29 -0800513 * Get the source switch DPID of a previously added flow.
514 *
515 * @param dbHandler the Graph Database handler to use.
516 * @param flowId the Flow ID of the flow to get.
517 * @return the source switch DPID if found, otherwise null.
518 */
519 static Dpid getFlowSourceDpid(GraphDBOperation dbHandler, FlowId flowId) {
520 IFlowPath flowObj = null;
521 try {
522 flowObj = dbHandler.searchFlowPath(flowId);
523 } catch (Exception e) {
524 // TODO: handle exceptions
525 dbHandler.rollback();
526 log.error(":getFlowSourceDpid FlowId:{} failed", flowId);
527 return null;
528 }
529 if (flowObj == null) {
530 dbHandler.commit();
531 return null; // Flow not found
532 }
533
534 //
535 // Extract the Flow Source DPID
536 //
537 String srcSwitchStr = flowObj.getSrcSwitch();
538 if (srcSwitchStr == null) {
539 // TODO: A work-around, becauuse of some bogus database objects
540 dbHandler.commit();
541 return null;
542 }
543
544 Dpid dpid = new Dpid(srcSwitchStr);
545
546 dbHandler.commit();
547
548 return dpid;
549 }
550
551 /**
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700552 * Get all installed flows by all installers.
553 *
554 * @param dbHandler the Graph Database handler to use.
555 * @return the Flow Paths if found, otherwise null.
556 */
557 static ArrayList<FlowPath> getAllFlows(GraphDBOperation dbHandler) {
558 Iterable<IFlowPath> flowPathsObj = null;
559 ArrayList<FlowPath> flowPaths = new ArrayList<FlowPath>();
560
561 try {
562 flowPathsObj = dbHandler.getAllFlowPaths();
563 } catch (Exception e) {
564 // TODO: handle exceptions
565 dbHandler.rollback();
566 log.error(":getAllFlowPaths failed");
567 return flowPaths;
568 }
569 if ((flowPathsObj == null) || (flowPathsObj.iterator().hasNext() == false)) {
570 dbHandler.commit();
571 return flowPaths; // No Flows found
572 }
573
574 for (IFlowPath flowObj : flowPathsObj) {
575 //
576 // Extract the Flow state
577 //
578 FlowPath flowPath = extractFlowPath(flowObj);
579 if (flowPath != null)
580 flowPaths.add(flowPath);
581 }
582
583 dbHandler.commit();
584
585 return flowPaths;
586 }
587
588 /**
Pavlin Radoslavov16b761d2014-01-08 09:47:14 -0800589 * Get all installed flows whose Source Switch is controlled by this
590 * instance.
591 *
592 * @param dbHandler the Graph Database handler to use.
593 * @param mySwitches the collection of the switches controlled by this
594 * instance.
595 * @return the Flow Paths if found, otherwise null.
596 */
597 static ArrayList<FlowPath> getAllMyFlows(GraphDBOperation dbHandler,
598 Map<Long, IOFSwitch> mySwitches) {
599 Iterable<IFlowPath> flowPathsObj = null;
600 ArrayList<FlowPath> flowPaths = new ArrayList<FlowPath>();
601
602 try {
603 flowPathsObj = dbHandler.getAllFlowPaths();
604 } catch (Exception e) {
605 // TODO: handle exceptions
606 dbHandler.rollback();
607 log.error(":getAllMyFlowPaths failed");
608 return flowPaths;
609 }
610 if ((flowPathsObj == null) || (flowPathsObj.iterator().hasNext() == false)) {
611 dbHandler.commit();
612 return flowPaths; // No Flows found
613 }
614
615 for (IFlowPath flowObj : flowPathsObj) {
616 //
617 // Extract the Source Switch DPID and ignore if the switch
618 // is not controlled by this instance.
619 //
620 String srcSwitchStr = flowObj.getSrcSwitch();
621 if (srcSwitchStr == null) {
622 // TODO: A work-around, becauuse of some bogus database objects
623 continue;
624 }
625 Dpid dpid = new Dpid(srcSwitchStr);
626 if (mySwitches.get(dpid.value()) == null)
627 continue;
628
629 //
630 // Extract the Flow state
631 //
632 FlowPath flowPath = extractFlowPath(flowObj);
633 if (flowPath != null)
634 flowPaths.add(flowPath);
635 }
636
637 dbHandler.commit();
638
639 return flowPaths;
640 }
641
642 /**
Pavlin Radoslavovf3f23bb2014-01-10 13:02:33 -0800643 * Get a subset of installed flows.
644 *
645 * @param dbHandler the Graph Database handler to use.
646 * @param flowIds the collection of Flow IDs to get.
647 * @return the Flow Paths if found, otherwise null.
648 */
649 static ArrayList<FlowPath> getFlows(GraphDBOperation dbHandler,
650 Collection<FlowId> flowIds) {
651 ArrayList<FlowPath> flowPaths = new ArrayList<FlowPath>();
652
653 // TODO: This implementation should use threads
654 for (FlowId flowId : flowIds) {
655 FlowPath flowPath = getFlow(dbHandler, flowId);
656 if (flowPath != null)
657 flowPaths.add(flowPath);
658 }
659 // dbHandler.commit();
660
661 return flowPaths;
662 }
663
664 /**
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700665 * Extract Flow Path State from a Titan Database Object @ref IFlowPath.
666 *
667 * @param flowObj the object to extract the Flow Path State from.
668 * @return the extracted Flow Path State.
669 */
670 private static FlowPath extractFlowPath(IFlowPath flowObj) {
671 //
672 // Extract the Flow state
673 //
674 String flowIdStr = flowObj.getFlowId();
675 String installerIdStr = flowObj.getInstallerId();
Pavlin Radoslavovd28cf7c2013-10-26 11:27:43 -0700676 String flowPathType = flowObj.getFlowPathType();
Pavlin Radoslavov7d4a40e2013-10-27 23:39:40 -0700677 String flowPathUserState = flowObj.getFlowPathUserState();
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700678 Long flowPathFlags = flowObj.getFlowPathFlags();
Pavlin Radoslavov5139c0b2013-12-09 18:04:53 -0800679 Integer idleTimeout = flowObj.getIdleTimeout();
680 Integer hardTimeout = flowObj.getHardTimeout();
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700681 String srcSwitchStr = flowObj.getSrcSwitch();
682 Short srcPortShort = flowObj.getSrcPort();
683 String dstSwitchStr = flowObj.getDstSwitch();
684 Short dstPortShort = flowObj.getDstPort();
685
686 if ((flowIdStr == null) ||
687 (installerIdStr == null) ||
Pavlin Radoslavovd28cf7c2013-10-26 11:27:43 -0700688 (flowPathType == null) ||
Pavlin Radoslavov7d4a40e2013-10-27 23:39:40 -0700689 (flowPathUserState == null) ||
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700690 (flowPathFlags == null) ||
Pavlin Radoslavov5139c0b2013-12-09 18:04:53 -0800691 (idleTimeout == null) ||
692 (hardTimeout == null) ||
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700693 (srcSwitchStr == null) ||
694 (srcPortShort == null) ||
695 (dstSwitchStr == null) ||
696 (dstPortShort == null)) {
697 // TODO: A work-around, becauuse of some bogus database objects
698 return null;
699 }
700
701 FlowPath flowPath = new FlowPath();
702 flowPath.setFlowId(new FlowId(flowIdStr));
703 flowPath.setInstallerId(new CallerId(installerIdStr));
Pavlin Radoslavovd28cf7c2013-10-26 11:27:43 -0700704 flowPath.setFlowPathType(FlowPathType.valueOf(flowPathType));
Pavlin Radoslavov7d4a40e2013-10-27 23:39:40 -0700705 flowPath.setFlowPathUserState(FlowPathUserState.valueOf(flowPathUserState));
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700706 flowPath.setFlowPathFlags(new FlowPathFlags(flowPathFlags));
Pavlin Radoslavov5139c0b2013-12-09 18:04:53 -0800707 flowPath.setIdleTimeout(idleTimeout);
708 flowPath.setHardTimeout(hardTimeout);
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700709 flowPath.dataPath().srcPort().setDpid(new Dpid(srcSwitchStr));
710 flowPath.dataPath().srcPort().setPort(new Port(srcPortShort));
711 flowPath.dataPath().dstPort().setDpid(new Dpid(dstSwitchStr));
712 flowPath.dataPath().dstPort().setPort(new Port(dstPortShort));
713 //
714 // Extract the match conditions common for all Flow Entries
715 //
716 {
717 FlowEntryMatch match = new FlowEntryMatch();
718 String matchSrcMac = flowObj.getMatchSrcMac();
719 if (matchSrcMac != null)
720 match.enableSrcMac(MACAddress.valueOf(matchSrcMac));
721 String matchDstMac = flowObj.getMatchDstMac();
722 if (matchDstMac != null)
723 match.enableDstMac(MACAddress.valueOf(matchDstMac));
724 Short matchEthernetFrameType = flowObj.getMatchEthernetFrameType();
725 if (matchEthernetFrameType != null)
726 match.enableEthernetFrameType(matchEthernetFrameType);
727 Short matchVlanId = flowObj.getMatchVlanId();
728 if (matchVlanId != null)
729 match.enableVlanId(matchVlanId);
730 Byte matchVlanPriority = flowObj.getMatchVlanPriority();
731 if (matchVlanPriority != null)
732 match.enableVlanPriority(matchVlanPriority);
733 String matchSrcIPv4Net = flowObj.getMatchSrcIPv4Net();
734 if (matchSrcIPv4Net != null)
735 match.enableSrcIPv4Net(new IPv4Net(matchSrcIPv4Net));
736 String matchDstIPv4Net = flowObj.getMatchDstIPv4Net();
737 if (matchDstIPv4Net != null)
738 match.enableDstIPv4Net(new IPv4Net(matchDstIPv4Net));
739 Byte matchIpProto = flowObj.getMatchIpProto();
740 if (matchIpProto != null)
741 match.enableIpProto(matchIpProto);
742 Byte matchIpToS = flowObj.getMatchIpToS();
743 if (matchIpToS != null)
744 match.enableIpToS(matchIpToS);
745 Short matchSrcTcpUdpPort = flowObj.getMatchSrcTcpUdpPort();
746 if (matchSrcTcpUdpPort != null)
747 match.enableSrcTcpUdpPort(matchSrcTcpUdpPort);
748 Short matchDstTcpUdpPort = flowObj.getMatchDstTcpUdpPort();
749 if (matchDstTcpUdpPort != null)
750 match.enableDstTcpUdpPort(matchDstTcpUdpPort);
751
752 flowPath.setFlowEntryMatch(match);
753 }
754 //
755 // Extract the actions for the first Flow Entry
756 //
757 {
758 String actionsStr = flowObj.getActions();
759 if (actionsStr != null) {
760 FlowEntryActions flowEntryActions = new FlowEntryActions(actionsStr);
761 flowPath.setFlowEntryActions(flowEntryActions);
762 }
763 }
764
765 //
766 // Extract all Flow Entries
767 //
768 Iterable<IFlowEntry> flowEntries = flowObj.getFlowEntries();
769 for (IFlowEntry flowEntryObj : flowEntries) {
770 FlowEntry flowEntry = extractFlowEntry(flowEntryObj);
771 if (flowEntry == null)
772 continue;
773 flowPath.dataPath().flowEntries().add(flowEntry);
774 }
775
776 return flowPath;
777 }
778
779 /**
780 * Extract Flow Entry State from a Titan Database Object @ref IFlowEntry.
781 *
782 * @param flowEntryObj the object to extract the Flow Entry State from.
783 * @return the extracted Flow Entry State.
784 */
Brian O'Connora8e49802013-10-30 20:49:59 -0700785 public static FlowEntry extractFlowEntry(IFlowEntry flowEntryObj) {
Pavlin Radoslavovcf87e532013-12-13 18:17:00 -0800786 IFlowPath flowObj = flowEntryObj.getFlow();
787 if (flowObj == null)
788 return null;
789
790 String flowIdStr = flowObj.getFlowId();
791 //
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700792 String flowEntryIdStr = flowEntryObj.getFlowEntryId();
Pavlin Radoslavov5139c0b2013-12-09 18:04:53 -0800793 Integer idleTimeout = flowEntryObj.getIdleTimeout();
794 Integer hardTimeout = flowEntryObj.getHardTimeout();
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700795 String switchDpidStr = flowEntryObj.getSwitchDpid();
796 String userState = flowEntryObj.getUserState();
797 String switchState = flowEntryObj.getSwitchState();
798
Pavlin Radoslavovcf87e532013-12-13 18:17:00 -0800799 if ((flowIdStr == null) ||
800 (flowEntryIdStr == null) ||
Pavlin Radoslavov5139c0b2013-12-09 18:04:53 -0800801 (idleTimeout == null) ||
802 (hardTimeout == null) ||
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700803 (switchDpidStr == null) ||
804 (userState == null) ||
805 (switchState == null)) {
Brian O'Connora8e49802013-10-30 20:49:59 -0700806 // TODO: A work-around, because of some bogus database objects
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700807 return null;
808 }
809
810 FlowEntry flowEntry = new FlowEntry();
811 flowEntry.setFlowEntryId(new FlowEntryId(flowEntryIdStr));
Pavlin Radoslavovcf87e532013-12-13 18:17:00 -0800812 flowEntry.setFlowId(new FlowId(flowIdStr));
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700813 flowEntry.setDpid(new Dpid(switchDpidStr));
Pavlin Radoslavovce93a032013-12-13 11:03:02 -0800814 flowEntry.setIdleTimeout(idleTimeout);
815 flowEntry.setHardTimeout(hardTimeout);
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700816
817 //
818 // Extract the match conditions
819 //
820 FlowEntryMatch match = new FlowEntryMatch();
821 Short matchInPort = flowEntryObj.getMatchInPort();
822 if (matchInPort != null)
823 match.enableInPort(new Port(matchInPort));
824 String matchSrcMac = flowEntryObj.getMatchSrcMac();
825 if (matchSrcMac != null)
826 match.enableSrcMac(MACAddress.valueOf(matchSrcMac));
827 String matchDstMac = flowEntryObj.getMatchDstMac();
828 if (matchDstMac != null)
829 match.enableDstMac(MACAddress.valueOf(matchDstMac));
830 Short matchEthernetFrameType = flowEntryObj.getMatchEthernetFrameType();
831 if (matchEthernetFrameType != null)
832 match.enableEthernetFrameType(matchEthernetFrameType);
833 Short matchVlanId = flowEntryObj.getMatchVlanId();
834 if (matchVlanId != null)
835 match.enableVlanId(matchVlanId);
836 Byte matchVlanPriority = flowEntryObj.getMatchVlanPriority();
837 if (matchVlanPriority != null)
838 match.enableVlanPriority(matchVlanPriority);
839 String matchSrcIPv4Net = flowEntryObj.getMatchSrcIPv4Net();
840 if (matchSrcIPv4Net != null)
841 match.enableSrcIPv4Net(new IPv4Net(matchSrcIPv4Net));
842 String matchDstIPv4Net = flowEntryObj.getMatchDstIPv4Net();
843 if (matchDstIPv4Net != null)
844 match.enableDstIPv4Net(new IPv4Net(matchDstIPv4Net));
845 Byte matchIpProto = flowEntryObj.getMatchIpProto();
846 if (matchIpProto != null)
847 match.enableIpProto(matchIpProto);
848 Byte matchIpToS = flowEntryObj.getMatchIpToS();
849 if (matchIpToS != null)
850 match.enableIpToS(matchIpToS);
851 Short matchSrcTcpUdpPort = flowEntryObj.getMatchSrcTcpUdpPort();
852 if (matchSrcTcpUdpPort != null)
853 match.enableSrcTcpUdpPort(matchSrcTcpUdpPort);
854 Short matchDstTcpUdpPort = flowEntryObj.getMatchDstTcpUdpPort();
855 if (matchDstTcpUdpPort != null)
856 match.enableDstTcpUdpPort(matchDstTcpUdpPort);
857 flowEntry.setFlowEntryMatch(match);
858
859 //
860 // Extract the actions
861 //
862 FlowEntryActions actions = new FlowEntryActions();
863 String actionsStr = flowEntryObj.getActions();
864 if (actionsStr != null)
865 actions = new FlowEntryActions(actionsStr);
866 flowEntry.setFlowEntryActions(actions);
867 flowEntry.setFlowEntryUserState(FlowEntryUserState.valueOf(userState));
868 flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.valueOf(switchState));
869 //
870 // TODO: Take care of FlowEntryErrorState.
871 //
872 return flowEntry;
873 }
874}