blob: 1f0c16374ba9273e0aad9e25189aea6b9660a4f0 [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;
Yuta HIGUCHIcb32b2a2014-01-10 18:07:33 -08008import java.util.Map;
9
Pavlin Radoslavov16b761d2014-01-08 09:47:14 -080010import net.floodlightcontroller.core.IOFSwitch;
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070011import net.floodlightcontroller.util.MACAddress;
yoshitomob292c622013-11-23 14:35:58 -080012import net.onrc.onos.graph.DBOperation;
Yuta HIGUCHIcb32b2a2014-01-10 18:07:33 -080013import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IBaseObject;
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070014import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowEntry;
15import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowPath;
16import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IPortObject;
17import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.ISwitchObject;
18import net.onrc.onos.ofcontroller.util.*;
19
20import org.slf4j.Logger;
21import org.slf4j.LoggerFactory;
22
Yuta HIGUCHIdad0a2d2014-01-06 15:52:52 -080023import com.tinkerpop.blueprints.impls.ramcloud.PerfMon;
Yuta HIGUCHIcb32b2a2014-01-10 18:07:33 -080024import com.tinkerpop.blueprints.impls.ramcloud.RamCloudVertex;
Yuta HIGUCHIdad0a2d2014-01-06 15:52:52 -080025
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070026/**
27 * Class for performing Flow-related operations on the Database.
28 */
Pavlin Radoslavov6bfaea62013-12-03 14:55:57 -080029public class FlowDatabaseOperation {
Yuta HIGUCHI6ac8d182013-10-22 15:24:56 -070030 private final static Logger log = LoggerFactory.getLogger(FlowDatabaseOperation.class);
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -080031 private static final boolean measureONOSFlowTimeProp = Long.valueOf(System.getProperty("benchmark.measureONOSFlow", "0")) != 0;
32 private static final boolean measureONOSFlowEntryTimeProp = Long.valueOf(System.getProperty("benchmark.measureONOSFlowEntry", "0")) != 0;
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070033
34 /**
35 * Add a flow.
36 *
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070037 * @param dbHandler the Graph Database handler to use.
38 * @param flowPath the Flow Path to install.
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070039 * @return true on success, otherwise false.
40 */
onlab-qa38805cd2013-12-06 20:08:54 -080041 static boolean addFlow(DBOperation dbHandler, FlowPath flowPath) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070042 IFlowPath flowObj = null;
43 boolean found = false;
Yuta HIGUCHI37c55472014-01-03 11:42:27 -080044 long startAddFlow = 0;
45 long endAddFlow = 0;
46 long endSearchExistingFlowPathTime = 0;
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -080047 long startCreateNewFlowPathTime = 0;
Yuta HIGUCHI37c55472014-01-03 11:42:27 -080048 long endCreateNewFlowPathTime = 0;
49 long startFollowExistingFlowEntries = 0;
50 long endFollowExistingFlowEntries = 0;
51 long accTimeRemovingFlowEntriesFromFlowPath = 0;
52 long accTimeRemovingFlowEntriesFromDB = 0;
53 long startSettingFlowPathProps = 0;
54 long endSettingFlowPathProps = 0;
55 int numPropsSet = 0;
56 long accTimeAddFlowEntries = 0;
57 int numNewFlowEntries = 0;
58 LinkedList<long[]> flowEntryTimes = new LinkedList<>();
Yuta HIGUCHIdad0a2d2014-01-06 15:52:52 -080059 PerfMon pm = PerfMon.getInstance();
Yuta HIGUCHI37c55472014-01-03 11:42:27 -080060
Yuta HIGUCHIdad0a2d2014-01-06 15:52:52 -080061 pm.addflowpath_start();
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070062 try {
Yuta HIGUCHI37c55472014-01-03 11:42:27 -080063 if ( measureONOSFlowTimeProp ) {
64 startAddFlow = System.nanoTime();
65 }
yoshi40210942013-12-03 08:21:02 -080066 flowObj = dbHandler.searchFlowPath(flowPath.flowId());
Yuta HIGUCHI37c55472014-01-03 11:42:27 -080067 if ( measureONOSFlowTimeProp ) {
68 endSearchExistingFlowPathTime = System.nanoTime();
69 }
yoshi40210942013-12-03 08:21:02 -080070 if (flowObj != null) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070071 found = true;
72 } else {
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -080073 if ( measureONOSFlowTimeProp ) {
74 startCreateNewFlowPathTime = System.nanoTime();
75 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070076 flowObj = dbHandler.newFlowPath();
Yuta HIGUCHI37c55472014-01-03 11:42:27 -080077 if ( measureONOSFlowTimeProp ) {
78 endCreateNewFlowPathTime = System.nanoTime();
79 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070080 }
81 } catch (Exception e) {
82 dbHandler.rollback();
83
84 StringWriter sw = new StringWriter();
85 e.printStackTrace(new PrintWriter(sw));
86 String stacktrace = sw.toString();
87
88 log.error(":addFlow FlowId:{} failed: {}",
Yuta HIGUCHI5302ddf2014-01-06 12:53:35 -080089 flowPath.flowId(),
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070090 stacktrace);
91 return false;
92 }
93 if (flowObj == null) {
94 log.error(":addFlow FlowId:{} failed: Flow object not created",
Yuta HIGUCHI5302ddf2014-01-06 12:53:35 -080095 flowPath.flowId());
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070096 dbHandler.rollback();
97 return false;
98 }
99
100 //
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800101 // Remove the old Flow Entries
102 //
103 if (found) {
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800104 if ( measureONOSFlowTimeProp ) {
105 startFollowExistingFlowEntries = System.nanoTime();
106 }
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800107 Iterable<IFlowEntry> flowEntries = flowObj.getFlowEntries();
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800108 if ( measureONOSFlowTimeProp ) {
109 endFollowExistingFlowEntries = System.nanoTime();
110 }
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800111 LinkedList<IFlowEntry> deleteFlowEntries =
112 new LinkedList<IFlowEntry>();
113 for (IFlowEntry flowEntryObj : flowEntries)
114 deleteFlowEntries.add(flowEntryObj);
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800115 if( measureONOSFlowTimeProp ) {
116 for (IFlowEntry flowEntryObj : deleteFlowEntries) {
117 long start = System.nanoTime();
118 flowObj.removeFlowEntry(flowEntryObj);
119 accTimeRemovingFlowEntriesFromFlowPath += System.nanoTime() - start;
120 start = System.nanoTime();
121 dbHandler.removeFlowEntry(flowEntryObj);
122 accTimeRemovingFlowEntriesFromDB += System.nanoTime() - start;
123 }
124 } else {
125 for (IFlowEntry flowEntryObj : deleteFlowEntries) {
126 flowObj.removeFlowEntry(flowEntryObj);
127 dbHandler.removeFlowEntry(flowEntryObj);
128 }
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800129 }
130 }
131
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800132 if ( measureONOSFlowTimeProp ) {
133 startSettingFlowPathProps = System.nanoTime();
134 }
Toshio Koidea9b25142014-01-10 01:15:57 -0800135
136 FlowPathProperty flowProp = new FlowPathProperty(dbHandler, flowObj);
137
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800138 //
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700139 // Set the Flow key:
140 // - flowId
141 //
Toshio Koidea9b25142014-01-10 01:15:57 -0800142 flowProp.setFlowId(flowPath.flowId().toString());
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800143 if ( measureONOSFlowTimeProp ) {
Yuta HIGUCHI337e46d2014-01-10 22:49:27 -0800144 numPropsSet += 1;
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800145 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700146
147 //
148 // Set the Flow attributes:
149 // - flowPath.installerId()
Pavlin Radoslavovd28cf7c2013-10-26 11:27:43 -0700150 // - flowPath.flowPathType()
Pavlin Radoslavov7d4a40e2013-10-27 23:39:40 -0700151 // - flowPath.flowPathUserState()
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700152 // - flowPath.flowPathFlags()
Pavlin Radoslavov5139c0b2013-12-09 18:04:53 -0800153 // - flowPath.idleTimeout()
154 // - flowPath.hardTimeout()
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700155 // - flowPath.dataPath().srcPort()
156 // - flowPath.dataPath().dstPort()
157 // - flowPath.matchSrcMac()
158 // - flowPath.matchDstMac()
159 // - flowPath.matchEthernetFrameType()
160 // - flowPath.matchVlanId()
161 // - flowPath.matchVlanPriority()
162 // - flowPath.matchSrcIPv4Net()
163 // - flowPath.matchDstIPv4Net()
164 // - flowPath.matchIpProto()
165 // - flowPath.matchIpToS()
166 // - flowPath.matchSrcTcpUdpPort()
167 // - flowPath.matchDstTcpUdpPort()
168 // - flowPath.flowEntryActions()
169 //
Toshio Koidea9b25142014-01-10 01:15:57 -0800170 flowProp.setInstallerId(flowPath.installerId().toString());
171 flowProp.setFlowPathType(flowPath.flowPathType().toString());
172 flowProp.setFlowPathUserState(flowPath.flowPathUserState().toString());
173 flowProp.setFlowPathFlags(flowPath.flowPathFlags().flags());
174 flowProp.setIdleTimeout(flowPath.idleTimeout());
175 flowProp.setHardTimeout(flowPath.hardTimeout());
176 flowProp.setSrcSwitch(flowPath.dataPath().srcPort().dpid().toString());
177 flowProp.setSrcPort(flowPath.dataPath().srcPort().port().value());
178 flowProp.setDstSwitch(flowPath.dataPath().dstPort().dpid().toString());
179 flowProp.setDstPort(flowPath.dataPath().dstPort().port().value());
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800180 if ( measureONOSFlowTimeProp ) {
181 numPropsSet += 10;
182 }
183
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700184 if (flowPath.flowEntryMatch().matchSrcMac()) {
Toshio Koidea9b25142014-01-10 01:15:57 -0800185 flowProp.setMatchSrcMac(flowPath.flowEntryMatch().srcMac().toString());
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800186 if ( measureONOSFlowTimeProp ) {
187 ++numPropsSet;
188 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700189 }
190 if (flowPath.flowEntryMatch().matchDstMac()) {
Toshio Koidea9b25142014-01-10 01:15:57 -0800191 flowProp.setMatchDstMac(flowPath.flowEntryMatch().dstMac().toString());
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800192 if ( measureONOSFlowTimeProp ) {
193 ++numPropsSet;
194 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700195 }
196 if (flowPath.flowEntryMatch().matchEthernetFrameType()) {
Toshio Koidea9b25142014-01-10 01:15:57 -0800197 flowProp.setMatchEthernetFrameType(flowPath.flowEntryMatch().ethernetFrameType());
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800198 if ( measureONOSFlowTimeProp ) {
199 ++numPropsSet;
200 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700201 }
202 if (flowPath.flowEntryMatch().matchVlanId()) {
Toshio Koidea9b25142014-01-10 01:15:57 -0800203 flowProp.setMatchVlanId(flowPath.flowEntryMatch().vlanId());
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800204 if ( measureONOSFlowTimeProp ) {
205 ++numPropsSet;
206 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700207 }
208 if (flowPath.flowEntryMatch().matchVlanPriority()) {
Toshio Koidea9b25142014-01-10 01:15:57 -0800209 flowProp.setMatchVlanPriority(flowPath.flowEntryMatch().vlanPriority());
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800210 if ( measureONOSFlowTimeProp ) {
211 ++numPropsSet;
212 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700213 }
214 if (flowPath.flowEntryMatch().matchSrcIPv4Net()) {
Toshio Koidea9b25142014-01-10 01:15:57 -0800215 flowProp.setMatchSrcIPv4Net(flowPath.flowEntryMatch().srcIPv4Net().toString());
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800216 if ( measureONOSFlowTimeProp ) {
217 ++numPropsSet;
218 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700219 }
220 if (flowPath.flowEntryMatch().matchDstIPv4Net()) {
Toshio Koidea9b25142014-01-10 01:15:57 -0800221 flowProp.setMatchDstIPv4Net(flowPath.flowEntryMatch().dstIPv4Net().toString());
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800222 if ( measureONOSFlowTimeProp ) {
223 ++numPropsSet;
224 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700225 }
226 if (flowPath.flowEntryMatch().matchIpProto()) {
Toshio Koidea9b25142014-01-10 01:15:57 -0800227 flowProp.setMatchIpProto(flowPath.flowEntryMatch().ipProto());
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800228 if ( measureONOSFlowTimeProp ) {
229 ++numPropsSet;
230 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700231 }
232 if (flowPath.flowEntryMatch().matchIpToS()) {
Toshio Koidea9b25142014-01-10 01:15:57 -0800233 flowProp.setMatchIpToS(flowPath.flowEntryMatch().ipToS());
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800234 if ( measureONOSFlowTimeProp ) {
235 ++numPropsSet;
236 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700237 }
238 if (flowPath.flowEntryMatch().matchSrcTcpUdpPort()) {
Toshio Koidea9b25142014-01-10 01:15:57 -0800239 flowProp.setMatchSrcTcpUdpPort(flowPath.flowEntryMatch().srcTcpUdpPort());
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800240 if ( measureONOSFlowTimeProp ) {
241 ++numPropsSet;
242 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700243 }
244 if (flowPath.flowEntryMatch().matchDstTcpUdpPort()) {
Toshio Koidea9b25142014-01-10 01:15:57 -0800245 flowProp.setMatchDstTcpUdpPort(flowPath.flowEntryMatch().dstTcpUdpPort());
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800246 if ( measureONOSFlowTimeProp ) {
247 ++numPropsSet;
248 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700249 }
250 if (! flowPath.flowEntryActions().actions().isEmpty()) {
Toshio Koidea9b25142014-01-10 01:15:57 -0800251 flowProp.setActions(flowPath.flowEntryActions().toString());
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800252 if ( measureONOSFlowTimeProp ) {
253 ++numPropsSet;
254 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700255 }
Toshio Koidea9b25142014-01-10 01:15:57 -0800256 flowProp.setDataPathSummary(flowPath.dataPath().dataPathSummary());
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800257 if ( measureONOSFlowTimeProp ) {
258 ++numPropsSet;
259 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700260
261 if (found)
Toshio Koidea9b25142014-01-10 01:15:57 -0800262 flowProp.setFlowPathUserState("FP_USER_MODIFY");
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700263 else
Toshio Koidea9b25142014-01-10 01:15:57 -0800264 flowProp.setFlowPathUserState("FP_USER_ADD");
265
266 flowProp.commitProperties();
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700267
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800268 if ( measureONOSFlowTimeProp ) {
269 ++numPropsSet;
270 }
271
272 if ( measureONOSFlowTimeProp ) {
273 endSettingFlowPathProps = System.nanoTime();
274 }
Yuta HIGUCHIdad0a2d2014-01-06 15:52:52 -0800275 pm.addflowpath_end();
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700276 // Flow edges:
277 // HeadFE
278
279
280 //
281 // Flow Entries:
282 // flowPath.dataPath().flowEntries()
283 //
Yuta HIGUCHIdad0a2d2014-01-06 15:52:52 -0800284 pm.addflowentry_start();
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700285 for (FlowEntry flowEntry : flowPath.dataPath().flowEntries()) {
Pavlin Radoslavov2fca8d12013-12-04 09:39:06 -0800286 if (flowEntry.flowEntryUserState() == FlowEntryUserState.FE_USER_DELETE)
287 continue; // Skip: all Flow Entries were deleted earlier
288
Yuta HIGUCHIdad0a2d2014-01-06 15:52:52 -0800289 pm.addflowentry_incr();
290
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800291 long startAddFlowEntry = 0, endAddFlowEntry;
292 if( measureONOSFlowTimeProp ) {
293 startAddFlowEntry = System.nanoTime();
294 }
295 IFlowEntry iFlowEntry = addFlowEntry(dbHandler, flowObj, flowEntry);
296 if( measureONOSFlowTimeProp ) {
297 endAddFlowEntry = System.nanoTime();
298 accTimeAddFlowEntries += endAddFlowEntry - startAddFlowEntry;
299
300 flowEntryTimes.addLast( new long[]{flowEntry.flowId().value(), endAddFlowEntry - startAddFlowEntry} );
301 }
302 if ( iFlowEntry == null) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700303 dbHandler.rollback();
304 return false;
305 }
306 }
Yuta HIGUCHIdad0a2d2014-01-06 15:52:52 -0800307 pm.addflowentry_end();
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700308 dbHandler.commit();
309
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800310
311 if ( measureONOSFlowTimeProp ) {
312 endAddFlow = System.nanoTime();
313
Yuta HIGUCHI0b4fbaf2014-01-04 22:23:05 -0800314 log.error("Performance addFlow(_,{}) -- "
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800315 + "GrandTotal: {} "
316 + "only FlowPathTotal: {} "
317 + "searchExistingFlowPath: {} "
318 + "createNewFlowPathTime: {}"
319 + "followExistingFlowEntries: {} "
320 + "accTimeRemovingFlowEntriesFromFlowPath: {} "
321 + "accTimeRemovingFlowEntriesFromDB: {} "
322 + "settingFlowPathProps: {} #Props: {} "
323 + "accFlowEntries: {} #FEs: {}",
324 flowPath.flowId(),
325 (endAddFlow - startAddFlow),
326 (endSettingFlowPathProps - startAddFlow),
327 (endSearchExistingFlowPathTime - startAddFlow),
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800328 (endCreateNewFlowPathTime - startCreateNewFlowPathTime),
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800329 (endFollowExistingFlowEntries - startFollowExistingFlowEntries),
330 (accTimeRemovingFlowEntriesFromFlowPath),
331 (accTimeRemovingFlowEntriesFromDB),
332 (endSettingFlowPathProps - startSettingFlowPathProps), numPropsSet,
333 accTimeAddFlowEntries, numNewFlowEntries
334 );
335
336 // Each FlowEntries
337 final String strFlowId = flowPath.flowId().toString();
338 for ( long[] idFE_Time : flowEntryTimes ) {
Yuta HIGUCHI0b4fbaf2014-01-04 22:23:05 -0800339 log.error("Performance addFlowEntry(_,{},{})@addFlow -- FlowEntryTotal: {}",
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800340 strFlowId,
341 "0x" + Long.toHexString(idFE_Time[0]),
342 idFE_Time[1]);
343 }
344 }
345
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700346 return true;
347 }
348
349 /**
350 * Add a flow entry to the Network MAP.
351 *
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700352 * @param dbHandler the Graph Database handler to use.
353 * @param flowObj the corresponding Flow Path object for the Flow Entry.
354 * @param flowEntry the Flow Entry to install.
355 * @return the added Flow Entry object on success, otherwise null.
356 */
onlab-qa38805cd2013-12-06 20:08:54 -0800357 static IFlowEntry addFlowEntry(DBOperation dbHandler,
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700358 IFlowPath flowObj,
359 FlowEntry flowEntry) {
360 // Flow edges
361 // HeadFE (TODO)
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800362 long startAddFlowEntry = 0;
363 long endAddFlowEntry = 0;
364
365 long endSearchFlowEntry = 0;
366
367 long startCreateNewFlowEntry = 0;
368 long endCreateNewFlowEntry = 0;
369
370 long startSetProperties = 0;
371 long endSetProperties = 0;
372 int numProperties = 0;
373
374 long startSearchSwitch = 0;
375 long endSearchSwitch = 0;
376
377 long startAddEdgeToSwitch =0;
378 long endAddEdgeToSwitch =0;
379
380 long startSearchInPort = 0;
381 long endSearchInPort = 0;
382
383 long startAddEdgeToInPort =0;
384 long endAddEdgeToInPort =0;
385
386 long startSearchOutPort = 0;
387 long endSearchOutPort = 0;
388
389 long startAddEdgeToOutPort =0;
390 long endAddEdgeToOutPort =0;
391
392 long startAddEdgeBetweenFlowPath = 0;
393 long endAddEdgeBetweenFlowPath = 0;
394
395 if (measureONOSFlowEntryTimeProp) {
396 startAddFlowEntry = System.nanoTime();
397 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700398
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700399 IFlowEntry flowEntryObj = null;
400 boolean found = false;
401 try {
Yuta HIGUCHIc27a6c92014-01-07 11:51:11 -0800402 flowEntryObj = dbHandler.searchFlowEntry(flowEntry.flowEntryId());
403 if (measureONOSFlowEntryTimeProp) {
404 endSearchFlowEntry = System.nanoTime();
405 }
406 if (flowEntryObj != null) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700407 found = true;
408 } else {
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800409 if (measureONOSFlowEntryTimeProp) {
410 startCreateNewFlowEntry = System.nanoTime();
411 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700412 flowEntryObj = dbHandler.newFlowEntry();
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800413 if (measureONOSFlowEntryTimeProp) {
414 endCreateNewFlowEntry = System.nanoTime();
415 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700416 }
417 } catch (Exception e) {
418 log.error(":addFlow FlowEntryId:{} failed",
Yuta HIGUCHI5302ddf2014-01-06 12:53:35 -0800419 flowEntry.flowEntryId());
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700420 return null;
421 }
422 if (flowEntryObj == null) {
423 log.error(":addFlow FlowEntryId:{} failed: FlowEntry object not created",
Yuta HIGUCHI5302ddf2014-01-06 12:53:35 -0800424 flowEntry.flowEntryId());
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700425 return null;
426 }
427
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800428 if (measureONOSFlowEntryTimeProp) {
429 startSetProperties = System.nanoTime();
430 }
Yuta HIGUCHI8685f9c2014-01-07 15:53:28 -0800431
Toshio Koide7f76e9e2014-01-09 22:06:35 -0800432 FlowEntryProperty flowProp = new FlowEntryProperty(dbHandler, flowEntryObj);
Yuta HIGUCHI8685f9c2014-01-07 15:53:28 -0800433
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700434 //
435 // Set the Flow Entry key:
436 // - flowEntry.flowEntryId()
437 //
Toshio Koide3f233542014-01-07 14:19:09 -0800438 flowProp.setFlowEntryId(flowEntry.flowEntryId().toString());
439 flowProp.setType("flow_entry");
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800440 if (measureONOSFlowEntryTimeProp) {
441 numProperties += 2;
442 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700443
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800444 //
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700445 // Set the Flow Entry Edges and attributes:
446 // - Switch edge
447 // - InPort edge
448 // - OutPort edge
449 //
Pavlin Radoslavov5139c0b2013-12-09 18:04:53 -0800450 // - flowEntry.idleTimeout()
451 // - flowEntry.hardTimeout()
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700452 // - flowEntry.dpid()
453 // - flowEntry.flowEntryUserState()
454 // - flowEntry.flowEntrySwitchState()
455 // - flowEntry.flowEntryErrorState()
456 // - flowEntry.matchInPort()
457 // - flowEntry.matchSrcMac()
458 // - flowEntry.matchDstMac()
459 // - flowEntry.matchEthernetFrameType()
460 // - flowEntry.matchVlanId()
461 // - flowEntry.matchVlanPriority()
462 // - flowEntry.matchSrcIPv4Net()
463 // - flowEntry.matchDstIPv4Net()
464 // - flowEntry.matchIpProto()
465 // - flowEntry.matchIpToS()
466 // - flowEntry.matchSrcTcpUdpPort()
467 // - flowEntry.matchDstTcpUdpPort()
468 // - flowEntry.actionOutputPort()
469 // - flowEntry.actions()
470 //
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800471 if (measureONOSFlowEntryTimeProp) {
472 startSearchSwitch = System.nanoTime();
473 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700474 ISwitchObject sw = dbHandler.searchSwitch(flowEntry.dpid().toString());
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800475 if (measureONOSFlowEntryTimeProp) {
476 endSearchSwitch = System.nanoTime();
477 }
478
Toshio Koide3f233542014-01-07 14:19:09 -0800479 flowProp.setIdleTimeout(flowEntry.idleTimeout());
480 flowProp.setHardTimeout(flowEntry.hardTimeout());
481 flowProp.setSwitchDpid(flowEntry.dpid().toString());
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800482 if (measureONOSFlowEntryTimeProp) {
483 numProperties += 3;
484 }
485
486 if (measureONOSFlowEntryTimeProp) {
487 startAddEdgeToSwitch = System.nanoTime();
488 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700489 flowEntryObj.setSwitch(sw);
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800490 if (measureONOSFlowEntryTimeProp) {
491 endAddEdgeToSwitch = System.nanoTime();
492 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700493 if (flowEntry.flowEntryMatch().matchInPort()) {
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800494 if (measureONOSFlowEntryTimeProp) {
495 startSearchInPort = System.nanoTime();
496 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700497 IPortObject inport =
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800498 dbHandler.searchPort(flowEntry.dpid().toString(),
499 flowEntry.flowEntryMatch().inPort().value());
500 if (measureONOSFlowEntryTimeProp) {
501 endSearchInPort = System.nanoTime();
502 }
503
Toshio Koide3f233542014-01-07 14:19:09 -0800504 flowProp.setMatchInPort(flowEntry.flowEntryMatch().inPort().value());
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800505 if (measureONOSFlowEntryTimeProp) {
506 ++numProperties;
507 }
508
509 if (measureONOSFlowEntryTimeProp) {
510 startAddEdgeToInPort = System.nanoTime();
511 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700512 flowEntryObj.setInPort(inport);
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800513 if (measureONOSFlowEntryTimeProp) {
514 endAddEdgeToInPort = System.nanoTime();
515 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700516 }
517 if (flowEntry.flowEntryMatch().matchSrcMac()) {
Toshio Koide3f233542014-01-07 14:19:09 -0800518 flowProp.setMatchSrcMac(flowEntry.flowEntryMatch().srcMac().toString());
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800519 if (measureONOSFlowEntryTimeProp) {
520 ++numProperties;
521 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700522 }
523 if (flowEntry.flowEntryMatch().matchDstMac()) {
Toshio Koide3f233542014-01-07 14:19:09 -0800524 flowProp.setMatchDstMac(flowEntry.flowEntryMatch().dstMac().toString());
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800525 if (measureONOSFlowEntryTimeProp) {
526 ++numProperties;
527 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700528 }
529 if (flowEntry.flowEntryMatch().matchEthernetFrameType()) {
Toshio Koide3f233542014-01-07 14:19:09 -0800530 flowProp.setMatchEthernetFrameType(flowEntry.flowEntryMatch().ethernetFrameType());
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800531 if (measureONOSFlowEntryTimeProp) {
532 ++numProperties;
533 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700534 }
535 if (flowEntry.flowEntryMatch().matchVlanId()) {
Toshio Koide3f233542014-01-07 14:19:09 -0800536 flowProp.setMatchVlanId(flowEntry.flowEntryMatch().vlanId());
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800537 if (measureONOSFlowEntryTimeProp) {
538 ++numProperties;
539 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700540 }
541 if (flowEntry.flowEntryMatch().matchVlanPriority()) {
Toshio Koide3f233542014-01-07 14:19:09 -0800542 flowProp.setMatchVlanPriority(flowEntry.flowEntryMatch().vlanPriority());
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800543 if (measureONOSFlowEntryTimeProp) {
544 ++numProperties;
545 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700546 }
547 if (flowEntry.flowEntryMatch().matchSrcIPv4Net()) {
Toshio Koide3f233542014-01-07 14:19:09 -0800548 flowProp.setMatchSrcIPv4Net(flowEntry.flowEntryMatch().srcIPv4Net().toString());
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800549 if (measureONOSFlowEntryTimeProp) {
550 ++numProperties;
551 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700552 }
553 if (flowEntry.flowEntryMatch().matchDstIPv4Net()) {
Toshio Koide3f233542014-01-07 14:19:09 -0800554 flowProp.setMatchDstIPv4Net(flowEntry.flowEntryMatch().dstIPv4Net().toString());
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800555 if (measureONOSFlowEntryTimeProp) {
556 ++numProperties;
557 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700558 }
559 if (flowEntry.flowEntryMatch().matchIpProto()) {
Toshio Koide3f233542014-01-07 14:19:09 -0800560 flowProp.setMatchIpProto(flowEntry.flowEntryMatch().ipProto());
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800561 if (measureONOSFlowEntryTimeProp) {
562 ++numProperties;
563 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700564 }
565 if (flowEntry.flowEntryMatch().matchIpToS()) {
Toshio Koide3f233542014-01-07 14:19:09 -0800566 flowProp.setMatchIpToS(flowEntry.flowEntryMatch().ipToS());
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800567 if (measureONOSFlowEntryTimeProp) {
568 ++numProperties;
569 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700570 }
571 if (flowEntry.flowEntryMatch().matchSrcTcpUdpPort()) {
Toshio Koide3f233542014-01-07 14:19:09 -0800572 flowProp.setMatchSrcTcpUdpPort(flowEntry.flowEntryMatch().srcTcpUdpPort());
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800573 if (measureONOSFlowEntryTimeProp) {
574 ++numProperties;
575 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700576 }
577 if (flowEntry.flowEntryMatch().matchDstTcpUdpPort()) {
Toshio Koide3f233542014-01-07 14:19:09 -0800578 flowProp.setMatchDstTcpUdpPort(flowEntry.flowEntryMatch().dstTcpUdpPort());
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800579 if (measureONOSFlowEntryTimeProp) {
580 ++numProperties;
581 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700582 }
583
584 for (FlowEntryAction fa : flowEntry.flowEntryActions().actions()) {
585 if (fa.actionOutput() != null) {
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800586 if (measureONOSFlowEntryTimeProp) {
587 if ( startSearchOutPort != 0 ) log.error("Performance addFlowEntry(_,{},{}) -- Multiple output port action unexpected.", flowEntry.flowId(), flowEntry.flowEntryId());
588 startSearchOutPort = System.nanoTime();
589 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700590 IPortObject outport =
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800591 dbHandler.searchPort(flowEntry.dpid().toString(),
592 fa.actionOutput().port().value());
593 if (measureONOSFlowEntryTimeProp) {
594 endSearchOutPort = System.nanoTime();
595 }
596
Toshio Koide3f233542014-01-07 14:19:09 -0800597 flowProp.setActionOutputPort(fa.actionOutput().port().value());
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800598 if (measureONOSFlowEntryTimeProp) {
599 ++numProperties;
600 }
601
602 if (measureONOSFlowEntryTimeProp) {
603 startAddEdgeToOutPort = System.nanoTime();
604 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700605 flowEntryObj.setOutPort(outport);
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800606 if (measureONOSFlowEntryTimeProp) {
607 endAddEdgeToOutPort = System.nanoTime();
608 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700609 }
610 }
611 if (! flowEntry.flowEntryActions().isEmpty()) {
Toshio Koide3f233542014-01-07 14:19:09 -0800612 flowProp.setActions(flowEntry.flowEntryActions().toString());
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800613 if (measureONOSFlowEntryTimeProp) {
614 ++numProperties;
615 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700616 }
617
Yuta HIGUCHI337e46d2014-01-10 22:49:27 -0800618 flowProp.setUserState(flowEntry.flowEntryUserState().toString());
Toshio Koide3f233542014-01-07 14:19:09 -0800619 flowProp.setSwitchState(flowEntry.flowEntrySwitchState().toString());
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800620 if (measureONOSFlowEntryTimeProp) {
621 numProperties += 2;
622 }
Yuta HIGUCHI8685f9c2014-01-07 15:53:28 -0800623 flowProp.commitProperties();
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700624 //
625 // TODO: Take care of the FlowEntryErrorState.
626 //
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800627 if (measureONOSFlowEntryTimeProp) {
628 endSetProperties = System.nanoTime();
629 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700630
631 // Flow Entries edges:
632 // Flow
633 // NextFE (TODO)
634 if (! found) {
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800635 if (measureONOSFlowEntryTimeProp) {
636 startAddEdgeBetweenFlowPath = System.nanoTime();
637 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700638 flowObj.addFlowEntry(flowEntryObj);
639 flowEntryObj.setFlow(flowObj);
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800640 if (measureONOSFlowEntryTimeProp) {
641 endAddEdgeBetweenFlowPath = System.nanoTime();
642 }
643 }
644 if (measureONOSFlowEntryTimeProp) {
645 endAddFlowEntry = System.nanoTime();
646
647 log.error("Performance addFlowEntry(_,{},{}) -- "
648 + "GrandTotal: {} "
649 + "SearchExistingFE: {} "
650 + "CreateNewFE: {} "
651 + "SetProp+Edge: {} #Props: {} "
652 + "SearchSwitch: {} "
653 + "AddEdgeToSwitch: {} "
654 + "SearchInPort: {} "
655 + "AddEdgeToInPort: {} "
656 + "SearchOutPort: {} "
657 + "AddEdgeToOutPort: {} "
658 + "AddEdgeBetweenFlowPath: {} "
659 , flowEntry.flowId(), flowEntry.flowEntryId()
660 , endAddFlowEntry - startAddFlowEntry
661 , endSearchFlowEntry - startAddFlowEntry
662 , endCreateNewFlowEntry - startCreateNewFlowEntry
663 , endSetProperties - startSetProperties, numProperties
664 , endSearchSwitch - startSearchSwitch
665 , endAddEdgeToSwitch - startAddEdgeToSwitch
666 , endSearchInPort - startSearchInPort
667 , endAddEdgeToInPort - startAddEdgeToInPort
668 , endSearchOutPort - startSearchOutPort
669 , endAddEdgeToOutPort - startAddEdgeToOutPort
670 , endAddEdgeBetweenFlowPath - startAddEdgeBetweenFlowPath
671 );
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700672 }
673
674 return flowEntryObj;
675 }
676
677 /**
Pavlin Radoslavov7407ab52013-11-01 22:19:00 -0700678 * Delete a flow entry from the Network MAP.
679 *
680 * @param dbHandler the Graph Database handler to use.
681 * @param flowObj the corresponding Flow Path object for the Flow Entry.
682 * @param flowEntry the Flow Entry to delete.
683 * @return true on success, otherwise false.
684 */
yoshitomob292c622013-11-23 14:35:58 -0800685 static boolean deleteFlowEntry(DBOperation dbHandler,
Pavlin Radoslavov7407ab52013-11-01 22:19:00 -0700686 IFlowPath flowObj,
687 FlowEntry flowEntry) {
688 IFlowEntry flowEntryObj = null;
689 try {
690 flowEntryObj = dbHandler.searchFlowEntry(flowEntry.flowEntryId());
691 } catch (Exception e) {
692 log.error(":deleteFlowEntry FlowEntryId:{} failed",
Yuta HIGUCHI5302ddf2014-01-06 12:53:35 -0800693 flowEntry.flowEntryId());
Pavlin Radoslavov7407ab52013-11-01 22:19:00 -0700694 return false;
695 }
696 //
697 // TODO: Don't print an error for now, because multiple controller
698 // instances might be deleting the same flow entry.
699 //
700 /*
701 if (flowEntryObj == null) {
702 log.error(":deleteFlowEntry FlowEntryId:{} failed: FlowEntry object not found",
Yuta HIGUCHI5302ddf2014-01-06 12:53:35 -0800703 flowEntry.flowEntryId());
Pavlin Radoslavov7407ab52013-11-01 22:19:00 -0700704 return false;
705 }
706 */
707 if (flowEntryObj == null)
708 return true;
709
710 flowObj.removeFlowEntry(flowEntryObj);
711 dbHandler.removeFlowEntry(flowEntryObj);
712 return true;
713 }
714
715 /**
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700716 * Delete all previously added flows.
717 *
718 * @param dbHandler the Graph Database handler to use.
719 * @return true on success, otherwise false.
720 */
yoshitomob292c622013-11-23 14:35:58 -0800721 static boolean deleteAllFlows(DBOperation dbHandler) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700722 Iterable<IFlowPath> allFlowPaths = dbHandler.getAllFlowPaths();
723 for (IFlowPath flowPathObj : allFlowPaths) {
724 if (flowPathObj == null)
725 continue;
Yuta HIGUCHI53794052014-01-10 16:49:41 -0800726 deleteIFlowPath(dbHandler, flowPathObj);
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700727 }
728
729 return true;
730 }
731
732 /**
Pavlin Radoslavovf2a52652013-11-22 12:35:42 -0800733 * Delete a previously added flow.
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700734 *
735 * @param dbHandler the Graph Database handler to use.
Pavlin Radoslavovf2a52652013-11-22 12:35:42 -0800736 * @param flowId the Flow ID of the flow to delete.
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700737 * @return true on success, otherwise false.
738 */
yoshitomob292c622013-11-23 14:35:58 -0800739 static boolean deleteFlow(DBOperation dbHandler, FlowId flowId) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700740 IFlowPath flowObj = null;
741 try {
742 flowObj = dbHandler.searchFlowPath(flowId);
743 } catch (Exception e) {
744 // TODO: handle exceptions
745 dbHandler.rollback();
Yuta HIGUCHI5302ddf2014-01-06 12:53:35 -0800746 log.error(":deleteFlow FlowId:{} failed", flowId);
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700747 return false;
748 }
749 if (flowObj == null) {
750 dbHandler.commit();
751 return true; // OK: No such flow
752 }
753
Yuta HIGUCHI53794052014-01-10 16:49:41 -0800754 deleteIFlowPath(dbHandler, flowObj);
755
756 return true;
757 }
758
759 private static void deleteIFlowPath(DBOperation dbHandler, IFlowPath flowObj) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700760 //
761 // Remove all Flow Entries
762 //
763 Iterable<IFlowEntry> flowEntries = flowObj.getFlowEntries();
764 for (IFlowEntry flowEntryObj : flowEntries) {
765 flowObj.removeFlowEntry(flowEntryObj);
766 dbHandler.removeFlowEntry(flowEntryObj);
767 }
768 // Remove the Flow itself
769 dbHandler.removeFlowPath(flowObj);
770 dbHandler.commit();
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700771 }
772
773 /**
774 * Get a previously added flow.
775 *
776 * @param dbHandler the Graph Database handler to use.
777 * @param flowId the Flow ID of the flow to get.
778 * @return the Flow Path if found, otherwise null.
779 */
yoshitomob292c622013-11-23 14:35:58 -0800780 static FlowPath getFlow(DBOperation dbHandler, FlowId flowId) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700781 IFlowPath flowObj = null;
782 try {
783 flowObj = dbHandler.searchFlowPath(flowId);
784 } catch (Exception e) {
785 // TODO: handle exceptions
786 dbHandler.rollback();
Yuta HIGUCHI5302ddf2014-01-06 12:53:35 -0800787 log.error(":getFlow FlowId:{} failed", flowId);
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700788 return null;
789 }
790 if (flowObj == null) {
791 dbHandler.commit();
792 return null; // Flow not found
793 }
794
795 //
796 // Extract the Flow state
797 //
798 FlowPath flowPath = extractFlowPath(flowObj);
799 dbHandler.commit();
800
801 return flowPath;
802 }
803
804 /**
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800805 * Get a previously added flow entry.
806 *
807 * @param dbHandler the Graph Database handler to use.
808 * @param flowEntryId the Flow Entry ID of the flow entry to get.
809 * @return the Flow Entry if found, otherwise null.
810 */
Yuta HIGUCHI337e46d2014-01-10 22:49:27 -0800811 static FlowEntry getFlowEntry(DBOperation dbHandler,
Pavlin Radoslavov52119fa2014-01-09 13:37:52 -0800812 FlowEntryId flowEntryId) {
813 IFlowEntry flowEntryObj = null;
814 try {
815 flowEntryObj = dbHandler.searchFlowEntry(flowEntryId);
816 } catch (Exception e) {
817 // TODO: handle exceptions
818 dbHandler.rollback();
819 log.error(":getFlowEntry FlowEntryId:{} failed", flowEntryId);
820 return null;
821 }
822 if (flowEntryObj == null) {
823 dbHandler.commit();
824 return null; // Flow not found
825 }
826
827 //
828 // Extract the Flow Entry state
829 //
830 FlowEntry flowEntry = extractFlowEntry(flowEntryObj);
831 dbHandler.commit();
832
833 return flowEntry;
834 }
835
836 /**
Pavlin Radoslavov8252fee2014-01-07 17:24:29 -0800837 * Get the source switch DPID of a previously added flow.
838 *
839 * @param dbHandler the Graph Database handler to use.
840 * @param flowId the Flow ID of the flow to get.
841 * @return the source switch DPID if found, otherwise null.
842 */
Yuta HIGUCHI337e46d2014-01-10 22:49:27 -0800843 static Dpid getFlowSourceDpid(DBOperation dbHandler, FlowId flowId) {
Pavlin Radoslavov8252fee2014-01-07 17:24:29 -0800844 IFlowPath flowObj = null;
845 try {
846 flowObj = dbHandler.searchFlowPath(flowId);
847 } catch (Exception e) {
848 // TODO: handle exceptions
849 dbHandler.rollback();
850 log.error(":getFlowSourceDpid FlowId:{} failed", flowId);
851 return null;
852 }
853 if (flowObj == null) {
854 dbHandler.commit();
855 return null; // Flow not found
856 }
857
858 //
859 // Extract the Flow Source DPID
860 //
861 String srcSwitchStr = flowObj.getSrcSwitch();
862 if (srcSwitchStr == null) {
863 // TODO: A work-around, becauuse of some bogus database objects
864 dbHandler.commit();
865 return null;
866 }
867
868 Dpid dpid = new Dpid(srcSwitchStr);
869
870 dbHandler.commit();
871
872 return dpid;
873 }
874
875 /**
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700876 * Get all installed flows by all installers.
877 *
878 * @param dbHandler the Graph Database handler to use.
879 * @return the Flow Paths if found, otherwise null.
880 */
yoshitomob292c622013-11-23 14:35:58 -0800881 static ArrayList<FlowPath> getAllFlows(DBOperation dbHandler) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700882 Iterable<IFlowPath> flowPathsObj = null;
883 ArrayList<FlowPath> flowPaths = new ArrayList<FlowPath>();
884
885 try {
886 flowPathsObj = dbHandler.getAllFlowPaths();
887 } catch (Exception e) {
888 // TODO: handle exceptions
889 dbHandler.rollback();
890 log.error(":getAllFlowPaths failed");
891 return flowPaths;
892 }
893 if ((flowPathsObj == null) || (flowPathsObj.iterator().hasNext() == false)) {
894 dbHandler.commit();
895 return flowPaths; // No Flows found
896 }
897
898 for (IFlowPath flowObj : flowPathsObj) {
899 //
900 // Extract the Flow state
901 //
902 FlowPath flowPath = extractFlowPath(flowObj);
903 if (flowPath != null)
904 flowPaths.add(flowPath);
905 }
906
907 dbHandler.commit();
908
909 return flowPaths;
910 }
911
912 /**
Pavlin Radoslavov16b761d2014-01-08 09:47:14 -0800913 * Get all installed flows whose Source Switch is controlled by this
914 * instance.
915 *
916 * @param dbHandler the Graph Database handler to use.
917 * @param mySwitches the collection of the switches controlled by this
918 * instance.
919 * @return the Flow Paths if found, otherwise null.
920 */
Yuta HIGUCHI337e46d2014-01-10 22:49:27 -0800921 static ArrayList<FlowPath> getAllMyFlows(DBOperation dbHandler,
Pavlin Radoslavov16b761d2014-01-08 09:47:14 -0800922 Map<Long, IOFSwitch> mySwitches) {
923 Iterable<IFlowPath> flowPathsObj = null;
924 ArrayList<FlowPath> flowPaths = new ArrayList<FlowPath>();
925
926 try {
927 flowPathsObj = dbHandler.getAllFlowPaths();
928 } catch (Exception e) {
929 // TODO: handle exceptions
930 dbHandler.rollback();
931 log.error(":getAllMyFlowPaths failed");
932 return flowPaths;
933 }
934 if ((flowPathsObj == null) || (flowPathsObj.iterator().hasNext() == false)) {
935 dbHandler.commit();
936 return flowPaths; // No Flows found
937 }
938
939 for (IFlowPath flowObj : flowPathsObj) {
940 //
941 // Extract the Source Switch DPID and ignore if the switch
942 // is not controlled by this instance.
943 //
944 String srcSwitchStr = flowObj.getSrcSwitch();
945 if (srcSwitchStr == null) {
946 // TODO: A work-around, becauuse of some bogus database objects
947 continue;
948 }
949 Dpid dpid = new Dpid(srcSwitchStr);
950 if (mySwitches.get(dpid.value()) == null)
951 continue;
952
953 //
954 // Extract the Flow state
955 //
956 FlowPath flowPath = extractFlowPath(flowObj);
957 if (flowPath != null)
958 flowPaths.add(flowPath);
959 }
960
961 dbHandler.commit();
962
963 return flowPaths;
964 }
965
966 /**
Pavlin Radoslavovf3f23bb2014-01-10 13:02:33 -0800967 * Get a subset of installed flows.
968 *
969 * @param dbHandler the Graph Database handler to use.
970 * @param flowIds the collection of Flow IDs to get.
971 * @return the Flow Paths if found, otherwise null.
972 */
Yuta HIGUCHI337e46d2014-01-10 22:49:27 -0800973 static ArrayList<FlowPath> getFlows(DBOperation dbHandler,
Pavlin Radoslavovf3f23bb2014-01-10 13:02:33 -0800974 Collection<FlowId> flowIds) {
975 ArrayList<FlowPath> flowPaths = new ArrayList<FlowPath>();
976
977 // TODO: This implementation should use threads
978 for (FlowId flowId : flowIds) {
979 FlowPath flowPath = getFlow(dbHandler, flowId);
980 if (flowPath != null)
981 flowPaths.add(flowPath);
982 }
983 // dbHandler.commit();
984
985 return flowPaths;
986 }
987
988 /**
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700989 * Extract Flow Path State from a Titan Database Object @ref IFlowPath.
990 *
991 * @param flowObj the object to extract the Flow Path State from.
992 * @return the extracted Flow Path State.
993 */
Brian O'Connor2c38efe2014-01-10 15:41:57 -0800994 static FlowPath extractFlowPath(IFlowPath flowObj) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700995 //
996 // Extract the Flow state
997 //
Toshio Koidea9b25142014-01-10 01:15:57 -0800998 log.info("extractFlowPath: start");
Yuta HIGUCHIcb32b2a2014-01-10 18:07:33 -0800999 String flowIdStr;
1000 String installerIdStr;
1001 String flowPathType;
1002 String flowPathUserState;
1003 Long flowPathFlags;
1004 Integer idleTimeout;
1005 Integer hardTimeout;
1006 String srcSwitchStr;
1007 Short srcPortShort;
1008 String dstSwitchStr;
1009 Short dstPortShort;
1010
1011 if ( flowObj.asVertex() instanceof RamCloudVertex ) {
1012 RamCloudVertex v = (RamCloudVertex)flowObj.asVertex();
1013 Map<String,Object> propMap = v.getProperties();
1014
1015 flowIdStr = (String) propMap.get("flow_id");
1016 installerIdStr = (String) propMap.get("installer_id");
1017 flowPathType = (String) propMap.get("flow_path_type");
1018 flowPathUserState = (String) propMap.get("user_state");
1019 flowPathFlags = (Long)propMap.get("flow_path_flags");
1020 idleTimeout = (Integer) propMap.get("idle_timeout");
1021 hardTimeout = (Integer) propMap.get("hard_timeout");
1022 srcSwitchStr = (String) propMap.get("src_switch");
1023 srcPortShort = (Short)propMap.get("src_port");
1024 dstSwitchStr = (String) propMap.get("dst_switch");
1025 dstPortShort = (Short)propMap.get("dst_port");
1026 } else {
1027 flowIdStr = flowObj.getFlowId();
1028 installerIdStr = flowObj.getInstallerId();
1029 flowPathType = flowObj.getFlowPathType();
1030 flowPathUserState = flowObj.getFlowPathUserState();
1031 flowPathFlags = flowObj.getFlowPathFlags();
1032 idleTimeout = flowObj.getIdleTimeout();
1033 hardTimeout = flowObj.getHardTimeout();
1034 srcSwitchStr = flowObj.getSrcSwitch();
1035 srcPortShort = flowObj.getSrcPort();
1036 dstSwitchStr = flowObj.getDstSwitch();
1037 dstPortShort = flowObj.getDstPort();
1038 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -07001039
1040 if ((flowIdStr == null) ||
1041 (installerIdStr == null) ||
Pavlin Radoslavovd28cf7c2013-10-26 11:27:43 -07001042 (flowPathType == null) ||
Pavlin Radoslavov7d4a40e2013-10-27 23:39:40 -07001043 (flowPathUserState == null) ||
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -07001044 (flowPathFlags == null) ||
Pavlin Radoslavov5139c0b2013-12-09 18:04:53 -08001045 (idleTimeout == null) ||
1046 (hardTimeout == null) ||
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -07001047 (srcSwitchStr == null) ||
1048 (srcPortShort == null) ||
1049 (dstSwitchStr == null) ||
1050 (dstPortShort == null)) {
Toshio Koidea9b25142014-01-10 01:15:57 -08001051 // TODO: A work-around, because of some bogus database objects
1052 log.error("extractFlowPath: wrong properties");
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -07001053 return null;
1054 }
1055
1056 FlowPath flowPath = new FlowPath();
1057 flowPath.setFlowId(new FlowId(flowIdStr));
1058 flowPath.setInstallerId(new CallerId(installerIdStr));
Pavlin Radoslavovd28cf7c2013-10-26 11:27:43 -07001059 flowPath.setFlowPathType(FlowPathType.valueOf(flowPathType));
Pavlin Radoslavov7d4a40e2013-10-27 23:39:40 -07001060 flowPath.setFlowPathUserState(FlowPathUserState.valueOf(flowPathUserState));
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -07001061 flowPath.setFlowPathFlags(new FlowPathFlags(flowPathFlags));
Pavlin Radoslavov5139c0b2013-12-09 18:04:53 -08001062 flowPath.setIdleTimeout(idleTimeout);
1063 flowPath.setHardTimeout(hardTimeout);
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -07001064 flowPath.dataPath().srcPort().setDpid(new Dpid(srcSwitchStr));
1065 flowPath.dataPath().srcPort().setPort(new Port(srcPortShort));
1066 flowPath.dataPath().dstPort().setDpid(new Dpid(dstSwitchStr));
1067 flowPath.dataPath().dstPort().setPort(new Port(dstPortShort));
1068 //
1069 // Extract the match conditions common for all Flow Entries
1070 //
1071 {
Yuta HIGUCHIcb32b2a2014-01-10 18:07:33 -08001072 FlowEntryMatch match = extractMatch(flowObj);
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -07001073
1074 flowPath.setFlowEntryMatch(match);
1075 }
1076 //
1077 // Extract the actions for the first Flow Entry
1078 //
1079 {
1080 String actionsStr = flowObj.getActions();
1081 if (actionsStr != null) {
1082 FlowEntryActions flowEntryActions = new FlowEntryActions(actionsStr);
1083 flowPath.setFlowEntryActions(flowEntryActions);
1084 }
1085 }
1086
1087 //
1088 // Extract all Flow Entries
1089 //
1090 Iterable<IFlowEntry> flowEntries = flowObj.getFlowEntries();
1091 for (IFlowEntry flowEntryObj : flowEntries) {
1092 FlowEntry flowEntry = extractFlowEntry(flowEntryObj);
1093 if (flowEntry == null)
1094 continue;
1095 flowPath.dataPath().flowEntries().add(flowEntry);
1096 }
1097
Toshio Koidea9b25142014-01-10 01:15:57 -08001098 log.info("extractFlowPath: end");
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -07001099 return flowPath;
1100 }
1101
1102 /**
1103 * Extract Flow Entry State from a Titan Database Object @ref IFlowEntry.
1104 *
1105 * @param flowEntryObj the object to extract the Flow Entry State from.
1106 * @return the extracted Flow Entry State.
1107 */
Brian O'Connora8e49802013-10-30 20:49:59 -07001108 public static FlowEntry extractFlowEntry(IFlowEntry flowEntryObj) {
Toshio Koidea9b25142014-01-10 01:15:57 -08001109 log.info("extractFlowEntry: start");
Pavlin Radoslavovcf87e532013-12-13 18:17:00 -08001110 IFlowPath flowObj = flowEntryObj.getFlow();
Toshio Koidea9b25142014-01-10 01:15:57 -08001111 if (flowObj == null) {
1112 log.error("extractFlowEntry: no flowPath exists");
Pavlin Radoslavovcf87e532013-12-13 18:17:00 -08001113 return null;
Toshio Koidea9b25142014-01-10 01:15:57 -08001114 }
Pavlin Radoslavovcf87e532013-12-13 18:17:00 -08001115
1116 String flowIdStr = flowObj.getFlowId();
1117 //
Yuta HIGUCHIcb32b2a2014-01-10 18:07:33 -08001118 String flowEntryIdStr;
1119 Integer idleTimeout;
1120 Integer hardTimeout;
1121 String switchDpidStr;
1122 String userState;
1123 String switchState;
1124 if ( flowEntryObj.asVertex() instanceof RamCloudVertex ) {
1125 RamCloudVertex v = (RamCloudVertex)flowEntryObj.asVertex();
1126 Map<String,Object> propMap = v.getProperties();
1127
1128 flowEntryIdStr = (String) propMap.get("flow_entry_id");
1129 idleTimeout = (Integer) propMap.get("idle_timeout");
1130 hardTimeout = (Integer) propMap.get("hard_timeout");
1131 switchDpidStr = (String) propMap.get("switch_dpid");
1132 userState = (String) propMap.get("user_state");
1133 switchState = (String) propMap.get("switch_state");
1134 } else {
1135 flowEntryIdStr = flowEntryObj.getFlowEntryId();
1136 idleTimeout = flowEntryObj.getIdleTimeout();
1137 hardTimeout = flowEntryObj.getHardTimeout();
1138 switchDpidStr = flowEntryObj.getSwitchDpid();
1139 userState = flowEntryObj.getUserState();
1140 switchState = flowEntryObj.getSwitchState();
1141 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -07001142
Pavlin Radoslavovcf87e532013-12-13 18:17:00 -08001143 if ((flowIdStr == null) ||
1144 (flowEntryIdStr == null) ||
Pavlin Radoslavov5139c0b2013-12-09 18:04:53 -08001145 (idleTimeout == null) ||
1146 (hardTimeout == null) ||
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -07001147 (switchDpidStr == null) ||
1148 (userState == null) ||
1149 (switchState == null)) {
Brian O'Connora8e49802013-10-30 20:49:59 -07001150 // TODO: A work-around, because of some bogus database objects
Toshio Koidea9b25142014-01-10 01:15:57 -08001151 log.error("extractFlowEntry: wrong properties");
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -07001152 return null;
1153 }
1154
1155 FlowEntry flowEntry = new FlowEntry();
1156 flowEntry.setFlowEntryId(new FlowEntryId(flowEntryIdStr));
Pavlin Radoslavovcf87e532013-12-13 18:17:00 -08001157 flowEntry.setFlowId(new FlowId(flowIdStr));
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -07001158 flowEntry.setDpid(new Dpid(switchDpidStr));
yoshia97632b2013-12-17 15:46:08 -08001159 flowEntry.setIdleTimeout(idleTimeout);
1160 flowEntry.setHardTimeout(hardTimeout);
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -07001161
1162 //
1163 // Extract the match conditions
1164 //
Yuta HIGUCHIcb32b2a2014-01-10 18:07:33 -08001165 FlowEntryMatch match = extractMatch(flowEntryObj);
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -07001166 flowEntry.setFlowEntryMatch(match);
1167
1168 //
1169 // Extract the actions
1170 //
1171 FlowEntryActions actions = new FlowEntryActions();
1172 String actionsStr = flowEntryObj.getActions();
1173 if (actionsStr != null)
1174 actions = new FlowEntryActions(actionsStr);
1175 flowEntry.setFlowEntryActions(actions);
1176 flowEntry.setFlowEntryUserState(FlowEntryUserState.valueOf(userState));
1177 flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.valueOf(switchState));
1178 //
1179 // TODO: Take care of FlowEntryErrorState.
1180 //
Toshio Koidea9b25142014-01-10 01:15:57 -08001181 log.info("extractFlowEntry: end");
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -07001182 return flowEntry;
1183 }
Yuta HIGUCHIcb32b2a2014-01-10 18:07:33 -08001184
1185 /**
1186 * Extract FlowEntryMatch from IFlowPath or IFlowEntry
1187 * @param flowObj : either IFlowPath or IFlowEntry
1188 * @return extracted Match info
1189 */
1190 private static FlowEntryMatch extractMatch(IBaseObject flowObj) {
1191 FlowEntryMatch match = new FlowEntryMatch();
1192
1193 Short matchInPort = null; // Only for IFlowEntry
1194 String matchSrcMac = null;
1195 String matchDstMac = null;
1196 Short matchEthernetFrameType = null;
1197 Short matchVlanId = null;
1198 Byte matchVlanPriority = null;
1199 String matchSrcIPv4Net = null;
1200 String matchDstIPv4Net = null;
1201 Byte matchIpProto = null;
1202 Byte matchIpToS = null;
1203 Short matchSrcTcpUdpPort = null;
1204 Short matchDstTcpUdpPort = null;
1205
1206 if ( flowObj.asVertex() instanceof RamCloudVertex ) {
1207 RamCloudVertex v = (RamCloudVertex)flowObj.asVertex();
1208 Map<String,Object> propMap = v.getProperties();
1209 matchInPort = (Short) propMap.get("matchInPort");
1210 matchSrcMac = (String) propMap.get("matchSrcMac");
1211 matchDstMac = (String) propMap.get("matchDstMac");
1212 matchEthernetFrameType = (Short) propMap.get("matchEthernetFrameType");
1213 matchVlanId = (Short) propMap.get("matchVlanId");
1214 matchVlanPriority = (Byte) propMap.get("matchVlanPriority");
1215 matchSrcIPv4Net = (String) propMap.get("matchSrcIPv4Net");
1216 matchDstIPv4Net = (String) propMap.get("matchDstIPv4Net");
1217 matchIpProto = (Byte) propMap.get("matchIpProto");
1218 matchIpToS = (Byte) propMap.get("matchIpToS");
1219 matchSrcTcpUdpPort = (Short) propMap.get("matchSrcTcpUdpPort");
1220 matchDstTcpUdpPort = (Short) propMap.get("matchDstTcpUdpPort");
1221 } else {
1222 if (flowObj instanceof IFlowEntry ){
1223 IFlowEntry flowEntry = (IFlowEntry) flowObj;
1224 matchInPort = flowEntry.getMatchInPort();
1225 matchSrcMac = flowEntry.getMatchSrcMac();
1226 matchDstMac = flowEntry.getMatchDstMac();
1227 matchEthernetFrameType = flowEntry.getMatchEthernetFrameType();
1228 matchVlanId = flowEntry.getMatchVlanId();
1229 matchVlanPriority = flowEntry.getMatchVlanPriority();
1230 matchSrcIPv4Net = flowEntry.getMatchSrcIPv4Net();
1231 matchDstIPv4Net = flowEntry.getMatchDstIPv4Net();
1232 matchIpProto = flowEntry.getMatchIpProto();
1233 matchIpToS = flowEntry.getMatchIpToS();
1234 matchSrcTcpUdpPort = flowEntry.getMatchSrcTcpUdpPort();
1235 matchDstTcpUdpPort = flowEntry.getMatchDstTcpUdpPort();
1236 } else if(flowObj instanceof IFlowPath) {
1237 IFlowPath flowPath = (IFlowPath) flowObj;
1238 matchSrcMac = flowPath.getMatchSrcMac();
1239 matchDstMac = flowPath.getMatchDstMac();
1240 matchEthernetFrameType = flowPath.getMatchEthernetFrameType();
1241 matchVlanId = flowPath.getMatchVlanId();
1242 matchVlanPriority = flowPath.getMatchVlanPriority();
1243 matchSrcIPv4Net = flowPath.getMatchSrcIPv4Net();
1244 matchDstIPv4Net = flowPath.getMatchDstIPv4Net();
1245 matchIpProto = flowPath.getMatchIpProto();
1246 matchIpToS = flowPath.getMatchIpToS();
1247 matchSrcTcpUdpPort = flowPath.getMatchSrcTcpUdpPort();
1248 matchDstTcpUdpPort = flowPath.getMatchDstTcpUdpPort();
1249 }
1250 }
1251
1252 if (matchInPort != null)
1253 match.enableInPort(new Port(matchInPort));
1254 if (matchSrcMac != null)
1255 match.enableSrcMac(MACAddress.valueOf(matchSrcMac));
1256 if (matchDstMac != null)
1257 match.enableDstMac(MACAddress.valueOf(matchDstMac));
1258 if (matchEthernetFrameType != null)
1259 match.enableEthernetFrameType(matchEthernetFrameType);
1260 if (matchVlanId != null)
1261 match.enableVlanId(matchVlanId);
1262 if (matchVlanPriority != null)
1263 match.enableVlanPriority(matchVlanPriority);
1264 if (matchSrcIPv4Net != null)
1265 match.enableSrcIPv4Net(new IPv4Net(matchSrcIPv4Net));
1266 if (matchDstIPv4Net != null)
1267 match.enableDstIPv4Net(new IPv4Net(matchDstIPv4Net));
1268 if (matchIpProto != null)
1269 match.enableIpProto(matchIpProto);
1270 if (matchIpToS != null)
1271 match.enableIpToS(matchIpToS);
1272 if (matchSrcTcpUdpPort != null)
1273 match.enableSrcTcpUdpPort(matchSrcTcpUdpPort);
1274 if (matchDstTcpUdpPort != null)
1275 match.enableDstTcpUdpPort(matchDstTcpUdpPort);
1276 return match;
1277 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -07001278}