blob: af7bca8208d6116e5d44404a714c071c49163c8b [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;
Yuta HIGUCHIcb32b2a2014-01-10 18:07:33 -08007import java.util.Map;
8
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -07009import net.floodlightcontroller.util.MACAddress;
yoshitomob292c622013-11-23 14:35:58 -080010import net.onrc.onos.graph.DBOperation;
Yuta HIGUCHIcb32b2a2014-01-10 18:07:33 -080011import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IBaseObject;
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070012import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowEntry;
13import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowPath;
14import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IPortObject;
15import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.ISwitchObject;
16import net.onrc.onos.ofcontroller.util.*;
17
18import org.slf4j.Logger;
19import org.slf4j.LoggerFactory;
20
Yuta HIGUCHIdad0a2d2014-01-06 15:52:52 -080021import com.tinkerpop.blueprints.impls.ramcloud.PerfMon;
Yuta HIGUCHIcb32b2a2014-01-10 18:07:33 -080022import com.tinkerpop.blueprints.impls.ramcloud.RamCloudVertex;
Yuta HIGUCHIdad0a2d2014-01-06 15:52:52 -080023
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070024/**
25 * Class for performing Flow-related operations on the Database.
26 */
Pavlin Radoslavov6bfaea62013-12-03 14:55:57 -080027public class FlowDatabaseOperation {
Yuta HIGUCHI6ac8d182013-10-22 15:24:56 -070028 private final static Logger log = LoggerFactory.getLogger(FlowDatabaseOperation.class);
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -080029 private static final boolean measureONOSFlowTimeProp = Long.valueOf(System.getProperty("benchmark.measureONOSFlow", "0")) != 0;
30 private static final boolean measureONOSFlowEntryTimeProp = Long.valueOf(System.getProperty("benchmark.measureONOSFlowEntry", "0")) != 0;
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070031
32 /**
33 * Add a flow.
34 *
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070035 * @param dbHandler the Graph Database handler to use.
36 * @param flowPath the Flow Path to install.
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070037 * @return true on success, otherwise false.
38 */
onlab-qa38805cd2013-12-06 20:08:54 -080039 static boolean addFlow(DBOperation dbHandler, FlowPath flowPath) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070040 IFlowPath flowObj = null;
41 boolean found = false;
Yuta HIGUCHI37c55472014-01-03 11:42:27 -080042 long startAddFlow = 0;
43 long endAddFlow = 0;
44 long endSearchExistingFlowPathTime = 0;
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -080045 long startCreateNewFlowPathTime = 0;
Yuta HIGUCHI37c55472014-01-03 11:42:27 -080046 long endCreateNewFlowPathTime = 0;
47 long startFollowExistingFlowEntries = 0;
48 long endFollowExistingFlowEntries = 0;
49 long accTimeRemovingFlowEntriesFromFlowPath = 0;
50 long accTimeRemovingFlowEntriesFromDB = 0;
51 long startSettingFlowPathProps = 0;
52 long endSettingFlowPathProps = 0;
53 int numPropsSet = 0;
54 long accTimeAddFlowEntries = 0;
55 int numNewFlowEntries = 0;
56 LinkedList<long[]> flowEntryTimes = new LinkedList<>();
Yuta HIGUCHIdad0a2d2014-01-06 15:52:52 -080057 PerfMon pm = PerfMon.getInstance();
Yuta HIGUCHI37c55472014-01-03 11:42:27 -080058
Yuta HIGUCHIdad0a2d2014-01-06 15:52:52 -080059 pm.addflowpath_start();
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070060 try {
Yuta HIGUCHI37c55472014-01-03 11:42:27 -080061 if ( measureONOSFlowTimeProp ) {
62 startAddFlow = System.nanoTime();
63 }
yoshi40210942013-12-03 08:21:02 -080064 flowObj = dbHandler.searchFlowPath(flowPath.flowId());
Yuta HIGUCHI37c55472014-01-03 11:42:27 -080065 if ( measureONOSFlowTimeProp ) {
66 endSearchExistingFlowPathTime = System.nanoTime();
67 }
yoshi40210942013-12-03 08:21:02 -080068 if (flowObj != null) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070069 found = true;
70 } else {
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -080071 if ( measureONOSFlowTimeProp ) {
72 startCreateNewFlowPathTime = System.nanoTime();
73 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070074 flowObj = dbHandler.newFlowPath();
Yuta HIGUCHI37c55472014-01-03 11:42:27 -080075 if ( measureONOSFlowTimeProp ) {
76 endCreateNewFlowPathTime = System.nanoTime();
77 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070078 }
79 } catch (Exception e) {
80 dbHandler.rollback();
81
82 StringWriter sw = new StringWriter();
83 e.printStackTrace(new PrintWriter(sw));
84 String stacktrace = sw.toString();
85
86 log.error(":addFlow FlowId:{} failed: {}",
Yuta HIGUCHI5302ddf2014-01-06 12:53:35 -080087 flowPath.flowId(),
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070088 stacktrace);
89 return false;
90 }
91 if (flowObj == null) {
92 log.error(":addFlow FlowId:{} failed: Flow object not created",
Yuta HIGUCHI5302ddf2014-01-06 12:53:35 -080093 flowPath.flowId());
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070094 dbHandler.rollback();
95 return false;
96 }
97
98 //
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -080099 // Remove the old Flow Entries
100 //
101 if (found) {
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800102 if ( measureONOSFlowTimeProp ) {
103 startFollowExistingFlowEntries = System.nanoTime();
104 }
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800105 Iterable<IFlowEntry> flowEntries = flowObj.getFlowEntries();
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800106 if ( measureONOSFlowTimeProp ) {
107 endFollowExistingFlowEntries = System.nanoTime();
108 }
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800109 LinkedList<IFlowEntry> deleteFlowEntries =
110 new LinkedList<IFlowEntry>();
111 for (IFlowEntry flowEntryObj : flowEntries)
112 deleteFlowEntries.add(flowEntryObj);
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800113 if( measureONOSFlowTimeProp ) {
114 for (IFlowEntry flowEntryObj : deleteFlowEntries) {
115 long start = System.nanoTime();
116 flowObj.removeFlowEntry(flowEntryObj);
117 accTimeRemovingFlowEntriesFromFlowPath += System.nanoTime() - start;
118 start = System.nanoTime();
119 dbHandler.removeFlowEntry(flowEntryObj);
120 accTimeRemovingFlowEntriesFromDB += System.nanoTime() - start;
121 }
122 } else {
123 for (IFlowEntry flowEntryObj : deleteFlowEntries) {
124 flowObj.removeFlowEntry(flowEntryObj);
125 dbHandler.removeFlowEntry(flowEntryObj);
126 }
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800127 }
128 }
129
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800130 if ( measureONOSFlowTimeProp ) {
131 startSettingFlowPathProps = System.nanoTime();
132 }
Toshio Koidea9b25142014-01-10 01:15:57 -0800133
134 FlowPathProperty flowProp = new FlowPathProperty(dbHandler, flowObj);
135
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800136 //
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700137 // Set the Flow key:
138 // - flowId
139 //
Toshio Koidea9b25142014-01-10 01:15:57 -0800140 flowProp.setFlowId(flowPath.flowId().toString());
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800141 if ( measureONOSFlowTimeProp ) {
142 numPropsSet += 2;
143 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700144
145 //
146 // Set the Flow attributes:
147 // - flowPath.installerId()
Pavlin Radoslavovd28cf7c2013-10-26 11:27:43 -0700148 // - flowPath.flowPathType()
Pavlin Radoslavov7d4a40e2013-10-27 23:39:40 -0700149 // - flowPath.flowPathUserState()
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700150 // - flowPath.flowPathFlags()
Pavlin Radoslavov5139c0b2013-12-09 18:04:53 -0800151 // - flowPath.idleTimeout()
152 // - flowPath.hardTimeout()
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700153 // - flowPath.dataPath().srcPort()
154 // - flowPath.dataPath().dstPort()
155 // - flowPath.matchSrcMac()
156 // - flowPath.matchDstMac()
157 // - flowPath.matchEthernetFrameType()
158 // - flowPath.matchVlanId()
159 // - flowPath.matchVlanPriority()
160 // - flowPath.matchSrcIPv4Net()
161 // - flowPath.matchDstIPv4Net()
162 // - flowPath.matchIpProto()
163 // - flowPath.matchIpToS()
164 // - flowPath.matchSrcTcpUdpPort()
165 // - flowPath.matchDstTcpUdpPort()
166 // - flowPath.flowEntryActions()
167 //
Toshio Koidea9b25142014-01-10 01:15:57 -0800168 flowProp.setInstallerId(flowPath.installerId().toString());
169 flowProp.setFlowPathType(flowPath.flowPathType().toString());
170 flowProp.setFlowPathUserState(flowPath.flowPathUserState().toString());
171 flowProp.setFlowPathFlags(flowPath.flowPathFlags().flags());
172 flowProp.setIdleTimeout(flowPath.idleTimeout());
173 flowProp.setHardTimeout(flowPath.hardTimeout());
174 flowProp.setSrcSwitch(flowPath.dataPath().srcPort().dpid().toString());
175 flowProp.setSrcPort(flowPath.dataPath().srcPort().port().value());
176 flowProp.setDstSwitch(flowPath.dataPath().dstPort().dpid().toString());
177 flowProp.setDstPort(flowPath.dataPath().dstPort().port().value());
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800178 if ( measureONOSFlowTimeProp ) {
179 numPropsSet += 10;
180 }
181
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700182 if (flowPath.flowEntryMatch().matchSrcMac()) {
Toshio Koidea9b25142014-01-10 01:15:57 -0800183 flowProp.setMatchSrcMac(flowPath.flowEntryMatch().srcMac().toString());
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800184 if ( measureONOSFlowTimeProp ) {
185 ++numPropsSet;
186 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700187 }
188 if (flowPath.flowEntryMatch().matchDstMac()) {
Toshio Koidea9b25142014-01-10 01:15:57 -0800189 flowProp.setMatchDstMac(flowPath.flowEntryMatch().dstMac().toString());
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800190 if ( measureONOSFlowTimeProp ) {
191 ++numPropsSet;
192 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700193 }
194 if (flowPath.flowEntryMatch().matchEthernetFrameType()) {
Toshio Koidea9b25142014-01-10 01:15:57 -0800195 flowProp.setMatchEthernetFrameType(flowPath.flowEntryMatch().ethernetFrameType());
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800196 if ( measureONOSFlowTimeProp ) {
197 ++numPropsSet;
198 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700199 }
200 if (flowPath.flowEntryMatch().matchVlanId()) {
Toshio Koidea9b25142014-01-10 01:15:57 -0800201 flowProp.setMatchVlanId(flowPath.flowEntryMatch().vlanId());
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800202 if ( measureONOSFlowTimeProp ) {
203 ++numPropsSet;
204 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700205 }
206 if (flowPath.flowEntryMatch().matchVlanPriority()) {
Toshio Koidea9b25142014-01-10 01:15:57 -0800207 flowProp.setMatchVlanPriority(flowPath.flowEntryMatch().vlanPriority());
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800208 if ( measureONOSFlowTimeProp ) {
209 ++numPropsSet;
210 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700211 }
212 if (flowPath.flowEntryMatch().matchSrcIPv4Net()) {
Toshio Koidea9b25142014-01-10 01:15:57 -0800213 flowProp.setMatchSrcIPv4Net(flowPath.flowEntryMatch().srcIPv4Net().toString());
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800214 if ( measureONOSFlowTimeProp ) {
215 ++numPropsSet;
216 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700217 }
218 if (flowPath.flowEntryMatch().matchDstIPv4Net()) {
Toshio Koidea9b25142014-01-10 01:15:57 -0800219 flowProp.setMatchDstIPv4Net(flowPath.flowEntryMatch().dstIPv4Net().toString());
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800220 if ( measureONOSFlowTimeProp ) {
221 ++numPropsSet;
222 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700223 }
224 if (flowPath.flowEntryMatch().matchIpProto()) {
Toshio Koidea9b25142014-01-10 01:15:57 -0800225 flowProp.setMatchIpProto(flowPath.flowEntryMatch().ipProto());
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800226 if ( measureONOSFlowTimeProp ) {
227 ++numPropsSet;
228 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700229 }
230 if (flowPath.flowEntryMatch().matchIpToS()) {
Toshio Koidea9b25142014-01-10 01:15:57 -0800231 flowProp.setMatchIpToS(flowPath.flowEntryMatch().ipToS());
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800232 if ( measureONOSFlowTimeProp ) {
233 ++numPropsSet;
234 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700235 }
236 if (flowPath.flowEntryMatch().matchSrcTcpUdpPort()) {
Toshio Koidea9b25142014-01-10 01:15:57 -0800237 flowProp.setMatchSrcTcpUdpPort(flowPath.flowEntryMatch().srcTcpUdpPort());
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800238 if ( measureONOSFlowTimeProp ) {
239 ++numPropsSet;
240 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700241 }
242 if (flowPath.flowEntryMatch().matchDstTcpUdpPort()) {
Toshio Koidea9b25142014-01-10 01:15:57 -0800243 flowProp.setMatchDstTcpUdpPort(flowPath.flowEntryMatch().dstTcpUdpPort());
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800244 if ( measureONOSFlowTimeProp ) {
245 ++numPropsSet;
246 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700247 }
248 if (! flowPath.flowEntryActions().actions().isEmpty()) {
Toshio Koidea9b25142014-01-10 01:15:57 -0800249 flowProp.setActions(flowPath.flowEntryActions().toString());
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800250 if ( measureONOSFlowTimeProp ) {
251 ++numPropsSet;
252 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700253 }
Toshio Koidea9b25142014-01-10 01:15:57 -0800254 flowProp.setDataPathSummary(flowPath.dataPath().dataPathSummary());
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800255 if ( measureONOSFlowTimeProp ) {
256 ++numPropsSet;
257 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700258
259 if (found)
Toshio Koidea9b25142014-01-10 01:15:57 -0800260 flowProp.setFlowPathUserState("FP_USER_MODIFY");
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700261 else
Toshio Koidea9b25142014-01-10 01:15:57 -0800262 flowProp.setFlowPathUserState("FP_USER_ADD");
263
264 flowProp.commitProperties();
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700265
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800266 if ( measureONOSFlowTimeProp ) {
267 ++numPropsSet;
268 }
269
270 if ( measureONOSFlowTimeProp ) {
271 endSettingFlowPathProps = System.nanoTime();
272 }
Yuta HIGUCHIdad0a2d2014-01-06 15:52:52 -0800273 pm.addflowpath_end();
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700274 // Flow edges:
275 // HeadFE
276
277
278 //
279 // Flow Entries:
280 // flowPath.dataPath().flowEntries()
281 //
Yuta HIGUCHIdad0a2d2014-01-06 15:52:52 -0800282 pm.addflowentry_start();
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700283 for (FlowEntry flowEntry : flowPath.dataPath().flowEntries()) {
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800284 if (flowEntry.flowEntryUserState() == FlowEntryUserState.FE_USER_DELETE)
285 continue; // Skip: all Flow Entries were deleted earlier
286
Yuta HIGUCHIdad0a2d2014-01-06 15:52:52 -0800287 pm.addflowentry_incr();
288
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800289 long startAddFlowEntry = 0, endAddFlowEntry;
290 if( measureONOSFlowTimeProp ) {
291 startAddFlowEntry = System.nanoTime();
292 }
293 IFlowEntry iFlowEntry = addFlowEntry(dbHandler, flowObj, flowEntry);
294 if( measureONOSFlowTimeProp ) {
295 endAddFlowEntry = System.nanoTime();
296 accTimeAddFlowEntries += endAddFlowEntry - startAddFlowEntry;
297
298 flowEntryTimes.addLast( new long[]{flowEntry.flowId().value(), endAddFlowEntry - startAddFlowEntry} );
299 }
300 if ( iFlowEntry == null) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700301 dbHandler.rollback();
302 return false;
303 }
304 }
Yuta HIGUCHIdad0a2d2014-01-06 15:52:52 -0800305 pm.addflowentry_end();
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700306 dbHandler.commit();
307
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800308
309 if ( measureONOSFlowTimeProp ) {
310 endAddFlow = System.nanoTime();
311
Yuta HIGUCHI0b4fbaf2014-01-04 22:23:05 -0800312 log.error("Performance addFlow(_,{}) -- "
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800313 + "GrandTotal: {} "
314 + "only FlowPathTotal: {} "
315 + "searchExistingFlowPath: {} "
316 + "createNewFlowPathTime: {}"
317 + "followExistingFlowEntries: {} "
318 + "accTimeRemovingFlowEntriesFromFlowPath: {} "
319 + "accTimeRemovingFlowEntriesFromDB: {} "
320 + "settingFlowPathProps: {} #Props: {} "
321 + "accFlowEntries: {} #FEs: {}",
322 flowPath.flowId(),
323 (endAddFlow - startAddFlow),
324 (endSettingFlowPathProps - startAddFlow),
325 (endSearchExistingFlowPathTime - startAddFlow),
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800326 (endCreateNewFlowPathTime - startCreateNewFlowPathTime),
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800327 (endFollowExistingFlowEntries - startFollowExistingFlowEntries),
328 (accTimeRemovingFlowEntriesFromFlowPath),
329 (accTimeRemovingFlowEntriesFromDB),
330 (endSettingFlowPathProps - startSettingFlowPathProps), numPropsSet,
331 accTimeAddFlowEntries, numNewFlowEntries
332 );
333
334 // Each FlowEntries
335 final String strFlowId = flowPath.flowId().toString();
336 for ( long[] idFE_Time : flowEntryTimes ) {
Yuta HIGUCHI0b4fbaf2014-01-04 22:23:05 -0800337 log.error("Performance addFlowEntry(_,{},{})@addFlow -- FlowEntryTotal: {}",
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800338 strFlowId,
339 "0x" + Long.toHexString(idFE_Time[0]),
340 idFE_Time[1]);
341 }
342 }
343
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700344 return true;
345 }
346
347 /**
348 * Add a flow entry to the Network MAP.
349 *
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700350 * @param dbHandler the Graph Database handler to use.
351 * @param flowObj the corresponding Flow Path object for the Flow Entry.
352 * @param flowEntry the Flow Entry to install.
353 * @return the added Flow Entry object on success, otherwise null.
354 */
onlab-qa38805cd2013-12-06 20:08:54 -0800355 static IFlowEntry addFlowEntry(DBOperation dbHandler,
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700356 IFlowPath flowObj,
357 FlowEntry flowEntry) {
358 // Flow edges
359 // HeadFE (TODO)
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800360 long startAddFlowEntry = 0;
361 long endAddFlowEntry = 0;
362
363 long endSearchFlowEntry = 0;
364
365 long startCreateNewFlowEntry = 0;
366 long endCreateNewFlowEntry = 0;
367
368 long startSetProperties = 0;
369 long endSetProperties = 0;
370 int numProperties = 0;
371
372 long startSearchSwitch = 0;
373 long endSearchSwitch = 0;
374
375 long startAddEdgeToSwitch =0;
376 long endAddEdgeToSwitch =0;
377
378 long startSearchInPort = 0;
379 long endSearchInPort = 0;
380
381 long startAddEdgeToInPort =0;
382 long endAddEdgeToInPort =0;
383
384 long startSearchOutPort = 0;
385 long endSearchOutPort = 0;
386
387 long startAddEdgeToOutPort =0;
388 long endAddEdgeToOutPort =0;
389
390 long startAddEdgeBetweenFlowPath = 0;
391 long endAddEdgeBetweenFlowPath = 0;
392
393 if (measureONOSFlowEntryTimeProp) {
394 startAddFlowEntry = System.nanoTime();
395 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700396
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700397 IFlowEntry flowEntryObj = null;
398 boolean found = false;
399 try {
Yuta HIGUCHIc27a6c92014-01-07 11:51:11 -0800400 flowEntryObj = dbHandler.searchFlowEntry(flowEntry.flowEntryId());
401 if (measureONOSFlowEntryTimeProp) {
402 endSearchFlowEntry = System.nanoTime();
403 }
404 if (flowEntryObj != null) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700405 found = true;
406 } else {
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800407 if (measureONOSFlowEntryTimeProp) {
408 startCreateNewFlowEntry = System.nanoTime();
409 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700410 flowEntryObj = dbHandler.newFlowEntry();
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800411 if (measureONOSFlowEntryTimeProp) {
412 endCreateNewFlowEntry = System.nanoTime();
413 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700414 }
415 } catch (Exception e) {
416 log.error(":addFlow FlowEntryId:{} failed",
Yuta HIGUCHI5302ddf2014-01-06 12:53:35 -0800417 flowEntry.flowEntryId());
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700418 return null;
419 }
420 if (flowEntryObj == null) {
421 log.error(":addFlow FlowEntryId:{} failed: FlowEntry object not created",
Yuta HIGUCHI5302ddf2014-01-06 12:53:35 -0800422 flowEntry.flowEntryId());
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700423 return null;
424 }
425
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800426 if (measureONOSFlowEntryTimeProp) {
427 startSetProperties = System.nanoTime();
428 }
Yuta HIGUCHI8685f9c2014-01-07 15:53:28 -0800429
Toshio Koide7f76e9e2014-01-09 22:06:35 -0800430 FlowEntryProperty flowProp = new FlowEntryProperty(dbHandler, flowEntryObj);
Yuta HIGUCHI8685f9c2014-01-07 15:53:28 -0800431
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700432 //
433 // Set the Flow Entry key:
434 // - flowEntry.flowEntryId()
435 //
Toshio Koide3f233542014-01-07 14:19:09 -0800436 flowProp.setFlowEntryId(flowEntry.flowEntryId().toString());
437 flowProp.setType("flow_entry");
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800438 if (measureONOSFlowEntryTimeProp) {
439 numProperties += 2;
440 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700441
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800442 //
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700443 // Set the Flow Entry Edges and attributes:
444 // - Switch edge
445 // - InPort edge
446 // - OutPort edge
447 //
Pavlin Radoslavov5139c0b2013-12-09 18:04:53 -0800448 // - flowEntry.idleTimeout()
449 // - flowEntry.hardTimeout()
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700450 // - flowEntry.dpid()
451 // - flowEntry.flowEntryUserState()
452 // - flowEntry.flowEntrySwitchState()
453 // - flowEntry.flowEntryErrorState()
454 // - flowEntry.matchInPort()
455 // - flowEntry.matchSrcMac()
456 // - flowEntry.matchDstMac()
457 // - flowEntry.matchEthernetFrameType()
458 // - flowEntry.matchVlanId()
459 // - flowEntry.matchVlanPriority()
460 // - flowEntry.matchSrcIPv4Net()
461 // - flowEntry.matchDstIPv4Net()
462 // - flowEntry.matchIpProto()
463 // - flowEntry.matchIpToS()
464 // - flowEntry.matchSrcTcpUdpPort()
465 // - flowEntry.matchDstTcpUdpPort()
466 // - flowEntry.actionOutputPort()
467 // - flowEntry.actions()
468 //
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800469 if (measureONOSFlowEntryTimeProp) {
470 startSearchSwitch = System.nanoTime();
471 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700472 ISwitchObject sw = dbHandler.searchSwitch(flowEntry.dpid().toString());
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800473 if (measureONOSFlowEntryTimeProp) {
474 endSearchSwitch = System.nanoTime();
475 }
476
Toshio Koide3f233542014-01-07 14:19:09 -0800477 flowProp.setIdleTimeout(flowEntry.idleTimeout());
478 flowProp.setHardTimeout(flowEntry.hardTimeout());
479 flowProp.setSwitchDpid(flowEntry.dpid().toString());
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800480 if (measureONOSFlowEntryTimeProp) {
481 numProperties += 3;
482 }
483
484 if (measureONOSFlowEntryTimeProp) {
485 startAddEdgeToSwitch = System.nanoTime();
486 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700487 flowEntryObj.setSwitch(sw);
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800488 if (measureONOSFlowEntryTimeProp) {
489 endAddEdgeToSwitch = System.nanoTime();
490 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700491 if (flowEntry.flowEntryMatch().matchInPort()) {
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800492 if (measureONOSFlowEntryTimeProp) {
493 startSearchInPort = System.nanoTime();
494 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700495 IPortObject inport =
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800496 dbHandler.searchPort(flowEntry.dpid().toString(),
497 flowEntry.flowEntryMatch().inPort().value());
498 if (measureONOSFlowEntryTimeProp) {
499 endSearchInPort = System.nanoTime();
500 }
501
Toshio Koide3f233542014-01-07 14:19:09 -0800502 flowProp.setMatchInPort(flowEntry.flowEntryMatch().inPort().value());
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800503 if (measureONOSFlowEntryTimeProp) {
504 ++numProperties;
505 }
506
507 if (measureONOSFlowEntryTimeProp) {
508 startAddEdgeToInPort = System.nanoTime();
509 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700510 flowEntryObj.setInPort(inport);
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800511 if (measureONOSFlowEntryTimeProp) {
512 endAddEdgeToInPort = System.nanoTime();
513 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700514 }
515 if (flowEntry.flowEntryMatch().matchSrcMac()) {
Toshio Koide3f233542014-01-07 14:19:09 -0800516 flowProp.setMatchSrcMac(flowEntry.flowEntryMatch().srcMac().toString());
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800517 if (measureONOSFlowEntryTimeProp) {
518 ++numProperties;
519 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700520 }
521 if (flowEntry.flowEntryMatch().matchDstMac()) {
Toshio Koide3f233542014-01-07 14:19:09 -0800522 flowProp.setMatchDstMac(flowEntry.flowEntryMatch().dstMac().toString());
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800523 if (measureONOSFlowEntryTimeProp) {
524 ++numProperties;
525 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700526 }
527 if (flowEntry.flowEntryMatch().matchEthernetFrameType()) {
Toshio Koide3f233542014-01-07 14:19:09 -0800528 flowProp.setMatchEthernetFrameType(flowEntry.flowEntryMatch().ethernetFrameType());
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800529 if (measureONOSFlowEntryTimeProp) {
530 ++numProperties;
531 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700532 }
533 if (flowEntry.flowEntryMatch().matchVlanId()) {
Toshio Koide3f233542014-01-07 14:19:09 -0800534 flowProp.setMatchVlanId(flowEntry.flowEntryMatch().vlanId());
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800535 if (measureONOSFlowEntryTimeProp) {
536 ++numProperties;
537 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700538 }
539 if (flowEntry.flowEntryMatch().matchVlanPriority()) {
Toshio Koide3f233542014-01-07 14:19:09 -0800540 flowProp.setMatchVlanPriority(flowEntry.flowEntryMatch().vlanPriority());
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800541 if (measureONOSFlowEntryTimeProp) {
542 ++numProperties;
543 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700544 }
545 if (flowEntry.flowEntryMatch().matchSrcIPv4Net()) {
Toshio Koide3f233542014-01-07 14:19:09 -0800546 flowProp.setMatchSrcIPv4Net(flowEntry.flowEntryMatch().srcIPv4Net().toString());
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800547 if (measureONOSFlowEntryTimeProp) {
548 ++numProperties;
549 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700550 }
551 if (flowEntry.flowEntryMatch().matchDstIPv4Net()) {
Toshio Koide3f233542014-01-07 14:19:09 -0800552 flowProp.setMatchDstIPv4Net(flowEntry.flowEntryMatch().dstIPv4Net().toString());
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800553 if (measureONOSFlowEntryTimeProp) {
554 ++numProperties;
555 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700556 }
557 if (flowEntry.flowEntryMatch().matchIpProto()) {
Toshio Koide3f233542014-01-07 14:19:09 -0800558 flowProp.setMatchIpProto(flowEntry.flowEntryMatch().ipProto());
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800559 if (measureONOSFlowEntryTimeProp) {
560 ++numProperties;
561 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700562 }
563 if (flowEntry.flowEntryMatch().matchIpToS()) {
Toshio Koide3f233542014-01-07 14:19:09 -0800564 flowProp.setMatchIpToS(flowEntry.flowEntryMatch().ipToS());
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800565 if (measureONOSFlowEntryTimeProp) {
566 ++numProperties;
567 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700568 }
569 if (flowEntry.flowEntryMatch().matchSrcTcpUdpPort()) {
Toshio Koide3f233542014-01-07 14:19:09 -0800570 flowProp.setMatchSrcTcpUdpPort(flowEntry.flowEntryMatch().srcTcpUdpPort());
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800571 if (measureONOSFlowEntryTimeProp) {
572 ++numProperties;
573 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700574 }
575 if (flowEntry.flowEntryMatch().matchDstTcpUdpPort()) {
Toshio Koide3f233542014-01-07 14:19:09 -0800576 flowProp.setMatchDstTcpUdpPort(flowEntry.flowEntryMatch().dstTcpUdpPort());
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800577 if (measureONOSFlowEntryTimeProp) {
578 ++numProperties;
579 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700580 }
581
582 for (FlowEntryAction fa : flowEntry.flowEntryActions().actions()) {
583 if (fa.actionOutput() != null) {
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800584 if (measureONOSFlowEntryTimeProp) {
585 if ( startSearchOutPort != 0 ) log.error("Performance addFlowEntry(_,{},{}) -- Multiple output port action unexpected.", flowEntry.flowId(), flowEntry.flowEntryId());
586 startSearchOutPort = System.nanoTime();
587 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700588 IPortObject outport =
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800589 dbHandler.searchPort(flowEntry.dpid().toString(),
590 fa.actionOutput().port().value());
591 if (measureONOSFlowEntryTimeProp) {
592 endSearchOutPort = System.nanoTime();
593 }
594
Toshio Koide3f233542014-01-07 14:19:09 -0800595 flowProp.setActionOutputPort(fa.actionOutput().port().value());
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800596 if (measureONOSFlowEntryTimeProp) {
597 ++numProperties;
598 }
599
600 if (measureONOSFlowEntryTimeProp) {
601 startAddEdgeToOutPort = System.nanoTime();
602 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700603 flowEntryObj.setOutPort(outport);
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800604 if (measureONOSFlowEntryTimeProp) {
605 endAddEdgeToOutPort = System.nanoTime();
606 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700607 }
608 }
609 if (! flowEntry.flowEntryActions().isEmpty()) {
Toshio Koide3f233542014-01-07 14:19:09 -0800610 flowProp.setActions(flowEntry.flowEntryActions().toString());
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800611 if (measureONOSFlowEntryTimeProp) {
612 ++numProperties;
613 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700614 }
615
616 // TODO: Hacks with hard-coded state names!
617 if (found)
Toshio Koide3f233542014-01-07 14:19:09 -0800618 flowProp.setUserState("FE_USER_MODIFY");
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700619 else
Toshio Koide3f233542014-01-07 14:19:09 -0800620 flowProp.setUserState("FE_USER_ADD");
621 flowProp.setSwitchState(flowEntry.flowEntrySwitchState().toString());
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800622 if (measureONOSFlowEntryTimeProp) {
623 numProperties += 2;
624 }
Yuta HIGUCHI8685f9c2014-01-07 15:53:28 -0800625 flowProp.commitProperties();
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700626 //
627 // TODO: Take care of the FlowEntryErrorState.
628 //
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800629 if (measureONOSFlowEntryTimeProp) {
630 endSetProperties = System.nanoTime();
631 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700632
633 // Flow Entries edges:
634 // Flow
635 // NextFE (TODO)
636 if (! found) {
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800637 if (measureONOSFlowEntryTimeProp) {
638 startAddEdgeBetweenFlowPath = System.nanoTime();
639 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700640 flowObj.addFlowEntry(flowEntryObj);
641 flowEntryObj.setFlow(flowObj);
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800642 if (measureONOSFlowEntryTimeProp) {
643 endAddEdgeBetweenFlowPath = System.nanoTime();
644 }
645 }
646 if (measureONOSFlowEntryTimeProp) {
647 endAddFlowEntry = System.nanoTime();
648
649 log.error("Performance addFlowEntry(_,{},{}) -- "
650 + "GrandTotal: {} "
651 + "SearchExistingFE: {} "
652 + "CreateNewFE: {} "
653 + "SetProp+Edge: {} #Props: {} "
654 + "SearchSwitch: {} "
655 + "AddEdgeToSwitch: {} "
656 + "SearchInPort: {} "
657 + "AddEdgeToInPort: {} "
658 + "SearchOutPort: {} "
659 + "AddEdgeToOutPort: {} "
660 + "AddEdgeBetweenFlowPath: {} "
661 , flowEntry.flowId(), flowEntry.flowEntryId()
662 , endAddFlowEntry - startAddFlowEntry
663 , endSearchFlowEntry - startAddFlowEntry
664 , endCreateNewFlowEntry - startCreateNewFlowEntry
665 , endSetProperties - startSetProperties, numProperties
666 , endSearchSwitch - startSearchSwitch
667 , endAddEdgeToSwitch - startAddEdgeToSwitch
668 , endSearchInPort - startSearchInPort
669 , endAddEdgeToInPort - startAddEdgeToInPort
670 , endSearchOutPort - startSearchOutPort
671 , endAddEdgeToOutPort - startAddEdgeToOutPort
672 , endAddEdgeBetweenFlowPath - startAddEdgeBetweenFlowPath
673 );
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700674 }
675
676 return flowEntryObj;
677 }
678
679 /**
Pavlin Radoslavov7407ab52013-11-01 22:19:00 -0700680 * Delete a flow entry from the Network MAP.
681 *
682 * @param dbHandler the Graph Database handler to use.
683 * @param flowObj the corresponding Flow Path object for the Flow Entry.
684 * @param flowEntry the Flow Entry to delete.
685 * @return true on success, otherwise false.
686 */
yoshitomob292c622013-11-23 14:35:58 -0800687 static boolean deleteFlowEntry(DBOperation dbHandler,
Pavlin Radoslavov7407ab52013-11-01 22:19:00 -0700688 IFlowPath flowObj,
689 FlowEntry flowEntry) {
690 IFlowEntry flowEntryObj = null;
691 try {
692 flowEntryObj = dbHandler.searchFlowEntry(flowEntry.flowEntryId());
693 } catch (Exception e) {
694 log.error(":deleteFlowEntry FlowEntryId:{} failed",
Yuta HIGUCHI5302ddf2014-01-06 12:53:35 -0800695 flowEntry.flowEntryId());
Pavlin Radoslavov7407ab52013-11-01 22:19:00 -0700696 return false;
697 }
698 //
699 // TODO: Don't print an error for now, because multiple controller
700 // instances might be deleting the same flow entry.
701 //
702 /*
703 if (flowEntryObj == null) {
704 log.error(":deleteFlowEntry FlowEntryId:{} failed: FlowEntry object not found",
Yuta HIGUCHI5302ddf2014-01-06 12:53:35 -0800705 flowEntry.flowEntryId());
Pavlin Radoslavov7407ab52013-11-01 22:19:00 -0700706 return false;
707 }
708 */
709 if (flowEntryObj == null)
710 return true;
711
712 flowObj.removeFlowEntry(flowEntryObj);
713 dbHandler.removeFlowEntry(flowEntryObj);
714 return true;
715 }
716
717 /**
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700718 * Delete all previously added flows.
719 *
720 * @param dbHandler the Graph Database handler to use.
721 * @return true on success, otherwise false.
722 */
yoshitomob292c622013-11-23 14:35:58 -0800723 static boolean deleteAllFlows(DBOperation dbHandler) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700724 Iterable<IFlowPath> allFlowPaths = dbHandler.getAllFlowPaths();
725 for (IFlowPath flowPathObj : allFlowPaths) {
726 if (flowPathObj == null)
727 continue;
Yuta HIGUCHI53794052014-01-10 16:49:41 -0800728 deleteIFlowPath(dbHandler, flowPathObj);
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700729 }
730
731 return true;
732 }
733
734 /**
Pavlin Radoslavovf2a52652013-11-22 12:35:42 -0800735 * Delete a previously added flow.
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700736 *
737 * @param dbHandler the Graph Database handler to use.
Pavlin Radoslavovf2a52652013-11-22 12:35:42 -0800738 * @param flowId the Flow ID of the flow to delete.
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700739 * @return true on success, otherwise false.
740 */
yoshitomob292c622013-11-23 14:35:58 -0800741 static boolean deleteFlow(DBOperation dbHandler, FlowId flowId) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700742 IFlowPath flowObj = null;
743 try {
744 flowObj = dbHandler.searchFlowPath(flowId);
745 } catch (Exception e) {
746 // TODO: handle exceptions
747 dbHandler.rollback();
Yuta HIGUCHI5302ddf2014-01-06 12:53:35 -0800748 log.error(":deleteFlow FlowId:{} failed", flowId);
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700749 return false;
750 }
751 if (flowObj == null) {
752 dbHandler.commit();
753 return true; // OK: No such flow
754 }
755
Yuta HIGUCHI53794052014-01-10 16:49:41 -0800756 deleteIFlowPath(dbHandler, flowObj);
757
758 return true;
759 }
760
761 private static void deleteIFlowPath(DBOperation dbHandler, IFlowPath flowObj) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700762 //
763 // Remove all Flow Entries
764 //
765 Iterable<IFlowEntry> flowEntries = flowObj.getFlowEntries();
766 for (IFlowEntry flowEntryObj : flowEntries) {
767 flowObj.removeFlowEntry(flowEntryObj);
768 dbHandler.removeFlowEntry(flowEntryObj);
769 }
770 // Remove the Flow itself
771 dbHandler.removeFlowPath(flowObj);
772 dbHandler.commit();
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700773 }
774
775 /**
776 * Get a previously added flow.
777 *
778 * @param dbHandler the Graph Database handler to use.
779 * @param flowId the Flow ID of the flow to get.
780 * @return the Flow Path if found, otherwise null.
781 */
yoshitomob292c622013-11-23 14:35:58 -0800782 static FlowPath getFlow(DBOperation dbHandler, FlowId flowId) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700783 IFlowPath flowObj = null;
784 try {
785 flowObj = dbHandler.searchFlowPath(flowId);
786 } catch (Exception e) {
787 // TODO: handle exceptions
788 dbHandler.rollback();
Yuta HIGUCHI5302ddf2014-01-06 12:53:35 -0800789 log.error(":getFlow FlowId:{} failed", flowId);
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700790 return null;
791 }
792 if (flowObj == null) {
793 dbHandler.commit();
794 return null; // Flow not found
795 }
796
797 //
798 // Extract the Flow state
799 //
800 FlowPath flowPath = extractFlowPath(flowObj);
801 dbHandler.commit();
802
803 return flowPath;
804 }
805
806 /**
807 * Get all installed flows by all installers.
808 *
809 * @param dbHandler the Graph Database handler to use.
810 * @return the Flow Paths if found, otherwise null.
811 */
yoshitomob292c622013-11-23 14:35:58 -0800812 static ArrayList<FlowPath> getAllFlows(DBOperation dbHandler) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700813 Iterable<IFlowPath> flowPathsObj = null;
814 ArrayList<FlowPath> flowPaths = new ArrayList<FlowPath>();
815
816 try {
817 flowPathsObj = dbHandler.getAllFlowPaths();
818 } catch (Exception e) {
819 // TODO: handle exceptions
820 dbHandler.rollback();
821 log.error(":getAllFlowPaths failed");
822 return flowPaths;
823 }
824 if ((flowPathsObj == null) || (flowPathsObj.iterator().hasNext() == false)) {
825 dbHandler.commit();
826 return flowPaths; // No Flows found
827 }
828
829 for (IFlowPath flowObj : flowPathsObj) {
830 //
831 // Extract the Flow state
832 //
833 FlowPath flowPath = extractFlowPath(flowObj);
834 if (flowPath != null)
835 flowPaths.add(flowPath);
836 }
837
838 dbHandler.commit();
839
840 return flowPaths;
841 }
842
843 /**
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700844 * Extract Flow Path State from a Titan Database Object @ref IFlowPath.
845 *
846 * @param flowObj the object to extract the Flow Path State from.
847 * @return the extracted Flow Path State.
848 */
849 private static FlowPath extractFlowPath(IFlowPath flowObj) {
850 //
851 // Extract the Flow state
852 //
Toshio Koidea9b25142014-01-10 01:15:57 -0800853 log.info("extractFlowPath: start");
Yuta HIGUCHIcb32b2a2014-01-10 18:07:33 -0800854 String flowIdStr;
855 String installerIdStr;
856 String flowPathType;
857 String flowPathUserState;
858 Long flowPathFlags;
859 Integer idleTimeout;
860 Integer hardTimeout;
861 String srcSwitchStr;
862 Short srcPortShort;
863 String dstSwitchStr;
864 Short dstPortShort;
865
866 if ( flowObj.asVertex() instanceof RamCloudVertex ) {
867 RamCloudVertex v = (RamCloudVertex)flowObj.asVertex();
868 Map<String,Object> propMap = v.getProperties();
869
870 flowIdStr = (String) propMap.get("flow_id");
871 installerIdStr = (String) propMap.get("installer_id");
872 flowPathType = (String) propMap.get("flow_path_type");
873 flowPathUserState = (String) propMap.get("user_state");
874 flowPathFlags = (Long)propMap.get("flow_path_flags");
875 idleTimeout = (Integer) propMap.get("idle_timeout");
876 hardTimeout = (Integer) propMap.get("hard_timeout");
877 srcSwitchStr = (String) propMap.get("src_switch");
878 srcPortShort = (Short)propMap.get("src_port");
879 dstSwitchStr = (String) propMap.get("dst_switch");
880 dstPortShort = (Short)propMap.get("dst_port");
881 } else {
882 flowIdStr = flowObj.getFlowId();
883 installerIdStr = flowObj.getInstallerId();
884 flowPathType = flowObj.getFlowPathType();
885 flowPathUserState = flowObj.getFlowPathUserState();
886 flowPathFlags = flowObj.getFlowPathFlags();
887 idleTimeout = flowObj.getIdleTimeout();
888 hardTimeout = flowObj.getHardTimeout();
889 srcSwitchStr = flowObj.getSrcSwitch();
890 srcPortShort = flowObj.getSrcPort();
891 dstSwitchStr = flowObj.getDstSwitch();
892 dstPortShort = flowObj.getDstPort();
893 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700894
895 if ((flowIdStr == null) ||
896 (installerIdStr == null) ||
Pavlin Radoslavovd28cf7c2013-10-26 11:27:43 -0700897 (flowPathType == null) ||
Pavlin Radoslavov7d4a40e2013-10-27 23:39:40 -0700898 (flowPathUserState == null) ||
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700899 (flowPathFlags == null) ||
Pavlin Radoslavov5139c0b2013-12-09 18:04:53 -0800900 (idleTimeout == null) ||
901 (hardTimeout == null) ||
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700902 (srcSwitchStr == null) ||
903 (srcPortShort == null) ||
904 (dstSwitchStr == null) ||
905 (dstPortShort == null)) {
Toshio Koidea9b25142014-01-10 01:15:57 -0800906 // TODO: A work-around, because of some bogus database objects
907 log.error("extractFlowPath: wrong properties");
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700908 return null;
909 }
910
911 FlowPath flowPath = new FlowPath();
912 flowPath.setFlowId(new FlowId(flowIdStr));
913 flowPath.setInstallerId(new CallerId(installerIdStr));
Pavlin Radoslavovd28cf7c2013-10-26 11:27:43 -0700914 flowPath.setFlowPathType(FlowPathType.valueOf(flowPathType));
Pavlin Radoslavov7d4a40e2013-10-27 23:39:40 -0700915 flowPath.setFlowPathUserState(FlowPathUserState.valueOf(flowPathUserState));
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700916 flowPath.setFlowPathFlags(new FlowPathFlags(flowPathFlags));
Pavlin Radoslavov5139c0b2013-12-09 18:04:53 -0800917 flowPath.setIdleTimeout(idleTimeout);
918 flowPath.setHardTimeout(hardTimeout);
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700919 flowPath.dataPath().srcPort().setDpid(new Dpid(srcSwitchStr));
920 flowPath.dataPath().srcPort().setPort(new Port(srcPortShort));
921 flowPath.dataPath().dstPort().setDpid(new Dpid(dstSwitchStr));
922 flowPath.dataPath().dstPort().setPort(new Port(dstPortShort));
923 //
924 // Extract the match conditions common for all Flow Entries
925 //
926 {
Yuta HIGUCHIcb32b2a2014-01-10 18:07:33 -0800927 FlowEntryMatch match = extractMatch(flowObj);
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700928
929 flowPath.setFlowEntryMatch(match);
930 }
931 //
932 // Extract the actions for the first Flow Entry
933 //
934 {
935 String actionsStr = flowObj.getActions();
936 if (actionsStr != null) {
937 FlowEntryActions flowEntryActions = new FlowEntryActions(actionsStr);
938 flowPath.setFlowEntryActions(flowEntryActions);
939 }
940 }
941
942 //
943 // Extract all Flow Entries
944 //
945 Iterable<IFlowEntry> flowEntries = flowObj.getFlowEntries();
946 for (IFlowEntry flowEntryObj : flowEntries) {
947 FlowEntry flowEntry = extractFlowEntry(flowEntryObj);
948 if (flowEntry == null)
949 continue;
950 flowPath.dataPath().flowEntries().add(flowEntry);
951 }
952
Toshio Koidea9b25142014-01-10 01:15:57 -0800953 log.info("extractFlowPath: end");
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700954 return flowPath;
955 }
956
957 /**
958 * Extract Flow Entry State from a Titan Database Object @ref IFlowEntry.
959 *
960 * @param flowEntryObj the object to extract the Flow Entry State from.
961 * @return the extracted Flow Entry State.
962 */
Brian O'Connora8e49802013-10-30 20:49:59 -0700963 public static FlowEntry extractFlowEntry(IFlowEntry flowEntryObj) {
Toshio Koidea9b25142014-01-10 01:15:57 -0800964 log.info("extractFlowEntry: start");
Pavlin Radoslavovcf87e532013-12-13 18:17:00 -0800965 IFlowPath flowObj = flowEntryObj.getFlow();
Toshio Koidea9b25142014-01-10 01:15:57 -0800966 if (flowObj == null) {
967 log.error("extractFlowEntry: no flowPath exists");
Pavlin Radoslavovcf87e532013-12-13 18:17:00 -0800968 return null;
Toshio Koidea9b25142014-01-10 01:15:57 -0800969 }
Pavlin Radoslavovcf87e532013-12-13 18:17:00 -0800970
971 String flowIdStr = flowObj.getFlowId();
972 //
Yuta HIGUCHIcb32b2a2014-01-10 18:07:33 -0800973 String flowEntryIdStr;
974 Integer idleTimeout;
975 Integer hardTimeout;
976 String switchDpidStr;
977 String userState;
978 String switchState;
979 if ( flowEntryObj.asVertex() instanceof RamCloudVertex ) {
980 RamCloudVertex v = (RamCloudVertex)flowEntryObj.asVertex();
981 Map<String,Object> propMap = v.getProperties();
982
983 flowEntryIdStr = (String) propMap.get("flow_entry_id");
984 idleTimeout = (Integer) propMap.get("idle_timeout");
985 hardTimeout = (Integer) propMap.get("hard_timeout");
986 switchDpidStr = (String) propMap.get("switch_dpid");
987 userState = (String) propMap.get("user_state");
988 switchState = (String) propMap.get("switch_state");
989 } else {
990 flowEntryIdStr = flowEntryObj.getFlowEntryId();
991 idleTimeout = flowEntryObj.getIdleTimeout();
992 hardTimeout = flowEntryObj.getHardTimeout();
993 switchDpidStr = flowEntryObj.getSwitchDpid();
994 userState = flowEntryObj.getUserState();
995 switchState = flowEntryObj.getSwitchState();
996 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700997
Pavlin Radoslavovcf87e532013-12-13 18:17:00 -0800998 if ((flowIdStr == null) ||
999 (flowEntryIdStr == null) ||
Pavlin Radoslavov5139c0b2013-12-09 18:04:53 -08001000 (idleTimeout == null) ||
1001 (hardTimeout == null) ||
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -07001002 (switchDpidStr == null) ||
1003 (userState == null) ||
1004 (switchState == null)) {
Brian O'Connora8e49802013-10-30 20:49:59 -07001005 // TODO: A work-around, because of some bogus database objects
Toshio Koidea9b25142014-01-10 01:15:57 -08001006 log.error("extractFlowEntry: wrong properties");
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -07001007 return null;
1008 }
1009
1010 FlowEntry flowEntry = new FlowEntry();
1011 flowEntry.setFlowEntryId(new FlowEntryId(flowEntryIdStr));
Pavlin Radoslavovcf87e532013-12-13 18:17:00 -08001012 flowEntry.setFlowId(new FlowId(flowIdStr));
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -07001013 flowEntry.setDpid(new Dpid(switchDpidStr));
yoshia97632b2013-12-17 15:46:08 -08001014 flowEntry.setIdleTimeout(idleTimeout);
1015 flowEntry.setHardTimeout(hardTimeout);
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -07001016
1017 //
1018 // Extract the match conditions
1019 //
Yuta HIGUCHIcb32b2a2014-01-10 18:07:33 -08001020 FlowEntryMatch match = extractMatch(flowEntryObj);
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -07001021 flowEntry.setFlowEntryMatch(match);
1022
1023 //
1024 // Extract the actions
1025 //
1026 FlowEntryActions actions = new FlowEntryActions();
1027 String actionsStr = flowEntryObj.getActions();
1028 if (actionsStr != null)
1029 actions = new FlowEntryActions(actionsStr);
1030 flowEntry.setFlowEntryActions(actions);
1031 flowEntry.setFlowEntryUserState(FlowEntryUserState.valueOf(userState));
1032 flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.valueOf(switchState));
1033 //
1034 // TODO: Take care of FlowEntryErrorState.
1035 //
Toshio Koidea9b25142014-01-10 01:15:57 -08001036 log.info("extractFlowEntry: end");
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -07001037 return flowEntry;
1038 }
Yuta HIGUCHIcb32b2a2014-01-10 18:07:33 -08001039
1040 /**
1041 * Extract FlowEntryMatch from IFlowPath or IFlowEntry
1042 * @param flowObj : either IFlowPath or IFlowEntry
1043 * @return extracted Match info
1044 */
1045 private static FlowEntryMatch extractMatch(IBaseObject flowObj) {
1046 FlowEntryMatch match = new FlowEntryMatch();
1047
1048 Short matchInPort = null; // Only for IFlowEntry
1049 String matchSrcMac = null;
1050 String matchDstMac = null;
1051 Short matchEthernetFrameType = null;
1052 Short matchVlanId = null;
1053 Byte matchVlanPriority = null;
1054 String matchSrcIPv4Net = null;
1055 String matchDstIPv4Net = null;
1056 Byte matchIpProto = null;
1057 Byte matchIpToS = null;
1058 Short matchSrcTcpUdpPort = null;
1059 Short matchDstTcpUdpPort = null;
1060
1061 if ( flowObj.asVertex() instanceof RamCloudVertex ) {
1062 RamCloudVertex v = (RamCloudVertex)flowObj.asVertex();
1063 Map<String,Object> propMap = v.getProperties();
1064 matchInPort = (Short) propMap.get("matchInPort");
1065 matchSrcMac = (String) propMap.get("matchSrcMac");
1066 matchDstMac = (String) propMap.get("matchDstMac");
1067 matchEthernetFrameType = (Short) propMap.get("matchEthernetFrameType");
1068 matchVlanId = (Short) propMap.get("matchVlanId");
1069 matchVlanPriority = (Byte) propMap.get("matchVlanPriority");
1070 matchSrcIPv4Net = (String) propMap.get("matchSrcIPv4Net");
1071 matchDstIPv4Net = (String) propMap.get("matchDstIPv4Net");
1072 matchIpProto = (Byte) propMap.get("matchIpProto");
1073 matchIpToS = (Byte) propMap.get("matchIpToS");
1074 matchSrcTcpUdpPort = (Short) propMap.get("matchSrcTcpUdpPort");
1075 matchDstTcpUdpPort = (Short) propMap.get("matchDstTcpUdpPort");
1076 } else {
1077 if (flowObj instanceof IFlowEntry ){
1078 IFlowEntry flowEntry = (IFlowEntry) flowObj;
1079 matchInPort = flowEntry.getMatchInPort();
1080 matchSrcMac = flowEntry.getMatchSrcMac();
1081 matchDstMac = flowEntry.getMatchDstMac();
1082 matchEthernetFrameType = flowEntry.getMatchEthernetFrameType();
1083 matchVlanId = flowEntry.getMatchVlanId();
1084 matchVlanPriority = flowEntry.getMatchVlanPriority();
1085 matchSrcIPv4Net = flowEntry.getMatchSrcIPv4Net();
1086 matchDstIPv4Net = flowEntry.getMatchDstIPv4Net();
1087 matchIpProto = flowEntry.getMatchIpProto();
1088 matchIpToS = flowEntry.getMatchIpToS();
1089 matchSrcTcpUdpPort = flowEntry.getMatchSrcTcpUdpPort();
1090 matchDstTcpUdpPort = flowEntry.getMatchDstTcpUdpPort();
1091 } else if(flowObj instanceof IFlowPath) {
1092 IFlowPath flowPath = (IFlowPath) flowObj;
1093 matchSrcMac = flowPath.getMatchSrcMac();
1094 matchDstMac = flowPath.getMatchDstMac();
1095 matchEthernetFrameType = flowPath.getMatchEthernetFrameType();
1096 matchVlanId = flowPath.getMatchVlanId();
1097 matchVlanPriority = flowPath.getMatchVlanPriority();
1098 matchSrcIPv4Net = flowPath.getMatchSrcIPv4Net();
1099 matchDstIPv4Net = flowPath.getMatchDstIPv4Net();
1100 matchIpProto = flowPath.getMatchIpProto();
1101 matchIpToS = flowPath.getMatchIpToS();
1102 matchSrcTcpUdpPort = flowPath.getMatchSrcTcpUdpPort();
1103 matchDstTcpUdpPort = flowPath.getMatchDstTcpUdpPort();
1104 }
1105 }
1106
1107 if (matchInPort != null)
1108 match.enableInPort(new Port(matchInPort));
1109 if (matchSrcMac != null)
1110 match.enableSrcMac(MACAddress.valueOf(matchSrcMac));
1111 if (matchDstMac != null)
1112 match.enableDstMac(MACAddress.valueOf(matchDstMac));
1113 if (matchEthernetFrameType != null)
1114 match.enableEthernetFrameType(matchEthernetFrameType);
1115 if (matchVlanId != null)
1116 match.enableVlanId(matchVlanId);
1117 if (matchVlanPriority != null)
1118 match.enableVlanPriority(matchVlanPriority);
1119 if (matchSrcIPv4Net != null)
1120 match.enableSrcIPv4Net(new IPv4Net(matchSrcIPv4Net));
1121 if (matchDstIPv4Net != null)
1122 match.enableDstIPv4Net(new IPv4Net(matchDstIPv4Net));
1123 if (matchIpProto != null)
1124 match.enableIpProto(matchIpProto);
1125 if (matchIpToS != null)
1126 match.enableIpToS(matchIpToS);
1127 if (matchSrcTcpUdpPort != null)
1128 match.enableSrcTcpUdpPort(matchSrcTcpUdpPort);
1129 if (matchDstTcpUdpPort != null)
1130 match.enableDstTcpUdpPort(matchDstTcpUdpPort);
1131 return match;
1132 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -07001133}