blob: d38d044d7be2bbdd18208237e934d483c18f4078 [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
Brian O'Connora3e5cd52015-12-05 15:59:19 -080018import com.google.common.annotations.Beta;
Hyunsun Moon7bfbc1c2016-04-05 16:40:43 -070019import com.google.common.base.Charsets;
20import com.google.common.hash.Funnel;
21import com.google.common.hash.HashCode;
22import com.google.common.hash.HashFunction;
23import com.google.common.hash.Hashing;
Brian O'Connorabafb502014-12-02 22:26:20 -080024import org.onosproject.core.ApplicationId;
25import org.onosproject.core.DefaultGroupId;
26import org.onosproject.core.GroupId;
27import org.onosproject.net.DeviceId;
alshabib7b2748f2014-09-16 20:21:11 -070028
Jonathan Hart607b1ff2015-05-05 10:55:51 -070029import java.util.Objects;
30
31import static com.google.common.base.MoreObjects.toStringHelper;
32import static com.google.common.base.Preconditions.checkArgument;
33import static com.google.common.base.Preconditions.checkNotNull;
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;
Sho SHIMIZU75a5bd92014-11-25 11:22:56 -080049 private final GroupId groupId;
alshabib6eb438a2014-10-01 16:39:37 -070050
alshabibdb774072015-04-20 13:13:51 -070051 private final Integer tableId;
jcc3d4e14a2015-04-21 11:32:05 +080052 private final FlowRuleExtPayLoad payLoad;
alshabib1c319ff2014-10-04 20:29:09 -070053
alshabib1c319ff2014-10-04 20:29:09 -070054 public DefaultFlowRule(FlowRule rule) {
55 this.deviceId = rule.deviceId();
56 this.priority = rule.priority();
57 this.selector = rule.selector();
58 this.treatment = rule.treatment();
59 this.appId = rule.appId();
alshabib28204e52014-11-12 18:29:45 -080060 this.groupId = rule.groupId();
alshabib1c319ff2014-10-04 20:29:09 -070061 this.id = rule.id();
62 this.timeout = rule.timeout();
Jonathan Hartbc4a7932014-10-21 11:46:00 -070063 this.permanent = rule.isPermanent();
alshabib219ebaa2014-09-22 15:41:24 -070064 this.created = System.currentTimeMillis();
alshabibdb774072015-04-20 13:13:51 -070065 this.tableId = rule.tableId();
jcc3d4e14a2015-04-21 11:32:05 +080066 this.payLoad = rule.payLoad();
alshabibdb774072015-04-20 13:13:51 -070067 }
68
69 private DefaultFlowRule(DeviceId deviceId, TrafficSelector selector,
70 TrafficTreatment treatment, Integer priority,
71 FlowId flowId, Boolean permanent, Integer timeout,
72 Integer tableId) {
73
74 this.deviceId = deviceId;
75 this.selector = selector;
76 this.treatment = treatment;
77 this.priority = priority;
78 this.appId = (short) (flowId.value() >>> 48);
79 this.id = flowId;
80 this.permanent = permanent;
81 this.timeout = timeout;
82 this.tableId = tableId;
83 this.created = System.currentTimeMillis();
84
85
86 //FIXME: fields below will be removed.
Jonathan Hart607b1ff2015-05-05 10:55:51 -070087 this.groupId = new DefaultGroupId(0);
jcc3d4e14a2015-04-21 11:32:05 +080088 this.payLoad = null;
89 }
alshabibdb774072015-04-20 13:13:51 -070090
jcc3d4e14a2015-04-21 11:32:05 +080091 /**
92 * Support for the third party flow rule. Creates a flow rule of flow table.
93 *
94 * @param deviceId the identity of the device where this rule applies
95 * @param selector the traffic selector that identifies what traffic this
96 * rule
97 * @param treatment the traffic treatment that applies to selected traffic
98 * @param priority the flow rule priority given in natural order
99 * @param appId the application id of this flow
100 * @param timeout the timeout for this flow requested by an application
101 * @param permanent whether the flow is permanent i.e. does not time out
102 * @param payLoad 3rd-party origin private flow
103 */
104 public DefaultFlowRule(DeviceId deviceId, TrafficSelector selector,
105 TrafficTreatment treatment, int priority,
106 ApplicationId appId, int timeout, boolean permanent,
107 FlowRuleExtPayLoad payLoad) {
alshabib1c319ff2014-10-04 20:29:09 -0700108
Kavitha Alagesan14dc5132016-06-13 17:25:18 +0530109 checkArgument(priority >= MIN_PRIORITY, "Priority cannot be less than " +
110 MIN_PRIORITY);
111 checkArgument(priority <= MAX_PRIORITY, "Priority cannot be greater than " +
112 MAX_PRIORITY);
jcc3d4e14a2015-04-21 11:32:05 +0800113
114 this.deviceId = deviceId;
115 this.priority = priority;
116 this.selector = selector;
117 this.treatment = treatment;
118 this.appId = appId.id();
119 this.groupId = new DefaultGroupId(0);
120 this.timeout = timeout;
121 this.permanent = permanent;
122 this.tableId = 0;
123 this.created = System.currentTimeMillis();
124 this.payLoad = payLoad;
125
126 /*
127 * id consists of the following. | appId (16 bits) | groupId (16 bits) |
128 * flowId (32 bits) |
129 */
130 this.id = FlowId.valueOf((((long) this.appId) << 48)
131 | (((long) this.groupId.id()) << 32)
132 | (this.hash() & 0xffffffffL));
133 }
134
135 /**
136 * Support for the third party flow rule. Creates a flow rule of group
137 * table.
138 *
139 * @param deviceId the identity of the device where this rule applies
140 * @param selector the traffic selector that identifies what traffic this
141 * rule
142 * @param treatment the traffic treatment that applies to selected traffic
143 * @param priority the flow rule priority given in natural order
144 * @param appId the application id of this flow
145 * @param groupId the group id of this flow
146 * @param timeout the timeout for this flow requested by an application
147 * @param permanent whether the flow is permanent i.e. does not time out
148 * @param payLoad 3rd-party origin private flow
149 *
150 */
151 public DefaultFlowRule(DeviceId deviceId, TrafficSelector selector,
152 TrafficTreatment treatment, int priority,
153 ApplicationId appId, GroupId groupId, int timeout,
154 boolean permanent, FlowRuleExtPayLoad payLoad) {
155
Kavitha Alagesan14dc5132016-06-13 17:25:18 +0530156 checkArgument(priority >= MIN_PRIORITY, "Priority cannot be less than " +
157 MIN_PRIORITY);
158 checkArgument(priority <= MAX_PRIORITY, "Priority cannot be greater than " +
159 MAX_PRIORITY);
jcc3d4e14a2015-04-21 11:32:05 +0800160
161 this.deviceId = deviceId;
162 this.priority = priority;
163 this.selector = selector;
164 this.treatment = treatment;
165 this.appId = appId.id();
166 this.groupId = groupId;
167 this.timeout = timeout;
168 this.permanent = permanent;
169 this.created = System.currentTimeMillis();
170 this.tableId = 0;
171 this.payLoad = payLoad;
172
173 /*
174 * id consists of the following. | appId (16 bits) | groupId (16 bits) |
175 * flowId (32 bits) |
176 */
177 this.id = FlowId.valueOf((((long) this.appId) << 48)
178 | (((long) this.groupId.id()) << 32)
179 | (this.hash() & 0xffffffffL));
alshabiba7f7ca82014-09-22 11:41:23 -0700180 }
181
Ayaka Koshibed4e53e12014-09-18 14:24:55 -0700182 @Override
183 public FlowId id() {
184 return id;
alshabib7b2748f2014-09-16 20:21:11 -0700185 }
186
187 @Override
alshabib92c65ad2014-10-08 21:56:05 -0700188 public short appId() {
alshabiba68eb962014-09-24 20:34:13 -0700189 return appId;
190 }
191
192 @Override
Sho SHIMIZU75a5bd92014-11-25 11:22:56 -0800193 public GroupId groupId() {
alshabib28204e52014-11-12 18:29:45 -0800194 return groupId;
195 }
196
197 @Override
alshabib7b2748f2014-09-16 20:21:11 -0700198 public int priority() {
Ayaka Koshibed4e53e12014-09-18 14:24:55 -0700199 return priority;
alshabib7b2748f2014-09-16 20:21:11 -0700200 }
201
202 @Override
203 public DeviceId deviceId() {
204 return deviceId;
205 }
206
207 @Override
208 public TrafficSelector selector() {
209 return selector;
210 }
211
212 @Override
213 public TrafficTreatment treatment() {
214 return treatment;
215 }
216
alshabiba7f7ca82014-09-22 11:41:23 -0700217 @Override
Ayaka Koshibed4e53e12014-09-18 14:24:55 -0700218 /*
219 * The priority and statistics can change on a given treatment and selector
220 *
221 * (non-Javadoc)
jcc3d4e14a2015-04-21 11:32:05 +0800222 *
Ayaka Koshibed4e53e12014-09-18 14:24:55 -0700223 * @see java.lang.Object#equals(java.lang.Object)
224 */
Ayaka Koshibe08eabaa2014-09-17 14:59:25 -0700225 public int hashCode() {
Thomas Vachuska711db552015-06-02 16:35:26 -0700226 return Objects.hash(deviceId, selector, tableId, payLoad);
alshabiba68eb962014-09-24 20:34:13 -0700227 }
228
Thomas Vachuska711db552015-06-02 16:35:26 -0700229 //FIXME do we need this method in addition to hashCode()?
230 private int hash() {
231 return Objects.hash(deviceId, selector, tableId, payLoad);
Ayaka Koshibe08eabaa2014-09-17 14:59:25 -0700232 }
233
234 @Override
235 /*
236 * The priority and statistics can change on a given treatment and selector
237 *
238 * (non-Javadoc)
jcc3d4e14a2015-04-21 11:32:05 +0800239 *
Ayaka Koshibe08eabaa2014-09-17 14:59:25 -0700240 * @see java.lang.Object#equals(java.lang.Object)
241 */
242 public boolean equals(Object obj) {
alshabiba7f7ca82014-09-22 11:41:23 -0700243 if (this == obj) {
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700244 return true;
Ayaka Koshibe08eabaa2014-09-17 14:59:25 -0700245 }
alshabib54ce5892014-09-23 17:50:51 -0700246 if (obj instanceof DefaultFlowRule) {
alshabib219ebaa2014-09-22 15:41:24 -0700247 DefaultFlowRule that = (DefaultFlowRule) obj;
248 return Objects.equals(deviceId, that.deviceId) &&
alshabibba5ac482014-10-02 17:15:20 -0700249 Objects.equals(priority, that.priority) &&
Saurav Dascbe6de32015-03-01 18:30:46 -0800250 Objects.equals(selector, that.selector) &&
jcc3d4e14a2015-04-21 11:32:05 +0800251 Objects.equals(tableId, that.tableId)
252 && Objects.equals(payLoad, that.payLoad);
alshabiba7f7ca82014-09-22 11:41:23 -0700253 }
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700254 return false;
Ayaka Koshibe08eabaa2014-09-17 14:59:25 -0700255 }
256
Ayaka Koshibed4e53e12014-09-18 14:24:55 -0700257 @Override
Jonathan Hartf44e42c2015-08-04 09:58:46 -0700258 public boolean exactMatch(FlowRule rule) {
259 return this.equals(rule) &&
260 Objects.equals(this.id, rule.id()) &&
261 Objects.equals(this.treatment, rule.treatment());
262 }
263
264 @Override
Ayaka Koshibed4e53e12014-09-18 14:24:55 -0700265 public String toString() {
266 return toStringHelper(this)
alshabib8ca53902014-10-07 13:11:17 -0700267 .add("id", Long.toHexString(id.value()))
Ayaka Koshibed4e53e12014-09-18 14:24:55 -0700268 .add("deviceId", deviceId)
269 .add("priority", priority)
alshabibba5ac482014-10-02 17:15:20 -0700270 .add("selector", selector.criteria())
Jian Lif0325112016-03-03 17:11:25 -0800271 .add("treatment", treatment == null ? "N/A" : treatment)
alshabib08d98982015-04-21 16:25:50 -0700272 .add("tableId", tableId)
Ayaka Koshibed4e53e12014-09-18 14:24:55 -0700273 .add("created", created)
Ray Milkeyd13a37b2015-06-12 11:55:17 -0700274 .add("payLoad", payLoad)
Ayaka Koshibed4e53e12014-09-18 14:24:55 -0700275 .toString();
276 }
Ayaka Koshibe08eabaa2014-09-17 14:59:25 -0700277
alshabib6eb438a2014-10-01 16:39:37 -0700278 @Override
alshabibba5ac482014-10-02 17:15:20 -0700279 public int timeout() {
alshabib58747a62014-10-07 11:05:30 -0700280 return timeout;
alshabib6eb438a2014-10-01 16:39:37 -0700281 }
282
Jonathan Hartbc4a7932014-10-21 11:46:00 -0700283 @Override
284 public boolean isPermanent() {
285 return permanent;
286 }
287
sangho11c30ac2015-01-22 14:30:55 -0800288 @Override
alshabibdb774072015-04-20 13:13:51 -0700289 public int tableId() {
290 return tableId;
291 }
292
Brian O'Connora3e5cd52015-12-05 15:59:19 -0800293 @Beta
294 public long created() {
295 return created;
296 }
297
alshabibdb774072015-04-20 13:13:51 -0700298 public static Builder builder() {
299 return new Builder();
300 }
301
alshabibd17abc22015-04-21 18:26:35 -0700302 public static final class Builder implements FlowRule.Builder {
alshabibdb774072015-04-20 13:13:51 -0700303
304 private FlowId flowId;
Jonathan Hart65d551b2015-09-22 09:49:09 -0700305 private ApplicationId appId;
alshabibdb774072015-04-20 13:13:51 -0700306 private Integer priority;
307 private DeviceId deviceId;
308 private Integer tableId = 0;
Charles Chancc4754d2015-12-10 15:58:18 -0800309 private TrafficSelector selector = DefaultTrafficSelector.builder().build();
310 private TrafficTreatment treatment = DefaultTrafficTreatment.builder().build();
alshabibdb774072015-04-20 13:13:51 -0700311 private Integer timeout;
312 private Boolean permanent;
313
314 @Override
315 public FlowRule.Builder withCookie(long cookie) {
316 this.flowId = FlowId.valueOf(cookie);
317 return this;
318 }
319
320 @Override
321 public FlowRule.Builder fromApp(ApplicationId appId) {
Jonathan Hart65d551b2015-09-22 09:49:09 -0700322 this.appId = appId;
alshabibdb774072015-04-20 13:13:51 -0700323 return this;
324 }
325
326 @Override
327 public FlowRule.Builder withPriority(int priority) {
328 this.priority = priority;
329 return this;
330 }
331
332 @Override
333 public FlowRule.Builder forDevice(DeviceId deviceId) {
334 this.deviceId = deviceId;
335 return this;
336 }
337
338 @Override
339 public FlowRule.Builder forTable(int tableId) {
340 this.tableId = tableId;
341 return this;
342 }
343
344 @Override
345 public FlowRule.Builder withSelector(TrafficSelector selector) {
346 this.selector = selector;
347 return this;
348 }
349
350 @Override
351 public FlowRule.Builder withTreatment(TrafficTreatment treatment) {
Jonathan Hart24e296b2016-01-12 14:47:07 -0800352 this.treatment = checkNotNull(treatment);
alshabibdb774072015-04-20 13:13:51 -0700353 return this;
354 }
355
356 @Override
357 public FlowRule.Builder makePermanent() {
358 this.timeout = 0;
359 this.permanent = true;
360 return this;
361 }
362
363 @Override
364 public FlowRule.Builder makeTemporary(int timeout) {
365 this.permanent = false;
366 this.timeout = timeout;
367 return this;
368 }
369
370 @Override
371 public FlowRule build() {
alshabibb05be2d2016-04-11 12:52:36 -0700372 FlowId localFlowId;
Jian Li8bac5762016-02-09 17:23:09 -0800373 checkArgument((flowId != null) ^ (appId != null), "Either an application" +
alshabibdb774072015-04-20 13:13:51 -0700374 " id or a cookie must be supplied");
Jonathan Hart65d551b2015-09-22 09:49:09 -0700375 checkNotNull(selector, "Traffic selector cannot be null");
376 checkArgument(timeout != null || permanent != null, "Must either have " +
alshabibdb774072015-04-20 13:13:51 -0700377 "a timeout or be permanent");
Jonathan Hart65d551b2015-09-22 09:49:09 -0700378 checkNotNull(deviceId, "Must refer to a device");
379 checkNotNull(priority, "Priority cannot be null");
Saurav Das3ea46622015-04-22 14:01:34 -0700380 checkArgument(priority >= MIN_PRIORITY, "Priority cannot be less than " +
alshabibdb774072015-04-20 13:13:51 -0700381 MIN_PRIORITY);
Kavitha Alagesan14dc5132016-06-13 17:25:18 +0530382 checkArgument(priority <= MAX_PRIORITY, "Priority cannot be greater than " +
383 MAX_PRIORITY);
Jonathan Hart65d551b2015-09-22 09:49:09 -0700384 // Computing a flow ID based on appId takes precedence over setting
385 // the flow ID directly
386 if (appId != null) {
alshabibb05be2d2016-04-11 12:52:36 -0700387 localFlowId = computeFlowId(appId);
388 } else {
389 localFlowId = flowId;
Jonathan Hart65d551b2015-09-22 09:49:09 -0700390 }
391
alshabibdb774072015-04-20 13:13:51 -0700392 return new DefaultFlowRule(deviceId, selector, treatment, priority,
alshabibb05be2d2016-04-11 12:52:36 -0700393 localFlowId, permanent, timeout, tableId);
alshabibdb774072015-04-20 13:13:51 -0700394 }
395
396 private FlowId computeFlowId(ApplicationId appId) {
397 return FlowId.valueOf((((long) appId.id()) << 48)
398 | (hash() & 0xffffffffL));
399 }
400
401 private int hash() {
Hyunsun Moon7bfbc1c2016-04-05 16:40:43 -0700402 Funnel<TrafficSelector> selectorFunnel = (from, into) -> from.criteria()
Hyunsun Moon7bfbc1c2016-04-05 16:40:43 -0700403 .forEach(c -> into.putString(c.toString(), Charsets.UTF_8));
alshabibdb774072015-04-20 13:13:51 -0700404
Hyunsun Moon7bfbc1c2016-04-05 16:40:43 -0700405 HashFunction hashFunction = Hashing.murmur3_32();
406 HashCode hashCode = hashFunction.newHasher()
407 .putString(deviceId.toString(), Charsets.UTF_8)
408 .putObject(selector, selectorFunnel)
409 .putInt(priority)
410 .putInt(tableId)
411 .hash();
412
413 return hashCode.asInt();
414 }
alshabibdb774072015-04-20 13:13:51 -0700415 }
416
jcc3d4e14a2015-04-21 11:32:05 +0800417 @Override
418 public FlowRuleExtPayLoad payLoad() {
419 return payLoad;
420 }
421
alshabib7b2748f2014-09-16 20:21:11 -0700422}