11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * INET An implementation of the TCP/IP protocol suite for the LINUX 31da177e4SLinus Torvalds * operating system. NET is implemented using the BSD Socket 41da177e4SLinus Torvalds * interface as the means of communication with the user level. 51da177e4SLinus Torvalds * 61da177e4SLinus Torvalds * Definitions for the Ethernet handlers. 71da177e4SLinus Torvalds * 81da177e4SLinus Torvalds * Version: @(#)eth.h 1.0.4 05/13/93 91da177e4SLinus Torvalds * 1002c30a84SJesper Juhl * Authors: Ross Biro 111da177e4SLinus Torvalds * Fred N. van Kempen, <[email protected]> 121da177e4SLinus Torvalds * 131da177e4SLinus Torvalds * Relocated to include/linux where it belongs by Alan Cox 141da177e4SLinus Torvalds * <[email protected]> 151da177e4SLinus Torvalds * 161da177e4SLinus Torvalds * This program is free software; you can redistribute it and/or 171da177e4SLinus Torvalds * modify it under the terms of the GNU General Public License 181da177e4SLinus Torvalds * as published by the Free Software Foundation; either version 191da177e4SLinus Torvalds * 2 of the License, or (at your option) any later version. 201da177e4SLinus Torvalds * 211da177e4SLinus Torvalds */ 221da177e4SLinus Torvalds #ifndef _LINUX_ETHERDEVICE_H 231da177e4SLinus Torvalds #define _LINUX_ETHERDEVICE_H 241da177e4SLinus Torvalds 251da177e4SLinus Torvalds #include <linux/if_ether.h> 26bcd61272SArnd Bergmann #include <linux/netdevice.h> 271da177e4SLinus Torvalds #include <linux/random.h> 281f87e235SEric Dumazet #include <asm/unaligned.h> 290d74c42fSJoe Perches #include <asm/bitsperlong.h> 301da177e4SLinus Torvalds 311da177e4SLinus Torvalds #ifdef __KERNEL__ 3256193d1bSAlexander Duyck u32 eth_get_headlen(void *data, unsigned int max_len); 33f629d208SJoe Perches __be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev); 343b04dddeSStephen Hemminger extern const struct header_ops eth_header_ops; 353b04dddeSStephen Hemminger 36f629d208SJoe Perches int eth_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, 373b04dddeSStephen Hemminger const void *daddr, const void *saddr, unsigned len); 38f629d208SJoe Perches int eth_header_parse(const struct sk_buff *skb, unsigned char *haddr); 39f629d208SJoe Perches int eth_header_cache(const struct neighbour *neigh, struct hh_cache *hh, 40f629d208SJoe Perches __be16 type); 41f629d208SJoe Perches void eth_header_cache_update(struct hh_cache *hh, const struct net_device *dev, 423b04dddeSStephen Hemminger const unsigned char *haddr); 43f629d208SJoe Perches int eth_prepare_mac_addr_change(struct net_device *dev, void *p); 44f629d208SJoe Perches void eth_commit_mac_addr_change(struct net_device *dev, void *p); 45f629d208SJoe Perches int eth_mac_addr(struct net_device *dev, void *p); 46f629d208SJoe Perches int eth_change_mtu(struct net_device *dev, int new_mtu); 47f629d208SJoe Perches int eth_validate_addr(struct net_device *dev); 48ccad637bSStephen Hemminger 49f629d208SJoe Perches struct net_device *alloc_etherdev_mqs(int sizeof_priv, unsigned int txqs, 5036909ea4STom Herbert unsigned int rxqs); 51f25f4e44SPeter P Waskiewicz Jr #define alloc_etherdev(sizeof_priv) alloc_etherdev_mq(sizeof_priv, 1) 5236909ea4STom Herbert #define alloc_etherdev_mq(sizeof_priv, count) alloc_etherdev_mqs(sizeof_priv, count, count) 531da177e4SLinus Torvalds 549b174d88SJesse Gross struct sk_buff **eth_gro_receive(struct sk_buff **head, 559b174d88SJesse Gross struct sk_buff *skb); 569b174d88SJesse Gross int eth_gro_complete(struct sk_buff *skb, int nhoff); 579b174d88SJesse Gross 58b3343a2aSJohn Fastabend /* Reserved Ethernet Addresses per IEEE 802.1Q */ 592bc80059SBen Hutchings static const u8 eth_reserved_addr_base[ETH_ALEN] __aligned(2) = 602bc80059SBen Hutchings { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 }; 61b3343a2aSJohn Fastabend 62b3343a2aSJohn Fastabend /** 6346acc460SBen Hutchings * is_link_local_ether_addr - Determine if given Ethernet address is link-local 64b3343a2aSJohn Fastabend * @addr: Pointer to a six-byte array containing the Ethernet address 65b3343a2aSJohn Fastabend * 66b3343a2aSJohn Fastabend * Return true if address is link local reserved addr (01:80:c2:00:00:0X) per 67b3343a2aSJohn Fastabend * IEEE 802.1Q 8.6.3 Frame filtering. 682c722fe1SJoe Perches * 692c722fe1SJoe Perches * Please note: addr must be aligned to u16. 70b3343a2aSJohn Fastabend */ 7146acc460SBen Hutchings static inline bool is_link_local_ether_addr(const u8 *addr) 72b3343a2aSJohn Fastabend { 7346acc460SBen Hutchings __be16 *a = (__be16 *)addr; 742bc80059SBen Hutchings static const __be16 *b = (const __be16 *)eth_reserved_addr_base; 75b3343a2aSJohn Fastabend static const __be16 m = cpu_to_be16(0xfff0); 76b3343a2aSJohn Fastabend 772c722fe1SJoe Perches #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) 782c722fe1SJoe Perches return (((*(const u32 *)addr) ^ (*(const u32 *)b)) | 79*fbaff3efSJesse Brandeburg (__force int)((a[2] ^ b[2]) & m)) == 0; 802c722fe1SJoe Perches #else 81b3343a2aSJohn Fastabend return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | ((a[2] ^ b[2]) & m)) == 0; 822c722fe1SJoe Perches #endif 83b3343a2aSJohn Fastabend } 84b3343a2aSJohn Fastabend 851da177e4SLinus Torvalds /** 86c2da8acaSStephen Hemminger * is_zero_ether_addr - Determine if give Ethernet address is all zeros. 87c2da8acaSStephen Hemminger * @addr: Pointer to a six-byte array containing the Ethernet address 88c2da8acaSStephen Hemminger * 89c2da8acaSStephen Hemminger * Return true if the address is all zeroes. 902c722fe1SJoe Perches * 912c722fe1SJoe Perches * Please note: addr must be aligned to u16. 921da177e4SLinus Torvalds */ 93b44907e6SJoe Perches static inline bool is_zero_ether_addr(const u8 *addr) 941da177e4SLinus Torvalds { 952c722fe1SJoe Perches #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) 962c722fe1SJoe Perches return ((*(const u32 *)addr) | (*(const u16 *)(addr + 4))) == 0; 972c722fe1SJoe Perches #else 982c722fe1SJoe Perches return (*(const u16 *)(addr + 0) | 992c722fe1SJoe Perches *(const u16 *)(addr + 2) | 1002c722fe1SJoe Perches *(const u16 *)(addr + 4)) == 0; 1012c722fe1SJoe Perches #endif 1021da177e4SLinus Torvalds } 1031da177e4SLinus Torvalds 1041da177e4SLinus Torvalds /** 105c2da8acaSStephen Hemminger * is_multicast_ether_addr - Determine if the Ethernet address is a multicast. 10679165121SMichael Ellerman * @addr: Pointer to a six-byte array containing the Ethernet address 10779165121SMichael Ellerman * 10879165121SMichael Ellerman * Return true if the address is a multicast address. 10988df8ef5SStephen Hemminger * By definition the broadcast address is also a multicast address. 11079165121SMichael Ellerman */ 111b44907e6SJoe Perches static inline bool is_multicast_ether_addr(const u8 *addr) 11279165121SMichael Ellerman { 113d54385ceSAlexander Duyck #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) 114d54385ceSAlexander Duyck u32 a = *(const u32 *)addr; 115d54385ceSAlexander Duyck #else 116d54385ceSAlexander Duyck u16 a = *(const u16 *)addr; 117d54385ceSAlexander Duyck #endif 118d54385ceSAlexander Duyck #ifdef __BIG_ENDIAN 119d54385ceSAlexander Duyck return 0x01 & (a >> ((sizeof(a) * 8) - 8)); 120d54385ceSAlexander Duyck #else 121d54385ceSAlexander Duyck return 0x01 & a; 122d54385ceSAlexander Duyck #endif 123d54385ceSAlexander Duyck } 124d54385ceSAlexander Duyck 125d54385ceSAlexander Duyck static inline bool is_multicast_ether_addr_64bits(const u8 addr[6+2]) 126d54385ceSAlexander Duyck { 127d54385ceSAlexander Duyck #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64 128d54385ceSAlexander Duyck #ifdef __BIG_ENDIAN 129d54385ceSAlexander Duyck return 0x01 & ((*(const u64 *)addr) >> 56); 130d54385ceSAlexander Duyck #else 131d54385ceSAlexander Duyck return 0x01 & (*(const u64 *)addr); 132d54385ceSAlexander Duyck #endif 133d54385ceSAlexander Duyck #else 134d54385ceSAlexander Duyck return is_multicast_ether_addr(addr); 135d54385ceSAlexander Duyck #endif 13679165121SMichael Ellerman } 13779165121SMichael Ellerman 138c2da8acaSStephen Hemminger /** 139bc2cda1eSRandy Dunlap * is_local_ether_addr - Determine if the Ethernet address is locally-assigned one (IEEE 802). 140e024715fSPaolo 'Blaisorblade' Giarrusso * @addr: Pointer to a six-byte array containing the Ethernet address 141e024715fSPaolo 'Blaisorblade' Giarrusso * 142e024715fSPaolo 'Blaisorblade' Giarrusso * Return true if the address is a local address. 143e024715fSPaolo 'Blaisorblade' Giarrusso */ 144b44907e6SJoe Perches static inline bool is_local_ether_addr(const u8 *addr) 145e024715fSPaolo 'Blaisorblade' Giarrusso { 146a02cec21SEric Dumazet return 0x02 & addr[0]; 147e024715fSPaolo 'Blaisorblade' Giarrusso } 148e024715fSPaolo 'Blaisorblade' Giarrusso 149e024715fSPaolo 'Blaisorblade' Giarrusso /** 150c2da8acaSStephen Hemminger * is_broadcast_ether_addr - Determine if the Ethernet address is broadcast 151c2da8acaSStephen Hemminger * @addr: Pointer to a six-byte array containing the Ethernet address 152c2da8acaSStephen Hemminger * 153c2da8acaSStephen Hemminger * Return true if the address is the broadcast address. 1542c722fe1SJoe Perches * 1552c722fe1SJoe Perches * Please note: addr must be aligned to u16. 156c2da8acaSStephen Hemminger */ 157b44907e6SJoe Perches static inline bool is_broadcast_ether_addr(const u8 *addr) 1589bd481f8SJeff Garzik { 1592c722fe1SJoe Perches return (*(const u16 *)(addr + 0) & 1602c722fe1SJoe Perches *(const u16 *)(addr + 2) & 1612c722fe1SJoe Perches *(const u16 *)(addr + 4)) == 0xffff; 1629bd481f8SJeff Garzik } 1639bd481f8SJeff Garzik 16479165121SMichael Ellerman /** 16551e7eed7STobias Klauser * is_unicast_ether_addr - Determine if the Ethernet address is unicast 16651e7eed7STobias Klauser * @addr: Pointer to a six-byte array containing the Ethernet address 16751e7eed7STobias Klauser * 16851e7eed7STobias Klauser * Return true if the address is a unicast address. 16951e7eed7STobias Klauser */ 170b44907e6SJoe Perches static inline bool is_unicast_ether_addr(const u8 *addr) 17151e7eed7STobias Klauser { 17251e7eed7STobias Klauser return !is_multicast_ether_addr(addr); 17351e7eed7STobias Klauser } 17451e7eed7STobias Klauser 17551e7eed7STobias Klauser /** 1761da177e4SLinus Torvalds * is_valid_ether_addr - Determine if the given Ethernet address is valid 1771da177e4SLinus Torvalds * @addr: Pointer to a six-byte array containing the Ethernet address 1781da177e4SLinus Torvalds * 1791da177e4SLinus Torvalds * Check that the Ethernet address (MAC) is not 00:00:00:00:00:00, is not 18079165121SMichael Ellerman * a multicast address, and is not FF:FF:FF:FF:FF:FF. 1811da177e4SLinus Torvalds * 1821da177e4SLinus Torvalds * Return true if the address is valid. 1832c722fe1SJoe Perches * 1842c722fe1SJoe Perches * Please note: addr must be aligned to u16. 1851da177e4SLinus Torvalds */ 186b44907e6SJoe Perches static inline bool is_valid_ether_addr(const u8 *addr) 1871da177e4SLinus Torvalds { 18879165121SMichael Ellerman /* FF:FF:FF:FF:FF:FF is a multicast address so we don't need to 18979165121SMichael Ellerman * explicitly check for it here. */ 19079165121SMichael Ellerman return !is_multicast_ether_addr(addr) && !is_zero_ether_addr(addr); 1911da177e4SLinus Torvalds } 1921da177e4SLinus Torvalds 1931da177e4SLinus Torvalds /** 1942c7a88c2SAlexander Duyck * eth_proto_is_802_3 - Determine if a given Ethertype/length is a protocol 1952c7a88c2SAlexander Duyck * @proto: Ethertype/length value to be tested 1962c7a88c2SAlexander Duyck * 1972c7a88c2SAlexander Duyck * Check that the value from the Ethertype/length field is a valid Ethertype. 1982c7a88c2SAlexander Duyck * 1992c7a88c2SAlexander Duyck * Return true if the valid is an 802.3 supported Ethertype. 2002c7a88c2SAlexander Duyck */ 2012c7a88c2SAlexander Duyck static inline bool eth_proto_is_802_3(__be16 proto) 2022c7a88c2SAlexander Duyck { 2032c7a88c2SAlexander Duyck #ifndef __BIG_ENDIAN 2042c7a88c2SAlexander Duyck /* if CPU is little endian mask off bits representing LSB */ 2052c7a88c2SAlexander Duyck proto &= htons(0xFF00); 2062c7a88c2SAlexander Duyck #endif 2072c7a88c2SAlexander Duyck /* cast both to u16 and compare since LSB can be ignored */ 2082c7a88c2SAlexander Duyck return (__force u16)proto >= (__force u16)htons(ETH_P_802_3_MIN); 2092c7a88c2SAlexander Duyck } 2102c7a88c2SAlexander Duyck 2112c7a88c2SAlexander Duyck /** 2120a4dd594SJoe Perches * eth_random_addr - Generate software assigned random Ethernet address 2131da177e4SLinus Torvalds * @addr: Pointer to a six-byte array containing the Ethernet address 2141da177e4SLinus Torvalds * 2151da177e4SLinus Torvalds * Generate a random Ethernet address (MAC) that is not multicast 2161da177e4SLinus Torvalds * and has the local assigned bit set. 2171da177e4SLinus Torvalds */ 2180a4dd594SJoe Perches static inline void eth_random_addr(u8 *addr) 2191da177e4SLinus Torvalds { 2201da177e4SLinus Torvalds get_random_bytes(addr, ETH_ALEN); 2211da177e4SLinus Torvalds addr[0] &= 0xfe; /* clear multicast bit */ 2221da177e4SLinus Torvalds addr[0] |= 0x02; /* set local assignment bit (IEEE802) */ 2231da177e4SLinus Torvalds } 224360ac8e2SStephen Hemminger 2250a4dd594SJoe Perches #define random_ether_addr(addr) eth_random_addr(addr) 2260a4dd594SJoe Perches 227360ac8e2SStephen Hemminger /** 228ad7eee98SJohannes Berg * eth_broadcast_addr - Assign broadcast address 229ad7eee98SJohannes Berg * @addr: Pointer to a six-byte array containing the Ethernet address 230ad7eee98SJohannes Berg * 231ad7eee98SJohannes Berg * Assign the broadcast address to the given address array. 232ad7eee98SJohannes Berg */ 233ad7eee98SJohannes Berg static inline void eth_broadcast_addr(u8 *addr) 234ad7eee98SJohannes Berg { 235ad7eee98SJohannes Berg memset(addr, 0xff, ETH_ALEN); 236ad7eee98SJohannes Berg } 237ad7eee98SJohannes Berg 238ad7eee98SJohannes Berg /** 2396d57e907SDuan Jiong * eth_zero_addr - Assign zero address 2406d57e907SDuan Jiong * @addr: Pointer to a six-byte array containing the Ethernet address 2416d57e907SDuan Jiong * 2426d57e907SDuan Jiong * Assign the zero address to the given address array. 2436d57e907SDuan Jiong */ 2446d57e907SDuan Jiong static inline void eth_zero_addr(u8 *addr) 2456d57e907SDuan Jiong { 2466d57e907SDuan Jiong memset(addr, 0x00, ETH_ALEN); 2476d57e907SDuan Jiong } 2486d57e907SDuan Jiong 2496d57e907SDuan Jiong /** 2501a0d6ae5SDanny Kukawka * eth_hw_addr_random - Generate software assigned random Ethernet and 2511a0d6ae5SDanny Kukawka * set device flag 252c1f79426SStefan Assmann * @dev: pointer to net_device structure 253c1f79426SStefan Assmann * 2541a0d6ae5SDanny Kukawka * Generate a random Ethernet address (MAC) to be used by a net device 2551a0d6ae5SDanny Kukawka * and set addr_assign_type so the state can be read by sysfs and be 2561a0d6ae5SDanny Kukawka * used by userspace. 257c1f79426SStefan Assmann */ 2581a0d6ae5SDanny Kukawka static inline void eth_hw_addr_random(struct net_device *dev) 259c1f79426SStefan Assmann { 260e41b2d7fSJiri Pirko dev->addr_assign_type = NET_ADDR_RANDOM; 2610a4dd594SJoe Perches eth_random_addr(dev->dev_addr); 262c1f79426SStefan Assmann } 263c1f79426SStefan Assmann 264c1f79426SStefan Assmann /** 265286ab723SJoe Perches * ether_addr_copy - Copy an Ethernet address 266286ab723SJoe Perches * @dst: Pointer to a six-byte array Ethernet address destination 267286ab723SJoe Perches * @src: Pointer to a six-byte array Ethernet address source 268286ab723SJoe Perches * 269286ab723SJoe Perches * Please note: dst & src must both be aligned to u16. 270286ab723SJoe Perches */ 271286ab723SJoe Perches static inline void ether_addr_copy(u8 *dst, const u8 *src) 272286ab723SJoe Perches { 273286ab723SJoe Perches #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) 274286ab723SJoe Perches *(u32 *)dst = *(const u32 *)src; 275286ab723SJoe Perches *(u16 *)(dst + 4) = *(const u16 *)(src + 4); 276286ab723SJoe Perches #else 277286ab723SJoe Perches u16 *a = (u16 *)dst; 278286ab723SJoe Perches const u16 *b = (const u16 *)src; 279286ab723SJoe Perches 280286ab723SJoe Perches a[0] = b[0]; 281286ab723SJoe Perches a[1] = b[1]; 282286ab723SJoe Perches a[2] = b[2]; 283286ab723SJoe Perches #endif 284286ab723SJoe Perches } 285286ab723SJoe Perches 286286ab723SJoe Perches /** 28783a093b4SBjørn Mork * eth_hw_addr_inherit - Copy dev_addr from another net_device 28883a093b4SBjørn Mork * @dst: pointer to net_device to copy dev_addr to 28983a093b4SBjørn Mork * @src: pointer to net_device to copy dev_addr from 29083a093b4SBjørn Mork * 29183a093b4SBjørn Mork * Copy the Ethernet address from one net_device to another along with 29283a093b4SBjørn Mork * the address attributes (addr_assign_type). 29383a093b4SBjørn Mork */ 29483a093b4SBjørn Mork static inline void eth_hw_addr_inherit(struct net_device *dst, 29583a093b4SBjørn Mork struct net_device *src) 29683a093b4SBjørn Mork { 29783a093b4SBjørn Mork dst->addr_assign_type = src->addr_assign_type; 298286ab723SJoe Perches ether_addr_copy(dst->dev_addr, src->dev_addr); 29983a093b4SBjørn Mork } 30083a093b4SBjørn Mork 30183a093b4SBjørn Mork /** 302a599b0f5SJoe Perches * ether_addr_equal - Compare two Ethernet addresses 303a599b0f5SJoe Perches * @addr1: Pointer to a six-byte array containing the Ethernet address 304a599b0f5SJoe Perches * @addr2: Pointer other six-byte array containing the Ethernet address 305a599b0f5SJoe Perches * 306048b899cSstephen hemminger * Compare two Ethernet addresses, returns true if equal 3070d74c42fSJoe Perches * 3080d74c42fSJoe Perches * Please note: addr1 & addr2 must both be aligned to u16. 309a599b0f5SJoe Perches */ 310a599b0f5SJoe Perches static inline bool ether_addr_equal(const u8 *addr1, const u8 *addr2) 311a599b0f5SJoe Perches { 3120d74c42fSJoe Perches #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) 3130d74c42fSJoe Perches u32 fold = ((*(const u32 *)addr1) ^ (*(const u32 *)addr2)) | 3140d74c42fSJoe Perches ((*(const u16 *)(addr1 + 4)) ^ (*(const u16 *)(addr2 + 4))); 315a599b0f5SJoe Perches 3160d74c42fSJoe Perches return fold == 0; 3171f87e235SEric Dumazet #else 3180d74c42fSJoe Perches const u16 *a = (const u16 *)addr1; 3190d74c42fSJoe Perches const u16 *b = (const u16 *)addr2; 3200d74c42fSJoe Perches 3210d74c42fSJoe Perches return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2])) == 0; 3221f87e235SEric Dumazet #endif 3231f87e235SEric Dumazet } 3241f87e235SEric Dumazet 3251f87e235SEric Dumazet /** 326baf523c9SJoe Perches * ether_addr_equal_64bits - Compare two Ethernet addresses 327baf523c9SJoe Perches * @addr1: Pointer to an array of 8 bytes 328baf523c9SJoe Perches * @addr2: Pointer to an other array of 8 bytes 329baf523c9SJoe Perches * 330048b899cSstephen hemminger * Compare two Ethernet addresses, returns true if equal, false otherwise. 331baf523c9SJoe Perches * 332baf523c9SJoe Perches * The function doesn't need any conditional branches and possibly uses 333baf523c9SJoe Perches * word memory accesses on CPU allowing cheap unaligned memory reads. 334048b899cSstephen hemminger * arrays = { byte1, byte2, byte3, byte4, byte5, byte6, pad1, pad2 } 335baf523c9SJoe Perches * 336048b899cSstephen hemminger * Please note that alignment of addr1 & addr2 are only guaranteed to be 16 bits. 337baf523c9SJoe Perches */ 338baf523c9SJoe Perches 339baf523c9SJoe Perches static inline bool ether_addr_equal_64bits(const u8 addr1[6+2], 340baf523c9SJoe Perches const u8 addr2[6+2]) 341baf523c9SJoe Perches { 3420d74c42fSJoe Perches #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64 3430d74c42fSJoe Perches u64 fold = (*(const u64 *)addr1) ^ (*(const u64 *)addr2); 344e550ba1aSJoe Perches 3450d74c42fSJoe Perches #ifdef __BIG_ENDIAN 3460d74c42fSJoe Perches return (fold >> 16) == 0; 3470d74c42fSJoe Perches #else 3480d74c42fSJoe Perches return (fold << 16) == 0; 3490d74c42fSJoe Perches #endif 350e550ba1aSJoe Perches #else 351e550ba1aSJoe Perches return ether_addr_equal(addr1, addr2); 352e550ba1aSJoe Perches #endif 353baf523c9SJoe Perches } 354baf523c9SJoe Perches 355baf523c9SJoe Perches /** 35673eaef87SJoe Perches * ether_addr_equal_unaligned - Compare two not u16 aligned Ethernet addresses 35773eaef87SJoe Perches * @addr1: Pointer to a six-byte array containing the Ethernet address 35873eaef87SJoe Perches * @addr2: Pointer other six-byte array containing the Ethernet address 35973eaef87SJoe Perches * 36073eaef87SJoe Perches * Compare two Ethernet addresses, returns true if equal 36173eaef87SJoe Perches * 36273eaef87SJoe Perches * Please note: Use only when any Ethernet address may not be u16 aligned. 36373eaef87SJoe Perches */ 36473eaef87SJoe Perches static inline bool ether_addr_equal_unaligned(const u8 *addr1, const u8 *addr2) 36573eaef87SJoe Perches { 36673eaef87SJoe Perches #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) 36773eaef87SJoe Perches return ether_addr_equal(addr1, addr2); 36873eaef87SJoe Perches #else 36973eaef87SJoe Perches return memcmp(addr1, addr2, ETH_ALEN) == 0; 37073eaef87SJoe Perches #endif 37173eaef87SJoe Perches } 37273eaef87SJoe Perches 37373eaef87SJoe Perches /** 374f001fde5SJiri Pirko * is_etherdev_addr - Tell if given Ethernet address belongs to the device. 375f001fde5SJiri Pirko * @dev: Pointer to a device structure 376f001fde5SJiri Pirko * @addr: Pointer to a six-byte array containing the Ethernet address 377f001fde5SJiri Pirko * 378f001fde5SJiri Pirko * Compare passed address with all addresses of the device. Return true if the 379f001fde5SJiri Pirko * address if one of the device addresses. 380f001fde5SJiri Pirko * 381e550ba1aSJoe Perches * Note that this function calls ether_addr_equal_64bits() so take care of 382f001fde5SJiri Pirko * the right padding. 383f001fde5SJiri Pirko */ 384f001fde5SJiri Pirko static inline bool is_etherdev_addr(const struct net_device *dev, 385f001fde5SJiri Pirko const u8 addr[6 + 2]) 386f001fde5SJiri Pirko { 387f001fde5SJiri Pirko struct netdev_hw_addr *ha; 388e550ba1aSJoe Perches bool res = false; 389f001fde5SJiri Pirko 390f001fde5SJiri Pirko rcu_read_lock(); 391f001fde5SJiri Pirko for_each_dev_addr(dev, ha) { 392e550ba1aSJoe Perches res = ether_addr_equal_64bits(addr, ha->addr); 393e550ba1aSJoe Perches if (res) 394f001fde5SJiri Pirko break; 395f001fde5SJiri Pirko } 396f001fde5SJiri Pirko rcu_read_unlock(); 397e550ba1aSJoe Perches return res; 398f001fde5SJiri Pirko } 39979165121SMichael Ellerman #endif /* __KERNEL__ */ 4001da177e4SLinus Torvalds 401aa4b9f53SHerbert Xu /** 402aa4b9f53SHerbert Xu * compare_ether_header - Compare two Ethernet headers 403aa4b9f53SHerbert Xu * @a: Pointer to Ethernet header 404aa4b9f53SHerbert Xu * @b: Pointer to Ethernet header 405aa4b9f53SHerbert Xu * 406048b899cSstephen hemminger * Compare two Ethernet headers, returns 0 if equal. 407aa4b9f53SHerbert Xu * This assumes that the network header (i.e., IP header) is 4-byte 408aa4b9f53SHerbert Xu * aligned OR the platform can handle unaligned access. This is the 409aa4b9f53SHerbert Xu * case for all packets coming into netif_receive_skb or similar 410aa4b9f53SHerbert Xu * entry points. 411aa4b9f53SHerbert Xu */ 412aa4b9f53SHerbert Xu 41340d0802bSEric Dumazet static inline unsigned long compare_ether_header(const void *a, const void *b) 414aa4b9f53SHerbert Xu { 41540d0802bSEric Dumazet #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64 41640d0802bSEric Dumazet unsigned long fold; 41740d0802bSEric Dumazet 41840d0802bSEric Dumazet /* 41940d0802bSEric Dumazet * We want to compare 14 bytes: 42040d0802bSEric Dumazet * [a0 ... a13] ^ [b0 ... b13] 42140d0802bSEric Dumazet * Use two long XOR, ORed together, with an overlap of two bytes. 42240d0802bSEric Dumazet * [a0 a1 a2 a3 a4 a5 a6 a7 ] ^ [b0 b1 b2 b3 b4 b5 b6 b7 ] | 42340d0802bSEric Dumazet * [a6 a7 a8 a9 a10 a11 a12 a13] ^ [b6 b7 b8 b9 b10 b11 b12 b13] 42440d0802bSEric Dumazet * This means the [a6 a7] ^ [b6 b7] part is done two times. 42540d0802bSEric Dumazet */ 42640d0802bSEric Dumazet fold = *(unsigned long *)a ^ *(unsigned long *)b; 42740d0802bSEric Dumazet fold |= *(unsigned long *)(a + 6) ^ *(unsigned long *)(b + 6); 42840d0802bSEric Dumazet return fold; 42940d0802bSEric Dumazet #else 430aa4b9f53SHerbert Xu u32 *a32 = (u32 *)((u8 *)a + 2); 431aa4b9f53SHerbert Xu u32 *b32 = (u32 *)((u8 *)b + 2); 432aa4b9f53SHerbert Xu 433aa4b9f53SHerbert Xu return (*(u16 *)a ^ *(u16 *)b) | (a32[0] ^ b32[0]) | 434aa4b9f53SHerbert Xu (a32[1] ^ b32[1]) | (a32[2] ^ b32[2]); 43540d0802bSEric Dumazet #endif 436aa4b9f53SHerbert Xu } 437aa4b9f53SHerbert Xu 4389c0c1124SAlexander Duyck /** 4399c0c1124SAlexander Duyck * eth_skb_pad - Pad buffer to mininum number of octets for Ethernet frame 4409c0c1124SAlexander Duyck * @skb: Buffer to pad 4419c0c1124SAlexander Duyck * 4429c0c1124SAlexander Duyck * An Ethernet frame should have a minimum size of 60 bytes. This function 4439c0c1124SAlexander Duyck * takes short frames and pads them with zeros up to the 60 byte limit. 4449c0c1124SAlexander Duyck */ 4459c0c1124SAlexander Duyck static inline int eth_skb_pad(struct sk_buff *skb) 4469c0c1124SAlexander Duyck { 4479c0c1124SAlexander Duyck return skb_put_padto(skb, ETH_ZLEN); 4489c0c1124SAlexander Duyck } 4499c0c1124SAlexander Duyck 4501da177e4SLinus Torvalds #endif /* _LINUX_ETHERDEVICE_H */ 451