[ovs-dev] [PATCHv2 1/2] packets: Adds ethernet-matching helper functions

Joe Stringer joe at wand.net.nz
Mon May 28 12:38:11 UTC 2012


With OpenFlow 1.1 requiring arbitrary ethernet match support, it simplifies
other code if we have some extra helper functions. This patch adds
eth_mask_is_exact(mask), eth_addr_bitand(src, mask, dst),
eth_addr_equal_except(a, b, mask) and eth_format_masked(eth, mask, output).

Signed-off-by: Joe Stringer <joe at wand.net.nz>
---
 lib/meta-flow.c |    5 +----
 lib/packets.c   |   20 ++++++++++++++++++++
 lib/packets.h   |   22 ++++++++++++++++++++++
 3 files changed, 43 insertions(+), 4 deletions(-)

diff --git a/lib/meta-flow.c b/lib/meta-flow.c
index 8b60b35..9387d3a 100644
--- a/lib/meta-flow.c
+++ b/lib/meta-flow.c
@@ -2273,10 +2273,7 @@ mf_format(const struct mf_field *mf,
         break;
 
     case MFS_ETHERNET:
-        ds_put_format(s, ETH_ADDR_FMT, ETH_ADDR_ARGS(value->mac));
-        if (mask) {
-            ds_put_format(s, "/"ETH_ADDR_FMT, ETH_ADDR_ARGS(mask->mac));
-        }
+        eth_format_masked(value->mac, mask->mac, s);
         break;
 
     case MFS_IPV4:
diff --git a/lib/packets.c b/lib/packets.c
index 84ca590..be36f29 100644
--- a/lib/packets.c
+++ b/lib/packets.c
@@ -148,6 +148,26 @@ eth_from_hex(const char *hex, struct ofpbuf **packetp)
     return NULL;
 }
 
+void
+eth_format_masked(const uint8_t eth[ETH_ADDR_LEN],
+                  const uint8_t mask[ETH_ADDR_LEN], struct ds *s)
+{
+    ds_put_format(s, ETH_ADDR_FMT, ETH_ADDR_ARGS(eth));
+    if (mask) {
+        ds_put_format(s, "/"ETH_ADDR_FMT, ETH_ADDR_ARGS(mask));
+    }
+}
+
+void eth_addr_bitand(const uint8_t src[ETH_ADDR_LEN],
+                     const uint8_t mask[ETH_ADDR_LEN],
+                     uint8_t dst[ETH_ADDR_LEN])
+{
+    int i = 0;
+    for (; i < ETH_ADDR_LEN; ++i) {
+        dst[i] = src[i] & mask[i];
+    }
+}
+
 /* Given the IP netmask 'netmask', returns the number of bits of the IP address
  * that it specifies, that is, the number of 1-bits in 'netmask'.  'netmask'
  * must be a CIDR netmask (see ip_is_cidr()). */
diff --git a/lib/packets.h b/lib/packets.h
index f9e5bb6..00c2b75 100644
--- a/lib/packets.h
+++ b/lib/packets.h
@@ -64,6 +64,12 @@ static inline bool eth_addr_is_zero(const uint8_t ea[6])
 {
     return !(ea[0] | ea[1] | ea[2] | ea[3] | ea[4] | ea[5]);
 }
+
+static inline int eth_mask_is_exact(const uint8_t ea[ETH_ADDR_LEN])
+{
+    return (ea[0] & ea[1] & ea[2] & ea[3] & ea[4] & ea[5]) == 0xff;
+}
+
 static inline int eth_addr_compare_3way(const uint8_t a[ETH_ADDR_LEN],
                                         const uint8_t b[ETH_ADDR_LEN])
 {
@@ -74,6 +80,17 @@ static inline bool eth_addr_equals(const uint8_t a[ETH_ADDR_LEN],
 {
     return !eth_addr_compare_3way(a, b);
 }
+static inline bool eth_addr_equal_except(const uint8_t a[ETH_ADDR_LEN],
+                                    const uint8_t b[ETH_ADDR_LEN],
+                                    const uint8_t mask[ETH_ADDR_LEN])
+{
+    return (((a[0] ^ b[0]) & mask[0])
+            || ((a[1] ^ b[1]) & mask[1])
+            || ((a[2] ^ b[2]) & mask[2])
+            || ((a[3] ^ b[3]) & mask[3])
+            || ((a[4] ^ b[4]) & mask[4])
+            || ((a[5] ^ b[5]) & mask[5]));
+}
 static inline uint64_t eth_addr_to_uint64(const uint8_t ea[ETH_ADDR_LEN])
 {
     return (((uint64_t) ea[0] << 40)
@@ -136,6 +153,11 @@ void eth_push_vlan(struct ofpbuf *, ovs_be16 tci);
 void eth_pop_vlan(struct ofpbuf *);
 
 const char *eth_from_hex(const char *hex, struct ofpbuf **packetp);
+void eth_format_masked(const uint8_t eth[ETH_ADDR_LEN],
+                       const uint8_t mask[ETH_ADDR_LEN], struct ds *s);
+void eth_addr_bitand(const uint8_t src[ETH_ADDR_LEN],
+                     const uint8_t mask[ETH_ADDR_LEN],
+                     uint8_t dst[ETH_ADDR_LEN]);
 
 /* Example:
  *
-- 
1.7.2.5




More information about the dev mailing list