blob: a05abab0169b72320bb537a31cb31c2b81b3e052 [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 Radoslavov661c86f2013-10-21 12:40:40 -07006import java.util.LinkedList;
7import java.util.List;
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -07008
9import net.floodlightcontroller.util.MACAddress;
yoshitomob292c622013-11-23 14:35:58 -080010import net.onrc.onos.graph.DBOperation;
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070011import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowEntry;
12import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowPath;
13import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IPortObject;
14import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.ISwitchObject;
15import net.onrc.onos.ofcontroller.util.*;
16
17import org.slf4j.Logger;
18import org.slf4j.LoggerFactory;
19
20/**
21 * Class for performing Flow-related operations on the Database.
22 */
Pavlin Radoslavov6bfaea62013-12-03 14:55:57 -080023public class FlowDatabaseOperation {
Yuta HIGUCHI6ac8d182013-10-22 15:24:56 -070024 private final static Logger log = LoggerFactory.getLogger(FlowDatabaseOperation.class);
Yuta HIGUCHI37c55472014-01-03 11:42:27 -080025 public static final boolean measureONOSFlowTimeProp = Long.valueOf(System.getProperty("benchmark.measureONOSFlow", "0")) != 0;
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070026
27 /**
28 * Add a flow.
29 *
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070030 * @param dbHandler the Graph Database handler to use.
31 * @param flowPath the Flow Path to install.
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070032 * @return true on success, otherwise false.
33 */
onlab-qa38805cd2013-12-06 20:08:54 -080034 static boolean addFlow(DBOperation dbHandler, FlowPath flowPath) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070035 IFlowPath flowObj = null;
36 boolean found = false;
Yuta HIGUCHI37c55472014-01-03 11:42:27 -080037 long startAddFlow = 0;
38 long endAddFlow = 0;
39 long endSearchExistingFlowPathTime = 0;
40 long endCreateNewFlowPathTime = 0;
41 long startFollowExistingFlowEntries = 0;
42 long endFollowExistingFlowEntries = 0;
43 long accTimeRemovingFlowEntriesFromFlowPath = 0;
44 long accTimeRemovingFlowEntriesFromDB = 0;
45 long startSettingFlowPathProps = 0;
46 long endSettingFlowPathProps = 0;
47 int numPropsSet = 0;
48 long accTimeAddFlowEntries = 0;
49 int numNewFlowEntries = 0;
50 LinkedList<long[]> flowEntryTimes = new LinkedList<>();
51
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070052 try {
Yuta HIGUCHI37c55472014-01-03 11:42:27 -080053 if ( measureONOSFlowTimeProp ) {
54 startAddFlow = System.nanoTime();
55 }
yoshi40210942013-12-03 08:21:02 -080056 flowObj = dbHandler.searchFlowPath(flowPath.flowId());
Yuta HIGUCHI37c55472014-01-03 11:42:27 -080057 if ( measureONOSFlowTimeProp ) {
58 endSearchExistingFlowPathTime = System.nanoTime();
59 }
yoshi40210942013-12-03 08:21:02 -080060 if (flowObj != null) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070061 found = true;
62 } else {
63 flowObj = dbHandler.newFlowPath();
Yuta HIGUCHI37c55472014-01-03 11:42:27 -080064 if ( measureONOSFlowTimeProp ) {
65 endCreateNewFlowPathTime = System.nanoTime();
66 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070067 }
68 } catch (Exception e) {
69 dbHandler.rollback();
70
71 StringWriter sw = new StringWriter();
72 e.printStackTrace(new PrintWriter(sw));
73 String stacktrace = sw.toString();
74
75 log.error(":addFlow FlowId:{} failed: {}",
76 flowPath.flowId().toString(),
77 stacktrace);
78 return false;
79 }
80 if (flowObj == null) {
81 log.error(":addFlow FlowId:{} failed: Flow object not created",
82 flowPath.flowId().toString());
83 dbHandler.rollback();
84 return false;
85 }
86
87 //
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -080088 // Remove the old Flow Entries
89 //
90 if (found) {
Yuta HIGUCHI37c55472014-01-03 11:42:27 -080091 if ( measureONOSFlowTimeProp ) {
92 startFollowExistingFlowEntries = System.nanoTime();
93 }
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -080094 Iterable<IFlowEntry> flowEntries = flowObj.getFlowEntries();
Yuta HIGUCHI37c55472014-01-03 11:42:27 -080095 if ( measureONOSFlowTimeProp ) {
96 endFollowExistingFlowEntries = System.nanoTime();
97 }
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -080098 LinkedList<IFlowEntry> deleteFlowEntries =
99 new LinkedList<IFlowEntry>();
100 for (IFlowEntry flowEntryObj : flowEntries)
101 deleteFlowEntries.add(flowEntryObj);
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800102 if( measureONOSFlowTimeProp ) {
103 for (IFlowEntry flowEntryObj : deleteFlowEntries) {
104 long start = System.nanoTime();
105 flowObj.removeFlowEntry(flowEntryObj);
106 accTimeRemovingFlowEntriesFromFlowPath += System.nanoTime() - start;
107 start = System.nanoTime();
108 dbHandler.removeFlowEntry(flowEntryObj);
109 accTimeRemovingFlowEntriesFromDB += System.nanoTime() - start;
110 }
111 } else {
112 for (IFlowEntry flowEntryObj : deleteFlowEntries) {
113 flowObj.removeFlowEntry(flowEntryObj);
114 dbHandler.removeFlowEntry(flowEntryObj);
115 }
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800116 }
117 }
118
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800119 if ( measureONOSFlowTimeProp ) {
120 startSettingFlowPathProps = System.nanoTime();
121 }
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800122 //
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700123 // Set the Flow key:
124 // - flowId
125 //
126 flowObj.setFlowId(flowPath.flowId().toString());
127 flowObj.setType("flow");
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800128 if ( measureONOSFlowTimeProp ) {
129 numPropsSet += 2;
130 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700131
132 //
133 // Set the Flow attributes:
134 // - flowPath.installerId()
Pavlin Radoslavovd28cf7c2013-10-26 11:27:43 -0700135 // - flowPath.flowPathType()
Pavlin Radoslavov7d4a40e2013-10-27 23:39:40 -0700136 // - flowPath.flowPathUserState()
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700137 // - flowPath.flowPathFlags()
Pavlin Radoslavov5139c0b2013-12-09 18:04:53 -0800138 // - flowPath.idleTimeout()
139 // - flowPath.hardTimeout()
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700140 // - flowPath.dataPath().srcPort()
141 // - flowPath.dataPath().dstPort()
142 // - flowPath.matchSrcMac()
143 // - flowPath.matchDstMac()
144 // - flowPath.matchEthernetFrameType()
145 // - flowPath.matchVlanId()
146 // - flowPath.matchVlanPriority()
147 // - flowPath.matchSrcIPv4Net()
148 // - flowPath.matchDstIPv4Net()
149 // - flowPath.matchIpProto()
150 // - flowPath.matchIpToS()
151 // - flowPath.matchSrcTcpUdpPort()
152 // - flowPath.matchDstTcpUdpPort()
153 // - flowPath.flowEntryActions()
154 //
155 flowObj.setInstallerId(flowPath.installerId().toString());
Pavlin Radoslavovd28cf7c2013-10-26 11:27:43 -0700156 flowObj.setFlowPathType(flowPath.flowPathType().toString());
Pavlin Radoslavov7d4a40e2013-10-27 23:39:40 -0700157 flowObj.setFlowPathUserState(flowPath.flowPathUserState().toString());
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700158 flowObj.setFlowPathFlags(flowPath.flowPathFlags().flags());
Pavlin Radoslavov5139c0b2013-12-09 18:04:53 -0800159 flowObj.setIdleTimeout(flowPath.idleTimeout());
160 flowObj.setHardTimeout(flowPath.hardTimeout());
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700161 flowObj.setSrcSwitch(flowPath.dataPath().srcPort().dpid().toString());
162 flowObj.setSrcPort(flowPath.dataPath().srcPort().port().value());
163 flowObj.setDstSwitch(flowPath.dataPath().dstPort().dpid().toString());
164 flowObj.setDstPort(flowPath.dataPath().dstPort().port().value());
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800165 if ( measureONOSFlowTimeProp ) {
166 numPropsSet += 10;
167 }
168
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700169 if (flowPath.flowEntryMatch().matchSrcMac()) {
170 flowObj.setMatchSrcMac(flowPath.flowEntryMatch().srcMac().toString());
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800171 if ( measureONOSFlowTimeProp ) {
172 ++numPropsSet;
173 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700174 }
175 if (flowPath.flowEntryMatch().matchDstMac()) {
176 flowObj.setMatchDstMac(flowPath.flowEntryMatch().dstMac().toString());
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800177 if ( measureONOSFlowTimeProp ) {
178 ++numPropsSet;
179 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700180 }
181 if (flowPath.flowEntryMatch().matchEthernetFrameType()) {
182 flowObj.setMatchEthernetFrameType(flowPath.flowEntryMatch().ethernetFrameType());
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800183 if ( measureONOSFlowTimeProp ) {
184 ++numPropsSet;
185 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700186 }
187 if (flowPath.flowEntryMatch().matchVlanId()) {
188 flowObj.setMatchVlanId(flowPath.flowEntryMatch().vlanId());
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800189 if ( measureONOSFlowTimeProp ) {
190 ++numPropsSet;
191 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700192 }
193 if (flowPath.flowEntryMatch().matchVlanPriority()) {
194 flowObj.setMatchVlanPriority(flowPath.flowEntryMatch().vlanPriority());
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800195 if ( measureONOSFlowTimeProp ) {
196 ++numPropsSet;
197 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700198 }
199 if (flowPath.flowEntryMatch().matchSrcIPv4Net()) {
200 flowObj.setMatchSrcIPv4Net(flowPath.flowEntryMatch().srcIPv4Net().toString());
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800201 if ( measureONOSFlowTimeProp ) {
202 ++numPropsSet;
203 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700204 }
205 if (flowPath.flowEntryMatch().matchDstIPv4Net()) {
206 flowObj.setMatchDstIPv4Net(flowPath.flowEntryMatch().dstIPv4Net().toString());
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800207 if ( measureONOSFlowTimeProp ) {
208 ++numPropsSet;
209 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700210 }
211 if (flowPath.flowEntryMatch().matchIpProto()) {
212 flowObj.setMatchIpProto(flowPath.flowEntryMatch().ipProto());
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800213 if ( measureONOSFlowTimeProp ) {
214 ++numPropsSet;
215 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700216 }
217 if (flowPath.flowEntryMatch().matchIpToS()) {
218 flowObj.setMatchIpToS(flowPath.flowEntryMatch().ipToS());
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800219 if ( measureONOSFlowTimeProp ) {
220 ++numPropsSet;
221 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700222 }
223 if (flowPath.flowEntryMatch().matchSrcTcpUdpPort()) {
224 flowObj.setMatchSrcTcpUdpPort(flowPath.flowEntryMatch().srcTcpUdpPort());
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800225 if ( measureONOSFlowTimeProp ) {
226 ++numPropsSet;
227 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700228 }
229 if (flowPath.flowEntryMatch().matchDstTcpUdpPort()) {
230 flowObj.setMatchDstTcpUdpPort(flowPath.flowEntryMatch().dstTcpUdpPort());
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800231 if ( measureONOSFlowTimeProp ) {
232 ++numPropsSet;
233 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700234 }
235 if (! flowPath.flowEntryActions().actions().isEmpty()) {
236 flowObj.setActions(flowPath.flowEntryActions().toString());
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800237 if ( measureONOSFlowTimeProp ) {
238 ++numPropsSet;
239 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700240 }
Pavlin Radoslavovbcc86ef2013-10-26 12:06:25 -0700241 flowObj.setDataPathSummary(flowPath.dataPath().dataPathSummary());
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800242 if ( measureONOSFlowTimeProp ) {
243 ++numPropsSet;
244 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700245
246 if (found)
Pavlin Radoslavov7d4a40e2013-10-27 23:39:40 -0700247 flowObj.setFlowPathUserState("FP_USER_MODIFY");
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700248 else
Pavlin Radoslavov7d4a40e2013-10-27 23:39:40 -0700249 flowObj.setFlowPathUserState("FP_USER_ADD");
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700250
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800251 if ( measureONOSFlowTimeProp ) {
252 ++numPropsSet;
253 }
254
255 if ( measureONOSFlowTimeProp ) {
256 endSettingFlowPathProps = System.nanoTime();
257 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700258 // Flow edges:
259 // HeadFE
260
261
262 //
263 // Flow Entries:
264 // flowPath.dataPath().flowEntries()
265 //
266 for (FlowEntry flowEntry : flowPath.dataPath().flowEntries()) {
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800267 if (flowEntry.flowEntryUserState() == FlowEntryUserState.FE_USER_DELETE)
268 continue; // Skip: all Flow Entries were deleted earlier
269
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800270 long startAddFlowEntry = 0, endAddFlowEntry;
271 if( measureONOSFlowTimeProp ) {
272 startAddFlowEntry = System.nanoTime();
273 }
274 IFlowEntry iFlowEntry = addFlowEntry(dbHandler, flowObj, flowEntry);
275 if( measureONOSFlowTimeProp ) {
276 endAddFlowEntry = System.nanoTime();
277 accTimeAddFlowEntries += endAddFlowEntry - startAddFlowEntry;
278
279 flowEntryTimes.addLast( new long[]{flowEntry.flowId().value(), endAddFlowEntry - startAddFlowEntry} );
280 }
281 if ( iFlowEntry == null) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700282 dbHandler.rollback();
283 return false;
284 }
285 }
286 dbHandler.commit();
287
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800288
289 if ( measureONOSFlowTimeProp ) {
290 endAddFlow = System.nanoTime();
291
292 log.debug("Performance addFlow(_,{}) -- "
293 + "GrandTotal: {} "
294 + "only FlowPathTotal: {} "
295 + "searchExistingFlowPath: {} "
296 + "createNewFlowPathTime: {}"
297 + "followExistingFlowEntries: {} "
298 + "accTimeRemovingFlowEntriesFromFlowPath: {} "
299 + "accTimeRemovingFlowEntriesFromDB: {} "
300 + "settingFlowPathProps: {} #Props: {} "
301 + "accFlowEntries: {} #FEs: {}",
302 flowPath.flowId(),
303 (endAddFlow - startAddFlow),
304 (endSettingFlowPathProps - startAddFlow),
305 (endSearchExistingFlowPathTime - startAddFlow),
306 (endCreateNewFlowPathTime - endSearchExistingFlowPathTime),
307 (endFollowExistingFlowEntries - startFollowExistingFlowEntries),
308 (accTimeRemovingFlowEntriesFromFlowPath),
309 (accTimeRemovingFlowEntriesFromDB),
310 (endSettingFlowPathProps - startSettingFlowPathProps), numPropsSet,
311 accTimeAddFlowEntries, numNewFlowEntries
312 );
313
314 // Each FlowEntries
315 final String strFlowId = flowPath.flowId().toString();
316 for ( long[] idFE_Time : flowEntryTimes ) {
317 log.debug("Performance addFlowEntry(_,{},{})@addFlow -- FlowEntryTotal: {}",
318 strFlowId,
319 "0x" + Long.toHexString(idFE_Time[0]),
320 idFE_Time[1]);
321 }
322 }
323
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700324 return true;
325 }
326
327 /**
328 * Add a flow entry to the Network MAP.
329 *
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700330 * @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 install.
333 * @return the added Flow Entry object on success, otherwise null.
334 */
onlab-qa38805cd2013-12-06 20:08:54 -0800335 static IFlowEntry addFlowEntry(DBOperation dbHandler,
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700336 IFlowPath flowObj,
337 FlowEntry flowEntry) {
338 // Flow edges
339 // HeadFE (TODO)
340
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700341 IFlowEntry flowEntryObj = null;
342 boolean found = false;
343 try {
344 if ((flowEntryObj =
345 dbHandler.searchFlowEntry(flowEntry.flowEntryId())) != null) {
346 found = true;
347 } else {
348 flowEntryObj = dbHandler.newFlowEntry();
349 }
350 } catch (Exception e) {
351 log.error(":addFlow FlowEntryId:{} failed",
352 flowEntry.flowEntryId().toString());
353 return null;
354 }
355 if (flowEntryObj == null) {
356 log.error(":addFlow FlowEntryId:{} failed: FlowEntry object not created",
357 flowEntry.flowEntryId().toString());
358 return null;
359 }
360
361 //
362 // Set the Flow Entry key:
363 // - flowEntry.flowEntryId()
364 //
365 flowEntryObj.setFlowEntryId(flowEntry.flowEntryId().toString());
366 flowEntryObj.setType("flow_entry");
367
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800368 //
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700369 // Set the Flow Entry Edges and attributes:
370 // - Switch edge
371 // - InPort edge
372 // - OutPort edge
373 //
Pavlin Radoslavov5139c0b2013-12-09 18:04:53 -0800374 // - flowEntry.idleTimeout()
375 // - flowEntry.hardTimeout()
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700376 // - flowEntry.dpid()
377 // - flowEntry.flowEntryUserState()
378 // - flowEntry.flowEntrySwitchState()
379 // - flowEntry.flowEntryErrorState()
380 // - flowEntry.matchInPort()
381 // - flowEntry.matchSrcMac()
382 // - flowEntry.matchDstMac()
383 // - flowEntry.matchEthernetFrameType()
384 // - flowEntry.matchVlanId()
385 // - flowEntry.matchVlanPriority()
386 // - flowEntry.matchSrcIPv4Net()
387 // - flowEntry.matchDstIPv4Net()
388 // - flowEntry.matchIpProto()
389 // - flowEntry.matchIpToS()
390 // - flowEntry.matchSrcTcpUdpPort()
391 // - flowEntry.matchDstTcpUdpPort()
392 // - flowEntry.actionOutputPort()
393 // - flowEntry.actions()
394 //
395 ISwitchObject sw = dbHandler.searchSwitch(flowEntry.dpid().toString());
Pavlin Radoslavov5139c0b2013-12-09 18:04:53 -0800396 flowEntryObj.setIdleTimeout(flowEntry.idleTimeout());
397 flowEntryObj.setHardTimeout(flowEntry.hardTimeout());
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700398 flowEntryObj.setSwitchDpid(flowEntry.dpid().toString());
399 flowEntryObj.setSwitch(sw);
400 if (flowEntry.flowEntryMatch().matchInPort()) {
401 IPortObject inport =
402 dbHandler.searchPort(flowEntry.dpid().toString(),
403 flowEntry.flowEntryMatch().inPort().value());
404 flowEntryObj.setMatchInPort(flowEntry.flowEntryMatch().inPort().value());
405 flowEntryObj.setInPort(inport);
406 }
407 if (flowEntry.flowEntryMatch().matchSrcMac()) {
408 flowEntryObj.setMatchSrcMac(flowEntry.flowEntryMatch().srcMac().toString());
409 }
410 if (flowEntry.flowEntryMatch().matchDstMac()) {
411 flowEntryObj.setMatchDstMac(flowEntry.flowEntryMatch().dstMac().toString());
412 }
413 if (flowEntry.flowEntryMatch().matchEthernetFrameType()) {
414 flowEntryObj.setMatchEthernetFrameType(flowEntry.flowEntryMatch().ethernetFrameType());
415 }
416 if (flowEntry.flowEntryMatch().matchVlanId()) {
417 flowEntryObj.setMatchVlanId(flowEntry.flowEntryMatch().vlanId());
418 }
419 if (flowEntry.flowEntryMatch().matchVlanPriority()) {
420 flowEntryObj.setMatchVlanPriority(flowEntry.flowEntryMatch().vlanPriority());
421 }
422 if (flowEntry.flowEntryMatch().matchSrcIPv4Net()) {
423 flowEntryObj.setMatchSrcIPv4Net(flowEntry.flowEntryMatch().srcIPv4Net().toString());
424 }
425 if (flowEntry.flowEntryMatch().matchDstIPv4Net()) {
426 flowEntryObj.setMatchDstIPv4Net(flowEntry.flowEntryMatch().dstIPv4Net().toString());
427 }
428 if (flowEntry.flowEntryMatch().matchIpProto()) {
429 flowEntryObj.setMatchIpProto(flowEntry.flowEntryMatch().ipProto());
430 }
431 if (flowEntry.flowEntryMatch().matchIpToS()) {
432 flowEntryObj.setMatchIpToS(flowEntry.flowEntryMatch().ipToS());
433 }
434 if (flowEntry.flowEntryMatch().matchSrcTcpUdpPort()) {
435 flowEntryObj.setMatchSrcTcpUdpPort(flowEntry.flowEntryMatch().srcTcpUdpPort());
436 }
437 if (flowEntry.flowEntryMatch().matchDstTcpUdpPort()) {
438 flowEntryObj.setMatchDstTcpUdpPort(flowEntry.flowEntryMatch().dstTcpUdpPort());
439 }
440
441 for (FlowEntryAction fa : flowEntry.flowEntryActions().actions()) {
442 if (fa.actionOutput() != null) {
443 IPortObject outport =
444 dbHandler.searchPort(flowEntry.dpid().toString(),
445 fa.actionOutput().port().value());
446 flowEntryObj.setActionOutputPort(fa.actionOutput().port().value());
447 flowEntryObj.setOutPort(outport);
448 }
449 }
450 if (! flowEntry.flowEntryActions().isEmpty()) {
451 flowEntryObj.setActions(flowEntry.flowEntryActions().toString());
452 }
453
454 // TODO: Hacks with hard-coded state names!
455 if (found)
456 flowEntryObj.setUserState("FE_USER_MODIFY");
457 else
458 flowEntryObj.setUserState("FE_USER_ADD");
Pavlin Radoslavovebc8b192013-10-29 15:35:35 -0700459 flowEntryObj.setSwitchState(flowEntry.flowEntrySwitchState().toString());
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700460 //
461 // TODO: Take care of the FlowEntryErrorState.
462 //
463
464 // Flow Entries edges:
465 // Flow
466 // NextFE (TODO)
467 if (! found) {
468 flowObj.addFlowEntry(flowEntryObj);
469 flowEntryObj.setFlow(flowObj);
470 }
471
472 return flowEntryObj;
473 }
474
475 /**
Pavlin Radoslavov7407ab52013-11-01 22:19:00 -0700476 * Delete a flow entry from the Network MAP.
477 *
478 * @param dbHandler the Graph Database handler to use.
479 * @param flowObj the corresponding Flow Path object for the Flow Entry.
480 * @param flowEntry the Flow Entry to delete.
481 * @return true on success, otherwise false.
482 */
yoshitomob292c622013-11-23 14:35:58 -0800483 static boolean deleteFlowEntry(DBOperation dbHandler,
Pavlin Radoslavov7407ab52013-11-01 22:19:00 -0700484 IFlowPath flowObj,
485 FlowEntry flowEntry) {
486 IFlowEntry flowEntryObj = null;
487 try {
488 flowEntryObj = dbHandler.searchFlowEntry(flowEntry.flowEntryId());
489 } catch (Exception e) {
490 log.error(":deleteFlowEntry FlowEntryId:{} failed",
491 flowEntry.flowEntryId().toString());
492 return false;
493 }
494 //
495 // TODO: Don't print an error for now, because multiple controller
496 // instances might be deleting the same flow entry.
497 //
498 /*
499 if (flowEntryObj == null) {
500 log.error(":deleteFlowEntry FlowEntryId:{} failed: FlowEntry object not found",
501 flowEntry.flowEntryId().toString());
502 return false;
503 }
504 */
505 if (flowEntryObj == null)
506 return true;
507
508 flowObj.removeFlowEntry(flowEntryObj);
509 dbHandler.removeFlowEntry(flowEntryObj);
510 return true;
511 }
512
513 /**
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700514 * Delete all previously added flows.
515 *
516 * @param dbHandler the Graph Database handler to use.
517 * @return true on success, otherwise false.
518 */
yoshitomob292c622013-11-23 14:35:58 -0800519 static boolean deleteAllFlows(DBOperation dbHandler) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700520 List<FlowId> allFlowIds = new LinkedList<FlowId>();
521
522 // Get all Flow IDs
523 Iterable<IFlowPath> allFlowPaths = dbHandler.getAllFlowPaths();
524 for (IFlowPath flowPathObj : allFlowPaths) {
525 if (flowPathObj == null)
526 continue;
527 String flowIdStr = flowPathObj.getFlowId();
528 if (flowIdStr == null)
529 continue;
530 FlowId flowId = new FlowId(flowIdStr);
531 allFlowIds.add(flowId);
532 }
533
Pavlin Radoslavovf2a52652013-11-22 12:35:42 -0800534 // Delete all flows one-by-one
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700535 for (FlowId flowId : allFlowIds) {
Pavlin Radoslavovf2a52652013-11-22 12:35:42 -0800536 deleteFlow(dbHandler, flowId);
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700537 }
538
539 return true;
540 }
541
542 /**
Pavlin Radoslavovf2a52652013-11-22 12:35:42 -0800543 * Delete a previously added flow.
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700544 *
545 * @param dbHandler the Graph Database handler to use.
Pavlin Radoslavovf2a52652013-11-22 12:35:42 -0800546 * @param flowId the Flow ID of the flow to delete.
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700547 * @return true on success, otherwise false.
548 */
yoshitomob292c622013-11-23 14:35:58 -0800549 static boolean deleteFlow(DBOperation dbHandler, FlowId flowId) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700550 IFlowPath flowObj = null;
551 try {
552 flowObj = dbHandler.searchFlowPath(flowId);
553 } catch (Exception e) {
554 // TODO: handle exceptions
555 dbHandler.rollback();
Pavlin Radoslavovf2a52652013-11-22 12:35:42 -0800556 log.error(":deleteFlow FlowId:{} failed", flowId.toString());
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700557 return false;
558 }
559 if (flowObj == null) {
560 dbHandler.commit();
561 return true; // OK: No such flow
562 }
563
564 //
565 // Remove all Flow Entries
566 //
567 Iterable<IFlowEntry> flowEntries = flowObj.getFlowEntries();
568 for (IFlowEntry flowEntryObj : flowEntries) {
569 flowObj.removeFlowEntry(flowEntryObj);
570 dbHandler.removeFlowEntry(flowEntryObj);
571 }
572 // Remove the Flow itself
573 dbHandler.removeFlowPath(flowObj);
574 dbHandler.commit();
575
576 return true;
577 }
578
579 /**
580 * Get a previously added flow.
581 *
582 * @param dbHandler the Graph Database handler to use.
583 * @param flowId the Flow ID of the flow to get.
584 * @return the Flow Path if found, otherwise null.
585 */
yoshitomob292c622013-11-23 14:35:58 -0800586 static FlowPath getFlow(DBOperation dbHandler, FlowId flowId) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700587 IFlowPath flowObj = null;
588 try {
589 flowObj = dbHandler.searchFlowPath(flowId);
590 } catch (Exception e) {
591 // TODO: handle exceptions
592 dbHandler.rollback();
593 log.error(":getFlow FlowId:{} failed", flowId.toString());
594 return null;
595 }
596 if (flowObj == null) {
597 dbHandler.commit();
598 return null; // Flow not found
599 }
600
601 //
602 // Extract the Flow state
603 //
604 FlowPath flowPath = extractFlowPath(flowObj);
605 dbHandler.commit();
606
607 return flowPath;
608 }
609
610 /**
611 * Get all installed flows by all installers.
612 *
613 * @param dbHandler the Graph Database handler to use.
614 * @return the Flow Paths if found, otherwise null.
615 */
yoshitomob292c622013-11-23 14:35:58 -0800616 static ArrayList<FlowPath> getAllFlows(DBOperation dbHandler) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700617 Iterable<IFlowPath> flowPathsObj = null;
618 ArrayList<FlowPath> flowPaths = new ArrayList<FlowPath>();
619
620 try {
621 flowPathsObj = dbHandler.getAllFlowPaths();
622 } catch (Exception e) {
623 // TODO: handle exceptions
624 dbHandler.rollback();
625 log.error(":getAllFlowPaths failed");
626 return flowPaths;
627 }
628 if ((flowPathsObj == null) || (flowPathsObj.iterator().hasNext() == false)) {
629 dbHandler.commit();
630 return flowPaths; // No Flows found
631 }
632
633 for (IFlowPath flowObj : flowPathsObj) {
634 //
635 // Extract the Flow state
636 //
637 FlowPath flowPath = extractFlowPath(flowObj);
638 if (flowPath != null)
639 flowPaths.add(flowPath);
640 }
641
642 dbHandler.commit();
643
644 return flowPaths;
645 }
646
647 /**
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700648 * Extract Flow Path State from a Titan Database Object @ref IFlowPath.
649 *
650 * @param flowObj the object to extract the Flow Path State from.
651 * @return the extracted Flow Path State.
652 */
653 private static FlowPath extractFlowPath(IFlowPath flowObj) {
654 //
655 // Extract the Flow state
656 //
657 String flowIdStr = flowObj.getFlowId();
658 String installerIdStr = flowObj.getInstallerId();
Pavlin Radoslavovd28cf7c2013-10-26 11:27:43 -0700659 String flowPathType = flowObj.getFlowPathType();
Pavlin Radoslavov7d4a40e2013-10-27 23:39:40 -0700660 String flowPathUserState = flowObj.getFlowPathUserState();
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700661 Long flowPathFlags = flowObj.getFlowPathFlags();
Pavlin Radoslavov5139c0b2013-12-09 18:04:53 -0800662 Integer idleTimeout = flowObj.getIdleTimeout();
663 Integer hardTimeout = flowObj.getHardTimeout();
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700664 String srcSwitchStr = flowObj.getSrcSwitch();
665 Short srcPortShort = flowObj.getSrcPort();
666 String dstSwitchStr = flowObj.getDstSwitch();
667 Short dstPortShort = flowObj.getDstPort();
668
669 if ((flowIdStr == null) ||
670 (installerIdStr == null) ||
Pavlin Radoslavovd28cf7c2013-10-26 11:27:43 -0700671 (flowPathType == null) ||
Pavlin Radoslavov7d4a40e2013-10-27 23:39:40 -0700672 (flowPathUserState == null) ||
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700673 (flowPathFlags == null) ||
Pavlin Radoslavov5139c0b2013-12-09 18:04:53 -0800674 (idleTimeout == null) ||
675 (hardTimeout == null) ||
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700676 (srcSwitchStr == null) ||
677 (srcPortShort == null) ||
678 (dstSwitchStr == null) ||
679 (dstPortShort == null)) {
680 // TODO: A work-around, becauuse of some bogus database objects
681 return null;
682 }
683
684 FlowPath flowPath = new FlowPath();
685 flowPath.setFlowId(new FlowId(flowIdStr));
686 flowPath.setInstallerId(new CallerId(installerIdStr));
Pavlin Radoslavovd28cf7c2013-10-26 11:27:43 -0700687 flowPath.setFlowPathType(FlowPathType.valueOf(flowPathType));
Pavlin Radoslavov7d4a40e2013-10-27 23:39:40 -0700688 flowPath.setFlowPathUserState(FlowPathUserState.valueOf(flowPathUserState));
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700689 flowPath.setFlowPathFlags(new FlowPathFlags(flowPathFlags));
Pavlin Radoslavov5139c0b2013-12-09 18:04:53 -0800690 flowPath.setIdleTimeout(idleTimeout);
691 flowPath.setHardTimeout(hardTimeout);
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700692 flowPath.dataPath().srcPort().setDpid(new Dpid(srcSwitchStr));
693 flowPath.dataPath().srcPort().setPort(new Port(srcPortShort));
694 flowPath.dataPath().dstPort().setDpid(new Dpid(dstSwitchStr));
695 flowPath.dataPath().dstPort().setPort(new Port(dstPortShort));
696 //
697 // Extract the match conditions common for all Flow Entries
698 //
699 {
700 FlowEntryMatch match = new FlowEntryMatch();
701 String matchSrcMac = flowObj.getMatchSrcMac();
702 if (matchSrcMac != null)
703 match.enableSrcMac(MACAddress.valueOf(matchSrcMac));
704 String matchDstMac = flowObj.getMatchDstMac();
705 if (matchDstMac != null)
706 match.enableDstMac(MACAddress.valueOf(matchDstMac));
707 Short matchEthernetFrameType = flowObj.getMatchEthernetFrameType();
708 if (matchEthernetFrameType != null)
709 match.enableEthernetFrameType(matchEthernetFrameType);
710 Short matchVlanId = flowObj.getMatchVlanId();
711 if (matchVlanId != null)
712 match.enableVlanId(matchVlanId);
713 Byte matchVlanPriority = flowObj.getMatchVlanPriority();
714 if (matchVlanPriority != null)
715 match.enableVlanPriority(matchVlanPriority);
716 String matchSrcIPv4Net = flowObj.getMatchSrcIPv4Net();
717 if (matchSrcIPv4Net != null)
718 match.enableSrcIPv4Net(new IPv4Net(matchSrcIPv4Net));
719 String matchDstIPv4Net = flowObj.getMatchDstIPv4Net();
720 if (matchDstIPv4Net != null)
721 match.enableDstIPv4Net(new IPv4Net(matchDstIPv4Net));
722 Byte matchIpProto = flowObj.getMatchIpProto();
723 if (matchIpProto != null)
724 match.enableIpProto(matchIpProto);
725 Byte matchIpToS = flowObj.getMatchIpToS();
726 if (matchIpToS != null)
727 match.enableIpToS(matchIpToS);
728 Short matchSrcTcpUdpPort = flowObj.getMatchSrcTcpUdpPort();
729 if (matchSrcTcpUdpPort != null)
730 match.enableSrcTcpUdpPort(matchSrcTcpUdpPort);
731 Short matchDstTcpUdpPort = flowObj.getMatchDstTcpUdpPort();
732 if (matchDstTcpUdpPort != null)
733 match.enableDstTcpUdpPort(matchDstTcpUdpPort);
734
735 flowPath.setFlowEntryMatch(match);
736 }
737 //
738 // Extract the actions for the first Flow Entry
739 //
740 {
741 String actionsStr = flowObj.getActions();
742 if (actionsStr != null) {
743 FlowEntryActions flowEntryActions = new FlowEntryActions(actionsStr);
744 flowPath.setFlowEntryActions(flowEntryActions);
745 }
746 }
747
748 //
749 // Extract all Flow Entries
750 //
751 Iterable<IFlowEntry> flowEntries = flowObj.getFlowEntries();
752 for (IFlowEntry flowEntryObj : flowEntries) {
753 FlowEntry flowEntry = extractFlowEntry(flowEntryObj);
754 if (flowEntry == null)
755 continue;
756 flowPath.dataPath().flowEntries().add(flowEntry);
757 }
758
759 return flowPath;
760 }
761
762 /**
763 * Extract Flow Entry State from a Titan Database Object @ref IFlowEntry.
764 *
765 * @param flowEntryObj the object to extract the Flow Entry State from.
766 * @return the extracted Flow Entry State.
767 */
Brian O'Connora8e49802013-10-30 20:49:59 -0700768 public static FlowEntry extractFlowEntry(IFlowEntry flowEntryObj) {
Pavlin Radoslavovcf87e532013-12-13 18:17:00 -0800769 IFlowPath flowObj = flowEntryObj.getFlow();
770 if (flowObj == null)
771 return null;
772
773 String flowIdStr = flowObj.getFlowId();
774 //
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700775 String flowEntryIdStr = flowEntryObj.getFlowEntryId();
Pavlin Radoslavov5139c0b2013-12-09 18:04:53 -0800776 Integer idleTimeout = flowEntryObj.getIdleTimeout();
777 Integer hardTimeout = flowEntryObj.getHardTimeout();
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700778 String switchDpidStr = flowEntryObj.getSwitchDpid();
779 String userState = flowEntryObj.getUserState();
780 String switchState = flowEntryObj.getSwitchState();
781
Pavlin Radoslavovcf87e532013-12-13 18:17:00 -0800782 if ((flowIdStr == null) ||
783 (flowEntryIdStr == null) ||
Pavlin Radoslavov5139c0b2013-12-09 18:04:53 -0800784 (idleTimeout == null) ||
785 (hardTimeout == null) ||
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700786 (switchDpidStr == null) ||
787 (userState == null) ||
788 (switchState == null)) {
Brian O'Connora8e49802013-10-30 20:49:59 -0700789 // TODO: A work-around, because of some bogus database objects
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700790 return null;
791 }
792
793 FlowEntry flowEntry = new FlowEntry();
794 flowEntry.setFlowEntryId(new FlowEntryId(flowEntryIdStr));
Pavlin Radoslavovcf87e532013-12-13 18:17:00 -0800795 flowEntry.setFlowId(new FlowId(flowIdStr));
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700796 flowEntry.setDpid(new Dpid(switchDpidStr));
yoshia97632b2013-12-17 15:46:08 -0800797 flowEntry.setIdleTimeout(idleTimeout);
798 flowEntry.setHardTimeout(hardTimeout);
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700799
800 //
801 // Extract the match conditions
802 //
803 FlowEntryMatch match = new FlowEntryMatch();
804 Short matchInPort = flowEntryObj.getMatchInPort();
805 if (matchInPort != null)
806 match.enableInPort(new Port(matchInPort));
807 String matchSrcMac = flowEntryObj.getMatchSrcMac();
808 if (matchSrcMac != null)
809 match.enableSrcMac(MACAddress.valueOf(matchSrcMac));
810 String matchDstMac = flowEntryObj.getMatchDstMac();
811 if (matchDstMac != null)
812 match.enableDstMac(MACAddress.valueOf(matchDstMac));
813 Short matchEthernetFrameType = flowEntryObj.getMatchEthernetFrameType();
814 if (matchEthernetFrameType != null)
815 match.enableEthernetFrameType(matchEthernetFrameType);
816 Short matchVlanId = flowEntryObj.getMatchVlanId();
817 if (matchVlanId != null)
818 match.enableVlanId(matchVlanId);
819 Byte matchVlanPriority = flowEntryObj.getMatchVlanPriority();
820 if (matchVlanPriority != null)
821 match.enableVlanPriority(matchVlanPriority);
822 String matchSrcIPv4Net = flowEntryObj.getMatchSrcIPv4Net();
823 if (matchSrcIPv4Net != null)
824 match.enableSrcIPv4Net(new IPv4Net(matchSrcIPv4Net));
825 String matchDstIPv4Net = flowEntryObj.getMatchDstIPv4Net();
826 if (matchDstIPv4Net != null)
827 match.enableDstIPv4Net(new IPv4Net(matchDstIPv4Net));
828 Byte matchIpProto = flowEntryObj.getMatchIpProto();
829 if (matchIpProto != null)
830 match.enableIpProto(matchIpProto);
831 Byte matchIpToS = flowEntryObj.getMatchIpToS();
832 if (matchIpToS != null)
833 match.enableIpToS(matchIpToS);
834 Short matchSrcTcpUdpPort = flowEntryObj.getMatchSrcTcpUdpPort();
835 if (matchSrcTcpUdpPort != null)
836 match.enableSrcTcpUdpPort(matchSrcTcpUdpPort);
837 Short matchDstTcpUdpPort = flowEntryObj.getMatchDstTcpUdpPort();
838 if (matchDstTcpUdpPort != null)
839 match.enableDstTcpUdpPort(matchDstTcpUdpPort);
840 flowEntry.setFlowEntryMatch(match);
841
842 //
843 // Extract the actions
844 //
845 FlowEntryActions actions = new FlowEntryActions();
846 String actionsStr = flowEntryObj.getActions();
847 if (actionsStr != null)
848 actions = new FlowEntryActions(actionsStr);
849 flowEntry.setFlowEntryActions(actions);
850 flowEntry.setFlowEntryUserState(FlowEntryUserState.valueOf(userState));
851 flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.valueOf(switchState));
852 //
853 // TODO: Take care of FlowEntryErrorState.
854 //
855 return flowEntry;
856 }
857}