OSDN Git Service

etherdev: Process is_multicast_ether_addr at same size as other operations
authorAlexander Duyck <alexander.h.duyck@redhat.com>
Thu, 30 Apr 2015 21:53:54 +0000 (14:53 -0700)
committerDavid S. Miller <davem@davemloft.net>
Mon, 4 May 2015 02:30:36 +0000 (22:30 -0400)
This change makes it so that we process the address in
is_multicast_ether_addr at the same size as the other calls.  This allows
us to avoid duplicate reads when used with other calls such as
is_zero_ether_addr or eth_addr_copy.  In addition I have added a 64 bit
version of the function so in eth_type_trans we can process the destination
address as a 64 bit value throughout.

Signed-off-by: Alexander Duyck <alexander.h.duyck@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/linux/etherdevice.h
net/ethernet/eth.c

index 606563e..c4a10f9 100644 (file)
@@ -110,7 +110,29 @@ static inline bool is_zero_ether_addr(const u8 *addr)
  */
 static inline bool is_multicast_ether_addr(const u8 *addr)
 {
-       return 0x01 & addr[0];
+#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
+       u32 a = *(const u32 *)addr;
+#else
+       u16 a = *(const u16 *)addr;
+#endif
+#ifdef __BIG_ENDIAN
+       return 0x01 & (a >> ((sizeof(a) * 8) - 8));
+#else
+       return 0x01 & a;
+#endif
+}
+
+static inline bool is_multicast_ether_addr_64bits(const u8 addr[6+2])
+{
+#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64
+#ifdef __BIG_ENDIAN
+       return 0x01 & ((*(const u64 *)addr) >> 56);
+#else
+       return 0x01 & (*(const u64 *)addr);
+#endif
+#else
+       return is_multicast_ether_addr(addr);
+#endif
 }
 
 /**
index 6006931..21c211e 100644 (file)
@@ -159,7 +159,7 @@ __be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev)
        skb_pull_inline(skb, ETH_HLEN);
        eth = eth_hdr(skb);
 
-       if (unlikely(is_multicast_ether_addr(eth->h_dest))) {
+       if (unlikely(is_multicast_ether_addr_64bits(eth->h_dest))) {
                if (ether_addr_equal_64bits(eth->h_dest, dev->broadcast))
                        skb->pkt_type = PACKET_BROADCAST;
                else