blob: 43a5bdfb87a77cc9579d8bbd4e76f6d3b9ba446e [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;
Daniele Moroc6f2f7f2020-12-18 10:55:57 +010026import org.onosproject.net.pi.runtime.PiOptionalFieldMatch;
Frank Wangdf383212017-06-23 09:17:41 +080027import org.onosproject.net.pi.runtime.PiRangeFieldMatch;
Carmelo Cascone32a01b22017-07-18 10:51:07 -040028import org.onosproject.net.pi.runtime.PiTernaryFieldMatch;
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() {
Carmelo Cascone0316b962018-04-11 17:39:07 -070097 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 /**
pierventre5a936f52020-10-08 17:21:49 +0200112 * Returns the PiCriterion builder initialized by the given PiCriterion.
113 *
114 * @param piCriterion the input PiCriterion
115 * @return PiCriterion builder
116 */
117 public static Builder builder(PiCriterion piCriterion) {
118 return new Builder(piCriterion);
119 }
120
121 /**
Frank Wangdf383212017-06-23 09:17:41 +0800122 * PiCriterion Builder.
123 */
124 @Beta
125 public static final class Builder {
126
Carmelo Cascone22619172017-07-13 16:08:17 -0400127 // Use map to guarantee that there's only one field match per field id.
Carmelo Cascone87892e22017-11-13 16:01:29 -0800128 private final ImmutableMap.Builder<PiMatchFieldId, PiFieldMatch> fieldMatchMapBuilder = ImmutableMap.builder();
Frank Wangdf383212017-06-23 09:17:41 +0800129
130 private Builder() {
131 // ban constructor.
132 }
133
pierventre5a936f52020-10-08 17:21:49 +0200134 private Builder(PiCriterion piCriterion) {
135 piCriterion.fieldMatchMap.forEach(((piMatchFieldId, piFieldMatch) -> add(piFieldMatch)));
136 }
137
138 /**
139 * Adds a match field to the builder.
140 *
141 * @param field the field value
142 * @return this
143 */
144 public Builder add(PiFieldMatch field) {
145 fieldMatchMapBuilder.put(field.fieldId(), field);
146 return this;
147 }
148
Frank Wangdf383212017-06-23 09:17:41 +0800149 /**
150 * Adds an exact field match for the given fieldId and value.
151 *
152 * @param fieldId protocol-independent header field Id
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400153 * @param value exact match value
Frank Wangdf383212017-06-23 09:17:41 +0800154 * @return this
155 */
Carmelo Cascone87892e22017-11-13 16:01:29 -0800156 public Builder matchExact(PiMatchFieldId fieldId, short value) {
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400157 fieldMatchMapBuilder.put(fieldId, new PiExactFieldMatch(fieldId, copyFrom(value)));
Frank Wangdf383212017-06-23 09:17:41 +0800158 return this;
159 }
160
161 /**
162 * Adds an exact field match for the given fieldId and value.
163 *
164 * @param fieldId protocol-independent header field Id
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400165 * @param value exact match value
Frank Wangdf383212017-06-23 09:17:41 +0800166 * @return this
167 */
Carmelo Cascone87892e22017-11-13 16:01:29 -0800168 public Builder matchExact(PiMatchFieldId fieldId, int value) {
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400169 fieldMatchMapBuilder.put(fieldId, new PiExactFieldMatch(fieldId, copyFrom(value)));
Frank Wangdf383212017-06-23 09:17:41 +0800170 return this;
171 }
172
173 /**
174 * Adds an exact field match for the given fieldId and value.
175 *
176 * @param fieldId protocol-independent header field Id
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400177 * @param value exact match value
Frank Wangdf383212017-06-23 09:17:41 +0800178 * @return this
179 */
Carmelo Cascone87892e22017-11-13 16:01:29 -0800180 public Builder matchExact(PiMatchFieldId fieldId, long value) {
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400181 fieldMatchMapBuilder.put(fieldId, new PiExactFieldMatch(fieldId, copyFrom(value)));
Frank Wangdf383212017-06-23 09:17:41 +0800182 return this;
183 }
184
185 /**
186 * Adds an exact field match for the given fieldId and value.
187 *
188 * @param fieldId protocol-independent header field Id
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400189 * @param value exact match value
Frank Wangdf383212017-06-23 09:17:41 +0800190 * @return this
191 */
Carmelo Cascone87892e22017-11-13 16:01:29 -0800192 public Builder matchExact(PiMatchFieldId fieldId, byte[] value) {
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400193 fieldMatchMapBuilder.put(fieldId, new PiExactFieldMatch(fieldId, copyFrom(value)));
Frank Wangdf383212017-06-23 09:17:41 +0800194 return this;
195 }
196
197 /**
Daniele Moro7aa13e62021-02-23 15:28:07 +0100198 * Adds an exact field match for the given fieldId and value.
199 *
200 * @param fieldId protocol-independent header field Id
201 * @param value exact match value
202 * @return this
203 */
204 public Builder matchExact(PiMatchFieldId fieldId, String value) {
205 fieldMatchMapBuilder.put(fieldId, new PiExactFieldMatch(fieldId, copyFrom(value)));
206 return this;
207 }
208
209 /**
Frank Wangdf383212017-06-23 09:17:41 +0800210 * Adds a ternary field match for the given fieldId, value and mask.
211 *
212 * @param fieldId protocol-independent header field Id
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400213 * @param value ternary match value
214 * @param mask ternary match mask
Frank Wangdf383212017-06-23 09:17:41 +0800215 * @return this
216 */
Carmelo Cascone87892e22017-11-13 16:01:29 -0800217 public Builder matchTernary(PiMatchFieldId fieldId, short value, short mask) {
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400218 fieldMatchMapBuilder.put(fieldId, new PiTernaryFieldMatch(fieldId, copyFrom(value), copyFrom(mask)));
Frank Wangdf383212017-06-23 09:17:41 +0800219 return this;
220 }
221
222 /**
223 * Adds a ternary field match for the given fieldId, value and mask.
224 *
225 * @param fieldId protocol-independent header field Id
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400226 * @param value ternary match value
227 * @param mask ternary match mask
Frank Wangdf383212017-06-23 09:17:41 +0800228 * @return this
229 */
Carmelo Cascone87892e22017-11-13 16:01:29 -0800230 public Builder matchTernary(PiMatchFieldId fieldId, int value, int mask) {
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400231 fieldMatchMapBuilder.put(fieldId, new PiTernaryFieldMatch(fieldId, copyFrom(value), copyFrom(mask)));
Frank Wangdf383212017-06-23 09:17:41 +0800232 return this;
233 }
234
235 /**
236 * Adds a ternary field match for the given fieldId, value and mask.
237 *
238 * @param fieldId protocol-independent header field Id
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400239 * @param value ternary match value
240 * @param mask ternary match mask
Frank Wangdf383212017-06-23 09:17:41 +0800241 * @return this
242 */
Carmelo Cascone87892e22017-11-13 16:01:29 -0800243 public Builder matchTernary(PiMatchFieldId fieldId, long value, long mask) {
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400244 fieldMatchMapBuilder.put(fieldId, new PiTernaryFieldMatch(fieldId, copyFrom(value), copyFrom(mask)));
Frank Wangdf383212017-06-23 09:17:41 +0800245 return this;
246 }
247
248 /**
249 * Adds a ternary field match for the given fieldId, value and mask.
250 *
251 * @param fieldId protocol-independent header field Id
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400252 * @param value ternary match value
253 * @param mask ternary match mask
Frank Wangdf383212017-06-23 09:17:41 +0800254 * @return this
255 */
Carmelo Cascone87892e22017-11-13 16:01:29 -0800256 public Builder matchTernary(PiMatchFieldId fieldId, byte[] value, byte[] mask) {
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400257 fieldMatchMapBuilder.put(fieldId, new PiTernaryFieldMatch(fieldId, copyFrom(value), copyFrom(mask)));
Frank Wangdf383212017-06-23 09:17:41 +0800258 return this;
259 }
260
261 /**
262 * Adds a longest-prefix field match for the given fieldId, value and prefix length.
263 *
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400264 * @param fieldId protocol-independent header field Id
265 * @param value lpm match value
Frank Wangdf383212017-06-23 09:17:41 +0800266 * @param prefixLength lpm match prefix length
267 * @return this
268 */
Carmelo Cascone87892e22017-11-13 16:01:29 -0800269 public Builder matchLpm(PiMatchFieldId fieldId, short value, int prefixLength) {
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400270 fieldMatchMapBuilder.put(fieldId, new PiLpmFieldMatch(fieldId, copyFrom(value), prefixLength));
Frank Wangdf383212017-06-23 09:17:41 +0800271 return this;
272 }
273
274 /**
275 * Adds a longest-prefix field match for the given fieldId, value and prefix length.
276 *
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400277 * @param fieldId protocol-independent header field Id
278 * @param value lpm match value
Frank Wangdf383212017-06-23 09:17:41 +0800279 * @param prefixLength lpm match prefix length
280 * @return this
281 */
Carmelo Cascone87892e22017-11-13 16:01:29 -0800282 public Builder matchLpm(PiMatchFieldId fieldId, int value, int prefixLength) {
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400283 fieldMatchMapBuilder.put(fieldId, new PiLpmFieldMatch(fieldId, copyFrom(value), prefixLength));
Frank Wangdf383212017-06-23 09:17:41 +0800284 return this;
285 }
286
287 /**
288 * Adds a longest-prefix field match for the given fieldId, value and prefix length.
289 *
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400290 * @param fieldId protocol-independent header field Id
291 * @param value lpm match value
Frank Wangdf383212017-06-23 09:17:41 +0800292 * @param prefixLength lpm match prefix length
293 * @return this
294 */
Carmelo Cascone87892e22017-11-13 16:01:29 -0800295 public Builder matchLpm(PiMatchFieldId fieldId, long value, int prefixLength) {
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400296 fieldMatchMapBuilder.put(fieldId, new PiLpmFieldMatch(fieldId, copyFrom(value), prefixLength));
Frank Wangdf383212017-06-23 09:17:41 +0800297 return this;
298 }
299
300 /**
301 * Adds a longest-prefix field match for the given fieldId, value and prefix length.
302 *
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400303 * @param fieldId protocol-independent header field Id
304 * @param value lpm match value
Frank Wangdf383212017-06-23 09:17:41 +0800305 * @param prefixLength lpm match prefix length
306 * @return this
307 */
Carmelo Cascone87892e22017-11-13 16:01:29 -0800308 public Builder matchLpm(PiMatchFieldId fieldId, byte[] value, int prefixLength) {
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400309 fieldMatchMapBuilder.put(fieldId, new PiLpmFieldMatch(fieldId, copyFrom(value), prefixLength));
Frank Wangdf383212017-06-23 09:17:41 +0800310 return this;
311 }
312
313 /**
Frank Wangdf383212017-06-23 09:17:41 +0800314 * Adds a range field match for the given fieldId, low and high.
315 *
316 * @param fieldId protocol-independent header field Id
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400317 * @param low range match low value
318 * @param high range match high value
Frank Wangdf383212017-06-23 09:17:41 +0800319 * @return this
320 */
Carmelo Cascone87892e22017-11-13 16:01:29 -0800321 public Builder matchRange(PiMatchFieldId fieldId, short low, short high) {
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400322 fieldMatchMapBuilder.put(fieldId, new PiRangeFieldMatch(fieldId, copyFrom(low), copyFrom(high)));
Frank Wangdf383212017-06-23 09:17:41 +0800323 return this;
324 }
325
326 /**
327 * Adds a range field match for the given fieldId, low and high.
328 *
329 * @param fieldId protocol-independent header field Id
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400330 * @param low range match low value
331 * @param high range match high value
Frank Wangdf383212017-06-23 09:17:41 +0800332 * @return this
333 */
Carmelo Cascone87892e22017-11-13 16:01:29 -0800334 public Builder matchRange(PiMatchFieldId fieldId, int low, int high) {
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400335 fieldMatchMapBuilder.put(fieldId, new PiRangeFieldMatch(fieldId, copyFrom(low), copyFrom(high)));
Frank Wangdf383212017-06-23 09:17:41 +0800336 return this;
337 }
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400338
Frank Wangdf383212017-06-23 09:17:41 +0800339 /**
340 * Adds a range field match for the given fieldId, low and high.
341 *
342 * @param fieldId protocol-independent header field Id
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400343 * @param low range match low value
344 * @param high range match high value
Frank Wangdf383212017-06-23 09:17:41 +0800345 * @return this
346 */
Carmelo Cascone87892e22017-11-13 16:01:29 -0800347 public Builder matchRange(PiMatchFieldId fieldId, long low, long high) {
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400348 fieldMatchMapBuilder.put(fieldId, new PiRangeFieldMatch(fieldId, copyFrom(low), copyFrom(high)));
Frank Wangdf383212017-06-23 09:17:41 +0800349 return this;
350 }
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400351
Frank Wangdf383212017-06-23 09:17:41 +0800352 /**
353 * Adds a range field match for the given fieldId, low and high.
354 *
355 * @param fieldId protocol-independent header field Id
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400356 * @param low range match low value
357 * @param high range match high value
Frank Wangdf383212017-06-23 09:17:41 +0800358 * @return this
359 */
Carmelo Cascone87892e22017-11-13 16:01:29 -0800360 public Builder matchRange(PiMatchFieldId fieldId, byte[] low, byte[] high) {
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400361 fieldMatchMapBuilder.put(fieldId, new PiRangeFieldMatch(fieldId, copyFrom(low), copyFrom(high)));
Frank Wangdf383212017-06-23 09:17:41 +0800362 return this;
363 }
364
365 /**
Daniele Moroc6f2f7f2020-12-18 10:55:57 +0100366 * Adds an optional field match for the given fieldId and value.
367 *
368 * @param fieldId protocol-independent header field Id
369 * @param value optional match value
370 * @return this
371 */
372 public Builder matchOptional(PiMatchFieldId fieldId, short value) {
373 fieldMatchMapBuilder.put(fieldId, new PiOptionalFieldMatch(fieldId, copyFrom(value)));
374 return this;
375 }
376
377 /**
378 * Adds an optional field match for the given fieldId and value.
379 *
380 * @param fieldId protocol-independent header field Id
381 * @param value optional match value
382 * @return this
383 */
384 public Builder matchOptional(PiMatchFieldId fieldId, int value) {
385 fieldMatchMapBuilder.put(fieldId, new PiOptionalFieldMatch(fieldId, copyFrom(value)));
386 return this;
387 }
388
389 /**
390 * Adds an optional field match for the given fieldId and value.
391 *
392 * @param fieldId protocol-independent header field Id
393 * @param value optional match value
394 * @return this
395 */
396 public Builder matchOptional(PiMatchFieldId fieldId, long value) {
397 fieldMatchMapBuilder.put(fieldId, new PiOptionalFieldMatch(fieldId, copyFrom(value)));
398 return this;
399 }
400
401 /**
402 * Adds an optional field match for the given fieldId and value.
403 *
404 * @param fieldId protocol-independent header field Id
405 * @param value optional match value
406 * @return this
407 */
408 public Builder matchOptional(PiMatchFieldId fieldId, byte[] value) {
409 fieldMatchMapBuilder.put(fieldId, new PiOptionalFieldMatch(fieldId, copyFrom(value)));
410 return this;
411 }
412
413 /**
Daniele Moro7aa13e62021-02-23 15:28:07 +0100414 * Adds an optional field match for the given fieldId and value.
415 *
416 * @param fieldId protocol-independent header field Id
417 * @param value optional match value
418 * @return this
419 */
420 public Builder matchOptional(PiMatchFieldId fieldId, String value) {
421 fieldMatchMapBuilder.put(fieldId, new PiOptionalFieldMatch(fieldId, copyFrom(value)));
422 return this;
423 }
424
425 /**
Frank Wangdf383212017-06-23 09:17:41 +0800426 * Builds a PiCriterion.
427 *
428 * @return PiCriterion
429 */
Carmelo Cascone770507f2017-09-14 20:58:04 +0200430 public PiCriterion build() {
Carmelo Cascone87892e22017-11-13 16:01:29 -0800431 ImmutableMap<PiMatchFieldId, PiFieldMatch> fieldMatchMap = fieldMatchMapBuilder.build();
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400432 checkArgument(fieldMatchMap.size() > 0, "Cannot build PI criterion with 0 field matches");
433 return new PiCriterion(fieldMatchMap);
Frank Wangdf383212017-06-23 09:17:41 +0800434 }
435 }
Carmelo Cascone87892e22017-11-13 16:01:29 -0800436}