Initial implementation of Meter Service (needs testing)
Change-Id: Ie07bd3e2bd7c67a6499c965d8926eb361ad16462
store impl started
Change-Id: Ib8b474f40dcecff335a421c12ad149fe9830c427
full implementation
Change-Id: Ie59fd61d02972bd04d887bdcca9745793b880681
diff --git a/providers/openflow/meter/src/main/java/org/onosproject/provider/of/meter/impl/OpenFlowMeterProvider.java b/providers/openflow/meter/src/main/java/org/onosproject/provider/of/meter/impl/OpenFlowMeterProvider.java
index dabeda0..e56a54c 100644
--- a/providers/openflow/meter/src/main/java/org/onosproject/provider/of/meter/impl/OpenFlowMeterProvider.java
+++ b/providers/openflow/meter/src/main/java/org/onosproject/provider/of/meter/impl/OpenFlowMeterProvider.java
@@ -20,7 +20,6 @@
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.RemovalCause;
-
import com.google.common.cache.RemovalNotification;
import com.google.common.collect.Maps;
import org.apache.felix.scr.annotations.Activate;
@@ -28,7 +27,10 @@
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
-import org.onosproject.net.DeviceId;
+import org.onosproject.core.CoreService;
+import org.onosproject.incubator.net.meter.Band;
+import org.onosproject.incubator.net.meter.DefaultBand;
+import org.onosproject.incubator.net.meter.DefaultMeter;
import org.onosproject.incubator.net.meter.Meter;
import org.onosproject.incubator.net.meter.MeterFailReason;
import org.onosproject.incubator.net.meter.MeterOperation;
@@ -36,6 +38,8 @@
import org.onosproject.incubator.net.meter.MeterProvider;
import org.onosproject.incubator.net.meter.MeterProviderRegistry;
import org.onosproject.incubator.net.meter.MeterProviderService;
+import org.onosproject.incubator.net.meter.MeterState;
+import org.onosproject.net.DeviceId;
import org.onosproject.net.provider.AbstractProvider;
import org.onosproject.net.provider.ProviderId;
import org.onosproject.openflow.controller.Dpid;
@@ -47,15 +51,23 @@
import org.projectfloodlight.openflow.protocol.OFErrorMsg;
import org.projectfloodlight.openflow.protocol.OFErrorType;
import org.projectfloodlight.openflow.protocol.OFMessage;
+import org.projectfloodlight.openflow.protocol.OFMeterBandStats;
+import org.projectfloodlight.openflow.protocol.OFMeterConfigStatsReply;
+import org.projectfloodlight.openflow.protocol.OFMeterStats;
+import org.projectfloodlight.openflow.protocol.OFMeterStatsReply;
import org.projectfloodlight.openflow.protocol.OFPortStatus;
import org.projectfloodlight.openflow.protocol.OFStatsReply;
+import org.projectfloodlight.openflow.protocol.OFStatsType;
import org.projectfloodlight.openflow.protocol.OFVersion;
import org.projectfloodlight.openflow.protocol.errormsg.OFMeterModFailedErrorMsg;
import org.slf4j.Logger;
+import java.util.Collection;
+import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
+import java.util.stream.Collectors;
import static org.slf4j.LoggerFactory.getLogger;
@@ -74,6 +86,9 @@
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected MeterProviderRegistry providerRegistry;
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected CoreService coreService;
+
private MeterProviderService providerService;
private static final AtomicLong XID_COUNTER = new AtomicLong(1);
@@ -81,8 +96,7 @@
static final int POLL_INTERVAL = 10;
static final long TIMEOUT = 30;
- private Cache<Integer, MeterOperation> pendingOperations;
- private Cache<Long, MeterOperation> pendingXid;
+ private Cache<Long, MeterOperation> pendingOperations;
private InternalMeterListener listener = new InternalMeterListener();
@@ -101,7 +115,7 @@
pendingOperations = CacheBuilder.newBuilder()
.expireAfterWrite(TIMEOUT, TimeUnit.SECONDS)
- .removalListener((RemovalNotification<Integer, MeterOperation> notification) -> {
+ .removalListener((RemovalNotification<Long, MeterOperation> notification) -> {
if (notification.getCause() == RemovalCause.EXPIRED) {
providerService.meterOperationFailed(notification.getValue(),
MeterFailReason.TIMEOUT);
@@ -149,6 +163,8 @@
return;
}
+ performOperation(sw, meterOp);
+
}
private void performOperation(OpenFlowSwitch sw, MeterOperation op) {
@@ -203,7 +219,57 @@
}
private void pushMeterStats(Dpid dpid, OFStatsReply msg) {
+ DeviceId deviceId = DeviceId.deviceId(Dpid.uri(dpid));
+ if (msg.getStatsType() == OFStatsType.METER) {
+ OFMeterStatsReply reply = (OFMeterStatsReply) msg;
+ Collection<Meter> meters = buildMeters(deviceId, reply.getEntries());
+ //TODO do meter accounting here.
+ providerService.pushMeterMetrics(deviceId, meters);
+ } else if (msg.getStatsType() == OFStatsType.METER_CONFIG) {
+ OFMeterConfigStatsReply reply = (OFMeterConfigStatsReply) msg;
+ // FIXME: Map<Long, Meter> meters = collectMeters(deviceId, reply);
+ }
+
+ }
+
+ private Map<Long, Meter> collectMeters(DeviceId deviceId,
+ OFMeterConfigStatsReply reply) {
+ return Maps.newHashMap();
+ //TODO: Needs a fix to be applied to loxi MeterConfig stat is incorrect
+ }
+
+ private Collection<Meter> buildMeters(DeviceId deviceId,
+ List<OFMeterStats> entries) {
+ return entries.stream().map(stat -> {
+ DefaultMeter.Builder builder = DefaultMeter.builder();
+ Collection<Band> bands = buildBands(stat.getBandStats());
+ builder.forDevice(deviceId)
+ .withId(stat.getMeterId())
+ //FIXME: need to encode appId in meter id, but that makes
+ // things a little annoying for debugging
+ .fromApp(coreService.getAppId("org.onosproject.core"))
+ .withBands(bands);
+ DefaultMeter meter = builder.build();
+ meter.setState(MeterState.ADDED);
+ meter.setLife(stat.getDurationSec());
+ meter.setProcessedBytes(stat.getByteInCount().getValue());
+ meter.setProcessedPackets(stat.getPacketInCount().getValue());
+ meter.setReferenceCount(stat.getFlowCount());
+
+ // marks the meter as seen on the dataplane
+ pendingOperations.invalidate(stat.getMeterId());
+ return meter;
+ }).collect(Collectors.toSet());
+ }
+
+ private Collection<Band> buildBands(List<OFMeterBandStats> bandStats) {
+ return bandStats.stream().map(stat -> {
+ DefaultBand band = DefaultBand.builder().build();
+ band.setBytes(stat.getByteBandCount().getValue());
+ band.setPackets(stat.getPacketBandCount().getValue());
+ return band;
+ }).collect(Collectors.toSet());
}
private void signalMeterError(OFMeterModFailedErrorMsg meterError,