[SDFAB-500][SDFAB-527] Meters cleanup and leftovers
- Improve ONOS cli enabling CRUD of p4rt trtcm
- Improve ONOS rest enabling CRUD of p4rt trtcm
- Improve MeterService with scope defined reads and integrate in cli/rest
- Add support along the stack for BYTE_PER_SEC unit
- Add support along the stack for COMMITTED and PEAK bands
- Fix several bugs in ONOS cli/rest interfaces
- Improve REST codecs
- Fix NPE in MeterDriverProvider
- Improve PiMeterTransalation by enforcing trtcm config
- Implement explicit translation of the bands
- Fix ONOS reconciliation by removing from the mirror the wrong configs
- Remove unnecessary checks in MeterEntryCodec
- Update unit tests
It will follow a 2nd patch to complete SDFAB-527
Change-Id: I855235b17f60cb1d39f5b9a042c1015105a8a269
diff --git a/core/api/src/main/java/org/onosproject/net/meter/Band.java b/core/api/src/main/java/org/onosproject/net/meter/Band.java
index 9f9479c..befbead 100644
--- a/core/api/src/main/java/org/onosproject/net/meter/Band.java
+++ b/core/api/src/main/java/org/onosproject/net/meter/Band.java
@@ -51,8 +51,27 @@
* Defines a meter band with no action, used to mark
* packets internally in the pipeline, i.e. without
* modifying the packet headers.
+ *
+ * @deprecated in onos-2.5, replace by MARK_YELLOW and MARK_RED
*/
+ @Deprecated
NONE,
+
+ /**
+ * Defines a meter band for the configuration of the committed
+ * rate AND the committed burst size. Used in conjunction with MARK_RED
+ * to implement a srTCM or trTCM, see RFCs 2697 and 2698 respectively.
+ */
+ MARK_YELLOW,
+
+ /**
+ * Defines a meter band for the configuration of the peak rate
+ * AND the peak burst size OR the excess burst size. When used to
+ * configure a srTCM excess rate must be 0. Used in conjunction with
+ * MARK_YELLOW to implement a srTCM or trTCM, see RFCs 2697 and 2698
+ * respectively.
+ */
+ MARK_RED,
}
/**
diff --git a/core/api/src/main/java/org/onosproject/net/meter/DefaultMeterRequest.java b/core/api/src/main/java/org/onosproject/net/meter/DefaultMeterRequest.java
index 0dbd4f7..617151d 100644
--- a/core/api/src/main/java/org/onosproject/net/meter/DefaultMeterRequest.java
+++ b/core/api/src/main/java/org/onosproject/net/meter/DefaultMeterRequest.java
@@ -33,8 +33,6 @@
*/
public final class DefaultMeterRequest extends AbstractAnnotated implements MeterRequest {
-
-
private final ApplicationId appId;
private final Meter.Unit unit;
private final boolean burst;
@@ -122,6 +120,8 @@
}
public static final class Builder implements MeterRequest.Builder {
+ // Relevant only for delete
+ private static final Band DUMMY_BAND = new DefaultBand(Band.Type.DROP, 0L, 0L, (short) 0);
private ApplicationId appId;
private Meter.Unit unit = Meter.Unit.KB_PER_SEC;
@@ -196,6 +196,11 @@
@Override
public MeterRequest remove() {
+ // Allow to create the removal request without specifying bands
+ if (bands == null || bands.isEmpty()) {
+ bands = ImmutableSet.of(DUMMY_BAND);
+ }
+
validate();
return new DefaultMeterRequest(deviceId, appId, unit, burst, bands, context,
Type.REMOVE, scope, desiredIndex, annotations);
diff --git a/core/api/src/main/java/org/onosproject/net/meter/MeterService.java b/core/api/src/main/java/org/onosproject/net/meter/MeterService.java
index 5b3ca3b..2d37f87 100644
--- a/core/api/src/main/java/org/onosproject/net/meter/MeterService.java
+++ b/core/api/src/main/java/org/onosproject/net/meter/MeterService.java
@@ -91,6 +91,15 @@
Collection<Meter> getMeters(DeviceId deviceId);
/**
+ * Fetches the meters by the device id and scope.
+ *
+ * @param deviceId a device id
+ * @param scope meters scope
+ * @return a collection of meters
+ */
+ Collection<Meter> getMeters(DeviceId deviceId, MeterScope scope);
+
+ /**
* Allocates a new meter id in the system.
*
* @param deviceId the device id
diff --git a/core/api/src/main/java/org/onosproject/net/meter/MeterStore.java b/core/api/src/main/java/org/onosproject/net/meter/MeterStore.java
index 7f4de4b..4abf233 100644
--- a/core/api/src/main/java/org/onosproject/net/meter/MeterStore.java
+++ b/core/api/src/main/java/org/onosproject/net/meter/MeterStore.java
@@ -118,6 +118,17 @@
Collection<Meter> getAllMeters(DeviceId deviceId);
/**
+ * Returns all meters stored in the store for a
+ * precise device and scope.
+ *
+ * @param deviceId a device id
+ * @param scope meters scope
+ * @return an immutable copy of the meters stored for a given device
+ * withing a given scope
+ */
+ Collection<Meter> getAllMeters(DeviceId deviceId, MeterScope scope);
+
+ /**
* Update the store by deleting the failed meter.
* Notifies the delegate that the meter failed to allow it
* to nofity the app.
diff --git a/core/api/src/main/java/org/onosproject/net/pi/runtime/PiMeterBand.java b/core/api/src/main/java/org/onosproject/net/pi/runtime/PiMeterBand.java
index b1dbcf5..ea8c34d 100644
--- a/core/api/src/main/java/org/onosproject/net/pi/runtime/PiMeterBand.java
+++ b/core/api/src/main/java/org/onosproject/net/pi/runtime/PiMeterBand.java
@@ -27,21 +27,33 @@
*/
@Beta
public final class PiMeterBand {
+ private final PiMeterBandType type;
private final long rate;
private final long burst;
/**
* Creates a band with rate and burst.
*
+ * @param type type of this band
* @param rate rate of this band
* @param burst burst of this band
*/
- public PiMeterBand(long rate, long burst) {
+ public PiMeterBand(PiMeterBandType type, long rate, long burst) {
+ this.type = type;
this.rate = rate;
this.burst = burst;
}
/**
+ * Returns the type of this band.
+ *
+ * @return type of this band
+ */
+ public PiMeterBandType type() {
+ return type;
+ }
+
+ /**
* Returns the rate of this band.
*
* @return rate of this band
@@ -61,7 +73,7 @@
@Override
public int hashCode() {
- return Objects.hash(rate, burst);
+ return Objects.hash(type, rate, burst);
}
@Override
@@ -71,7 +83,8 @@
}
if (obj instanceof PiMeterBand) {
PiMeterBand that = (PiMeterBand) obj;
- return Objects.equals(rate, that.rate) &&
+ return Objects.equals(type, that.type) &&
+ Objects.equals(rate, that.rate) &&
Objects.equals(burst, that.burst);
}
@@ -80,6 +93,7 @@
public String toString() {
return toStringHelper(this)
+ .add("type", type)
.add("rate", rate)
.add("burst", burst).toString();
}
diff --git a/core/api/src/main/java/org/onosproject/net/pi/runtime/PiMeterBandType.java b/core/api/src/main/java/org/onosproject/net/pi/runtime/PiMeterBandType.java
new file mode 100644
index 0000000..ee15a57
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/pi/runtime/PiMeterBandType.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2021-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.net.pi.runtime;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * Type of meter band of a protocol-independent pipeline.
+ */
+@Beta
+public enum PiMeterBandType {
+ /**
+ * Committed band config.
+ */
+ COMMITTED("committed"),
+
+ /**
+ * Peak band config.
+ */
+ PEAK("peak");
+
+ private final String humanReadableName;
+
+ PiMeterBandType(String humanReadableName) {
+ this.humanReadableName = humanReadableName;
+ }
+
+ /**
+ * Returns a human readable representation of this PI meter band type (useful
+ * for logging).
+ *
+ * @return string
+ */
+ public String humanReadableName() {
+ return humanReadableName;
+ }
+}
diff --git a/core/api/src/main/java/org/onosproject/net/pi/runtime/PiMeterCellConfig.java b/core/api/src/main/java/org/onosproject/net/pi/runtime/PiMeterCellConfig.java
index d3da340..ecbfe07 100644
--- a/core/api/src/main/java/org/onosproject/net/pi/runtime/PiMeterCellConfig.java
+++ b/core/api/src/main/java/org/onosproject/net/pi/runtime/PiMeterCellConfig.java
@@ -19,13 +19,12 @@
import com.google.common.annotations.Beta;
import com.google.common.base.MoreObjects;
import com.google.common.base.Objects;
-import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Maps;
import org.onosproject.net.DeviceId;
-import java.util.ArrayList;
-import java.util.Collection;
import java.util.Collections;
-import java.util.List;
+import java.util.Map;
import static com.google.common.base.Preconditions.checkNotNull;
@@ -36,7 +35,7 @@
public final class PiMeterCellConfig implements PiEntity {
private final PiMeterCellId cellId;
- private final ImmutableList<PiMeterBand> piMeterBands;
+ private final ImmutableMap<PiMeterBandType, PiMeterBand> piMeterBands;
/**
* Creates a new meter cell configuration for the given cell identifier and meter bands.
@@ -44,9 +43,9 @@
* @param cellId meter cell identifier
* @param piMeterBands meter bands
*/
- private PiMeterCellConfig(PiMeterCellId cellId, Collection<PiMeterBand> piMeterBands) {
+ private PiMeterCellConfig(PiMeterCellId cellId, Map<PiMeterBandType, PiMeterBand> piMeterBands) {
this.cellId = cellId;
- this.piMeterBands = ImmutableList.copyOf(piMeterBands);
+ this.piMeterBands = ImmutableMap.copyOf(piMeterBands);
}
/**
@@ -59,11 +58,11 @@
}
/**
- * Returns the collection of bands of this cell.
+ * Returns the map of bands of this cell.
*
* @return meter bands
*/
- public Collection<PiMeterBand> meterBands() {
+ public Map<PiMeterBandType, PiMeterBand> meterBands() {
return piMeterBands;
}
@@ -88,6 +87,24 @@
}
/**
+ * Returns the committed configuration if present.
+ *
+ * @return the committed band. Null otherwise
+ */
+ public PiMeterBand committedBand() {
+ return piMeterBands.get(PiMeterBandType.COMMITTED);
+ }
+
+ /**
+ * Returns the peak configuration if present.
+ *
+ * @return the peak band. Null otherwise
+ */
+ public PiMeterBand peakBand() {
+ return piMeterBands.get(PiMeterBandType.PEAK);
+ }
+
+ /**
* Returns a PiMeterCellConfig with no bands.
* Used to reset a PI meter cell.
*
@@ -95,7 +112,7 @@
* @return a PiMeterCellConfig with no bands
*/
public static PiMeterCellConfig reset(PiMeterCellId piMeterCellId) {
- return new PiMeterCellConfig(piMeterCellId, Collections.emptyList());
+ return new PiMeterCellConfig(piMeterCellId, Collections.emptyMap());
}
@Override
@@ -118,8 +135,7 @@
}
PiMeterCellConfig that = (PiMeterCellConfig) o;
- return piMeterBands.containsAll((that.piMeterBands)) &&
- piMeterBands.size() == that.piMeterBands.size() &&
+ return Objects.equal(piMeterBands, that.piMeterBands) &&
Objects.equal(cellId, that.cellId);
}
@@ -146,8 +162,8 @@
}
public static final class Builder {
- private PiMeterCellId cellId;
- private List<PiMeterBand> bands = new ArrayList<>();
+ private PiMeterCellId cellId;
+ private Map<PiMeterBandType, PiMeterBand> bands = Maps.newHashMap();
private Builder() {
@@ -173,7 +189,31 @@
* @return this
*/
public PiMeterCellConfig.Builder withMeterBand(PiMeterBand band) {
- this.bands.add(band);
+ this.bands.put(band.type(), band);
+ return this;
+ }
+
+ /**
+ * Sets the committed band of this meter.
+ *
+ * @param rate committed rate
+ * @param burst committed burst
+ * @return this
+ */
+ public PiMeterCellConfig.Builder withCommittedBand(long rate, long burst) {
+ this.bands.put(PiMeterBandType.COMMITTED, new PiMeterBand(PiMeterBandType.COMMITTED, rate, burst));
+ return this;
+ }
+
+ /**
+ * Sets the peak band of this meter.
+ *
+ * @param rate peak rate
+ * @param burst peak burst
+ * @return this
+ */
+ public PiMeterCellConfig.Builder withPeakBand(long rate, long burst) {
+ this.bands.put(PiMeterBandType.PEAK, new PiMeterBand(PiMeterBandType.PEAK, rate, burst));
return this;
}
diff --git a/core/api/src/test/java/org/onosproject/net/meter/MeterServiceAdapter.java b/core/api/src/test/java/org/onosproject/net/meter/MeterServiceAdapter.java
index 2a298b4..86795e9 100644
--- a/core/api/src/test/java/org/onosproject/net/meter/MeterServiceAdapter.java
+++ b/core/api/src/test/java/org/onosproject/net/meter/MeterServiceAdapter.java
@@ -61,6 +61,11 @@
}
@Override
+ public Collection<Meter> getMeters(DeviceId deviceId, MeterScope scope) {
+ return null;
+ }
+
+ @Override
public MeterId allocateMeterId(DeviceId deviceId) {
return null;
}
diff --git a/core/common/src/main/java/org/onosproject/codec/impl/MeterBandCodec.java b/core/common/src/main/java/org/onosproject/codec/impl/MeterBandCodec.java
index 4621e94..3cb68a0 100644
--- a/core/common/src/main/java/org/onosproject/codec/impl/MeterBandCodec.java
+++ b/core/common/src/main/java/org/onosproject/codec/impl/MeterBandCodec.java
@@ -21,17 +21,14 @@
import org.onosproject.net.meter.Band;
import org.onosproject.net.meter.Band.Builder;
import org.onosproject.net.meter.DefaultBand;
-import org.slf4j.Logger;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.onlab.util.Tools.nullIsIllegal;
-import static org.slf4j.LoggerFactory.getLogger;
/**
* Meter band JSON codec.
*/
public final class MeterBandCodec extends JsonCodec<Band> {
- private final Logger log = getLogger(getClass());
// JSON field names
private static final String TYPE = "type";
@@ -93,6 +90,18 @@
builder.ofType(type);
builder.dropPrecedence(precedence);
break;
+ case "NONE":
+ type = Band.Type.NONE;
+ builder.ofType(type);
+ break;
+ case "MARK_YELLOW":
+ type = Band.Type.MARK_YELLOW;
+ builder.ofType(type);
+ break;
+ case "MARK_RED":
+ type = Band.Type.MARK_RED;
+ builder.ofType(type);
+ break;
default:
nullIsIllegal(type, "The requested type " + typeStr + " is not defined for band.");
}
diff --git a/core/common/src/main/java/org/onosproject/codec/impl/MeterCodec.java b/core/common/src/main/java/org/onosproject/codec/impl/MeterCodec.java
index 5cf1d13..26b6677 100644
--- a/core/common/src/main/java/org/onosproject/codec/impl/MeterCodec.java
+++ b/core/common/src/main/java/org/onosproject/codec/impl/MeterCodec.java
@@ -21,17 +21,14 @@
import org.onosproject.codec.JsonCodec;
import org.onosproject.net.meter.Band;
import org.onosproject.net.meter.Meter;
-import org.slf4j.Logger;
import static com.google.common.base.Preconditions.checkNotNull;
-import static org.slf4j.LoggerFactory.getLogger;
/**
* Meter JSON codec.
*/
public final class MeterCodec extends JsonCodec<Meter> {
- private final Logger log = getLogger(getClass());
// JSON field names
private static final String ID = "id";
@@ -51,7 +48,7 @@
public ObjectNode encode(Meter meter, CodecContext context) {
checkNotNull(meter, "Meter cannot be null");
ObjectNode result = context.mapper().createObjectNode()
- .put(ID, meter.id().toString())
+ .put(ID, meter.meterCellId().toString())
.put(LIFE, meter.life())
.put(PACKETS, meter.packetsSeen())
.put(BYTES, meter.bytesSeen())
diff --git a/core/common/src/main/java/org/onosproject/codec/impl/MeterRequestCodec.java b/core/common/src/main/java/org/onosproject/codec/impl/MeterRequestCodec.java
index d254428..d46e257 100644
--- a/core/common/src/main/java/org/onosproject/codec/impl/MeterRequestCodec.java
+++ b/core/common/src/main/java/org/onosproject/codec/impl/MeterRequestCodec.java
@@ -26,29 +26,32 @@
import org.onosproject.net.meter.DefaultMeterRequest;
import org.onosproject.net.meter.Meter;
import org.onosproject.net.meter.MeterRequest;
-import org.slf4j.Logger;
+import org.onosproject.net.meter.MeterScope;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.IntStream;
import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Strings.isNullOrEmpty;
import static org.onlab.util.Tools.nullIsIllegal;
-import static org.slf4j.LoggerFactory.getLogger;
/**
* MeterRequest JSON codec.
*/
public final class MeterRequestCodec extends JsonCodec<MeterRequest> {
- private final Logger log = getLogger(getClass());
// JSON field names
private static final String DEVICE_ID = "deviceId";
private static final String UNIT = "unit";
private static final String BANDS = "bands";
- public static final String REST_APP_ID = "org.onosproject.rest";
+ private static final String SCOPE = "scope";
+ private static final String INDEX = "index";
+ private static final String REST_APP_ID = "org.onosproject.rest";
private static final String MISSING_MEMBER_MESSAGE = " member is required in MeterRequest";
+ private ApplicationId applicationId;
+
@Override
public MeterRequest decode(ObjectNode json, CodecContext context) {
if (json == null || !json.isObject()) {
@@ -56,14 +59,17 @@
}
final JsonCodec<Band> meterBandCodec = context.codec(Band.class);
- CoreService coreService = context.getService(CoreService.class);
+
// parse device id
DeviceId deviceId = DeviceId.deviceId(nullIsIllegal(json.get(DEVICE_ID),
DEVICE_ID + MISSING_MEMBER_MESSAGE).asText());
// application id
- ApplicationId appId = coreService.registerApplication(REST_APP_ID);
+ if (applicationId == null) {
+ CoreService coreService = context.getService(CoreService.class);
+ applicationId = coreService.registerApplication(REST_APP_ID);
+ }
// parse burst
boolean burst = false;
@@ -83,6 +89,9 @@
case "PKTS_PER_SEC":
meterUnit = Meter.Unit.PKTS_PER_SEC;
break;
+ case "BYTES_PER_SEC":
+ meterUnit = Meter.Unit.BYTES_PER_SEC;
+ break;
default:
nullIsIllegal(meterUnit, "The requested unit " + unit + " is not defined for meter.");
}
@@ -98,22 +107,39 @@
});
}
- MeterRequest meterRequest;
- if (burst) {
- meterRequest = DefaultMeterRequest.builder()
- .fromApp(appId)
- .forDevice(deviceId)
- .withUnit(meterUnit)
- .withBands(bandList)
- .burst().add();
- } else {
- meterRequest = DefaultMeterRequest.builder()
- .fromApp(appId)
- .forDevice(deviceId)
- .withUnit(meterUnit)
- .withBands(bandList).add();
+ // parse scope and index
+ JsonNode scopeJson = json.get(SCOPE);
+ MeterScope scope = null;
+ if (scopeJson != null && !isNullOrEmpty(scopeJson.asText())) {
+ scope = MeterScope.of(scopeJson.asText());
}
- return meterRequest;
+ JsonNode indexJson = json.get(INDEX);
+ Long index = null;
+ if (indexJson != null && !isNullOrEmpty(indexJson.asText()) && scope != null) {
+ index = indexJson.asLong();
+ }
+
+ // build the final request
+ MeterRequest.Builder meterRequest = DefaultMeterRequest.builder();
+ if (scope != null) {
+ meterRequest.withScope(scope);
+ }
+
+ if (index != null) {
+ meterRequest.withIndex(index);
+ }
+
+ meterRequest.fromApp(applicationId)
+ .forDevice(deviceId)
+ .withUnit(meterUnit)
+ .withBands(bandList);
+
+ if (burst) {
+ meterRequest.burst();
+ }
+
+ return meterRequest.add();
}
+
}
diff --git a/core/net/src/main/java/org/onosproject/net/meter/impl/MeterDriverProvider.java b/core/net/src/main/java/org/onosproject/net/meter/impl/MeterDriverProvider.java
index cf7d198..b1422e8 100644
--- a/core/net/src/main/java/org/onosproject/net/meter/impl/MeterDriverProvider.java
+++ b/core/net/src/main/java/org/onosproject/net/meter/impl/MeterDriverProvider.java
@@ -152,7 +152,9 @@
private void getMeterFeatures(DeviceId deviceId) {
Collection<MeterFeatures> meterFeatures = Collections.emptySet();
try {
- meterFeatures = getMeterProgrammable(deviceId).getMeterFeatures().get(pollFrequency, TimeUnit.SECONDS);
+ if (isMeterProgrammable(deviceId)) {
+ meterFeatures = getMeterProgrammable(deviceId).getMeterFeatures().get(pollFrequency, TimeUnit.SECONDS);
+ }
} catch (Exception e) {
log.warn("Unable to get the Meter Features from {}, error: {}", deviceId, e.getMessage());
log.debug("Exception: ", e);
@@ -160,6 +162,11 @@
meterProviderService.pushMeterFeatures(deviceId, meterFeatures);
}
+ private boolean isMeterProgrammable(DeviceId deviceId) {
+ Device device = deviceService.getDevice(deviceId);
+ return device.is(MeterProgrammable.class);
+ }
+
private MeterProgrammable getMeterProgrammable(DeviceId deviceId) {
Device device = deviceService.getDevice(deviceId);
if (device.is(MeterProgrammable.class)) {
diff --git a/core/net/src/main/java/org/onosproject/net/meter/impl/MeterManager.java b/core/net/src/main/java/org/onosproject/net/meter/impl/MeterManager.java
index b2e6730..98e79a9 100644
--- a/core/net/src/main/java/org/onosproject/net/meter/impl/MeterManager.java
+++ b/core/net/src/main/java/org/onosproject/net/meter/impl/MeterManager.java
@@ -343,8 +343,12 @@
@Override
public Collection<Meter> getMeters(DeviceId deviceId) {
- return store.getAllMeters().stream().filter(m ->
- m.deviceId().equals(deviceId)).collect(Collectors.toList());
+ return store.getAllMeters(deviceId);
+ }
+
+ @Override
+ public Collection<Meter> getMeters(DeviceId deviceId, MeterScope scope) {
+ return store.getAllMeters(deviceId, scope);
}
@Override
diff --git a/core/net/src/main/java/org/onosproject/net/pi/impl/PiMeterTranslatorImpl.java b/core/net/src/main/java/org/onosproject/net/pi/impl/PiMeterTranslatorImpl.java
index 3831699..48cd4ba 100644
--- a/core/net/src/main/java/org/onosproject/net/pi/impl/PiMeterTranslatorImpl.java
+++ b/core/net/src/main/java/org/onosproject/net/pi/impl/PiMeterTranslatorImpl.java
@@ -20,7 +20,6 @@
import org.onosproject.net.meter.Band;
import org.onosproject.net.meter.Meter;
import org.onosproject.net.pi.model.PiPipeconf;
-import org.onosproject.net.pi.runtime.PiMeterBand;
import org.onosproject.net.pi.runtime.PiMeterCellConfig;
import org.onosproject.net.pi.runtime.PiMeterCellId;
import org.onosproject.net.pi.service.PiTranslationException;
@@ -36,7 +35,7 @@
// Hides constructor.
}
- private static final int TRTCM_RATES = 2;
+ private static final int TCM_BANDS = 2;
/**
* Returns a PI meter config equivalent to the given meter, for the given pipeconf and device.
@@ -53,23 +52,52 @@
throw new PiTranslationException("PI meter cell type must be PIPELINE_INDEPENDENT!");
}
- // FIXME: we might want to move this check to P4Runtime driver or protocol layer.
- // In general, This check is more of P4Runtime limitation, we should do this check in the low level layer.
- if (meter.bands().size() > TRTCM_RATES) {
- throw new PiTranslationException("PI meter can not have more than 2 bands!");
+ // In general, this check is more of P4Runtime limitation, we should do this check in the low level layer.
+ // At the same time we could extend to support other configurations (for example srTCM).
+ // TODO implement SRTCM and TRTCM helper classes to improve readability of the code.
+ // Or in future when we support other markers we can simply create two different methods.
+ if (meter.bands().size() != TCM_BANDS) {
+ throw new PiTranslationException("PI meter must have 2 bands in order to implement TCM metering!");
}
-
- PiMeterCellConfig.Builder builder = PiMeterCellConfig.builder();
- for (Band band : meter.bands()) {
- if (band.type() != Band.Type.NONE) {
- throw new PiTranslationException("PI meter can not have band with other types except NONE!");
- }
-
- PiMeterBand piMeterBand = new PiMeterBand(band.rate(), band.burst());
- builder.withMeterBand(piMeterBand);
+ final Band[] bands = meter.bands().toArray(new Band[0]);
+ // Validate proper config of the TCM settings.
+ if ((bands[0].type() != Band.Type.MARK_YELLOW && bands[0].type() != Band.Type.MARK_RED) ||
+ (bands[1].type() != Band.Type.MARK_YELLOW && bands[1].type() != Band.Type.MARK_RED) ||
+ (bands[0].type() == bands[1].type())) {
+ throw new PiTranslationException("PI TCM meter must have a MARK_YELLOW band and a MARK_RED band!");
}
- return builder.withMeterCellId((PiMeterCellId) meter.meterCellId()).build();
+ // Validate proper config of the trTCM settings
+ if (bands[0].burst() <= 0 || bands[1].burst() <= 0) {
+ throw new PiTranslationException("PI trTCM meter can not have band with burst <= 0!");
+ }
+ if (bands[0].rate() <= 0 || bands[1].rate() <= 0) {
+ throw new PiTranslationException("PI trTCM meter can not have band with rate <= 0!");
+ }
+
+ long cir, cburst, pir, pburst;
+ if (bands[0].type() == Band.Type.MARK_YELLOW) {
+ cir = bands[0].rate();
+ cburst = bands[0].burst();
+ pir = bands[1].rate();
+ pburst = bands[1].burst();
+ } else {
+ pir = bands[0].rate();
+ pburst = bands[0].burst();
+ cir = bands[1].rate();
+ cburst = bands[1].burst();
+ }
+
+ if (cir > pir) {
+ throw new PiTranslationException("PI trTCM meter must have a pir >= cir!");
+ }
+
+ return PiMeterCellConfig.builder()
+ .withCommittedBand(cir, cburst)
+ .withPeakBand(pir, pburst)
+ .withMeterCellId((PiMeterCellId) meter.meterCellId())
+ .build();
}
+
}
diff --git a/core/store/dist/src/main/java/org/onosproject/store/meter/impl/DistributedMeterStore.java b/core/store/dist/src/main/java/org/onosproject/store/meter/impl/DistributedMeterStore.java
index afc6d94..7d8c7a5 100644
--- a/core/store/dist/src/main/java/org/onosproject/store/meter/impl/DistributedMeterStore.java
+++ b/core/store/dist/src/main/java/org/onosproject/store/meter/impl/DistributedMeterStore.java
@@ -365,6 +365,21 @@
}
@Override
+ public Collection<Meter> getAllMeters(DeviceId deviceId, MeterScope scope) {
+ if (scope.equals(MeterScope.globalScope())) {
+ return Collections2.transform(
+ Collections2.filter(ImmutableSet.copyOf(metersMap.values()),
+ (MeterData m) -> m.meter().meterCellId().type() == INDEX),
+ MeterData::meter);
+ }
+ return Collections2.transform(
+ Collections2.filter(ImmutableSet.copyOf(metersMap.values()),
+ (MeterData m) -> m.meter().meterCellId().type() == PIPELINE_INDEPENDENT &&
+ ((PiMeterCellId) m.meter().meterCellId()).meterId().id().equals(scope.id())),
+ MeterData::meter);
+ }
+
+ @Override
public void failedMeter(MeterOperation op, MeterFailReason reason) {
// Meter ops failed (got notification from the sb)
MeterKey key = MeterKey.key(op.meter().deviceId(), op.meter().meterCellId());
@@ -701,8 +716,9 @@
return null;
});
notifyDelegate(new MeterEvent(MeterEvent.Type.METER_ADDED, data.meter()));
- // Update stats case
- } else if (data.meter().referenceCount() == 0) {
+ // Update stats case - we report reference count zero only for INDEX based meters
+ } else if (data.meter().referenceCount() == 0 &&
+ data.meter().meterCellId().type() == INDEX) {
notifyDelegate(new MeterEvent(MeterEvent.Type.METER_REFERENCE_COUNT_ZERO,
data.meter()));
}