blob: 34dbf6517f64ab3f3081f590635e05ccc8e82bd8 [file] [log] [blame]
#ifndef _BACKPORT_LINUX_ETHERDEVICE_H
#define _BACKPORT_LINUX_ETHERDEVICE_H
#include_next <linux/etherdevice.h>
#include <linux/version.h>
/*
* newer kernels include this already and some
* users rely on getting this indirectly
*/
#include <asm/unaligned.h>
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0)
#define eth_hw_addr_random LINUX_BACKPORT(eth_hw_addr_random)
static inline void eth_hw_addr_random(struct net_device *dev)
{
dev->addr_assign_type |= NET_ADDR_RANDOM;
random_ether_addr(dev->dev_addr);
}
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0)
#include <linux/random.h>
/**
* eth_broadcast_addr - Assign broadcast address
* @addr: Pointer to a six-byte array containing the Ethernet address
*
* Assign the broadcast address to the given address array.
*/
#define eth_broadcast_addr LINUX_BACKPORT(eth_broadcast_addr)
static inline void eth_broadcast_addr(u8 *addr)
{
memset(addr, 0xff, ETH_ALEN);
}
/**
* eth_random_addr - Generate software assigned random Ethernet address
* @addr: Pointer to a six-byte array containing the Ethernet address
*
* Generate a random Ethernet address (MAC) that is not multicast
* and has the local assigned bit set.
*/
#define eth_random_addr LINUX_BACKPORT(eth_random_addr)
static inline void eth_random_addr(u8 *addr)
{
get_random_bytes(addr, ETH_ALEN);
addr[0] &= 0xfe; /* clear multicast bit */
addr[0] |= 0x02; /* set local assignment bit (IEEE802) */
}
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0) */
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0)
/* This backports:
*
* commit 6d57e9078e880a3dd232d579f42ac437a8f1ef7b
* Author: Duan Jiong <djduanjiong@gmail.com>
* Date: Sat Sep 8 16:32:28 2012 +0000
*
* etherdevice: introduce help function eth_zero_addr()
*/
#define eth_zero_addr LINUX_BACKPORT(eth_zero_addr)
static inline void eth_zero_addr(u8 *addr)
{
memset(addr, 0x00, ETH_ALEN);
}
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0)
#define ether_addr_equal LINUX_BACKPORT(ether_addr_equal)
static inline bool ether_addr_equal(const u8 *addr1, const u8 *addr2)
{
return !compare_ether_addr(addr1, addr2);
}
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,9,0)
#define eth_prepare_mac_addr_change LINUX_BACKPORT(eth_prepare_mac_addr_change)
extern int eth_prepare_mac_addr_change(struct net_device *dev, void *p);
#define eth_commit_mac_addr_change LINUX_BACKPORT(eth_commit_mac_addr_change)
extern void eth_commit_mac_addr_change(struct net_device *dev, void *p);
#endif /* < 3.9 */
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,12,0)
/**
* eth_hw_addr_inherit - Copy dev_addr from another net_device
* @dst: pointer to net_device to copy dev_addr to
* @src: pointer to net_device to copy dev_addr from
*
* Copy the Ethernet address from one net_device to another along with
* the address attributes (addr_assign_type).
*/
static inline void eth_hw_addr_inherit(struct net_device *dst,
struct net_device *src)
{
dst->addr_assign_type = src->addr_assign_type;
memcpy(dst->dev_addr, src->dev_addr, ETH_ALEN);
}
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3,13,0) */
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0)
/**
* ether_addr_equal_64bits - Compare two Ethernet addresses
* @addr1: Pointer to an array of 8 bytes
* @addr2: Pointer to an other array of 8 bytes
*
* Compare two Ethernet addresses, returns true if equal, false otherwise.
*
* The function doesn't need any conditional branches and possibly uses
* word memory accesses on CPU allowing cheap unaligned memory reads.
* arrays = { byte1, byte2, byte3, byte4, byte5, byte6, pad1, pad2 }
*
* Please note that alignment of addr1 & addr2 are only guaranteed to be 16 bits.
*/
#define ether_addr_equal_64bits LINUX_BACKPORT(ether_addr_equal_64bits)
static inline bool ether_addr_equal_64bits(const u8 addr1[6+2],
const u8 addr2[6+2])
{
#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64
u64 fold = (*(const u64 *)addr1) ^ (*(const u64 *)addr2);
#ifdef __BIG_ENDIAN
return (fold >> 16) == 0;
#else
return (fold << 16) == 0;
#endif
#else
return ether_addr_equal(addr1, addr2);
#endif
}
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) */
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0)
/**
* ether_addr_equal_unaligned - Compare two not u16 aligned Ethernet addresses
* @addr1: Pointer to a six-byte array containing the Ethernet address
* @addr2: Pointer other six-byte array containing the Ethernet address
*
* Compare two Ethernet addresses, returns true if equal
*
* Please note: Use only when any Ethernet address may not be u16 aligned.
*/
#define ether_addr_equal_unaligned LINUX_BACKPORT(ether_addr_equal_unaligned)
static inline bool ether_addr_equal_unaligned(const u8 *addr1, const u8 *addr2)
{
#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
return ether_addr_equal(addr1, addr2);
#else
return memcmp(addr1, addr2, ETH_ALEN) == 0;
#endif
}
/**
* ether_addr_copy - Copy an Ethernet address
* @dst: Pointer to a six-byte array Ethernet address destination
* @src: Pointer to a six-byte array Ethernet address source
*
* Please note: dst & src must both be aligned to u16.
*/
#define ether_addr_copy LINUX_BACKPORT(ether_addr_copy)
static inline void ether_addr_copy(u8 *dst, const u8 *src)
{
#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
*(u32 *)dst = *(const u32 *)src;
*(u16 *)(dst + 4) = *(const u16 *)(src + 4);
#else
u16 *a = (u16 *)dst;
const u16 *b = (const u16 *)src;
a[0] = b[0];
a[1] = b[1];
a[2] = b[2];
#endif
}
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0) */
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,18,0)
#define eth_get_headlen LINUX_BACKPORT(eth_get_headlen)
int eth_get_headlen(unsigned char *data, unsigned int max_len);
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3,18,0) */
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0)
#define eth_skb_pad LINUX_BACKPORT(eth_skb_pad)
/**
* eth_skb_pad - Pad buffer to mininum number of octets for Ethernet frame
* @skb: Buffer to pad
*
* An Ethernet frame should have a minimum size of 60 bytes. This function
* takes short frames and pads them with zeros up to the 60 byte limit.
*/
static inline int eth_skb_pad(struct sk_buff *skb)
{
return skb_put_padto(skb, ETH_ZLEN);
}
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0) */
#endif /* _BACKPORT_LINUX_ETHERDEVICE_H */