Add JSON codec for ETH_DST_MASKED Criterion

- Enabling for a mcast flow rule to fetch its mask value from JSON dump

Change-Id: I8a69b0244dc332605d14e40998c329802a921286
(cherry picked from commit b62492324b4f913349ff7ed3e0ed3014b3f8f660)
diff --git a/core/common/src/main/java/org/onosproject/codec/impl/CriterionCodec.java b/core/common/src/main/java/org/onosproject/codec/impl/CriterionCodec.java
index 4be8008..24b749c 100644
--- a/core/common/src/main/java/org/onosproject/codec/impl/CriterionCodec.java
+++ b/core/common/src/main/java/org/onosproject/codec/impl/CriterionCodec.java
@@ -34,6 +34,7 @@
     static final String TYPE = "type";
     static final String ETH_TYPE = "ethType";
     static final String MAC = "mac";
+    static final String MAC_MASK = "macMask";
     static final String PORT = "port";
     static final String METADATA = "metadata";
 
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 ac88527..f690d5d 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
@@ -71,6 +71,7 @@
         decoderMap.put(Criterion.Type.IN_PHY_PORT.name(), new InPhyPortDecoder());
         decoderMap.put(Criterion.Type.METADATA.name(), new MetadataDecoder());
         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_TYPE.name(), new EthTypeDecoder());
         decoderMap.put(Criterion.Type.VLAN_VID.name(), new VlanVidDecoder());
@@ -138,7 +139,16 @@
             return Criteria.matchEthDst(mac);
         }
     }
-
+    private class EthDstMaskedDecoder 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 + MISSING_MEMBER_MESSAGE).asText());
+            return Criteria.matchEthDstMasked(mac, macMask);
+        }
+    }
     private class EthSrcDecoder 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 83b25a7..067a99a 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
@@ -89,6 +89,7 @@
         formatMap.put(Criterion.Type.IN_PHY_PORT, new FormatInPort());
         formatMap.put(Criterion.Type.METADATA, new FormatMetadata());
         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_TYPE, new FormatEthType());
         formatMap.put(Criterion.Type.VLAN_VID, new FormatVlanVid());
@@ -146,7 +147,6 @@
         formatMap.put(Criterion.Type.ACTSET_OUTPUT, new FormatUnknown());
         formatMap.put(Criterion.Type.PACKET_TYPE, new FormatUnknown());
         formatMap.put(Criterion.Type.EXTENSION, new FormatUnknown());
-        formatMap.put(Criterion.Type.ETH_DST_MASKED, 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());
@@ -193,6 +193,17 @@
         }
     }
 
+    private static class FormatEthMasked implements CriterionTypeFormatter {
+        @Override
+        public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
+            final EthCriterion ethCriterion = (EthCriterion) criterion;
+            root.put(CriterionCodec.MAC, ethCriterion.mac().toString());
+            root.put(CriterionCodec.MAC_MASK, ethCriterion.mask().toString());
+
+            return root;
+        }
+    }
+
     private static class FormatEthType implements CriterionTypeFormatter {
         @Override
         public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {