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__ 32f629d208SJoe Perches __be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev); 333b04dddeSStephen Hemminger extern const struct header_ops eth_header_ops; 343b04dddeSStephen Hemminger 35f629d208SJoe Perches int eth_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, 363b04dddeSStephen Hemminger const void *daddr, const void *saddr, unsigned len); 37f629d208SJoe Perches int eth_rebuild_header(struct sk_buff *skb); 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 54b3343a2aSJohn Fastabend /* Reserved Ethernet Addresses per IEEE 802.1Q */ 552bc80059SBen Hutchings static const u8 eth_reserved_addr_base[ETH_ALEN] __aligned(2) = 562bc80059SBen Hutchings { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 }; 57b3343a2aSJohn Fastabend 58b3343a2aSJohn Fastabend /** 5946acc460SBen Hutchings * is_link_local_ether_addr - Determine if given Ethernet address is link-local 60b3343a2aSJohn Fastabend * @addr: Pointer to a six-byte array containing the Ethernet address 61b3343a2aSJohn Fastabend * 62b3343a2aSJohn Fastabend * Return true if address is link local reserved addr (01:80:c2:00:00:0X) per 63b3343a2aSJohn Fastabend * IEEE 802.1Q 8.6.3 Frame filtering. 64b3343a2aSJohn Fastabend */ 6546acc460SBen Hutchings static inline bool is_link_local_ether_addr(const u8 *addr) 66b3343a2aSJohn Fastabend { 6746acc460SBen Hutchings __be16 *a = (__be16 *)addr; 682bc80059SBen Hutchings static const __be16 *b = (const __be16 *)eth_reserved_addr_base; 69b3343a2aSJohn Fastabend static const __be16 m = cpu_to_be16(0xfff0); 70b3343a2aSJohn Fastabend 71b3343a2aSJohn Fastabend return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | ((a[2] ^ b[2]) & m)) == 0; 72b3343a2aSJohn Fastabend } 73b3343a2aSJohn Fastabend 741da177e4SLinus Torvalds /** 75c2da8acaSStephen Hemminger * is_zero_ether_addr - Determine if give Ethernet address is all zeros. 76c2da8acaSStephen Hemminger * @addr: Pointer to a six-byte array containing the Ethernet address 77c2da8acaSStephen Hemminger * 78c2da8acaSStephen Hemminger * Return true if the address is all zeroes. 791da177e4SLinus Torvalds */ 80b44907e6SJoe Perches static inline bool is_zero_ether_addr(const u8 *addr) 811da177e4SLinus Torvalds { 821da177e4SLinus Torvalds return !(addr[0] | addr[1] | addr[2] | addr[3] | addr[4] | addr[5]); 831da177e4SLinus Torvalds } 841da177e4SLinus Torvalds 851da177e4SLinus Torvalds /** 86c2da8acaSStephen Hemminger * is_multicast_ether_addr - Determine if the Ethernet address is a multicast. 8779165121SMichael Ellerman * @addr: Pointer to a six-byte array containing the Ethernet address 8879165121SMichael Ellerman * 8979165121SMichael Ellerman * Return true if the address is a multicast address. 9088df8ef5SStephen Hemminger * By definition the broadcast address is also a multicast address. 9179165121SMichael Ellerman */ 92b44907e6SJoe Perches static inline bool is_multicast_ether_addr(const u8 *addr) 9379165121SMichael Ellerman { 94a02cec21SEric Dumazet return 0x01 & addr[0]; 9579165121SMichael Ellerman } 9679165121SMichael Ellerman 97c2da8acaSStephen Hemminger /** 98bc2cda1eSRandy Dunlap * is_local_ether_addr - Determine if the Ethernet address is locally-assigned one (IEEE 802). 99e024715fSPaolo 'Blaisorblade' Giarrusso * @addr: Pointer to a six-byte array containing the Ethernet address 100e024715fSPaolo 'Blaisorblade' Giarrusso * 101e024715fSPaolo 'Blaisorblade' Giarrusso * Return true if the address is a local address. 102e024715fSPaolo 'Blaisorblade' Giarrusso */ 103b44907e6SJoe Perches static inline bool is_local_ether_addr(const u8 *addr) 104e024715fSPaolo 'Blaisorblade' Giarrusso { 105a02cec21SEric Dumazet return 0x02 & addr[0]; 106e024715fSPaolo 'Blaisorblade' Giarrusso } 107e024715fSPaolo 'Blaisorblade' Giarrusso 108e024715fSPaolo 'Blaisorblade' Giarrusso /** 109c2da8acaSStephen Hemminger * is_broadcast_ether_addr - Determine if the Ethernet address is broadcast 110c2da8acaSStephen Hemminger * @addr: Pointer to a six-byte array containing the Ethernet address 111c2da8acaSStephen Hemminger * 112c2da8acaSStephen Hemminger * Return true if the address is the broadcast address. 113c2da8acaSStephen Hemminger */ 114b44907e6SJoe Perches static inline bool is_broadcast_ether_addr(const u8 *addr) 1159bd481f8SJeff Garzik { 1162407534fSStephen Hemminger return (addr[0] & addr[1] & addr[2] & addr[3] & addr[4] & addr[5]) == 0xff; 1179bd481f8SJeff Garzik } 1189bd481f8SJeff Garzik 11979165121SMichael Ellerman /** 12051e7eed7STobias Klauser * is_unicast_ether_addr - Determine if the Ethernet address is unicast 12151e7eed7STobias Klauser * @addr: Pointer to a six-byte array containing the Ethernet address 12251e7eed7STobias Klauser * 12351e7eed7STobias Klauser * Return true if the address is a unicast address. 12451e7eed7STobias Klauser */ 125b44907e6SJoe Perches static inline bool is_unicast_ether_addr(const u8 *addr) 12651e7eed7STobias Klauser { 12751e7eed7STobias Klauser return !is_multicast_ether_addr(addr); 12851e7eed7STobias Klauser } 12951e7eed7STobias Klauser 13051e7eed7STobias Klauser /** 1311da177e4SLinus Torvalds * is_valid_ether_addr - Determine if the given Ethernet address is valid 1321da177e4SLinus Torvalds * @addr: Pointer to a six-byte array containing the Ethernet address 1331da177e4SLinus Torvalds * 1341da177e4SLinus Torvalds * Check that the Ethernet address (MAC) is not 00:00:00:00:00:00, is not 13579165121SMichael Ellerman * a multicast address, and is not FF:FF:FF:FF:FF:FF. 1361da177e4SLinus Torvalds * 1371da177e4SLinus Torvalds * Return true if the address is valid. 1381da177e4SLinus Torvalds */ 139b44907e6SJoe Perches static inline bool is_valid_ether_addr(const u8 *addr) 1401da177e4SLinus Torvalds { 14179165121SMichael Ellerman /* FF:FF:FF:FF:FF:FF is a multicast address so we don't need to 14279165121SMichael Ellerman * explicitly check for it here. */ 14379165121SMichael Ellerman return !is_multicast_ether_addr(addr) && !is_zero_ether_addr(addr); 1441da177e4SLinus Torvalds } 1451da177e4SLinus Torvalds 1461da177e4SLinus Torvalds /** 1470a4dd594SJoe Perches * eth_random_addr - Generate software assigned random Ethernet address 1481da177e4SLinus Torvalds * @addr: Pointer to a six-byte array containing the Ethernet address 1491da177e4SLinus Torvalds * 1501da177e4SLinus Torvalds * Generate a random Ethernet address (MAC) that is not multicast 1511da177e4SLinus Torvalds * and has the local assigned bit set. 1521da177e4SLinus Torvalds */ 1530a4dd594SJoe Perches static inline void eth_random_addr(u8 *addr) 1541da177e4SLinus Torvalds { 1551da177e4SLinus Torvalds get_random_bytes(addr, ETH_ALEN); 1561da177e4SLinus Torvalds addr[0] &= 0xfe; /* clear multicast bit */ 1571da177e4SLinus Torvalds addr[0] |= 0x02; /* set local assignment bit (IEEE802) */ 1581da177e4SLinus Torvalds } 159360ac8e2SStephen Hemminger 1600a4dd594SJoe Perches #define random_ether_addr(addr) eth_random_addr(addr) 1610a4dd594SJoe Perches 162360ac8e2SStephen Hemminger /** 163ad7eee98SJohannes Berg * eth_broadcast_addr - Assign broadcast address 164ad7eee98SJohannes Berg * @addr: Pointer to a six-byte array containing the Ethernet address 165ad7eee98SJohannes Berg * 166ad7eee98SJohannes Berg * Assign the broadcast address to the given address array. 167ad7eee98SJohannes Berg */ 168ad7eee98SJohannes Berg static inline void eth_broadcast_addr(u8 *addr) 169ad7eee98SJohannes Berg { 170ad7eee98SJohannes Berg memset(addr, 0xff, ETH_ALEN); 171ad7eee98SJohannes Berg } 172ad7eee98SJohannes Berg 173ad7eee98SJohannes Berg /** 1746d57e907SDuan Jiong * eth_zero_addr - Assign zero address 1756d57e907SDuan Jiong * @addr: Pointer to a six-byte array containing the Ethernet address 1766d57e907SDuan Jiong * 1776d57e907SDuan Jiong * Assign the zero address to the given address array. 1786d57e907SDuan Jiong */ 1796d57e907SDuan Jiong static inline void eth_zero_addr(u8 *addr) 1806d57e907SDuan Jiong { 1816d57e907SDuan Jiong memset(addr, 0x00, ETH_ALEN); 1826d57e907SDuan Jiong } 1836d57e907SDuan Jiong 1846d57e907SDuan Jiong /** 1851a0d6ae5SDanny Kukawka * eth_hw_addr_random - Generate software assigned random Ethernet and 1861a0d6ae5SDanny Kukawka * set device flag 187c1f79426SStefan Assmann * @dev: pointer to net_device structure 188c1f79426SStefan Assmann * 1891a0d6ae5SDanny Kukawka * Generate a random Ethernet address (MAC) to be used by a net device 1901a0d6ae5SDanny Kukawka * and set addr_assign_type so the state can be read by sysfs and be 1911a0d6ae5SDanny Kukawka * used by userspace. 192c1f79426SStefan Assmann */ 1931a0d6ae5SDanny Kukawka static inline void eth_hw_addr_random(struct net_device *dev) 194c1f79426SStefan Assmann { 195e41b2d7fSJiri Pirko dev->addr_assign_type = NET_ADDR_RANDOM; 1960a4dd594SJoe Perches eth_random_addr(dev->dev_addr); 197c1f79426SStefan Assmann } 198c1f79426SStefan Assmann 199c1f79426SStefan Assmann /** 20083a093b4SBjørn Mork * eth_hw_addr_inherit - Copy dev_addr from another net_device 20183a093b4SBjørn Mork * @dst: pointer to net_device to copy dev_addr to 20283a093b4SBjørn Mork * @src: pointer to net_device to copy dev_addr from 20383a093b4SBjørn Mork * 20483a093b4SBjørn Mork * Copy the Ethernet address from one net_device to another along with 20583a093b4SBjørn Mork * the address attributes (addr_assign_type). 20683a093b4SBjørn Mork */ 20783a093b4SBjørn Mork static inline void eth_hw_addr_inherit(struct net_device *dst, 20883a093b4SBjørn Mork struct net_device *src) 20983a093b4SBjørn Mork { 21083a093b4SBjørn Mork dst->addr_assign_type = src->addr_assign_type; 21183a093b4SBjørn Mork memcpy(dst->dev_addr, src->dev_addr, ETH_ALEN); 21283a093b4SBjørn Mork } 21383a093b4SBjørn Mork 21483a093b4SBjørn Mork /** 215a599b0f5SJoe Perches * ether_addr_equal - Compare two Ethernet addresses 216a599b0f5SJoe Perches * @addr1: Pointer to a six-byte array containing the Ethernet address 217a599b0f5SJoe Perches * @addr2: Pointer other six-byte array containing the Ethernet address 218a599b0f5SJoe Perches * 219048b899cSstephen hemminger * Compare two Ethernet addresses, returns true if equal 2200d74c42fSJoe Perches * 2210d74c42fSJoe Perches * Please note: addr1 & addr2 must both be aligned to u16. 222a599b0f5SJoe Perches */ 223a599b0f5SJoe Perches static inline bool ether_addr_equal(const u8 *addr1, const u8 *addr2) 224a599b0f5SJoe Perches { 2250d74c42fSJoe Perches #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) 2260d74c42fSJoe Perches u32 fold = ((*(const u32 *)addr1) ^ (*(const u32 *)addr2)) | 2270d74c42fSJoe Perches ((*(const u16 *)(addr1 + 4)) ^ (*(const u16 *)(addr2 + 4))); 228a599b0f5SJoe Perches 2290d74c42fSJoe Perches return fold == 0; 2301f87e235SEric Dumazet #else 2310d74c42fSJoe Perches const u16 *a = (const u16 *)addr1; 2320d74c42fSJoe Perches const u16 *b = (const u16 *)addr2; 2330d74c42fSJoe Perches 2340d74c42fSJoe Perches return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2])) == 0; 2351f87e235SEric Dumazet #endif 2361f87e235SEric Dumazet } 2371f87e235SEric Dumazet 2381f87e235SEric Dumazet /** 239baf523c9SJoe Perches * ether_addr_equal_64bits - Compare two Ethernet addresses 240baf523c9SJoe Perches * @addr1: Pointer to an array of 8 bytes 241baf523c9SJoe Perches * @addr2: Pointer to an other array of 8 bytes 242baf523c9SJoe Perches * 243048b899cSstephen hemminger * Compare two Ethernet addresses, returns true if equal, false otherwise. 244baf523c9SJoe Perches * 245baf523c9SJoe Perches * The function doesn't need any conditional branches and possibly uses 246baf523c9SJoe Perches * word memory accesses on CPU allowing cheap unaligned memory reads. 247048b899cSstephen hemminger * arrays = { byte1, byte2, byte3, byte4, byte5, byte6, pad1, pad2 } 248baf523c9SJoe Perches * 249048b899cSstephen hemminger * Please note that alignment of addr1 & addr2 are only guaranteed to be 16 bits. 250baf523c9SJoe Perches */ 251baf523c9SJoe Perches 252baf523c9SJoe Perches static inline bool ether_addr_equal_64bits(const u8 addr1[6+2], 253baf523c9SJoe Perches const u8 addr2[6+2]) 254baf523c9SJoe Perches { 2550d74c42fSJoe Perches #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64 2560d74c42fSJoe Perches u64 fold = (*(const u64 *)addr1) ^ (*(const u64 *)addr2); 257e550ba1aSJoe Perches 2580d74c42fSJoe Perches #ifdef __BIG_ENDIAN 2590d74c42fSJoe Perches return (fold >> 16) == 0; 2600d74c42fSJoe Perches #else 2610d74c42fSJoe Perches return (fold << 16) == 0; 2620d74c42fSJoe Perches #endif 263e550ba1aSJoe Perches #else 264e550ba1aSJoe Perches return ether_addr_equal(addr1, addr2); 265e550ba1aSJoe Perches #endif 266baf523c9SJoe Perches } 267baf523c9SJoe Perches 268baf523c9SJoe Perches /** 269*73eaef87SJoe Perches * ether_addr_equal_unaligned - Compare two not u16 aligned Ethernet addresses 270*73eaef87SJoe Perches * @addr1: Pointer to a six-byte array containing the Ethernet address 271*73eaef87SJoe Perches * @addr2: Pointer other six-byte array containing the Ethernet address 272*73eaef87SJoe Perches * 273*73eaef87SJoe Perches * Compare two Ethernet addresses, returns true if equal 274*73eaef87SJoe Perches * 275*73eaef87SJoe Perches * Please note: Use only when any Ethernet address may not be u16 aligned. 276*73eaef87SJoe Perches */ 277*73eaef87SJoe Perches static inline bool ether_addr_equal_unaligned(const u8 *addr1, const u8 *addr2) 278*73eaef87SJoe Perches { 279*73eaef87SJoe Perches #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) 280*73eaef87SJoe Perches return ether_addr_equal(addr1, addr2); 281*73eaef87SJoe Perches #else 282*73eaef87SJoe Perches return memcmp(addr1, addr2, ETH_ALEN) == 0; 283*73eaef87SJoe Perches #endif 284*73eaef87SJoe Perches } 285*73eaef87SJoe Perches 286*73eaef87SJoe Perches /** 287f001fde5SJiri Pirko * is_etherdev_addr - Tell if given Ethernet address belongs to the device. 288f001fde5SJiri Pirko * @dev: Pointer to a device structure 289f001fde5SJiri Pirko * @addr: Pointer to a six-byte array containing the Ethernet address 290f001fde5SJiri Pirko * 291f001fde5SJiri Pirko * Compare passed address with all addresses of the device. Return true if the 292f001fde5SJiri Pirko * address if one of the device addresses. 293f001fde5SJiri Pirko * 294e550ba1aSJoe Perches * Note that this function calls ether_addr_equal_64bits() so take care of 295f001fde5SJiri Pirko * the right padding. 296f001fde5SJiri Pirko */ 297f001fde5SJiri Pirko static inline bool is_etherdev_addr(const struct net_device *dev, 298f001fde5SJiri Pirko const u8 addr[6 + 2]) 299f001fde5SJiri Pirko { 300f001fde5SJiri Pirko struct netdev_hw_addr *ha; 301e550ba1aSJoe Perches bool res = false; 302f001fde5SJiri Pirko 303f001fde5SJiri Pirko rcu_read_lock(); 304f001fde5SJiri Pirko for_each_dev_addr(dev, ha) { 305e550ba1aSJoe Perches res = ether_addr_equal_64bits(addr, ha->addr); 306e550ba1aSJoe Perches if (res) 307f001fde5SJiri Pirko break; 308f001fde5SJiri Pirko } 309f001fde5SJiri Pirko rcu_read_unlock(); 310e550ba1aSJoe Perches return res; 311f001fde5SJiri Pirko } 31279165121SMichael Ellerman #endif /* __KERNEL__ */ 3131da177e4SLinus Torvalds 314aa4b9f53SHerbert Xu /** 315aa4b9f53SHerbert Xu * compare_ether_header - Compare two Ethernet headers 316aa4b9f53SHerbert Xu * @a: Pointer to Ethernet header 317aa4b9f53SHerbert Xu * @b: Pointer to Ethernet header 318aa4b9f53SHerbert Xu * 319048b899cSstephen hemminger * Compare two Ethernet headers, returns 0 if equal. 320aa4b9f53SHerbert Xu * This assumes that the network header (i.e., IP header) is 4-byte 321aa4b9f53SHerbert Xu * aligned OR the platform can handle unaligned access. This is the 322aa4b9f53SHerbert Xu * case for all packets coming into netif_receive_skb or similar 323aa4b9f53SHerbert Xu * entry points. 324aa4b9f53SHerbert Xu */ 325aa4b9f53SHerbert Xu 32640d0802bSEric Dumazet static inline unsigned long compare_ether_header(const void *a, const void *b) 327aa4b9f53SHerbert Xu { 32840d0802bSEric Dumazet #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64 32940d0802bSEric Dumazet unsigned long fold; 33040d0802bSEric Dumazet 33140d0802bSEric Dumazet /* 33240d0802bSEric Dumazet * We want to compare 14 bytes: 33340d0802bSEric Dumazet * [a0 ... a13] ^ [b0 ... b13] 33440d0802bSEric Dumazet * Use two long XOR, ORed together, with an overlap of two bytes. 33540d0802bSEric Dumazet * [a0 a1 a2 a3 a4 a5 a6 a7 ] ^ [b0 b1 b2 b3 b4 b5 b6 b7 ] | 33640d0802bSEric Dumazet * [a6 a7 a8 a9 a10 a11 a12 a13] ^ [b6 b7 b8 b9 b10 b11 b12 b13] 33740d0802bSEric Dumazet * This means the [a6 a7] ^ [b6 b7] part is done two times. 33840d0802bSEric Dumazet */ 33940d0802bSEric Dumazet fold = *(unsigned long *)a ^ *(unsigned long *)b; 34040d0802bSEric Dumazet fold |= *(unsigned long *)(a + 6) ^ *(unsigned long *)(b + 6); 34140d0802bSEric Dumazet return fold; 34240d0802bSEric Dumazet #else 343aa4b9f53SHerbert Xu u32 *a32 = (u32 *)((u8 *)a + 2); 344aa4b9f53SHerbert Xu u32 *b32 = (u32 *)((u8 *)b + 2); 345aa4b9f53SHerbert Xu 346aa4b9f53SHerbert Xu return (*(u16 *)a ^ *(u16 *)b) | (a32[0] ^ b32[0]) | 347aa4b9f53SHerbert Xu (a32[1] ^ b32[1]) | (a32[2] ^ b32[2]); 34840d0802bSEric Dumazet #endif 349aa4b9f53SHerbert Xu } 350aa4b9f53SHerbert Xu 3511da177e4SLinus Torvalds #endif /* _LINUX_ETHERDEVICE_H */ 352