[ONOS-7051] Support for P4Runtime meters
Change-Id: Id71374af65aeb84b71636b4ec230dc6001a77a8b
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 5d7965b..04e3e56 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
@@ -30,6 +30,7 @@
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.driver.DriverService;
import org.onosproject.net.meter.DefaultMeter;
+import org.onosproject.net.meter.MeterCellId.MeterCellType;
import org.onosproject.net.meter.Meter;
import org.onosproject.net.meter.MeterEvent;
import org.onosproject.net.meter.MeterFailReason;
@@ -132,10 +133,10 @@
}
});
- };
+ };
executorService = newFixedThreadPool(numThreads,
- groupedThreads(GROUP_THREAD_NAME, WORKER_PATTERN, log));
+ groupedThreads(GROUP_THREAD_NAME, WORKER_PATTERN, log));
modified(context);
log.info("Started");
}
@@ -146,7 +147,7 @@
readComponentConfiguration(context);
}
defaultProvider.init(deviceService, createProviderService(defaultProvider),
- mastershipService, fallbackMeterPollFrequency);
+ mastershipService, fallbackMeterPollFrequency);
}
@Deactivate
@@ -289,7 +290,7 @@
// The meter is missing in the device. Reinstall!
log.debug("Adding meter missing in device {} {}", deviceId, m);
provider().performMeterOperation(deviceId,
- new MeterOperation(m, MeterOperation.Type.ADD));
+ new MeterOperation(m, MeterOperation.Type.ADD));
}
});
@@ -297,12 +298,19 @@
meterEntriesMap.entrySet().stream()
.filter(md -> !allMeters.stream().anyMatch(m -> m.id().equals(md.getKey())))
.forEach(mio -> {
- // The meter is missin in onos. Uninstall!
- log.debug("Remove meter in device not in onos {} {}", deviceId, mio.getKey());
Meter meter = mio.getValue();
- provider().performMeterOperation(deviceId,
- new MeterOperation(meter, MeterOperation.Type.REMOVE));
- });
+ // FIXME: Removing a meter is meaningfull for OpenFlow, but not for P4Runtime.
+ // In P4Runtime meter cells cannot be removed. For the
+ // moment, we make the distinction between OpenFlow and
+ // P4Runtime by looking at the MeterCellType (always
+ // INDEX for OpenFlow).
+ if (meter.meterCellId().type() == MeterCellType.INDEX) {
+ // The meter is missing in onos. Uninstall!
+ log.debug("Remove meter in device not in onos {} {}", deviceId, mio.getKey());
+ provider().performMeterOperation(deviceId,
+ new MeterOperation(meter, MeterOperation.Type.REMOVE));
+ }
+ });
meterEntries.stream()
.filter(m -> allMeters.stream()
@@ -339,11 +347,11 @@
switch (event.type()) {
case METER_ADD_REQ:
executorService.execute(new MeterInstaller(deviceId, event.subject(),
- MeterOperation.Type.ADD));
+ MeterOperation.Type.ADD));
break;
case METER_REM_REQ:
executorService.execute(new MeterInstaller(deviceId, event.subject(),
- MeterOperation.Type.REMOVE));
+ MeterOperation.Type.REMOVE));
break;
case METER_ADDED:
log.info("Meter added {}", event.subject());
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
new file mode 100644
index 0000000..3831699
--- /dev/null
+++ b/core/net/src/main/java/org/onosproject/net/pi/impl/PiMeterTranslatorImpl.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2017-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.impl;
+
+import org.onosproject.net.Device;
+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;
+
+import static org.onosproject.net.meter.MeterCellId.MeterCellType.PIPELINE_INDEPENDENT;
+
+/**
+ * Implementation of meter translation logic.
+ */
+final class PiMeterTranslatorImpl {
+
+ private PiMeterTranslatorImpl() {
+ // Hides constructor.
+ }
+
+ private static final int TRTCM_RATES = 2;
+
+ /**
+ * Returns a PI meter config equivalent to the given meter, for the given pipeconf and device.
+ *
+ * @param meter meter
+ * @param pipeconf pipeconf
+ * @param device device
+ * @return PI meter configs
+ * @throws PiTranslationException if the meter cannot be translated
+ */
+ static PiMeterCellConfig translate(Meter meter, PiPipeconf pipeconf, Device device) throws PiTranslationException {
+
+ if (meter.meterCellId().type() != PIPELINE_INDEPENDENT) {
+ 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!");
+ }
+
+
+ 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);
+ }
+
+ return builder.withMeterCellId((PiMeterCellId) meter.meterCellId()).build();
+ }
+}
diff --git a/core/net/src/main/java/org/onosproject/net/pi/impl/PiTranslationServiceImpl.java b/core/net/src/main/java/org/onosproject/net/pi/impl/PiTranslationServiceImpl.java
index 9780fac..c69ced9 100644
--- a/core/net/src/main/java/org/onosproject/net/pi/impl/PiTranslationServiceImpl.java
+++ b/core/net/src/main/java/org/onosproject/net/pi/impl/PiTranslationServiceImpl.java
@@ -27,13 +27,17 @@
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.group.Group;
+import org.onosproject.net.meter.Meter;
import org.onosproject.net.pi.model.PiPipeconf;
import org.onosproject.net.pi.runtime.PiActionGroup;
+import org.onosproject.net.pi.runtime.PiMeterCellConfig;
import org.onosproject.net.pi.runtime.PiTableEntry;
import org.onosproject.net.pi.service.PiFlowRuleTranslationStore;
import org.onosproject.net.pi.service.PiFlowRuleTranslator;
import org.onosproject.net.pi.service.PiGroupTranslationStore;
import org.onosproject.net.pi.service.PiGroupTranslator;
+import org.onosproject.net.pi.service.PiMeterTranslationStore;
+import org.onosproject.net.pi.service.PiMeterTranslator;
import org.onosproject.net.pi.service.PiTranslationException;
import org.onosproject.net.pi.service.PiTranslationService;
import org.slf4j.Logger;
@@ -59,13 +63,18 @@
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
private PiGroupTranslationStore groupTranslationStore;
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ private PiMeterTranslationStore meterTranslationStore;
+
private PiFlowRuleTranslator flowRuleTranslator;
private PiGroupTranslator groupTranslator;
+ private PiMeterTranslator meterTranslator;
@Activate
public void activate() {
flowRuleTranslator = new InternalFlowRuleTranslator(flowRuleTranslationStore);
groupTranslator = new InternalGroupTranslator(groupTranslationStore);
+ meterTranslator = new InternalMeterTranslator(meterTranslationStore);
log.info("Started");
}
@@ -73,6 +82,7 @@
public void deactivate() {
flowRuleTranslator = null;
groupTranslator = null;
+ meterTranslator = null;
log.info("Stopped");
}
@@ -86,6 +96,11 @@
return groupTranslator;
}
+ @Override
+ public PiMeterTranslator meterTranslator() {
+ return meterTranslator;
+ }
+
private Device getDevice(DeviceId deviceId) throws PiTranslationException {
final Device device = deviceService.getDevice(deviceId);
if (device == null) {
@@ -125,5 +140,21 @@
.translate(original, pipeconf, getDevice(original.deviceId()));
}
}
+
+ private final class InternalMeterTranslator
+ extends AbstractPiTranslatorImpl<Meter, PiMeterCellConfig>
+ implements PiMeterTranslator {
+
+ private InternalMeterTranslator(PiMeterTranslationStore store) {
+ super(store);
+ }
+
+ @Override
+ public PiMeterCellConfig translate(Meter original, PiPipeconf pipeconf)
+ throws PiTranslationException {
+ return PiMeterTranslatorImpl
+ .translate(original, pipeconf, getDevice(original.deviceId()));
+ }
+ }
}