blob: 0a8ecfb0cf10aa0302add3ed4f29ab9c5f1bd7b1 [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.hash.Funnel;
19import com.google.common.hash.HashCode;
20import com.google.common.hash.HashFunction;
21import com.google.common.hash.Hashing;
Brian O'Connorabafb502014-12-02 22:26:20 -080022import org.onosproject.core.ApplicationId;
Brian O'Connorabafb502014-12-02 22:26:20 -080023import org.onosproject.core.GroupId;
24import org.onosproject.net.DeviceId;
alshabib7b2748f2014-09-16 20:21:11 -070025
Jonathan Hart607b1ff2015-05-05 10:55:51 -070026import java.util.Objects;
27
28import static com.google.common.base.MoreObjects.toStringHelper;
29import static com.google.common.base.Preconditions.checkArgument;
30import static com.google.common.base.Preconditions.checkNotNull;
31
Jonathan Hart2b3e22b2017-02-03 18:31:13 -080032/**
33 * Default flow rule.
34 */
alshabib7b2748f2014-09-16 20:21:11 -070035public class DefaultFlowRule implements FlowRule {
36
Ayaka Koshibed4e53e12014-09-18 14:24:55 -070037 private final DeviceId deviceId;
38 private final int priority;
alshabib7b2748f2014-09-16 20:21:11 -070039 private final TrafficSelector selector;
40 private final TrafficTreatment treatment;
Ayaka Koshibed4e53e12014-09-18 14:24:55 -070041 private final long created;
42
alshabib219ebaa2014-09-22 15:41:24 -070043 private final FlowId id;
Ayaka Koshibed4e53e12014-09-18 14:24:55 -070044
alshabibdb774072015-04-20 13:13:51 -070045 private final Short appId;
alshabiba68eb962014-09-24 20:34:13 -070046
alshabibba5ac482014-10-02 17:15:20 -070047 private final int timeout;
Jonathan Hartbc4a7932014-10-21 11:46:00 -070048 private final boolean permanent;
Murat Parlakisikc6759e82016-06-29 03:22:22 -070049 private final int hardTimeout;
50 private final FlowRemoveReason reason;
Sho SHIMIZU75a5bd92014-11-25 11:22:56 -080051 private final GroupId groupId;
alshabib6eb438a2014-10-01 16:39:37 -070052
alshabibdb774072015-04-20 13:13:51 -070053 private final Integer tableId;
jcc3d4e14a2015-04-21 11:32:05 +080054 private final FlowRuleExtPayLoad payLoad;
alshabib1c319ff2014-10-04 20:29:09 -070055
Jonathan Hart2b3e22b2017-02-03 18:31:13 -080056 /**
57 * Creates a new flow rule from an existing rule.
58 *
59 * @param rule new flow rule
60 */
alshabib1c319ff2014-10-04 20:29:09 -070061 public DefaultFlowRule(FlowRule rule) {
62 this.deviceId = rule.deviceId();
63 this.priority = rule.priority();
64 this.selector = rule.selector();
65 this.treatment = rule.treatment();
66 this.appId = rule.appId();
alshabib28204e52014-11-12 18:29:45 -080067 this.groupId = rule.groupId();
alshabib1c319ff2014-10-04 20:29:09 -070068 this.id = rule.id();
69 this.timeout = rule.timeout();
Murat Parlakisikc6759e82016-06-29 03:22:22 -070070 this.hardTimeout = rule.hardTimeout();
71 this.reason = rule.reason();
Jonathan Hartbc4a7932014-10-21 11:46:00 -070072 this.permanent = rule.isPermanent();
alshabib219ebaa2014-09-22 15:41:24 -070073 this.created = System.currentTimeMillis();
alshabibdb774072015-04-20 13:13:51 -070074 this.tableId = rule.tableId();
jcc3d4e14a2015-04-21 11:32:05 +080075 this.payLoad = rule.payLoad();
alshabibdb774072015-04-20 13:13:51 -070076 }
77
78 private DefaultFlowRule(DeviceId deviceId, TrafficSelector selector,
79 TrafficTreatment treatment, Integer priority,
Murat Parlakisikc6759e82016-06-29 03:22:22 -070080 FlowId flowId, Boolean permanent, Integer timeout, Integer hardTimeout,
81 FlowRemoveReason reason, Integer tableId) {
alshabibdb774072015-04-20 13:13:51 -070082
83 this.deviceId = deviceId;
84 this.selector = selector;
85 this.treatment = treatment;
86 this.priority = priority;
87 this.appId = (short) (flowId.value() >>> 48);
88 this.id = flowId;
89 this.permanent = permanent;
90 this.timeout = timeout;
Murat Parlakisikc6759e82016-06-29 03:22:22 -070091 this.hardTimeout = hardTimeout;
92 this.reason = reason;
alshabibdb774072015-04-20 13:13:51 -070093 this.tableId = tableId;
94 this.created = System.currentTimeMillis();
95
96
97 //FIXME: fields below will be removed.
Yi Tsengfa394de2017-02-01 11:26:40 -080098 this.groupId = new GroupId(0);
jcc3d4e14a2015-04-21 11:32:05 +080099 this.payLoad = null;
100 }
alshabibdb774072015-04-20 13:13:51 -0700101
jcc3d4e14a2015-04-21 11:32:05 +0800102 /**
103 * Support for the third party flow rule. Creates a flow rule of flow table.
104 *
105 * @param deviceId the identity of the device where this rule applies
106 * @param selector the traffic selector that identifies what traffic this
107 * rule
108 * @param treatment the traffic treatment that applies to selected traffic
109 * @param priority the flow rule priority given in natural order
110 * @param appId the application id of this flow
111 * @param timeout the timeout for this flow requested by an application
112 * @param permanent whether the flow is permanent i.e. does not time out
113 * @param payLoad 3rd-party origin private flow
Jonathan Hart2b3e22b2017-02-03 18:31:13 -0800114 * @deprecated in Junco release. Use FlowRule.Builder instead.
jcc3d4e14a2015-04-21 11:32:05 +0800115 */
Jonathan Hart2b3e22b2017-02-03 18:31:13 -0800116 @Deprecated
jcc3d4e14a2015-04-21 11:32:05 +0800117 public DefaultFlowRule(DeviceId deviceId, TrafficSelector selector,
118 TrafficTreatment treatment, int priority,
119 ApplicationId appId, int timeout, boolean permanent,
120 FlowRuleExtPayLoad payLoad) {
Murat Parlakisikc6759e82016-06-29 03:22:22 -0700121 this(deviceId, selector, treatment, priority, appId, timeout, 0, permanent, payLoad);
122 }
123
124
125 /**
126 * Support for the third party flow rule. Creates a flow rule of flow table.
127 *
128 * @param deviceId the identity of the device where this rule applies
129 * @param selector the traffic selector that identifies what traffic this
130 * rule
131 * @param treatment the traffic treatment that applies to selected traffic
132 * @param priority the flow rule priority given in natural order
133 * @param appId the application id of this flow
134 * @param timeout the timeout for this flow requested by an application
135 * @param hardTimeout the hard timeout located switch's flow table for this flow requested by an application
136 * @param permanent whether the flow is permanent i.e. does not time out
137 * @param payLoad 3rd-party origin private flow
Jonathan Hart2b3e22b2017-02-03 18:31:13 -0800138 * @deprecated in Junco release. Use FlowRule.Builder instead.
Murat Parlakisikc6759e82016-06-29 03:22:22 -0700139 */
Jonathan Hart2b3e22b2017-02-03 18:31:13 -0800140 @Deprecated
Murat Parlakisikc6759e82016-06-29 03:22:22 -0700141 public DefaultFlowRule(DeviceId deviceId, TrafficSelector selector,
142 TrafficTreatment treatment, int priority,
143 ApplicationId appId, int timeout, int hardTimeout, boolean permanent,
144 FlowRuleExtPayLoad payLoad) {
alshabib1c319ff2014-10-04 20:29:09 -0700145
Kavitha Alagesan14dc5132016-06-13 17:25:18 +0530146 checkArgument(priority >= MIN_PRIORITY, "Priority cannot be less than " +
147 MIN_PRIORITY);
148 checkArgument(priority <= MAX_PRIORITY, "Priority cannot be greater than " +
149 MAX_PRIORITY);
jcc3d4e14a2015-04-21 11:32:05 +0800150
151 this.deviceId = deviceId;
152 this.priority = priority;
153 this.selector = selector;
154 this.treatment = treatment;
155 this.appId = appId.id();
Yi Tsengfa394de2017-02-01 11:26:40 -0800156 this.groupId = new GroupId(0);
jcc3d4e14a2015-04-21 11:32:05 +0800157 this.timeout = timeout;
Murat Parlakisikc6759e82016-06-29 03:22:22 -0700158 this.reason = FlowRemoveReason.NO_REASON;
159 this.hardTimeout = hardTimeout;
jcc3d4e14a2015-04-21 11:32:05 +0800160 this.permanent = permanent;
161 this.tableId = 0;
162 this.created = System.currentTimeMillis();
163 this.payLoad = payLoad;
164
165 /*
166 * id consists of the following. | appId (16 bits) | groupId (16 bits) |
167 * flowId (32 bits) |
168 */
169 this.id = FlowId.valueOf((((long) this.appId) << 48)
170 | (((long) this.groupId.id()) << 32)
171 | (this.hash() & 0xffffffffL));
172 }
173
174 /**
175 * Support for the third party flow rule. Creates a flow rule of group
176 * table.
177 *
178 * @param deviceId the identity of the device where this rule applies
179 * @param selector the traffic selector that identifies what traffic this
180 * rule
181 * @param treatment the traffic treatment that applies to selected traffic
182 * @param priority the flow rule priority given in natural order
183 * @param appId the application id of this flow
184 * @param groupId the group id of this flow
185 * @param timeout the timeout for this flow requested by an application
186 * @param permanent whether the flow is permanent i.e. does not time out
187 * @param payLoad 3rd-party origin private flow
Jonathan Hart2b3e22b2017-02-03 18:31:13 -0800188 * @deprecated in Junco release. Use FlowRule.Builder instead.
jcc3d4e14a2015-04-21 11:32:05 +0800189 */
Jonathan Hart2b3e22b2017-02-03 18:31:13 -0800190 @Deprecated
jcc3d4e14a2015-04-21 11:32:05 +0800191 public DefaultFlowRule(DeviceId deviceId, TrafficSelector selector,
192 TrafficTreatment treatment, int priority,
193 ApplicationId appId, GroupId groupId, int timeout,
194 boolean permanent, FlowRuleExtPayLoad payLoad) {
Murat Parlakisikc6759e82016-06-29 03:22:22 -0700195 this(deviceId, selector, treatment, priority, appId, groupId, timeout, 0, permanent, payLoad);
196 }
197
198 /**
199 * Support for the third party flow rule. Creates a flow rule of group
200 * table.
201 *
202 * @param deviceId the identity of the device where this rule applies
203 * @param selector the traffic selector that identifies what traffic this
204 * rule
205 * @param treatment the traffic treatment that applies to selected traffic
206 * @param priority the flow rule priority given in natural order
207 * @param appId the application id of this flow
208 * @param groupId the group id of this flow
209 * @param timeout the timeout for this flow requested by an application
210 * @param hardTimeout the hard timeout located switch's flow table for this flow requested by an application
211 * @param permanent whether the flow is permanent i.e. does not time out
212 * @param payLoad 3rd-party origin private flow
Jonathan Hart2b3e22b2017-02-03 18:31:13 -0800213 * @deprecated in Junco release. Use FlowRule.Builder instead.
Murat Parlakisikc6759e82016-06-29 03:22:22 -0700214 */
Jonathan Hart2b3e22b2017-02-03 18:31:13 -0800215 @Deprecated
Murat Parlakisikc6759e82016-06-29 03:22:22 -0700216 public DefaultFlowRule(DeviceId deviceId, TrafficSelector selector,
217 TrafficTreatment treatment, int priority,
218 ApplicationId appId, GroupId groupId, int timeout, int hardTimeout,
219 boolean permanent, FlowRuleExtPayLoad payLoad) {
jcc3d4e14a2015-04-21 11:32:05 +0800220
Kavitha Alagesan14dc5132016-06-13 17:25:18 +0530221 checkArgument(priority >= MIN_PRIORITY, "Priority cannot be less than " +
222 MIN_PRIORITY);
223 checkArgument(priority <= MAX_PRIORITY, "Priority cannot be greater than " +
224 MAX_PRIORITY);
jcc3d4e14a2015-04-21 11:32:05 +0800225
226 this.deviceId = deviceId;
227 this.priority = priority;
228 this.selector = selector;
229 this.treatment = treatment;
230 this.appId = appId.id();
231 this.groupId = groupId;
232 this.timeout = timeout;
Murat Parlakisikc6759e82016-06-29 03:22:22 -0700233 this.reason = FlowRemoveReason.NO_REASON;
234 this.hardTimeout = hardTimeout;
jcc3d4e14a2015-04-21 11:32:05 +0800235 this.permanent = permanent;
236 this.created = System.currentTimeMillis();
237 this.tableId = 0;
238 this.payLoad = payLoad;
239
240 /*
241 * id consists of the following. | appId (16 bits) | groupId (16 bits) |
242 * flowId (32 bits) |
243 */
244 this.id = FlowId.valueOf((((long) this.appId) << 48)
245 | (((long) this.groupId.id()) << 32)
246 | (this.hash() & 0xffffffffL));
alshabiba7f7ca82014-09-22 11:41:23 -0700247 }
248
Ayaka Koshibed4e53e12014-09-18 14:24:55 -0700249 @Override
250 public FlowId id() {
251 return id;
alshabib7b2748f2014-09-16 20:21:11 -0700252 }
253
254 @Override
alshabib92c65ad2014-10-08 21:56:05 -0700255 public short appId() {
alshabiba68eb962014-09-24 20:34:13 -0700256 return appId;
257 }
258
259 @Override
Sho SHIMIZU75a5bd92014-11-25 11:22:56 -0800260 public GroupId groupId() {
alshabib28204e52014-11-12 18:29:45 -0800261 return groupId;
262 }
263
264 @Override
alshabib7b2748f2014-09-16 20:21:11 -0700265 public int priority() {
Ayaka Koshibed4e53e12014-09-18 14:24:55 -0700266 return priority;
alshabib7b2748f2014-09-16 20:21:11 -0700267 }
268
269 @Override
270 public DeviceId deviceId() {
271 return deviceId;
272 }
273
274 @Override
275 public TrafficSelector selector() {
276 return selector;
277 }
278
279 @Override
280 public TrafficTreatment treatment() {
281 return treatment;
282 }
283
Ayaka Koshibed4e53e12014-09-18 14:24:55 -0700284 /*
285 * The priority and statistics can change on a given treatment and selector
286 *
287 * (non-Javadoc)
jcc3d4e14a2015-04-21 11:32:05 +0800288 *
Ayaka Koshibed4e53e12014-09-18 14:24:55 -0700289 * @see java.lang.Object#equals(java.lang.Object)
290 */
Jonathan Hart2b3e22b2017-02-03 18:31:13 -0800291 @Override
Ayaka Koshibe08eabaa2014-09-17 14:59:25 -0700292 public int hashCode() {
Thomas Vachuska711db552015-06-02 16:35:26 -0700293 return Objects.hash(deviceId, selector, tableId, payLoad);
alshabiba68eb962014-09-24 20:34:13 -0700294 }
295
Thomas Vachuska711db552015-06-02 16:35:26 -0700296 //FIXME do we need this method in addition to hashCode()?
297 private int hash() {
298 return Objects.hash(deviceId, selector, tableId, payLoad);
Ayaka Koshibe08eabaa2014-09-17 14:59:25 -0700299 }
300
Ayaka Koshibe08eabaa2014-09-17 14:59:25 -0700301 /*
302 * The priority and statistics can change on a given treatment and selector
303 *
304 * (non-Javadoc)
jcc3d4e14a2015-04-21 11:32:05 +0800305 *
Ayaka Koshibe08eabaa2014-09-17 14:59:25 -0700306 * @see java.lang.Object#equals(java.lang.Object)
307 */
Jonathan Hart2b3e22b2017-02-03 18:31:13 -0800308 @Override
Ayaka Koshibe08eabaa2014-09-17 14:59:25 -0700309 public boolean equals(Object obj) {
alshabiba7f7ca82014-09-22 11:41:23 -0700310 if (this == obj) {
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700311 return true;
Ayaka Koshibe08eabaa2014-09-17 14:59:25 -0700312 }
alshabib54ce5892014-09-23 17:50:51 -0700313 if (obj instanceof DefaultFlowRule) {
alshabib219ebaa2014-09-22 15:41:24 -0700314 DefaultFlowRule that = (DefaultFlowRule) obj;
315 return Objects.equals(deviceId, that.deviceId) &&
alshabibba5ac482014-10-02 17:15:20 -0700316 Objects.equals(priority, that.priority) &&
Saurav Dascbe6de32015-03-01 18:30:46 -0800317 Objects.equals(selector, that.selector) &&
jcc3d4e14a2015-04-21 11:32:05 +0800318 Objects.equals(tableId, that.tableId)
319 && Objects.equals(payLoad, that.payLoad);
alshabiba7f7ca82014-09-22 11:41:23 -0700320 }
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700321 return false;
Ayaka Koshibe08eabaa2014-09-17 14:59:25 -0700322 }
323
Ayaka Koshibed4e53e12014-09-18 14:24:55 -0700324 @Override
Jonathan Hartf44e42c2015-08-04 09:58:46 -0700325 public boolean exactMatch(FlowRule rule) {
326 return this.equals(rule) &&
327 Objects.equals(this.id, rule.id()) &&
328 Objects.equals(this.treatment, rule.treatment());
329 }
330
331 @Override
Ayaka Koshibed4e53e12014-09-18 14:24:55 -0700332 public String toString() {
333 return toStringHelper(this)
alshabib8ca53902014-10-07 13:11:17 -0700334 .add("id", Long.toHexString(id.value()))
Ayaka Koshibed4e53e12014-09-18 14:24:55 -0700335 .add("deviceId", deviceId)
336 .add("priority", priority)
alshabibba5ac482014-10-02 17:15:20 -0700337 .add("selector", selector.criteria())
Jian Lif0325112016-03-03 17:11:25 -0800338 .add("treatment", treatment == null ? "N/A" : treatment)
alshabib08d98982015-04-21 16:25:50 -0700339 .add("tableId", tableId)
Ayaka Koshibed4e53e12014-09-18 14:24:55 -0700340 .add("created", created)
Ray Milkeyd13a37b2015-06-12 11:55:17 -0700341 .add("payLoad", payLoad)
Ayaka Koshibed4e53e12014-09-18 14:24:55 -0700342 .toString();
343 }
Ayaka Koshibe08eabaa2014-09-17 14:59:25 -0700344
alshabib6eb438a2014-10-01 16:39:37 -0700345 @Override
alshabibba5ac482014-10-02 17:15:20 -0700346 public int timeout() {
alshabib58747a62014-10-07 11:05:30 -0700347 return timeout;
alshabib6eb438a2014-10-01 16:39:37 -0700348 }
349
Murat Parlakisikc6759e82016-06-29 03:22:22 -0700350 @Override
351 public int hardTimeout() {
352 return hardTimeout;
353 }
354
355 @Override
356 public FlowRemoveReason reason() {
357 return reason;
358 }
359
Jonathan Hartbc4a7932014-10-21 11:46:00 -0700360 @Override
361 public boolean isPermanent() {
362 return permanent;
363 }
364
sangho11c30ac2015-01-22 14:30:55 -0800365 @Override
alshabibdb774072015-04-20 13:13:51 -0700366 public int tableId() {
367 return tableId;
368 }
369
Jonathan Hart2b3e22b2017-02-03 18:31:13 -0800370 /**
371 * Returns the wallclock time that the flow was created.
372 *
373 * @return creation time in milliseconds since epoch
374 */
Brian O'Connora3e5cd52015-12-05 15:59:19 -0800375 public long created() {
376 return created;
377 }
378
Jonathan Hart2b3e22b2017-02-03 18:31:13 -0800379 /**
380 * Returns a default flow rule builder.
381 *
382 * @return builder
383 */
alshabibdb774072015-04-20 13:13:51 -0700384 public static Builder builder() {
385 return new Builder();
386 }
387
Jonathan Hart2b3e22b2017-02-03 18:31:13 -0800388 /**
389 * Default flow rule builder.
390 */
alshabibd17abc22015-04-21 18:26:35 -0700391 public static final class Builder implements FlowRule.Builder {
alshabibdb774072015-04-20 13:13:51 -0700392
393 private FlowId flowId;
Jonathan Hart65d551b2015-09-22 09:49:09 -0700394 private ApplicationId appId;
alshabibdb774072015-04-20 13:13:51 -0700395 private Integer priority;
396 private DeviceId deviceId;
397 private Integer tableId = 0;
Charles Chancc4754d2015-12-10 15:58:18 -0800398 private TrafficSelector selector = DefaultTrafficSelector.builder().build();
399 private TrafficTreatment treatment = DefaultTrafficTreatment.builder().build();
alshabibdb774072015-04-20 13:13:51 -0700400 private Integer timeout;
401 private Boolean permanent;
Murat Parlakisikc6759e82016-06-29 03:22:22 -0700402 private Integer hardTimeout = 0;
403 private FlowRemoveReason reason = FlowRemoveReason.NO_REASON;
alshabibdb774072015-04-20 13:13:51 -0700404
405 @Override
406 public FlowRule.Builder withCookie(long cookie) {
407 this.flowId = FlowId.valueOf(cookie);
408 return this;
409 }
410
411 @Override
412 public FlowRule.Builder fromApp(ApplicationId appId) {
Jonathan Hart65d551b2015-09-22 09:49:09 -0700413 this.appId = appId;
alshabibdb774072015-04-20 13:13:51 -0700414 return this;
415 }
416
417 @Override
418 public FlowRule.Builder withPriority(int priority) {
419 this.priority = priority;
420 return this;
421 }
422
423 @Override
424 public FlowRule.Builder forDevice(DeviceId deviceId) {
425 this.deviceId = deviceId;
426 return this;
427 }
428
429 @Override
430 public FlowRule.Builder forTable(int tableId) {
431 this.tableId = tableId;
432 return this;
433 }
434
435 @Override
436 public FlowRule.Builder withSelector(TrafficSelector selector) {
437 this.selector = selector;
438 return this;
439 }
440
441 @Override
442 public FlowRule.Builder withTreatment(TrafficTreatment treatment) {
Jonathan Hart24e296b2016-01-12 14:47:07 -0800443 this.treatment = checkNotNull(treatment);
alshabibdb774072015-04-20 13:13:51 -0700444 return this;
445 }
446
447 @Override
448 public FlowRule.Builder makePermanent() {
449 this.timeout = 0;
450 this.permanent = true;
451 return this;
452 }
453
454 @Override
455 public FlowRule.Builder makeTemporary(int timeout) {
456 this.permanent = false;
457 this.timeout = timeout;
458 return this;
459 }
460
461 @Override
Murat Parlakisikc6759e82016-06-29 03:22:22 -0700462 public FlowRule.Builder withHardTimeout(int timeout) {
463 this.permanent = false;
464 this.hardTimeout = timeout;
465 this.timeout = timeout;
466 return this;
467 }
468
469 @Override
470 public FlowRule.Builder withReason(FlowRemoveReason reason) {
471 this.reason = reason;
472 return this;
473 }
474
475 @Override
alshabibdb774072015-04-20 13:13:51 -0700476 public FlowRule build() {
alshabibb05be2d2016-04-11 12:52:36 -0700477 FlowId localFlowId;
Jian Li8bac5762016-02-09 17:23:09 -0800478 checkArgument((flowId != null) ^ (appId != null), "Either an application" +
alshabibdb774072015-04-20 13:13:51 -0700479 " id or a cookie must be supplied");
Jonathan Hart65d551b2015-09-22 09:49:09 -0700480 checkNotNull(selector, "Traffic selector cannot be null");
481 checkArgument(timeout != null || permanent != null, "Must either have " +
alshabibdb774072015-04-20 13:13:51 -0700482 "a timeout or be permanent");
Jonathan Hart65d551b2015-09-22 09:49:09 -0700483 checkNotNull(deviceId, "Must refer to a device");
484 checkNotNull(priority, "Priority cannot be null");
Saurav Das3ea46622015-04-22 14:01:34 -0700485 checkArgument(priority >= MIN_PRIORITY, "Priority cannot be less than " +
alshabibdb774072015-04-20 13:13:51 -0700486 MIN_PRIORITY);
Kavitha Alagesan14dc5132016-06-13 17:25:18 +0530487 checkArgument(priority <= MAX_PRIORITY, "Priority cannot be greater than " +
488 MAX_PRIORITY);
Jonathan Hart65d551b2015-09-22 09:49:09 -0700489 // Computing a flow ID based on appId takes precedence over setting
490 // the flow ID directly
491 if (appId != null) {
alshabibb05be2d2016-04-11 12:52:36 -0700492 localFlowId = computeFlowId(appId);
493 } else {
494 localFlowId = flowId;
Jonathan Hart65d551b2015-09-22 09:49:09 -0700495 }
496
alshabibdb774072015-04-20 13:13:51 -0700497 return new DefaultFlowRule(deviceId, selector, treatment, priority,
Murat Parlakisikc6759e82016-06-29 03:22:22 -0700498 localFlowId, permanent, timeout, hardTimeout, reason, tableId);
alshabibdb774072015-04-20 13:13:51 -0700499 }
500
501 private FlowId computeFlowId(ApplicationId appId) {
502 return FlowId.valueOf((((long) appId.id()) << 48)
503 | (hash() & 0xffffffffL));
504 }
505
506 private int hash() {
Jordan Halterman485da342017-05-31 14:13:53 -0700507 // Guava documentation recommends using putUnencodedChars to hash raw character bytes within any encoding
508 // unless cross-language compatibility is needed. See the Hasher.putString documentation for more info.
Hyunsun Moon7bfbc1c2016-04-05 16:40:43 -0700509 Funnel<TrafficSelector> selectorFunnel = (from, into) -> from.criteria()
Jordan Halterman485da342017-05-31 14:13:53 -0700510 .forEach(c -> into.putUnencodedChars(c.toString()));
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()
Jordan Halterman485da342017-05-31 14:13:53 -0700514 .putUnencodedChars(deviceId.toString())
Hyunsun Moon7bfbc1c2016-04-05 16:40:43 -0700515 .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}