blob: ed0a3abb4d2017a1d6549ee656c2171c50598999 [file] [log] [blame]
Thomas Vachuska83e090e2014-10-22 14:25:35 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2014-present Open Networking Foundation
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;
Carmelo Cascone41605742017-06-19 15:46:44 +090031import static org.onosproject.net.flow.TableId.Type.INDEX;
Jonathan Hart607b1ff2015-05-05 10:55:51 -070032
Jonathan Hart2b3e22b2017-02-03 18:31:13 -080033/**
34 * Default flow rule.
35 */
alshabib7b2748f2014-09-16 20:21:11 -070036public class DefaultFlowRule implements FlowRule {
37
Ayaka Koshibed4e53e12014-09-18 14:24:55 -070038 private final DeviceId deviceId;
39 private final int priority;
alshabib7b2748f2014-09-16 20:21:11 -070040 private final TrafficSelector selector;
41 private final TrafficTreatment treatment;
Ayaka Koshibed4e53e12014-09-18 14:24:55 -070042 private final long created;
43
alshabib219ebaa2014-09-22 15:41:24 -070044 private final FlowId id;
Ayaka Koshibed4e53e12014-09-18 14:24:55 -070045
alshabibdb774072015-04-20 13:13:51 -070046 private final Short appId;
alshabiba68eb962014-09-24 20:34:13 -070047
alshabibba5ac482014-10-02 17:15:20 -070048 private final int timeout;
Jonathan Hartbc4a7932014-10-21 11:46:00 -070049 private final boolean permanent;
Murat Parlakisikc6759e82016-06-29 03:22:22 -070050 private final int hardTimeout;
51 private final FlowRemoveReason reason;
Sho SHIMIZU75a5bd92014-11-25 11:22:56 -080052 private final GroupId groupId;
alshabib6eb438a2014-10-01 16:39:37 -070053
Carmelo Cascone41605742017-06-19 15:46:44 +090054 private final TableId tableId;
jcc3d4e14a2015-04-21 11:32:05 +080055 private final FlowRuleExtPayLoad payLoad;
alshabib1c319ff2014-10-04 20:29:09 -070056
Jonathan Hart2b3e22b2017-02-03 18:31:13 -080057 /**
58 * Creates a new flow rule from an existing rule.
59 *
60 * @param rule new flow rule
61 */
alshabib1c319ff2014-10-04 20:29:09 -070062 public DefaultFlowRule(FlowRule rule) {
63 this.deviceId = rule.deviceId();
64 this.priority = rule.priority();
65 this.selector = rule.selector();
66 this.treatment = rule.treatment();
67 this.appId = rule.appId();
alshabib28204e52014-11-12 18:29:45 -080068 this.groupId = rule.groupId();
alshabib1c319ff2014-10-04 20:29:09 -070069 this.id = rule.id();
70 this.timeout = rule.timeout();
Murat Parlakisikc6759e82016-06-29 03:22:22 -070071 this.hardTimeout = rule.hardTimeout();
72 this.reason = rule.reason();
Jonathan Hartbc4a7932014-10-21 11:46:00 -070073 this.permanent = rule.isPermanent();
alshabib219ebaa2014-09-22 15:41:24 -070074 this.created = System.currentTimeMillis();
Carmelo Cascone41605742017-06-19 15:46:44 +090075 this.tableId = rule.table();
jcc3d4e14a2015-04-21 11:32:05 +080076 this.payLoad = rule.payLoad();
alshabibdb774072015-04-20 13:13:51 -070077 }
78
79 private DefaultFlowRule(DeviceId deviceId, TrafficSelector selector,
80 TrafficTreatment treatment, Integer priority,
Murat Parlakisikc6759e82016-06-29 03:22:22 -070081 FlowId flowId, Boolean permanent, Integer timeout, Integer hardTimeout,
Carmelo Cascone41605742017-06-19 15:46:44 +090082 FlowRemoveReason reason, TableId tableId) {
alshabibdb774072015-04-20 13:13:51 -070083
84 this.deviceId = deviceId;
85 this.selector = selector;
86 this.treatment = treatment;
87 this.priority = priority;
88 this.appId = (short) (flowId.value() >>> 48);
89 this.id = flowId;
90 this.permanent = permanent;
91 this.timeout = timeout;
Murat Parlakisikc6759e82016-06-29 03:22:22 -070092 this.hardTimeout = hardTimeout;
93 this.reason = reason;
alshabibdb774072015-04-20 13:13:51 -070094 this.tableId = tableId;
95 this.created = System.currentTimeMillis();
96
97
98 //FIXME: fields below will be removed.
Yi Tsengfa394de2017-02-01 11:26:40 -080099 this.groupId = new GroupId(0);
jcc3d4e14a2015-04-21 11:32:05 +0800100 this.payLoad = null;
101 }
alshabibdb774072015-04-20 13:13:51 -0700102
jcc3d4e14a2015-04-21 11:32:05 +0800103 /**
104 * Support for the third party flow rule. Creates a flow rule of flow table.
105 *
106 * @param deviceId the identity of the device where this rule applies
107 * @param selector the traffic selector that identifies what traffic this
108 * rule
109 * @param treatment the traffic treatment that applies to selected traffic
110 * @param priority the flow rule priority given in natural order
111 * @param appId the application id of this flow
112 * @param timeout the timeout for this flow requested by an application
113 * @param permanent whether the flow is permanent i.e. does not time out
114 * @param payLoad 3rd-party origin private flow
Jonathan Hart2b3e22b2017-02-03 18:31:13 -0800115 * @deprecated in Junco release. Use FlowRule.Builder instead.
jcc3d4e14a2015-04-21 11:32:05 +0800116 */
Jonathan Hart2b3e22b2017-02-03 18:31:13 -0800117 @Deprecated
jcc3d4e14a2015-04-21 11:32:05 +0800118 public DefaultFlowRule(DeviceId deviceId, TrafficSelector selector,
119 TrafficTreatment treatment, int priority,
120 ApplicationId appId, int timeout, boolean permanent,
121 FlowRuleExtPayLoad payLoad) {
Murat Parlakisikc6759e82016-06-29 03:22:22 -0700122 this(deviceId, selector, treatment, priority, appId, timeout, 0, permanent, payLoad);
123 }
124
125
126 /**
127 * Support for the third party flow rule. Creates a flow rule of flow table.
128 *
129 * @param deviceId the identity of the device where this rule applies
130 * @param selector the traffic selector that identifies what traffic this
131 * rule
132 * @param treatment the traffic treatment that applies to selected traffic
133 * @param priority the flow rule priority given in natural order
134 * @param appId the application id of this flow
135 * @param timeout the timeout for this flow requested by an application
136 * @param hardTimeout the hard timeout located switch's flow table for this flow requested by an application
137 * @param permanent whether the flow is permanent i.e. does not time out
138 * @param payLoad 3rd-party origin private flow
Jonathan Hart2b3e22b2017-02-03 18:31:13 -0800139 * @deprecated in Junco release. Use FlowRule.Builder instead.
Murat Parlakisikc6759e82016-06-29 03:22:22 -0700140 */
Jonathan Hart2b3e22b2017-02-03 18:31:13 -0800141 @Deprecated
Murat Parlakisikc6759e82016-06-29 03:22:22 -0700142 public DefaultFlowRule(DeviceId deviceId, TrafficSelector selector,
143 TrafficTreatment treatment, int priority,
144 ApplicationId appId, int timeout, int hardTimeout, boolean permanent,
145 FlowRuleExtPayLoad payLoad) {
alshabib1c319ff2014-10-04 20:29:09 -0700146
Kavitha Alagesan14dc5132016-06-13 17:25:18 +0530147 checkArgument(priority >= MIN_PRIORITY, "Priority cannot be less than " +
148 MIN_PRIORITY);
149 checkArgument(priority <= MAX_PRIORITY, "Priority cannot be greater than " +
150 MAX_PRIORITY);
jcc3d4e14a2015-04-21 11:32:05 +0800151
152 this.deviceId = deviceId;
153 this.priority = priority;
154 this.selector = selector;
155 this.treatment = treatment;
156 this.appId = appId.id();
Yi Tsengfa394de2017-02-01 11:26:40 -0800157 this.groupId = new GroupId(0);
jcc3d4e14a2015-04-21 11:32:05 +0800158 this.timeout = timeout;
Murat Parlakisikc6759e82016-06-29 03:22:22 -0700159 this.reason = FlowRemoveReason.NO_REASON;
160 this.hardTimeout = hardTimeout;
jcc3d4e14a2015-04-21 11:32:05 +0800161 this.permanent = permanent;
Carmelo Cascone41605742017-06-19 15:46:44 +0900162 this.tableId = DEFAULT_TABLE;
jcc3d4e14a2015-04-21 11:32:05 +0800163 this.created = System.currentTimeMillis();
164 this.payLoad = payLoad;
165
166 /*
167 * id consists of the following. | appId (16 bits) | groupId (16 bits) |
168 * flowId (32 bits) |
169 */
170 this.id = FlowId.valueOf((((long) this.appId) << 48)
171 | (((long) this.groupId.id()) << 32)
172 | (this.hash() & 0xffffffffL));
173 }
174
175 /**
176 * Support for the third party flow rule. Creates a flow rule of group
177 * table.
178 *
179 * @param deviceId the identity of the device where this rule applies
180 * @param selector the traffic selector that identifies what traffic this
181 * rule
182 * @param treatment the traffic treatment that applies to selected traffic
183 * @param priority the flow rule priority given in natural order
184 * @param appId the application id of this flow
185 * @param groupId the group id of this flow
186 * @param timeout the timeout for this flow requested by an application
187 * @param permanent whether the flow is permanent i.e. does not time out
188 * @param payLoad 3rd-party origin private flow
Jonathan Hart2b3e22b2017-02-03 18:31:13 -0800189 * @deprecated in Junco release. Use FlowRule.Builder instead.
jcc3d4e14a2015-04-21 11:32:05 +0800190 */
Jonathan Hart2b3e22b2017-02-03 18:31:13 -0800191 @Deprecated
jcc3d4e14a2015-04-21 11:32:05 +0800192 public DefaultFlowRule(DeviceId deviceId, TrafficSelector selector,
193 TrafficTreatment treatment, int priority,
194 ApplicationId appId, GroupId groupId, int timeout,
195 boolean permanent, FlowRuleExtPayLoad payLoad) {
Murat Parlakisikc6759e82016-06-29 03:22:22 -0700196 this(deviceId, selector, treatment, priority, appId, groupId, timeout, 0, permanent, payLoad);
197 }
198
199 /**
200 * Support for the third party flow rule. Creates a flow rule of group
201 * table.
202 *
203 * @param deviceId the identity of the device where this rule applies
204 * @param selector the traffic selector that identifies what traffic this
205 * rule
206 * @param treatment the traffic treatment that applies to selected traffic
207 * @param priority the flow rule priority given in natural order
208 * @param appId the application id of this flow
209 * @param groupId the group id of this flow
210 * @param timeout the timeout for this flow requested by an application
211 * @param hardTimeout the hard timeout located switch's flow table for this flow requested by an application
212 * @param permanent whether the flow is permanent i.e. does not time out
213 * @param payLoad 3rd-party origin private flow
Jonathan Hart2b3e22b2017-02-03 18:31:13 -0800214 * @deprecated in Junco release. Use FlowRule.Builder instead.
Murat Parlakisikc6759e82016-06-29 03:22:22 -0700215 */
Jonathan Hart2b3e22b2017-02-03 18:31:13 -0800216 @Deprecated
Murat Parlakisikc6759e82016-06-29 03:22:22 -0700217 public DefaultFlowRule(DeviceId deviceId, TrafficSelector selector,
218 TrafficTreatment treatment, int priority,
219 ApplicationId appId, GroupId groupId, int timeout, int hardTimeout,
220 boolean permanent, FlowRuleExtPayLoad payLoad) {
jcc3d4e14a2015-04-21 11:32:05 +0800221
Kavitha Alagesan14dc5132016-06-13 17:25:18 +0530222 checkArgument(priority >= MIN_PRIORITY, "Priority cannot be less than " +
223 MIN_PRIORITY);
224 checkArgument(priority <= MAX_PRIORITY, "Priority cannot be greater than " +
225 MAX_PRIORITY);
jcc3d4e14a2015-04-21 11:32:05 +0800226
227 this.deviceId = deviceId;
228 this.priority = priority;
229 this.selector = selector;
230 this.treatment = treatment;
231 this.appId = appId.id();
232 this.groupId = groupId;
233 this.timeout = timeout;
Murat Parlakisikc6759e82016-06-29 03:22:22 -0700234 this.reason = FlowRemoveReason.NO_REASON;
235 this.hardTimeout = hardTimeout;
jcc3d4e14a2015-04-21 11:32:05 +0800236 this.permanent = permanent;
237 this.created = System.currentTimeMillis();
Carmelo Cascone41605742017-06-19 15:46:44 +0900238 this.tableId = DEFAULT_TABLE;
jcc3d4e14a2015-04-21 11:32:05 +0800239 this.payLoad = payLoad;
240
241 /*
242 * id consists of the following. | appId (16 bits) | groupId (16 bits) |
243 * flowId (32 bits) |
244 */
245 this.id = FlowId.valueOf((((long) this.appId) << 48)
246 | (((long) this.groupId.id()) << 32)
247 | (this.hash() & 0xffffffffL));
alshabiba7f7ca82014-09-22 11:41:23 -0700248 }
249
Ayaka Koshibed4e53e12014-09-18 14:24:55 -0700250 @Override
251 public FlowId id() {
252 return id;
alshabib7b2748f2014-09-16 20:21:11 -0700253 }
254
255 @Override
alshabib92c65ad2014-10-08 21:56:05 -0700256 public short appId() {
alshabiba68eb962014-09-24 20:34:13 -0700257 return appId;
258 }
259
260 @Override
Sho SHIMIZU75a5bd92014-11-25 11:22:56 -0800261 public GroupId groupId() {
alshabib28204e52014-11-12 18:29:45 -0800262 return groupId;
263 }
264
265 @Override
alshabib7b2748f2014-09-16 20:21:11 -0700266 public int priority() {
Ayaka Koshibed4e53e12014-09-18 14:24:55 -0700267 return priority;
alshabib7b2748f2014-09-16 20:21:11 -0700268 }
269
270 @Override
271 public DeviceId deviceId() {
272 return deviceId;
273 }
274
275 @Override
276 public TrafficSelector selector() {
277 return selector;
278 }
279
280 @Override
281 public TrafficTreatment treatment() {
282 return treatment;
283 }
284
Ayaka Koshibed4e53e12014-09-18 14:24:55 -0700285 /*
286 * The priority and statistics can change on a given treatment and selector
287 *
288 * (non-Javadoc)
jcc3d4e14a2015-04-21 11:32:05 +0800289 *
Ayaka Koshibed4e53e12014-09-18 14:24:55 -0700290 * @see java.lang.Object#equals(java.lang.Object)
291 */
Jonathan Hart2b3e22b2017-02-03 18:31:13 -0800292 @Override
Ayaka Koshibe08eabaa2014-09-17 14:59:25 -0700293 public int hashCode() {
Thomas Vachuska711db552015-06-02 16:35:26 -0700294 return Objects.hash(deviceId, selector, tableId, payLoad);
alshabiba68eb962014-09-24 20:34:13 -0700295 }
296
Thomas Vachuska711db552015-06-02 16:35:26 -0700297 //FIXME do we need this method in addition to hashCode()?
298 private int hash() {
299 return Objects.hash(deviceId, selector, tableId, payLoad);
Ayaka Koshibe08eabaa2014-09-17 14:59:25 -0700300 }
301
Ayaka Koshibe08eabaa2014-09-17 14:59:25 -0700302 /*
303 * The priority and statistics can change on a given treatment and selector
304 *
305 * (non-Javadoc)
jcc3d4e14a2015-04-21 11:32:05 +0800306 *
Ayaka Koshibe08eabaa2014-09-17 14:59:25 -0700307 * @see java.lang.Object#equals(java.lang.Object)
308 */
Jonathan Hart2b3e22b2017-02-03 18:31:13 -0800309 @Override
Ayaka Koshibe08eabaa2014-09-17 14:59:25 -0700310 public boolean equals(Object obj) {
alshabiba7f7ca82014-09-22 11:41:23 -0700311 if (this == obj) {
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700312 return true;
Ayaka Koshibe08eabaa2014-09-17 14:59:25 -0700313 }
alshabib54ce5892014-09-23 17:50:51 -0700314 if (obj instanceof DefaultFlowRule) {
alshabib219ebaa2014-09-22 15:41:24 -0700315 DefaultFlowRule that = (DefaultFlowRule) obj;
316 return Objects.equals(deviceId, that.deviceId) &&
alshabibba5ac482014-10-02 17:15:20 -0700317 Objects.equals(priority, that.priority) &&
Saurav Dascbe6de32015-03-01 18:30:46 -0800318 Objects.equals(selector, that.selector) &&
jcc3d4e14a2015-04-21 11:32:05 +0800319 Objects.equals(tableId, that.tableId)
320 && Objects.equals(payLoad, that.payLoad);
alshabiba7f7ca82014-09-22 11:41:23 -0700321 }
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700322 return false;
Ayaka Koshibe08eabaa2014-09-17 14:59:25 -0700323 }
324
Ayaka Koshibed4e53e12014-09-18 14:24:55 -0700325 @Override
Jonathan Hartf44e42c2015-08-04 09:58:46 -0700326 public boolean exactMatch(FlowRule rule) {
327 return this.equals(rule) &&
328 Objects.equals(this.id, rule.id()) &&
329 Objects.equals(this.treatment, rule.treatment());
330 }
331
332 @Override
Ayaka Koshibed4e53e12014-09-18 14:24:55 -0700333 public String toString() {
334 return toStringHelper(this)
alshabib8ca53902014-10-07 13:11:17 -0700335 .add("id", Long.toHexString(id.value()))
Ayaka Koshibed4e53e12014-09-18 14:24:55 -0700336 .add("deviceId", deviceId)
337 .add("priority", priority)
alshabibba5ac482014-10-02 17:15:20 -0700338 .add("selector", selector.criteria())
Jian Lif0325112016-03-03 17:11:25 -0800339 .add("treatment", treatment == null ? "N/A" : treatment)
alshabib08d98982015-04-21 16:25:50 -0700340 .add("tableId", tableId)
Ayaka Koshibed4e53e12014-09-18 14:24:55 -0700341 .add("created", created)
Ray Milkeyd13a37b2015-06-12 11:55:17 -0700342 .add("payLoad", payLoad)
Ayaka Koshibed4e53e12014-09-18 14:24:55 -0700343 .toString();
344 }
Ayaka Koshibe08eabaa2014-09-17 14:59:25 -0700345
alshabib6eb438a2014-10-01 16:39:37 -0700346 @Override
alshabibba5ac482014-10-02 17:15:20 -0700347 public int timeout() {
alshabib58747a62014-10-07 11:05:30 -0700348 return timeout;
alshabib6eb438a2014-10-01 16:39:37 -0700349 }
350
Murat Parlakisikc6759e82016-06-29 03:22:22 -0700351 @Override
352 public int hardTimeout() {
353 return hardTimeout;
354 }
355
356 @Override
357 public FlowRemoveReason reason() {
358 return reason;
359 }
360
Jonathan Hartbc4a7932014-10-21 11:46:00 -0700361 @Override
362 public boolean isPermanent() {
363 return permanent;
364 }
365
sangho11c30ac2015-01-22 14:30:55 -0800366 @Override
alshabibdb774072015-04-20 13:13:51 -0700367 public int tableId() {
Carmelo Cascone41605742017-06-19 15:46:44 +0900368 // Workaround until we remove this method. Deprecated in Loon.
369 return tableId.type() == INDEX ? ((IndexTableId) tableId).id() : tableId.hashCode();
370 }
371
372 @Override
373 public TableId table() {
alshabibdb774072015-04-20 13:13:51 -0700374 return tableId;
375 }
376
Jonathan Hart2b3e22b2017-02-03 18:31:13 -0800377 /**
378 * Returns the wallclock time that the flow was created.
379 *
380 * @return creation time in milliseconds since epoch
381 */
Brian O'Connora3e5cd52015-12-05 15:59:19 -0800382 public long created() {
383 return created;
384 }
385
Jonathan Hart2b3e22b2017-02-03 18:31:13 -0800386 /**
387 * Returns a default flow rule builder.
388 *
389 * @return builder
390 */
alshabibdb774072015-04-20 13:13:51 -0700391 public static Builder builder() {
392 return new Builder();
393 }
394
Jonathan Hart2b3e22b2017-02-03 18:31:13 -0800395 /**
396 * Default flow rule builder.
397 */
alshabibd17abc22015-04-21 18:26:35 -0700398 public static final class Builder implements FlowRule.Builder {
alshabibdb774072015-04-20 13:13:51 -0700399
400 private FlowId flowId;
Jonathan Hart65d551b2015-09-22 09:49:09 -0700401 private ApplicationId appId;
alshabibdb774072015-04-20 13:13:51 -0700402 private Integer priority;
403 private DeviceId deviceId;
Carmelo Cascone41605742017-06-19 15:46:44 +0900404 private TableId tableId = DEFAULT_TABLE;
Charles Chancc4754d2015-12-10 15:58:18 -0800405 private TrafficSelector selector = DefaultTrafficSelector.builder().build();
406 private TrafficTreatment treatment = DefaultTrafficTreatment.builder().build();
alshabibdb774072015-04-20 13:13:51 -0700407 private Integer timeout;
408 private Boolean permanent;
Murat Parlakisikc6759e82016-06-29 03:22:22 -0700409 private Integer hardTimeout = 0;
410 private FlowRemoveReason reason = FlowRemoveReason.NO_REASON;
alshabibdb774072015-04-20 13:13:51 -0700411
412 @Override
413 public FlowRule.Builder withCookie(long cookie) {
414 this.flowId = FlowId.valueOf(cookie);
415 return this;
416 }
417
418 @Override
419 public FlowRule.Builder fromApp(ApplicationId appId) {
Jonathan Hart65d551b2015-09-22 09:49:09 -0700420 this.appId = appId;
alshabibdb774072015-04-20 13:13:51 -0700421 return this;
422 }
423
424 @Override
425 public FlowRule.Builder withPriority(int priority) {
426 this.priority = priority;
427 return this;
428 }
429
430 @Override
431 public FlowRule.Builder forDevice(DeviceId deviceId) {
432 this.deviceId = deviceId;
433 return this;
434 }
435
436 @Override
437 public FlowRule.Builder forTable(int tableId) {
Carmelo Cascone41605742017-06-19 15:46:44 +0900438 this.tableId = IndexTableId.of(tableId);
439 return this;
440 }
441
442 @Override
443 public FlowRule.Builder forTable(TableId tableId) {
alshabibdb774072015-04-20 13:13:51 -0700444 this.tableId = tableId;
445 return this;
446 }
447
448 @Override
449 public FlowRule.Builder withSelector(TrafficSelector selector) {
450 this.selector = selector;
451 return this;
452 }
453
454 @Override
455 public FlowRule.Builder withTreatment(TrafficTreatment treatment) {
Jonathan Hart24e296b2016-01-12 14:47:07 -0800456 this.treatment = checkNotNull(treatment);
alshabibdb774072015-04-20 13:13:51 -0700457 return this;
458 }
459
460 @Override
461 public FlowRule.Builder makePermanent() {
462 this.timeout = 0;
463 this.permanent = true;
464 return this;
465 }
466
467 @Override
468 public FlowRule.Builder makeTemporary(int timeout) {
469 this.permanent = false;
470 this.timeout = timeout;
471 return this;
472 }
473
474 @Override
Murat Parlakisikc6759e82016-06-29 03:22:22 -0700475 public FlowRule.Builder withHardTimeout(int timeout) {
476 this.permanent = false;
477 this.hardTimeout = timeout;
478 this.timeout = timeout;
479 return this;
480 }
481
482 @Override
483 public FlowRule.Builder withReason(FlowRemoveReason reason) {
484 this.reason = reason;
485 return this;
486 }
487
488 @Override
alshabibdb774072015-04-20 13:13:51 -0700489 public FlowRule build() {
alshabibb05be2d2016-04-11 12:52:36 -0700490 FlowId localFlowId;
Carmelo Cascone41605742017-06-19 15:46:44 +0900491 checkNotNull(tableId, "Table id cannot be null");
Jian Li8bac5762016-02-09 17:23:09 -0800492 checkArgument((flowId != null) ^ (appId != null), "Either an application" +
alshabibdb774072015-04-20 13:13:51 -0700493 " id or a cookie must be supplied");
Jonathan Hart65d551b2015-09-22 09:49:09 -0700494 checkNotNull(selector, "Traffic selector cannot be null");
495 checkArgument(timeout != null || permanent != null, "Must either have " +
alshabibdb774072015-04-20 13:13:51 -0700496 "a timeout or be permanent");
Jonathan Hart65d551b2015-09-22 09:49:09 -0700497 checkNotNull(deviceId, "Must refer to a device");
498 checkNotNull(priority, "Priority cannot be null");
Saurav Das3ea46622015-04-22 14:01:34 -0700499 checkArgument(priority >= MIN_PRIORITY, "Priority cannot be less than " +
alshabibdb774072015-04-20 13:13:51 -0700500 MIN_PRIORITY);
Kavitha Alagesan14dc5132016-06-13 17:25:18 +0530501 checkArgument(priority <= MAX_PRIORITY, "Priority cannot be greater than " +
502 MAX_PRIORITY);
Jonathan Hart65d551b2015-09-22 09:49:09 -0700503 // Computing a flow ID based on appId takes precedence over setting
504 // the flow ID directly
505 if (appId != null) {
alshabibb05be2d2016-04-11 12:52:36 -0700506 localFlowId = computeFlowId(appId);
507 } else {
508 localFlowId = flowId;
Jonathan Hart65d551b2015-09-22 09:49:09 -0700509 }
510
alshabibdb774072015-04-20 13:13:51 -0700511 return new DefaultFlowRule(deviceId, selector, treatment, priority,
Murat Parlakisikc6759e82016-06-29 03:22:22 -0700512 localFlowId, permanent, timeout, hardTimeout, reason, tableId);
alshabibdb774072015-04-20 13:13:51 -0700513 }
514
515 private FlowId computeFlowId(ApplicationId appId) {
516 return FlowId.valueOf((((long) appId.id()) << 48)
517 | (hash() & 0xffffffffL));
518 }
519
520 private int hash() {
Jordan Halterman485da342017-05-31 14:13:53 -0700521 // Guava documentation recommends using putUnencodedChars to hash raw character bytes within any encoding
522 // unless cross-language compatibility is needed. See the Hasher.putString documentation for more info.
Hyunsun Moon7bfbc1c2016-04-05 16:40:43 -0700523 Funnel<TrafficSelector> selectorFunnel = (from, into) -> from.criteria()
Jordan Halterman485da342017-05-31 14:13:53 -0700524 .forEach(c -> into.putUnencodedChars(c.toString()));
alshabibdb774072015-04-20 13:13:51 -0700525
Hyunsun Moon7bfbc1c2016-04-05 16:40:43 -0700526 HashFunction hashFunction = Hashing.murmur3_32();
527 HashCode hashCode = hashFunction.newHasher()
Jordan Halterman485da342017-05-31 14:13:53 -0700528 .putUnencodedChars(deviceId.toString())
Hyunsun Moon7bfbc1c2016-04-05 16:40:43 -0700529 .putObject(selector, selectorFunnel)
530 .putInt(priority)
Carmelo Cascone41605742017-06-19 15:46:44 +0900531 .putUnencodedChars(tableId.toString())
Hyunsun Moon7bfbc1c2016-04-05 16:40:43 -0700532 .hash();
533
534 return hashCode.asInt();
535 }
alshabibdb774072015-04-20 13:13:51 -0700536 }
537
jcc3d4e14a2015-04-21 11:32:05 +0800538 @Override
539 public FlowRuleExtPayLoad payLoad() {
540 return payLoad;
541 }
542
alshabib7b2748f2014-09-16 20:21:11 -0700543}