Implement some of the missing Selector and Match Conditions

Work toward ONOS-509

The following match conditions are added/implemented:
  - IPV6_EXTHDR

Also, fixed the match criteria for the optical signal type
to represent unsigned 8 bits integer (per spec).

Change-Id: I925db19cb43c5d9f589c1f090b6a75faabe0a19b
diff --git a/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficSelector.java b/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficSelector.java
index aa9405db..f3f3bf8 100644
--- a/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficSelector.java
+++ b/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficSelector.java
@@ -280,6 +280,11 @@
         }
 
         @Override
+        public Builder matchIPv6ExthdrFlags(Integer exthdrFlags) {
+            return add(Criteria.matchIPv6ExthdrFlags(exthdrFlags));
+        }
+
+        @Override
         public Builder matchLambda(Short lambda) {
             return add(Criteria.matchLambda(lambda));
         }
diff --git a/core/api/src/main/java/org/onosproject/net/flow/TrafficSelector.java b/core/api/src/main/java/org/onosproject/net/flow/TrafficSelector.java
index 1ecab71..7d31b08 100644
--- a/core/api/src/main/java/org/onosproject/net/flow/TrafficSelector.java
+++ b/core/api/src/main/java/org/onosproject/net/flow/TrafficSelector.java
@@ -300,6 +300,14 @@
         public Builder matchMplsLabel(Integer mplsLabel);
 
         /**
+         * Matches on IPv6 Extension Header pseudo-field fiags.
+         *
+         * @param exthdrFlags the IPv6 Extension Header pseudo-field fiags
+         * @return a selection builder
+         */
+        public Builder matchIPv6ExthdrFlags(Integer exthdrFlags);
+
+        /**
          * Matches an optical signal ID or lambda.
          *
          * @param lambda lamda
diff --git a/core/api/src/main/java/org/onosproject/net/flow/criteria/Criteria.java b/core/api/src/main/java/org/onosproject/net/flow/criteria/Criteria.java
index 3c32dea..34893a4 100644
--- a/core/api/src/main/java/org/onosproject/net/flow/criteria/Criteria.java
+++ b/core/api/src/main/java/org/onosproject/net/flow/criteria/Criteria.java
@@ -62,7 +62,7 @@
      * @param metadata metadata value (64 bits data)
      * @return match criterion
      */
-    public static Criterion matchMetadata(Long metadata) {
+    public static Criterion matchMetadata(long metadata) {
         return new MetadataCriterion(metadata);
     }
 
@@ -338,11 +338,22 @@
      * @param mplsLabel MPLS label (20 bits)
      * @return match criterion
      */
-    public static Criterion matchMplsLabel(Integer mplsLabel) {
+    public static Criterion matchMplsLabel(int mplsLabel) {
         return new MplsCriterion(mplsLabel);
     }
 
     /**
+     * Creates a match on IPv6 Extension Header pseudo-field fiags.
+     * Those are defined in Criterion.IPv6ExthdrFlags.
+     *
+     * @param exthdrFlags IPv6 Extension Header pseudo-field flags (16 bits)
+     * @return match criterion
+     */
+    public static Criterion matchIPv6ExthdrFlags(int exthdrFlags) {
+        return new IPv6ExthdrFlagsCriterion(exthdrFlags);
+    }
+
+    /**
      * Creates a match on lambda field using the specified value.
      *
      * @param lambda lambda to match on (16 bits unsigned integer)
@@ -355,10 +366,10 @@
     /**
      * Creates a match on optical signal type using the specified value.
      *
-     * @param sigType optical signal type (16 bits unsigned integer)
+     * @param sigType optical signal type (8 bits unsigned integer)
      * @return match criterion
      */
-    public static Criterion matchOpticalSignalType(int sigType) {
+    public static Criterion matchOpticalSignalType(short sigType) {
         return new OpticalSignalTypeCriterion(sigType, Type.OCH_SIGTYPE);
     }
 
@@ -1550,6 +1561,64 @@
     }
 
     /**
+     * Implementation of IPv6 Extension Header pseudo-field criterion
+     * (16 bits). Those are defined in Criterion.IPv6ExthdrFlags.
+     */
+    public static final class IPv6ExthdrFlagsCriterion implements Criterion {
+        private static final int MASK = 0xffff;
+        private final int exthdrFlags;          // IPv6 Exthdr flags: 16 bits
+
+        /**
+         * Constructor.
+         *
+         * @param exthdrFlags the IPv6 Extension Header pseudo-field flags
+         * to match (16 bits). Those are defined in Criterion.IPv6ExthdrFlags
+         */
+        public IPv6ExthdrFlagsCriterion(int exthdrFlags) {
+            this.exthdrFlags = exthdrFlags & MASK;
+        }
+
+        @Override
+        public Type type() {
+            return Type.IPV6_EXTHDR;
+        }
+
+        /**
+         * Gets the IPv6 Extension Header pseudo-field flags to match.
+         *
+         * @return the IPv6 Extension Header pseudo-field flags to match
+         * (16 bits). Those are defined in Criterion.IPv6ExthdrFlags
+         */
+        public int exthdrFlags() {
+            return exthdrFlags;
+        }
+
+        @Override
+        public String toString() {
+            return toStringHelper(type().toString())
+                .add("exthdrFlags", Long.toHexString(exthdrFlags)).toString();
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(type(), exthdrFlags);
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj) {
+                return true;
+            }
+            if (obj instanceof IPv6ExthdrFlagsCriterion) {
+                IPv6ExthdrFlagsCriterion that = (IPv6ExthdrFlagsCriterion) obj;
+                return Objects.equals(exthdrFlags, that.exthdrFlags) &&
+                        Objects.equals(this.type(), that.type());
+            }
+            return false;
+        }
+    }
+
+    /**
      * Implementation of lambda (wavelength) criterion (16 bits unsigned
      * integer).
      */
@@ -1610,23 +1679,23 @@
     }
 
     /**
-     * Implementation of optical signal type criterion (16 bits unsigned
+     * Implementation of optical signal type criterion (8 bits unsigned
      * integer).
      */
     public static final class OpticalSignalTypeCriterion implements Criterion {
-        private static final int MASK = 0xffff;
-        private final int signalType;           // Signal type value: 16 bits
+        private static final short MASK = 0xff;
+        private final short signalType;         // Signal type value: 8 bits
         private final Type type;
 
         /**
          * Constructor.
          *
-         * @param signalType the optical signal type to match (16 bits unsigned
+         * @param signalType the optical signal type to match (8 bits unsigned
          * integer)
          * @param type the match type. Should be Type.OCH_SIGTYPE
          */
-        public OpticalSignalTypeCriterion(int signalType, Type type) {
-            this.signalType = signalType & MASK;
+        public OpticalSignalTypeCriterion(short signalType, Type type) {
+            this.signalType = (short) (signalType & MASK);
             this.type = type;
         }
 
@@ -1638,9 +1707,9 @@
         /**
          * Gets the optical signal type to match.
          *
-         * @return the optical signal type to match
+         * @return the optical signal type to match (8 bits unsigned integer)
          */
-        public int signalType() {
+        public short signalType() {
             return signalType;
         }
 
diff --git a/core/api/src/main/java/org/onosproject/net/flow/criteria/Criterion.java b/core/api/src/main/java/org/onosproject/net/flow/criteria/Criterion.java
index 6122567..25764d4 100644
--- a/core/api/src/main/java/org/onosproject/net/flow/criteria/Criterion.java
+++ b/core/api/src/main/java/org/onosproject/net/flow/criteria/Criterion.java
@@ -129,11 +129,48 @@
 
     /**
      * Returns the type of criterion.
+     *
      * @return type of criterion
      */
     public Type type();
 
-    // TODO: Create factory class 'Criteria' that will have various factory
-    // to create specific criterions.
+    /**
+     * Bit definitions for IPv6 Extension Header pseudo-field.
+     * From page 79 of OpenFlow 1.5.0 spec.
+     */
+    public enum IPv6ExthdrFlags {
+        /** "No next header" encountered. */
+        NONEXT(1 << 0),
+        /** Encrypted Sec Payload header present. */
+        ESP(1 << 1),
+        /** Authentication header present. */
+        AUTH(1 << 2),
+        /** 1 or 2 dest headers present. */
+        DEST(1 << 3),
+        /** Fragment header present. */
+        FRAG(1 << 4),
+        /** Router header present. */
+        ROUTER(1 << 5),
+        /** Hop-by-hop header present. */
+        HOP(1 << 6),
+        /** Unexpected repeats encountered. */
+        UNREP(1 << 7),
+        /** Unexpected sequencing encountered. */
+        UNSEQ(1 << 8);
 
+        private int value;
+
+        IPv6ExthdrFlags(int value) {
+            this.value = value;
+        }
+
+        /**
+         * Gets the value as an integer.
+         *
+         * @return the value as an integer
+         */
+        public int getValue() {
+            return this.value;
+        }
+    }
 }
diff --git a/core/api/src/test/java/org/onosproject/net/flow/DefaultTrafficSelectorTest.java b/core/api/src/test/java/org/onosproject/net/flow/DefaultTrafficSelectorTest.java
index 3fb62a7..68c15ff 100644
--- a/core/api/src/test/java/org/onosproject/net/flow/DefaultTrafficSelectorTest.java
+++ b/core/api/src/test/java/org/onosproject/net/flow/DefaultTrafficSelectorTest.java
@@ -255,6 +255,10 @@
         assertThat(selector, hasCriterionWithType(Type.MPLS_LABEL));
 
         selector = DefaultTrafficSelector.builder()
+                .matchIPv6ExthdrFlags(Criterion.IPv6ExthdrFlags.NONEXT.getValue()).build();
+        assertThat(selector, hasCriterionWithType(Type.IPV6_EXTHDR));
+
+        selector = DefaultTrafficSelector.builder()
                 .matchLambda(shortValue).build();
         assertThat(selector, hasCriterionWithType(Type.OCH_SIGID));
 
diff --git a/core/api/src/test/java/org/onosproject/net/flow/criteria/CriteriaTest.java b/core/api/src/test/java/org/onosproject/net/flow/criteria/CriteriaTest.java
index b9e1233..42a7281 100644
--- a/core/api/src/test/java/org/onosproject/net/flow/criteria/CriteriaTest.java
+++ b/core/api/src/test/java/org/onosproject/net/flow/criteria/CriteriaTest.java
@@ -192,14 +192,32 @@
     Criterion sameAsMatchMpls1 = Criteria.matchMplsLabel(mpls1);
     Criterion matchMpls2 = Criteria.matchMplsLabel(mpls2);
 
+    int ipv6ExthdrFlags1 =
+        Criterion.IPv6ExthdrFlags.NONEXT.getValue() |
+        Criterion.IPv6ExthdrFlags.ESP.getValue() |
+        Criterion.IPv6ExthdrFlags.AUTH.getValue() |
+        Criterion.IPv6ExthdrFlags.DEST.getValue() |
+        Criterion.IPv6ExthdrFlags.FRAG.getValue() |
+        Criterion.IPv6ExthdrFlags.ROUTER.getValue() |
+        Criterion.IPv6ExthdrFlags.HOP.getValue() |
+        Criterion.IPv6ExthdrFlags.UNREP.getValue();
+    int ipv6ExthdrFlags2 = ipv6ExthdrFlags1 |
+        Criterion.IPv6ExthdrFlags.UNSEQ.getValue();
+    Criterion matchIpv6ExthdrFlags1 =
+        Criteria.matchIPv6ExthdrFlags(ipv6ExthdrFlags1);
+    Criterion sameAsMatchIpv6ExthdrFlags1 =
+        Criteria.matchIPv6ExthdrFlags(ipv6ExthdrFlags1);
+    Criterion matchIpv6ExthdrFlags2 =
+        Criteria.matchIPv6ExthdrFlags(ipv6ExthdrFlags2);
+
     int lambda1 = 1;
     int lambda2 = 2;
     Criterion matchLambda1 = Criteria.matchLambda(lambda1);
     Criterion sameAsMatchLambda1 = Criteria.matchLambda(lambda1);
     Criterion matchLambda2 = Criteria.matchLambda(lambda2);
 
-    int signalLambda1 = 1;
-    int signalLambda2 = 2;
+    short signalLambda1 = 1;
+    short signalLambda2 = 2;
     Criterion matchSignalLambda1 = Criteria.matchOpticalSignalType(signalLambda1);
     Criterion sameAsMatchSignalLambda1 = Criteria.matchOpticalSignalType(signalLambda1);
     Criterion matchSignalLambda2 = Criteria.matchOpticalSignalType(signalLambda2);
@@ -256,6 +274,7 @@
         assertThatClassIsImmutable(Criteria.IPv6NDTargetAddressCriterion.class);
         assertThatClassIsImmutable(Criteria.IPv6NDLinkLayerAddressCriterion.class);
         assertThatClassIsImmutable(Criteria.MplsCriterion.class);
+        assertThatClassIsImmutable(Criteria.IPv6ExthdrFlagsCriterion.class);
         assertThatClassIsImmutable(Criteria.LambdaCriterion.class);
         assertThatClassIsImmutable(Criteria.OpticalSignalTypeCriterion.class);
     }
@@ -952,6 +971,35 @@
                 .testEquals();
     }
 
+    // IPv6ExthdrFlagsCriterion class
+
+    /**
+     * Test the matchIPv6ExthdrFlags method.
+     */
+    @Test
+    public void testMatchIPv6ExthdrFlagsMethod() {
+        Criterion matchExthdrFlags =
+            Criteria.matchIPv6ExthdrFlags(ipv6ExthdrFlags1);
+        Criteria.IPv6ExthdrFlagsCriterion exthdrFlagsCriterion =
+                checkAndConvert(matchExthdrFlags,
+                        Criterion.Type.IPV6_EXTHDR,
+                        Criteria.IPv6ExthdrFlagsCriterion.class);
+        assertThat(exthdrFlagsCriterion.exthdrFlags(),
+                   is(equalTo(ipv6ExthdrFlags1)));
+    }
+
+    /**
+     * Test the equals() method of the IPv6ExthdrFlagsCriterion class.
+     */
+    @Test
+    public void testIPv6ExthdrFlagsCriterionEquals() {
+        new EqualsTester()
+                .addEqualityGroup(matchIpv6ExthdrFlags1,
+                                  sameAsMatchIpv6ExthdrFlags1)
+                .addEqualityGroup(matchIpv6ExthdrFlags2)
+                .testEquals();
+    }
+
     // LambdaCriterion class
 
     /**