Commit f5184d26 authored by Johannes Berg's avatar Johannes Berg Committed by David S. Miller

net: Allow netdevices to specify needed head/tailroom

This patch adds needed_headroom/needed_tailroom members to struct
net_device and updates many places that allocate sbks to use them. Not
all of them can be converted though, and I'm sure I missed some (I
mostly grepped for LL_RESERVED_SPACE)
Signed-off-by: default avatarJohannes Berg <johannes@sipsolutions.net>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 8388e3da
...@@ -246,11 +246,16 @@ struct hh_cache ...@@ -246,11 +246,16 @@ struct hh_cache
* *
* We could use other alignment values, but we must maintain the * We could use other alignment values, but we must maintain the
* relationship HH alignment <= LL alignment. * relationship HH alignment <= LL alignment.
*
* LL_ALLOCATED_SPACE also takes into account the tailroom the device
* may need.
*/ */
#define LL_RESERVED_SPACE(dev) \ #define LL_RESERVED_SPACE(dev) \
(((dev)->hard_header_len&~(HH_DATA_MOD - 1)) + HH_DATA_MOD) ((((dev)->hard_header_len+(dev)->needed_headroom)&~(HH_DATA_MOD - 1)) + HH_DATA_MOD)
#define LL_RESERVED_SPACE_EXTRA(dev,extra) \ #define LL_RESERVED_SPACE_EXTRA(dev,extra) \
((((dev)->hard_header_len+extra)&~(HH_DATA_MOD - 1)) + HH_DATA_MOD) ((((dev)->hard_header_len+(dev)->needed_headroom+(extra))&~(HH_DATA_MOD - 1)) + HH_DATA_MOD)
#define LL_ALLOCATED_SPACE(dev) \
((((dev)->hard_header_len+(dev)->needed_headroom+(dev)->needed_tailroom)&~(HH_DATA_MOD - 1)) + HH_DATA_MOD)
struct header_ops { struct header_ops {
int (*create) (struct sk_buff *skb, struct net_device *dev, int (*create) (struct sk_buff *skb, struct net_device *dev,
...@@ -569,6 +574,13 @@ struct net_device ...@@ -569,6 +574,13 @@ struct net_device
unsigned short type; /* interface hardware type */ unsigned short type; /* interface hardware type */
unsigned short hard_header_len; /* hardware hdr length */ unsigned short hard_header_len; /* hardware hdr length */
/* extra head- and tailroom the hardware may need, but not in all cases
* can this be guaranteed, especially tailroom. Some cases also use
* LL_MAX_HEADER instead to allocate the skb.
*/
unsigned short needed_headroom;
unsigned short needed_tailroom;
struct net_device *master; /* Pointer to master device of a group, struct net_device *master; /* Pointer to master device of a group,
* which this device is member of. * which this device is member of.
*/ */
......
...@@ -419,7 +419,7 @@ static void arp_reply(struct sk_buff *skb) ...@@ -419,7 +419,7 @@ static void arp_reply(struct sk_buff *skb)
return; return;
size = arp_hdr_len(skb->dev); size = arp_hdr_len(skb->dev);
send_skb = find_skb(np, size + LL_RESERVED_SPACE(np->dev), send_skb = find_skb(np, size + LL_ALLOCATED_SPACE(np->dev),
LL_RESERVED_SPACE(np->dev)); LL_RESERVED_SPACE(np->dev));
if (!send_skb) if (!send_skb)
......
...@@ -340,7 +340,7 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock, ...@@ -340,7 +340,7 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
dev_hold(dev); dev_hold(dev);
skb = sock_alloc_send_skb(sk, len+LL_RESERVED_SPACE(dev), skb = sock_alloc_send_skb(sk, len+LL_ALLOCATED_SPACE(dev),
msg->msg_flags & MSG_DONTWAIT, &err); msg->msg_flags & MSG_DONTWAIT, &err);
if (skb==NULL) if (skb==NULL)
goto out_unlock; goto out_unlock;
......
...@@ -570,7 +570,7 @@ struct sk_buff *arp_create(int type, int ptype, __be32 dest_ip, ...@@ -570,7 +570,7 @@ struct sk_buff *arp_create(int type, int ptype, __be32 dest_ip,
* Allocate a buffer * Allocate a buffer
*/ */
skb = alloc_skb(arp_hdr_len(dev) + LL_RESERVED_SPACE(dev), GFP_ATOMIC); skb = alloc_skb(arp_hdr_len(dev) + LL_ALLOCATED_SPACE(dev), GFP_ATOMIC);
if (skb == NULL) if (skb == NULL)
return NULL; return NULL;
......
...@@ -292,7 +292,7 @@ static struct sk_buff *igmpv3_newpack(struct net_device *dev, int size) ...@@ -292,7 +292,7 @@ static struct sk_buff *igmpv3_newpack(struct net_device *dev, int size)
struct iphdr *pip; struct iphdr *pip;
struct igmpv3_report *pig; struct igmpv3_report *pig;
skb = alloc_skb(size + LL_RESERVED_SPACE(dev), GFP_ATOMIC); skb = alloc_skb(size + LL_ALLOCATED_SPACE(dev), GFP_ATOMIC);
if (skb == NULL) if (skb == NULL)
return NULL; return NULL;
...@@ -653,7 +653,7 @@ static int igmp_send_report(struct in_device *in_dev, struct ip_mc_list *pmc, ...@@ -653,7 +653,7 @@ static int igmp_send_report(struct in_device *in_dev, struct ip_mc_list *pmc,
return -1; return -1;
} }
skb=alloc_skb(IGMP_SIZE+LL_RESERVED_SPACE(dev), GFP_ATOMIC); skb=alloc_skb(IGMP_SIZE+LL_ALLOCATED_SPACE(dev), GFP_ATOMIC);
if (skb == NULL) { if (skb == NULL) {
ip_rt_put(rt); ip_rt_put(rt);
return -1; return -1;
......
...@@ -710,14 +710,14 @@ static void __init ic_bootp_send_if(struct ic_device *d, unsigned long jiffies_d ...@@ -710,14 +710,14 @@ 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 = LL_RESERVED_SPACE(dev);
struct iphdr *h; struct iphdr *h;
/* Allocate packet */ /* Allocate packet */
skb = alloc_skb(sizeof(struct bootp_pkt) + hh_len + 15, GFP_KERNEL); skb = alloc_skb(sizeof(struct bootp_pkt) + LL_ALLOCATED_SPACE(dev) + 15,
GFP_KERNEL);
if (!skb) if (!skb)
return; return;
skb_reserve(skb, hh_len); skb_reserve(skb, LL_RESERVED_SPACE(dev));
b = (struct bootp_pkt *) skb_put(skb, sizeof(struct bootp_pkt)); b = (struct bootp_pkt *) skb_put(skb, sizeof(struct bootp_pkt));
memset(b, 0, sizeof(struct bootp_pkt)); memset(b, 0, sizeof(struct bootp_pkt));
......
...@@ -322,7 +322,6 @@ static int raw_send_hdrinc(struct sock *sk, void *from, size_t length, ...@@ -322,7 +322,6 @@ static int raw_send_hdrinc(struct sock *sk, void *from, size_t length,
unsigned int flags) unsigned int flags)
{ {
struct inet_sock *inet = inet_sk(sk); struct inet_sock *inet = inet_sk(sk);
int hh_len;
struct iphdr *iph; struct iphdr *iph;
struct sk_buff *skb; struct sk_buff *skb;
unsigned int iphlen; unsigned int iphlen;
...@@ -336,13 +335,12 @@ static int raw_send_hdrinc(struct sock *sk, void *from, size_t length, ...@@ -336,13 +335,12 @@ static int raw_send_hdrinc(struct sock *sk, void *from, size_t length,
if (flags&MSG_PROBE) if (flags&MSG_PROBE)
goto out; goto out;
hh_len = LL_RESERVED_SPACE(rt->u.dst.dev); skb = sock_alloc_send_skb(sk,
length + LL_ALLOCATED_SPACE(rt->u.dst.dev) + 15,
skb = sock_alloc_send_skb(sk, length+hh_len+15, flags & MSG_DONTWAIT, &err);
flags&MSG_DONTWAIT, &err);
if (skb == NULL) if (skb == NULL)
goto error; goto error;
skb_reserve(skb, hh_len); skb_reserve(skb, LL_RESERVED_SPACE(rt->u.dst.dev));
skb->priority = sk->sk_priority; skb->priority = sk->sk_priority;
skb->mark = sk->sk_mark; skb->mark = sk->sk_mark;
......
...@@ -780,7 +780,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) ...@@ -780,7 +780,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
* Allocate buffer. * Allocate buffer.
*/ */
if ((frag = alloc_skb(len+hlen+sizeof(struct frag_hdr)+LL_RESERVED_SPACE(rt->u.dst.dev), GFP_ATOMIC)) == NULL) { if ((frag = alloc_skb(len+hlen+sizeof(struct frag_hdr)+LL_ALLOCATED_SPACE(rt->u.dst.dev), GFP_ATOMIC)) == NULL) {
NETDEBUG(KERN_INFO "IPv6: frag: no memory for new fragment!\n"); NETDEBUG(KERN_INFO "IPv6: frag: no memory for new fragment!\n");
IP6_INC_STATS(ip6_dst_idev(skb->dst), IP6_INC_STATS(ip6_dst_idev(skb->dst),
IPSTATS_MIB_FRAGFAILS); IPSTATS_MIB_FRAGFAILS);
......
...@@ -1411,7 +1411,7 @@ static struct sk_buff *mld_newpack(struct net_device *dev, int size) ...@@ -1411,7 +1411,7 @@ static struct sk_buff *mld_newpack(struct net_device *dev, int size)
IPV6_TLV_PADN, 0 }; IPV6_TLV_PADN, 0 };
/* we assume size > sizeof(ra) here */ /* we assume size > sizeof(ra) here */
skb = sock_alloc_send_skb(sk, size + LL_RESERVED_SPACE(dev), 1, &err); skb = sock_alloc_send_skb(sk, size + LL_ALLOCATED_SPACE(dev), 1, &err);
if (!skb) if (!skb)
return NULL; return NULL;
...@@ -1790,7 +1790,7 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) ...@@ -1790,7 +1790,7 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
payload_len = len + sizeof(ra); payload_len = len + sizeof(ra);
full_len = sizeof(struct ipv6hdr) + payload_len; full_len = sizeof(struct ipv6hdr) + payload_len;
skb = sock_alloc_send_skb(sk, LL_RESERVED_SPACE(dev) + full_len, 1, &err); skb = sock_alloc_send_skb(sk, LL_ALLOCATED_SPACE(dev) + full_len, 1, &err);
if (skb == NULL) { if (skb == NULL) {
rcu_read_lock(); rcu_read_lock();
......
...@@ -479,7 +479,7 @@ static void __ndisc_send(struct net_device *dev, ...@@ -479,7 +479,7 @@ static void __ndisc_send(struct net_device *dev,
skb = sock_alloc_send_skb(sk, skb = sock_alloc_send_skb(sk,
(MAX_HEADER + sizeof(struct ipv6hdr) + (MAX_HEADER + sizeof(struct ipv6hdr) +
len + LL_RESERVED_SPACE(dev)), len + LL_ALLOCATED_SPACE(dev)),
1, &err); 1, &err);
if (!skb) { if (!skb) {
ND_PRINTK0(KERN_ERR ND_PRINTK0(KERN_ERR
...@@ -1521,7 +1521,7 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, ...@@ -1521,7 +1521,7 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
buff = sock_alloc_send_skb(sk, buff = sock_alloc_send_skb(sk,
(MAX_HEADER + sizeof(struct ipv6hdr) + (MAX_HEADER + sizeof(struct ipv6hdr) +
len + LL_RESERVED_SPACE(dev)), len + LL_ALLOCATED_SPACE(dev)),
1, &err); 1, &err);
if (buff == NULL) { if (buff == NULL) {
ND_PRINTK0(KERN_ERR ND_PRINTK0(KERN_ERR
......
...@@ -609,7 +609,6 @@ static int rawv6_send_hdrinc(struct sock *sk, void *from, int length, ...@@ -609,7 +609,6 @@ static int rawv6_send_hdrinc(struct sock *sk, void *from, int length,
struct ipv6_pinfo *np = inet6_sk(sk); struct ipv6_pinfo *np = inet6_sk(sk);
struct ipv6hdr *iph; struct ipv6hdr *iph;
struct sk_buff *skb; struct sk_buff *skb;
unsigned int hh_len;
int err; int err;
if (length > rt->u.dst.dev->mtu) { if (length > rt->u.dst.dev->mtu) {
...@@ -619,13 +618,12 @@ static int rawv6_send_hdrinc(struct sock *sk, void *from, int length, ...@@ -619,13 +618,12 @@ static int rawv6_send_hdrinc(struct sock *sk, void *from, int length,
if (flags&MSG_PROBE) if (flags&MSG_PROBE)
goto out; goto out;
hh_len = LL_RESERVED_SPACE(rt->u.dst.dev); skb = sock_alloc_send_skb(sk,
length + LL_ALLOCATED_SPACE(rt->u.dst.dev) + 15,
skb = sock_alloc_send_skb(sk, length+hh_len+15, flags & MSG_DONTWAIT, &err);
flags&MSG_DONTWAIT, &err);
if (skb == NULL) if (skb == NULL)
goto error; goto error;
skb_reserve(skb, hh_len); skb_reserve(skb, LL_RESERVED_SPACE(rt->u.dst.dev));
skb->priority = sk->sk_priority; skb->priority = sk->sk_priority;
skb->mark = sk->sk_mark; skb->mark = sk->sk_mark;
......
...@@ -743,7 +743,7 @@ static int packet_sendmsg(struct kiocb *iocb, struct socket *sock, ...@@ -743,7 +743,7 @@ static int packet_sendmsg(struct kiocb *iocb, struct socket *sock,
if (len > dev->mtu+reserve) if (len > dev->mtu+reserve)
goto out_unlock; goto out_unlock;
skb = sock_alloc_send_skb(sk, len + LL_RESERVED_SPACE(dev), skb = sock_alloc_send_skb(sk, len + LL_ALLOCATED_SPACE(dev),
msg->msg_flags & MSG_DONTWAIT, &err); msg->msg_flags & MSG_DONTWAIT, &err);
if (skb==NULL) if (skb==NULL)
goto out_unlock; goto out_unlock;
......
...@@ -25,11 +25,11 @@ static int xfrm_state_check_space(struct xfrm_state *x, struct sk_buff *skb) ...@@ -25,11 +25,11 @@ static int xfrm_state_check_space(struct xfrm_state *x, struct sk_buff *skb)
struct dst_entry *dst = skb->dst; struct dst_entry *dst = skb->dst;
int nhead = dst->header_len + LL_RESERVED_SPACE(dst->dev) int nhead = dst->header_len + LL_RESERVED_SPACE(dst->dev)
- skb_headroom(skb); - skb_headroom(skb);
int ntail = dst->dev->needed_tailroom - skb_tailroom(skb);
if (nhead > 0) if (nhead > 0 || ntail > 0)
return pskb_expand_head(skb, nhead, 0, GFP_ATOMIC); return pskb_expand_head(skb, nhead, ntail, GFP_ATOMIC);
/* Check tail too... */
return 0; return 0;
} }
......
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