blob: 2ba0bc8ddd7c9489ac1d1d32eebf45287eced978 [file] [log] [blame]
Carmelo Cascone1022a4e2017-05-25 00:16:18 -04001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2017-present Open Networking Foundation
Carmelo Cascone1022a4e2017-05-25 00:16:18 -04003 *
4 * 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
7 *
8 * 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.
15 */
16
17package org.onosproject.net.flow.criteria;
18
19import com.google.common.annotations.Beta;
20import com.google.common.base.Objects;
Carmelo Cascone32a01b22017-07-18 10:51:07 -040021import com.google.common.collect.ImmutableMap;
Carmelo Cascone87892e22017-11-13 16:01:29 -080022import org.onosproject.net.pi.model.PiMatchFieldId;
Carmelo Cascone32a01b22017-07-18 10:51:07 -040023import org.onosproject.net.pi.runtime.PiExactFieldMatch;
Carmelo Cascone1022a4e2017-05-25 00:16:18 -040024import org.onosproject.net.pi.runtime.PiFieldMatch;
Frank Wangdf383212017-06-23 09:17:41 +080025import org.onosproject.net.pi.runtime.PiLpmFieldMatch;
26import org.onosproject.net.pi.runtime.PiRangeFieldMatch;
Carmelo Cascone32a01b22017-07-18 10:51:07 -040027import org.onosproject.net.pi.runtime.PiTernaryFieldMatch;
Frank Wangdf383212017-06-23 09:17:41 +080028import org.onosproject.net.pi.runtime.PiValidFieldMatch;
Carmelo Cascone1022a4e2017-05-25 00:16:18 -040029
30import java.util.Collection;
Carmelo Cascone32a01b22017-07-18 10:51:07 -040031import java.util.Optional;
Carmelo Cascone1022a4e2017-05-25 00:16:18 -040032import java.util.StringJoiner;
33
Frank Wangdf383212017-06-23 09:17:41 +080034import static com.google.common.base.Preconditions.checkArgument;
35import static org.onlab.util.ImmutableByteSequence.copyFrom;
36
Carmelo Cascone1022a4e2017-05-25 00:16:18 -040037/**
Carmelo Cascone22619172017-07-13 16:08:17 -040038 * Protocol-independent criterion.
Carmelo Cascone1022a4e2017-05-25 00:16:18 -040039 */
40@Beta
41public final class PiCriterion implements Criterion {
42
Carmelo Cascone87892e22017-11-13 16:01:29 -080043 private final ImmutableMap<PiMatchFieldId, PiFieldMatch> fieldMatchMap;
Carmelo Cascone1022a4e2017-05-25 00:16:18 -040044
45 /**
46 * Creates a new protocol-independent criterion for the given match fields.
47 *
Carmelo Cascone32a01b22017-07-18 10:51:07 -040048 * @param fieldMatchMap field match map
Carmelo Cascone1022a4e2017-05-25 00:16:18 -040049 */
Carmelo Cascone87892e22017-11-13 16:01:29 -080050 private PiCriterion(ImmutableMap<PiMatchFieldId, PiFieldMatch> fieldMatchMap) {
Carmelo Cascone32a01b22017-07-18 10:51:07 -040051 this.fieldMatchMap = fieldMatchMap;
Carmelo Cascone1022a4e2017-05-25 00:16:18 -040052 }
53
54 /**
Carmelo Cascone32a01b22017-07-18 10:51:07 -040055 * Returns all protocol-independent field matches defined by this criterion.
Carmelo Cascone1022a4e2017-05-25 00:16:18 -040056 *
Carmelo Cascone32a01b22017-07-18 10:51:07 -040057 * @return collection of match parameters
Carmelo Cascone1022a4e2017-05-25 00:16:18 -040058 */
59 public Collection<PiFieldMatch> fieldMatches() {
Carmelo Cascone32a01b22017-07-18 10:51:07 -040060 return fieldMatchMap.values();
61 }
62
63 /**
64 * If present, returns the field match associated with the given header field identifier.
65 *
66 * @param fieldId field identifier
67 * @return optional field match
68 */
Carmelo Cascone87892e22017-11-13 16:01:29 -080069 public Optional<PiFieldMatch> fieldMatch(PiMatchFieldId fieldId) {
Carmelo Cascone32a01b22017-07-18 10:51:07 -040070 return Optional.ofNullable(fieldMatchMap.get(fieldId));
Carmelo Cascone1022a4e2017-05-25 00:16:18 -040071 }
72
73 @Override
74 public Type type() {
75 return Type.PROTOCOL_INDEPENDENT;
76 }
77
78 @Override
79 public boolean equals(Object o) {
80 if (this == o) {
81 return true;
82 }
83 if (o == null || getClass() != o.getClass()) {
84 return false;
85 }
86 PiCriterion that = (PiCriterion) o;
Carmelo Cascone32a01b22017-07-18 10:51:07 -040087 return Objects.equal(fieldMatchMap, that.fieldMatchMap);
Carmelo Cascone1022a4e2017-05-25 00:16:18 -040088 }
89
90 @Override
91 public int hashCode() {
Carmelo Cascone32a01b22017-07-18 10:51:07 -040092 return Objects.hashCode(fieldMatchMap);
Carmelo Cascone1022a4e2017-05-25 00:16:18 -040093 }
94
95 @Override
96 public String toString() {
97 StringJoiner stringParams = new StringJoiner(", ", "{", "}");
Carmelo Cascone32a01b22017-07-18 10:51:07 -040098 fieldMatchMap.forEach((key, value) -> stringParams.add(value.toString()));
Carmelo Cascone1022a4e2017-05-25 00:16:18 -040099 return stringParams.toString();
100 }
Frank Wangdf383212017-06-23 09:17:41 +0800101
102 /**
103 * Returns the PiCriterion builder.
104 *
105 * @return PiCriterion builder
106 */
107 public static Builder builder() {
108 return new Builder();
109 }
110
111 /**
112 * PiCriterion Builder.
113 */
114 @Beta
115 public static final class Builder {
116
Carmelo Cascone22619172017-07-13 16:08:17 -0400117 // Use map to guarantee that there's only one field match per field id.
Carmelo Cascone87892e22017-11-13 16:01:29 -0800118 private final ImmutableMap.Builder<PiMatchFieldId, PiFieldMatch> fieldMatchMapBuilder = ImmutableMap.builder();
Frank Wangdf383212017-06-23 09:17:41 +0800119
120 private Builder() {
121 // ban constructor.
122 }
123
124 /**
125 * Adds an exact field match for the given fieldId and value.
126 *
127 * @param fieldId protocol-independent header field Id
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400128 * @param value exact match value
Frank Wangdf383212017-06-23 09:17:41 +0800129 * @return this
130 */
Carmelo Cascone87892e22017-11-13 16:01:29 -0800131 public Builder matchExact(PiMatchFieldId fieldId, short value) {
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400132 fieldMatchMapBuilder.put(fieldId, new PiExactFieldMatch(fieldId, copyFrom(value)));
Frank Wangdf383212017-06-23 09:17:41 +0800133 return this;
134 }
135
136 /**
137 * Adds an exact field match for the given fieldId and value.
138 *
139 * @param fieldId protocol-independent header field Id
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400140 * @param value exact match value
Frank Wangdf383212017-06-23 09:17:41 +0800141 * @return this
142 */
Carmelo Cascone87892e22017-11-13 16:01:29 -0800143 public Builder matchExact(PiMatchFieldId fieldId, int value) {
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400144 fieldMatchMapBuilder.put(fieldId, new PiExactFieldMatch(fieldId, copyFrom(value)));
Frank Wangdf383212017-06-23 09:17:41 +0800145 return this;
146 }
147
148 /**
149 * Adds an exact field match for the given fieldId and value.
150 *
151 * @param fieldId protocol-independent header field Id
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400152 * @param value exact match value
Frank Wangdf383212017-06-23 09:17:41 +0800153 * @return this
154 */
Carmelo Cascone87892e22017-11-13 16:01:29 -0800155 public Builder matchExact(PiMatchFieldId fieldId, long value) {
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400156 fieldMatchMapBuilder.put(fieldId, new PiExactFieldMatch(fieldId, copyFrom(value)));
Frank Wangdf383212017-06-23 09:17:41 +0800157 return this;
158 }
159
160 /**
161 * Adds an exact field match for the given fieldId and value.
162 *
163 * @param fieldId protocol-independent header field Id
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400164 * @param value exact match value
Frank Wangdf383212017-06-23 09:17:41 +0800165 * @return this
166 */
Carmelo Cascone87892e22017-11-13 16:01:29 -0800167 public Builder matchExact(PiMatchFieldId fieldId, byte[] value) {
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400168 fieldMatchMapBuilder.put(fieldId, new PiExactFieldMatch(fieldId, copyFrom(value)));
Frank Wangdf383212017-06-23 09:17:41 +0800169 return this;
170 }
171
172 /**
173 * Adds a ternary field match for the given fieldId, value and mask.
174 *
175 * @param fieldId protocol-independent header field Id
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400176 * @param value ternary match value
177 * @param mask ternary match mask
Frank Wangdf383212017-06-23 09:17:41 +0800178 * @return this
179 */
Carmelo Cascone87892e22017-11-13 16:01:29 -0800180 public Builder matchTernary(PiMatchFieldId fieldId, short value, short mask) {
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400181 fieldMatchMapBuilder.put(fieldId, new PiTernaryFieldMatch(fieldId, copyFrom(value), copyFrom(mask)));
Frank Wangdf383212017-06-23 09:17:41 +0800182 return this;
183 }
184
185 /**
186 * Adds a ternary field match for the given fieldId, value and mask.
187 *
188 * @param fieldId protocol-independent header field Id
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400189 * @param value ternary match value
190 * @param mask ternary match mask
Frank Wangdf383212017-06-23 09:17:41 +0800191 * @return this
192 */
Carmelo Cascone87892e22017-11-13 16:01:29 -0800193 public Builder matchTernary(PiMatchFieldId fieldId, int value, int mask) {
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400194 fieldMatchMapBuilder.put(fieldId, new PiTernaryFieldMatch(fieldId, copyFrom(value), copyFrom(mask)));
Frank Wangdf383212017-06-23 09:17:41 +0800195 return this;
196 }
197
198 /**
199 * Adds a ternary field match for the given fieldId, value and mask.
200 *
201 * @param fieldId protocol-independent header field Id
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400202 * @param value ternary match value
203 * @param mask ternary match mask
Frank Wangdf383212017-06-23 09:17:41 +0800204 * @return this
205 */
Carmelo Cascone87892e22017-11-13 16:01:29 -0800206 public Builder matchTernary(PiMatchFieldId fieldId, long value, long mask) {
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400207 fieldMatchMapBuilder.put(fieldId, new PiTernaryFieldMatch(fieldId, copyFrom(value), copyFrom(mask)));
Frank Wangdf383212017-06-23 09:17:41 +0800208 return this;
209 }
210
211 /**
212 * Adds a ternary field match for the given fieldId, value and mask.
213 *
214 * @param fieldId protocol-independent header field Id
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400215 * @param value ternary match value
216 * @param mask ternary match mask
Frank Wangdf383212017-06-23 09:17:41 +0800217 * @return this
218 */
Carmelo Cascone87892e22017-11-13 16:01:29 -0800219 public Builder matchTernary(PiMatchFieldId fieldId, byte[] value, byte[] mask) {
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400220 fieldMatchMapBuilder.put(fieldId, new PiTernaryFieldMatch(fieldId, copyFrom(value), copyFrom(mask)));
Frank Wangdf383212017-06-23 09:17:41 +0800221 return this;
222 }
223
224 /**
225 * Adds a longest-prefix field match for the given fieldId, value and prefix length.
226 *
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400227 * @param fieldId protocol-independent header field Id
228 * @param value lpm match value
Frank Wangdf383212017-06-23 09:17:41 +0800229 * @param prefixLength lpm match prefix length
230 * @return this
231 */
Carmelo Cascone87892e22017-11-13 16:01:29 -0800232 public Builder matchLpm(PiMatchFieldId fieldId, short value, int prefixLength) {
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400233 fieldMatchMapBuilder.put(fieldId, new PiLpmFieldMatch(fieldId, copyFrom(value), prefixLength));
Frank Wangdf383212017-06-23 09:17:41 +0800234 return this;
235 }
236
237 /**
238 * Adds a longest-prefix field match for the given fieldId, value and prefix length.
239 *
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400240 * @param fieldId protocol-independent header field Id
241 * @param value lpm match value
Frank Wangdf383212017-06-23 09:17:41 +0800242 * @param prefixLength lpm match prefix length
243 * @return this
244 */
Carmelo Cascone87892e22017-11-13 16:01:29 -0800245 public Builder matchLpm(PiMatchFieldId fieldId, int value, int prefixLength) {
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400246 fieldMatchMapBuilder.put(fieldId, new PiLpmFieldMatch(fieldId, copyFrom(value), prefixLength));
Frank Wangdf383212017-06-23 09:17:41 +0800247 return this;
248 }
249
250 /**
251 * Adds a longest-prefix field match for the given fieldId, value and prefix length.
252 *
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400253 * @param fieldId protocol-independent header field Id
254 * @param value lpm match value
Frank Wangdf383212017-06-23 09:17:41 +0800255 * @param prefixLength lpm match prefix length
256 * @return this
257 */
Carmelo Cascone87892e22017-11-13 16:01:29 -0800258 public Builder matchLpm(PiMatchFieldId fieldId, long value, int prefixLength) {
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400259 fieldMatchMapBuilder.put(fieldId, new PiLpmFieldMatch(fieldId, copyFrom(value), prefixLength));
Frank Wangdf383212017-06-23 09:17:41 +0800260 return this;
261 }
262
263 /**
264 * Adds a longest-prefix field match for the given fieldId, value and prefix length.
265 *
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400266 * @param fieldId protocol-independent header field Id
267 * @param value lpm match value
Frank Wangdf383212017-06-23 09:17:41 +0800268 * @param prefixLength lpm match prefix length
269 * @return this
270 */
Carmelo Cascone87892e22017-11-13 16:01:29 -0800271 public Builder matchLpm(PiMatchFieldId fieldId, byte[] value, int prefixLength) {
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400272 fieldMatchMapBuilder.put(fieldId, new PiLpmFieldMatch(fieldId, copyFrom(value), prefixLength));
Frank Wangdf383212017-06-23 09:17:41 +0800273 return this;
274 }
275
276 /**
277 * Adds a valid field match for the given fieldId and flag.
278 *
279 * @param fieldId protocol-independent header field Id
280 * @param flag a boolean value
281 * @return this
282 */
Carmelo Cascone87892e22017-11-13 16:01:29 -0800283 public Builder matchValid(PiMatchFieldId fieldId, boolean flag) {
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400284 fieldMatchMapBuilder.put(fieldId, new PiValidFieldMatch(fieldId, flag));
Frank Wangdf383212017-06-23 09:17:41 +0800285 return this;
286 }
287
288 /**
289 * Adds a range field match for the given fieldId, low and high.
290 *
291 * @param fieldId protocol-independent header field Id
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400292 * @param low range match low value
293 * @param high range match high value
Frank Wangdf383212017-06-23 09:17:41 +0800294 * @return this
295 */
Carmelo Cascone87892e22017-11-13 16:01:29 -0800296 public Builder matchRange(PiMatchFieldId fieldId, short low, short high) {
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400297 fieldMatchMapBuilder.put(fieldId, new PiRangeFieldMatch(fieldId, copyFrom(low), copyFrom(high)));
Frank Wangdf383212017-06-23 09:17:41 +0800298 return this;
299 }
300
301 /**
302 * Adds a range field match for the given fieldId, low and high.
303 *
304 * @param fieldId protocol-independent header field Id
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400305 * @param low range match low value
306 * @param high range match high value
Frank Wangdf383212017-06-23 09:17:41 +0800307 * @return this
308 */
Carmelo Cascone87892e22017-11-13 16:01:29 -0800309 public Builder matchRange(PiMatchFieldId fieldId, int low, int high) {
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400310 fieldMatchMapBuilder.put(fieldId, new PiRangeFieldMatch(fieldId, copyFrom(low), copyFrom(high)));
Frank Wangdf383212017-06-23 09:17:41 +0800311 return this;
312 }
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400313
Frank Wangdf383212017-06-23 09:17:41 +0800314 /**
315 * Adds a range field match for the given fieldId, low and high.
316 *
317 * @param fieldId protocol-independent header field Id
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400318 * @param low range match low value
319 * @param high range match high value
Frank Wangdf383212017-06-23 09:17:41 +0800320 * @return this
321 */
Carmelo Cascone87892e22017-11-13 16:01:29 -0800322 public Builder matchRange(PiMatchFieldId fieldId, long low, long high) {
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400323 fieldMatchMapBuilder.put(fieldId, new PiRangeFieldMatch(fieldId, copyFrom(low), copyFrom(high)));
Frank Wangdf383212017-06-23 09:17:41 +0800324 return this;
325 }
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400326
Frank Wangdf383212017-06-23 09:17:41 +0800327 /**
328 * Adds a range field match for the given fieldId, low and high.
329 *
330 * @param fieldId protocol-independent header field Id
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400331 * @param low range match low value
332 * @param high range match high value
Frank Wangdf383212017-06-23 09:17:41 +0800333 * @return this
334 */
Carmelo Cascone87892e22017-11-13 16:01:29 -0800335 public Builder matchRange(PiMatchFieldId fieldId, byte[] low, byte[] high) {
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400336 fieldMatchMapBuilder.put(fieldId, new PiRangeFieldMatch(fieldId, copyFrom(low), copyFrom(high)));
Frank Wangdf383212017-06-23 09:17:41 +0800337 return this;
338 }
339
340 /**
341 * Builds a PiCriterion.
342 *
343 * @return PiCriterion
344 */
Carmelo Cascone770507f2017-09-14 20:58:04 +0200345 public PiCriterion build() {
Carmelo Cascone87892e22017-11-13 16:01:29 -0800346 ImmutableMap<PiMatchFieldId, PiFieldMatch> fieldMatchMap = fieldMatchMapBuilder.build();
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400347 checkArgument(fieldMatchMap.size() > 0, "Cannot build PI criterion with 0 field matches");
348 return new PiCriterion(fieldMatchMap);
Frank Wangdf383212017-06-23 09:17:41 +0800349 }
350 }
Carmelo Cascone87892e22017-11-13 16:01:29 -0800351}