struct list_head list;
unsigned char addr[MAX_ADDR_LEN];
unsigned char type;
-#define NETDEV_HW_ADDR_T_LAN 1
-#define NETDEV_HW_ADDR_T_SAN 2
-#define NETDEV_HW_ADDR_T_SLAVE 3
+#define NETDEV_HW_ADDR_T_LAN 1
+#define NETDEV_HW_ADDR_T_SAN 2
+#define NETDEV_HW_ADDR_T_SLAVE 3
+#define NETDEV_HW_ADDR_T_UNICAST 4
+ int refcount;
+ bool synced;
struct rcu_head rcu_head;
};
+struct netdev_hw_addr_list {
+ struct list_head list;
+ int count;
+};
+
struct hh_cache
{
struct hh_cache *hh_next; /* Next entry */
unsigned char addr_len; /* hardware address length */
unsigned short dev_id; /* for shared network cards */
- spinlock_t addr_list_lock;
- struct dev_addr_list *uc_list; /* Secondary unicast mac addresses */
- int uc_count; /* Number of installed ucasts */
+ struct netdev_hw_addr_list uc; /* Secondary unicast
+ mac addresses */
int uc_promisc;
+ spinlock_t addr_list_lock;
struct dev_addr_list *mc_list; /* Multicast mac addresses */
int mc_count; /* Number of installed mcasts */
unsigned int promiscuity;
because most packets are
unicast) */
- struct list_head dev_addr_list; /* list of device hw addresses */
+ struct netdev_hw_addr_list dev_addrs; /* list of device
+ hw addresses */
unsigned char broadcast[MAX_ADDR_LEN]; /* hw bcast add */
#define to_net_dev(d) container_of(d, struct net_device, dev)
#define NETDEV_ALIGN 32
-#define NETDEV_ALIGN_CONST (NETDEV_ALIGN - 1)
static inline
struct netdev_queue *netdev_get_tx_queue(const struct net_device *dev,
*/
static inline void *netdev_priv(const struct net_device *dev)
{
- return (char *)dev + ((sizeof(struct net_device)
- + NETDEV_ALIGN_CONST)
- & ~NETDEV_ALIGN_CONST);
+ return (char *)dev + ALIGN(sizeof(struct net_device), NETDEV_ALIGN);
}
/* Set the sysfs physical device reference for the network logical device
/* Virtual address of skb_shinfo(skb)->frags[0].page + offset. */
void *frag0;
+ /* Length of frag0. */
+ unsigned int frag0_len;
+
/* This indicates where we are processing relative to skb->data. */
int data_offset;
NAPI_GRO_CB(skb)->data_offset += len;
}
-static inline void *skb_gro_header(struct sk_buff *skb, unsigned int hlen)
+static inline void *skb_gro_header_fast(struct sk_buff *skb,
+ unsigned int offset)
{
- unsigned int offset = skb_gro_offset(skb);
+ return NAPI_GRO_CB(skb)->frag0 + offset;
+}
- hlen += offset;
- if (!NAPI_GRO_CB(skb)->frag0 ||
- unlikely(skb_shinfo(skb)->frags[0].size + skb_headlen(skb) < hlen))
- return pskb_may_pull(skb, hlen) ? skb->data + offset : NULL;
+static inline int skb_gro_header_hard(struct sk_buff *skb, unsigned int hlen)
+{
+ return NAPI_GRO_CB(skb)->frag0_len < hlen;
+}
- return NAPI_GRO_CB(skb)->frag0 + offset;
+static inline void *skb_gro_header_slow(struct sk_buff *skb, unsigned int hlen,
+ unsigned int offset)
+{
+ NAPI_GRO_CB(skb)->frag0 = NULL;
+ NAPI_GRO_CB(skb)->frag0_len = 0;
+ return pskb_may_pull(skb, hlen) ? skb->data + offset : NULL;
}
static inline void *skb_gro_mac_header(struct sk_buff *skb)
{
- return skb_headlen(skb) ? skb_mac_header(skb) :
- NAPI_GRO_CB(skb)->frag0;
+ return NAPI_GRO_CB(skb)->frag0 ?: skb_mac_header(skb);
}
static inline void *skb_gro_network_header(struct sk_buff *skb)
{
- return skb_headlen(skb) ? skb_network_header(skb) :
- NAPI_GRO_CB(skb)->frag0 + skb_network_offset(skb);
+ return (NAPI_GRO_CB(skb)->frag0 ?: skb->data) +
+ skb_network_offset(skb);
}
static inline int dev_hard_header(struct sk_buff *skb, struct net_device *dev,
}
/*
- * dev_addr_list walker. Should be used only for read access. Call with
+ * dev_addrs walker. Should be used only for read access. Call with
* rcu_read_lock held.
*/
#define for_each_dev_addr(dev, ha) \
- list_for_each_entry_rcu(ha, &dev->dev_addr_list, list)
+ list_for_each_entry_rcu(ha, &dev->dev_addrs.list, list)
/* These functions live elsewhere (drivers/net/net_init.c, but related) */
/* Functions used for secondary unicast and multicast support */
extern void dev_set_rx_mode(struct net_device *dev);
extern void __dev_set_rx_mode(struct net_device *dev);
-extern int dev_unicast_delete(struct net_device *dev, void *addr, int alen);
-extern int dev_unicast_add(struct net_device *dev, void *addr, int alen);
+extern int dev_unicast_delete(struct net_device *dev, void *addr);
+extern int dev_unicast_add(struct net_device *dev, void *addr);
extern int dev_unicast_sync(struct net_device *to, struct net_device *from);
extern void dev_unicast_unsync(struct net_device *to, struct net_device *from);
extern int dev_mc_delete(struct net_device *dev, void *addr, int alen, int all);
static inline int skb_gso_ok(struct sk_buff *skb, int features)
{
- return net_gso_ok(features, skb_shinfo(skb)->gso_type);
+ return net_gso_ok(features, skb_shinfo(skb)->gso_type) &&
+ (!skb_has_frags(skb) || (features & NETIF_F_FRAGLIST));
}
static inline int netif_needs_gso(struct net_device *dev, struct sk_buff *skb)
{
return skb_is_gso(skb) &&
(!skb_gso_ok(skb, dev->features) ||
- (skb_shinfo(skb)->frag_list &&
- !(dev->features & NETIF_F_FRAGLIST)) ||
unlikely(skb->ip_summed != CHECKSUM_PARTIAL));
}
dev->gso_max_size = size;
}
+static inline void skb_bond_set_mac_by_master(struct sk_buff *skb,
+ struct net_device *master)
+{
+ if (skb->pkt_type == PACKET_HOST) {
+ u16 *dest = (u16 *) eth_hdr(skb)->h_dest;
+
+ memcpy(dest, master->dev_addr, ETH_ALEN);
+ }
+}
+
/* On bonding slaves other than the currently active slave, suppress
* duplicates except for 802.3ad ETH_P_SLOW, alb non-mcast/bcast, and
* ARP on active-backup slaves with arp_validate enabled.
if (master->priv_flags & IFF_MASTER_ARPMON)
dev->last_rx = jiffies;
+ if ((master->priv_flags & IFF_MASTER_ALB) && master->br_port) {
+ /* Do address unmangle. The local destination address
+ * will be always the one master has. Provides the right
+ * functionality in a bridge.
+ */
+ skb_bond_set_mac_by_master(skb, master);
+ }
+
if (dev->priv_flags & IFF_SLAVE_INACTIVE) {
if ((dev->priv_flags & IFF_SLAVE_NEEDARP) &&
skb->protocol == __cpu_to_be16(ETH_P_ARP))
}
#endif /* __KERNEL__ */
-#endif /* _LINUX_DEV_H */
+#endif /* _LINUX_NETDEVICE_H */