blob: 3a243959279f7f58935d57edeab9758fa8911c9b [file] [log] [blame]
Frank Wangd7e3b4b2017-09-24 13:37:54 +09001/*
2 * Copyright 2017-present Open Networking Foundation
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 */
16
17package org.onosproject.net.pi.impl;
18
19import org.onosproject.net.Device;
20import org.onosproject.net.meter.Band;
21import org.onosproject.net.meter.Meter;
22import org.onosproject.net.pi.model.PiPipeconf;
Frank Wangd7e3b4b2017-09-24 13:37:54 +090023import org.onosproject.net.pi.runtime.PiMeterCellConfig;
24import org.onosproject.net.pi.runtime.PiMeterCellId;
25import org.onosproject.net.pi.service.PiTranslationException;
26
27import static org.onosproject.net.meter.MeterCellId.MeterCellType.PIPELINE_INDEPENDENT;
28
29/**
30 * Implementation of meter translation logic.
31 */
32final class PiMeterTranslatorImpl {
33
34 private PiMeterTranslatorImpl() {
35 // Hides constructor.
36 }
37
pierventre36b9a892021-08-27 15:25:02 +020038 private static final int TCM_BANDS = 2;
Frank Wangd7e3b4b2017-09-24 13:37:54 +090039
40 /**
41 * Returns a PI meter config equivalent to the given meter, for the given pipeconf and device.
42 *
43 * @param meter meter
44 * @param pipeconf pipeconf
45 * @param device device
46 * @return PI meter configs
47 * @throws PiTranslationException if the meter cannot be translated
48 */
49 static PiMeterCellConfig translate(Meter meter, PiPipeconf pipeconf, Device device) throws PiTranslationException {
50
51 if (meter.meterCellId().type() != PIPELINE_INDEPENDENT) {
52 throw new PiTranslationException("PI meter cell type must be PIPELINE_INDEPENDENT!");
53 }
54
pierventre36b9a892021-08-27 15:25:02 +020055 // In general, this check is more of P4Runtime limitation, we should do this check in the low level layer.
56 // At the same time we could extend to support other configurations (for example srTCM).
57 // TODO implement SRTCM and TRTCM helper classes to improve readability of the code.
58 // Or in future when we support other markers we can simply create two different methods.
59 if (meter.bands().size() != TCM_BANDS) {
60 throw new PiTranslationException("PI meter must have 2 bands in order to implement TCM metering!");
Frank Wangd7e3b4b2017-09-24 13:37:54 +090061 }
62
pierventre36b9a892021-08-27 15:25:02 +020063 final Band[] bands = meter.bands().toArray(new Band[0]);
64 // Validate proper config of the TCM settings.
65 if ((bands[0].type() != Band.Type.MARK_YELLOW && bands[0].type() != Band.Type.MARK_RED) ||
66 (bands[1].type() != Band.Type.MARK_YELLOW && bands[1].type() != Band.Type.MARK_RED) ||
67 (bands[0].type() == bands[1].type())) {
68 throw new PiTranslationException("PI TCM meter must have a MARK_YELLOW band and a MARK_RED band!");
Frank Wangd7e3b4b2017-09-24 13:37:54 +090069 }
70
pierventre25c62782022-02-24 12:16:33 -080071 // Validate proper config. NOTE that we have relaxed some checks
72 // and the ONOS meters are not spec compliants with trTCM RFC
73 if (bands[0].burst() < 0 || bands[1].burst() < 0) {
74 throw new PiTranslationException("PI trTCM meter can not have band with burst < 0!");
pierventre36b9a892021-08-27 15:25:02 +020075 }
pierventre25c62782022-02-24 12:16:33 -080076 if (bands[0].rate() < 0 || bands[1].rate() < 0) {
77 throw new PiTranslationException("PI trTCM meter can not have band with rate < 0!");
pierventre36b9a892021-08-27 15:25:02 +020078 }
79
80 long cir, cburst, pir, pburst;
81 if (bands[0].type() == Band.Type.MARK_YELLOW) {
82 cir = bands[0].rate();
83 cburst = bands[0].burst();
84 pir = bands[1].rate();
85 pburst = bands[1].burst();
86 } else {
87 pir = bands[0].rate();
88 pburst = bands[0].burst();
89 cir = bands[1].rate();
90 cburst = bands[1].burst();
91 }
92
93 if (cir > pir) {
94 throw new PiTranslationException("PI trTCM meter must have a pir >= cir!");
95 }
96
97 return PiMeterCellConfig.builder()
98 .withCommittedBand(cir, cburst)
99 .withPeakBand(pir, pburst)
100 .withMeterCellId((PiMeterCellId) meter.meterCellId())
101 .build();
Frank Wangd7e3b4b2017-09-24 13:37:54 +0900102 }
pierventre36b9a892021-08-27 15:25:02 +0200103
Frank Wangd7e3b4b2017-09-24 13:37:54 +0900104}