[ONOS-7003] Policer implementation

Changes:
- Introduce trafficcontrol package
- Add policer
- Add policer id
- Add policing resource
- Add token bucket
- Add unit tests

Change-Id: I70065d58d3df7033e67a81943ebf60187c33c3e2
diff --git a/core/api/src/main/java/org/onosproject/net/behaviour/trafficcontrol/DefaultPolicer.java b/core/api/src/main/java/org/onosproject/net/behaviour/trafficcontrol/DefaultPolicer.java
new file mode 100644
index 0000000..d375f9d
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/behaviour/trafficcontrol/DefaultPolicer.java
@@ -0,0 +1,260 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.net.behaviour.trafficcontrol;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableSet;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.net.DeviceId;
+
+import java.util.Collection;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Default implementation of the policer interface.
+ */
+@Beta
+public final class DefaultPolicer implements Policer, PolicerEntry {
+
+    // Immutable parameters
+    private final DeviceId deviceId;
+    private final ApplicationId applicationId;
+    private final PolicerId policerId;
+    private final boolean colorAware;
+    private final Unit unit;
+    private final Collection<TokenBucket> tokenBuckets;
+    private final String description;
+
+    // Mutable parameters
+    private long referenceCount;
+    private long processedPackets;
+    private long processedBytes;
+    private long life;
+
+    private DefaultPolicer(DeviceId dId, ApplicationId aId, PolicerId pId,
+                           boolean cA, Unit u, Collection<TokenBucket> tB,
+                           String d) {
+        deviceId = dId;
+        applicationId = aId;
+        policerId = pId;
+        colorAware = cA;
+        unit = u;
+        tokenBuckets = tB;
+        description = d;
+    }
+
+    @Override
+    public DeviceId deviceId() {
+        return deviceId;
+    }
+
+    @Override
+    public ApplicationId applicationId() {
+        return applicationId;
+    }
+
+    @Override
+    public PolicerId policerId() {
+        return policerId;
+    }
+
+    @Override
+    public boolean isColorAware() {
+        return colorAware;
+    }
+
+    @Override
+    public Unit unit() {
+        return unit;
+    }
+
+    @Override
+    public Collection<TokenBucket> tokenBuckets() {
+        return tokenBuckets;
+    }
+
+    @Override
+    public String description() {
+        return description;
+    }
+
+    @Override
+    public long referenceCount() {
+        return referenceCount;
+    }
+
+    @Override
+    public void setReferenceCount(long count) {
+        referenceCount = count;
+    }
+
+    @Override
+    public long processedPackets() {
+        return processedPackets;
+    }
+
+    @Override
+    public void setProcessedPackets(long packets) {
+        processedPackets = packets;
+    }
+
+    @Override
+    public long processedBytes() {
+        return processedBytes;
+    }
+
+    @Override
+    public void setProcessedBytes(long bytes) {
+        processedBytes = bytes;
+    }
+
+    @Override
+    public long life() {
+        return life;
+    }
+
+    @Override
+    public void setLife(long l) {
+        life = l;
+    }
+
+    @Override
+    public String toString() {
+        return toStringHelper(this)
+                .add("appId", applicationId())
+                .add("id", policerId())
+                .add("isColorAware", isColorAware())
+                .add("unit", unit())
+                .add("tokenBuckets", tokenBuckets())
+                .add("description", description())
+                .toString();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        DefaultPolicer that = (DefaultPolicer) o;
+        return Objects.equal(policerId, that.policerId);
+    }
+
+    @Override
+    public int hashCode() {
+        return policerId.hashCode();
+    }
+
+    /**
+     * Returns a new builder reference.
+     *
+     * @return a new builder
+     */
+    public static Builder builder() {
+        return new Builder();
+    }
+
+    /**
+     * Implementation of the policer builder interface.
+     */
+    public static final class Builder implements Policer.Builder {
+
+        private DeviceId deviceId;
+        private ApplicationId applicationId;
+        private PolicerId policerId;
+        // Default to unaware
+        private boolean colorAware = false;
+        // Default to MBps
+        private Unit unit = Unit.MB_PER_SEC;
+        private Collection<TokenBucket> tokenBuckets;
+        private String description = "";
+
+        @Override
+        public Policer.Builder forDeviceId(DeviceId dId) {
+            deviceId = dId;
+            return this;
+        }
+
+        @Override
+        public Policer.Builder fromApp(ApplicationId appId) {
+            applicationId = appId;
+            return this;
+        }
+
+        @Override
+        public Policer.Builder withId(PolicerId id) {
+            policerId = id;
+            return this;
+        }
+
+        @Override
+        public Policer.Builder colorAware(boolean isColorAware) {
+            colorAware = isColorAware;
+            return this;
+        }
+
+        @Override
+        public Policer.Builder withUnit(Unit u) {
+            unit = u;
+            return this;
+        }
+
+        @Override
+        public Policer.Builder withPolicingResource(PolicingResource policingResource) {
+            policerId = policingResource.policerId();
+            deviceId = policingResource.connectPoint().deviceId();
+            return this;
+        }
+
+        @Override
+        public Policer.Builder withTokenBuckets(Collection<TokenBucket> tB) {
+            tokenBuckets = ImmutableSet.copyOf(tB);
+            return this;
+        }
+
+       @Override
+       public Policer.Builder withDescription(String d) {
+           description = d;
+           return this;
+       }
+
+        @Override
+        public DefaultPolicer build() {
+            // Not null condition on some mandatory parameters
+            checkNotNull(deviceId, "Must specify a deviceId");
+            checkNotNull(applicationId, "Must specify an application id");
+            checkNotNull(policerId, "Must specify a policer id");
+            checkNotNull(unit, "Must specify a unit for the policer");
+            checkNotNull(tokenBuckets, "Must have token buckets");
+            checkNotNull(description, "Must have a description");
+
+            // Verify argument conditions
+            checkArgument(!tokenBuckets.isEmpty(), "Must have at least one token bucket");
+
+            // Finally we build the policer
+            return new DefaultPolicer(deviceId, applicationId, policerId,
+                                      colorAware, unit, tokenBuckets,
+                                      description);
+        }
+    }
+}
diff --git a/core/api/src/main/java/org/onosproject/net/behaviour/trafficcontrol/DefaultTokenBucket.java b/core/api/src/main/java/org/onosproject/net/behaviour/trafficcontrol/DefaultTokenBucket.java
new file mode 100644
index 0000000..f3920b2
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/behaviour/trafficcontrol/DefaultTokenBucket.java
@@ -0,0 +1,179 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.net.behaviour.trafficcontrol;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onosproject.net.behaviour.trafficcontrol.TokenBucket.Action.DSCP_CLASS;
+import static org.onosproject.net.behaviour.trafficcontrol.TokenBucket.Action.DSCP_PRECEDENCE;
+
+/**
+ * Default implementation of the token bucket interface.
+ */
+@Beta
+public final class DefaultTokenBucket implements TokenBucket, TokenBucketEntry {
+
+    // Immutable parameters
+    private final long rate;
+    private final long burstSize;
+    private final Action action;
+    private final short dscp;
+
+    // Mutable parameters
+    private long processedPackets;
+    private long processedBytes;
+
+    private DefaultTokenBucket(long r, long bS, Action a, short d) {
+        rate = r;
+        burstSize = bS;
+        action = a;
+        dscp = d;
+    }
+
+    @Override
+    public long rate() {
+        return rate;
+    }
+
+    @Override
+    public long burstSize() {
+        return burstSize;
+    }
+
+    @Override
+    public Action action() {
+        return action;
+    }
+
+    @Override
+    public short dscp() {
+        return dscp;
+    }
+
+    @Override
+    public long processedPackets() {
+        return processedPackets;
+    }
+
+    @Override
+    public void setProcessedPackets(long packets) {
+        processedPackets = packets;
+    }
+
+    @Override
+    public long processedBytes() {
+        return processedBytes;
+    }
+
+    @Override
+    public void setProcessedBytes(long bytes) {
+        processedBytes = bytes;
+    }
+
+    @Override
+    public String toString() {
+        return toStringHelper(this)
+                .add("rate", rate())
+                .add("burstSize", burstSize())
+                .add("action", action())
+                .add("dscp", dscp()).toString();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        DefaultTokenBucket that = (DefaultTokenBucket) o;
+        return rate == that.rate &&
+                burstSize == that.burstSize &&
+                Objects.equal(action, that.action) &&
+                dscp == that.dscp;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(rate, burstSize, action, dscp);
+    }
+
+    /**
+     * Returns a new builder reference.
+     *
+     * @return a new builder
+     */
+    public static Builder builder() {
+        return new Builder();
+    }
+
+    /**
+     * Implementation of the token bucket builder interface.
+     */
+    public static final class Builder implements TokenBucket.Builder {
+
+        private long rate;
+        // Default to 2 * MTU
+        private long burstSize = 2 * 1500;
+        private Action action;
+        private short dscp;
+
+        @Override
+        public TokenBucket.Builder withRate(long r) {
+            rate = r;
+            return this;
+        }
+
+        @Override
+        public TokenBucket.Builder withBurstSize(long bS) {
+            burstSize = bS;
+            return this;
+        }
+
+        @Override
+        public TokenBucket.Builder withAction(Action a) {
+            action = a;
+            return this;
+        }
+
+        @Override
+        public TokenBucket.Builder withDscp(short d) {
+            dscp = d;
+            return this;
+        }
+
+        @Override
+        public DefaultTokenBucket build() {
+            // Not null condition on the action
+            checkNotNull(action, "Must specify an action");
+
+            // If action is based on DSCP modification
+            if (action == DSCP_CLASS || action == DSCP_PRECEDENCE) {
+                // dscp should be a value between 0 and 255
+                checkArgument(dscp >= MIN_DSCP && dscp <= MAX_DSCP, "Dscp is out of range");
+            }
+
+            // Finally we build the token bucket
+            return new DefaultTokenBucket(rate, burstSize, action, dscp);
+        }
+    }
+}
diff --git a/core/api/src/main/java/org/onosproject/net/behaviour/trafficcontrol/Policer.java b/core/api/src/main/java/org/onosproject/net/behaviour/trafficcontrol/Policer.java
new file mode 100644
index 0000000..af17050
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/behaviour/trafficcontrol/Policer.java
@@ -0,0 +1,262 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.net.behaviour.trafficcontrol;
+
+import com.google.common.annotations.Beta;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.net.DeviceId;
+
+import java.util.Collection;
+
+/**
+ * Generic abstraction for a policer which can mark and/or discard ingress
+ * traffic. Each policer is made up of an identifier and a set of attributes
+ * which defines the type of policer.
+ * <p>
+ * For example a policer specifying only a single token bucket, it will model
+ * a simple drop policer or a marker policer. For the former, the traffic in
+ * profile is green or red if it is out-of-profile. The latter envisages green
+ * or yellow traffic. Currently there is no RFC for this kind of policer but
+ * some vendors implement this model.
+ * <p>
+ * RFC 2697 can be modelled creating a policer with a collection of two
+ * token buckets: [0] CIR + CBS; [1] CIR + EBS. In this way, it is possible
+ * to create a policer single rate three color marker.
+ * <p>
+ * RFC 2698 and P4 meter are modelled in the same way but different attributes
+ * for the token buckets: [0] PIR + PBS; [2] CIR + CBS. In this way, we can
+ * create a policer two rate three color marker.
+ * <p>
+ * How these policers will be implemented depends on the specific technology
+ * used in the device. For an OF device, the single rate two color marker it
+ * could be implemented with a simple meter with a drop band.
+ * <p>
+ * Following abstraction has been designed to cover several types of policing
+ * that have been specified during the years. However, this does not assure that
+ * used technology will support all possible scenarios. For example, OF limitations
+ * are well known in this field and implementations are even worse.
+ */
+@Beta
+public interface Policer {
+
+    /**
+     * Unit of traffic used by this policer.
+     */
+    enum Unit {
+        /**
+         * Packets per second.
+         */
+        PKTS_PER_SEC,
+        /**
+         * Byte per second.
+         */
+        B_PER_SEC,
+        /**
+         * KByte per second.
+         */
+        KB_PER_SEC,
+        /**
+         * MByte per second.
+         */
+        MB_PER_SEC
+    }
+
+    /**
+     * The device of this policer, where policing
+     * is applied.
+     *
+     * @return the device id
+     */
+    DeviceId deviceId();
+
+    /**
+     * The id of the application which created this policer.
+     *
+     * @return the identifier of the application
+     */
+    ApplicationId applicationId();
+
+    /**
+     * Returns how many are referencing this policer.
+     *
+     * Availability of this information depends on the
+     * technology used for the implementation of this policer.
+     *
+     * @return the reference count
+     */
+    long referenceCount();
+
+    /**
+     * Stats which reports how many packets have been
+     * processed so far.
+     *
+     * Availability of this information depends on the
+     * technology used for the implementation of this policer.
+     *
+     * @return the processed packets
+     */
+    long processedPackets();
+
+    /**
+     * Stats which reports how many bytes have been
+     * processed so far.
+     *
+     * Availability of this information depends on the
+     * technology used for the implementation of this policer.
+     *
+     * @return the processed bytes
+     */
+    long processedBytes();
+
+    /**
+     * The id of this policer.
+     *
+     * @return the policer id
+     */
+    PolicerId policerId();
+
+    /**
+     * Indicates if this policer is aware of the marking indication
+     * in the ethernet frames.
+     *
+     * TODO Understand for the future how it is implemented by the vendors
+     *
+     * @return true if this policer is color aware.
+     */
+    boolean isColorAware();
+
+    /**
+     * The lifetime in seconds of this policer.
+     *
+     * Availability of this information depends on the
+     * technology used for the implementation of this policer.
+     *
+     * @return number of seconds
+     */
+    long life();
+
+    /**
+     * The unit used within this policer.
+     *
+     * @return the unit
+     */
+    Unit unit();
+
+    /**
+     * The token buckets used within this policer.
+     *
+     * @return the list of the token buckets
+     */
+    Collection<TokenBucket> tokenBuckets();
+
+    /**
+     * Brief description of this policer.
+     *
+     * @return human readable description
+     */
+    String description();
+
+    /**
+     * A policer builder.
+     */
+    interface Builder {
+
+        /**
+         * Assigns the device for this policer.
+         * <p>
+         * Note: mandatory setter for this builder
+         * </p>
+         * @param deviceId a device id
+         * @return this
+         */
+        Builder forDeviceId(DeviceId deviceId);
+
+        /**
+         * Assigns the application that built this policer.
+         * <p>
+         * Note: mandatory setter for this builder
+         * </p>
+         * @param appId an application id
+         * @return this
+         */
+        Builder fromApp(ApplicationId appId);
+
+        /**
+         * Assigns the id to this policer.
+         * <p>
+         * Note: mandatory setter for this builder
+         * </p>
+         * @param id an identifier
+         * @return this
+         */
+        Builder withId(PolicerId id);
+
+        /**
+         * Sets this policer to be color aware.
+         * Defaults to false.
+         *
+         * @param isColorAware if it is color aware or not
+         * @return this
+         */
+        Builder colorAware(boolean isColorAware);
+
+        /**
+         * Assigns the unit to use for this policer.
+         * Defaults to MB/s.
+         *
+         * @param unit a unit
+         * @return this
+         */
+        Builder withUnit(Unit unit);
+
+        /**
+         * Assigns policer id and device id for this policer.
+         *
+         * @param policingResource the policing resource
+         * @return this
+         */
+        Builder withPolicingResource(PolicingResource policingResource);
+
+        /**
+         * Assigns token buckets for this policer.
+         * <p>
+         * Note: at least one token bucket
+         * </p>
+         * @param tokenBuckets the collection of token buckets
+         * @return this
+         */
+        Builder withTokenBuckets(Collection<TokenBucket> tokenBuckets);
+
+        /**
+         * Assigns description for this policer.
+         * Default is empty description.
+         *
+         * @param description the description
+         * @return this
+         */
+        Builder withDescription(String description);
+
+        /**
+         * Builds the policer based on the specified parameters
+         * when possible.
+         *
+         * @return a policer
+         */
+        Policer build();
+    }
+
+}
diff --git a/core/api/src/main/java/org/onosproject/net/behaviour/trafficcontrol/PolicerEntry.java b/core/api/src/main/java/org/onosproject/net/behaviour/trafficcontrol/PolicerEntry.java
new file mode 100644
index 0000000..0f019ef
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/behaviour/trafficcontrol/PolicerEntry.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.net.behaviour.trafficcontrol;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * Represents a stored policer.
+ */
+@Beta
+public interface PolicerEntry {
+
+    /**
+     * Set the amount of time the policer has existed in seconds.
+     *
+     * @param life number of seconds
+     */
+    void setLife(long life);
+
+    /**
+     * Sets how many are using this policer.
+     *
+     * @param count a reference count.
+     */
+    void setReferenceCount(long count);
+
+    /**
+     * Updates the number of packets seen by this policer.
+     *
+     * @param packets a packet count.
+     */
+    void setProcessedPackets(long packets);
+
+    /**
+     * Updates the number of bytes seen by the policer.
+     *
+     * @param bytes a byte counter.
+     */
+    void setProcessedBytes(long bytes);
+
+}
diff --git a/core/api/src/main/java/org/onosproject/net/behaviour/trafficcontrol/PolicerId.java b/core/api/src/main/java/org/onosproject/net/behaviour/trafficcontrol/PolicerId.java
new file mode 100644
index 0000000..c373dbe
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/behaviour/trafficcontrol/PolicerId.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.net.behaviour.trafficcontrol;
+
+
+import com.google.common.annotations.Beta;
+import org.onlab.util.Identifier;
+
+import java.net.URI;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+/**
+ * Unique identifier for an ONOS Policer {@link org.onosproject.net.behaviour.trafficcontrol.Policer}.
+ * It uniquely identifies a Policer in the scope of a single device inside ONOS. There may not be any
+ * correspondence with the identifiers of the technology implementing the Policer in the device.
+ * Mapping (if necessary) is left to the specific implementation.
+ */
+@Beta
+public final class PolicerId extends Identifier<String> {
+
+    /**
+     * Represents either no id, or an unspecified id.
+     */
+    public static final PolicerId NONE = policerId("none:none");
+
+    private static final int POLICER_ID_MAX_LENGTH = 1024;
+
+    private final URI uri;
+
+    // Not allowed
+    private PolicerId(URI u) {
+        super(u.toString());
+        uri = u;
+    }
+
+    // Needed for serialization
+    private PolicerId() {
+        super();
+        uri = null;
+    }
+
+    /**
+     * Creates a policer id using the supplied URI.
+     *
+     * @param uri policer id URI
+     * @return PolicerId
+     */
+    public static PolicerId policerId(URI uri) {
+        return new PolicerId(uri);
+    }
+
+    /**
+     * Creates a policer id using the supplied URI string.
+     *
+     * @param string policer id URI string
+     * @return PolicerID
+     */
+    public static PolicerId policerId(String string) {
+        checkArgument(string.length() <= POLICER_ID_MAX_LENGTH,
+                      "URI string exceeds maximum length " + POLICER_ID_MAX_LENGTH);
+        return policerId(URI.create(string));
+    }
+
+    /**
+     * Returns the backing URI.
+     *
+     * @return backing URI
+     */
+    public URI uri() {
+        return uri;
+    }
+
+}
diff --git a/core/api/src/main/java/org/onosproject/net/behaviour/trafficcontrol/PolicingResource.java b/core/api/src/main/java/org/onosproject/net/behaviour/trafficcontrol/PolicingResource.java
new file mode 100644
index 0000000..29ab258
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/behaviour/trafficcontrol/PolicingResource.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.net.behaviour.trafficcontrol;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Objects;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.NetworkResource;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Abstraction which encapsulates policer
+ * data to be used as network resource.
+ */
+@Beta
+public final class PolicingResource implements NetworkResource {
+
+    // The policer id identifying this resource
+    private final PolicerId policerId;
+    // The connect point where the policer applies
+    private final ConnectPoint connectPoint;
+
+    public PolicingResource(PolicerId pId, ConnectPoint cP) {
+        checkNotNull(pId, "Must specify a policer id");
+        checkNotNull(cP, "Must specify a connect point");
+        policerId = pId;
+        connectPoint = cP;
+    }
+
+    /**
+     * Return the policer id of this resource.
+     *
+     * @return the policer id
+     */
+    public PolicerId policerId() {
+        return policerId;
+    }
+
+    /**
+     * Returns the connect point of this resource.
+     *
+     * @return the connect point
+     */
+    public ConnectPoint connectPoint() {
+        return connectPoint;
+    }
+
+    @Override
+    public String toString() {
+        return toStringHelper(this)
+                .add("id", policerId())
+                .add("connectPoint", connectPoint()).toString();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        PolicingResource that = (PolicingResource) o;
+        return Objects.equal(policerId, that.policerId) &&
+                Objects.equal(connectPoint, that.connectPoint);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(policerId, connectPoint);
+    }
+
+}
diff --git a/core/api/src/main/java/org/onosproject/net/behaviour/trafficcontrol/TokenBucket.java b/core/api/src/main/java/org/onosproject/net/behaviour/trafficcontrol/TokenBucket.java
new file mode 100644
index 0000000..a86466b
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/behaviour/trafficcontrol/TokenBucket.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.net.behaviour.trafficcontrol;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * Generic abstraction for a token bucket which can mark and/or discard
+ * traffic. Each token bucket in ONOS is made up of a set of attributes which
+ * identifies the type.
+ */
+@Beta
+public interface TokenBucket {
+
+    /**
+     * Upper bound for DSCP.
+     */
+    short MAX_DSCP = 255;
+    /**
+     * Lower bound for DSCP.
+     */
+    short MIN_DSCP = 0;
+
+    /**
+     * Action applied to the exceeding traffic.
+     * Action depends on the tocken bucket type
+     */
+    enum Action {
+        /**
+         * Drop action.
+         */
+        DROP,
+        /**
+         * Marking increases DSCP drop precedence.
+         */
+        DSCP_PRECEDENCE,
+        /**
+         * Marking sets DSCP class.
+         */
+        DSCP_CLASS,
+        /**
+         * Marking sets Drop Elegible Indicator.
+         */
+        DEI
+    }
+
+    /**
+     * Rate of traffic subject to the SLAs
+     * specified for this token bucket.
+     *
+     * @return the rate value
+     */
+    long rate();
+
+    /**
+     * Maximum burst size subject to the SLAs
+     * specified for this token bucket.
+     *
+     * @return the burst size in bytes
+     */
+    long burstSize();
+
+    /**
+     * Action used by this token bucket
+     * for the exceeding traffic.
+     *
+     * @return the type of action
+     */
+    Action action();
+
+    /**
+     * Dscp value, it meaning depends on the used marking.
+     *
+     * @return the dscp value for this token bucket
+     */
+    short dscp();
+
+    /**
+     * Stats which reports how many packets have been
+     * processed so far.
+     *
+     * Availability of this information depends on the
+     * technology used for the implementation of the policer.
+     *
+     * @return the processed packets
+     */
+    long processedPackets();
+
+    /**
+     * Stats which reports how many bytes have been
+     * processed so far.
+     *
+     * Availability of this information depends on the
+     * technology used for the implementation of the policer.
+     *
+     * @return the processed bytes
+     */
+    long processedBytes();
+
+    /**
+     * Token bucket builder.
+     */
+    interface Builder {
+
+        /**
+         * Assigns the rate to this token bucket.
+         *
+         * @param rate a rate value
+         * @return this
+         */
+        Builder withRate(long rate);
+
+        /**
+         * Assigns the burst size to this token bucket.
+         * Default to 2 * 1500 bytes.
+         *
+         * @param burstSize a burst size
+         * @return this
+         */
+        Builder withBurstSize(long burstSize);
+
+        /**
+         * Assigns the action to this token bucket.
+         * <p>
+         * Note: mandatory setter for this builder
+         * </p>
+         * @param action an action
+         * @return this
+         */
+        Builder withAction(Action action);
+
+        /**
+         * Assigns the dscp value to this token bucket.
+         *
+         * @param dscp a dscp value
+         * @return this
+         */
+        Builder withDscp(short dscp);
+
+        /**
+         * Builds the token bucket based on the specified
+         * parameters when possible.
+         *
+         * @return a token bucket
+         */
+        TokenBucket build();
+
+    }
+}
diff --git a/core/api/src/main/java/org/onosproject/net/behaviour/trafficcontrol/TokenBucketEntry.java b/core/api/src/main/java/org/onosproject/net/behaviour/trafficcontrol/TokenBucketEntry.java
new file mode 100644
index 0000000..00ca270
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/behaviour/trafficcontrol/TokenBucketEntry.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.net.behaviour.trafficcontrol;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * Represents a stored token bucket.
+ */
+@Beta
+public interface TokenBucketEntry {
+
+    /**
+     * Updates the number of packets seen by this token bucket.
+     *
+     * @param packets a packet count.
+     */
+    void setProcessedPackets(long packets);
+
+    /**
+     * Updates the number of bytes seen by this token bucket.
+     *
+     * @param bytes a byte counter.
+     */
+    void setProcessedBytes(long bytes);
+
+}
diff --git a/core/api/src/main/java/org/onosproject/net/behaviour/trafficcontrol/package-info.java b/core/api/src/main/java/org/onosproject/net/behaviour/trafficcontrol/package-info.java
new file mode 100644
index 0000000..188f3de
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/behaviour/trafficcontrol/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Traffic control behaviors and related classes.
+ */
+package org.onosproject.net.behaviour.trafficcontrol;
diff --git a/core/api/src/test/java/org/onosproject/net/behaviour/trafficcontrol/PolicerIdTest.java b/core/api/src/test/java/org/onosproject/net/behaviour/trafficcontrol/PolicerIdTest.java
new file mode 100644
index 0000000..883f40d
--- /dev/null
+++ b/core/api/src/test/java/org/onosproject/net/behaviour/trafficcontrol/PolicerIdTest.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.net.behaviour.trafficcontrol;
+
+import com.google.common.base.Strings;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.onlab.junit.ImmutableClassChecker;
+
+import java.net.URI;
+
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Test class for PolicerId.
+ */
+public class PolicerIdTest {
+
+    // Test scheme
+    private static final String FOO_SCHEME = "foo";
+    // OpenFlow scheme
+    private static final String OF_SCHEME = "of";
+    // Some test ids
+    private static final Short ONE = 1;
+    private static final Short TWO = 15;
+    private static final String A = "A";
+    private static final String LA = "a";
+
+    /**
+     * Test policer id creation from URI.
+     */
+    @Test
+    public void testfromUriCreation() {
+        // Create URI representing the id
+        URI uriOne = URI.create(OF_SCHEME + ":" + Integer.toHexString(ONE));
+        // Create policer id
+        PolicerId one = PolicerId.policerId(uriOne);
+        // Verify proper creation
+        assertThat(one, notNullValue());
+        assertThat(one.id(), is(uriOne.toString().toLowerCase()));
+        assertThat(one.uri(), is(uriOne));
+    }
+
+    /**
+     * Test policer id creation from string.
+     */
+    @Test
+    public void testfromStringCreation() {
+        // Create String representing the id
+        String stringTwo = OF_SCHEME + ":" + Integer.toHexString(TWO);
+        // Create policer id
+        PolicerId two = PolicerId.policerId(stringTwo);
+        // Verify proper creation
+        assertThat(two, notNullValue());
+        assertThat(two.id(), is(stringTwo));
+        assertThat(two.uri(), is(URI.create(stringTwo)));
+    }
+
+    /**
+     * Exception expected to raise when creating a wrong policer id.
+     */
+    @Rule
+    public ExpectedException exceptionWrongId = ExpectedException.none();
+
+    /**
+     * Test wrong creation of a policer id.
+     */
+    @Test
+    public void testWrongCreation() {
+        // Build not allowed string
+        String wrongString = Strings.repeat("x", 1025);
+        // Define expected exception
+        exceptionWrongId.expect(IllegalArgumentException.class);
+        // Create policer id
+        PolicerId.policerId(wrongString);
+    }
+
+    /**
+     * Test equality between policer ids.
+     */
+    @Test
+    public void testEquality() {
+        // Create URI representing the id one
+        URI uriOne = URI.create(OF_SCHEME + ":" + Integer.toHexString(ONE));
+        // Create String representing the id one
+        String stringOne = OF_SCHEME + ":" + Integer.toHexString(ONE);
+        // Create String representing the id two
+        String stringTwo = OF_SCHEME + ":" + Integer.toHexString(TWO);
+        // Create String representing the id A
+        String stringA = FOO_SCHEME + ":" + A;
+        // Create String representing the id LA
+        String stringLA = FOO_SCHEME + ":" + LA;
+        // Create policer id one
+        PolicerId one = PolicerId.policerId(uriOne);
+        // Create policer id one
+        PolicerId copyOfOne = PolicerId.policerId(stringOne);
+        // Verify equality
+        assertEquals(one, copyOfOne);
+        // Create a different policer id
+        PolicerId two = PolicerId.policerId(stringTwo);
+        // Verify not equals
+        assertNotEquals(two, one);
+        assertNotEquals(two, copyOfOne);
+        // Create policer id A
+        PolicerId a = PolicerId.policerId(A);
+        // Create policer id LA
+        PolicerId la = PolicerId.policerId(LA);
+        // Verify not equals
+        assertNotEquals(a, la);
+    }
+
+    /**
+     * Tests immutability of PolicerId.
+     */
+    @Test
+    public void testImmutability() {
+        ImmutableClassChecker.assertThatClassIsImmutable(PolicerId.class);
+    }
+
+}
diff --git a/core/api/src/test/java/org/onosproject/net/behaviour/trafficcontrol/PolicerTest.java b/core/api/src/test/java/org/onosproject/net/behaviour/trafficcontrol/PolicerTest.java
new file mode 100644
index 0000000..142f962
--- /dev/null
+++ b/core/api/src/test/java/org/onosproject/net/behaviour/trafficcontrol/PolicerTest.java
@@ -0,0 +1,343 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.net.behaviour.trafficcontrol;
+
+import com.google.common.collect.ImmutableList;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.onosproject.TestApplicationId;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.net.DeviceId;
+
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.*;
+import static org.onosproject.net.behaviour.trafficcontrol.Policer.Unit.KB_PER_SEC;
+import static org.onosproject.net.behaviour.trafficcontrol.Policer.Unit.MB_PER_SEC;
+import static org.onosproject.net.behaviour.trafficcontrol.TokenBucket.Action.DROP;
+import static org.onosproject.net.behaviour.trafficcontrol.TokenBucket.Action.DSCP_CLASS;
+import static org.onosproject.net.behaviour.trafficcontrol.TokenBucket.Action.DSCP_PRECEDENCE;
+
+/**
+ * Test class for policer implementation.
+ */
+public class PolicerTest {
+
+    // Fake Application Id
+    private static final ApplicationId FOO_APP_ID = new TestApplicationId("foo");
+    // Connect points
+    private static final String SDID1 = "of:00000000000001";
+    private static final DeviceId DID1 = DeviceId.deviceId(SDID1);
+    // OpenFlow scheme
+    private static final String OF_SCHEME = "of";
+    // Policers identifiers
+    private static final String SID1 = OF_SCHEME + ":" + Integer.toHexString(1);
+    private static final PolicerId ID1 = PolicerId.policerId(SID1);
+    private static final String SID2 = OF_SCHEME + ":" + Integer.toHexString(2);
+    private static final PolicerId ID2 = PolicerId.policerId(SID2);
+    private static final String SID3 = OF_SCHEME + ":" + Integer.toHexString(3);
+    private static final PolicerId ID3 = PolicerId.policerId(SID3);
+    private static final String SID4 = OF_SCHEME + ":" + Integer.toHexString(4);
+    private static final PolicerId ID4 = PolicerId.policerId(SID4);
+    private static final String SID5 = OF_SCHEME + ":" + Integer.toHexString(5);
+    private static final PolicerId ID5 = PolicerId.policerId(SID5);
+    private static final String SID6 = OF_SCHEME + ":" + Integer.toHexString(6);
+    private static final PolicerId ID6 = PolicerId.policerId(SID6);
+    private static final String SID7 = OF_SCHEME + ":" + Integer.toHexString(7);
+    private static final PolicerId ID7 = PolicerId.policerId(SID7);
+    private static final String SID8 = OF_SCHEME + ":" + Integer.toHexString(8);
+    private static final PolicerId ID8 = PolicerId.policerId(SID8);
+    private static final String SID9 = OF_SCHEME + ":" + Integer.toHexString(9);
+    private static final PolicerId ID9 = PolicerId.policerId(SID9);
+
+    /**
+     * Test block traffic policer.
+     */
+    @Test
+    public void testBlockCreation() {
+        // Create a block traffic token bucket
+        TokenBucket tokenBucket = DefaultTokenBucket.builder()
+                .withBurstSize(0)
+                .withAction(DROP)
+                .build();
+        // Create a policer with above token bucket
+        Policer policer = DefaultPolicer.builder()
+                .forDeviceId(DID1)
+                .fromApp(FOO_APP_ID)
+                .withId(ID1)
+                .withTokenBuckets(ImmutableList.of(tokenBucket))
+                .build();
+        // Assert on device id
+        assertThat(policer.deviceId(), is(DID1));
+        // Assert on app id
+        assertThat(policer.applicationId(), is(FOO_APP_ID));
+        // Assert on policer id
+        assertThat(policer.policerId(), is(ID1));
+        // It is not color aware
+        assertFalse(policer.isColorAware());
+        // Unit is Mbps
+        assertThat(policer.unit(), is(MB_PER_SEC));
+        // One token bucket
+        assertThat(policer.tokenBuckets().size(), is(1));
+        // One token bucket equals to tokenBucket
+        assertTrue(policer.tokenBuckets().contains(tokenBucket));
+    }
+
+    /**
+     * Test simple drop policer.
+     */
+    @Test
+    public void testDropCreation() {
+        // Create a drop traffic token bucket at 1MB/s
+        TokenBucket tokenBucket = DefaultTokenBucket.builder()
+                .withRate(1)
+                .withAction(DROP)
+                .build();
+        // Create a policer with above token bucket
+        Policer policer = DefaultPolicer.builder()
+                .forDeviceId(DID1)
+                .fromApp(FOO_APP_ID)
+                .withId(ID2)
+                .withTokenBuckets(ImmutableList.of(tokenBucket))
+                .build();
+        // Assert on device id
+        assertThat(policer.deviceId(), is(DID1));
+        // Assert on app id
+        assertThat(policer.applicationId(), is(FOO_APP_ID));
+        // Assert on policer id
+        assertThat(policer.policerId(), is(ID2));
+        // It is not color aware
+        assertFalse(policer.isColorAware());
+        // Unit is Mbps
+        assertThat(policer.unit(), is(MB_PER_SEC));
+        // One token bucket
+        assertThat(policer.tokenBuckets().size(), is(1));
+        // One token bucket equals to tokenBucket
+        assertTrue(policer.tokenBuckets().contains(tokenBucket));
+    }
+
+    /**
+     * Test simple mark policer.
+     */
+    @Test
+    public void testMarkCreation() {
+        // Create a drop traffic token bucket at 1MB/s
+        TokenBucket tokenBucket = DefaultTokenBucket.builder()
+                .withRate(1)
+                .withAction(DSCP_PRECEDENCE)
+                .withDscp((short) 2)
+                .build();
+        // Create a policer with above token bucket
+        Policer policer = DefaultPolicer.builder()
+                .forDeviceId(DID1)
+                .fromApp(FOO_APP_ID)
+                .withId(ID3)
+                .withTokenBuckets(ImmutableList.of(tokenBucket))
+                .build();
+        // Assert on device id
+        assertThat(policer.deviceId(), is(DID1));
+        // Assert on app id
+        assertThat(policer.applicationId(), is(FOO_APP_ID));
+        // Assert on policer id
+        assertThat(policer.policerId(), is(ID3));
+        // It is not color aware
+        assertFalse(policer.isColorAware());
+        // Unit is Mbps
+        assertThat(policer.unit(), is(MB_PER_SEC));
+        // One token bucket
+        assertThat(policer.tokenBuckets().size(), is(1));
+        // One token bucket equals to tokenBucket
+        assertTrue(policer.tokenBuckets().contains(tokenBucket));
+    }
+
+    /**
+     * Test single rate three colors scenario (RFC 2697).
+     */
+    @Test
+    public void testSingleRateThreeColors() {
+        // Create token bucket for committed rate
+        TokenBucket crTokenBucket = DefaultTokenBucket.builder()
+                .withRate(1)
+                .withAction(DSCP_PRECEDENCE)
+                .withDscp((short) 2)
+                .build();
+        // Create token bucket for excess rate
+        TokenBucket erTokenBucket = DefaultTokenBucket.builder()
+                .withRate(1)
+                .withBurstSize(4 * 1500)
+                .withAction(DROP)
+                .build();
+        // Create a policer with above token buckets
+        Policer policer = DefaultPolicer.builder()
+                .forDeviceId(DID1)
+                .fromApp(FOO_APP_ID)
+                .withId(ID4)
+                // The order is important
+                .withTokenBuckets(ImmutableList.of(crTokenBucket, erTokenBucket))
+                .build();
+        // Assert on device id
+        assertThat(policer.deviceId(), is(DID1));
+        // Assert on app id
+        assertThat(policer.applicationId(), is(FOO_APP_ID));
+        // Assert on policer id
+        assertThat(policer.policerId(), is(ID4));
+        // It is not color aware
+        assertFalse(policer.isColorAware());
+        // Unit is Mbps
+        assertThat(policer.unit(), is(MB_PER_SEC));
+        // Two token buckets
+        assertThat(policer.tokenBuckets().size(), is(2));
+        // One token bucket equals to crTokenBucket
+        assertTrue(policer.tokenBuckets().contains(crTokenBucket));
+        // One token bucket equals to erTokenBucket
+        assertTrue(policer.tokenBuckets().contains(erTokenBucket));
+    }
+
+    /**
+     * Test two rates three colors scenario (RFC 2698 and P4 meter).
+     */
+    @Test
+    public void testTwoRatesThreeColors() {
+        // Create token bucket for peak rate at 10Mb/s
+        TokenBucket prTokenBucket = DefaultTokenBucket.builder()
+                // (10 * 1000)/8 ---> 1250KB/s
+                .withRate(1250)
+                .withBurstSize(10 * 1500)
+                .withAction(DROP)
+                .build();
+        // Create token bucket for committed rate at 1Mb/s
+        TokenBucket crTokenBucket = DefaultTokenBucket.builder()
+                // (1 * 1000)/8 ---> 125KB/s
+                .withRate(125)
+                .withAction(DSCP_CLASS)
+                .withDscp((short) 10)
+                .build();
+        // Create a policer with above token buckets
+        Policer policer = DefaultPolicer.builder()
+                .forDeviceId(DID1)
+                .fromApp(FOO_APP_ID)
+                .withId(ID5)
+                .withUnit(KB_PER_SEC)
+                // The order is important
+                .withTokenBuckets(ImmutableList.of(prTokenBucket, crTokenBucket))
+                .build();
+        // Assert on device id
+        assertThat(policer.deviceId(), is(DID1));
+        // Assert on app id
+        assertThat(policer.applicationId(), is(FOO_APP_ID));
+        // Assert on policer id
+        assertThat(policer.policerId(), is(ID5));
+        // It is not color aware
+        assertFalse(policer.isColorAware());
+        // Unit is Mbps
+        assertThat(policer.unit(), is(KB_PER_SEC));
+        // Two token buckets
+        assertThat(policer.tokenBuckets().size(), is(2));
+        // One token bucket equals to prTokenBucket
+        assertTrue(policer.tokenBuckets().contains(prTokenBucket));
+        // One token bucket equals to crTokenBucket
+        assertTrue(policer.tokenBuckets().contains(crTokenBucket));
+    }
+
+    /**
+     * Exception expected to raise when creating a policer with null params.
+     */
+    @Rule
+    public ExpectedException exceptionNullParam = ExpectedException.none();
+
+    /**
+     * Test creation with null parameters.
+     */
+    @Test
+    public void testNullParam() {
+        // Define expected exception
+        exceptionNullParam.expect(NullPointerException.class);
+        // Invalid policer, device id is not defined
+        DefaultPolicer.builder()
+                .fromApp(FOO_APP_ID)
+                .withId(ID6)
+                .build();
+    }
+
+    /**
+     * Exception expected to raise when creating a policer without token buckets.
+     */
+    @Rule
+    public ExpectedException exceptionNoTokenBuckets = ExpectedException.none();
+
+    /**
+     * Test creation without token buckets.
+     */
+    @Test
+    public void testNoTokenBuckets() {
+        // Define expected exception
+        exceptionNoTokenBuckets.expect(IllegalArgumentException.class);
+        // Invalid policer, no token buckets
+        DefaultPolicer.builder()
+                .fromApp(FOO_APP_ID)
+                .withId(ID7)
+                .forDeviceId(DID1)
+                .withTokenBuckets(ImmutableList.of())
+                .build();
+    }
+
+    /**
+     * Test equality between policers.
+     */
+    @Test
+    public void testEqualilty() {
+        // Create a block traffic token bucket
+        TokenBucket blockTokenBucket = DefaultTokenBucket.builder()
+                .withBurstSize(0)
+                .withAction(DROP)
+                .build();
+        // Create a mark traffic token bucket
+        TokenBucket markTokenBucket = DefaultTokenBucket.builder()
+                .withBurstSize(0)
+                .withAction(DSCP_CLASS)
+                .withDscp((short) 10)
+                .build();
+        // Create first policer
+        Policer policerOne = DefaultPolicer.builder()
+                .forDeviceId(DID1)
+                .fromApp(FOO_APP_ID)
+                .withId(ID8)
+                .withTokenBuckets(ImmutableList.of(blockTokenBucket))
+                .build();
+        // Create second policer
+        Policer policerTwo = DefaultPolicer.builder()
+                .forDeviceId(DID1)
+                .fromApp(FOO_APP_ID)
+                .withId(ID9)
+                .withTokenBuckets(ImmutableList.of(markTokenBucket))
+                .build();
+        // Create third policer copy of one
+        // Create first policer
+        Policer policerThree = DefaultPolicer.builder()
+                .forDeviceId(DID1)
+                .fromApp(FOO_APP_ID)
+                .withId(ID8)
+                .withTokenBuckets(ImmutableList.of(blockTokenBucket))
+                .build();
+        // One and Three are equal
+        assertEquals(policerOne, policerThree);
+        // Two is different due to the different id
+        assertNotEquals(policerOne, policerTwo);
+        assertNotEquals(policerThree, policerTwo);
+    }
+
+}
diff --git a/core/api/src/test/java/org/onosproject/net/behaviour/trafficcontrol/PolicingResourceTest.java b/core/api/src/test/java/org/onosproject/net/behaviour/trafficcontrol/PolicingResourceTest.java
new file mode 100644
index 0000000..7f6d1f9
--- /dev/null
+++ b/core/api/src/test/java/org/onosproject/net/behaviour/trafficcontrol/PolicingResourceTest.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.net.behaviour.trafficcontrol;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.onlab.junit.ImmutableClassChecker;
+import org.onosproject.net.ConnectPoint;
+
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.junit.Assert.*;
+
+/**
+ * Test class for PolicingResource.
+ */
+public class PolicingResourceTest {
+
+    // Connectpoints
+    private static final String SCP1 = "of:00000000000001/1";
+    private static final String SCP2 = "of:00000000000001/2";
+    private static final ConnectPoint CP1 = ConnectPoint.deviceConnectPoint(SCP1);
+    private static final ConnectPoint CP2 = ConnectPoint.deviceConnectPoint(SCP2);
+    // OpenFlow scheme
+    private static final String OF_SCHEME = "of";
+    // Policer identifier
+    private static final String SID = OF_SCHEME + ":" + Integer.toHexString(1);
+    private static final PolicerId PID = PolicerId.policerId(SID);
+
+    /**
+     * Test policing resource creation.
+     */
+    @Test
+    public void testCreation() {
+        // Create a new policing resource
+        PolicingResource policingResource = new PolicingResource(PID, CP1);
+        // Verify proper creation
+        assertThat(policingResource, notNullValue());
+        assertThat(policingResource.policerId(), is(PID));
+        assertThat(policingResource.connectPoint(), is(CP1));
+    }
+
+    /**
+     * Exception expected to raise when creating policing resource with null id.
+     */
+    @Rule
+    public ExpectedException exceptionNullId = ExpectedException.none();
+
+    /**
+     * Test wrong creation of a policing resource.
+     */
+    @Test
+    public void testNullIdCreation() {
+        // Define expected exception
+        exceptionNullId.expect(NullPointerException.class);
+        // Create wrong policing resource
+        new PolicingResource(null, CP1);
+    }
+
+    /**
+     * Test equality between policing resources.
+     */
+    @Test
+    public void testEqualilty() {
+        // Create two identical resources
+        PolicingResource one = new PolicingResource(PID, CP1);
+        PolicingResource copyOfOne = new PolicingResource(PID, CP1);
+        // Verify equality
+        assertEquals(one, copyOfOne);
+        // Create a different resource
+        PolicingResource two = new PolicingResource(PID, CP2);
+        // Verify not equals
+        assertNotEquals(two, one);
+        assertNotEquals(two, copyOfOne);
+    }
+
+    /**
+     * Tests immutability of PolicingResource.
+     */
+    @Test
+    public void testImmutability() {
+        ImmutableClassChecker.assertThatClassIsImmutable(PolicingResource.class);
+    }
+
+}
diff --git a/core/api/src/test/java/org/onosproject/net/behaviour/trafficcontrol/TokenBucketTest.java b/core/api/src/test/java/org/onosproject/net/behaviour/trafficcontrol/TokenBucketTest.java
new file mode 100644
index 0000000..7deedda
--- /dev/null
+++ b/core/api/src/test/java/org/onosproject/net/behaviour/trafficcontrol/TokenBucketTest.java
@@ -0,0 +1,179 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.net.behaviour.trafficcontrol;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.junit.Assert.*;
+import static org.onosproject.net.behaviour.trafficcontrol.TokenBucket.Action.DROP;
+import static org.onosproject.net.behaviour.trafficcontrol.TokenBucket.Action.DSCP_CLASS;
+import static org.onosproject.net.behaviour.trafficcontrol.TokenBucket.Action.DSCP_PRECEDENCE;
+
+/**
+ * Test class for TokenBucket.
+ */
+public class TokenBucketTest {
+
+    // Test rate
+    private static final long RATE = 1;
+    // Test dscp drop precedence
+    private static final short DSCP_PREC = 2;
+    // Test dscp class
+    private static final short DSCP_CL = 250;
+    // Test wrong dscp
+    private static final short WRONG_DSCP = -1;
+
+    /**
+     * Test creation of a drop token bucket.
+     */
+    @Test
+    public void testDropCreation() {
+        // Create a drop token bucket
+        TokenBucket drop = DefaultTokenBucket.builder()
+                .withRate(RATE)
+                .withAction(DROP)
+                .build();
+        // Not null
+        assertThat(drop, notNullValue());
+        // Rate should be equal to RATE
+        assertThat(drop.rate(), is(RATE));
+        // Burst size should be equal to 2xMTU
+        assertThat(drop.burstSize(), is(2 * 1500L));
+        // Action should be drop
+        assertThat(drop.action(), is(DROP));
+    }
+
+    /**
+     * Test creation of a dscp precedence token bucket.
+     */
+    @Test
+    public void testDscpPrecCreation() {
+        // Create a dscp precedence token bucket
+        TokenBucket drop = DefaultTokenBucket.builder()
+                .withRate(RATE)
+                .withAction(DSCP_PRECEDENCE)
+                .withBurstSize(6 * 1500)
+                .withDscp(DSCP_PREC)
+                .build();
+        // Not null
+        assertThat(drop, notNullValue());
+        // Rate should be equal to RATE
+        assertThat(drop.rate(), is(RATE));
+        // Burst size should be equal to 6xMTU
+        assertThat(drop.burstSize(), is(6 * 1500L));
+        // Action should increase dscp drop precedence
+        assertThat(drop.action(), is(DSCP_PRECEDENCE));
+        // Dcsp drop precedence should be increased of 2
+        assertThat(drop.dscp(), is(DSCP_PREC));
+    }
+
+    /**
+     * Test creation of a dscp class token bucket.
+     */
+    @Test
+    public void testDscpClassCreation() {
+        // Create a dscp class token bucket
+        TokenBucket drop = DefaultTokenBucket.builder()
+                .withRate(RATE)
+                .withAction(DSCP_CLASS)
+                .withDscp(DSCP_CL)
+                .build();
+        // Not null
+        assertThat(drop, notNullValue());
+        // Rate should be equal to RATE
+        assertThat(drop.rate(), is(RATE));
+        // Burst size should be equal to 2xMTU
+        assertThat(drop.burstSize(), is(2 * 1500L));
+        // Action should be drop
+        assertThat(drop.action(), is(DSCP_CLASS));
+        // Dcsp drop precedence should be increased of 2
+        assertThat(drop.dscp(), is(DSCP_CL));
+    }
+
+    /**
+     * Exception expected to raise when creating a token bucket with null action.
+     */
+    @Rule
+    public ExpectedException exceptionNullAction = ExpectedException.none();
+
+    /**
+     * Test creation of a token bucket with null action.
+     */
+    @Test
+    public void testNullActionCreation() {
+        // Define expected exception
+        exceptionNullAction.expect(NullPointerException.class);
+        // Create a token bucket without action
+        TokenBucket drop = DefaultTokenBucket.builder()
+                .withRate(RATE)
+                .build();
+    }
+
+    /**
+     * Exception expected to raise when creating a token bucket with wrong dscp.
+     */
+    @Rule
+    public ExpectedException exceptionWrongDscp = ExpectedException.none();
+
+    /**
+     * Test creation of a token bucket with wrong dscp.
+     */
+    @Test
+    public void testWrongDscpCreation() {
+        // Define expected exception
+        exceptionWrongDscp.expect(IllegalArgumentException.class);
+        // Create a token bucket with wrong dscp
+        TokenBucket drop = DefaultTokenBucket.builder()
+                .withRate(RATE)
+                .withAction(DSCP_PRECEDENCE)
+                .withDscp(WRONG_DSCP)
+                .build();
+    }
+
+    /**
+     * Test equality between policer ids.
+     */
+    @Test
+    public void testEqualilty() {
+        // Create a drop token bucket
+        TokenBucket drop = DefaultTokenBucket.builder()
+                .withRate(RATE)
+                .withAction(DROP)
+                .build();
+        // Create a mark token bucket
+        TokenBucket mark = DefaultTokenBucket.builder()
+                .withRate(RATE)
+                .withAction(DSCP_PRECEDENCE)
+                .withDscp(DSCP_PREC)
+                .build();
+        // Create a copy of the drop token bucket
+        TokenBucket copyDrop = DefaultTokenBucket.builder()
+                .withRate(RATE)
+                .withAction(DROP)
+                .build();
+        // Verify equality
+        assertEquals(drop, copyDrop);
+        // Verify not equals
+        assertNotEquals(mark, drop);
+        assertNotEquals(mark, copyDrop);
+    }
+
+}
diff --git a/core/api/src/test/java/org/onosproject/net/behaviour/trafficcontrol/package-info.java b/core/api/src/test/java/org/onosproject/net/behaviour/trafficcontrol/package-info.java
new file mode 100644
index 0000000..63c5f92
--- /dev/null
+++ b/core/api/src/test/java/org/onosproject/net/behaviour/trafficcontrol/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Test class for traffic control behaviors and related classes.
+ */
+package org.onosproject.net.behaviour.trafficcontrol;