aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/etherdevice.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/linux/etherdevice.h')
-rw-r--r--include/linux/etherdevice.h118
1 files changed, 82 insertions, 36 deletions
diff --git a/include/linux/etherdevice.h b/include/linux/etherdevice.h
index fc4a9aa7dd82..9c5529dc6d07 100644
--- a/include/linux/etherdevice.h
+++ b/include/linux/etherdevice.h
@@ -26,6 +26,7 @@
26#include <linux/netdevice.h> 26#include <linux/netdevice.h>
27#include <linux/random.h> 27#include <linux/random.h>
28#include <asm/unaligned.h> 28#include <asm/unaligned.h>
29#include <asm/bitsperlong.h>
29 30
30#ifdef __KERNEL__ 31#ifdef __KERNEL__
31__be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev); 32__be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev);
@@ -60,6 +61,8 @@ static const u8 eth_reserved_addr_base[ETH_ALEN] __aligned(2) =
60 * 61 *
61 * Return true if address is link local reserved addr (01:80:c2:00:00:0X) per 62 * Return true if address is link local reserved addr (01:80:c2:00:00:0X) per
62 * IEEE 802.1Q 8.6.3 Frame filtering. 63 * IEEE 802.1Q 8.6.3 Frame filtering.
64 *
65 * Please note: addr must be aligned to u16.
63 */ 66 */
64static inline bool is_link_local_ether_addr(const u8 *addr) 67static inline bool is_link_local_ether_addr(const u8 *addr)
65{ 68{
@@ -67,7 +70,12 @@ static inline bool is_link_local_ether_addr(const u8 *addr)
67 static const __be16 *b = (const __be16 *)eth_reserved_addr_base; 70 static const __be16 *b = (const __be16 *)eth_reserved_addr_base;
68 static const __be16 m = cpu_to_be16(0xfff0); 71 static const __be16 m = cpu_to_be16(0xfff0);
69 72
73#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
74 return (((*(const u32 *)addr) ^ (*(const u32 *)b)) |
75 ((a[2] ^ b[2]) & m)) == 0;
76#else
70 return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | ((a[2] ^ b[2]) & m)) == 0; 77 return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | ((a[2] ^ b[2]) & m)) == 0;
78#endif
71} 79}
72 80
73/** 81/**
@@ -75,10 +83,18 @@ static inline bool is_link_local_ether_addr(const u8 *addr)
75 * @addr: Pointer to a six-byte array containing the Ethernet address 83 * @addr: Pointer to a six-byte array containing the Ethernet address
76 * 84 *
77 * Return true if the address is all zeroes. 85 * Return true if the address is all zeroes.
86 *
87 * Please note: addr must be aligned to u16.
78 */ 88 */
79static inline bool is_zero_ether_addr(const u8 *addr) 89static inline bool is_zero_ether_addr(const u8 *addr)
80{ 90{
81 return !(addr[0] | addr[1] | addr[2] | addr[3] | addr[4] | addr[5]); 91#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
92 return ((*(const u32 *)addr) | (*(const u16 *)(addr + 4))) == 0;
93#else
94 return (*(const u16 *)(addr + 0) |
95 *(const u16 *)(addr + 2) |
96 *(const u16 *)(addr + 4)) == 0;
97#endif
82} 98}
83 99
84/** 100/**
@@ -109,10 +125,14 @@ static inline bool is_local_ether_addr(const u8 *addr)
109 * @addr: Pointer to a six-byte array containing the Ethernet address 125 * @addr: Pointer to a six-byte array containing the Ethernet address
110 * 126 *
111 * Return true if the address is the broadcast address. 127 * Return true if the address is the broadcast address.
128 *
129 * Please note: addr must be aligned to u16.
112 */ 130 */
113static inline bool is_broadcast_ether_addr(const u8 *addr) 131static inline bool is_broadcast_ether_addr(const u8 *addr)
114{ 132{
115 return (addr[0] & addr[1] & addr[2] & addr[3] & addr[4] & addr[5]) == 0xff; 133 return (*(const u16 *)(addr + 0) &
134 *(const u16 *)(addr + 2) &
135 *(const u16 *)(addr + 4)) == 0xffff;
116} 136}
117 137
118/** 138/**
@@ -134,6 +154,8 @@ static inline bool is_unicast_ether_addr(const u8 *addr)
134 * a multicast address, and is not FF:FF:FF:FF:FF:FF. 154 * a multicast address, and is not FF:FF:FF:FF:FF:FF.
135 * 155 *
136 * Return true if the address is valid. 156 * Return true if the address is valid.
157 *
158 * Please note: addr must be aligned to u16.
137 */ 159 */
138static inline bool is_valid_ether_addr(const u8 *addr) 160static inline bool is_valid_ether_addr(const u8 *addr)
139{ 161{
@@ -196,6 +218,28 @@ static inline void eth_hw_addr_random(struct net_device *dev)
196} 218}
197 219
198/** 220/**
221 * ether_addr_copy - Copy an Ethernet address
222 * @dst: Pointer to a six-byte array Ethernet address destination
223 * @src: Pointer to a six-byte array Ethernet address source
224 *
225 * Please note: dst & src must both be aligned to u16.
226 */
227static inline void ether_addr_copy(u8 *dst, const u8 *src)
228{
229#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
230 *(u32 *)dst = *(const u32 *)src;
231 *(u16 *)(dst + 4) = *(const u16 *)(src + 4);
232#else
233 u16 *a = (u16 *)dst;
234 const u16 *b = (const u16 *)src;
235
236 a[0] = b[0];
237 a[1] = b[1];
238 a[2] = b[2];
239#endif
240}
241
242/**
199 * eth_hw_addr_inherit - Copy dev_addr from another net_device 243 * eth_hw_addr_inherit - Copy dev_addr from another net_device
200 * @dst: pointer to net_device to copy dev_addr to 244 * @dst: pointer to net_device to copy dev_addr to
201 * @src: pointer to net_device to copy dev_addr from 245 * @src: pointer to net_device to copy dev_addr from
@@ -207,24 +251,7 @@ static inline void eth_hw_addr_inherit(struct net_device *dst,
207 struct net_device *src) 251 struct net_device *src)
208{ 252{
209 dst->addr_assign_type = src->addr_assign_type; 253 dst->addr_assign_type = src->addr_assign_type;
210 memcpy(dst->dev_addr, src->dev_addr, ETH_ALEN); 254 ether_addr_copy(dst->dev_addr, src->dev_addr);
211}
212
213/**
214 * compare_ether_addr - Compare two Ethernet addresses
215 * @addr1: Pointer to a six-byte array containing the Ethernet address
216 * @addr2: Pointer other six-byte array containing the Ethernet address
217 *
218 * Compare two Ethernet addresses, returns 0 if equal, non-zero otherwise.
219 * Unlike memcmp(), it doesn't return a value suitable for sorting.
220 */
221static inline unsigned compare_ether_addr(const u8 *addr1, const u8 *addr2)
222{
223 const u16 *a = (const u16 *) addr1;
224 const u16 *b = (const u16 *) addr2;
225
226 BUILD_BUG_ON(ETH_ALEN != 6);
227 return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2])) != 0;
228} 255}
229 256
230/** 257/**
@@ -233,18 +260,21 @@ static inline unsigned compare_ether_addr(const u8 *addr1, const u8 *addr2)
233 * @addr2: Pointer other six-byte array containing the Ethernet address 260 * @addr2: Pointer other six-byte array containing the Ethernet address
234 * 261 *
235 * Compare two Ethernet addresses, returns true if equal 262 * Compare two Ethernet addresses, returns true if equal
263 *
264 * Please note: addr1 & addr2 must both be aligned to u16.
236 */ 265 */
237static inline bool ether_addr_equal(const u8 *addr1, const u8 *addr2) 266static inline bool ether_addr_equal(const u8 *addr1, const u8 *addr2)
238{ 267{
239 return !compare_ether_addr(addr1, addr2); 268#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
240} 269 u32 fold = ((*(const u32 *)addr1) ^ (*(const u32 *)addr2)) |
270 ((*(const u16 *)(addr1 + 4)) ^ (*(const u16 *)(addr2 + 4)));
241 271
242static inline unsigned long zap_last_2bytes(unsigned long value) 272 return fold == 0;
243{
244#ifdef __BIG_ENDIAN
245 return value >> 16;
246#else 273#else
247 return value << 16; 274 const u16 *a = (const u16 *)addr1;
275 const u16 *b = (const u16 *)addr2;
276
277 return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2])) == 0;
248#endif 278#endif
249} 279}
250 280
@@ -265,22 +295,38 @@ static inline unsigned long zap_last_2bytes(unsigned long value)
265static inline bool ether_addr_equal_64bits(const u8 addr1[6+2], 295static inline bool ether_addr_equal_64bits(const u8 addr1[6+2],
266 const u8 addr2[6+2]) 296 const u8 addr2[6+2])
267{ 297{
268#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS 298#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64
269 unsigned long fold = ((*(unsigned long *)addr1) ^ 299 u64 fold = (*(const u64 *)addr1) ^ (*(const u64 *)addr2);
270 (*(unsigned long *)addr2));
271
272 if (sizeof(fold) == 8)
273 return zap_last_2bytes(fold) == 0;
274 300
275 fold |= zap_last_2bytes((*(unsigned long *)(addr1 + 4)) ^ 301#ifdef __BIG_ENDIAN
276 (*(unsigned long *)(addr2 + 4))); 302 return (fold >> 16) == 0;
277 return fold == 0; 303#else
304 return (fold << 16) == 0;
305#endif
278#else 306#else
279 return ether_addr_equal(addr1, addr2); 307 return ether_addr_equal(addr1, addr2);
280#endif 308#endif
281} 309}
282 310
283/** 311/**
312 * ether_addr_equal_unaligned - Compare two not u16 aligned Ethernet addresses
313 * @addr1: Pointer to a six-byte array containing the Ethernet address
314 * @addr2: Pointer other six-byte array containing the Ethernet address
315 *
316 * Compare two Ethernet addresses, returns true if equal
317 *
318 * Please note: Use only when any Ethernet address may not be u16 aligned.
319 */
320static inline bool ether_addr_equal_unaligned(const u8 *addr1, const u8 *addr2)
321{
322#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
323 return ether_addr_equal(addr1, addr2);
324#else
325 return memcmp(addr1, addr2, ETH_ALEN) == 0;
326#endif
327}
328
329/**
284 * is_etherdev_addr - Tell if given Ethernet address belongs to the device. 330 * is_etherdev_addr - Tell if given Ethernet address belongs to the device.
285 * @dev: Pointer to a device structure 331 * @dev: Pointer to a device structure
286 * @addr: Pointer to a six-byte array containing the Ethernet address 332 * @addr: Pointer to a six-byte array containing the Ethernet address