blob: 17d1270cd917703f009c34d5f596609638ec2626 [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;
Carmelo Cascone1022a4e2017-05-25 00:16:18 -040028
29import java.util.Collection;
Carmelo Cascone32a01b22017-07-18 10:51:07 -040030import java.util.Optional;
Carmelo Cascone1022a4e2017-05-25 00:16:18 -040031import java.util.StringJoiner;
32
Frank Wangdf383212017-06-23 09:17:41 +080033import static com.google.common.base.Preconditions.checkArgument;
34import static org.onlab.util.ImmutableByteSequence.copyFrom;
35
Carmelo Cascone1022a4e2017-05-25 00:16:18 -040036/**
Carmelo Cascone22619172017-07-13 16:08:17 -040037 * Protocol-independent criterion.
Carmelo Cascone1022a4e2017-05-25 00:16:18 -040038 */
39@Beta
40public final class PiCriterion implements Criterion {
41
Carmelo Cascone87892e22017-11-13 16:01:29 -080042 private final ImmutableMap<PiMatchFieldId, PiFieldMatch> fieldMatchMap;
Carmelo Cascone1022a4e2017-05-25 00:16:18 -040043
44 /**
45 * Creates a new protocol-independent criterion for the given match fields.
46 *
Carmelo Cascone32a01b22017-07-18 10:51:07 -040047 * @param fieldMatchMap field match map
Carmelo Cascone1022a4e2017-05-25 00:16:18 -040048 */
Carmelo Cascone87892e22017-11-13 16:01:29 -080049 private PiCriterion(ImmutableMap<PiMatchFieldId, PiFieldMatch> fieldMatchMap) {
Carmelo Cascone32a01b22017-07-18 10:51:07 -040050 this.fieldMatchMap = fieldMatchMap;
Carmelo Cascone1022a4e2017-05-25 00:16:18 -040051 }
52
53 /**
Carmelo Cascone32a01b22017-07-18 10:51:07 -040054 * Returns all protocol-independent field matches defined by this criterion.
Carmelo Cascone1022a4e2017-05-25 00:16:18 -040055 *
Carmelo Cascone32a01b22017-07-18 10:51:07 -040056 * @return collection of match parameters
Carmelo Cascone1022a4e2017-05-25 00:16:18 -040057 */
58 public Collection<PiFieldMatch> fieldMatches() {
Carmelo Cascone32a01b22017-07-18 10:51:07 -040059 return fieldMatchMap.values();
60 }
61
62 /**
63 * If present, returns the field match associated with the given header field identifier.
64 *
65 * @param fieldId field identifier
66 * @return optional field match
67 */
Carmelo Cascone87892e22017-11-13 16:01:29 -080068 public Optional<PiFieldMatch> fieldMatch(PiMatchFieldId fieldId) {
Carmelo Cascone32a01b22017-07-18 10:51:07 -040069 return Optional.ofNullable(fieldMatchMap.get(fieldId));
Carmelo Cascone1022a4e2017-05-25 00:16:18 -040070 }
71
72 @Override
73 public Type type() {
74 return Type.PROTOCOL_INDEPENDENT;
75 }
76
77 @Override
78 public boolean equals(Object o) {
79 if (this == o) {
80 return true;
81 }
82 if (o == null || getClass() != o.getClass()) {
83 return false;
84 }
85 PiCriterion that = (PiCriterion) o;
Carmelo Cascone32a01b22017-07-18 10:51:07 -040086 return Objects.equal(fieldMatchMap, that.fieldMatchMap);
Carmelo Cascone1022a4e2017-05-25 00:16:18 -040087 }
88
89 @Override
90 public int hashCode() {
Carmelo Cascone32a01b22017-07-18 10:51:07 -040091 return Objects.hashCode(fieldMatchMap);
Carmelo Cascone1022a4e2017-05-25 00:16:18 -040092 }
93
94 @Override
95 public String toString() {
Carmelo Cascone0316b962018-04-11 17:39:07 -070096 StringJoiner stringParams = new StringJoiner(", ");
Carmelo Cascone32a01b22017-07-18 10:51:07 -040097 fieldMatchMap.forEach((key, value) -> stringParams.add(value.toString()));
Carmelo Cascone1022a4e2017-05-25 00:16:18 -040098 return stringParams.toString();
99 }
Frank Wangdf383212017-06-23 09:17:41 +0800100
101 /**
102 * Returns the PiCriterion builder.
103 *
104 * @return PiCriterion builder
105 */
106 public static Builder builder() {
107 return new Builder();
108 }
109
110 /**
pierventre26eb65d2020-10-08 17:21:49 +0200111 * Returns the PiCriterion builder initialized by the given PiCriterion.
112 *
113 * @param piCriterion the input PiCriterion
114 * @return PiCriterion builder
115 */
116 public static Builder builder(PiCriterion piCriterion) {
117 return new Builder(piCriterion);
118 }
119
120 /**
Frank Wangdf383212017-06-23 09:17:41 +0800121 * PiCriterion Builder.
122 */
123 @Beta
124 public static final class Builder {
125
Carmelo Cascone22619172017-07-13 16:08:17 -0400126 // Use map to guarantee that there's only one field match per field id.
Carmelo Cascone87892e22017-11-13 16:01:29 -0800127 private final ImmutableMap.Builder<PiMatchFieldId, PiFieldMatch> fieldMatchMapBuilder = ImmutableMap.builder();
Frank Wangdf383212017-06-23 09:17:41 +0800128
129 private Builder() {
130 // ban constructor.
131 }
132
pierventre26eb65d2020-10-08 17:21:49 +0200133 private Builder(PiCriterion piCriterion) {
134 piCriterion.fieldMatchMap.forEach(((piMatchFieldId, piFieldMatch) -> add(piFieldMatch)));
135 }
136
137 /**
138 * Adds a match field to the builder.
139 *
140 * @param field the field value
141 * @return this
142 */
143 public Builder add(PiFieldMatch field) {
144 fieldMatchMapBuilder.put(field.fieldId(), field);
145 return this;
146 }
147
Frank Wangdf383212017-06-23 09:17:41 +0800148 /**
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, short 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, int 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 an exact field match for the given fieldId and value.
174 *
175 * @param fieldId protocol-independent header field Id
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400176 * @param value exact match value
Frank Wangdf383212017-06-23 09:17:41 +0800177 * @return this
178 */
Carmelo Cascone87892e22017-11-13 16:01:29 -0800179 public Builder matchExact(PiMatchFieldId fieldId, long value) {
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400180 fieldMatchMapBuilder.put(fieldId, new PiExactFieldMatch(fieldId, copyFrom(value)));
Frank Wangdf383212017-06-23 09:17:41 +0800181 return this;
182 }
183
184 /**
185 * Adds an exact field match for the given fieldId and value.
186 *
187 * @param fieldId protocol-independent header field Id
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400188 * @param value exact match value
Frank Wangdf383212017-06-23 09:17:41 +0800189 * @return this
190 */
Carmelo Cascone87892e22017-11-13 16:01:29 -0800191 public Builder matchExact(PiMatchFieldId fieldId, byte[] value) {
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400192 fieldMatchMapBuilder.put(fieldId, new PiExactFieldMatch(fieldId, copyFrom(value)));
Frank Wangdf383212017-06-23 09:17:41 +0800193 return this;
194 }
195
196 /**
197 * Adds a ternary field match for the given fieldId, value and mask.
198 *
199 * @param fieldId protocol-independent header field Id
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400200 * @param value ternary match value
201 * @param mask ternary match mask
Frank Wangdf383212017-06-23 09:17:41 +0800202 * @return this
203 */
Carmelo Cascone87892e22017-11-13 16:01:29 -0800204 public Builder matchTernary(PiMatchFieldId fieldId, short value, short mask) {
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400205 fieldMatchMapBuilder.put(fieldId, new PiTernaryFieldMatch(fieldId, copyFrom(value), copyFrom(mask)));
Frank Wangdf383212017-06-23 09:17:41 +0800206 return this;
207 }
208
209 /**
210 * 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, int value, int 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, long value, long 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, byte[] value, byte[] 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 longest-prefix field match for the given fieldId, value and prefix length.
250 *
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400251 * @param fieldId protocol-independent header field Id
252 * @param value lpm match value
Frank Wangdf383212017-06-23 09:17:41 +0800253 * @param prefixLength lpm match prefix length
254 * @return this
255 */
Carmelo Cascone87892e22017-11-13 16:01:29 -0800256 public Builder matchLpm(PiMatchFieldId fieldId, short value, int prefixLength) {
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400257 fieldMatchMapBuilder.put(fieldId, new PiLpmFieldMatch(fieldId, copyFrom(value), prefixLength));
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, int 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, long 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, byte[] 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 /**
Frank Wangdf383212017-06-23 09:17:41 +0800301 * Adds a range field match for the given fieldId, low and high.
302 *
303 * @param fieldId protocol-independent header field Id
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400304 * @param low range match low value
305 * @param high range match high value
Frank Wangdf383212017-06-23 09:17:41 +0800306 * @return this
307 */
Carmelo Cascone87892e22017-11-13 16:01:29 -0800308 public Builder matchRange(PiMatchFieldId fieldId, short low, short high) {
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400309 fieldMatchMapBuilder.put(fieldId, new PiRangeFieldMatch(fieldId, copyFrom(low), copyFrom(high)));
Frank Wangdf383212017-06-23 09:17:41 +0800310 return this;
311 }
312
313 /**
314 * 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, int low, int 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 }
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400325
Frank Wangdf383212017-06-23 09:17:41 +0800326 /**
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, long low, long 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, byte[] low, byte[] 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 }
351
352 /**
353 * Builds a PiCriterion.
354 *
355 * @return PiCriterion
356 */
Carmelo Cascone770507f2017-09-14 20:58:04 +0200357 public PiCriterion build() {
Carmelo Cascone87892e22017-11-13 16:01:29 -0800358 ImmutableMap<PiMatchFieldId, PiFieldMatch> fieldMatchMap = fieldMatchMapBuilder.build();
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400359 checkArgument(fieldMatchMap.size() > 0, "Cannot build PI criterion with 0 field matches");
360 return new PiCriterion(fieldMatchMap);
Frank Wangdf383212017-06-23 09:17:41 +0800361 }
362 }
Carmelo Cascone87892e22017-11-13 16:01:29 -0800363}