Implements policer-meter-mapping [ONOS-5867]
Changes
- Adds Policer config behavior and its implementation
- Implements id mapping
- Adds tests for OpenFlowPolicerConfig
- Adds free id api to MeterService and MeterStore
- Improves test for MeterStore
Change-Id: Ibb47375430e253131d9d9c8a60e61023ee6c8225
diff --git a/core/api/src/main/java/org/onosproject/net/behaviour/trafficcontrol/PolicerConfigurable.java b/core/api/src/main/java/org/onosproject/net/behaviour/trafficcontrol/PolicerConfigurable.java
new file mode 100644
index 0000000..189bf60
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/behaviour/trafficcontrol/PolicerConfigurable.java
@@ -0,0 +1,60 @@
+/*
+ * 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.behaviour.trafficcontrol;
+
+import com.google.common.annotations.Beta;
+import org.onosproject.net.driver.HandlerBehaviour;
+
+import java.util.Collection;
+
+/**
+ * Behaviour for handling various drivers for policer configurations.
+ */
+@Beta
+public interface PolicerConfigurable extends HandlerBehaviour {
+
+ /**
+ * Allocates a new policer id. There may not be any correspondence with the identifiers
+ * of the technology implementing the Policer in the device. Mapping (if necessary) is left
+ * to the specific implementation.
+ *
+ * @return the policer id or {@link PolicerId#NONE} if there is a failure
+ */
+ PolicerId allocatePolicerId();
+
+ /**
+ * Free a policer id. There may not be any correspondence with the identifiers
+ * of the technology implementing the Policer in the device. Mapping (if necessary) is left
+ * to the specific implementation.
+ *
+ * @param id the policer id
+ */
+ void freePolicerId(PolicerId id);
+
+ // Still WIP, throws NotImplementedException
+ void addPolicer(Policer policer);
+
+ // Still WIP, throws NotImplementedException
+ void deletePolicer(PolicerId id);
+
+ // Still WIP, throws NotImplementedException
+ Policer getPolicer(PolicerId policerId);
+
+ // Still WIP, throws NotImplementedException
+ Collection<Policer> getPolicers();
+
+}
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 c0a8671..560d94e 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
@@ -67,4 +67,21 @@
* @return a collection of meters
*/
Collection<Meter> getMeters(DeviceId deviceId);
+
+ /**
+ * Allocates a new meter id in the system.
+ *
+ * @param deviceId the device id
+ * @return the allocated meter id, null if there is an internal error
+ * or there are no meter ids available
+ */
+ MeterId allocateMeterId(DeviceId deviceId);
+
+ /**
+ * Frees the given meter id.
+ *
+ * @param deviceId the device id
+ * @param meterId the id to be freed
+ */
+ void freeMeterId(DeviceId deviceId, MeterId meterId);
}
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
new file mode 100644
index 0000000..26def99
--- /dev/null
+++ b/core/api/src/test/java/org/onosproject/net/meter/MeterServiceAdapter.java
@@ -0,0 +1,71 @@
+/*
+ * 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.meter;
+
+import org.onosproject.net.DeviceId;
+
+import java.util.Collection;
+
+/**
+ * Testing adapter for the meter service interface.
+ */
+public class MeterServiceAdapter implements MeterService {
+ @Override
+ public Meter submit(MeterRequest meter) {
+ return null;
+ }
+
+ @Override
+ public void withdraw(MeterRequest meter, MeterId meterId) {
+
+ }
+
+ @Override
+ public Meter getMeter(DeviceId deviceId, MeterId id) {
+ return null;
+ }
+
+ @Override
+ public Collection<Meter> getAllMeters() {
+ return null;
+ }
+
+ @Override
+ public Collection<Meter> getMeters(DeviceId deviceId) {
+ return null;
+ }
+
+ @Override
+ public MeterId allocateMeterId(DeviceId deviceId) {
+ return null;
+ }
+
+ @Override
+ public void freeMeterId(DeviceId deviceId, MeterId meterId) {
+
+ }
+
+ @Override
+ public void addListener(MeterListener listener) {
+
+ }
+
+ @Override
+ public void removeListener(MeterListener listener) {
+
+ }
+}
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 2bd9746..5d7965b 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
@@ -243,11 +243,18 @@
return store.getAllMeters();
}
- private MeterId allocateMeterId(DeviceId deviceId) {
+ @Override
+ public MeterId allocateMeterId(DeviceId deviceId) {
// We delegate direclty to the store
return store.allocateMeterId(deviceId);
}
+ @Override
+ public void freeMeterId(DeviceId deviceId, MeterId meterId) {
+ // We delegate direclty to the store
+ store.freeMeterId(deviceId, meterId);
+ }
+
private class InternalMeterProviderService
extends AbstractProviderService<MeterProvider>
implements MeterProviderService {
diff --git a/drivers/default/src/main/java/org/onosproject/driver/trafficcontrol/OpenFlowPolicerConfigurable.java b/drivers/default/src/main/java/org/onosproject/driver/trafficcontrol/OpenFlowPolicerConfigurable.java
new file mode 100644
index 0000000..1b8c199
--- /dev/null
+++ b/drivers/default/src/main/java/org/onosproject/driver/trafficcontrol/OpenFlowPolicerConfigurable.java
@@ -0,0 +1,140 @@
+/*
+ * 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.driver.trafficcontrol;
+
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.behaviour.trafficcontrol.Policer;
+import org.onosproject.net.behaviour.trafficcontrol.PolicerConfigurable;
+import org.onosproject.net.behaviour.trafficcontrol.PolicerId;
+import org.onosproject.net.driver.AbstractHandlerBehaviour;
+import org.onosproject.net.driver.DriverHandler;
+import org.onosproject.net.meter.MeterId;
+import org.onosproject.net.meter.MeterService;
+import org.slf4j.Logger;
+
+import java.net.URI;
+import java.util.Collection;
+
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Implementation of policer config which allows to add, delete and get policers.
+ */
+public class OpenFlowPolicerConfigurable extends AbstractHandlerBehaviour implements PolicerConfigurable {
+
+ // log
+ private final Logger log = getLogger(OpenFlowPolicerConfigurable.class);
+ // OpenFlow scheme
+ private static final String OF_SCHEME = "of";
+ // Hex
+ private static final int HEX = 16;
+
+ // Create a policer id from a meter id
+ private PolicerId getPolicerIdFromMeterId(MeterId meterId) {
+ // Create URI representing the meter id
+ URI uri = URI.create(OF_SCHEME + ":" + Long.toHexString(meterId.id()));
+ // Return the new policer id
+ return PolicerId.policerId(uri);
+ }
+
+ // Create a meter id from a policer id
+ private MeterId getMeterIdFromPolicerId(PolicerId policerId) {
+ // Get scheme specific part
+ Long id = Long.parseLong(policerId.uri().getSchemeSpecificPart(), HEX);
+ // Return the meter id
+ return MeterId.meterId(id);
+ }
+
+ @Override
+ public PolicerId allocatePolicerId() {
+ // Init step
+ DriverHandler handler = handler();
+ // First step is to get MeterService
+ MeterService meterService = handler.get(MeterService.class);
+ // There was a problem, return none
+ if (meterService == null) {
+ log.warn("MeterService is null");
+ return PolicerId.NONE;
+ }
+ // Let's get the device id
+ DeviceId deviceId = handler.data().deviceId();
+ // Double check correspondence between schemas
+ if (!deviceId.uri().getScheme().equals(OF_SCHEME)) {
+ log.warn("The device {} does not seem to be managed by OpenFlow", deviceId);
+ return PolicerId.NONE;
+ }
+ // Get a new meter id
+ MeterId meterId = meterService.allocateMeterId(deviceId);
+ // There was a problem
+ if (meterId == null) {
+ log.warn("MeterService does not provide valid ids");
+ return PolicerId.NONE;
+ }
+ // Create a policer id from the meter id
+ return getPolicerIdFromMeterId(meterId);
+ }
+
+ @Override
+ public void freePolicerId(PolicerId id) {
+ // Init step
+ DriverHandler handler = handler();
+ // First step is to get MeterService
+ MeterService meterService = handler.get(MeterService.class);
+ // There was a problem, return none
+ if (meterService == null) {
+ log.warn("MeterService is null");
+ return;
+ }
+ // Let's get the device id
+ DeviceId deviceId = handler.data().deviceId();
+ // Double check correspondence with device schema
+ if (!deviceId.uri().getScheme().equals(OF_SCHEME)) {
+ log.warn("The device {} does not seem to be managed by OpenFlow", deviceId);
+ return;
+ }
+ // Double check correspondence with pid schema
+ if (!id.uri().getScheme().equals(OF_SCHEME)) {
+ log.warn("The id {} does not seem to be OpenFlow", id);
+ return;
+ }
+ // Get the meter id
+ MeterId meterId = getMeterIdFromPolicerId(id);
+ // Free the meter id
+ meterService.freeMeterId(deviceId, meterId);
+ }
+
+ @Override
+ public void addPolicer(Policer policer) {
+ throw new UnsupportedOperationException("addPolicer not yet implemented");
+ }
+
+ @Override
+ public void deletePolicer(PolicerId id) {
+ throw new UnsupportedOperationException("deletePolicer not yet implemented");
+ }
+
+ @Override
+ public Policer getPolicer(PolicerId policerId) {
+ throw new UnsupportedOperationException("getPolicer not yet implemented");
+ }
+
+ @Override
+ public Collection<Policer> getPolicers() {
+ throw new UnsupportedOperationException("getPolicers not yet implemented");
+ }
+
+}
diff --git a/drivers/default/src/main/java/org/onosproject/driver/trafficcontrol/package-info.java b/drivers/default/src/main/java/org/onosproject/driver/trafficcontrol/package-info.java
new file mode 100644
index 0000000..165442a
--- /dev/null
+++ b/drivers/default/src/main/java/org/onosproject/driver/trafficcontrol/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+/**
+ * Implementations of the traffic control behaviours.
+ */
+package org.onosproject.driver.trafficcontrol;
diff --git a/drivers/default/src/test/java/org/onosproject/driver/trafficcontrol/OpenFlowPolicerConfigurableTest.java b/drivers/default/src/test/java/org/onosproject/driver/trafficcontrol/OpenFlowPolicerConfigurableTest.java
new file mode 100644
index 0000000..b61ec6a
--- /dev/null
+++ b/drivers/default/src/test/java/org/onosproject/driver/trafficcontrol/OpenFlowPolicerConfigurableTest.java
@@ -0,0 +1,269 @@
+/*
+ * 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.driver.trafficcontrol;
+
+import com.google.common.collect.ImmutableList;
+import org.junit.Test;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.behaviour.trafficcontrol.PolicerConfigurable;
+import org.onosproject.net.behaviour.trafficcontrol.PolicerId;
+import org.onosproject.net.driver.Behaviour;
+import org.onosproject.net.driver.DefaultDriverData;
+import org.onosproject.net.driver.Driver;
+import org.onosproject.net.driver.DriverData;
+import org.onosproject.net.driver.DriverHandler;
+import org.onosproject.net.driver.DriverService;
+import org.onosproject.net.driver.DriverServiceAdapter;
+import org.onosproject.net.meter.MeterId;
+import org.onosproject.net.meter.MeterServiceAdapter;
+
+import java.util.Comparator;
+import java.util.Set;
+import java.util.TreeSet;
+
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+import static org.onosproject.net.NetTestTools.did;
+
+/**
+ * OpenFlow Policer config test.
+ */
+public class OpenFlowPolicerConfigurableTest {
+
+ // Device id used during the tests
+ private DeviceId ofDid = did("1");
+ private DeviceId fooDid = DeviceId.deviceId(FOO_SCHEME + ":1");
+
+ // Schemes used during the tests
+ private static final String OF_SCHEME = "of";
+ private static final String FOO_SCHEME = "foo";
+
+ // Policer id used during the tests
+ private PolicerId fooPid = PolicerId.policerId(FOO_SCHEME + ":1");
+
+ // Meter ids used during the tests
+ private MeterId mid1 = MeterId.meterId(1);
+ private MeterId mid10 = MeterId.meterId(10);
+ private MeterId mid100 = MeterId.meterId(100);
+
+ // Test Driver service used during the tests
+ private DriverService driverService = new TestDriverService();
+
+ // Test Meter service used during the tests
+ private TestMeterService meterService = new TestMeterService();
+
+ /**
+ * Test allocate policer id.
+ */
+ @Test
+ public void testAllocateId() {
+ // Get device handler
+ DriverHandler driverHandler = driverService.createHandler(ofDid);
+ // Get policer config behavior
+ PolicerConfigurable policerConfigurable = driverHandler.behaviour(PolicerConfigurable.class);
+ // Get policer id
+ PolicerId policerId = policerConfigurable.allocatePolicerId();
+ // Assert that scheme is equal to OF
+ assertThat(policerId.uri().getScheme(), is(OF_SCHEME));
+ // Convert in hex the id
+ String hexId = Long.toHexString((mid1.id()));
+ // Assert that specific part contains hex of meter id
+ assertThat(policerId.uri().getSchemeSpecificPart(), is(hexId));
+ }
+
+ /**
+ * Test no corresponding device.
+ */
+ @Test
+ public void testWrongDevice() {
+ // Get device handler
+ DriverHandler driverHandler = driverService.createHandler(fooDid);
+ // Get policer config behavior
+ PolicerConfigurable policerConfigurable = driverHandler.behaviour(PolicerConfigurable.class);
+ // Get policer id
+ PolicerId policerId = policerConfigurable.allocatePolicerId();
+ // Assert that is none
+ assertThat(policerId, is(PolicerId.NONE));
+ }
+
+ /**
+ * Test meter problems.
+ */
+ @Test
+ public void testMeterNull() {
+ // Get device handler
+ DriverHandler driverHandler = driverService.createHandler(ofDid);
+ // Get policer config behavior
+ PolicerConfigurable policerConfigurable = driverHandler.behaviour(PolicerConfigurable.class);
+ // Get policer id
+ PolicerId policerId = policerConfigurable.allocatePolicerId();
+ // this works
+ assertThat(policerId.uri().getScheme(), is(OF_SCHEME));
+ String hexId = Long.toHexString((mid1.id()));
+ assertThat(policerId.uri().getSchemeSpecificPart(), is(hexId));
+ // Get another policer id
+ policerId = policerConfigurable.allocatePolicerId();
+ assertThat(policerId.uri().getScheme(), is(OF_SCHEME));
+ hexId = Long.toHexString((mid10.id()));
+ assertThat(policerId.uri().getSchemeSpecificPart(), is(hexId));
+ // Get the last policer id
+ policerId = policerConfigurable.allocatePolicerId();
+ assertThat(policerId.uri().getScheme(), is(OF_SCHEME));
+ hexId = Long.toHexString((mid100.id()));
+ assertThat(policerId.uri().getSchemeSpecificPart(), is(hexId));
+ // this does not work
+ policerId = policerConfigurable.allocatePolicerId();
+ // Assert that is none
+ assertThat(policerId, is(PolicerId.NONE));
+ }
+
+ /**
+ * Test free policer id.
+ */
+ @Test
+ public void testFreeId() {
+ // Get device handler
+ DriverHandler driverHandler = driverService.createHandler(ofDid);
+ // Get policer config behavior
+ PolicerConfigurable policerConfigurable = driverHandler.behaviour(PolicerConfigurable.class);
+ // Get policer id
+ PolicerId policerId = policerConfigurable.allocatePolicerId();
+ // this works
+ assertThat(policerId.uri().getScheme(), is(OF_SCHEME));
+ String hexId = Long.toHexString((mid1.id()));
+ assertThat(policerId.uri().getSchemeSpecificPart(), is(hexId));
+ // Verify the allocation before free
+ assertThat(meterService.availableIds.size(), is(2));
+ // Let's free the policer id
+ policerConfigurable.freePolicerId(policerId);
+ // Verify the availability after free
+ assertThat(meterService.availableIds.size(), is(3));
+ }
+
+ /**
+ * Test wrong policer id.
+ */
+ @Test
+ public void testWrongId() {
+ // Get device handler
+ DriverHandler driverHandler = driverService.createHandler(ofDid);
+ // Get policer config behavior
+ PolicerConfigurable policerConfigurable = driverHandler.behaviour(PolicerConfigurable.class);
+ // Get policer id
+ PolicerId policerId = policerConfigurable.allocatePolicerId();
+ // this works
+ assertThat(policerId.uri().getScheme(), is(OF_SCHEME));
+ String hexId = Long.toHexString((mid1.id()));
+ assertThat(policerId.uri().getSchemeSpecificPart(), is(hexId));
+ // Verify the allocation before free
+ assertThat(meterService.availableIds.size(), is(2));
+ // Update the pid with a wrong id (same id but wrong schema)
+ policerId = fooPid;
+ // Let's free the policer id
+ policerConfigurable.freePolicerId(policerId);
+ // Free does not end correctly
+ assertThat(meterService.availableIds.size(), is(2));
+ }
+
+ // Test class for driver handler
+ private class TestDriverHandler implements DriverHandler {
+
+ private final DeviceId deviceId;
+
+ TestDriverHandler(DeviceId deviceId) {
+ this.deviceId = deviceId;
+ }
+
+ @Override
+ public Driver driver() {
+ return null;
+ }
+
+ @Override
+ public DriverData data() {
+ // Just create a fake driver data
+ return new DefaultDriverData(null, deviceId);
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public <T extends Behaviour> T behaviour(Class<T> behaviourClass) {
+ // Let's create the behavior
+ PolicerConfigurable policerConfigurable = new OpenFlowPolicerConfigurable();
+ // Set the handler
+ policerConfigurable.setHandler(this);
+ // Done, return the behavior
+ return (T) policerConfigurable;
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public <T> T get(Class<T> serviceClass) {
+ return (T) meterService;
+ }
+
+ @Override
+ public boolean hasBehaviour(Class<? extends Behaviour> behaviourClass) {
+ return true;
+ }
+ }
+
+ // Test class for driver service
+ private class TestDriverService extends DriverServiceAdapter {
+
+ @Override
+ public DriverHandler createHandler(DeviceId deviceId, String... credentials) {
+ return new TestDriverHandler(deviceId);
+ }
+
+ }
+
+ // Test class for meter service
+ private class TestMeterService extends MeterServiceAdapter {
+
+ // Let's simulate a store
+ Set<MeterId> availableIds = new TreeSet<>(
+ (Comparator<MeterId>) (id1, id2) -> id1.id().compareTo(id2.id())
+ );
+
+ TestMeterService() {
+ availableIds.addAll(ImmutableList.of(mid1, mid10, mid100));
+ }
+
+ @Override
+ public MeterId allocateMeterId(DeviceId deviceId) {
+ // If there are no more ids, return null
+ if (availableIds.isEmpty()) {
+ return null;
+ }
+ // Get the next id
+ MeterId meterId = availableIds.iterator().next();
+ // Make it unavailable
+ availableIds.remove(meterId);
+ // Done, return it
+ return meterId;
+ }
+
+ @Override
+ public void freeMeterId(DeviceId deviceId, MeterId meterId) {
+ // Make the id available
+ availableIds.add(meterId);
+ }
+
+ }
+
+}
diff --git a/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkMeterManager.java b/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkMeterManager.java
index d661719..faa6ca7 100644
--- a/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkMeterManager.java
+++ b/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkMeterManager.java
@@ -183,7 +183,7 @@
.getAtomicCounter(String.format(METERCOUNTERIDENTIFIER, deviceId));
}
- private MeterId allocateMeterId(DeviceId deviceId) {
+ public MeterId allocateMeterId(DeviceId deviceId) {
long maxMeters = store.getMaxMeters(networkId(), MeterFeaturesKey.key(deviceId));
if (maxMeters == 0L) {
// MeterFeatures couldn't be retrieved, trying with queryMeters
@@ -211,6 +211,11 @@
return MeterId.meterId(id);
}
+ @Override
+ public void freeMeterId(DeviceId deviceId, MeterId meterId) {
+ // Do nothing
+ }
+
private class InternalMeterProviderService
extends AbstractVirtualProviderService<VirtualMeterProvider>
implements VirtualMeterProviderService {
diff --git a/incubator/protobuf/services/nb/src/test/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbMeterServiceTest.java b/incubator/protobuf/services/nb/src/test/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbMeterServiceTest.java
index b309479..46ade10 100644
--- a/incubator/protobuf/services/nb/src/test/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbMeterServiceTest.java
+++ b/incubator/protobuf/services/nb/src/test/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbMeterServiceTest.java
@@ -335,6 +335,16 @@
}
return meters;
}
+
+ @Override
+ public MeterId allocateMeterId(DeviceId deviceId) {
+ return null;
+ }
+
+ @Override
+ public void freeMeterId(DeviceId deviceId, MeterId meterId) {
+
+ }
}
}
diff --git a/incubator/store/src/main/java/org/onosproject/incubator/store/meter/impl/DistributedMeterStore.java b/incubator/store/src/main/java/org/onosproject/incubator/store/meter/impl/DistributedMeterStore.java
index cf4bfcb..28cc7ba 100644
--- a/incubator/store/src/main/java/org/onosproject/incubator/store/meter/impl/DistributedMeterStore.java
+++ b/incubator/store/src/main/java/org/onosproject/incubator/store/meter/impl/DistributedMeterStore.java
@@ -433,6 +433,10 @@
@Override
public void freeMeterId(DeviceId deviceId, MeterId meterId) {
+ // Avoid to free meter not allocated
+ if (meterIdGenerators.get(deviceId) < meterId.id()) {
+ return;
+ }
// Update the availability
updateMeterIdAvailability(deviceId, meterId, true);
}
diff --git a/incubator/store/src/test/java/org/onosproject/incubator/store/meter/impl/DistributedMeterStoreTest.java b/incubator/store/src/test/java/org/onosproject/incubator/store/meter/impl/DistributedMeterStoreTest.java
index f66d3ef..3c3727c 100644
--- a/incubator/store/src/test/java/org/onosproject/incubator/store/meter/impl/DistributedMeterStoreTest.java
+++ b/incubator/store/src/test/java/org/onosproject/incubator/store/meter/impl/DistributedMeterStoreTest.java
@@ -84,6 +84,7 @@
// Meter ids used during the tests
private MeterId mid1 = MeterId.meterId(1);
private MeterId mid2 = MeterId.meterId(2);
+ private MeterId mid10 = MeterId.meterId(10);
// Bands used during the tests
private Band b1 = DefaultBand.builder()
@@ -209,6 +210,10 @@
meterStore.freeMeterId(did1, mid1);
// Allocate a meter id and verify is equal to mid1
assertThat(mid1, is(meterStore.allocateMeterId(did1)));
+ // Free an id not allocated
+ meterStore.freeMeterId(did1, mid10);
+ // Allocate a meter id and verify is equal to mid2
+ assertThat(mid2, is(meterStore.allocateMeterId(did1)));
}
/**