blob: b8645feaafcdcb7512e04b2074d2e3384d1259c5 [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;
Brian O'Connorabafb502014-12-02 22:26:20 -080019import org.onosproject.core.ApplicationId;
20import org.onosproject.core.DefaultGroupId;
21import org.onosproject.core.GroupId;
22import org.onosproject.net.DeviceId;
alshabib7b2748f2014-09-16 20:21:11 -070023
Jonathan Hart607b1ff2015-05-05 10:55:51 -070024import java.util.Objects;
25
26import static com.google.common.base.MoreObjects.toStringHelper;
27import static com.google.common.base.Preconditions.checkArgument;
28import static com.google.common.base.Preconditions.checkNotNull;
29
alshabib7b2748f2014-09-16 20:21:11 -070030public class DefaultFlowRule implements FlowRule {
31
Ayaka Koshibed4e53e12014-09-18 14:24:55 -070032 private final DeviceId deviceId;
33 private final int priority;
alshabib7b2748f2014-09-16 20:21:11 -070034 private final TrafficSelector selector;
35 private final TrafficTreatment treatment;
Ayaka Koshibed4e53e12014-09-18 14:24:55 -070036 private final long created;
37
alshabib219ebaa2014-09-22 15:41:24 -070038 private final FlowId id;
Ayaka Koshibed4e53e12014-09-18 14:24:55 -070039
alshabibdb774072015-04-20 13:13:51 -070040 private final Short appId;
alshabiba68eb962014-09-24 20:34:13 -070041
alshabibba5ac482014-10-02 17:15:20 -070042 private final int timeout;
Jonathan Hartbc4a7932014-10-21 11:46:00 -070043 private final boolean permanent;
Sho SHIMIZU75a5bd92014-11-25 11:22:56 -080044 private final GroupId groupId;
alshabib6eb438a2014-10-01 16:39:37 -070045
alshabibdb774072015-04-20 13:13:51 -070046 private final Integer tableId;
jcc3d4e14a2015-04-21 11:32:05 +080047 private final FlowRuleExtPayLoad payLoad;
alshabib1c319ff2014-10-04 20:29:09 -070048
alshabib1c319ff2014-10-04 20:29:09 -070049 public DefaultFlowRule(FlowRule rule) {
50 this.deviceId = rule.deviceId();
51 this.priority = rule.priority();
52 this.selector = rule.selector();
53 this.treatment = rule.treatment();
54 this.appId = rule.appId();
alshabib28204e52014-11-12 18:29:45 -080055 this.groupId = rule.groupId();
alshabib1c319ff2014-10-04 20:29:09 -070056 this.id = rule.id();
57 this.timeout = rule.timeout();
Jonathan Hartbc4a7932014-10-21 11:46:00 -070058 this.permanent = rule.isPermanent();
alshabib219ebaa2014-09-22 15:41:24 -070059 this.created = System.currentTimeMillis();
alshabibdb774072015-04-20 13:13:51 -070060 this.tableId = rule.tableId();
jcc3d4e14a2015-04-21 11:32:05 +080061 this.payLoad = rule.payLoad();
alshabibdb774072015-04-20 13:13:51 -070062 }
63
64 private DefaultFlowRule(DeviceId deviceId, TrafficSelector selector,
65 TrafficTreatment treatment, Integer priority,
66 FlowId flowId, Boolean permanent, Integer timeout,
67 Integer tableId) {
68
69 this.deviceId = deviceId;
70 this.selector = selector;
71 this.treatment = treatment;
72 this.priority = priority;
73 this.appId = (short) (flowId.value() >>> 48);
74 this.id = flowId;
75 this.permanent = permanent;
76 this.timeout = timeout;
77 this.tableId = tableId;
78 this.created = System.currentTimeMillis();
79
80
81 //FIXME: fields below will be removed.
Jonathan Hart607b1ff2015-05-05 10:55:51 -070082 this.groupId = new DefaultGroupId(0);
jcc3d4e14a2015-04-21 11:32:05 +080083 this.payLoad = null;
84 }
alshabibdb774072015-04-20 13:13:51 -070085
jcc3d4e14a2015-04-21 11:32:05 +080086 /**
87 * Support for the third party flow rule. Creates a flow rule of flow table.
88 *
89 * @param deviceId the identity of the device where this rule applies
90 * @param selector the traffic selector that identifies what traffic this
91 * rule
92 * @param treatment the traffic treatment that applies to selected traffic
93 * @param priority the flow rule priority given in natural order
94 * @param appId the application id of this flow
95 * @param timeout the timeout for this flow requested by an application
96 * @param permanent whether the flow is permanent i.e. does not time out
97 * @param payLoad 3rd-party origin private flow
98 */
99 public DefaultFlowRule(DeviceId deviceId, TrafficSelector selector,
100 TrafficTreatment treatment, int priority,
101 ApplicationId appId, int timeout, boolean permanent,
102 FlowRuleExtPayLoad payLoad) {
alshabib1c319ff2014-10-04 20:29:09 -0700103
jcc3d4e14a2015-04-21 11:32:05 +0800104 if (priority < FlowRule.MIN_PRIORITY) {
105 throw new IllegalArgumentException("Priority cannot be less than "
106 + MIN_PRIORITY);
107 }
108
109 this.deviceId = deviceId;
110 this.priority = priority;
111 this.selector = selector;
112 this.treatment = treatment;
113 this.appId = appId.id();
114 this.groupId = new DefaultGroupId(0);
115 this.timeout = timeout;
116 this.permanent = permanent;
117 this.tableId = 0;
118 this.created = System.currentTimeMillis();
119 this.payLoad = payLoad;
120
121 /*
122 * id consists of the following. | appId (16 bits) | groupId (16 bits) |
123 * flowId (32 bits) |
124 */
125 this.id = FlowId.valueOf((((long) this.appId) << 48)
126 | (((long) this.groupId.id()) << 32)
127 | (this.hash() & 0xffffffffL));
128 }
129
130 /**
131 * Support for the third party flow rule. Creates a flow rule of group
132 * table.
133 *
134 * @param deviceId the identity of the device where this rule applies
135 * @param selector the traffic selector that identifies what traffic this
136 * rule
137 * @param treatment the traffic treatment that applies to selected traffic
138 * @param priority the flow rule priority given in natural order
139 * @param appId the application id of this flow
140 * @param groupId the group id of this flow
141 * @param timeout the timeout for this flow requested by an application
142 * @param permanent whether the flow is permanent i.e. does not time out
143 * @param payLoad 3rd-party origin private flow
144 *
145 */
146 public DefaultFlowRule(DeviceId deviceId, TrafficSelector selector,
147 TrafficTreatment treatment, int priority,
148 ApplicationId appId, GroupId groupId, int timeout,
149 boolean permanent, FlowRuleExtPayLoad payLoad) {
150
151 if (priority < FlowRule.MIN_PRIORITY) {
152 throw new IllegalArgumentException("Priority cannot be less than "
153 + MIN_PRIORITY);
154 }
155
156 this.deviceId = deviceId;
157 this.priority = priority;
158 this.selector = selector;
159 this.treatment = treatment;
160 this.appId = appId.id();
161 this.groupId = groupId;
162 this.timeout = timeout;
163 this.permanent = permanent;
164 this.created = System.currentTimeMillis();
165 this.tableId = 0;
166 this.payLoad = payLoad;
167
168 /*
169 * id consists of the following. | appId (16 bits) | groupId (16 bits) |
170 * flowId (32 bits) |
171 */
172 this.id = FlowId.valueOf((((long) this.appId) << 48)
173 | (((long) this.groupId.id()) << 32)
174 | (this.hash() & 0xffffffffL));
alshabiba7f7ca82014-09-22 11:41:23 -0700175 }
176
Ayaka Koshibed4e53e12014-09-18 14:24:55 -0700177 @Override
178 public FlowId id() {
179 return id;
alshabib7b2748f2014-09-16 20:21:11 -0700180 }
181
182 @Override
alshabib92c65ad2014-10-08 21:56:05 -0700183 public short appId() {
alshabiba68eb962014-09-24 20:34:13 -0700184 return appId;
185 }
186
187 @Override
Sho SHIMIZU75a5bd92014-11-25 11:22:56 -0800188 public GroupId groupId() {
alshabib28204e52014-11-12 18:29:45 -0800189 return groupId;
190 }
191
192 @Override
alshabib7b2748f2014-09-16 20:21:11 -0700193 public int priority() {
Ayaka Koshibed4e53e12014-09-18 14:24:55 -0700194 return priority;
alshabib7b2748f2014-09-16 20:21:11 -0700195 }
196
197 @Override
198 public DeviceId deviceId() {
199 return deviceId;
200 }
201
202 @Override
203 public TrafficSelector selector() {
204 return selector;
205 }
206
207 @Override
208 public TrafficTreatment treatment() {
209 return treatment;
210 }
211
alshabiba7f7ca82014-09-22 11:41:23 -0700212 @Override
Ayaka Koshibed4e53e12014-09-18 14:24:55 -0700213 /*
214 * The priority and statistics can change on a given treatment and selector
215 *
216 * (non-Javadoc)
jcc3d4e14a2015-04-21 11:32:05 +0800217 *
Ayaka Koshibed4e53e12014-09-18 14:24:55 -0700218 * @see java.lang.Object#equals(java.lang.Object)
219 */
Ayaka Koshibe08eabaa2014-09-17 14:59:25 -0700220 public int hashCode() {
Thomas Vachuska711db552015-06-02 16:35:26 -0700221 return Objects.hash(deviceId, selector, tableId, payLoad);
alshabiba68eb962014-09-24 20:34:13 -0700222 }
223
Thomas Vachuska711db552015-06-02 16:35:26 -0700224 //FIXME do we need this method in addition to hashCode()?
225 private int hash() {
226 return Objects.hash(deviceId, selector, tableId, payLoad);
Ayaka Koshibe08eabaa2014-09-17 14:59:25 -0700227 }
228
229 @Override
230 /*
231 * The priority and statistics can change on a given treatment and selector
232 *
233 * (non-Javadoc)
jcc3d4e14a2015-04-21 11:32:05 +0800234 *
Ayaka Koshibe08eabaa2014-09-17 14:59:25 -0700235 * @see java.lang.Object#equals(java.lang.Object)
236 */
237 public boolean equals(Object obj) {
alshabiba7f7ca82014-09-22 11:41:23 -0700238 if (this == obj) {
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700239 return true;
Ayaka Koshibe08eabaa2014-09-17 14:59:25 -0700240 }
alshabib54ce5892014-09-23 17:50:51 -0700241 if (obj instanceof DefaultFlowRule) {
alshabib219ebaa2014-09-22 15:41:24 -0700242 DefaultFlowRule that = (DefaultFlowRule) obj;
243 return Objects.equals(deviceId, that.deviceId) &&
alshabibba5ac482014-10-02 17:15:20 -0700244 Objects.equals(priority, that.priority) &&
Saurav Dascbe6de32015-03-01 18:30:46 -0800245 Objects.equals(selector, that.selector) &&
jcc3d4e14a2015-04-21 11:32:05 +0800246 Objects.equals(tableId, that.tableId)
247 && Objects.equals(payLoad, that.payLoad);
alshabiba7f7ca82014-09-22 11:41:23 -0700248 }
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700249 return false;
Ayaka Koshibe08eabaa2014-09-17 14:59:25 -0700250 }
251
Ayaka Koshibed4e53e12014-09-18 14:24:55 -0700252 @Override
Jonathan Hartf44e42c2015-08-04 09:58:46 -0700253 public boolean exactMatch(FlowRule rule) {
254 return this.equals(rule) &&
255 Objects.equals(this.id, rule.id()) &&
256 Objects.equals(this.treatment, rule.treatment());
257 }
258
259 @Override
Ayaka Koshibed4e53e12014-09-18 14:24:55 -0700260 public String toString() {
261 return toStringHelper(this)
alshabib8ca53902014-10-07 13:11:17 -0700262 .add("id", Long.toHexString(id.value()))
Ayaka Koshibed4e53e12014-09-18 14:24:55 -0700263 .add("deviceId", deviceId)
264 .add("priority", priority)
alshabibba5ac482014-10-02 17:15:20 -0700265 .add("selector", selector.criteria())
Jian Lif0325112016-03-03 17:11:25 -0800266 .add("treatment", treatment == null ? "N/A" : treatment)
alshabib08d98982015-04-21 16:25:50 -0700267 .add("tableId", tableId)
Ayaka Koshibed4e53e12014-09-18 14:24:55 -0700268 .add("created", created)
Ray Milkeyd13a37b2015-06-12 11:55:17 -0700269 .add("payLoad", payLoad)
Ayaka Koshibed4e53e12014-09-18 14:24:55 -0700270 .toString();
271 }
Ayaka Koshibe08eabaa2014-09-17 14:59:25 -0700272
alshabib6eb438a2014-10-01 16:39:37 -0700273 @Override
alshabibba5ac482014-10-02 17:15:20 -0700274 public int timeout() {
alshabib58747a62014-10-07 11:05:30 -0700275 return timeout;
alshabib6eb438a2014-10-01 16:39:37 -0700276 }
277
Jonathan Hartbc4a7932014-10-21 11:46:00 -0700278 @Override
279 public boolean isPermanent() {
280 return permanent;
281 }
282
sangho11c30ac2015-01-22 14:30:55 -0800283 @Override
alshabibdb774072015-04-20 13:13:51 -0700284 public int tableId() {
285 return tableId;
286 }
287
Brian O'Connora3e5cd52015-12-05 15:59:19 -0800288 @Beta
289 public long created() {
290 return created;
291 }
292
alshabibdb774072015-04-20 13:13:51 -0700293 public static Builder builder() {
294 return new Builder();
295 }
296
alshabibd17abc22015-04-21 18:26:35 -0700297 public static final class Builder implements FlowRule.Builder {
alshabibdb774072015-04-20 13:13:51 -0700298
299 private FlowId flowId;
Jonathan Hart65d551b2015-09-22 09:49:09 -0700300 private ApplicationId appId;
alshabibdb774072015-04-20 13:13:51 -0700301 private Integer priority;
302 private DeviceId deviceId;
303 private Integer tableId = 0;
Charles Chancc4754d2015-12-10 15:58:18 -0800304 private TrafficSelector selector = DefaultTrafficSelector.builder().build();
305 private TrafficTreatment treatment = DefaultTrafficTreatment.builder().build();
alshabibdb774072015-04-20 13:13:51 -0700306 private Integer timeout;
307 private Boolean permanent;
308
309 @Override
310 public FlowRule.Builder withCookie(long cookie) {
311 this.flowId = FlowId.valueOf(cookie);
312 return this;
313 }
314
315 @Override
316 public FlowRule.Builder fromApp(ApplicationId appId) {
Jonathan Hart65d551b2015-09-22 09:49:09 -0700317 this.appId = appId;
alshabibdb774072015-04-20 13:13:51 -0700318 return this;
319 }
320
321 @Override
322 public FlowRule.Builder withPriority(int priority) {
323 this.priority = priority;
324 return this;
325 }
326
327 @Override
328 public FlowRule.Builder forDevice(DeviceId deviceId) {
329 this.deviceId = deviceId;
330 return this;
331 }
332
333 @Override
334 public FlowRule.Builder forTable(int tableId) {
335 this.tableId = tableId;
336 return this;
337 }
338
339 @Override
340 public FlowRule.Builder withSelector(TrafficSelector selector) {
341 this.selector = selector;
342 return this;
343 }
344
345 @Override
346 public FlowRule.Builder withTreatment(TrafficTreatment treatment) {
Jonathan Hart24e296b2016-01-12 14:47:07 -0800347 this.treatment = checkNotNull(treatment);
alshabibdb774072015-04-20 13:13:51 -0700348 return this;
349 }
350
351 @Override
352 public FlowRule.Builder makePermanent() {
353 this.timeout = 0;
354 this.permanent = true;
355 return this;
356 }
357
358 @Override
359 public FlowRule.Builder makeTemporary(int timeout) {
360 this.permanent = false;
361 this.timeout = timeout;
362 return this;
363 }
364
365 @Override
366 public FlowRule build() {
Jian Li8bac5762016-02-09 17:23:09 -0800367 checkArgument((flowId != null) ^ (appId != null), "Either an application" +
alshabibdb774072015-04-20 13:13:51 -0700368 " id or a cookie must be supplied");
Jonathan Hart65d551b2015-09-22 09:49:09 -0700369 checkNotNull(selector, "Traffic selector cannot be null");
370 checkArgument(timeout != null || permanent != null, "Must either have " +
alshabibdb774072015-04-20 13:13:51 -0700371 "a timeout or be permanent");
Jonathan Hart65d551b2015-09-22 09:49:09 -0700372 checkNotNull(deviceId, "Must refer to a device");
373 checkNotNull(priority, "Priority cannot be null");
Saurav Das3ea46622015-04-22 14:01:34 -0700374 checkArgument(priority >= MIN_PRIORITY, "Priority cannot be less than " +
alshabibdb774072015-04-20 13:13:51 -0700375 MIN_PRIORITY);
376
Jonathan Hart65d551b2015-09-22 09:49:09 -0700377 // Computing a flow ID based on appId takes precedence over setting
378 // the flow ID directly
379 if (appId != null) {
380 flowId = computeFlowId(appId);
381 }
382
alshabibdb774072015-04-20 13:13:51 -0700383 return new DefaultFlowRule(deviceId, selector, treatment, priority,
384 flowId, permanent, timeout, tableId);
385 }
386
387 private FlowId computeFlowId(ApplicationId appId) {
388 return FlowId.valueOf((((long) appId.id()) << 48)
389 | (hash() & 0xffffffffL));
390 }
391
392 private int hash() {
Jonathan Hartf44e42c2015-08-04 09:58:46 -0700393 return Objects.hash(deviceId, priority, selector, tableId);
alshabibdb774072015-04-20 13:13:51 -0700394 }
395
396 }
397
jcc3d4e14a2015-04-21 11:32:05 +0800398 @Override
399 public FlowRuleExtPayLoad payLoad() {
400 return payLoad;
401 }
402
alshabib7b2748f2014-09-16 20:21:11 -0700403}