Commit 689827f0 authored by Alexey Kuznetsov's avatar Alexey Kuznetsov Committed by David S. Miller

[NET]: hard_header reservation.

1. Fix bad reservation in xfrm_state_check_space()
2. Macroize formula for reservation, use the macro over all the places
   in IP.
parent 7f2c2754
...@@ -90,6 +90,11 @@ struct vlan_group; ...@@ -90,6 +90,11 @@ struct vlan_group;
#define MAX_HEADER (LL_MAX_HEADER + 48) #define MAX_HEADER (LL_MAX_HEADER + 48)
#endif #endif
/* Reserve 16byte aligned hard_header_len, but at least 16.
* Alternative is: dev->hard_header_len ? (dev->hard_header_len + 15)&~15 : 0
*/
#define LL_RESERVED_SPACE(dev) (((dev)->hard_header_len&~15) + 16)
/* /*
* Network device statistics. Akin to the 2.0 ether stats but * Network device statistics. Akin to the 2.0 ether stats but
* with byte counters. * with byte counters.
......
...@@ -510,11 +510,11 @@ void arp_send(int type, int ptype, u32 dest_ip, ...@@ -510,11 +510,11 @@ void arp_send(int type, int ptype, u32 dest_ip,
*/ */
skb = alloc_skb(sizeof(struct arphdr)+ 2*(dev->addr_len+4) skb = alloc_skb(sizeof(struct arphdr)+ 2*(dev->addr_len+4)
+ dev->hard_header_len + 15, GFP_ATOMIC); + LL_RESERVED_SPACE(dev), GFP_ATOMIC);
if (skb == NULL) if (skb == NULL)
return; return;
skb_reserve(skb, (dev->hard_header_len+15)&~15); skb_reserve(skb, LL_RESERVED_SPACE(dev));
skb->nh.raw = skb->data; skb->nh.raw = skb->data;
arp = (struct arphdr *) skb_put(skb,sizeof(struct arphdr) + 2*(dev->addr_len+4)); arp = (struct arphdr *) skb_put(skb,sizeof(struct arphdr) + 2*(dev->addr_len+4));
skb->dev = dev; skb->dev = dev;
......
...@@ -211,7 +211,7 @@ static int igmp_send_report(struct net_device *dev, u32 group, int type) ...@@ -211,7 +211,7 @@ static int igmp_send_report(struct net_device *dev, u32 group, int type)
return -1; return -1;
} }
skb=alloc_skb(IGMP_SIZE+dev->hard_header_len+15, GFP_ATOMIC); skb=alloc_skb(IGMP_SIZE+LL_RESERVED_SPACE(dev), GFP_ATOMIC);
if (skb == NULL) { if (skb == NULL) {
ip_rt_put(rt); ip_rt_put(rt);
return -1; return -1;
...@@ -219,7 +219,7 @@ static int igmp_send_report(struct net_device *dev, u32 group, int type) ...@@ -219,7 +219,7 @@ static int igmp_send_report(struct net_device *dev, u32 group, int type)
skb->dst = &rt->u.dst; skb->dst = &rt->u.dst;
skb_reserve(skb, (dev->hard_header_len+15)&~15); skb_reserve(skb, LL_RESERVED_SPACE(dev));
skb->nh.iph = iph = (struct iphdr *)skb_put(skb, sizeof(struct iphdr)+4); skb->nh.iph = iph = (struct iphdr *)skb_put(skb, sizeof(struct iphdr)+4);
......
...@@ -92,7 +92,7 @@ int ip_forward(struct sk_buff *skb) ...@@ -92,7 +92,7 @@ int ip_forward(struct sk_buff *skb)
goto sr_failed; goto sr_failed;
/* We are about to mangle packet. Copy it! */ /* We are about to mangle packet. Copy it! */
if (skb_cow(skb, rt->u.dst.dev->hard_header_len+rt->u.dst.header_len)) if (skb_cow(skb, LL_RESERVED_SPACE(rt->u.dst.dev)+rt->u.dst.header_len))
goto drop; goto drop;
iph = skb->nh.iph; iph = skb->nh.iph;
......
...@@ -824,7 +824,7 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -824,7 +824,7 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
skb->h.raw = skb->nh.raw; skb->h.raw = skb->nh.raw;
max_headroom = ((tdev->hard_header_len+15)&~15)+ gre_hlen; max_headroom = LL_RESERVED_SPACE(tdev) + gre_hlen;
if (skb_headroom(skb) < max_headroom || skb_cloned(skb) || skb_shared(skb)) { if (skb_headroom(skb) < max_headroom || skb_cloned(skb) || skb_shared(skb)) {
struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom); struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom);
......
...@@ -162,13 +162,13 @@ static inline int ip_finish_output2(struct sk_buff *skb) ...@@ -162,13 +162,13 @@ static inline int ip_finish_output2(struct sk_buff *skb)
struct dst_entry *dst = skb->dst; struct dst_entry *dst = skb->dst;
struct hh_cache *hh = dst->hh; struct hh_cache *hh = dst->hh;
struct net_device *dev = dst->dev; struct net_device *dev = dst->dev;
int hh_len = LL_RESERVED_SPACE(dev);
/* Be paranoid, rather than too clever. */ /* Be paranoid, rather than too clever. */
if (unlikely(skb_headroom(skb) < dev->hard_header_len if (unlikely(skb_headroom(skb) < hh_len && dev->hard_header)) {
&& dev->hard_header)) {
struct sk_buff *skb2; struct sk_buff *skb2;
skb2 = skb_realloc_headroom(skb, (dev->hard_header_len&~15) + 16); skb2 = skb_realloc_headroom(skb, LL_RESERVED_SPACE(dev));
if (skb2 == NULL) { if (skb2 == NULL) {
kfree_skb(skb); kfree_skb(skb);
return -ENOMEM; return -ENOMEM;
...@@ -572,7 +572,7 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*)) ...@@ -572,7 +572,7 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*))
* Allocate buffer. * Allocate buffer.
*/ */
if ((skb2 = alloc_skb(len+hlen+rt->u.dst.dev->hard_header_len+16,GFP_ATOMIC)) == NULL) { if ((skb2 = alloc_skb(len+hlen+LL_RESERVED_SPACE(rt->u.dst.dev), GFP_ATOMIC)) == NULL) {
NETDEBUG(printk(KERN_INFO "IP: frag: no memory for new fragment!\n")); NETDEBUG(printk(KERN_INFO "IP: frag: no memory for new fragment!\n"));
err = -ENOMEM; err = -ENOMEM;
goto fail; goto fail;
...@@ -583,7 +583,7 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*)) ...@@ -583,7 +583,7 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*))
*/ */
ip_copy_metadata(skb2, skb); ip_copy_metadata(skb2, skb);
skb_reserve(skb2, (rt->u.dst.dev->hard_header_len&~15)+16); skb_reserve(skb2, LL_RESERVED_SPACE(rt->u.dst.dev));
skb_put(skb2, len + hlen); skb_put(skb2, len + hlen);
skb2->nh.raw = skb2->data; skb2->nh.raw = skb2->data;
skb2->h.raw = skb2->data + hlen; skb2->h.raw = skb2->data + hlen;
...@@ -771,7 +771,7 @@ int ip_append_data(struct sock *sk, ...@@ -771,7 +771,7 @@ int ip_append_data(struct sock *sk,
exthdrlen = 0; exthdrlen = 0;
mtu = inet->cork.fragsize; mtu = inet->cork.fragsize;
} }
hh_len = (rt->u.dst.dev->hard_header_len&~15) + 16; hh_len = LL_RESERVED_SPACE(rt->u.dst.dev);
fragheaderlen = sizeof(struct iphdr) + (opt ? opt->optlen : 0); fragheaderlen = sizeof(struct iphdr) + (opt ? opt->optlen : 0);
maxfraglen = ((mtu-fragheaderlen) & ~7) + fragheaderlen; maxfraglen = ((mtu-fragheaderlen) & ~7) + fragheaderlen;
...@@ -967,7 +967,7 @@ ssize_t ip_append_page(struct sock *sk, struct page *page, ...@@ -967,7 +967,7 @@ ssize_t ip_append_page(struct sock *sk, struct page *page,
if (!(rt->u.dst.dev->features&NETIF_F_SG)) if (!(rt->u.dst.dev->features&NETIF_F_SG))
return -EOPNOTSUPP; return -EOPNOTSUPP;
hh_len = (rt->u.dst.dev->hard_header_len&~15)+16; hh_len = LL_RESERVED_SPACE(rt->u.dst.dev);
mtu = inet->cork.fragsize; mtu = inet->cork.fragsize;
fragheaderlen = sizeof(struct iphdr) + (opt ? opt->optlen : 0); fragheaderlen = sizeof(struct iphdr) + (opt ? opt->optlen : 0);
......
...@@ -656,7 +656,7 @@ static void __init ic_bootp_send_if(struct ic_device *d, unsigned long jiffies_d ...@@ -656,7 +656,7 @@ static void __init ic_bootp_send_if(struct ic_device *d, unsigned long jiffies_d
struct net_device *dev = d->dev; struct net_device *dev = d->dev;
struct sk_buff *skb; struct sk_buff *skb;
struct bootp_pkt *b; struct bootp_pkt *b;
int hh_len = (dev->hard_header_len + 15) & ~15; int hh_len = LL_RESERVED_SPACE(dev);
struct iphdr *h; struct iphdr *h;
/* Allocate packet */ /* Allocate packet */
......
...@@ -616,7 +616,7 @@ static int ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -616,7 +616,7 @@ static int ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
/* /*
* Okay, now see if we can stuff it in the buffer as-is. * Okay, now see if we can stuff it in the buffer as-is.
*/ */
max_headroom = (((tdev->hard_header_len+15)&~15)+sizeof(struct iphdr)); max_headroom = (LL_RESERVED_SPACE(tdev)+sizeof(struct iphdr));
if (skb_headroom(skb) < max_headroom || skb_cloned(skb) || skb_shared(skb)) { if (skb_headroom(skb) < max_headroom || skb_cloned(skb) || skb_shared(skb)) {
struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom); struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom);
......
...@@ -1178,7 +1178,7 @@ static void ipmr_queue_xmit(struct sk_buff *skb, struct mfc_cache *c, ...@@ -1178,7 +1178,7 @@ static void ipmr_queue_xmit(struct sk_buff *skb, struct mfc_cache *c,
return; return;
} }
encap += dev->hard_header_len; encap += LL_RESERVED_SPACE(dev);
if (skb_headroom(skb) < encap || skb_cloned(skb) || !last) if (skb_headroom(skb) < encap || skb_cloned(skb) || !last)
skb2 = skb_realloc_headroom(skb, (encap + 15)&~15); skb2 = skb_realloc_headroom(skb, (encap + 15)&~15);
......
...@@ -280,7 +280,7 @@ static int raw_send_hdrinc(struct sock *sk, void *from, int length, ...@@ -280,7 +280,7 @@ static int raw_send_hdrinc(struct sock *sk, void *from, int length,
if (flags&MSG_PROBE) if (flags&MSG_PROBE)
goto out; goto out;
hh_len = (rt->u.dst.dev->hard_header_len&~15) + 16; hh_len = LL_RESERVED_SPACE(rt->u.dst.dev);
skb = sock_alloc_send_skb(sk, length+hh_len+15, skb = sock_alloc_send_skb(sk, length+hh_len+15,
flags&MSG_DONTWAIT, &err); flags&MSG_DONTWAIT, &err);
......
...@@ -501,7 +501,7 @@ int xfrm_state_check_expire(struct xfrm_state *x) ...@@ -501,7 +501,7 @@ int xfrm_state_check_expire(struct xfrm_state *x)
int xfrm_state_check_space(struct xfrm_state *x, struct sk_buff *skb) int xfrm_state_check_space(struct xfrm_state *x, struct sk_buff *skb)
{ {
int nhead = x->props.header_len + skb->dst->dev->hard_header_len int nhead = x->props.header_len + LL_RESERVED_SPACE(skb->dst->dev)
- skb_headroom(skb); - skb_headroom(skb);
if (nhead > 0) if (nhead > 0)
......
...@@ -552,7 +552,7 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -552,7 +552,7 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
/* /*
* Okay, now see if we can stuff it in the buffer as-is. * Okay, now see if we can stuff it in the buffer as-is.
*/ */
max_headroom = (((tdev->hard_header_len+15)&~15)+sizeof(struct iphdr)); max_headroom = LL_RESERVED_SPACE(tdev)+sizeof(struct iphdr);
if (skb_headroom(skb) < max_headroom || skb_cloned(skb) || skb_shared(skb)) { if (skb_headroom(skb) < max_headroom || skb_cloned(skb) || skb_shared(skb)) {
struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom); struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment