diff --git a/cli/src/main/java/org/onosproject/cli/net/AddMeter.java b/cli/src/main/java/org/onosproject/cli/net/AddMeter.java new file mode 100644 index 0000000000..25a7726bda --- /dev/null +++ b/cli/src/main/java/org/onosproject/cli/net/AddMeter.java @@ -0,0 +1,74 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * 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.cli.net; + +import org.apache.karaf.shell.commands.Argument; +import org.apache.karaf.shell.commands.Command; +import org.onosproject.cli.AbstractShellCommand; +import org.onosproject.core.CoreService; +import org.onosproject.net.DeviceId; +import org.onosproject.net.meter.Band; +import org.onosproject.net.meter.DefaultBand; +import org.onosproject.net.meter.DefaultMeter; +import org.onosproject.net.meter.Meter; +import org.onosproject.net.meter.MeterId; +import org.onosproject.net.meter.MeterOperation; +import org.onosproject.net.meter.MeterService; + +import java.util.Collections; + +/** + * Add a meter. + */ +@Command(scope = "onos", name = "add-meter", + description = "Adds a meter to a device (currently for testing)") +public class AddMeter extends AbstractShellCommand { + + @Argument(index = 0, name = "uri", description = "Device ID", + required = true, multiValued = false) + String uri = null; + + private final String appId = "org.onosproject.cli.addMeter"; + + @Override + protected void execute() { + MeterService service = get(MeterService.class); + CoreService coreService = get(CoreService.class); + + DeviceId deviceId = DeviceId.deviceId(uri); + + MeterId meterId = service.allocateMeterId(); + + Band band = DefaultBand.builder() + .ofType(Band.Type.DROP) + .withRate(500) + .build(); + + + Meter meter = DefaultMeter.builder() + .forDevice(deviceId) + .fromApp(coreService.registerApplication(appId)) + .withId(meterId) + .withUnit(Meter.Unit.KB_PER_SEC) + .withBands(Collections.singleton(band)) + .build(); + + MeterOperation op = new MeterOperation(meter, MeterOperation.Type.ADD, null); + + service.addMeter(op); + + } +} diff --git a/cli/src/main/java/org/onosproject/cli/net/Meters.java b/cli/src/main/java/org/onosproject/cli/net/Meters.java new file mode 100644 index 0000000000..76f3813c26 --- /dev/null +++ b/cli/src/main/java/org/onosproject/cli/net/Meters.java @@ -0,0 +1,58 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * 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.cli.net; + +import com.google.common.collect.Collections2; +import org.apache.karaf.shell.commands.Argument; +import org.apache.karaf.shell.commands.Command; +import org.onosproject.cli.AbstractShellCommand; +import org.onosproject.net.DeviceId; +import org.onosproject.net.meter.Meter; +import org.onosproject.net.meter.MeterService; + +import java.util.Collection; + +/** + * Add a meter. + */ +@Command(scope = "onos", name = "meters", + description = "Shows meters") +public class Meters extends AbstractShellCommand { + + @Argument(index = 0, name = "uri", description = "Device ID", + required = false, multiValued = false) + String uri = null; + + + @Override + protected void execute() { + MeterService service = get(MeterService.class); + + Collection meters = service.getAllMeters(); + if (uri != null) { + DeviceId deviceId = DeviceId.deviceId(uri); + Collection devMeters = Collections2.filter(meters, + m -> m.deviceId().equals(deviceId)); + printMeters(devMeters); + } else { + printMeters(meters); + } + } + + private void printMeters(Collection meters) { + meters.forEach(m -> print(" %s", m)); + } +} diff --git a/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml b/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml index 4912c82a1d..75680d8ac2 100644 --- a/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml +++ b/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml @@ -112,6 +112,18 @@ + + + + + + + + + + + + diff --git a/core/api/src/main/java/org/onosproject/net/meter/DefaultBand.java b/core/api/src/main/java/org/onosproject/net/meter/DefaultBand.java index a3a4fc2742..58a2476670 100644 --- a/core/api/src/main/java/org/onosproject/net/meter/DefaultBand.java +++ b/core/api/src/main/java/org/onosproject/net/meter/DefaultBand.java @@ -15,6 +15,7 @@ */ package org.onosproject.net.meter; +import static com.google.common.base.MoreObjects.toStringHelper; import static com.google.common.base.Preconditions.checkArgument; /** @@ -24,13 +25,14 @@ public final class DefaultBand implements Band, BandEntry { private final Type type; private final long rate; - private final long burstSize; - private final short prec; + //TODO: should be made optional + private final Long burstSize; + private final Short prec; private long packets; private long bytes; public DefaultBand(Type type, long rate, - long burstSize, short prec) { + Long burstSize, Short prec) { this.type = type; this.rate = rate; this.burstSize = burstSize; @@ -77,6 +79,15 @@ public final class DefaultBand implements Band, BandEntry { this.bytes = bytes; } + @Override + public String toString() { + return toStringHelper(this) + .add("rate", rate) + .add("burst-size", burstSize) + .add("type", type) + .add("drop-precedence", prec).toString(); + } + public static Builder builder() { return new Builder(); } @@ -84,7 +95,7 @@ public final class DefaultBand implements Band, BandEntry { public static final class Builder implements Band.Builder { private long rate; - private long burstSize; + private Long burstSize; private Short prec; private Type type; @@ -114,7 +125,7 @@ public final class DefaultBand implements Band, BandEntry { @Override public DefaultBand build() { - checkArgument(prec != null && type == Type.REMARK, + checkArgument(type != Type.REMARK && prec == null, "Only REMARK bands can have a precendence."); return new DefaultBand(type, rate, burstSize, prec); diff --git a/core/api/src/main/java/org/onosproject/net/meter/DefaultMeter.java b/core/api/src/main/java/org/onosproject/net/meter/DefaultMeter.java index 611a23eaea..ab6b444414 100644 --- a/core/api/src/main/java/org/onosproject/net/meter/DefaultMeter.java +++ b/core/api/src/main/java/org/onosproject/net/meter/DefaultMeter.java @@ -15,12 +15,13 @@ */ package org.onosproject.net.meter; +import com.google.common.collect.ImmutableSet; import org.onosproject.core.ApplicationId; import org.onosproject.net.DeviceId; import java.util.Collection; -import java.util.Collections; +import static com.google.common.base.MoreObjects.toStringHelper; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; @@ -138,6 +139,18 @@ public final class DefaultMeter implements Meter, MeterEntry { this.bytes = bytes; } + @Override + public String toString() { + return toStringHelper(this) + .add("device", deviceId) + .add("id", id) + .add("appId", appId.name()) + .add("unit", unit) + .add("isBurst", burst) + .add("state", state) + .add("bands", bands).toString(); + } + public static final class Builder implements Meter.Builder { private MeterId id; @@ -155,8 +168,8 @@ public final class DefaultMeter implements Meter, MeterEntry { } @Override - public Meter.Builder withId(long id) { - this.id = MeterId.meterId(id); + public Meter.Builder withId(MeterId id) { + this.id = id; return this; } @@ -180,7 +193,7 @@ public final class DefaultMeter implements Meter, MeterEntry { @Override public Meter.Builder withBands(Collection bands) { - this.bands = Collections.unmodifiableCollection(bands); + this.bands = ImmutableSet.copyOf(bands); return this; } diff --git a/core/api/src/main/java/org/onosproject/net/meter/Meter.java b/core/api/src/main/java/org/onosproject/net/meter/Meter.java index 5181c92475..8ea04b0d69 100644 --- a/core/api/src/main/java/org/onosproject/net/meter/Meter.java +++ b/core/api/src/main/java/org/onosproject/net/meter/Meter.java @@ -130,10 +130,10 @@ public interface Meter { /** * Assigns the id to this meter. * - * @param id a long + * @param id a meter id * @return this */ - Builder withId(long id); + Builder withId(MeterId id); /** * Assigns the application that built this meter. diff --git a/core/api/src/main/java/org/onosproject/net/meter/MeterId.java b/core/api/src/main/java/org/onosproject/net/meter/MeterId.java index f479ac5455..872de2d89e 100644 --- a/core/api/src/main/java/org/onosproject/net/meter/MeterId.java +++ b/core/api/src/main/java/org/onosproject/net/meter/MeterId.java @@ -32,7 +32,7 @@ public final class MeterId { public static final MeterId ALL = new MeterId(0xFFFFFFFF); private MeterId(long id) { - checkArgument(id <= MAX, "id cannot be larger than 0xFFFF0000"); + checkArgument(id >= MAX, "id cannot be larger than 0xFFFF0000"); this.id = id; } @@ -65,6 +65,11 @@ public final class MeterId { return Long.hashCode(id); } + @Override + public String toString() { + return Long.toHexString(this.id); + } + public static MeterId meterId(long id) { return new MeterId(id); 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 eaa2a504fd..31aa17f229 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 @@ -17,6 +17,8 @@ package org.onosproject.net.meter; import org.onosproject.event.ListenerService; +import java.util.Collection; + /** * Service for add/updating and removing meters. Meters are * are assigned to flow to rate limit them and provide a certain @@ -54,6 +56,13 @@ public interface MeterService */ Meter getMeter(MeterId id); + /** + * Fetches all the meters. + * + * @return a collection of meters + */ + Collection getAllMeters(); + /** * Allocate a meter id which must be used to create the meter. * diff --git a/incubator/net/src/main/java/org/onosproject/incubator/net/meter/impl/MeterManager.java b/incubator/net/src/main/java/org/onosproject/incubator/net/meter/impl/MeterManager.java index a0c1dfc056..4e75301637 100644 --- a/incubator/net/src/main/java/org/onosproject/incubator/net/meter/impl/MeterManager.java +++ b/incubator/net/src/main/java/org/onosproject/incubator/net/meter/impl/MeterManager.java @@ -52,7 +52,7 @@ import static org.slf4j.LoggerFactory.getLogger; /** * Provides implementation of the meter service APIs. */ -@Component(immediate = true) +@Component(immediate = true, enabled = true) @Service public class MeterManager extends AbstractListenerProviderRegistry @@ -66,7 +66,7 @@ public class MeterManager extends AbstractListenerProviderRegistry { op.context().ifPresent(c -> { @@ -98,6 +100,7 @@ public class MeterManager extends AbstractListenerProviderRegistry getAllMeters() { + return store.getAllMeters(); + } + @Override public MeterId allocateMeterId() { // FIXME: This will break one day. 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 ed7c9bff81..bc8456eabe 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 @@ -18,11 +18,16 @@ package org.onosproject.incubator.store.meter.impl; import com.google.common.collect.Collections2; import com.google.common.collect.Maps; import org.apache.felix.scr.annotations.Activate; +import org.apache.felix.scr.annotations.Component; import org.apache.felix.scr.annotations.Deactivate; import org.apache.felix.scr.annotations.Reference; import org.apache.felix.scr.annotations.ReferenceCardinality; +import org.apache.felix.scr.annotations.Service; import org.onosproject.cluster.ClusterService; import org.onosproject.cluster.NodeId; +import org.onosproject.mastership.MastershipService; +import org.onosproject.net.meter.Band; +import org.onosproject.net.meter.DefaultBand; import org.onosproject.net.meter.DefaultMeter; import org.onosproject.net.meter.Meter; import org.onosproject.net.meter.MeterEvent; @@ -33,7 +38,6 @@ import org.onosproject.net.meter.MeterState; import org.onosproject.net.meter.MeterStore; import org.onosproject.net.meter.MeterStoreDelegate; import org.onosproject.net.meter.MeterStoreResult; -import org.onosproject.mastership.MastershipService; import org.onosproject.store.AbstractStore; import org.onosproject.store.serializers.KryoNamespaces; import org.onosproject.store.service.ConsistentMap; @@ -56,6 +60,8 @@ import static org.slf4j.LoggerFactory.getLogger; * A distributed meter store implementation. Meters are stored consistently * across the cluster. */ +@Component(immediate = true) +@Service public class DistributedMeterStore extends AbstractStore implements MeterStore { @@ -89,8 +95,14 @@ public class DistributedMeterStore extends AbstractStoreconsistentMapBuilder() .withName(METERSTORE) .withSerializer(Serializer.using(Arrays.asList(KryoNamespaces.API), - MeterData.class)) - .build(); + MeterData.class, + DefaultMeter.class, + DefaultBand.class, + Band.Type.class, + MeterState.class, + Meter.Unit.class, + MeterFailReason.class, + MeterId.class)).build(); meters.addListener(mapListener); @@ -205,13 +217,13 @@ public class DistributedMeterStore extends AbstractStore no friend - futures.get(data.meter().id()).complete(msr); + futures.remove(data.meter().id()).complete(msr); } break; case ADDED: case REMOVED: if (local.equals(data.origin())) { - futures.get(data.meter().id()).complete(MeterStoreResult.success()); + futures.remove(data.meter().id()).complete(MeterStoreResult.success()); } break; default: diff --git a/providers/openflow/meter/src/main/java/org/onosproject/provider/of/meter/impl/MeterModBuilder.java b/providers/openflow/meter/src/main/java/org/onosproject/provider/of/meter/impl/MeterModBuilder.java index 930042bc3b..c07354b6f8 100644 --- a/providers/openflow/meter/src/main/java/org/onosproject/provider/of/meter/impl/MeterModBuilder.java +++ b/providers/openflow/meter/src/main/java/org/onosproject/provider/of/meter/impl/MeterModBuilder.java @@ -116,7 +116,8 @@ public final class MeterModBuilder { default: log.warn("Unknown unit type {}", unit); } - builder.setBands(buildBands()); + //FIXME: THIS WILL CHANGE IN OF1.4 to setBands. + builder.setMeters(buildBands()); builder.setFlags(flags) .setMeterId(id) .setXid(xid); 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 2e1611d1f8..f5a777be8e 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 @@ -33,6 +33,7 @@ import org.onosproject.net.meter.DefaultBand; import org.onosproject.net.meter.DefaultMeter; import org.onosproject.net.meter.Meter; import org.onosproject.net.meter.MeterFailReason; +import org.onosproject.net.meter.MeterId; import org.onosproject.net.meter.MeterOperation; import org.onosproject.net.meter.MeterOperations; import org.onosproject.net.meter.MeterProvider; @@ -74,7 +75,7 @@ import static org.slf4j.LoggerFactory.getLogger; /** * Provider which uses an OpenFlow controller to handle meters. */ -@Component(immediate = true, enabled = false) +@Component(immediate = true, enabled = true) public class OpenFlowMeterProvider extends AbstractProvider implements MeterProvider { @@ -245,7 +246,7 @@ public class OpenFlowMeterProvider extends AbstractProvider implements MeterProv DefaultMeter.Builder builder = DefaultMeter.builder(); Collection bands = buildBands(stat.getBandStats()); builder.forDevice(deviceId) - .withId(stat.getMeterId()) + .withId(MeterId.meterId(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"))