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
 
     /**
diff --git a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowEntryBuilder.java b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowEntryBuilder.java
index 95e37d0..04ff897 100644
--- a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowEntryBuilder.java
+++ b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowEntryBuilder.java
@@ -410,7 +410,6 @@
             case IPV4_SRC:
                 if (match.isPartiallyMasked(MatchField.IPV4_SRC)) {
                     Masked<IPv4Address> maskedIp = match.getMasked(MatchField.IPV4_SRC);
-
                     ip4Prefix = Ip4Prefix.valueOf(
                             maskedIp.getValue().getInt(),
                             maskedIp.getMask().asCidrMaskLength());
@@ -419,13 +418,11 @@
                             match.get(MatchField.IPV4_SRC).getInt(),
                             Ip4Prefix.MAX_MASK_LENGTH);
                 }
-
                 builder.matchIPSrc(ip4Prefix);
                 break;
             case IPV4_DST:
                 if (match.isPartiallyMasked(MatchField.IPV4_DST)) {
                     Masked<IPv4Address> maskedIp = match.getMasked(MatchField.IPV4_DST);
-
                     ip4Prefix = Ip4Prefix.valueOf(
                             maskedIp.getValue().getInt(),
                             maskedIp.getMask().asCidrMaskLength());
@@ -434,7 +431,6 @@
                             match.get(MatchField.IPV4_DST).getInt(),
                             Ip4Prefix.MAX_MASK_LENGTH);
                 }
-
                 builder.matchIPDst(ip4Prefix);
                 break;
             case TCP_SRC:
@@ -519,6 +515,10 @@
                 builder.matchMplsLabel((int) match.get(MatchField.MPLS_LABEL)
                                             .getValue());
                 break;
+            case IPV6_EXTHDR:
+                builder.matchIPv6ExthdrFlags((int) match.get(MatchField.IPV6_EXTHDR)
+                                            .getValue());
+                break;
             case OCH_SIGID:
                 builder.matchLambda(match.get(MatchField.OCH_SIGID).getChannelNumber());
                 break;
@@ -539,5 +539,4 @@
         }
         return builder.build();
     }
-
 }
diff --git a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilder.java b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilder.java
index 15aa511..b21ea0b 100644
--- a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilder.java
+++ b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilder.java
@@ -67,6 +67,7 @@
 import org.projectfloodlight.openflow.types.OFPort;
 import org.projectfloodlight.openflow.types.OFVlanVidMatch;
 import org.projectfloodlight.openflow.types.TransportPort;
+import org.projectfloodlight.openflow.types.U16;
 import org.projectfloodlight.openflow.types.U32;
 import org.projectfloodlight.openflow.types.U8;
 import org.projectfloodlight.openflow.types.VlanPcp;
@@ -363,6 +364,12 @@
                 Criteria.MplsCriterion mp = (Criteria.MplsCriterion) c;
                 mBuilder.setExact(MatchField.MPLS_LABEL, U32.of(mp.label()));
                 break;
+            case IPV6_EXTHDR:
+                Criteria.IPv6ExthdrFlagsCriterion exthdrFlagsCriterion =
+                    (Criteria.IPv6ExthdrFlagsCriterion) c;
+                mBuilder.setExact(MatchField.IPV6_EXTHDR,
+                                  U16.of(exthdrFlagsCriterion.exthdrFlags()));
+                break;
             case OCH_SIGID:
                 LambdaCriterion lc = (LambdaCriterion) c;
                 mBuilder.setExact(MatchField.OCH_SIGID,
@@ -373,14 +380,13 @@
                 Criteria.OpticalSignalTypeCriterion sc =
                         (Criteria.OpticalSignalTypeCriterion) c;
                 mBuilder.setExact(MatchField.OCH_SIGTYPE,
-                                  U8.of((short) sc.signalType()));
+                                  U8.of(sc.signalType()));
                 break;
             case ARP_OP:
             case ARP_SHA:
             case ARP_SPA:
             case ARP_THA:
             case ARP_TPA:
-            case IPV6_EXTHDR:
             case MPLS_BOS:
             case MPLS_TC:
             case PBB_ISID:
diff --git a/web/api/src/main/java/org/onosproject/codec/impl/CriterionCodec.java b/web/api/src/main/java/org/onosproject/codec/impl/CriterionCodec.java
index 135fd83..d270555 100644
--- a/web/api/src/main/java/org/onosproject/codec/impl/CriterionCodec.java
+++ b/web/api/src/main/java/org/onosproject/codec/impl/CriterionCodec.java
@@ -71,6 +71,7 @@
         formatMap.put(Criterion.Type.IPV6_ND_SLL, new FormatV6NDTll());
         formatMap.put(Criterion.Type.IPV6_ND_TLL, new FormatV6NDTll());
         formatMap.put(Criterion.Type.MPLS_LABEL, new FormatMplsLabel());
+        formatMap.put(Criterion.Type.IPV6_EXTHDR, new FormatIpV6Exthdr());
         formatMap.put(Criterion.Type.OCH_SIGID, new FormatOchSigId());
         formatMap.put(Criterion.Type.OCH_SIGTYPE, new FormatOchSigType());
 
@@ -84,7 +85,6 @@
         formatMap.put(Criterion.Type.MPLS_BOS, new FormatUnknown());
         formatMap.put(Criterion.Type.PBB_ISID, new FormatUnknown());
         formatMap.put(Criterion.Type.TUNNEL_ID, new FormatUnknown());
-        formatMap.put(Criterion.Type.IPV6_EXTHDR, new FormatUnknown());
         formatMap.put(Criterion.Type.UNASSIGNED_40, new FormatUnknown());
         formatMap.put(Criterion.Type.PBB_UCA, new FormatUnknown());
         formatMap.put(Criterion.Type.TCP_FLAGS, new FormatUnknown());
@@ -289,6 +289,15 @@
         }
     }
 
+    private static class FormatIpV6Exthdr implements CriterionTypeFormatter {
+        @Override
+        public ObjectNode formatCriterion(ObjectNode root, Criterion criterion) {
+            final Criteria.IPv6ExthdrFlagsCriterion exthdrCriterion =
+                    (Criteria.IPv6ExthdrFlagsCriterion) criterion;
+            return root.put("exthdrFlags", exthdrCriterion.exthdrFlags());
+        }
+    }
+
     private static class FormatOchSigId implements CriterionTypeFormatter {
         @Override
         public ObjectNode formatCriterion(ObjectNode root, Criterion criterion) {
diff --git a/web/api/src/test/java/org/onosproject/codec/impl/CriterionCodecTest.java b/web/api/src/test/java/org/onosproject/codec/impl/CriterionCodecTest.java
index 6276f24..3efc018 100644
--- a/web/api/src/test/java/org/onosproject/codec/impl/CriterionCodecTest.java
+++ b/web/api/src/test/java/org/onosproject/codec/impl/CriterionCodecTest.java
@@ -407,6 +407,27 @@
     }
 
     /**
+     * Tests IPv6 Extension Header pseudo-field flags criterion.
+     */
+    @Test
+    public void matchIPv6ExthdrFlagsTest() {
+        int exthdrFlags =
+            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() |
+            Criterion.IPv6ExthdrFlags.UNSEQ.getValue();
+        Criterion criterion = Criteria.matchIPv6ExthdrFlags(exthdrFlags);
+        ObjectNode result = criterionCodec.encode(criterion, context);
+        assertThat(result.get("type").textValue(), is(criterion.type().toString()));
+        assertThat(result.get("exthdrFlags").asInt(), is(exthdrFlags));
+    }
+
+    /**
      * Tests lambda criterion.
      */
     @Test
@@ -422,10 +443,10 @@
      */
     @Test
     public void matchOpticalSignalTypeTest() {
-        Criterion criterion = Criteria.matchOpticalSignalType((short) 40000);
+        Criterion criterion = Criteria.matchOpticalSignalType((byte) 250);
         ObjectNode result = criterionCodec.encode(criterion, context);
         assertThat(result.get("type").textValue(), is(criterion.type().toString()));
-        assertThat(result.get("signalType").asInt(), is(40000));
+        assertThat(result.get("signalType").asInt(), is(250));
     }
 
 }
diff --git a/web/api/src/test/java/org/onosproject/codec/impl/CriterionJsonMatcher.java b/web/api/src/test/java/org/onosproject/codec/impl/CriterionJsonMatcher.java
index 9901f1a..0ffeed4 100644
--- a/web/api/src/test/java/org/onosproject/codec/impl/CriterionJsonMatcher.java
+++ b/web/api/src/test/java/org/onosproject/codec/impl/CriterionJsonMatcher.java
@@ -294,6 +294,18 @@
                 }
                 break;
 
+            case IPV6_EXTHDR:
+                final Criteria.IPv6ExthdrFlagsCriterion exthdrCriterion =
+                        (Criteria.IPv6ExthdrFlagsCriterion) criterion;
+                final int exthdrFlags = exthdrCriterion.exthdrFlags();
+                final int jsonExthdrFlags =
+                    jsonCriterion.get("exthdrFlags").intValue();
+                if (exthdrFlags != jsonExthdrFlags) {
+                    description.appendText("exthdrFlags was " + Long.toHexString(jsonExthdrFlags));
+                    return false;
+                }
+                break;
+
             case OCH_SIGID:
                 final Criteria.LambdaCriterion lambdaCriterion =
                         (Criteria.LambdaCriterion) criterion;
@@ -308,10 +320,10 @@
             case OCH_SIGTYPE:
                 final Criteria.OpticalSignalTypeCriterion opticalSignalTypeCriterion =
                         (Criteria.OpticalSignalTypeCriterion) criterion;
-                final int signalType = opticalSignalTypeCriterion.signalType();
-                final int jsonSignalType = jsonCriterion.get("signalType").intValue();
+                final short signalType = opticalSignalTypeCriterion.signalType();
+                final short jsonSignalType = jsonCriterion.get("signalType").shortValue();
                 if (signalType != jsonSignalType) {
-                    description.appendText("signal type was " + Integer.toString(signalType));
+                    description.appendText("signal type was " + Short.toString(signalType));
                     return false;
                 }
                 break;