blob: a346927fd721e76e5958dae8396631da45b2e57b [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 /**
111 * PiCriterion Builder.
112 */
113 @Beta
114 public static final class Builder {
115
Carmelo Cascone22619172017-07-13 16:08:17 -0400116 // Use map to guarantee that there's only one field match per field id.
Carmelo Cascone87892e22017-11-13 16:01:29 -0800117 private final ImmutableMap.Builder<PiMatchFieldId, PiFieldMatch> fieldMatchMapBuilder = ImmutableMap.builder();
Frank Wangdf383212017-06-23 09:17:41 +0800118
119 private Builder() {
120 // ban constructor.
121 }
122
123 /**
124 * Adds an exact field match for the given fieldId and value.
125 *
126 * @param fieldId protocol-independent header field Id
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400127 * @param value exact match value
Frank Wangdf383212017-06-23 09:17:41 +0800128 * @return this
129 */
Carmelo Cascone87892e22017-11-13 16:01:29 -0800130 public Builder matchExact(PiMatchFieldId fieldId, short value) {
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400131 fieldMatchMapBuilder.put(fieldId, new PiExactFieldMatch(fieldId, copyFrom(value)));
Frank Wangdf383212017-06-23 09:17:41 +0800132 return this;
133 }
134
135 /**
136 * Adds an exact field match for the given fieldId and value.
137 *
138 * @param fieldId protocol-independent header field Id
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400139 * @param value exact match value
Frank Wangdf383212017-06-23 09:17:41 +0800140 * @return this
141 */
Carmelo Cascone87892e22017-11-13 16:01:29 -0800142 public Builder matchExact(PiMatchFieldId fieldId, int value) {
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400143 fieldMatchMapBuilder.put(fieldId, new PiExactFieldMatch(fieldId, copyFrom(value)));
Frank Wangdf383212017-06-23 09:17:41 +0800144 return this;
145 }
146
147 /**
148 * Adds an exact field match for the given fieldId and value.
149 *
150 * @param fieldId protocol-independent header field Id
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400151 * @param value exact match value
Frank Wangdf383212017-06-23 09:17:41 +0800152 * @return this
153 */
Carmelo Cascone87892e22017-11-13 16:01:29 -0800154 public Builder matchExact(PiMatchFieldId fieldId, long value) {
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400155 fieldMatchMapBuilder.put(fieldId, new PiExactFieldMatch(fieldId, copyFrom(value)));
Frank Wangdf383212017-06-23 09:17:41 +0800156 return this;
157 }
158
159 /**
160 * Adds an exact field match for the given fieldId and value.
161 *
162 * @param fieldId protocol-independent header field Id
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400163 * @param value exact match value
Frank Wangdf383212017-06-23 09:17:41 +0800164 * @return this
165 */
Carmelo Cascone87892e22017-11-13 16:01:29 -0800166 public Builder matchExact(PiMatchFieldId fieldId, byte[] value) {
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400167 fieldMatchMapBuilder.put(fieldId, new PiExactFieldMatch(fieldId, copyFrom(value)));
Frank Wangdf383212017-06-23 09:17:41 +0800168 return this;
169 }
170
171 /**
172 * Adds a ternary field match for the given fieldId, value and mask.
173 *
174 * @param fieldId protocol-independent header field Id
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400175 * @param value ternary match value
176 * @param mask ternary match mask
Frank Wangdf383212017-06-23 09:17:41 +0800177 * @return this
178 */
Carmelo Cascone87892e22017-11-13 16:01:29 -0800179 public Builder matchTernary(PiMatchFieldId fieldId, short value, short mask) {
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400180 fieldMatchMapBuilder.put(fieldId, new PiTernaryFieldMatch(fieldId, copyFrom(value), copyFrom(mask)));
Frank Wangdf383212017-06-23 09:17:41 +0800181 return this;
182 }
183
184 /**
185 * Adds a ternary field match for the given fieldId, value and mask.
186 *
187 * @param fieldId protocol-independent header field Id
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400188 * @param value ternary match value
189 * @param mask ternary match mask
Frank Wangdf383212017-06-23 09:17:41 +0800190 * @return this
191 */
Carmelo Cascone87892e22017-11-13 16:01:29 -0800192 public Builder matchTernary(PiMatchFieldId fieldId, int value, int mask) {
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400193 fieldMatchMapBuilder.put(fieldId, new PiTernaryFieldMatch(fieldId, copyFrom(value), copyFrom(mask)));
Frank Wangdf383212017-06-23 09:17:41 +0800194 return this;
195 }
196
197 /**
198 * Adds a ternary field match for the given fieldId, value and mask.
199 *
200 * @param fieldId protocol-independent header field Id
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400201 * @param value ternary match value
202 * @param mask ternary match mask
Frank Wangdf383212017-06-23 09:17:41 +0800203 * @return this
204 */
Carmelo Cascone87892e22017-11-13 16:01:29 -0800205 public Builder matchTernary(PiMatchFieldId fieldId, long value, long mask) {
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400206 fieldMatchMapBuilder.put(fieldId, new PiTernaryFieldMatch(fieldId, copyFrom(value), copyFrom(mask)));
Frank Wangdf383212017-06-23 09:17:41 +0800207 return this;
208 }
209
210 /**
211 * Adds a ternary field match for the given fieldId, value and mask.
212 *
213 * @param fieldId protocol-independent header field Id
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400214 * @param value ternary match value
215 * @param mask ternary match mask
Frank Wangdf383212017-06-23 09:17:41 +0800216 * @return this
217 */
Carmelo Cascone87892e22017-11-13 16:01:29 -0800218 public Builder matchTernary(PiMatchFieldId fieldId, byte[] value, byte[] mask) {
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400219 fieldMatchMapBuilder.put(fieldId, new PiTernaryFieldMatch(fieldId, copyFrom(value), copyFrom(mask)));
Frank Wangdf383212017-06-23 09:17:41 +0800220 return this;
221 }
222
223 /**
224 * Adds a longest-prefix field match for the given fieldId, value and prefix length.
225 *
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400226 * @param fieldId protocol-independent header field Id
227 * @param value lpm match value
Frank Wangdf383212017-06-23 09:17:41 +0800228 * @param prefixLength lpm match prefix length
229 * @return this
230 */
Carmelo Cascone87892e22017-11-13 16:01:29 -0800231 public Builder matchLpm(PiMatchFieldId fieldId, short value, int prefixLength) {
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400232 fieldMatchMapBuilder.put(fieldId, new PiLpmFieldMatch(fieldId, copyFrom(value), prefixLength));
Frank Wangdf383212017-06-23 09:17:41 +0800233 return this;
234 }
235
236 /**
237 * Adds a longest-prefix field match for the given fieldId, value and prefix length.
238 *
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400239 * @param fieldId protocol-independent header field Id
240 * @param value lpm match value
Frank Wangdf383212017-06-23 09:17:41 +0800241 * @param prefixLength lpm match prefix length
242 * @return this
243 */
Carmelo Cascone87892e22017-11-13 16:01:29 -0800244 public Builder matchLpm(PiMatchFieldId fieldId, int value, int prefixLength) {
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400245 fieldMatchMapBuilder.put(fieldId, new PiLpmFieldMatch(fieldId, copyFrom(value), prefixLength));
Frank Wangdf383212017-06-23 09:17:41 +0800246 return this;
247 }
248
249 /**
250 * Adds a longest-prefix field match for the given fieldId, value and prefix length.
251 *
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400252 * @param fieldId protocol-independent header field Id
253 * @param value lpm match value
Frank Wangdf383212017-06-23 09:17:41 +0800254 * @param prefixLength lpm match prefix length
255 * @return this
256 */
Carmelo Cascone87892e22017-11-13 16:01:29 -0800257 public Builder matchLpm(PiMatchFieldId fieldId, long value, int prefixLength) {
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400258 fieldMatchMapBuilder.put(fieldId, new PiLpmFieldMatch(fieldId, copyFrom(value), prefixLength));
Frank Wangdf383212017-06-23 09:17:41 +0800259 return this;
260 }
261
262 /**
263 * Adds a longest-prefix field match for the given fieldId, value and prefix length.
264 *
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400265 * @param fieldId protocol-independent header field Id
266 * @param value lpm match value
Frank Wangdf383212017-06-23 09:17:41 +0800267 * @param prefixLength lpm match prefix length
268 * @return this
269 */
Carmelo Cascone87892e22017-11-13 16:01:29 -0800270 public Builder matchLpm(PiMatchFieldId fieldId, byte[] value, int prefixLength) {
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400271 fieldMatchMapBuilder.put(fieldId, new PiLpmFieldMatch(fieldId, copyFrom(value), prefixLength));
Frank Wangdf383212017-06-23 09:17:41 +0800272 return this;
273 }
274
275 /**
Frank Wangdf383212017-06-23 09:17:41 +0800276 * Adds a range field match for the given fieldId, low and high.
277 *
278 * @param fieldId protocol-independent header field Id
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400279 * @param low range match low value
280 * @param high range match high value
Frank Wangdf383212017-06-23 09:17:41 +0800281 * @return this
282 */
Carmelo Cascone87892e22017-11-13 16:01:29 -0800283 public Builder matchRange(PiMatchFieldId fieldId, short low, short high) {
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400284 fieldMatchMapBuilder.put(fieldId, new PiRangeFieldMatch(fieldId, copyFrom(low), copyFrom(high)));
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, int low, int 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 }
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400300
Frank Wangdf383212017-06-23 09:17:41 +0800301 /**
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, long low, long 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, byte[] low, byte[] 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 }
326
327 /**
328 * Builds a PiCriterion.
329 *
330 * @return PiCriterion
331 */
Carmelo Cascone770507f2017-09-14 20:58:04 +0200332 public PiCriterion build() {
Carmelo Cascone87892e22017-11-13 16:01:29 -0800333 ImmutableMap<PiMatchFieldId, PiFieldMatch> fieldMatchMap = fieldMatchMapBuilder.build();
Carmelo Cascone32a01b22017-07-18 10:51:07 -0400334 checkArgument(fieldMatchMap.size() > 0, "Cannot build PI criterion with 0 field matches");
335 return new PiCriterion(fieldMatchMap);
Frank Wangdf383212017-06-23 09:17:41 +0800336 }
337 }
Carmelo Cascone87892e22017-11-13 16:01:29 -0800338}