OpenFlow Meter Provider - still need to parse meter stats
Change-Id: I4b313ea003b3801f81ec7d4823bf69de37fd8643
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
new file mode 100644
index 0000000..a9a3889
--- /dev/null
+++ b/providers/openflow/meter/src/main/java/org/onosproject/provider/of/meter/impl/MeterModBuilder.java
@@ -0,0 +1,158 @@
+/*
+ * 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.provider.of.meter.impl;
+
+import org.onosproject.net.meter.Band;
+import org.onosproject.net.meter.Meter;
+import org.onosproject.net.meter.MeterId;
+import org.projectfloodlight.openflow.protocol.OFFactory;
+import org.projectfloodlight.openflow.protocol.OFMeterFlags;
+import org.projectfloodlight.openflow.protocol.OFMeterMod;
+import org.projectfloodlight.openflow.protocol.OFMeterModCommand;
+import org.projectfloodlight.openflow.protocol.meterband.OFMeterBand;
+import org.projectfloodlight.openflow.protocol.meterband.OFMeterBandDrop;
+import org.projectfloodlight.openflow.protocol.meterband.OFMeterBandDscpRemark;
+import org.slf4j.Logger;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Builder for a meter modification.
+ */
+public final class MeterModBuilder {
+
+ private final Logger log = getLogger(getClass());
+
+ private final long xid;
+ private final OFFactory factory;
+ private Meter.Unit unit = Meter.Unit.KB_PER_SEC;
+ private boolean burst = false;
+ private Integer id;
+ private Collection<Band> bands;
+
+ public MeterModBuilder(long xid, OFFactory factory) {
+ this.xid = xid;
+ this.factory = factory;
+ }
+
+ public static MeterModBuilder builder(long xid, OFFactory factory) {
+ return new MeterModBuilder(xid, factory);
+ }
+
+ public MeterModBuilder withRateUnit(Meter.Unit unit) {
+ this.unit = unit;
+ return this;
+ }
+
+ public MeterModBuilder burst() {
+ this.burst = true;
+ return this;
+ }
+
+ public MeterModBuilder withId(MeterId meterId) {
+ this.id = meterId.id();
+ return this;
+ }
+
+ public MeterModBuilder withBands(Collection<Band> bands) {
+ this.bands = bands;
+ return this;
+ }
+
+ public OFMeterMod add() {
+ validate();
+ OFMeterMod.Builder builder = builderMeterMod();
+ builder.setCommand(OFMeterModCommand.ADD.ordinal());
+ return builder.build();
+ }
+
+ public OFMeterMod remove() {
+ validate();
+ OFMeterMod.Builder builder = builderMeterMod();
+ builder.setCommand(OFMeterModCommand.DELETE.ordinal());
+ return builder.build();
+ }
+
+ public OFMeterMod modify() {
+ validate();
+ OFMeterMod.Builder builder = builderMeterMod();
+ builder.setCommand(OFMeterModCommand.MODIFY.ordinal());
+ return builder.build();
+ }
+
+ private OFMeterMod.Builder builderMeterMod() {
+ OFMeterMod.Builder builder = factory.buildMeterMod();
+ int flags = 0;
+ if (burst) {
+ // covering loxi short comings.
+ flags |= 1 << OFMeterFlags.BURST.ordinal();
+ }
+ switch (unit) {
+ case PKTS_PER_SEC:
+ flags |= 1 << OFMeterFlags.PKTPS.ordinal();
+ break;
+ case KB_PER_SEC:
+ flags |= 1 << OFMeterFlags.KBPS.ordinal();
+ break;
+ default:
+ log.warn("Unknown unit type {}", unit);
+ }
+ builder.setBands(buildBands());
+ builder.setFlags(flags)
+ .setMeterId(id)
+ .setXid(xid);
+ return builder;
+ }
+
+ private List<OFMeterBand> buildBands() {
+ return bands.stream().map(b -> {
+ switch (b.type()) {
+ case DROP:
+ OFMeterBandDrop.Builder dropBuilder =
+ factory.meterBands().buildDrop();
+ if (burst) {
+ dropBuilder.setBurstSize(b.burst());
+ }
+ dropBuilder.setRate(b.rate());
+ return dropBuilder.build();
+ case REMARK:
+ OFMeterBandDscpRemark.Builder remarkBand =
+ factory.meterBands().buildDscpRemark();
+ if (burst) {
+ remarkBand.setBurstSize(b.burst());
+ }
+ remarkBand.setRate(b.rate());
+ remarkBand.setPrecLevel(b.dropPrecedence());
+ return remarkBand.build();
+ default:
+ log.warn("Unknown band type {}", b.type());
+ return null;
+ }
+ }).filter(value -> value != null).collect(Collectors.toList());
+ }
+
+ private void validate() {
+ checkNotNull(id, "id cannot be null");
+ checkNotNull(bands, "Must have bands");
+ checkArgument(bands.size() > 0, "Must have at lease one band");
+ }
+}