blob: 2a934fd5ed21d92e2361723dfae769f3edc16370 [file] [log] [blame]
Konstantinos Kanonakis0a9031d2016-09-22 11:35:11 -05001/*
2 * Copyright 2016-present Open Networking Laboratory
3 *
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 */
16package org.onosproject.net.behaviour;
17
18import com.google.common.annotations.Beta;
19import com.google.common.base.MoreObjects;
20import org.onlab.packet.DscpClass;
21import org.onlab.util.Bandwidth;
22import org.onosproject.net.meter.Band;
23import org.onosproject.net.meter.Meter;
24import static org.onosproject.net.behaviour.BandwidthProfileAction.Action;
25
26import java.util.Iterator;
27import java.util.Objects;
28
29import static com.google.common.base.Preconditions.checkArgument;
30import static com.google.common.base.Preconditions.checkNotNull;
31
32/**
33 * Implementation of a generic bandwidth profile (marker/policer).
34 */
35@Beta
36public final class BandwidthProfile {
37
38 /**
39 * Denotes the type of the bandwidth profile.
40 */
41 enum Type {
42 /**
43 * Corresponds to a Single Rate Two Color Marker/Policer.
44 */
45 sr2CM,
46
47 /**
48 * Corresponds to a Single Rate Three Color Marker/Policer.
49 * (IETF RFC 2697)
50 */
51 srTCM,
52
53 /**
54 * Corresponds to a Two Rate Three Color Marker/Policer.
55 * (IETF RFC 2698)
56 */
57 trTCM
58 }
59
60 private final String name;
61 private final Bandwidth cir;
62 private final Bandwidth pir;
63 private final Integer cbs;
64 private final Integer pbs;
65 private final Integer ebs;
66 private final BandwidthProfileAction greenAction;
67 private final BandwidthProfileAction yellowAction;
68 private final BandwidthProfileAction redAction;
69 private final boolean colorAware;
70
71 /**
72 * BandwidthProfile constructor.
73 *
74 * @param name the profile name
75 * @param cir the committed information rate (CIR)
76 * @param cbs the committed burst size (CBS) measured in bytes
77 * @param pir the peak information rate (PIR)
78 * @param pbs the peak burst size (PBS) measured in bytes
79 * @param greenAction the action to be taken for traffic that conforms
80 * to the CIR/CBS
81 * @param yellowAction srTCM: the action to be taken for traffic that
82 * conforms to the EBS but not to the CIR/CBS
83 * trTCM: the action to be taken for traffic that
84 * conforms to the PIR/PBS but not to the CIR/CBS
85 * @param redAction sr2CM: the action to be taken for traffic that
86 * does not conform to the CIR/CBS
87 * srTCM: the action to be taken for traffic that
88 * does not conform to the EBS
89 * trTCM: the action to be taken for traffic that
90 * does not conform to the PIR/PBS
91 * @param colorAware indicates whether the profile considers incoming
92 * traffic as already colored
93 */
94 private BandwidthProfile(String name,
95 Bandwidth cir, Bandwidth pir,
96 Integer cbs, Integer pbs, Integer ebs,
97 BandwidthProfileAction greenAction,
98 BandwidthProfileAction yellowAction,
99 BandwidthProfileAction redAction,
100 boolean colorAware) {
101 this.name = name;
102 this.cir = cir;
103 this.pir = pir;
104 this.cbs = cbs;
105 this.pbs = pbs;
106 this.ebs = ebs;
107 this.greenAction = greenAction;
108 this.yellowAction = yellowAction;
109 this.redAction = redAction;
110 this.colorAware = colorAware;
111 }
112
113 /**
114 * Obtains the name of this bandwidth profile.
115 *
116 * @return the bandwidth profile name
117 */
118 public String name() {
119 return name;
120 }
121
122 /**
123 * Obtains the committed information rate (CIR) of this bandwidth profile.
124 *
125 * @return the CIR of the bandwidth profile
126 */
127 public Bandwidth cir() {
128 return cir;
129 }
130
131 /**
132 * Obtains the peak information rate (PIR) of this bandwidth profile.
133 * If this profile does not have a PIR, null is returned.
134 *
135 * @return the PIR of the profile; null if the profile does not have a PIR
136 */
137 public Bandwidth pir() {
138 return pir;
139 }
140
141 /**
142 * Obtains the committed burst size (CBS) of this bandwidth profile.
143 * The CBS is measured in bytes.
144 * If this profile does not have a CBS, null is returned.
145 *
146 * @return the CBS of the profile (bytes);
147 * null if the profile does not have a CBS
148 */
149 public Integer cbs() {
150 return cbs;
151 }
152
153 /**
154 * Obtains the peak burst size (PBS) of this bandwidth profile.
155 * The PBS is measured in bytes.
156 * If this profile does not have a PBS, null is returned.
157 *
158 * @return the PBS of the bandwidth profile (bytes);
159 * null if the profile does not have a PBS
160 */
161 public Integer pbs() {
162 return pbs;
163 }
164
165 /**
166 * Obtains the excess burst size (EBS) of this bandwidth profile.
167 * The EBS is measured in bytes.
168 * If this profile does not have an EBS, null is returned.
169 *
170 * @return the EBS of the bandwidth profile (bytes);
171 * null if the profile does not have an EBS
172 */
173 public Integer ebs() {
174 return ebs;
175 }
176
177 /**
178 * Obtains the action to be taken for traffic marked as green.
179 * Green color marking is applied to traffic that conforms to the CIR/CBS.
180 *
181 * @return the action to be taken for traffic marked as green
182 */
183 public BandwidthProfileAction greenAction() {
184 return greenAction;
185 }
186
187 /**
188 * Obtains the action to be taken for traffic marked as yellow.
189 * Yellow color marking is applied to traffic that does not conform
190 * to the CIR/CBS but conforms to one of:
191 * <ul>
192 * <li>EBS (srTCM type)</li>
193 * <li>PIR/PBS (trTCM type)</li>
194 * </ul>
195 * If this profile does has neither EBS or PIR/PBS, null is returned.
196 *
197 * @return the action to be taken for traffic marked as yellow;
198 * null if neither EBS nor PIR/PBS are defined
199 */
200 public BandwidthProfileAction yellowAction() {
201 return yellowAction;
202 }
203
204 /**
205 * Obtains the action to be taken for traffic marked as red.
206 * Red color marking is applied to traffic that does not conform
207 * to one of the following:
208 * <ul>
209 * <li>CIR/CBS (sr2CM type)</li>
210 * <li>EBS (srTCM type)</li>
211 * <li>PIR/PBS (trTCM type)</li>
212 * </ul>
213 *
214 * @return the action to be taken for traffic marked as red
215 */
216 public BandwidthProfileAction redAction() {
217 return redAction;
218 }
219
220 /**
221 * Obtains the color-aware mode of the bandwidth profile.
222 *
223 * @return true if the bandwidth profile is color-aware; false otherwise
224 */
225 public boolean colorAware() {
226 return colorAware;
227 }
228
229 /**
230 * Obtains the bandwidth profile type depending on the profile parameters.
231 * <ul>
232 * <li>When PIR is defined, the profile corresponds to a
233 * Two Rate Three Color Marker (trTCM)</li>
234 * <li>When EBS is defined, the profile corresponds to a
235 * Single Rate Three Color Marker (srTCM)</li>
236 * <li>When neither PIR nor EBS are defined, the profile corresponds to a
237 * Single Rate Two Color Marker/Policer (sr2CM)</li>
238 * </ul>
239 *
240 * @return the bandwidth profile type
241 */
242 public Type type() {
243 return pir != null ? Type.trTCM :
244 ebs != null ? Type.srTCM : Type.sr2CM;
245 }
246
247 /**
248 * Creates a bandwidth profile based on the parameters of a Meter.
249 * NOTE: The dropPrecedence in the Meter is interpreted as
250 * the DSCP class to set on the packet
251 *
252 * @param meter the Meter to be used for creating the bandwidth profile
253 * @return the bandwidth profile created
254 */
255 public static BandwidthProfile fromMeter(Meter meter) {
256
257 checkNotNull(meter);
258 checkArgument(meter.bands().size() <= 2,
259 "Meter must have no more than two bands.");
260
261 Iterator<Band> bandIterator = meter.bands().iterator();
262 Band bandOne = bandIterator.next();
263 Band bandTwo = bandIterator.hasNext() ? bandIterator.next() : null;
264
265 // Assign values to yellowBand and redBand depending on
266 // the number of bands in the meter.
267 // If only one band exists it will be designated as the redBand.
268 // If two bands exist, the one with the lower rate will be
269 // the yellowBand and the other the redBand.
270 Band yellowBand = (bandTwo == null ? null :
271 bandTwo.rate() > bandOne.rate() ? bandOne : bandTwo);
272 Band redBand = (bandTwo == null ? bandOne :
273 yellowBand == bandOne ? bandTwo : bandOne);
274
275 BandwidthProfile.Builder bandwidthProfileBuilder = new Builder()
276 // Consider the meter id as the bandwidth profile name
277 .name(meter.id().toString())
278 .colorAware(false)
279 // The implicit green action is pass
280 .greenAction(getBuilder(Action.PASS).build());
281
282 if (yellowBand != null) {
283 // Try to add yellow action; CIR/CBS will be obtained from
284 // yellowBand and PIR/PBS from redBand.
285 BandwidthProfileAction yellowAction =
286 getBwProfileActionFromBand(yellowBand);
287 checkNotNull(yellowAction,
288 "Could not obtain yellow action from meter band");
289 bandwidthProfileBuilder
290 .cir(Bandwidth.kBps(yellowBand.rate()))
291 .cbs(yellowBand.burst() == null ? null :
292 yellowBand.burst().intValue())
293 .pir(Bandwidth.kBps(redBand.rate()))
294 .pbs(redBand.burst() == null ? null :
295 redBand.burst().intValue())
296 .yellowAction(yellowAction);
297 } else {
298 // No yellow action to add; CIR/CBS will be obtained from redBand
299 bandwidthProfileBuilder
300 .cir(Bandwidth.kBps(redBand.rate()))
301 .cbs(redBand.burst() == null ? null :
302 redBand.burst().intValue());
303 }
304
305 // Try to add red action in any case
306 BandwidthProfileAction redAction =
307 getBwProfileActionFromBand(redBand);
308 checkNotNull(redAction,
309 "Could not obtain red action from meter band");
310
311 return bandwidthProfileBuilder
312 .redAction(redAction)
313 .build();
314 }
315
316 private static BandwidthProfileAction.Builder getBuilder(Action action) {
317 return BandwidthProfileAction.builder().action(action);
318 }
319
320 private static BandwidthProfileAction getBwProfileActionFromBand(Band band) {
321 checkNotNull(band.type(),
322 "Could not obtain BW profile: Meter band type is null");
323 Action action = null;
324 if (band.type().equals(Band.Type.DROP)) {
325 action = Action.DISCARD;
326 } else if (band.type().equals(Band.Type.REMARK)) {
327 action = Action.REMARK;
328 }
329 checkNotNull(action,
330 "Could not obtain BW profile: Invalid meter band type");
331 BandwidthProfileAction.Builder actionBuilder = getBuilder(action);
332 if (band.type().equals(Band.Type.REMARK)) {
333 checkNotNull(band.dropPrecedence(),
334 "Could not obtain DSCP class from meter band");
335 actionBuilder.dscpClass(DscpClass.fromShort(band.dropPrecedence()));
336 }
337 return actionBuilder.build();
338 }
339
340 /**
341 * Returns a new builder.
342 *
343 * @return new builder
344 */
345 public static Builder builder() {
346 return new Builder();
347 }
348
349 /**
350 * Builder of BandwidthProfile entities.
351 */
352 public static final class Builder {
353
354 private String name;
355 private Bandwidth cir;
356 private Bandwidth pir;
357 private Integer cbs;
358 private Integer pbs;
359 private Integer ebs;
360 private BandwidthProfileAction greenAction;
361 private BandwidthProfileAction yellowAction;
362 private BandwidthProfileAction redAction;
363 private boolean colorAware;
364
365 /**
366 * Sets the name of this bandwidth profile builder.
367 *
368 * @param name the builder name to set
369 * @return this builder instance
370 */
371 public Builder name(String name) {
372 this.name = name;
373 return this;
374 }
375
376 /**
377 * Sets the committed information rate (CIR) of this builder.
378 *
379 * @param cir the builder CIR to set
380 * @return this builder instance
381 */
382 public Builder cir(Bandwidth cir) {
383 this.cir = cir;
384 return this;
385 }
386
387 /**
388 * Sets the peak information rate (PIR) of this builder.
389 *
390 * @param pir the builder PIR to set
391 * @return this builder instance
392 */
393 public Builder pir(Bandwidth pir) {
394 this.pir = pir;
395 return this;
396 }
397
398 /**
399 * Sets the committed burst size (CBS) of this builder.
400 * The CBS is measured in bytes.
401 *
402 * @param cbs the builder CBS to set
403 * @return this builder instance
404 */
405 public Builder cbs(Integer cbs) {
406 this.cbs = cbs;
407 return this;
408 }
409
410 /**
411 * Sets the peak burst size (PBS) of this builder.
412 * The PBS is measured in bytes.
413 *
414 * @param pbs the builder CBS to set
415 * @return this builder instance
416 */
417 public Builder pbs(Integer pbs) {
418 this.pbs = pbs;
419 return this;
420 }
421
422 /**
423 * Sets the excess burst size (EBS) of this builder.
424 * The EBS is measured in bytes.
425 *
426 * @param ebs the builder EBS to set
427 * @return this builder instance
428 */
429 public Builder ebs(Integer ebs) {
430 this.ebs = ebs;
431 return this;
432 }
433
434 /**
435 * Sets the green action of this builder.
436 *
437 * @param greenAction the builder green action to set
438 * @return this builder instance
439 */
440 public Builder greenAction(BandwidthProfileAction greenAction) {
441 this.greenAction = greenAction;
442 return this;
443 }
444
445 /**
446 * Sets the yellow action of this builder.
447 *
448 * @param yellowAction the builder green action to set
449 * @return this builder instance
450 */
451 public Builder yellowAction(BandwidthProfileAction yellowAction) {
452 this.yellowAction = yellowAction;
453 return this;
454 }
455
456 /**
457 * Sets the red action of this builder.
458 *
459 * @param redAction the builder green action to set
460 * @return this builder instance
461 */
462 public Builder redAction(BandwidthProfileAction redAction) {
463 this.redAction = redAction;
464 return this;
465 }
466
467 /**
468 * Sets the color-aware mode of this builder.
469 *
470 * @param colorAware true if profile to be build is color-aware;
471 * false otherwise
472 * @return this builder instance
473 */
474 public Builder colorAware(boolean colorAware) {
475 this.colorAware = colorAware;
476 return this;
477 }
478
479 /**
480 * Builds a new BandwidthProfile instance.
481 * based on this builder's parameters
482 *
483 * @return a new BandwidthProfile instance
484 */
485 public BandwidthProfile build() {
486 checkNotNull(name, "Bandwidth profile must have a name");
487 checkNotNull(cir, "Bandwidth profile must have a CIR");
488 checkNotNull(greenAction,
489 "Bandwidth profile must have a green action");
490 checkNotNull(redAction,
491 "Bandwidth profile must have a red action");
492 checkArgument(pir != null || pbs == null,
493 "Bandwidth profile cannot have PBS without PIR");
494 checkArgument(pir == null || ebs == null,
495 "Bandwidth profile cannot have both PIR and EBS");
496 checkArgument(yellowAction == null && pir == null && ebs == null ||
497 yellowAction != null &&
498 (pir != null ^ ebs != null),
499 "Bandwidth profile must have a yellow action only " +
500 "when either PIR or EBS are defined");
501 return new BandwidthProfile(name,
502 cir, pir, cbs, pbs, ebs,
503 greenAction, yellowAction, redAction,
504 colorAware);
505 }
506 }
507
508 @Override
509 public int hashCode() {
510 return Objects.hash(cir, pir, cbs, pbs, ebs,
511 greenAction, yellowAction, redAction,
512 colorAware);
513 }
514
515 @Override
516 public boolean equals(Object obj) {
517 if (this == obj) {
518 return true;
519 }
520 if (obj instanceof BandwidthProfile) {
521 final BandwidthProfile that = (BandwidthProfile) obj;
522 return this.getClass() == that.getClass() &&
523 Objects.equals(this.cir, that.cir) &&
524 Objects.equals(this.pir, that.pir) &&
525 Objects.equals(this.cbs, that.cbs) &&
526 Objects.equals(this.pbs, that.pbs) &&
527 Objects.equals(this.ebs, that.ebs) &&
528 Objects.equals(this.greenAction, that.greenAction) &&
529 Objects.equals(this.yellowAction, that.yellowAction) &&
530 Objects.equals(this.redAction, that.redAction) &&
531 Objects.equals(this.colorAware, that.colorAware);
532 }
533 return false;
534 }
535
536 @Override
537 public String toString() {
538 return MoreObjects.toStringHelper(getClass())
539 .add("name", name)
540 .add("cir", cir)
541 .add("pir", pir)
542 .add("cbs", cbs)
543 .add("pbs", pbs)
544 .add("ebs", ebs)
545 .add("greenAction", greenAction)
546 .add("yellowAction", yellowAction)
547 .add("redAction", redAction)
548 .add("colorAware", colorAware)
549 .toString();
550 }
551}