[SDFAB-356] Extend P4RuntimeMeterProgrammable and Codecs to support reset scenario
Change-Id: Ifad0b296568d3f78b2aa792fa63f2f81fa80ebae
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 f13e276..e62482b 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
@@ -24,6 +24,7 @@
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
import java.util.List;
import static com.google.common.base.Preconditions.checkNotNull;
@@ -66,6 +67,35 @@
return piMeterBands;
}
+ /**
+ * Check if the config represents a modify operation.
+ *
+ * @return true if there are exactly 2 bands
+ */
+ public boolean isModify() {
+ return piMeterBands.size() == 2;
+ }
+
+ /**
+ * Check if the config represents a reset operation.
+ *
+ * @return true if there is no band.
+ */
+ public boolean isReset() {
+ return piMeterBands.isEmpty();
+ }
+
+ /**
+ * Returns a PiMeterCellConfig with no bands.
+ * Used to reset a PI meter cell.
+ *
+ * @param piMeterCellId the PiMeterCellId need to be reset
+ * @return a PiMeterCellConfig with no bands
+ */
+ public static PiMeterCellConfig reset(PiMeterCellId piMeterCellId) {
+ return new PiMeterCellConfig(piMeterCellId, Collections.emptyList());
+ }
+
@Override
public PiEntityType piEntityType() {
return PiEntityType.METER_CELL_CONFIG;
diff --git a/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeMeterProgrammable.java b/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeMeterProgrammable.java
index 0bcfcaf..caaa751 100644
--- a/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeMeterProgrammable.java
+++ b/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeMeterProgrammable.java
@@ -37,6 +37,7 @@
import org.onosproject.net.pi.model.PiPipelineModel;
import org.onosproject.net.pi.runtime.PiMeterCellConfig;
import org.onosproject.net.pi.runtime.PiMeterCellHandle;
+import org.onosproject.net.pi.runtime.PiMeterCellId;
import org.onosproject.net.pi.service.PiMeterTranslator;
import org.onosproject.net.pi.service.PiTranslationException;
@@ -51,6 +52,9 @@
import java.util.stream.Collectors;
import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onosproject.net.meter.MeterOperation.Type.ADD;
+import static org.onosproject.net.meter.MeterOperation.Type.MODIFY;
+import static org.onosproject.net.meter.MeterOperation.Type.REMOVE;
/**
* Implementation of MeterProgrammable behaviour for P4Runtime.
@@ -95,19 +99,27 @@
}
private boolean processMeterOp(MeterOperation meterOp) {
-
- if (meterOp.type() != MeterOperation.Type.MODIFY) {
- log.warn("P4Runtime meter operations must be MODIFY!");
- return false;
- }
-
PiMeterCellConfig piMeterCellConfig;
- try {
- piMeterCellConfig = translator.translate(meterOp.meter(), pipeconf);
- } catch (PiTranslationException e) {
- log.warn("Unable translate meter, aborting meter operation {}: {}", meterOp.type(), e.getMessage());
- log.debug("exception", e);
- return false;
+ switch (meterOp.type()) {
+ case ADD:
+ case MODIFY:
+ // Create a config for modify operation
+ try {
+ piMeterCellConfig = translator.translate(meterOp.meter(), pipeconf);
+ } catch (PiTranslationException e) {
+ log.warn("Unable translate meter, aborting meter operation {}: {}", meterOp.type(), e.getMessage());
+ log.debug("exception", e);
+ return false;
+ }
+ break;
+ case REMOVE:
+ // Create a empty config for reset operation
+ PiMeterCellId piMeterCellId = (PiMeterCellId) meterOp.meter().meterCellId();
+ piMeterCellConfig = PiMeterCellConfig.reset(piMeterCellId);
+ break;
+ default:
+ log.warn("Meter Operation type {} not supported", meterOp.type());
+ return false;
}
final PiMeterCellHandle handle = PiMeterCellHandle.of(deviceId, piMeterCellConfig);
diff --git a/protocols/p4runtime/utils/src/main/java/org/onosproject/p4runtime/ctl/codec/DirectMeterEntryCodec.java b/protocols/p4runtime/utils/src/main/java/org/onosproject/p4runtime/ctl/codec/DirectMeterEntryCodec.java
index 3bedfbf..0f32417 100644
--- a/protocols/p4runtime/utils/src/main/java/org/onosproject/p4runtime/ctl/codec/DirectMeterEntryCodec.java
+++ b/protocols/p4runtime/utils/src/main/java/org/onosproject/p4runtime/ctl/codec/DirectMeterEntryCodec.java
@@ -38,11 +38,16 @@
PiMeterCellConfig piEntity, Object ignored, PiPipeconf pipeconf,
P4InfoBrowser browser)
throws CodecException {
- return P4RuntimeOuterClass.DirectMeterEntry.newBuilder()
+ P4RuntimeOuterClass.DirectMeterEntry.Builder builder =
+ P4RuntimeOuterClass.DirectMeterEntry.newBuilder()
.setTableEntry(CODECS.tableEntry().encode(
- piEntity.cellId().tableEntry(), null, pipeconf))
- .setConfig(MeterEntryCodec.getP4Config(piEntity))
- .build();
+ piEntity.cellId().tableEntry(), null, pipeconf));
+ // We keep the config field unset if it is reset scenario
+ P4RuntimeOuterClass.MeterConfig meterConfig = MeterEntryCodec.getP4Config(piEntity);
+ if (meterConfig != null) {
+ builder = builder.setConfig(meterConfig);
+ }
+ return builder.build();
}
@Override
diff --git a/protocols/p4runtime/utils/src/main/java/org/onosproject/p4runtime/ctl/codec/MeterEntryCodec.java b/protocols/p4runtime/utils/src/main/java/org/onosproject/p4runtime/ctl/codec/MeterEntryCodec.java
index b210709..2da12d1 100644
--- a/protocols/p4runtime/utils/src/main/java/org/onosproject/p4runtime/ctl/codec/MeterEntryCodec.java
+++ b/protocols/p4runtime/utils/src/main/java/org/onosproject/p4runtime/ctl/codec/MeterEntryCodec.java
@@ -34,8 +34,13 @@
static P4RuntimeOuterClass.MeterConfig getP4Config(PiMeterCellConfig piConfig)
throws CodecException {
- if (piConfig.meterBands().size() != 2) {
- throw new CodecException("Number of meter bands should be 2");
+ // A reset config has no band
+ if (piConfig.isReset()) {
+ return null;
+ }
+ // A modify config has exactly 2 bands
+ if (!piConfig.isModify()) {
+ throw new CodecException("Number of meter bands should be 2 (Modify) or 0 (Reset)");
}
final PiMeterBand[] bands = piConfig.meterBands().toArray(new PiMeterBand[0]);
long cir, cburst, pir, pburst;
@@ -68,12 +73,17 @@
throws P4InfoBrowser.NotFoundException, CodecException {
final int meterId = browser.meters().getByName(
piEntity.cellId().meterId().id()).getPreamble().getId();
- return P4RuntimeOuterClass.MeterEntry.newBuilder()
+ P4RuntimeOuterClass.MeterEntry.Builder builder =
+ P4RuntimeOuterClass.MeterEntry.newBuilder()
.setMeterId(meterId)
.setIndex(P4RuntimeOuterClass.Index.newBuilder()
- .setIndex(piEntity.cellId().index()).build())
- .setConfig(getP4Config(piEntity))
- .build();
+ .setIndex(piEntity.cellId().index()).build());
+ // We keep the config field unset if it is reset scenario
+ P4RuntimeOuterClass.MeterConfig meterConfig = getP4Config(piEntity);
+ if (meterConfig != null) {
+ builder = builder.setConfig(meterConfig);
+ }
+ return builder.build();
}
@Override