fixes for Meter Service

Change-Id: I83d5b8a2e0a955c050f7afe96761d5709d4f9f18
This commit is contained in:
alshabib 2015-08-19 17:16:13 -07:00 committed by Gerrit Code Review
parent bad538c7c4
commit 58fe6dc46f
12 changed files with 226 additions and 22 deletions

View File

@ -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);
}
}

View File

@ -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<Meter> meters = service.getAllMeters();
if (uri != null) {
DeviceId deviceId = DeviceId.deviceId(uri);
Collection<Meter> devMeters = Collections2.filter(meters,
m -> m.deviceId().equals(deviceId));
printMeters(devMeters);
} else {
printMeters(meters);
}
}
private void printMeters(Collection<Meter> meters) {
meters.forEach(m -> print(" %s", m));
}
}

View File

@ -112,6 +112,18 @@
<ref component-id="deviceIdCompleter"/> <ref component-id="deviceIdCompleter"/>
</completers> </completers>
</command> </command>
<command>
<action class="org.onosproject.cli.net.AddMeter"/>
<completers>
<ref component-id="deviceIdCompleter"/>
</completers>
</command>
<command>
<action class="org.onosproject.cli.net.Meters"/>
<completers>
<ref component-id="deviceIdCompleter"/>
</completers>
</command>
<command> <command>
<action class="org.onosproject.cli.net.DeviceRoleCommand"/> <action class="org.onosproject.cli.net.DeviceRoleCommand"/>
<completers> <completers>

View File

@ -15,6 +15,7 @@
*/ */
package org.onosproject.net.meter; package org.onosproject.net.meter;
import static com.google.common.base.MoreObjects.toStringHelper;
import static com.google.common.base.Preconditions.checkArgument; 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 Type type;
private final long rate; private final long rate;
private final long burstSize; //TODO: should be made optional
private final short prec; private final Long burstSize;
private final Short prec;
private long packets; private long packets;
private long bytes; private long bytes;
public DefaultBand(Type type, long rate, public DefaultBand(Type type, long rate,
long burstSize, short prec) { Long burstSize, Short prec) {
this.type = type; this.type = type;
this.rate = rate; this.rate = rate;
this.burstSize = burstSize; this.burstSize = burstSize;
@ -77,6 +79,15 @@ public final class DefaultBand implements Band, BandEntry {
this.bytes = bytes; 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() { public static Builder builder() {
return new Builder(); return new Builder();
} }
@ -84,7 +95,7 @@ public final class DefaultBand implements Band, BandEntry {
public static final class Builder implements Band.Builder { public static final class Builder implements Band.Builder {
private long rate; private long rate;
private long burstSize; private Long burstSize;
private Short prec; private Short prec;
private Type type; private Type type;
@ -114,7 +125,7 @@ public final class DefaultBand implements Band, BandEntry {
@Override @Override
public DefaultBand build() { public DefaultBand build() {
checkArgument(prec != null && type == Type.REMARK, checkArgument(type != Type.REMARK && prec == null,
"Only REMARK bands can have a precendence."); "Only REMARK bands can have a precendence.");
return new DefaultBand(type, rate, burstSize, prec); return new DefaultBand(type, rate, burstSize, prec);

View File

@ -15,12 +15,13 @@
*/ */
package org.onosproject.net.meter; package org.onosproject.net.meter;
import com.google.common.collect.ImmutableSet;
import org.onosproject.core.ApplicationId; import org.onosproject.core.ApplicationId;
import org.onosproject.net.DeviceId; import org.onosproject.net.DeviceId;
import java.util.Collection; 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.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
@ -138,6 +139,18 @@ public final class DefaultMeter implements Meter, MeterEntry {
this.bytes = bytes; 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 { public static final class Builder implements Meter.Builder {
private MeterId id; private MeterId id;
@ -155,8 +168,8 @@ public final class DefaultMeter implements Meter, MeterEntry {
} }
@Override @Override
public Meter.Builder withId(long id) { public Meter.Builder withId(MeterId id) {
this.id = MeterId.meterId(id); this.id = id;
return this; return this;
} }
@ -180,7 +193,7 @@ public final class DefaultMeter implements Meter, MeterEntry {
@Override @Override
public Meter.Builder withBands(Collection<Band> bands) { public Meter.Builder withBands(Collection<Band> bands) {
this.bands = Collections.unmodifiableCollection(bands); this.bands = ImmutableSet.copyOf(bands);
return this; return this;
} }

View File

@ -130,10 +130,10 @@ public interface Meter {
/** /**
* Assigns the id to this meter. * Assigns the id to this meter.
* *
* @param id a long * @param id a meter id
* @return this * @return this
*/ */
Builder withId(long id); Builder withId(MeterId id);
/** /**
* Assigns the application that built this meter. * Assigns the application that built this meter.

View File

@ -32,7 +32,7 @@ public final class MeterId {
public static final MeterId ALL = new MeterId(0xFFFFFFFF); public static final MeterId ALL = new MeterId(0xFFFFFFFF);
private MeterId(long id) { 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; this.id = id;
} }
@ -65,6 +65,11 @@ public final class MeterId {
return Long.hashCode(id); return Long.hashCode(id);
} }
@Override
public String toString() {
return Long.toHexString(this.id);
}
public static MeterId meterId(long id) { public static MeterId meterId(long id) {
return new MeterId(id); return new MeterId(id);

View File

@ -17,6 +17,8 @@ package org.onosproject.net.meter;
import org.onosproject.event.ListenerService; import org.onosproject.event.ListenerService;
import java.util.Collection;
/** /**
* Service for add/updating and removing meters. Meters are * Service for add/updating and removing meters. Meters are
* are assigned to flow to rate limit them and provide a certain * are assigned to flow to rate limit them and provide a certain
@ -54,6 +56,13 @@ public interface MeterService
*/ */
Meter getMeter(MeterId id); Meter getMeter(MeterId id);
/**
* Fetches all the meters.
*
* @return a collection of meters
*/
Collection<Meter> getAllMeters();
/** /**
* Allocate a meter id which must be used to create the meter. * Allocate a meter id which must be used to create the meter.
* *

View File

@ -52,7 +52,7 @@ import static org.slf4j.LoggerFactory.getLogger;
/** /**
* Provides implementation of the meter service APIs. * Provides implementation of the meter service APIs.
*/ */
@Component(immediate = true) @Component(immediate = true, enabled = true)
@Service @Service
public class MeterManager extends AbstractListenerProviderRegistry<MeterEvent, MeterListener, public class MeterManager extends AbstractListenerProviderRegistry<MeterEvent, MeterListener,
MeterProvider, MeterProviderService> MeterProvider, MeterProviderService>
@ -66,7 +66,7 @@ public class MeterManager extends AbstractListenerProviderRegistry<MeterEvent, M
protected StorageService storageService; protected StorageService storageService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
MeterStore store; protected MeterStore store;
private AtomicCounter meterIdCounter; private AtomicCounter meterIdCounter;
@ -78,6 +78,8 @@ public class MeterManager extends AbstractListenerProviderRegistry<MeterEvent, M
.withName(meterIdentifier) .withName(meterIdentifier)
.build(); .build();
store.setDelegate(delegate);
onComplete = (op, result, error) -> onComplete = (op, result, error) ->
{ {
op.context().ifPresent(c -> { op.context().ifPresent(c -> {
@ -98,6 +100,7 @@ public class MeterManager extends AbstractListenerProviderRegistry<MeterEvent, M
@Deactivate @Deactivate
public void deactivate() { public void deactivate() {
store.unsetDelegate(delegate);
log.info("Stopped"); log.info("Stopped");
} }
@ -135,6 +138,11 @@ public class MeterManager extends AbstractListenerProviderRegistry<MeterEvent, M
return store.getMeter(id); return store.getMeter(id);
} }
@Override
public Collection<Meter> getAllMeters() {
return store.getAllMeters();
}
@Override @Override
public MeterId allocateMeterId() { public MeterId allocateMeterId() {
// FIXME: This will break one day. // FIXME: This will break one day.

View File

@ -18,11 +18,16 @@ package org.onosproject.incubator.store.meter.impl;
import com.google.common.collect.Collections2; import com.google.common.collect.Collections2;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import org.apache.felix.scr.annotations.Activate; 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.Deactivate;
import org.apache.felix.scr.annotations.Reference; import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality; import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;
import org.onosproject.cluster.ClusterService; import org.onosproject.cluster.ClusterService;
import org.onosproject.cluster.NodeId; 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.DefaultMeter;
import org.onosproject.net.meter.Meter; import org.onosproject.net.meter.Meter;
import org.onosproject.net.meter.MeterEvent; 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.MeterStore;
import org.onosproject.net.meter.MeterStoreDelegate; import org.onosproject.net.meter.MeterStoreDelegate;
import org.onosproject.net.meter.MeterStoreResult; import org.onosproject.net.meter.MeterStoreResult;
import org.onosproject.mastership.MastershipService;
import org.onosproject.store.AbstractStore; import org.onosproject.store.AbstractStore;
import org.onosproject.store.serializers.KryoNamespaces; import org.onosproject.store.serializers.KryoNamespaces;
import org.onosproject.store.service.ConsistentMap; 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 * A distributed meter store implementation. Meters are stored consistently
* across the cluster. * across the cluster.
*/ */
@Component(immediate = true)
@Service
public class DistributedMeterStore extends AbstractStore<MeterEvent, MeterStoreDelegate> public class DistributedMeterStore extends AbstractStore<MeterEvent, MeterStoreDelegate>
implements MeterStore { implements MeterStore {
@ -89,8 +95,14 @@ public class DistributedMeterStore extends AbstractStore<MeterEvent, MeterStoreD
meters = storageService.<MeterId, MeterData>consistentMapBuilder() meters = storageService.<MeterId, MeterData>consistentMapBuilder()
.withName(METERSTORE) .withName(METERSTORE)
.withSerializer(Serializer.using(Arrays.asList(KryoNamespaces.API), .withSerializer(Serializer.using(Arrays.asList(KryoNamespaces.API),
MeterData.class)) MeterData.class,
.build(); DefaultMeter.class,
DefaultBand.class,
Band.Type.class,
MeterState.class,
Meter.Unit.class,
MeterFailReason.class,
MeterId.class)).build();
meters.addListener(mapListener); meters.addListener(mapListener);
@ -205,13 +217,13 @@ public class DistributedMeterStore extends AbstractStore<MeterEvent, MeterStoreD
} else if (data.reason().isPresent() && local.equals(data.origin())) { } else if (data.reason().isPresent() && local.equals(data.origin())) {
MeterStoreResult msr = MeterStoreResult.fail(data.reason().get()); MeterStoreResult msr = MeterStoreResult.fail(data.reason().get());
//TODO: No future -> no friend //TODO: No future -> no friend
futures.get(data.meter().id()).complete(msr); futures.remove(data.meter().id()).complete(msr);
} }
break; break;
case ADDED: case ADDED:
case REMOVED: case REMOVED:
if (local.equals(data.origin())) { if (local.equals(data.origin())) {
futures.get(data.meter().id()).complete(MeterStoreResult.success()); futures.remove(data.meter().id()).complete(MeterStoreResult.success());
} }
break; break;
default: default:

View File

@ -116,7 +116,8 @@ public final class MeterModBuilder {
default: default:
log.warn("Unknown unit type {}", unit); log.warn("Unknown unit type {}", unit);
} }
builder.setBands(buildBands()); //FIXME: THIS WILL CHANGE IN OF1.4 to setBands.
builder.setMeters(buildBands());
builder.setFlags(flags) builder.setFlags(flags)
.setMeterId(id) .setMeterId(id)
.setXid(xid); .setXid(xid);

View File

@ -33,6 +33,7 @@ import org.onosproject.net.meter.DefaultBand;
import org.onosproject.net.meter.DefaultMeter; import org.onosproject.net.meter.DefaultMeter;
import org.onosproject.net.meter.Meter; import org.onosproject.net.meter.Meter;
import org.onosproject.net.meter.MeterFailReason; import org.onosproject.net.meter.MeterFailReason;
import org.onosproject.net.meter.MeterId;
import org.onosproject.net.meter.MeterOperation; import org.onosproject.net.meter.MeterOperation;
import org.onosproject.net.meter.MeterOperations; import org.onosproject.net.meter.MeterOperations;
import org.onosproject.net.meter.MeterProvider; 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. * 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 { public class OpenFlowMeterProvider extends AbstractProvider implements MeterProvider {
@ -245,7 +246,7 @@ public class OpenFlowMeterProvider extends AbstractProvider implements MeterProv
DefaultMeter.Builder builder = DefaultMeter.builder(); DefaultMeter.Builder builder = DefaultMeter.builder();
Collection<Band> bands = buildBands(stat.getBandStats()); Collection<Band> bands = buildBands(stat.getBandStats());
builder.forDevice(deviceId) builder.forDevice(deviceId)
.withId(stat.getMeterId()) .withId(MeterId.meterId(stat.getMeterId()))
//FIXME: need to encode appId in meter id, but that makes //FIXME: need to encode appId in meter id, but that makes
// things a little annoying for debugging // things a little annoying for debugging
.fromApp(coreService.getAppId("org.onosproject.core")) .fromApp(coreService.getAppId("org.onosproject.core"))