Introducing BandwidthProfileConfigBehaviour to manage policers/markers

- Creating BandwidthProfile Class to represent generic policers/markers
- BandwidthProfile can be Single/Two Rate, Two/Three Color depending on parameters
- Including fromMeter() method to convert a Meter into a BandwidthProfile
- Adding unit tests for BandwidthProfile class
- Creating BandwidthProfileAction class to represent a color (green/yellow/red) action
- BandwidthProfileAction allows remarking one of: DSCP class, IP precedence, Drop precedence
- Adding unit tests for BandwidthProfileAction class
- Creating DscpClass and IPPrecedence Enums and unit tests in org.onlab.packet
- Adding kBps/MBps/GBps methods in org.onlab.util.Bandwidth class

Change-Id: I54156329a527ebd9165d8f55e03e0782925caa2b
diff --git a/core/api/src/main/java/org/onosproject/net/behaviour/BandwidthProfile.java b/core/api/src/main/java/org/onosproject/net/behaviour/BandwidthProfile.java
new file mode 100644
index 0000000..2a934fd
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/behaviour/BandwidthProfile.java
@@ -0,0 +1,551 @@
+/*
+ * Copyright 2016-present 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.net.behaviour;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.MoreObjects;
+import org.onlab.packet.DscpClass;
+import org.onlab.util.Bandwidth;
+import org.onosproject.net.meter.Band;
+import org.onosproject.net.meter.Meter;
+import static org.onosproject.net.behaviour.BandwidthProfileAction.Action;
+
+import java.util.Iterator;
+import java.util.Objects;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Implementation of a generic bandwidth profile (marker/policer).
+ */
+@Beta
+public final class BandwidthProfile {
+
+    /**
+     * Denotes the type of the bandwidth profile.
+     */
+    enum Type {
+        /**
+         * Corresponds to a Single Rate Two Color Marker/Policer.
+         */
+        sr2CM,
+
+        /**
+         * Corresponds to a Single Rate Three Color Marker/Policer.
+         * (IETF RFC 2697)
+         */
+        srTCM,
+
+        /**
+         * Corresponds to a Two Rate Three Color Marker/Policer.
+         * (IETF RFC 2698)
+         */
+        trTCM
+    }
+
+    private final String name;
+    private final Bandwidth cir;
+    private final Bandwidth pir;
+    private final Integer cbs;
+    private final Integer pbs;
+    private final Integer ebs;
+    private final BandwidthProfileAction greenAction;
+    private final BandwidthProfileAction yellowAction;
+    private final BandwidthProfileAction redAction;
+    private final boolean colorAware;
+
+    /**
+     * BandwidthProfile constructor.
+     *
+     * @param name the profile name
+     * @param cir the committed information rate (CIR)
+     * @param cbs the committed burst size (CBS) measured in bytes
+     * @param pir the peak information rate (PIR)
+     * @param pbs the peak burst size (PBS) measured in bytes
+     * @param greenAction the action to be taken for traffic that conforms
+     *                    to the CIR/CBS
+     * @param yellowAction srTCM: the action to be taken for traffic that
+     *                     conforms to the EBS but not to the CIR/CBS
+     *                     trTCM: the action to be taken for traffic that
+     *                     conforms to the PIR/PBS but not to the CIR/CBS
+     * @param redAction sr2CM: the action to be taken for traffic that
+     *                  does not conform to the CIR/CBS
+     *                  srTCM: the action to be taken for traffic that
+     *                  does not conform to the EBS
+     *                  trTCM: the action to be taken for traffic that
+     *                  does not conform to the PIR/PBS
+     * @param colorAware indicates whether the profile considers incoming
+     *                   traffic as already colored
+     */
+    private BandwidthProfile(String name,
+                             Bandwidth cir, Bandwidth pir,
+                             Integer cbs, Integer pbs, Integer ebs,
+                             BandwidthProfileAction greenAction,
+                             BandwidthProfileAction yellowAction,
+                             BandwidthProfileAction redAction,
+                             boolean colorAware) {
+        this.name = name;
+        this.cir = cir;
+        this.pir = pir;
+        this.cbs = cbs;
+        this.pbs = pbs;
+        this.ebs = ebs;
+        this.greenAction = greenAction;
+        this.yellowAction = yellowAction;
+        this.redAction = redAction;
+        this.colorAware = colorAware;
+    }
+
+    /**
+     * Obtains the name of this bandwidth profile.
+     *
+     * @return the bandwidth profile name
+     */
+    public String name() {
+        return name;
+    }
+
+    /**
+     * Obtains the committed information rate (CIR) of this bandwidth profile.
+     *
+     * @return the CIR of the bandwidth profile
+     */
+    public Bandwidth cir() {
+        return cir;
+    }
+
+    /**
+     * Obtains the peak information rate (PIR) of this bandwidth profile.
+     * If this profile does not have a PIR, null is returned.
+     *
+     * @return the PIR of the profile; null if the profile does not have a PIR
+     */
+    public Bandwidth pir() {
+        return pir;
+    }
+
+    /**
+     * Obtains the committed burst size (CBS) of this bandwidth profile.
+     * The CBS is measured in bytes.
+     * If this profile does not have a CBS, null is returned.
+     *
+     * @return the CBS of the profile (bytes);
+     * null if the profile does not have a CBS
+     */
+    public Integer cbs() {
+        return cbs;
+    }
+
+    /**
+     * Obtains the peak burst size (PBS) of this bandwidth profile.
+     * The PBS is measured in bytes.
+     * If this profile does not have a PBS, null is returned.
+     *
+     * @return the PBS of the bandwidth profile (bytes);
+     * null if the profile does not have a PBS
+     */
+    public Integer pbs() {
+        return pbs;
+    }
+
+    /**
+     * Obtains the excess burst size (EBS) of this bandwidth profile.
+     * The EBS is measured in bytes.
+     * If this profile does not have an EBS, null is returned.
+     *
+     * @return the EBS of the bandwidth profile (bytes);
+     * null if the profile does not have an EBS
+     */
+    public Integer ebs() {
+        return ebs;
+    }
+
+    /**
+     * Obtains the action to be taken for traffic marked as green.
+     * Green color marking is applied to traffic that conforms to the CIR/CBS.
+     *
+     * @return the action to be taken for traffic marked as green
+     */
+    public BandwidthProfileAction greenAction() {
+        return greenAction;
+    }
+
+    /**
+     * Obtains the action to be taken for traffic marked as yellow.
+     * Yellow color marking is applied to traffic that does not conform
+     * to the CIR/CBS but conforms to one of:
+     * <ul>
+     *     <li>EBS (srTCM type)</li>
+     *     <li>PIR/PBS (trTCM type)</li>
+     * </ul>
+     * If this profile does has neither EBS or PIR/PBS, null is returned.
+     *
+     * @return the action to be taken for traffic marked as yellow;
+     * null if neither EBS nor PIR/PBS are defined
+     */
+    public BandwidthProfileAction yellowAction() {
+        return yellowAction;
+    }
+
+    /**
+     * Obtains the action to be taken for traffic marked as red.
+     * Red color marking is applied to traffic that does not conform
+     * to one of the following:
+     * <ul>
+     *     <li>CIR/CBS (sr2CM type)</li>
+     *     <li>EBS (srTCM type)</li>
+     *     <li>PIR/PBS (trTCM type)</li>
+     * </ul>
+     *
+     * @return the action to be taken for traffic marked as red
+     */
+    public BandwidthProfileAction redAction() {
+        return redAction;
+    }
+
+    /**
+     * Obtains the color-aware mode of the bandwidth profile.
+     *
+     * @return true if the bandwidth profile is color-aware; false otherwise
+     */
+    public boolean colorAware() {
+        return colorAware;
+    }
+
+    /**
+     * Obtains the bandwidth profile type depending on the profile parameters.
+     * <ul>
+     *     <li>When PIR is defined, the profile corresponds to a
+     *     Two Rate Three Color Marker (trTCM)</li>
+     *     <li>When EBS is defined, the profile corresponds to a
+     *     Single Rate Three Color Marker (srTCM)</li>
+     *     <li>When neither PIR nor EBS are defined, the profile corresponds to a
+     *     Single Rate Two Color Marker/Policer (sr2CM)</li>
+     * </ul>
+     *
+     * @return the bandwidth profile type
+     */
+    public Type type() {
+        return pir != null ? Type.trTCM :
+                ebs != null ? Type.srTCM : Type.sr2CM;
+    }
+
+    /**
+     * Creates a bandwidth profile based on the parameters of a Meter.
+     * NOTE: The dropPrecedence in the Meter is interpreted as
+     * the DSCP class to set on the packet
+     *
+     * @param meter the Meter to be used for creating the bandwidth profile
+     * @return the bandwidth profile created
+     */
+    public static BandwidthProfile fromMeter(Meter meter) {
+
+        checkNotNull(meter);
+        checkArgument(meter.bands().size() <= 2,
+                      "Meter must have no more than two bands.");
+
+        Iterator<Band> bandIterator = meter.bands().iterator();
+        Band bandOne = bandIterator.next();
+        Band bandTwo = bandIterator.hasNext() ? bandIterator.next() : null;
+
+        // Assign values to yellowBand and redBand depending on
+        // the number of bands in the meter.
+        // If only one band exists it will be designated as the redBand.
+        // If two bands exist, the one with the lower rate will be
+        // the yellowBand and the other the redBand.
+        Band yellowBand = (bandTwo == null ? null :
+                bandTwo.rate() > bandOne.rate() ? bandOne : bandTwo);
+        Band redBand = (bandTwo == null ? bandOne :
+                yellowBand == bandOne ? bandTwo : bandOne);
+
+        BandwidthProfile.Builder bandwidthProfileBuilder = new Builder()
+                // Consider the meter id as the bandwidth profile name
+                .name(meter.id().toString())
+                .colorAware(false)
+                // The implicit green action is pass
+                .greenAction(getBuilder(Action.PASS).build());
+
+        if (yellowBand != null) {
+            // Try to add yellow action; CIR/CBS will be obtained from
+            // yellowBand and PIR/PBS from redBand.
+            BandwidthProfileAction yellowAction =
+                    getBwProfileActionFromBand(yellowBand);
+            checkNotNull(yellowAction,
+                         "Could not obtain yellow action from meter band");
+            bandwidthProfileBuilder
+                    .cir(Bandwidth.kBps(yellowBand.rate()))
+                    .cbs(yellowBand.burst() == null ? null :
+                                 yellowBand.burst().intValue())
+                    .pir(Bandwidth.kBps(redBand.rate()))
+                    .pbs(redBand.burst() == null ? null :
+                                 redBand.burst().intValue())
+                    .yellowAction(yellowAction);
+        } else {
+            // No yellow action to add; CIR/CBS will be obtained from redBand
+            bandwidthProfileBuilder
+                    .cir(Bandwidth.kBps(redBand.rate()))
+                    .cbs(redBand.burst() == null ? null :
+                                 redBand.burst().intValue());
+        }
+
+        // Try to add red action in any case
+        BandwidthProfileAction redAction =
+                getBwProfileActionFromBand(redBand);
+        checkNotNull(redAction,
+                     "Could not obtain red action from meter band");
+
+        return bandwidthProfileBuilder
+                .redAction(redAction)
+                .build();
+    }
+
+    private static BandwidthProfileAction.Builder getBuilder(Action action) {
+        return BandwidthProfileAction.builder().action(action);
+    }
+
+    private static BandwidthProfileAction getBwProfileActionFromBand(Band band) {
+        checkNotNull(band.type(),
+                     "Could not obtain BW profile: Meter band type is null");
+        Action action = null;
+        if (band.type().equals(Band.Type.DROP)) {
+            action = Action.DISCARD;
+        } else if (band.type().equals(Band.Type.REMARK)) {
+            action = Action.REMARK;
+        }
+        checkNotNull(action,
+                     "Could not obtain BW profile: Invalid meter band type");
+        BandwidthProfileAction.Builder actionBuilder = getBuilder(action);
+        if (band.type().equals(Band.Type.REMARK)) {
+            checkNotNull(band.dropPrecedence(),
+                         "Could not obtain DSCP class from meter band");
+            actionBuilder.dscpClass(DscpClass.fromShort(band.dropPrecedence()));
+        }
+        return actionBuilder.build();
+    }
+
+    /**
+     * Returns a new builder.
+     *
+     * @return new builder
+     */
+    public static Builder builder() {
+        return new Builder();
+    }
+
+    /**
+     * Builder of BandwidthProfile entities.
+     */
+    public static final class Builder {
+
+        private String name;
+        private Bandwidth cir;
+        private Bandwidth pir;
+        private Integer cbs;
+        private Integer pbs;
+        private Integer ebs;
+        private BandwidthProfileAction greenAction;
+        private BandwidthProfileAction yellowAction;
+        private BandwidthProfileAction redAction;
+        private boolean colorAware;
+
+        /**
+         * Sets the name of this bandwidth profile builder.
+         *
+         * @param name the builder name to set
+         * @return this builder instance
+         */
+        public Builder name(String name) {
+            this.name = name;
+            return this;
+        }
+
+        /**
+         * Sets the committed information rate (CIR) of this builder.
+         *
+         * @param cir the builder CIR to set
+         * @return this builder instance
+         */
+        public Builder cir(Bandwidth cir) {
+            this.cir = cir;
+            return this;
+        }
+
+        /**
+         * Sets the peak information rate (PIR) of this builder.
+         *
+         * @param pir the builder PIR to set
+         * @return this builder instance
+         */
+        public Builder pir(Bandwidth pir) {
+            this.pir = pir;
+            return this;
+        }
+
+        /**
+         * Sets the committed burst size (CBS) of this builder.
+         * The CBS is measured in bytes.
+         *
+         * @param cbs the builder CBS to set
+         * @return this builder instance
+         */
+        public Builder cbs(Integer cbs) {
+            this.cbs = cbs;
+            return this;
+        }
+
+        /**
+         * Sets the peak burst size (PBS) of this builder.
+         * The PBS is measured in bytes.
+         *
+         * @param pbs the builder CBS to set
+         * @return this builder instance
+         */
+        public Builder pbs(Integer pbs) {
+            this.pbs = pbs;
+            return this;
+        }
+
+        /**
+         * Sets the excess burst size (EBS) of this builder.
+         * The EBS is measured in bytes.
+         *
+         * @param ebs the builder EBS to set
+         * @return this builder instance
+         */
+        public Builder ebs(Integer ebs) {
+            this.ebs = ebs;
+            return this;
+        }
+
+        /**
+         * Sets the green action of this builder.
+         *
+         * @param greenAction the builder green action to set
+         * @return this builder instance
+         */
+        public Builder greenAction(BandwidthProfileAction greenAction) {
+            this.greenAction = greenAction;
+            return this;
+        }
+
+        /**
+         * Sets the yellow action of this builder.
+         *
+         * @param yellowAction the builder green action to set
+         * @return this builder instance
+         */
+        public Builder yellowAction(BandwidthProfileAction yellowAction) {
+            this.yellowAction = yellowAction;
+            return this;
+        }
+
+        /**
+         * Sets the red action of this builder.
+         *
+         * @param redAction the builder green action to set
+         * @return this builder instance
+         */
+        public Builder redAction(BandwidthProfileAction redAction) {
+            this.redAction = redAction;
+            return this;
+        }
+
+        /**
+         * Sets the color-aware mode of this builder.
+         *
+         * @param colorAware true if profile to be build is color-aware;
+         *                   false otherwise
+         * @return this builder instance
+         */
+        public Builder colorAware(boolean colorAware) {
+            this.colorAware = colorAware;
+            return this;
+        }
+
+        /**
+         * Builds a new BandwidthProfile instance.
+         * based on this builder's parameters
+         *
+         * @return a new BandwidthProfile instance
+         */
+        public BandwidthProfile build() {
+            checkNotNull(name, "Bandwidth profile must have a name");
+            checkNotNull(cir, "Bandwidth profile must have a CIR");
+            checkNotNull(greenAction,
+                         "Bandwidth profile must have a green action");
+            checkNotNull(redAction,
+                         "Bandwidth profile must have a red action");
+            checkArgument(pir != null || pbs == null,
+                          "Bandwidth profile cannot have PBS without PIR");
+            checkArgument(pir == null || ebs == null,
+                          "Bandwidth profile cannot have both PIR and EBS");
+            checkArgument(yellowAction == null && pir == null && ebs == null ||
+                                  yellowAction != null &&
+                                          (pir != null ^ ebs != null),
+                          "Bandwidth profile must have a yellow action only " +
+                                  "when either PIR or EBS are defined");
+            return new BandwidthProfile(name,
+                                        cir, pir, cbs, pbs, ebs,
+                                        greenAction, yellowAction, redAction,
+                                        colorAware);
+        }
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(cir, pir, cbs, pbs, ebs,
+                            greenAction, yellowAction, redAction,
+                            colorAware);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof BandwidthProfile) {
+            final BandwidthProfile that = (BandwidthProfile) obj;
+            return this.getClass() == that.getClass() &&
+                    Objects.equals(this.cir, that.cir) &&
+                    Objects.equals(this.pir, that.pir)  &&
+                    Objects.equals(this.cbs, that.cbs) &&
+                    Objects.equals(this.pbs, that.pbs)  &&
+                    Objects.equals(this.ebs, that.ebs) &&
+                    Objects.equals(this.greenAction, that.greenAction)  &&
+                    Objects.equals(this.yellowAction, that.yellowAction) &&
+                    Objects.equals(this.redAction, that.redAction) &&
+                    Objects.equals(this.colorAware, that.colorAware);
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(getClass())
+                .add("name", name)
+                .add("cir", cir)
+                .add("pir", pir)
+                .add("cbs", cbs)
+                .add("pbs", pbs)
+                .add("ebs", ebs)
+                .add("greenAction", greenAction)
+                .add("yellowAction", yellowAction)
+                .add("redAction", redAction)
+                .add("colorAware", colorAware)
+                .toString();
+    }
+}
diff --git a/core/api/src/main/java/org/onosproject/net/behaviour/BandwidthProfileAction.java b/core/api/src/main/java/org/onosproject/net/behaviour/BandwidthProfileAction.java
new file mode 100644
index 0000000..ae6a153
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/behaviour/BandwidthProfileAction.java
@@ -0,0 +1,223 @@
+/*
+ * Copyright 2016-present 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.net.behaviour;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.MoreObjects;
+import org.onlab.packet.DscpClass;
+import org.onlab.packet.IPPrecedence;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.Objects;
+
+/**
+ * Represents an action to be taken by a marker/policer.
+ */
+@Beta
+public final class BandwidthProfileAction {
+
+    /**
+     * Denotes the type of action to be taken.
+     */
+    public enum Action {
+        /**
+         * Traffic is allowed to pass unmodified.
+         */
+        PASS,
+
+        /**
+         * Traffic is allowed to pass after being appropriately remarked.
+         */
+        REMARK,
+
+        /**
+         * Traffic is dropped.
+         */
+        DISCARD
+    }
+
+    private final Action action;
+    private final DscpClass dscpClass;
+    private final IPPrecedence ipPrecedence;
+    private final Short dropPrecedence;
+
+    private BandwidthProfileAction(Action action,
+                                   DscpClass dscpClass,
+                                   IPPrecedence ipPrecedence,
+                                   Short dropPrecedence) {
+        this.action = action;
+        this.dscpClass = dscpClass;
+        this.ipPrecedence = ipPrecedence;
+        this.dropPrecedence = dropPrecedence;
+    }
+
+    /**
+     * Obtains the type of this bandwidth profile action object.
+     *
+     * @return the bandwidth profile action type
+     */
+    public Action getAction() {
+        return this.action;
+    }
+
+    /**
+     * Obtains the DSCP class corresponding to the REMARK action.
+     * If this is not a REMARK action or if another field is remarked
+     * null is returned.
+     *
+     * @return the DSCP class for the action; may be null
+     */
+    public DscpClass getDscpClass() {
+        return this.dscpClass;
+    }
+
+    /**
+     * Obtains the IP precedence corresponding to the REMARK action.
+     * If this is not a REMARK action or if another field is remarked
+     * null is returned.
+     *
+     * @return the IP precedence for the action; may be null
+     */
+    public IPPrecedence getIpPrecedence() {
+        return this.ipPrecedence;
+    }
+
+    /**
+     * Obtains the drop precedence corresponding to the REMARK action.
+     * If this is not a REMARK action or if another field is remarked
+     * null is returned.
+     *
+     * @return the drop precedence for the action; may be null
+     */
+    public Short getDropPrecedence() {
+        return this.dropPrecedence;
+    }
+
+    /**
+     * Returns a new builder.
+     *
+     * @return new builder
+     */
+    public static Builder builder() {
+        return new Builder();
+    }
+
+    /**
+     * Builder of BandwidthProfileAction entities.
+     */
+    public static final class Builder {
+
+        private Action action;
+        private DscpClass dscpClass;
+        private IPPrecedence ipPrecedence;
+        private Short dropPrecedence;
+
+        /**
+         * Sets the type of this builder.
+         *
+         * @param action the builder type to set
+         * @return this builder instance
+         */
+        public Builder action(Action action) {
+            this.action = action;
+            return this;
+        }
+
+        /**
+         * Sets the DSCP class of this builder.
+         *
+         * @param dscpClass the builder DSCP class to set
+         * @return this builder instance
+         */
+        public Builder dscpClass(DscpClass dscpClass) {
+            this.dscpClass = dscpClass;
+            return this;
+        }
+
+        /**
+         * Sets the IP precedence of this builder.
+         *
+         * @param ipPrecedence the builder IP precedence to set
+         * @return this builder instance
+         */
+        public Builder ipPrecedence(IPPrecedence ipPrecedence) {
+            this.ipPrecedence = ipPrecedence;
+            return this;
+        }
+
+        /**
+         * Sets the drop precedence of this builder.
+         *
+         * @param dropPrecedence the drop IP precedence to set
+         * @return this builder instance
+         */
+        public Builder dropPrecedence(Short dropPrecedence) {
+            this.dropPrecedence = dropPrecedence;
+            return this;
+        }
+
+        /**
+         * Builds a new BandwidthProfileAction based on builder's parameters.
+         *
+         * @return a new BandwidthProfileAction instance
+         */
+        public BandwidthProfileAction build() {
+            checkNotNull(action);
+            checkArgument(!action.equals(Action.REMARK) ||
+                                  (dscpClass != null ^
+                                          ipPrecedence != null ^
+                                          dropPrecedence != null),
+                          "Exactly one remark type must be defined");
+            return new BandwidthProfileAction(action,
+                                              dscpClass,
+                                              ipPrecedence,
+                                              dropPrecedence);
+        }
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(action, dscpClass, ipPrecedence, dropPrecedence);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof BandwidthProfileAction) {
+            final BandwidthProfileAction that = (BandwidthProfileAction) obj;
+            return this.getClass() == that.getClass() &&
+                    Objects.equals(this.action, that.action) &&
+                    Objects.equals(this.dscpClass, that.dscpClass) &&
+                    Objects.equals(this.ipPrecedence, that.ipPrecedence) &&
+                    Objects.equals(this.dropPrecedence, that.dropPrecedence);
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(getClass())
+                .add("action", action == null ? null : action.name())
+                .add("dscpClass", dscpClass == null ? null : dscpClass.name())
+                .add("ipPrecedence", ipPrecedence)
+                .add("dropPrecedence", dropPrecedence)
+                .toString();
+    }
+}
diff --git a/core/api/src/main/java/org/onosproject/net/behaviour/BandwidthProfileConfigBehaviour.java b/core/api/src/main/java/org/onosproject/net/behaviour/BandwidthProfileConfigBehaviour.java
new file mode 100644
index 0000000..bd222cd
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/behaviour/BandwidthProfileConfigBehaviour.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2016-present 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.net.behaviour;
+
+import com.google.common.annotations.Beta;
+import org.onosproject.net.driver.HandlerBehaviour;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Collection;
+
+/**
+ * Means to configure bandwidth profiles on devices.
+ */
+@Beta
+public interface BandwidthProfileConfigBehaviour extends HandlerBehaviour {
+    /**
+     * Adds a new bandwidth profile on the device.
+     * If a profile with the same name already exists on the device, the profile
+     * is not added.
+     *
+     * @param bwProfile the bandwidth profile to add
+     * @return true, if the profile was added successfully; false otherwise
+     */
+    default boolean addBandwidthProfile(BandwidthProfile bwProfile) {
+        return addBandwidthProfile(Collections.singletonList(bwProfile));
+    }
+
+    /**
+     * Adds new bandwidth profiles on the device.
+     * If profiles with the same names already exist on the device, the
+     * conflicting profiles are not added.
+     *
+     * @param bwProfiles the bandwidth profiles to add
+     * @return true, if any of the profiles were added successfully;
+     * false otherwise
+     */
+    boolean addBandwidthProfile(Collection<BandwidthProfile> bwProfiles);
+
+    /**
+     * Removes an existing bandwidth profile from a device.
+     * Returns false if the profile does not exist on the device.
+     *
+     * @param profileName the name of the profile to remove from the device
+     * @return true, if the profile was removed successfully; false otherwise
+     */
+    default boolean removeBandwidthProfile(String profileName) {
+        return removeBandwidthProfile(Collections.singletonList(profileName));
+    }
+
+    /**
+     * Removes existing bandwidth profiles from a device.
+     * Returns false if none of the profiles exist on the device.
+     *
+     * @param profileNames the names of the profiles to remove from the device
+     * @return true, if any of the profiles were removed successfully;
+     * false otherwise
+     */
+    boolean removeBandwidthProfile(Collection<String> profileNames);
+
+    /**
+     * Removes all existing bandwidth profiles from a device.
+     * Returns true if no profiles exist on the device.
+     *
+     * @return true, if all profiles were removed successfully; false otherwise
+     */
+    boolean removeAllBandwidthProfiles();
+
+    /**
+     * Updates an already configured bandwidth profile on the device.
+     * Returns false if the profile does not exist on the device.
+     *
+     * @param bwProfile the updated bandwidth profile
+     * @return true, if the profile was updated successfully; false otherwise
+     */
+    default boolean updateBandwidthProfile(BandwidthProfile bwProfile) {
+        return updateBandwidthProfile(Collections.singletonList(bwProfile));
+    }
+
+    /**
+     * Updates already configured bandwidth profiles on the device.
+     * Returns false if none of the profiles exist on the device.
+     *
+     * @param bwProfiles the updated bandwidth profile
+     * @return true, if any of the profiles were updated successfully;
+     * false otherwise
+     */
+    boolean updateBandwidthProfile(
+            Collection<BandwidthProfile> bwProfiles);
+
+    /**
+     * Obtains an already configured bandwidth profile from the device.
+     *
+     * @param profileName the name of the profile to obtain from the device
+     * @return the bandwidth profile; null if the profile does not exist
+     * @throws IOException if profile could not be obtained due to
+     * communication issues with the device
+     */
+    BandwidthProfile getBandwidthProfile(String profileName) throws IOException;
+
+    /**
+     * Obtains all already configured bandwidth profiles from the device.
+     *
+     * @return the bandwidth profiles; empty collection if no profiles exist
+     * @throws IOException if profiles could not be obtained due to
+     * communication issues with the device
+     */
+    Collection<BandwidthProfile> getAllBandwidthProfiles() throws IOException;
+}
diff --git a/core/api/src/test/java/org/onosproject/net/behaviour/BandwidthProfileActionTest.java b/core/api/src/test/java/org/onosproject/net/behaviour/BandwidthProfileActionTest.java
new file mode 100644
index 0000000..e8bc68c
--- /dev/null
+++ b/core/api/src/test/java/org/onosproject/net/behaviour/BandwidthProfileActionTest.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2016-present 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.net.behaviour;
+
+import com.google.common.testing.EqualsTester;
+import org.junit.Test;
+import org.onlab.packet.DscpClass;
+import static org.onosproject.net.behaviour.BandwidthProfileAction.Action;
+
+/**
+ * Test for BandwidthProfileAction class.
+ */
+public class BandwidthProfileActionTest {
+
+    @Test
+    public void testEquals() {
+        BandwidthProfileAction passAction1 = BandwidthProfileAction.builder()
+                .action(Action.PASS)
+                .build();
+        BandwidthProfileAction passAction2 = BandwidthProfileAction.builder()
+                .action(Action.PASS)
+                .build();
+        BandwidthProfileAction discardAction1 = BandwidthProfileAction.builder()
+                .action(Action.DISCARD)
+                .build();
+        BandwidthProfileAction discardAction2 = BandwidthProfileAction.builder()
+                .action(Action.DISCARD)
+                .build();
+        BandwidthProfileAction remarkAction1 = BandwidthProfileAction.builder()
+                .action(Action.REMARK)
+                .dscpClass(DscpClass.AF11)
+                .build();
+        BandwidthProfileAction remarkAction2 = BandwidthProfileAction.builder()
+                .action(Action.REMARK)
+                .dscpClass(DscpClass.AF11)
+                .build();
+        new EqualsTester()
+                .addEqualityGroup(passAction1, passAction2)
+                .addEqualityGroup(discardAction1, discardAction2)
+                .addEqualityGroup(remarkAction1, remarkAction2)
+                .testEquals();
+    }
+}
diff --git a/core/api/src/test/java/org/onosproject/net/behaviour/BandwidthProfileTest.java b/core/api/src/test/java/org/onosproject/net/behaviour/BandwidthProfileTest.java
new file mode 100644
index 0000000..8052593
--- /dev/null
+++ b/core/api/src/test/java/org/onosproject/net/behaviour/BandwidthProfileTest.java
@@ -0,0 +1,195 @@
+/*
+ * Copyright 2016-present 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.net.behaviour;
+
+import org.junit.Test;
+import org.onlab.packet.DscpClass;
+import org.onlab.util.Bandwidth;
+import org.onosproject.TestApplicationId;
+import org.onosproject.core.ApplicationId;
+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 static org.onosproject.net.behaviour.BandwidthProfileAction.Action;
+
+import java.util.Arrays;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Test for BandwidthProfile class.
+ */
+public class BandwidthProfileTest {
+
+    private static final long ONE = 1L;
+    private static final long ONE_K = 1_000L;
+    private static final long TWO_K = 2_000L;
+    private static final long EIGHT_K = 8_000L;
+    private static final long ONE_M = 1_000_000L;
+    private static final long TEN_M = 10_000_000L;
+
+    @Test
+    public void testMeterConversion() {
+        DeviceId deviceId = DeviceId.deviceId("netconf:10.0.0.1:22");
+        ApplicationId appId = TestApplicationId.create("org.onosproject.foo.app");
+        Meter.Builder meterBuilder = new DefaultMeter.Builder()
+                .withId(MeterId.meterId(ONE))
+                .withUnit(Meter.Unit.KB_PER_SEC)
+                .forDevice(deviceId)
+                .burst();
+
+        // Create Meter with single band
+        Band band1 = DefaultBand.builder()
+                .ofType(Band.Type.DROP)
+                .withRate(TEN_M)
+                .burstSize(TWO_K)
+                .build();
+        Meter meter = meterBuilder
+                .fromApp(appId)
+                .withBands(Arrays.asList(band1))
+                .build();
+        BandwidthProfile bandwidthProfile = BandwidthProfile.fromMeter(meter);
+
+        assertEquals("wrong bw profile name",
+                     bandwidthProfile.name(), meter.id().toString());
+        assertEquals("wrong bw profile type",
+                     bandwidthProfile.type(), BandwidthProfile.Type.sr2CM);
+        assertEquals("wrong bw profile CIR",
+                     bandwidthProfile.cir().bps(), band1.rate() * EIGHT_K, 0);
+        assertEquals("wrong bw profile CBS",
+                     (long) bandwidthProfile.cbs(), (long) band1.burst());
+        assertNull(bandwidthProfile.pir());
+        assertNull(bandwidthProfile.pbs());
+        assertNull(bandwidthProfile.ebs());
+        assertEquals("wrong green action",
+                     bandwidthProfile.greenAction(),
+                     getBuilder(Action.PASS).build());
+        assertNull(bandwidthProfile.yellowAction());
+        assertEquals("wrong red action",
+                     bandwidthProfile.redAction(),
+                     getBuilder(Action.DISCARD).build());
+        assertEquals("wrong color-aware mode",
+                     bandwidthProfile.colorAware(), false);
+
+        // Create Meter with two bands
+        Band band2 = DefaultBand.builder().burstSize(ONE_K)
+                .ofType(Band.Type.REMARK)
+                .dropPrecedence((short) 0b001010)
+                .withRate(ONE_M)
+                .build();
+        meter = meterBuilder
+                .fromApp(appId)
+                .withBands(Arrays.asList(band1, band2))
+                .build();
+        bandwidthProfile = BandwidthProfile.fromMeter(meter);
+
+        assertEquals("wrong bw profile name",
+                     bandwidthProfile.name(), meter.id().toString());
+        assertEquals("wrong bw profile type",
+                     bandwidthProfile.type(), BandwidthProfile.Type.trTCM);
+        assertEquals("wrong bw profile CIR",
+                     bandwidthProfile.cir().bps(), band2.rate() * EIGHT_K, 0);
+        assertEquals("wrong bw profile CBS",
+                     (long) bandwidthProfile.cbs(), (long) band2.burst());
+        assertEquals("wrong bw profile PIR",
+                     bandwidthProfile.pir().bps(), band1.rate() * EIGHT_K, 0);
+        assertEquals("wrong bw profile PBS",
+                     (long) bandwidthProfile.pbs(), (long) band1.burst());
+        assertNull(bandwidthProfile.ebs());
+        assertEquals("wrong green action",
+                     bandwidthProfile.greenAction(),
+                     getBuilder(Action.PASS).build());
+        assertEquals("wrong yellow action",
+                     bandwidthProfile.yellowAction(),
+                     getBuilder(Action.REMARK)
+                             .dscpClass(DscpClass.AF11)
+                             .build());
+        assertEquals("wrong red action",
+                     bandwidthProfile.redAction(),
+                     getBuilder(Action.DISCARD).build());
+        assertEquals("wrong color-aware mode",
+                     bandwidthProfile.colorAware(), false);
+    }
+
+    @Test
+    public void testType() {
+        BandwidthProfile.Builder bwProfileBuilder = BandwidthProfile.builder()
+                .name("profile")
+                .cir(Bandwidth.bps(ONE_M))
+                .cbs((int) ONE_K)
+                .greenAction(getBuilder(Action.PASS).build())
+                .redAction(getBuilder(Action.DISCARD).build())
+                .colorAware(false);
+        assertEquals("wrong bw profile type",
+                     bwProfileBuilder.build().type(),
+                     BandwidthProfile.Type.sr2CM);
+
+        bwProfileBuilder.ebs((int) TWO_K)
+                .yellowAction(getBuilder(Action.REMARK)
+                                      .dscpClass(DscpClass.AF11)
+                                      .build());
+        assertEquals("wrong bw profile type",
+                     bwProfileBuilder.build().type(),
+                     BandwidthProfile.Type.srTCM);
+        bwProfileBuilder.ebs(null);
+
+        bwProfileBuilder.pir(Bandwidth.bps(TEN_M))
+                .pbs((int) TWO_K);
+        assertEquals("wrong bw profile type",
+                     bwProfileBuilder.build().type(),
+                     BandwidthProfile.Type.trTCM);
+    }
+
+    @Test
+    public void testEquals() {
+        BandwidthProfile bwProfile1 = new BandwidthProfile.Builder()
+                .name("profile1")
+                .cir(Bandwidth.bps(ONE_M))
+                .cbs((int) ONE_K)
+                .pir(Bandwidth.bps(TEN_M))
+                .pbs((int) TWO_K)
+                .greenAction(getBuilder(Action.PASS).build())
+                .yellowAction(getBuilder(Action.REMARK)
+                                      .dscpClass(DscpClass.AF11)
+                                      .build())
+                .redAction(getBuilder(Action.DISCARD).build())
+                .colorAware(false)
+                .build();
+        BandwidthProfile bwProfile2 = new BandwidthProfile.Builder()
+                .name("profile2")
+                .cir(Bandwidth.bps(ONE_M))
+                .cbs((int) ONE_K)
+                .pir(Bandwidth.bps(TEN_M))
+                .pbs((int) TWO_K)
+                .greenAction(getBuilder(Action.PASS).build())
+                .yellowAction(getBuilder(Action.REMARK)
+                                      .dscpClass(DscpClass.AF11)
+                                      .build())
+                .redAction(getBuilder(Action.DISCARD).build())
+                .colorAware(false)
+                .build();
+        assertTrue("wrong equals method", bwProfile1.equals(bwProfile2));
+    }
+
+    private static BandwidthProfileAction.Builder getBuilder(Action action) {
+        return new BandwidthProfileAction.Builder().action(action);
+    }
+}
diff --git a/utils/misc/src/main/java/org/onlab/packet/DscpClass.java b/utils/misc/src/main/java/org/onlab/packet/DscpClass.java
new file mode 100644
index 0000000..14be087
--- /dev/null
+++ b/utils/misc/src/main/java/org/onlab/packet/DscpClass.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2016-present 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.onlab.packet;
+
+/**
+ * Represents the DiffServ classes defined by the IPv4/IPv6 DSCP value.
+ * DSCP occupies the 6 most-significant bits of the IPv4/IPv6 DS field
+ */
+public enum DscpClass {
+
+    BE((short) 0b000000),
+    AF11((short) 0b001010),
+    AF12((short) 0b001100),
+    AF13((short) 0b001110),
+    AF21((short) 0b010010),
+    AF22((short) 0b010100),
+    AF23((short) 0b010110),
+    AF31((short) 0b011010),
+    AF32((short) 0b011100),
+    AF33((short) 0b011110),
+    AF41((short) 0b100010),
+    AF42((short) 0b100100),
+    AF43((short) 0b100110),
+    CS1((short) 0b001000),
+    CS2((short) 0b010000),
+    CS3((short) 0b011000),
+    CS4((short) 0b100000),
+    CS5((short) 0b101000),
+    CS6((short) 0b110000),
+    CS7((short) 0b111000),
+    EF((short) 0b101110);
+
+    private static final short IP_PREC_MASK = 0b111000;
+    private static final short IP_PREC_RSHIFT = 3;
+    private static final short DROP_PREC_MASK = 0b000110;
+    private static final short DROP_PREC_RSHIFT = 1;
+
+    private short value;
+
+    DscpClass(short value) {
+        this.value = value;
+    }
+
+    /**
+     * Returns the DSCP class Enum corresponding to the specified short.
+     *
+     * @param value the short value of the DSCP class
+     * @return the DSCP class Enum corresponding to the specified short
+     * @throws IllegalArgumentException if the short provided does not
+     * correspond to an DSCP class Enum value
+     */
+    public static DscpClass fromShort(short value) {
+        for (DscpClass b : DscpClass.values()) {
+            if (value == b.value) {
+                return b;
+            }
+        }
+        throw new IllegalArgumentException("DSCP class " + value + " is not valid");
+    }
+
+    /**
+     * Returns the short value of this DSCP class Enum.
+     *
+     * @return the short value of this DSCP class Enum
+     */
+    public short getValue() {
+        return value;
+    }
+
+    /**
+     * Returns the corresponding IP precedence.
+     *
+     * @return the corresponding IP precedence
+     */
+    public IPPrecedence getIPPrecedence() {
+        return IPPrecedence.fromShort((short) ((value & IP_PREC_MASK) >> IP_PREC_RSHIFT));
+    }
+
+    /**
+     * Returns the corresponding drop precedence.
+     *
+     * @return the corresponding drop precedence
+     */
+    public short getDropPrecedence() {
+        return (short) ((value & DROP_PREC_MASK) >> DROP_PREC_RSHIFT);
+    }
+}
diff --git a/utils/misc/src/main/java/org/onlab/packet/IPPrecedence.java b/utils/misc/src/main/java/org/onlab/packet/IPPrecedence.java
new file mode 100644
index 0000000..09ad0e9
--- /dev/null
+++ b/utils/misc/src/main/java/org/onlab/packet/IPPrecedence.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2016-present 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.onlab.packet;
+
+/**
+ * Represents the deprecated IPv4 IP precedence.
+ * IP precedence occupied the 3 most-significant bits of the IPv4 ToS field
+ */
+public enum IPPrecedence {
+
+    BEST_EFFORT((short) 0b000),
+    PRIORITY((short) 0b001),
+    IMMEDIATE((short) 0b010),
+    FLASH((short) 0b011),
+    FLASH_OVERRIDE((short) 0b100),
+    CRITICAL((short) 0b101),
+    INTERNETWORK_CONTROL((short) 0b110),
+    NETWORK_CONTROL((short) 0b111);
+
+    private short value;
+
+    IPPrecedence(short value) {
+        this.value = value;
+    }
+
+    /**
+     * Returns the IP precedence Enum corresponding to the specified short.
+     *
+     * @param value the short value of the IP precedence
+     * @return the IP precedence Enum corresponding to the specified short
+     * @throws IllegalArgumentException if the short provided does not correspond to an IP precedence Enum value
+     */
+    public static IPPrecedence fromShort(short value) {
+        for (IPPrecedence b : IPPrecedence.values()) {
+            if (value == b.value) {
+                return b;
+            }
+        }
+        throw new IllegalArgumentException("IP precedence " + value + " is not valid");
+    }
+
+    /**
+     * Returns the short value of this IP precedence Enum.
+     *
+     * @return the short value of this IP precedence Enum
+     */
+    public short getValue() {
+        return value;
+    }
+}
diff --git a/utils/misc/src/main/java/org/onlab/util/Bandwidth.java b/utils/misc/src/main/java/org/onlab/util/Bandwidth.java
index bf43bc7..0797dcd 100644
--- a/utils/misc/src/main/java/org/onlab/util/Bandwidth.java
+++ b/utils/misc/src/main/java/org/onlab/util/Bandwidth.java
@@ -86,6 +86,26 @@
     }
 
     /**
+     * Creates a new instance with given bandwidth in KBps.
+     *
+     * @param kBps bandwidth value to be assigned
+     * @return {@link Bandwidth} instance with given bandwidth
+     */
+    static Bandwidth kBps(long kBps) {
+        return bps(kBps * 8_000L);
+    }
+
+    /**
+     * Creates a new instance with given bandwidth in KBps.
+     *
+     * @param kBps bandwidth value to be assigned
+     * @return {@link Bandwidth} instance with given bandwidth
+     */
+    static Bandwidth kBps(double kBps) {
+        return bps(kBps * 8_000L);
+    }
+
+    /**
      * Creates a new instance with given bandwidth in Mbps.
      *
      * @param mbps bandwidth value to be assigned
@@ -106,6 +126,26 @@
     }
 
     /**
+     * Creates a new instance with given bandwidth in MBps.
+     *
+     * @param mBps bandwidth value to be assigned
+     * @return {@link Bandwidth} instance with given bandwidth
+     */
+    static Bandwidth mBps(long mBps) {
+        return bps(mBps * 8_000_000L);
+    }
+
+    /**
+     * Creates a new instance with given bandwidth in MBps.
+     *
+     * @param mBps bandwidth value to be assigned
+     * @return {@link Bandwidth} instance with given bandwidth
+     */
+    static Bandwidth mBps(double mBps) {
+        return bps(mBps * 8_000_000L);
+    }
+
+    /**
      * Creates a new instance with given bandwidth in Gbps.
      *
      * @param gbps bandwidth value to be assigned
@@ -126,6 +166,26 @@
     }
 
     /**
+     * Creates a new instance with given bandwidth in GBps.
+     *
+     * @param gBps bandwidth value to be assigned
+     * @return {@link Bandwidth} instance with given bandwidth
+     */
+    static Bandwidth gBps(long gBps) {
+        return bps(gBps * 8_000_000_000L);
+    }
+
+    /**
+     * Creates a new instance with given bandwidth in GBps.
+     *
+     * @param gBps bandwidth value to be assigned
+     * @return {@link Bandwidth} instance with given bandwidth
+     */
+    static Bandwidth gBps(double gBps) {
+        return bps(gBps * 8_000_000_000L);
+    }
+
+    /**
      * Returns bandwidth in bps.
      *
      * @return bandwidth in bps.
diff --git a/utils/misc/src/test/java/org/onlab/packet/DscpClassTest.java b/utils/misc/src/test/java/org/onlab/packet/DscpClassTest.java
new file mode 100644
index 0000000..295b9e8
--- /dev/null
+++ b/utils/misc/src/test/java/org/onlab/packet/DscpClassTest.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2016-present 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.onlab.packet;
+
+import org.junit.Test;
+
+/**
+ * Test for DscpClassTest enum.
+ */
+public class DscpClassTest {
+    @Test(expected = IllegalArgumentException.class)
+    public void testIllicitDscpClass() {
+        DscpClass.fromShort((short) 0b111001);
+    }
+}
diff --git a/utils/misc/src/test/java/org/onlab/packet/IPPrecedenceTest.java b/utils/misc/src/test/java/org/onlab/packet/IPPrecedenceTest.java
new file mode 100644
index 0000000..999d3c4
--- /dev/null
+++ b/utils/misc/src/test/java/org/onlab/packet/IPPrecedenceTest.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2016-present 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.onlab.packet;
+
+import org.junit.Test;
+
+/**
+ * Test for IPPrecedence enum.
+ */
+public class IPPrecedenceTest {
+    @Test(expected = IllegalArgumentException.class)
+    public void testIllicitIPPrecedence() {
+        IPPrecedence.fromShort((short) 0b1000);
+    }
+}