1 --- a/include/linux/netdevice.h
2 +++ b/include/linux/netdevice.h
3 @@ -1216,6 +1216,7 @@ enum netdev_priv_flags {
4 IFF_LIVE_ADDR_CHANGE = 1<<20,
6 IFF_XMIT_DST_RELEASE_PERM = 1<<22,
7 + IFF_NO_IP_ALIGN = 1<<23,
10 #define IFF_802_1Q_VLAN IFF_802_1Q_VLAN
11 --- a/include/linux/skbuff.h
12 +++ b/include/linux/skbuff.h
13 @@ -2044,6 +2044,10 @@ static inline int pskb_trim(struct sk_bu
14 return (len < skb->len) ? __pskb_trim(skb, len) : 0;
17 +extern struct sk_buff *__netdev_alloc_skb_ip_align(struct net_device *dev,
18 + unsigned int length, gfp_t gfp);
22 * pskb_trim_unique - remove end from a paged unique (not cloned) buffer
23 * @skb: buffer to alter
24 @@ -2170,16 +2174,6 @@ static inline struct sk_buff *dev_alloc_
28 -static inline struct sk_buff *__netdev_alloc_skb_ip_align(struct net_device *dev,
29 - unsigned int length, gfp_t gfp)
31 - struct sk_buff *skb = __netdev_alloc_skb(dev, length + NET_IP_ALIGN, gfp);
33 - if (NET_IP_ALIGN && skb)
34 - skb_reserve(skb, NET_IP_ALIGN);
38 static inline struct sk_buff *netdev_alloc_skb_ip_align(struct net_device *dev,
43 @@ -25,6 +25,12 @@ menuconfig NET
47 +config ETHERNET_PACKET_MANGLE
50 + This option can be selected by phy drivers that need to mangle
51 + packets going in or out of an ethernet device.
53 config WANT_COMPAT_NETLINK_MESSAGES
58 @@ -2607,10 +2607,20 @@ static int xmit_one(struct sk_buff *skb,
59 if (!list_empty(&ptype_all))
60 dev_queue_xmit_nit(skb, dev);
63 - trace_net_dev_start_xmit(skb, dev);
64 - rc = netdev_start_xmit(skb, dev, txq, more);
65 - trace_net_dev_xmit(skb, rc, dev, len);
66 +#ifdef CONFIG_ETHERNET_PACKET_MANGLE
67 + if (!dev->eth_mangle_tx ||
68 + (skb = dev->eth_mangle_tx(dev, skb)) != NULL)
74 + trace_net_dev_start_xmit(skb, dev);
75 + rc = netdev_start_xmit(skb, dev, txq, more);
76 + trace_net_dev_xmit(skb, rc, dev, len);
83 --- a/net/core/skbuff.c
84 +++ b/net/core/skbuff.c
86 #include <linux/errqueue.h>
87 #include <linux/prefetch.h>
88 #include <linux/if_vlan.h>
89 +#include <linux/if.h>
91 #include <net/protocol.h>
93 @@ -451,6 +452,22 @@ struct sk_buff *__netdev_alloc_skb(struc
95 EXPORT_SYMBOL(__netdev_alloc_skb);
97 +struct sk_buff *__netdev_alloc_skb_ip_align(struct net_device *dev,
98 + unsigned int length, gfp_t gfp)
100 + struct sk_buff *skb = __netdev_alloc_skb(dev, length + NET_IP_ALIGN, gfp);
102 +#ifdef CONFIG_ETHERNET_PACKET_MANGLE
103 + if (dev && (dev->priv_flags & IFF_NO_IP_ALIGN))
107 + if (NET_IP_ALIGN && skb)
108 + skb_reserve(skb, NET_IP_ALIGN);
111 +EXPORT_SYMBOL(__netdev_alloc_skb_ip_align);
113 void skb_add_rx_frag(struct sk_buff *skb, int i, struct page *page, int off,
114 int size, unsigned int truesize)
116 --- a/net/ethernet/eth.c
117 +++ b/net/ethernet/eth.c
118 @@ -188,6 +188,12 @@ __be16 eth_type_trans(struct sk_buff *sk
119 const struct ethhdr *eth;
123 +#ifdef CONFIG_ETHERNET_PACKET_MANGLE
124 + if (dev->eth_mangle_rx)
125 + dev->eth_mangle_rx(dev, skb);
128 skb_reset_mac_header(skb);
129 skb_pull_inline(skb, ETH_HLEN);