Adding eth masking in match

Change-Id: I95e0ee66b1c6c139de7672f9bc04871fd0ead6d7
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 6e5f466..a0a171ad 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
@@ -174,11 +174,21 @@
         }
 
         @Override
+        public Builder matchEthDstMasked(MacAddress addr, MacAddress mask) {
+            return add(Criteria.matchEthDstMasked(addr, mask));
+        }
+
+        @Override
         public Builder matchEthSrc(MacAddress addr) {
             return add(Criteria.matchEthSrc(addr));
         }
 
         @Override
+        public Builder matchEthSrcMasked(MacAddress addr, MacAddress mask) {
+            return add(Criteria.matchEthSrcMasked(addr, mask));
+        }
+
+        @Override
         public Builder matchEthType(short ethType) {
             return add(Criteria.matchEthType(ethType));
         }
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 b45dc45..dddacea 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
@@ -97,6 +97,15 @@
         Builder matchEthDst(MacAddress addr);
 
         /**
+         * Matches a l2 dst address with mask.
+         *
+         * @param addr a l2 address
+         * @param mask a mask for an l2 address
+         * @return a selection builder
+         */
+        Builder matchEthDstMasked(MacAddress addr, MacAddress mask);
+
+        /**
          * Matches a l2 src address.
          *
          * @param addr a l2 address
@@ -105,6 +114,15 @@
         Builder matchEthSrc(MacAddress addr);
 
         /**
+         * Matches a l2 src address with mask.
+         *
+         * @param addr a l2 address
+         * @param mask a mask for an l2 address
+         * @return a selection builder
+         */
+        Builder matchEthSrcMasked(MacAddress addr, MacAddress mask);
+
+        /**
          * Matches the ethernet type.
          *
          * @param ethType an ethernet type
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 4259f5d..e306871 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
@@ -86,6 +86,17 @@
     }
 
     /**
+     * Creates a masked match on ETH_DST field using the specified value and mask.
+     *
+     * @param mac MAC address value
+     * @param mask MAC address masking
+     * @return match criterion
+     */
+    public static Criterion matchEthDstMasked(MacAddress mac, MacAddress mask) {
+        return new EthCriterion(mac, mask, Type.ETH_DST_MASKED);
+    }
+
+    /**
      * Creates a match on ETH_SRC field using the specified value. This value
      * may be a wildcard mask.
      *
@@ -97,6 +108,17 @@
     }
 
     /**
+     * Creates a masked match on ETH_SRC field using the specified value and mask.
+     *
+     * @param mac MAC address value
+     * @param mask MAC address masking
+     * @return match criterion
+     */
+    public static Criterion matchEthSrcMasked(MacAddress mac, MacAddress mask) {
+        return new EthCriterion(mac, mask, Type.ETH_SRC_MASKED);
+    }
+
+    /**
      * Creates a match on ETH_TYPE field using the specified value.
      *
      * @param ethType eth type value (16 bits unsigned integer)
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 5b2cfcc..c58bd6c 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
@@ -40,9 +40,15 @@
         /** Ethernet destination address. */
         ETH_DST,
 
+        /** Ethernet destination address with masking. */
+        ETH_DST_MASKED,
+
         /** Ethernet source address. */
         ETH_SRC,
 
+        /** Ethernet source address with masking. */
+        ETH_SRC_MASKED,
+
         /** Ethernet frame type. */
         ETH_TYPE,
 
diff --git a/core/api/src/main/java/org/onosproject/net/flow/criteria/EthCriterion.java b/core/api/src/main/java/org/onosproject/net/flow/criteria/EthCriterion.java
index f4664c9..f7c6f48 100644
--- a/core/api/src/main/java/org/onosproject/net/flow/criteria/EthCriterion.java
+++ b/core/api/src/main/java/org/onosproject/net/flow/criteria/EthCriterion.java
@@ -24,18 +24,32 @@
  */
 public final class EthCriterion implements Criterion {
     private final MacAddress mac;
+    private final MacAddress mask;
     private final Type type;
 
     /**
      * Constructor.
      *
      * @param mac the source or destination MAC address to match
+     * @param mask the mask for the address
+     * @param type the match type. Should be either Type.ETH_DST_MASKED or
+     *             Type.ETH_SRC_MASKED
+     */
+    EthCriterion(MacAddress mac, MacAddress mask, Type type) {
+        this.mac = mac;
+        this.mask = mask;
+        this.type = type;
+    }
+
+    /**
+     * Constructor.
+     *
+     * @param mac the source or destination MAC address to match
      * @param type the match type. Should be either Type.ETH_DST or
-     * Type.ETH_SRC
+     *             Type.ETH_SRC
      */
     EthCriterion(MacAddress mac, Type type) {
-        this.mac = mac;
-        this.type = type;
+        this(mac, null, type);
     }
 
     @Override
@@ -52,14 +66,23 @@
         return this.mac;
     }
 
+    /**
+     * Gets the mask for the MAC address to match.
+     *
+     * @return the MAC address to match
+     */
+    public MacAddress mask() {
+        return this.mask;
+    }
+
     @Override
     public String toString() {
-        return type().toString() + SEPARATOR + mac;
+        return type().toString() + SEPARATOR + mac + "/" + mask;
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(type.ordinal(), mac);
+        return Objects.hash(type.ordinal(), mac, mask);
     }
 
     @Override
@@ -70,6 +93,7 @@
         if (obj instanceof EthCriterion) {
             EthCriterion that = (EthCriterion) obj;
             return Objects.equals(mac, that.mac) &&
+                    Objects.equals(mask, that.mask) &&
                     Objects.equals(type, that.type);
         }
         return false;
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 2130293..bc7388a 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
@@ -130,6 +130,9 @@
         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());
+
     }
 
     private interface CriterionTypeFormatter {
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 1fa4717..8ead323 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
@@ -615,12 +615,26 @@
                 builder.matchMetadata(metadata);
                 break;
             case ETH_DST:
-                mac = MacAddress.valueOf(match.get(MatchField.ETH_DST).getLong());
-                builder.matchEthDst(mac);
+                if (match.isPartiallyMasked(MatchField.ETH_DST)) {
+                    Masked<org.projectfloodlight.openflow.types.MacAddress> maskedMac =
+                            match.getMasked(MatchField.ETH_DST);
+                    builder.matchEthDstMasked(MacAddress.valueOf(maskedMac.getValue().getLong()),
+                                              MacAddress.valueOf(maskedMac.getMask().getLong()));
+                } else {
+                    mac = MacAddress.valueOf(match.get(MatchField.ETH_DST).getLong());
+                    builder.matchEthDst(mac);
+                }
                 break;
             case ETH_SRC:
-                mac = MacAddress.valueOf(match.get(MatchField.ETH_SRC).getLong());
-                builder.matchEthSrc(mac);
+                if (match.isPartiallyMasked(MatchField.ETH_SRC)) {
+                    Masked<org.projectfloodlight.openflow.types.MacAddress> maskedMac =
+                            match.getMasked(MatchField.ETH_SRC);
+                    builder.matchEthSrcMasked(MacAddress.valueOf(maskedMac.getValue().getLong()),
+                                              MacAddress.valueOf(maskedMac.getMask().getLong()));
+                } else {
+                    mac = MacAddress.valueOf(match.get(MatchField.ETH_SRC).getLong());
+                    builder.matchEthSrc(mac);
+                }
                 break;
             case ETH_TYPE:
                 int ethType = match.get(MatchField.ETH_TYPE).getValue();
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 792e369..4cdbb83 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
@@ -219,11 +219,23 @@
                 mBuilder.setExact(MatchField.ETH_DST,
                                   MacAddress.of(ethCriterion.mac().toLong()));
                 break;
+            case ETH_DST_MASKED:
+                ethCriterion = (EthCriterion) c;
+                mBuilder.setMasked(MatchField.ETH_DST,
+                                   MacAddress.of(ethCriterion.mac().toLong()),
+                                   MacAddress.of(ethCriterion.mask().toLong()));
+                break;
             case ETH_SRC:
                 ethCriterion = (EthCriterion) c;
                 mBuilder.setExact(MatchField.ETH_SRC,
                                   MacAddress.of(ethCriterion.mac().toLong()));
                 break;
+            case ETH_SRC_MASKED:
+                ethCriterion = (EthCriterion) c;
+                mBuilder.setMasked(MatchField.ETH_SRC,
+                                   MacAddress.of(ethCriterion.mac().toLong()),
+                                   MacAddress.of(ethCriterion.mask().toLong()));
+                break;
             case ETH_TYPE:
                 EthTypeCriterion ethType = (EthTypeCriterion) c;
                 mBuilder.setExact(MatchField.ETH_TYPE, EthType.of(ethType.ethType().toShort()));