blob: 5b97fa3cec84aa69578a47679e39eb8866ada7aa [file] [log] [blame]
Thomas Vachuska83e090e2014-10-22 14:25:35 -07001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2014-present Open Networking Laboratory
Thomas Vachuska83e090e2014-10-22 14:25:35 -07003 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07004 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
Thomas Vachuska83e090e2014-10-22 14:25:35 -07007 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07008 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
Thomas Vachuska83e090e2014-10-22 14:25:35 -070015 */
Brian O'Connorabafb502014-12-02 22:26:20 -080016package org.onosproject.net.flow;
alshabib7b2748f2014-09-16 20:21:11 -070017
Hyunsun Moon7bfbc1c2016-04-05 16:40:43 -070018import com.google.common.base.Charsets;
19import com.google.common.hash.Funnel;
20import com.google.common.hash.HashCode;
21import com.google.common.hash.HashFunction;
22import com.google.common.hash.Hashing;
Brian O'Connorabafb502014-12-02 22:26:20 -080023import org.onosproject.core.ApplicationId;
24import org.onosproject.core.DefaultGroupId;
25import org.onosproject.core.GroupId;
26import org.onosproject.net.DeviceId;
alshabib7b2748f2014-09-16 20:21:11 -070027
Jonathan Hart607b1ff2015-05-05 10:55:51 -070028import java.util.Objects;
29
30import static com.google.common.base.MoreObjects.toStringHelper;
31import static com.google.common.base.Preconditions.checkArgument;
32import static com.google.common.base.Preconditions.checkNotNull;
33
Jonathan Hart2b3e22b2017-02-03 18:31:13 -080034/**
35 * Default flow rule.
36 */
alshabib7b2748f2014-09-16 20:21:11 -070037public class DefaultFlowRule implements FlowRule {
38
Ayaka Koshibed4e53e12014-09-18 14:24:55 -070039 private final DeviceId deviceId;
40 private final int priority;
alshabib7b2748f2014-09-16 20:21:11 -070041 private final TrafficSelector selector;
42 private final TrafficTreatment treatment;
Ayaka Koshibed4e53e12014-09-18 14:24:55 -070043 private final long created;
44
alshabib219ebaa2014-09-22 15:41:24 -070045 private final FlowId id;
Ayaka Koshibed4e53e12014-09-18 14:24:55 -070046
alshabibdb774072015-04-20 13:13:51 -070047 private final Short appId;
alshabiba68eb962014-09-24 20:34:13 -070048
alshabibba5ac482014-10-02 17:15:20 -070049 private final int timeout;
Jonathan Hartbc4a7932014-10-21 11:46:00 -070050 private final boolean permanent;
Murat Parlakisikc6759e82016-06-29 03:22:22 -070051 private final int hardTimeout;
52 private final FlowRemoveReason reason;
Sho SHIMIZU75a5bd92014-11-25 11:22:56 -080053 private final GroupId groupId;
alshabib6eb438a2014-10-01 16:39:37 -070054
alshabibdb774072015-04-20 13:13:51 -070055 private final Integer tableId;
jcc3d4e14a2015-04-21 11:32:05 +080056 private final FlowRuleExtPayLoad payLoad;
alshabib1c319ff2014-10-04 20:29:09 -070057
Jonathan Hart2b3e22b2017-02-03 18:31:13 -080058 /**
59 * Creates a new flow rule from an existing rule.
60 *
61 * @param rule new flow rule
62 */
alshabib1c319ff2014-10-04 20:29:09 -070063 public DefaultFlowRule(FlowRule rule) {
64 this.deviceId = rule.deviceId();
65 this.priority = rule.priority();
66 this.selector = rule.selector();
67 this.treatment = rule.treatment();
68 this.appId = rule.appId();
alshabib28204e52014-11-12 18:29:45 -080069 this.groupId = rule.groupId();
alshabib1c319ff2014-10-04 20:29:09 -070070 this.id = rule.id();
71 this.timeout = rule.timeout();
Murat Parlakisikc6759e82016-06-29 03:22:22 -070072 this.hardTimeout = rule.hardTimeout();
73 this.reason = rule.reason();
Jonathan Hartbc4a7932014-10-21 11:46:00 -070074 this.permanent = rule.isPermanent();
alshabib219ebaa2014-09-22 15:41:24 -070075 this.created = System.currentTimeMillis();
alshabibdb774072015-04-20 13:13:51 -070076 this.tableId = rule.tableId();
jcc3d4e14a2015-04-21 11:32:05 +080077 this.payLoad = rule.payLoad();
alshabibdb774072015-04-20 13:13:51 -070078 }
79
80 private DefaultFlowRule(DeviceId deviceId, TrafficSelector selector,
81 TrafficTreatment treatment, Integer priority,
Murat Parlakisikc6759e82016-06-29 03:22:22 -070082 FlowId flowId, Boolean permanent, Integer timeout, Integer hardTimeout,
83 FlowRemoveReason reason, Integer tableId) {
alshabibdb774072015-04-20 13:13:51 -070084
85 this.deviceId = deviceId;
86 this.selector = selector;
87 this.treatment = treatment;
88 this.priority = priority;
89 this.appId = (short) (flowId.value() >>> 48);
90 this.id = flowId;
91 this.permanent = permanent;
92 this.timeout = timeout;
Murat Parlakisikc6759e82016-06-29 03:22:22 -070093 this.hardTimeout = hardTimeout;
94 this.reason = reason;
alshabibdb774072015-04-20 13:13:51 -070095 this.tableId = tableId;
96 this.created = System.currentTimeMillis();
97
98
99 //FIXME: fields below will be removed.
Jonathan Hart607b1ff2015-05-05 10:55:51 -0700100 this.groupId = new DefaultGroupId(0);
jcc3d4e14a2015-04-21 11:32:05 +0800101 this.payLoad = null;
102 }
alshabibdb774072015-04-20 13:13:51 -0700103
jcc3d4e14a2015-04-21 11:32:05 +0800104 /**
105 * Support for the third party flow rule. Creates a flow rule of flow table.
106 *
107 * @param deviceId the identity of the device where this rule applies
108 * @param selector the traffic selector that identifies what traffic this
109 * rule
110 * @param treatment the traffic treatment that applies to selected traffic
111 * @param priority the flow rule priority given in natural order
112 * @param appId the application id of this flow
113 * @param timeout the timeout for this flow requested by an application
114 * @param permanent whether the flow is permanent i.e. does not time out
115 * @param payLoad 3rd-party origin private flow
Jonathan Hart2b3e22b2017-02-03 18:31:13 -0800116 * @deprecated in Junco release. Use FlowRule.Builder instead.
jcc3d4e14a2015-04-21 11:32:05 +0800117 */
Jonathan Hart2b3e22b2017-02-03 18:31:13 -0800118 @Deprecated
jcc3d4e14a2015-04-21 11:32:05 +0800119 public DefaultFlowRule(DeviceId deviceId, TrafficSelector selector,
120 TrafficTreatment treatment, int priority,
121 ApplicationId appId, int timeout, boolean permanent,
122 FlowRuleExtPayLoad payLoad) {
Murat Parlakisikc6759e82016-06-29 03:22:22 -0700123 this(deviceId, selector, treatment, priority, appId, timeout, 0, permanent, payLoad);
124 }
125
126
127 /**
128 * Support for the third party flow rule. Creates a flow rule of flow table.
129 *
130 * @param deviceId the identity of the device where this rule applies
131 * @param selector the traffic selector that identifies what traffic this
132 * rule
133 * @param treatment the traffic treatment that applies to selected traffic
134 * @param priority the flow rule priority given in natural order
135 * @param appId the application id of this flow
136 * @param timeout the timeout for this flow requested by an application
137 * @param hardTimeout the hard timeout located switch's flow table for this flow requested by an application
138 * @param permanent whether the flow is permanent i.e. does not time out
139 * @param payLoad 3rd-party origin private flow
Jonathan Hart2b3e22b2017-02-03 18:31:13 -0800140 * @deprecated in Junco release. Use FlowRule.Builder instead.
Murat Parlakisikc6759e82016-06-29 03:22:22 -0700141 */
Jonathan Hart2b3e22b2017-02-03 18:31:13 -0800142 @Deprecated
Murat Parlakisikc6759e82016-06-29 03:22:22 -0700143 public DefaultFlowRule(DeviceId deviceId, TrafficSelector selector,
144 TrafficTreatment treatment, int priority,
145 ApplicationId appId, int timeout, int hardTimeout, boolean permanent,
146 FlowRuleExtPayLoad payLoad) {
alshabib1c319ff2014-10-04 20:29:09 -0700147
Kavitha Alagesan14dc5132016-06-13 17:25:18 +0530148 checkArgument(priority >= MIN_PRIORITY, "Priority cannot be less than " +
149 MIN_PRIORITY);
150 checkArgument(priority <= MAX_PRIORITY, "Priority cannot be greater than " +
151 MAX_PRIORITY);
jcc3d4e14a2015-04-21 11:32:05 +0800152
153 this.deviceId = deviceId;
154 this.priority = priority;
155 this.selector = selector;
156 this.treatment = treatment;
157 this.appId = appId.id();
158 this.groupId = new DefaultGroupId(0);
159 this.timeout = timeout;
Murat Parlakisikc6759e82016-06-29 03:22:22 -0700160 this.reason = FlowRemoveReason.NO_REASON;
161 this.hardTimeout = hardTimeout;
jcc3d4e14a2015-04-21 11:32:05 +0800162 this.permanent = permanent;
163 this.tableId = 0;
164 this.created = System.currentTimeMillis();
165 this.payLoad = payLoad;
166
167 /*
168 * id consists of the following. | appId (16 bits) | groupId (16 bits) |
169 * flowId (32 bits) |
170 */
171 this.id = FlowId.valueOf((((long) this.appId) << 48)
172 | (((long) this.groupId.id()) << 32)
173 | (this.hash() & 0xffffffffL));
174 }
175
176 /**
177 * Support for the third party flow rule. Creates a flow rule of group
178 * table.
179 *
180 * @param deviceId the identity of the device where this rule applies
181 * @param selector the traffic selector that identifies what traffic this
182 * rule
183 * @param treatment the traffic treatment that applies to selected traffic
184 * @param priority the flow rule priority given in natural order
185 * @param appId the application id of this flow
186 * @param groupId the group id of this flow
187 * @param timeout the timeout for this flow requested by an application
188 * @param permanent whether the flow is permanent i.e. does not time out
189 * @param payLoad 3rd-party origin private flow
Jonathan Hart2b3e22b2017-02-03 18:31:13 -0800190 * @deprecated in Junco release. Use FlowRule.Builder instead.
jcc3d4e14a2015-04-21 11:32:05 +0800191 */
Jonathan Hart2b3e22b2017-02-03 18:31:13 -0800192 @Deprecated
jcc3d4e14a2015-04-21 11:32:05 +0800193 public DefaultFlowRule(DeviceId deviceId, TrafficSelector selector,
194 TrafficTreatment treatment, int priority,
195 ApplicationId appId, GroupId groupId, int timeout,
196 boolean permanent, FlowRuleExtPayLoad payLoad) {
Murat Parlakisikc6759e82016-06-29 03:22:22 -0700197 this(deviceId, selector, treatment, priority, appId, groupId, timeout, 0, permanent, payLoad);
198 }
199
200 /**
201 * Support for the third party flow rule. Creates a flow rule of group
202 * table.
203 *
204 * @param deviceId the identity of the device where this rule applies
205 * @param selector the traffic selector that identifies what traffic this
206 * rule
207 * @param treatment the traffic treatment that applies to selected traffic
208 * @param priority the flow rule priority given in natural order
209 * @param appId the application id of this flow
210 * @param groupId the group id of this flow
211 * @param timeout the timeout for this flow requested by an application
212 * @param hardTimeout the hard timeout located switch's flow table for this flow requested by an application
213 * @param permanent whether the flow is permanent i.e. does not time out
214 * @param payLoad 3rd-party origin private flow
Jonathan Hart2b3e22b2017-02-03 18:31:13 -0800215 * @deprecated in Junco release. Use FlowRule.Builder instead.
Murat Parlakisikc6759e82016-06-29 03:22:22 -0700216 */
Jonathan Hart2b3e22b2017-02-03 18:31:13 -0800217 @Deprecated
Murat Parlakisikc6759e82016-06-29 03:22:22 -0700218 public DefaultFlowRule(DeviceId deviceId, TrafficSelector selector,
219 TrafficTreatment treatment, int priority,
220 ApplicationId appId, GroupId groupId, int timeout, int hardTimeout,
221 boolean permanent, FlowRuleExtPayLoad payLoad) {
jcc3d4e14a2015-04-21 11:32:05 +0800222
Kavitha Alagesan14dc5132016-06-13 17:25:18 +0530223 checkArgument(priority >= MIN_PRIORITY, "Priority cannot be less than " +
224 MIN_PRIORITY);
225 checkArgument(priority <= MAX_PRIORITY, "Priority cannot be greater than " +
226 MAX_PRIORITY);
jcc3d4e14a2015-04-21 11:32:05 +0800227
228 this.deviceId = deviceId;
229 this.priority = priority;
230 this.selector = selector;
231 this.treatment = treatment;
232 this.appId = appId.id();
233 this.groupId = groupId;
234 this.timeout = timeout;
Murat Parlakisikc6759e82016-06-29 03:22:22 -0700235 this.reason = FlowRemoveReason.NO_REASON;
236 this.hardTimeout = hardTimeout;
jcc3d4e14a2015-04-21 11:32:05 +0800237 this.permanent = permanent;
238 this.created = System.currentTimeMillis();
239 this.tableId = 0;
240 this.payLoad = payLoad;
241
242 /*
243 * id consists of the following. | appId (16 bits) | groupId (16 bits) |
244 * flowId (32 bits) |
245 */
246 this.id = FlowId.valueOf((((long) this.appId) << 48)
247 | (((long) this.groupId.id()) << 32)
248 | (this.hash() & 0xffffffffL));
alshabiba7f7ca82014-09-22 11:41:23 -0700249 }
250
Ayaka Koshibed4e53e12014-09-18 14:24:55 -0700251 @Override
252 public FlowId id() {
253 return id;
alshabib7b2748f2014-09-16 20:21:11 -0700254 }
255
256 @Override
alshabib92c65ad2014-10-08 21:56:05 -0700257 public short appId() {
alshabiba68eb962014-09-24 20:34:13 -0700258 return appId;
259 }
260
261 @Override
Sho SHIMIZU75a5bd92014-11-25 11:22:56 -0800262 public GroupId groupId() {
alshabib28204e52014-11-12 18:29:45 -0800263 return groupId;
264 }
265
266 @Override
alshabib7b2748f2014-09-16 20:21:11 -0700267 public int priority() {
Ayaka Koshibed4e53e12014-09-18 14:24:55 -0700268 return priority;
alshabib7b2748f2014-09-16 20:21:11 -0700269 }
270
271 @Override
272 public DeviceId deviceId() {
273 return deviceId;
274 }
275
276 @Override
277 public TrafficSelector selector() {
278 return selector;
279 }
280
281 @Override
282 public TrafficTreatment treatment() {
283 return treatment;
284 }
285
Ayaka Koshibed4e53e12014-09-18 14:24:55 -0700286 /*
287 * The priority and statistics can change on a given treatment and selector
288 *
289 * (non-Javadoc)
jcc3d4e14a2015-04-21 11:32:05 +0800290 *
Ayaka Koshibed4e53e12014-09-18 14:24:55 -0700291 * @see java.lang.Object#equals(java.lang.Object)
292 */
Jonathan Hart2b3e22b2017-02-03 18:31:13 -0800293 @Override
Ayaka Koshibe08eabaa2014-09-17 14:59:25 -0700294 public int hashCode() {
Thomas Vachuska711db552015-06-02 16:35:26 -0700295 return Objects.hash(deviceId, selector, tableId, payLoad);
alshabiba68eb962014-09-24 20:34:13 -0700296 }
297
Thomas Vachuska711db552015-06-02 16:35:26 -0700298 //FIXME do we need this method in addition to hashCode()?
299 private int hash() {
300 return Objects.hash(deviceId, selector, tableId, payLoad);
Ayaka Koshibe08eabaa2014-09-17 14:59:25 -0700301 }
302
Ayaka Koshibe08eabaa2014-09-17 14:59:25 -0700303 /*
304 * The priority and statistics can change on a given treatment and selector
305 *
306 * (non-Javadoc)
jcc3d4e14a2015-04-21 11:32:05 +0800307 *
Ayaka Koshibe08eabaa2014-09-17 14:59:25 -0700308 * @see java.lang.Object#equals(java.lang.Object)
309 */
Jonathan Hart2b3e22b2017-02-03 18:31:13 -0800310 @Override
Ayaka Koshibe08eabaa2014-09-17 14:59:25 -0700311 public boolean equals(Object obj) {
alshabiba7f7ca82014-09-22 11:41:23 -0700312 if (this == obj) {
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700313 return true;
Ayaka Koshibe08eabaa2014-09-17 14:59:25 -0700314 }
alshabib54ce5892014-09-23 17:50:51 -0700315 if (obj instanceof DefaultFlowRule) {
alshabib219ebaa2014-09-22 15:41:24 -0700316 DefaultFlowRule that = (DefaultFlowRule) obj;
317 return Objects.equals(deviceId, that.deviceId) &&
alshabibba5ac482014-10-02 17:15:20 -0700318 Objects.equals(priority, that.priority) &&
Saurav Dascbe6de32015-03-01 18:30:46 -0800319 Objects.equals(selector, that.selector) &&
jcc3d4e14a2015-04-21 11:32:05 +0800320 Objects.equals(tableId, that.tableId)
321 && Objects.equals(payLoad, that.payLoad);
alshabiba7f7ca82014-09-22 11:41:23 -0700322 }
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700323 return false;
Ayaka Koshibe08eabaa2014-09-17 14:59:25 -0700324 }
325
Ayaka Koshibed4e53e12014-09-18 14:24:55 -0700326 @Override
Jonathan Hartf44e42c2015-08-04 09:58:46 -0700327 public boolean exactMatch(FlowRule rule) {
328 return this.equals(rule) &&
329 Objects.equals(this.id, rule.id()) &&
330 Objects.equals(this.treatment, rule.treatment());
331 }
332
333 @Override
Ayaka Koshibed4e53e12014-09-18 14:24:55 -0700334 public String toString() {
335 return toStringHelper(this)
alshabib8ca53902014-10-07 13:11:17 -0700336 .add("id", Long.toHexString(id.value()))
Ayaka Koshibed4e53e12014-09-18 14:24:55 -0700337 .add("deviceId", deviceId)
338 .add("priority", priority)
alshabibba5ac482014-10-02 17:15:20 -0700339 .add("selector", selector.criteria())
Jian Lif0325112016-03-03 17:11:25 -0800340 .add("treatment", treatment == null ? "N/A" : treatment)
alshabib08d98982015-04-21 16:25:50 -0700341 .add("tableId", tableId)
Ayaka Koshibed4e53e12014-09-18 14:24:55 -0700342 .add("created", created)
Ray Milkeyd13a37b2015-06-12 11:55:17 -0700343 .add("payLoad", payLoad)
Ayaka Koshibed4e53e12014-09-18 14:24:55 -0700344 .toString();
345 }
Ayaka Koshibe08eabaa2014-09-17 14:59:25 -0700346
alshabib6eb438a2014-10-01 16:39:37 -0700347 @Override
alshabibba5ac482014-10-02 17:15:20 -0700348 public int timeout() {
alshabib58747a62014-10-07 11:05:30 -0700349 return timeout;
alshabib6eb438a2014-10-01 16:39:37 -0700350 }
351
Murat Parlakisikc6759e82016-06-29 03:22:22 -0700352 @Override
353 public int hardTimeout() {
354 return hardTimeout;
355 }
356
357 @Override
358 public FlowRemoveReason reason() {
359 return reason;
360 }
361
Jonathan Hartbc4a7932014-10-21 11:46:00 -0700362 @Override
363 public boolean isPermanent() {
364 return permanent;
365 }
366
sangho11c30ac2015-01-22 14:30:55 -0800367 @Override
alshabibdb774072015-04-20 13:13:51 -0700368 public int tableId() {
369 return tableId;
370 }
371
Jonathan Hart2b3e22b2017-02-03 18:31:13 -0800372 /**
373 * Returns the wallclock time that the flow was created.
374 *
375 * @return creation time in milliseconds since epoch
376 */
Brian O'Connora3e5cd52015-12-05 15:59:19 -0800377 public long created() {
378 return created;
379 }
380
Jonathan Hart2b3e22b2017-02-03 18:31:13 -0800381 /**
382 * Returns a default flow rule builder.
383 *
384 * @return builder
385 */
alshabibdb774072015-04-20 13:13:51 -0700386 public static Builder builder() {
387 return new Builder();
388 }
389
Jonathan Hart2b3e22b2017-02-03 18:31:13 -0800390 /**
391 * Default flow rule builder.
392 */
alshabibd17abc22015-04-21 18:26:35 -0700393 public static final class Builder implements FlowRule.Builder {
alshabibdb774072015-04-20 13:13:51 -0700394
395 private FlowId flowId;
Jonathan Hart65d551b2015-09-22 09:49:09 -0700396 private ApplicationId appId;
alshabibdb774072015-04-20 13:13:51 -0700397 private Integer priority;
398 private DeviceId deviceId;
399 private Integer tableId = 0;
Charles Chancc4754d2015-12-10 15:58:18 -0800400 private TrafficSelector selector = DefaultTrafficSelector.builder().build();
401 private TrafficTreatment treatment = DefaultTrafficTreatment.builder().build();
alshabibdb774072015-04-20 13:13:51 -0700402 private Integer timeout;
403 private Boolean permanent;
Murat Parlakisikc6759e82016-06-29 03:22:22 -0700404 private Integer hardTimeout = 0;
405 private FlowRemoveReason reason = FlowRemoveReason.NO_REASON;
alshabibdb774072015-04-20 13:13:51 -0700406
407 @Override
408 public FlowRule.Builder withCookie(long cookie) {
409 this.flowId = FlowId.valueOf(cookie);
410 return this;
411 }
412
413 @Override
414 public FlowRule.Builder fromApp(ApplicationId appId) {
Jonathan Hart65d551b2015-09-22 09:49:09 -0700415 this.appId = appId;
alshabibdb774072015-04-20 13:13:51 -0700416 return this;
417 }
418
419 @Override
420 public FlowRule.Builder withPriority(int priority) {
421 this.priority = priority;
422 return this;
423 }
424
425 @Override
426 public FlowRule.Builder forDevice(DeviceId deviceId) {
427 this.deviceId = deviceId;
428 return this;
429 }
430
431 @Override
432 public FlowRule.Builder forTable(int tableId) {
433 this.tableId = tableId;
434 return this;
435 }
436
437 @Override
438 public FlowRule.Builder withSelector(TrafficSelector selector) {
439 this.selector = selector;
440 return this;
441 }
442
443 @Override
444 public FlowRule.Builder withTreatment(TrafficTreatment treatment) {
Jonathan Hart24e296b2016-01-12 14:47:07 -0800445 this.treatment = checkNotNull(treatment);
alshabibdb774072015-04-20 13:13:51 -0700446 return this;
447 }
448
449 @Override
450 public FlowRule.Builder makePermanent() {
451 this.timeout = 0;
452 this.permanent = true;
453 return this;
454 }
455
456 @Override
457 public FlowRule.Builder makeTemporary(int timeout) {
458 this.permanent = false;
459 this.timeout = timeout;
460 return this;
461 }
462
463 @Override
Murat Parlakisikc6759e82016-06-29 03:22:22 -0700464 public FlowRule.Builder withHardTimeout(int timeout) {
465 this.permanent = false;
466 this.hardTimeout = timeout;
467 this.timeout = timeout;
468 return this;
469 }
470
471 @Override
472 public FlowRule.Builder withReason(FlowRemoveReason reason) {
473 this.reason = reason;
474 return this;
475 }
476
477 @Override
alshabibdb774072015-04-20 13:13:51 -0700478 public FlowRule build() {
alshabibb05be2d2016-04-11 12:52:36 -0700479 FlowId localFlowId;
Jian Li8bac5762016-02-09 17:23:09 -0800480 checkArgument((flowId != null) ^ (appId != null), "Either an application" +
alshabibdb774072015-04-20 13:13:51 -0700481 " id or a cookie must be supplied");
Jonathan Hart65d551b2015-09-22 09:49:09 -0700482 checkNotNull(selector, "Traffic selector cannot be null");
483 checkArgument(timeout != null || permanent != null, "Must either have " +
alshabibdb774072015-04-20 13:13:51 -0700484 "a timeout or be permanent");
Jonathan Hart65d551b2015-09-22 09:49:09 -0700485 checkNotNull(deviceId, "Must refer to a device");
486 checkNotNull(priority, "Priority cannot be null");
Saurav Das3ea46622015-04-22 14:01:34 -0700487 checkArgument(priority >= MIN_PRIORITY, "Priority cannot be less than " +
alshabibdb774072015-04-20 13:13:51 -0700488 MIN_PRIORITY);
Kavitha Alagesan14dc5132016-06-13 17:25:18 +0530489 checkArgument(priority <= MAX_PRIORITY, "Priority cannot be greater than " +
490 MAX_PRIORITY);
Jonathan Hart65d551b2015-09-22 09:49:09 -0700491 // Computing a flow ID based on appId takes precedence over setting
492 // the flow ID directly
493 if (appId != null) {
alshabibb05be2d2016-04-11 12:52:36 -0700494 localFlowId = computeFlowId(appId);
495 } else {
496 localFlowId = flowId;
Jonathan Hart65d551b2015-09-22 09:49:09 -0700497 }
498
alshabibdb774072015-04-20 13:13:51 -0700499 return new DefaultFlowRule(deviceId, selector, treatment, priority,
Murat Parlakisikc6759e82016-06-29 03:22:22 -0700500 localFlowId, permanent, timeout, hardTimeout, reason, tableId);
alshabibdb774072015-04-20 13:13:51 -0700501 }
502
503 private FlowId computeFlowId(ApplicationId appId) {
504 return FlowId.valueOf((((long) appId.id()) << 48)
505 | (hash() & 0xffffffffL));
506 }
507
508 private int hash() {
Hyunsun Moon7bfbc1c2016-04-05 16:40:43 -0700509 Funnel<TrafficSelector> selectorFunnel = (from, into) -> from.criteria()
Hyunsun Moon7bfbc1c2016-04-05 16:40:43 -0700510 .forEach(c -> into.putString(c.toString(), Charsets.UTF_8));
alshabibdb774072015-04-20 13:13:51 -0700511
Hyunsun Moon7bfbc1c2016-04-05 16:40:43 -0700512 HashFunction hashFunction = Hashing.murmur3_32();
513 HashCode hashCode = hashFunction.newHasher()
514 .putString(deviceId.toString(), Charsets.UTF_8)
515 .putObject(selector, selectorFunnel)
516 .putInt(priority)
517 .putInt(tableId)
518 .hash();
519
520 return hashCode.asInt();
521 }
alshabibdb774072015-04-20 13:13:51 -0700522 }
523
jcc3d4e14a2015-04-21 11:32:05 +0800524 @Override
525 public FlowRuleExtPayLoad payLoad() {
526 return payLoad;
527 }
528
alshabib7b2748f2014-09-16 20:21:11 -0700529}