diff options
author | David S. Miller <davem@davemloft.net> | 2005-09-27 19:03:05 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2005-09-27 19:03:05 -0400 |
commit | ba645c16026ed733a51f904df34756f61bc155fc (patch) | |
tree | 504d51adf47bb9fa3cd548e5594f15a60faeba6c /net/ethernet/eth.c | |
parent | 2fab35d78f32fc107e1af4b1ec23f557fa20d911 (diff) |
[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.c | 31 |
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) | |||
146 | return 0; | 146 | return 0; |
147 | } | 147 | } |
148 | 148 | ||
149 | static inline unsigned int compare_eth_addr(const unsigned char *__a, const unsigned char *__b) | ||
150 | { | ||
151 | const unsigned short *dest = (unsigned short *) __a; | ||
152 | const unsigned short *devaddr = (unsigned short *) __b; | ||
153 | unsigned int res; | ||
154 | |||
155 | BUILD_BUG_ON(ETH_ALEN != 6); | ||
156 | res = ((dest[0] ^ devaddr[0]) | | ||
157 | (dest[1] ^ devaddr[1]) | | ||
158 | (dest[2] ^ devaddr[2])) != 0; | ||
159 | |||
160 | return res; | ||
161 | } | ||
149 | 162 | ||
150 | /* | 163 | /* |
151 | * Determine the packet's protocol ID. The rule here is that we | 164 | * 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) | |||
158 | struct ethhdr *eth; | 171 | struct ethhdr *eth; |
159 | unsigned char *rawp; | 172 | unsigned char *rawp; |
160 | 173 | ||
161 | skb->mac.raw=skb->data; | 174 | skb->mac.raw = skb->data; |
162 | skb_pull(skb,ETH_HLEN); | 175 | skb_pull(skb,ETH_HLEN); |
163 | eth = eth_hdr(skb); | 176 | eth = eth_hdr(skb); |
164 | 177 | ||
165 | if(*eth->h_dest&1) | 178 | if (*eth->h_dest&1) { |
166 | { | 179 | if (!compare_eth_addr(eth->h_dest, dev->broadcast)) |
167 | if(memcmp(eth->h_dest,dev->broadcast, ETH_ALEN)==0) | 180 | skb->pkt_type = PACKET_BROADCAST; |
168 | skb->pkt_type=PACKET_BROADCAST; | ||
169 | else | 181 | else |
170 | skb->pkt_type=PACKET_MULTICAST; | 182 | skb->pkt_type = PACKET_MULTICAST; |
171 | } | 183 | } |
172 | 184 | ||
173 | /* | 185 | /* |
@@ -178,10 +190,9 @@ __be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev) | |||
178 | * seems to set IFF_PROMISC. | 190 | * seems to set IFF_PROMISC. |
179 | */ | 191 | */ |
180 | 192 | ||
181 | else if(1 /*dev->flags&IFF_PROMISC*/) | 193 | else if(1 /*dev->flags&IFF_PROMISC*/) { |
182 | { | 194 | if (unlikely(!compare_eth_addr(eth->h_dest, dev->dev_addr))) |
183 | if(memcmp(eth->h_dest,dev->dev_addr, ETH_ALEN)) | 195 | skb->pkt_type = PACKET_OTHERHOST; |
184 | skb->pkt_type=PACKET_OTHERHOST; | ||
185 | } | 196 | } |
186 | 197 | ||
187 | if (ntohs(eth->h_proto) >= 1536) | 198 | if (ntohs(eth->h_proto) >= 1536) |