[VOL-4765] Adding reference check on pending_add flows before deleting meter
Change-Id: I7581975932b14c9350815f4db9a7cca843b3053c
diff --git a/impl/src/main/java/org/opencord/olt/impl/OltMeterService.java b/impl/src/main/java/org/opencord/olt/impl/OltMeterService.java
index c6f2709..133a2d2 100644
--- a/impl/src/main/java/org/opencord/olt/impl/OltMeterService.java
+++ b/impl/src/main/java/org/opencord/olt/impl/OltMeterService.java
@@ -17,12 +17,18 @@
package org.opencord.olt.impl;
import com.google.common.collect.ImmutableMap;
+import org.onlab.util.Identifier;
import org.onlab.util.KryoNamespace;
import org.onlab.util.Tools;
import org.onosproject.cfg.ComponentConfigService;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.net.DeviceId;
+import org.onosproject.net.flow.FlowEntry;
+import org.onosproject.net.flow.FlowRule;
+import org.onosproject.net.flow.FlowRuleService;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.flow.instructions.Instructions;
import org.onosproject.net.meter.Band;
import org.onosproject.net.meter.DefaultBand;
import org.onosproject.net.meter.DefaultMeterRequest;
@@ -57,6 +63,7 @@
import org.slf4j.Logger;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.Iterator;
@@ -71,6 +78,7 @@
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
+import java.util.stream.StreamSupport;
import static com.google.common.base.Strings.isNullOrEmpty;
import static org.onlab.util.Tools.get;
@@ -93,6 +101,9 @@
@Reference(cardinality = ReferenceCardinality.MANDATORY)
protected StorageService storageService;
+ @Reference(cardinality = ReferenceCardinality.MANDATORY)
+ protected FlowRuleService flowRuleService;
+
@Reference(cardinality = ReferenceCardinality.OPTIONAL,
bind = "bindSadisService",
unbind = "unbindSadisService",
@@ -585,9 +596,16 @@
meter.id(), meter.deviceId());
incrementMeterCount(meter.deviceId(), key);
if (pendingRemoveMeters.get(meter.deviceId())
- .get(key).get() == zeroReferenceMeterCount) {
+ .get(key).get() >= zeroReferenceMeterCount) {
// only delete the meters if the app is configured to do so
if (deleteMeters) {
+ // Check if there's any pending flow referencing that meter.
+ if (isUsedByPendingAddFlow(meter)) {
+ log.info("Meter {} is still being referenced by pending flows, avoiding removal.",
+ meter.id());
+ removeMeterCount(meter, key);
+ return;
+ }
log.info("Meter {} on device {} is unused, removing it", meter.id(), meter.deviceId());
deleteMeter(meter.deviceId(), meter.id());
}
@@ -600,6 +618,18 @@
});
}
+ private boolean isUsedByPendingAddFlow(Meter meter) {
+ Long meterId = meter.id().id();
+ Iterable<FlowEntry> pendingAddFlows = flowRuleService.getFlowEntriesByState(meter.deviceId(),
+ FlowEntry.FlowEntryState.PENDING_ADD);
+ return StreamSupport.stream(pendingAddFlows.spliterator(), true)
+ .map(FlowRule::treatment)
+ .map(TrafficTreatment::meters)
+ .flatMap(Collection::parallelStream)
+ .map(Instructions.MeterInstruction::meterId)
+ .map(Identifier::id)
+ .anyMatch(meterId::equals);
+ }
private void removeMeterCount(Meter meter, MeterKey key) {
pendingRemoveMeters.computeIfPresent(meter.deviceId(),
(id, meters) -> {