summaryrefslogtreecommitdiffstats
path: root/net/ethernet/eth.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2005-09-28 01:03:05 +0200
committerDavid S. Miller <davem@davemloft.net>2005-09-28 01:03:05 +0200
commitba645c16026ed733a51f904df34756f61bc155fc (patch)
tree504d51adf47bb9fa3cd548e5594f15a60faeba6c /net/ethernet/eth.c
parent[NET]: Fix GCC4 compile error: sysctl in linux/if_ether.h (diff)
downloadlinux-ba645c16026ed733a51f904df34756f61bc155fc.tar.xz
linux-ba645c16026ed733a51f904df34756f61bc155fc.zip
[NET]: Slightly optimize ethernet address comparison.
We know the thing is at least 2-byte aligned, so take advantage of that instead of invoking memcmp() which results in truly horrifically inefficient code because it can't assume anything about alignment. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ethernet/eth.c')
-rw-r--r--net/ethernet/eth.c31
1 files changed, 21 insertions, 10 deletions
diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c
index 87a052a9a84f..8b299cc82060 100644
--- a/net/ethernet/eth.c
+++ b/net/ethernet/eth.c
@@ -146,6 +146,19 @@ int eth_rebuild_header(struct sk_buff *skb)
return 0;
}
+static inline unsigned int compare_eth_addr(const unsigned char *__a, const unsigned char *__b)
+{
+ const unsigned short *dest = (unsigned short *) __a;
+ const unsigned short *devaddr = (unsigned short *) __b;
+ unsigned int res;
+
+ BUILD_BUG_ON(ETH_ALEN != 6);
+ res = ((dest[0] ^ devaddr[0]) |
+ (dest[1] ^ devaddr[1]) |
+ (dest[2] ^ devaddr[2])) != 0;
+
+ return res;
+}
/*
* Determine the packet's protocol ID. The rule here is that we
@@ -158,16 +171,15 @@ __be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev)
struct ethhdr *eth;
unsigned char *rawp;
- skb->mac.raw=skb->data;
+ skb->mac.raw = skb->data;
skb_pull(skb,ETH_HLEN);
eth = eth_hdr(skb);
- if(*eth->h_dest&1)
- {
- if(memcmp(eth->h_dest,dev->broadcast, ETH_ALEN)==0)
- skb->pkt_type=PACKET_BROADCAST;
+ if (*eth->h_dest&1) {
+ if (!compare_eth_addr(eth->h_dest, dev->broadcast))
+ skb->pkt_type = PACKET_BROADCAST;
else
- skb->pkt_type=PACKET_MULTICAST;
+ skb->pkt_type = PACKET_MULTICAST;
}
/*
@@ -178,10 +190,9 @@ __be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev)
* seems to set IFF_PROMISC.
*/
- else if(1 /*dev->flags&IFF_PROMISC*/)
- {
- if(memcmp(eth->h_dest,dev->dev_addr, ETH_ALEN))
- skb->pkt_type=PACKET_OTHERHOST;
+ else if(1 /*dev->flags&IFF_PROMISC*/) {
+ if (unlikely(!compare_eth_addr(eth->h_dest, dev->dev_addr)))
+ skb->pkt_type = PACKET_OTHERHOST;
}
if (ntohs(eth->h_proto) >= 1536)