Fix to properly encode several MASKED criterion into JSON.

Change-Id: I6a3b16c3382d60275de0fc0c61087e79038e5ebb
(cherry picked from commit e3c605e3cf137532af81f51f435cc5f2d81cedf5)
diff --git a/core/common/src/main/java/org/onosproject/codec/impl/DecodeCriterionCodecHelper.java b/core/common/src/main/java/org/onosproject/codec/impl/DecodeCriterionCodecHelper.java
index cf4cfa2..cbd1df3 100644
--- a/core/common/src/main/java/org/onosproject/codec/impl/DecodeCriterionCodecHelper.java
+++ b/core/common/src/main/java/org/onosproject/codec/impl/DecodeCriterionCodecHelper.java
@@ -82,6 +82,7 @@
         decoderMap.put(Criterion.Type.ETH_DST.name(), new EthDstDecoder());
         decoderMap.put(Criterion.Type.ETH_DST_MASKED.name(), new EthDstMaskedDecoder());
         decoderMap.put(Criterion.Type.ETH_SRC.name(), new EthSrcDecoder());
+        decoderMap.put(Criterion.Type.ETH_SRC_MASKED.name(), new EthSrcMaskedDecoder());
         decoderMap.put(Criterion.Type.ETH_TYPE.name(), new EthTypeDecoder());
         decoderMap.put(Criterion.Type.VLAN_VID.name(), new VlanVidDecoder());
         decoderMap.put(Criterion.Type.VLAN_PCP.name(), new VlanPcpDecoder());
@@ -155,9 +156,9 @@
         @Override
         public Criterion decodeCriterion(ObjectNode json) {
             MacAddress mac = MacAddress.valueOf(nullIsIllegal(json.get(CriterionCodec.MAC),
-                                                              CriterionCodec.MAC + MISSING_MEMBER_MESSAGE).asText());
+                    CriterionCodec.MAC + MISSING_MEMBER_MESSAGE).asText());
             MacAddress macMask = MacAddress.valueOf(nullIsIllegal(json.get(CriterionCodec.MAC_MASK),
-                                                              CriterionCodec.MAC + MISSING_MEMBER_MESSAGE).asText());
+                    CriterionCodec.MAC_MASK + MISSING_MEMBER_MESSAGE).asText());
             return Criteria.matchEthDstMasked(mac, macMask);
         }
     }
@@ -172,6 +173,17 @@
         }
     }
 
+    private class EthSrcMaskedDecoder implements CriterionDecoder {
+        @Override
+        public Criterion decodeCriterion(ObjectNode json) {
+            MacAddress mac = MacAddress.valueOf(nullIsIllegal(json.get(CriterionCodec.MAC),
+                    CriterionCodec.MAC + MISSING_MEMBER_MESSAGE).asText());
+            MacAddress macMask = MacAddress.valueOf(nullIsIllegal(json.get(CriterionCodec.MAC_MASK),
+                    CriterionCodec.MAC_MASK + MISSING_MEMBER_MESSAGE).asText());
+            return Criteria.matchEthSrcMasked(mac, macMask);
+        }
+    }
+
     private class InPortDecoder implements CriterionDecoder {
         @Override
         public Criterion decodeCriterion(ObjectNode json) {
diff --git a/core/common/src/main/java/org/onosproject/codec/impl/EncodeCriterionCodecHelper.java b/core/common/src/main/java/org/onosproject/codec/impl/EncodeCriterionCodecHelper.java
index 03cab28..8a3feaa 100644
--- a/core/common/src/main/java/org/onosproject/codec/impl/EncodeCriterionCodecHelper.java
+++ b/core/common/src/main/java/org/onosproject/codec/impl/EncodeCriterionCodecHelper.java
@@ -95,6 +95,7 @@
         formatMap.put(Criterion.Type.ETH_DST, new FormatEth());
         formatMap.put(Criterion.Type.ETH_DST_MASKED, new FormatEthMasked());
         formatMap.put(Criterion.Type.ETH_SRC, new FormatEth());
+        formatMap.put(Criterion.Type.ETH_SRC_MASKED, new FormatEthMasked());
         formatMap.put(Criterion.Type.ETH_TYPE, new FormatEthType());
         formatMap.put(Criterion.Type.VLAN_VID, new FormatVlanVid());
         formatMap.put(Criterion.Type.VLAN_PCP, new FormatVlanPcp());
@@ -151,14 +152,6 @@
         formatMap.put(Criterion.Type.TCP_FLAGS, new FormatUnknown());
         formatMap.put(Criterion.Type.ACTSET_OUTPUT, new FormatUnknown());
         formatMap.put(Criterion.Type.PACKET_TYPE, new FormatUnknown());
-        formatMap.put(Criterion.Type.ETH_SRC_MASKED, new FormatUnknown());
-        formatMap.put(Criterion.Type.TCP_SRC_MASKED, new FormatUnknown());
-        formatMap.put(Criterion.Type.TCP_DST_MASKED, new FormatUnknown());
-        formatMap.put(Criterion.Type.UDP_SRC_MASKED, new FormatUnknown());
-        formatMap.put(Criterion.Type.UDP_DST_MASKED, new FormatUnknown());
-        formatMap.put(Criterion.Type.SCTP_SRC_MASKED, new FormatUnknown());
-        formatMap.put(Criterion.Type.SCTP_DST_MASKED, new FormatUnknown());
-
     }
 
     private interface CriterionTypeFormatter {
diff --git a/core/common/src/test/java/org/onosproject/codec/impl/CriterionCodecTest.java b/core/common/src/test/java/org/onosproject/codec/impl/CriterionCodecTest.java
index f2fd5e5..1542f0d 100644
--- a/core/common/src/test/java/org/onosproject/codec/impl/CriterionCodecTest.java
+++ b/core/common/src/test/java/org/onosproject/codec/impl/CriterionCodecTest.java
@@ -74,6 +74,7 @@
     final MacAddress mcastMac = MacAddress.valueOf("01:00:5E:00:00:01");
     final MacAddress mcastMacMask = MacAddress.valueOf("FF:FF:FF:80:00:00");
     final TpPort tpPort = TpPort.tpPort(40000);
+    final TpPort tpPortMask = TpPort.tpPort(65472);
     final int tributaryPortNumber = 11;
     final int tributarySlotLen = 80;
     final byte[] tributarySlotBitmap = new byte[] {1, 2, 3, 4, 2, 3, 4, 2, 3, 4};
@@ -169,6 +170,16 @@
     }
 
     /**
+     * Tests masked ethernet source criterion (Criterion.Type.ETH_SRC_MASKED).
+     */
+    @Test
+    public void matchEthSrcMaskTest() {
+        Criterion criterion = Criteria.matchEthSrcMasked(mcastMac, mcastMacMask);
+        ObjectNode result = criterionCodec.encode(criterion, context);
+        assertThat(result, matchesCriterion(criterion));
+    }
+
+    /**
      * Tests ethernet type criterion.
      */
     @Test
@@ -259,6 +270,16 @@
     }
 
     /**
+     * Tests source TCP port masked criterion.
+     */
+    @Test
+    public void matchTcpSrcMaskedTest() {
+        Criterion criterion = Criteria.matchTcpSrcMasked(tpPort, tpPortMask);
+        ObjectNode result = criterionCodec.encode(criterion, context);
+        assertThat(result, matchesCriterion(criterion));
+    }
+
+    /**
      * Tests destination TCP port criterion.
      */
     @Test
@@ -269,6 +290,16 @@
     }
 
     /**
+     * Tests destination TCP port masked criterion.
+     */
+    @Test
+    public void matchTcpDstMaskedTest() {
+        Criterion criterion = Criteria.matchTcpDstMasked(tpPort, tpPortMask);
+        ObjectNode result = criterionCodec.encode(criterion, context);
+        assertThat(result, matchesCriterion(criterion));
+    }
+
+    /**
      * Tests source UDP port criterion.
      */
     @Test
@@ -279,6 +310,16 @@
     }
 
     /**
+     * Tests source UDP port masked criterion.
+     */
+    @Test
+    public void matchUdpSrcMaskedTest() {
+        Criterion criterion = Criteria.matchUdpSrcMasked(tpPort, tpPortMask);
+        ObjectNode result = criterionCodec.encode(criterion, context);
+        assertThat(result, matchesCriterion(criterion));
+    }
+
+    /**
      * Tests destination UDP criterion.
      */
     @Test
@@ -289,6 +330,16 @@
     }
 
     /**
+     * Tests destination UDP port masked criterion.
+     */
+    @Test
+    public void matchUdpDstMaskedTest() {
+        Criterion criterion = Criteria.matchUdpDstMasked(tpPort, tpPortMask);
+        ObjectNode result = criterionCodec.encode(criterion, context);
+        assertThat(result, matchesCriterion(criterion));
+    }
+
+    /**
      * Tests source SCTP criterion.
      */
     @Test
@@ -299,6 +350,16 @@
     }
 
     /**
+     * Tests source SCTP port masked criterion.
+     */
+    @Test
+    public void matchSctpSrcMaskedTest() {
+        Criterion criterion = Criteria.matchSctpSrcMasked(tpPort, tpPortMask);
+        ObjectNode result = criterionCodec.encode(criterion, context);
+        assertThat(result, matchesCriterion(criterion));
+    }
+
+    /**
      * Tests destination SCTP criterion.
      */
     @Test
@@ -309,6 +370,16 @@
     }
 
     /**
+     * Tests destination SCTP port masked criterion.
+     */
+    @Test
+    public void matchSctpDstMaskedTest() {
+        Criterion criterion = Criteria.matchSctpDstMasked(tpPort, tpPortMask);
+        ObjectNode result = criterionCodec.encode(criterion, context);
+        assertThat(result, matchesCriterion(criterion));
+    }
+
+    /**
      * Tests ICMP type criterion.
      */
     @Test
diff --git a/core/common/src/test/java/org/onosproject/codec/impl/CriterionJsonMatcher.java b/core/common/src/test/java/org/onosproject/codec/impl/CriterionJsonMatcher.java
index d1e1f19..9113124 100644
--- a/core/common/src/test/java/org/onosproject/codec/impl/CriterionJsonMatcher.java
+++ b/core/common/src/test/java/org/onosproject/codec/impl/CriterionJsonMatcher.java
@@ -138,7 +138,7 @@
             description.appendText("mac was " + jsonMac);
             return false;
         }
-        if (criterion.type() == Criterion.Type.ETH_DST_MASKED) {
+        if (criterion.type() == Criterion.Type.ETH_SRC_MASKED || criterion.type() == Criterion.Type.ETH_DST_MASKED) {
             final String macMask = criterion.mask().toString();
             final String jsonMacMask = jsonCriterion.get("macMask").textValue();
             if (!macMask.equals(jsonMacMask)) {
@@ -278,6 +278,15 @@
                     + Integer.toString(jsonTcpPort));
             return false;
         }
+        if (criterion.type() == Criterion.Type.TCP_SRC_MASKED || criterion.type() == Criterion.Type.TCP_DST_MASKED) {
+            final int tcpMask = criterion.mask().toInt();
+            final int jsonTcpMask = jsonCriterion.get("tcpMask").intValue();
+            if (tcpMask != jsonTcpMask) {
+                description.appendText("tcp mask was "
+                        + Integer.toString(jsonTcpMask));
+                return false;
+            }
+        }
         return true;
     }
 
@@ -295,6 +304,16 @@
                     + Integer.toString(jsonUdpPort));
             return false;
         }
+
+        if (criterion.type() == Criterion.Type.UDP_SRC_MASKED || criterion.type() == Criterion.Type.UDP_DST_MASKED) {
+            final int udpMask = criterion.mask().toInt();
+            final int jsonUdpMask = jsonCriterion.get("udpMask").intValue();
+            if (udpMask != jsonUdpMask) {
+                description.appendText("udp mask was "
+                        + Integer.toString(jsonUdpMask));
+                return false;
+            }
+        }
         return true;
     }
 
@@ -312,6 +331,15 @@
                     + Integer.toString(jsonSctpPort));
             return false;
         }
+        if (criterion.type() == Criterion.Type.SCTP_SRC_MASKED || criterion.type() == Criterion.Type.SCTP_DST_MASKED) {
+            final int sctpMask = criterion.mask().toInt();
+            final int jsonSctpMask = jsonCriterion.get("sctpMask").intValue();
+            if (sctpMask != jsonSctpMask) {
+                description.appendText("sctp mask was "
+                        + Integer.toString(jsonSctpMask));
+                return false;
+            }
+        }
         return true;
     }
 
@@ -676,6 +704,7 @@
             case ETH_DST:
             case ETH_DST_MASKED:
             case ETH_SRC:
+            case ETH_SRC_MASKED:
                 return matchCriterion((EthCriterion) criterion);
 
             case ETH_TYPE:
@@ -703,15 +732,21 @@
                 return matchCriterion((IPCriterion) criterion);
 
             case TCP_SRC:
+            case TCP_SRC_MASKED:
             case TCP_DST:
+            case TCP_DST_MASKED:
                 return matchCriterion((TcpPortCriterion) criterion);
 
             case UDP_SRC:
+            case UDP_SRC_MASKED:
             case UDP_DST:
+            case UDP_DST_MASKED:
                 return matchCriterion((UdpPortCriterion) criterion);
 
             case SCTP_SRC:
+            case SCTP_SRC_MASKED:
             case SCTP_DST:
+            case SCTP_DST_MASKED:
                 return matchCriterion((SctpPortCriterion) criterion);
 
             case ICMPV4_TYPE: