[ONOS-7208] Improves policer with rate type

Change-Id: Idf20fce19bfc071193f55609d3bb7297d2dee479
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
index f3920b2..8313f3f 100644
--- 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
@@ -18,6 +18,7 @@
 
 import com.google.common.annotations.Beta;
 import com.google.common.base.Objects;
+import org.onosproject.net.behaviour.trafficcontrol.TokenBucket.Type;
 
 import static com.google.common.base.MoreObjects.toStringHelper;
 import static com.google.common.base.Preconditions.checkArgument;
@@ -36,16 +37,18 @@
     private final long burstSize;
     private final Action action;
     private final short dscp;
+    private final Type type;
 
     // Mutable parameters
     private long processedPackets;
     private long processedBytes;
 
-    private DefaultTokenBucket(long r, long bS, Action a, short d) {
+    private DefaultTokenBucket(long r, long bS, Action a, short d, Type t) {
         rate = r;
         burstSize = bS;
         action = a;
         dscp = d;
+        type = t;
     }
 
     @Override
@@ -69,6 +72,11 @@
     }
 
     @Override
+    public Type type() {
+        return type;
+    }
+
+    @Override
     public long processedPackets() {
         return processedPackets;
     }
@@ -94,7 +102,8 @@
                 .add("rate", rate())
                 .add("burstSize", burstSize())
                 .add("action", action())
-                .add("dscp", dscp()).toString();
+                .add("dscp", dscp())
+                .add("type", type()).toString();
     }
 
     @Override
@@ -109,12 +118,13 @@
         return rate == that.rate &&
                 burstSize == that.burstSize &&
                 Objects.equal(action, that.action) &&
-                dscp == that.dscp;
+                dscp == that.dscp &&
+                Objects.equal(type, that.type);
     }
 
     @Override
     public int hashCode() {
-        return Objects.hashCode(rate, burstSize, action, dscp);
+        return Objects.hashCode(rate, burstSize, action, dscp, type);
     }
 
     /**
@@ -136,6 +146,7 @@
         private long burstSize = 2 * 1500;
         private Action action;
         private short dscp;
+        private Type type;
 
         @Override
         public TokenBucket.Builder withRate(long r) {
@@ -162,9 +173,16 @@
         }
 
         @Override
+        public TokenBucket.Builder withType(Type t) {
+            type = t;
+            return this;
+        }
+
+        @Override
         public DefaultTokenBucket build() {
-            // Not null condition on the action
+            // Not null condition on the action and on the type
             checkNotNull(action, "Must specify an action");
+            checkNotNull(type, "Must specify a type");
 
             // If action is based on DSCP modification
             if (action == DSCP_CLASS || action == DSCP_PRECEDENCE) {
@@ -173,7 +191,7 @@
             }
 
             // Finally we build the token bucket
-            return new DefaultTokenBucket(rate, burstSize, action, dscp);
+            return new DefaultTokenBucket(rate, burstSize, action, dscp, type);
         }
     }
 }
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
index a86466b..7e3a943 100644
--- 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
@@ -36,8 +36,26 @@
     short MIN_DSCP = 0;
 
     /**
+     * Token bucket type.
+     */
+    enum Type {
+        /**
+         * Committed rate.
+         */
+        COMMITTED,
+        /**
+         * Excess rate.
+         */
+        EXCESS,
+        /**
+         * Peak rate.
+         */
+        PEAK
+    }
+
+    /**
      * Action applied to the exceeding traffic.
-     * Action depends on the tocken bucket type
+     * Action in general depends on the token bucket type.
      */
     enum Action {
         /**
@@ -90,6 +108,13 @@
     short dscp();
 
     /**
+     * Token bucket type.
+     *
+     * @return the token bucket type
+     */
+    Type type();
+
+    /**
      * Stats which reports how many packets have been
      * processed so far.
      *
@@ -152,6 +177,16 @@
         Builder withDscp(short dscp);
 
         /**
+         * Assigns the type to this token bucket.
+         * <p>
+         * Note: mandatory setter for this builder
+         * </p>
+         * @param type the type
+         * @return this
+         */
+        Builder withType(Type type);
+
+        /**
          * Builds the token bucket based on the specified
          * parameters when possible.
          *
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
index 142f962..ba5d7cd 100644
--- 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
@@ -31,6 +31,9 @@
 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;
+import static org.onosproject.net.behaviour.trafficcontrol.TokenBucket.Type.COMMITTED;
+import static org.onosproject.net.behaviour.trafficcontrol.TokenBucket.Type.EXCESS;
+import static org.onosproject.net.behaviour.trafficcontrol.TokenBucket.Type.PEAK;
 
 /**
  * Test class for policer implementation.
@@ -73,6 +76,7 @@
         TokenBucket tokenBucket = DefaultTokenBucket.builder()
                 .withBurstSize(0)
                 .withAction(DROP)
+                .withType(COMMITTED)
                 .build();
         // Create a policer with above token bucket
         Policer policer = DefaultPolicer.builder()
@@ -106,6 +110,7 @@
         TokenBucket tokenBucket = DefaultTokenBucket.builder()
                 .withRate(1)
                 .withAction(DROP)
+                .withType(COMMITTED)
                 .build();
         // Create a policer with above token bucket
         Policer policer = DefaultPolicer.builder()
@@ -140,6 +145,7 @@
                 .withRate(1)
                 .withAction(DSCP_PRECEDENCE)
                 .withDscp((short) 2)
+                .withType(COMMITTED)
                 .build();
         // Create a policer with above token bucket
         Policer policer = DefaultPolicer.builder()
@@ -174,12 +180,14 @@
                 .withRate(1)
                 .withAction(DSCP_PRECEDENCE)
                 .withDscp((short) 2)
+                .withType(COMMITTED)
                 .build();
         // Create token bucket for excess rate
         TokenBucket erTokenBucket = DefaultTokenBucket.builder()
                 .withRate(1)
                 .withBurstSize(4 * 1500)
                 .withAction(DROP)
+                .withType(EXCESS)
                 .build();
         // Create a policer with above token buckets
         Policer policer = DefaultPolicer.builder()
@@ -218,6 +226,7 @@
                 .withRate(1250)
                 .withBurstSize(10 * 1500)
                 .withAction(DROP)
+                .withType(PEAK)
                 .build();
         // Create token bucket for committed rate at 1Mb/s
         TokenBucket crTokenBucket = DefaultTokenBucket.builder()
@@ -225,6 +234,7 @@
                 .withRate(125)
                 .withAction(DSCP_CLASS)
                 .withDscp((short) 10)
+                .withType(COMMITTED)
                 .build();
         // Create a policer with above token buckets
         Policer policer = DefaultPolicer.builder()
@@ -304,12 +314,14 @@
         TokenBucket blockTokenBucket = DefaultTokenBucket.builder()
                 .withBurstSize(0)
                 .withAction(DROP)
+                .withType(COMMITTED)
                 .build();
         // Create a mark traffic token bucket
         TokenBucket markTokenBucket = DefaultTokenBucket.builder()
                 .withBurstSize(0)
                 .withAction(DSCP_CLASS)
                 .withDscp((short) 10)
+                .withType(COMMITTED)
                 .build();
         // Create first policer
         Policer policerOne = DefaultPolicer.builder()
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
index 7deedda..7f3d818 100644
--- 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
@@ -26,6 +26,9 @@
 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;
+import static org.onosproject.net.behaviour.trafficcontrol.TokenBucket.Type.COMMITTED;
+import static org.onosproject.net.behaviour.trafficcontrol.TokenBucket.Type.EXCESS;
+import static org.onosproject.net.behaviour.trafficcontrol.TokenBucket.Type.PEAK;
 
 /**
  * Test class for TokenBucket.
@@ -50,6 +53,7 @@
         TokenBucket drop = DefaultTokenBucket.builder()
                 .withRate(RATE)
                 .withAction(DROP)
+                .withType(COMMITTED)
                 .build();
         // Not null
         assertThat(drop, notNullValue());
@@ -59,6 +63,8 @@
         assertThat(drop.burstSize(), is(2 * 1500L));
         // Action should be drop
         assertThat(drop.action(), is(DROP));
+        // For committed rate
+        assertThat(drop.type(), is(COMMITTED));
     }
 
     /**
@@ -67,22 +73,25 @@
     @Test
     public void testDscpPrecCreation() {
         // Create a dscp precedence token bucket
-        TokenBucket drop = DefaultTokenBucket.builder()
+        TokenBucket mark = DefaultTokenBucket.builder()
                 .withRate(RATE)
                 .withAction(DSCP_PRECEDENCE)
                 .withBurstSize(6 * 1500)
                 .withDscp(DSCP_PREC)
+                .withType(EXCESS)
                 .build();
         // Not null
-        assertThat(drop, notNullValue());
+        assertThat(mark, notNullValue());
         // Rate should be equal to RATE
-        assertThat(drop.rate(), is(RATE));
+        assertThat(mark.rate(), is(RATE));
         // Burst size should be equal to 6xMTU
-        assertThat(drop.burstSize(), is(6 * 1500L));
+        assertThat(mark.burstSize(), is(6 * 1500L));
         // Action should increase dscp drop precedence
-        assertThat(drop.action(), is(DSCP_PRECEDENCE));
+        assertThat(mark.action(), is(DSCP_PRECEDENCE));
         // Dcsp drop precedence should be increased of 2
-        assertThat(drop.dscp(), is(DSCP_PREC));
+        assertThat(mark.dscp(), is(DSCP_PREC));
+        // For excess rate
+        assertThat(mark.type(), is(EXCESS));
     }
 
     /**
@@ -91,21 +100,24 @@
     @Test
     public void testDscpClassCreation() {
         // Create a dscp class token bucket
-        TokenBucket drop = DefaultTokenBucket.builder()
+        TokenBucket mark = DefaultTokenBucket.builder()
                 .withRate(RATE)
                 .withAction(DSCP_CLASS)
                 .withDscp(DSCP_CL)
+                .withType(PEAK)
                 .build();
         // Not null
-        assertThat(drop, notNullValue());
+        assertThat(mark, notNullValue());
         // Rate should be equal to RATE
-        assertThat(drop.rate(), is(RATE));
+        assertThat(mark.rate(), is(RATE));
         // Burst size should be equal to 2xMTU
-        assertThat(drop.burstSize(), is(2 * 1500L));
+        assertThat(mark.burstSize(), is(2 * 1500L));
         // Action should be drop
-        assertThat(drop.action(), is(DSCP_CLASS));
+        assertThat(mark.action(), is(DSCP_CLASS));
         // Dcsp drop precedence should be increased of 2
-        assertThat(drop.dscp(), is(DSCP_CL));
+        assertThat(mark.dscp(), is(DSCP_CL));
+        // For peak rate
+        assertThat(mark.type(), is(PEAK));
     }
 
     /**
@@ -122,7 +134,7 @@
         // Define expected exception
         exceptionNullAction.expect(NullPointerException.class);
         // Create a token bucket without action
-        TokenBucket drop = DefaultTokenBucket.builder()
+        DefaultTokenBucket.builder()
                 .withRate(RATE)
                 .build();
     }
@@ -141,10 +153,11 @@
         // Define expected exception
         exceptionWrongDscp.expect(IllegalArgumentException.class);
         // Create a token bucket with wrong dscp
-        TokenBucket drop = DefaultTokenBucket.builder()
+        DefaultTokenBucket.builder()
                 .withRate(RATE)
                 .withAction(DSCP_PRECEDENCE)
                 .withDscp(WRONG_DSCP)
+                .withType(COMMITTED)
                 .build();
     }
 
@@ -157,17 +170,20 @@
         TokenBucket drop = DefaultTokenBucket.builder()
                 .withRate(RATE)
                 .withAction(DROP)
+                .withType(COMMITTED)
                 .build();
         // Create a mark token bucket
         TokenBucket mark = DefaultTokenBucket.builder()
                 .withRate(RATE)
                 .withAction(DSCP_PRECEDENCE)
                 .withDscp(DSCP_PREC)
+                .withType(COMMITTED)
                 .build();
         // Create a copy of the drop token bucket
         TokenBucket copyDrop = DefaultTokenBucket.builder()
                 .withRate(RATE)
                 .withAction(DROP)
+                .withType(COMMITTED)
                 .build();
         // Verify equality
         assertEquals(drop, copyDrop);