diff options
author | Herbert Xu <herbert@gondor.apana.org.au> | 2011-11-17 21:20:04 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-11-18 14:37:09 -0500 |
commit | a7ae1992248e5cf9dc5bd35695ab846d27efe15f (patch) | |
tree | ed3f450a41ca5975aecae2850105ca22f98ca318 | |
parent | 660882432909dbe611f1792eda158188065cb9f1 (diff) |
ipv6: Remove all uses of LL_ALLOCATED_SPACE
ipv6: Remove all uses of LL_ALLOCATED_SPACE
The macro LL_ALLOCATED_SPACE was ill-conceived. It applies the
alignment to the sum of needed_headroom and needed_tailroom. As
the amount that is then reserved for head room is needed_headroom
with alignment, this means that the tail room left may be too small.
This patch replaces all uses of LL_ALLOCATED_SPACE in net/ipv6
with the macro LL_RESERVED_SPACE and direct reference to
needed_tailroom.
This also fixes the problem with needed_headroom changing between
allocating the skb and reserving the head room.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/ipv6/ip6_output.c | 8 | ||||
-rw-r--r-- | net/ipv6/mcast.c | 12 | ||||
-rw-r--r-- | net/ipv6/ndisc.c | 13 | ||||
-rw-r--r-- | net/ipv6/raw.c | 6 |
4 files changed, 27 insertions, 12 deletions
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 84d0bd5cac93..68ef97f353b6 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
@@ -631,6 +631,7 @@ int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) | |||
631 | struct ipv6hdr *tmp_hdr; | 631 | struct ipv6hdr *tmp_hdr; |
632 | struct frag_hdr *fh; | 632 | struct frag_hdr *fh; |
633 | unsigned int mtu, hlen, left, len; | 633 | unsigned int mtu, hlen, left, len; |
634 | int hroom, troom; | ||
634 | __be32 frag_id = 0; | 635 | __be32 frag_id = 0; |
635 | int ptr, offset = 0, err=0; | 636 | int ptr, offset = 0, err=0; |
636 | u8 *prevhdr, nexthdr = 0; | 637 | u8 *prevhdr, nexthdr = 0; |
@@ -797,6 +798,8 @@ slow_path: | |||
797 | */ | 798 | */ |
798 | 799 | ||
799 | *prevhdr = NEXTHDR_FRAGMENT; | 800 | *prevhdr = NEXTHDR_FRAGMENT; |
801 | hroom = LL_RESERVED_SPACE(rt->dst.dev); | ||
802 | troom = rt->dst.dev->needed_tailroom; | ||
800 | 803 | ||
801 | /* | 804 | /* |
802 | * Keep copying data until we run out. | 805 | * Keep copying data until we run out. |
@@ -815,7 +818,8 @@ slow_path: | |||
815 | * Allocate buffer. | 818 | * Allocate buffer. |
816 | */ | 819 | */ |
817 | 820 | ||
818 | if ((frag = alloc_skb(len+hlen+sizeof(struct frag_hdr)+LL_ALLOCATED_SPACE(rt->dst.dev), GFP_ATOMIC)) == NULL) { | 821 | if ((frag = alloc_skb(len + hlen + sizeof(struct frag_hdr) + |
822 | hroom + troom, GFP_ATOMIC)) == NULL) { | ||
819 | NETDEBUG(KERN_INFO "IPv6: frag: no memory for new fragment!\n"); | 823 | NETDEBUG(KERN_INFO "IPv6: frag: no memory for new fragment!\n"); |
820 | IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), | 824 | IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), |
821 | IPSTATS_MIB_FRAGFAILS); | 825 | IPSTATS_MIB_FRAGFAILS); |
@@ -828,7 +832,7 @@ slow_path: | |||
828 | */ | 832 | */ |
829 | 833 | ||
830 | ip6_copy_metadata(frag, skb); | 834 | ip6_copy_metadata(frag, skb); |
831 | skb_reserve(frag, LL_RESERVED_SPACE(rt->dst.dev)); | 835 | skb_reserve(frag, hroom); |
832 | skb_put(frag, len + hlen + sizeof(struct frag_hdr)); | 836 | skb_put(frag, len + hlen + sizeof(struct frag_hdr)); |
833 | skb_reset_network_header(frag); | 837 | skb_reset_network_header(frag); |
834 | fh = (struct frag_hdr *)(skb_network_header(frag) + hlen); | 838 | fh = (struct frag_hdr *)(skb_network_header(frag) + hlen); |
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index ee7839f4d6e3..7b94bebb73b1 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c | |||
@@ -1343,13 +1343,15 @@ static struct sk_buff *mld_newpack(struct net_device *dev, int size) | |||
1343 | struct mld2_report *pmr; | 1343 | struct mld2_report *pmr; |
1344 | struct in6_addr addr_buf; | 1344 | struct in6_addr addr_buf; |
1345 | const struct in6_addr *saddr; | 1345 | const struct in6_addr *saddr; |
1346 | int hlen = LL_RESERVED_SPACE(dev); | ||
1347 | int tlen = dev->needed_tailroom; | ||
1346 | int err; | 1348 | int err; |
1347 | u8 ra[8] = { IPPROTO_ICMPV6, 0, | 1349 | u8 ra[8] = { IPPROTO_ICMPV6, 0, |
1348 | IPV6_TLV_ROUTERALERT, 2, 0, 0, | 1350 | IPV6_TLV_ROUTERALERT, 2, 0, 0, |
1349 | IPV6_TLV_PADN, 0 }; | 1351 | IPV6_TLV_PADN, 0 }; |
1350 | 1352 | ||
1351 | /* we assume size > sizeof(ra) here */ | 1353 | /* we assume size > sizeof(ra) here */ |
1352 | size += LL_ALLOCATED_SPACE(dev); | 1354 | size += hlen + tlen; |
1353 | /* limit our allocations to order-0 page */ | 1355 | /* limit our allocations to order-0 page */ |
1354 | size = min_t(int, size, SKB_MAX_ORDER(0, 0)); | 1356 | size = min_t(int, size, SKB_MAX_ORDER(0, 0)); |
1355 | skb = sock_alloc_send_skb(sk, size, 1, &err); | 1357 | skb = sock_alloc_send_skb(sk, size, 1, &err); |
@@ -1357,7 +1359,7 @@ static struct sk_buff *mld_newpack(struct net_device *dev, int size) | |||
1357 | if (!skb) | 1359 | if (!skb) |
1358 | return NULL; | 1360 | return NULL; |
1359 | 1361 | ||
1360 | skb_reserve(skb, LL_RESERVED_SPACE(dev)); | 1362 | skb_reserve(skb, hlen); |
1361 | 1363 | ||
1362 | if (ipv6_get_lladdr(dev, &addr_buf, IFA_F_TENTATIVE)) { | 1364 | if (ipv6_get_lladdr(dev, &addr_buf, IFA_F_TENTATIVE)) { |
1363 | /* <draft-ietf-magma-mld-source-05.txt>: | 1365 | /* <draft-ietf-magma-mld-source-05.txt>: |
@@ -1723,6 +1725,8 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) | |||
1723 | struct mld_msg *hdr; | 1725 | struct mld_msg *hdr; |
1724 | const struct in6_addr *snd_addr, *saddr; | 1726 | const struct in6_addr *snd_addr, *saddr; |
1725 | struct in6_addr addr_buf; | 1727 | struct in6_addr addr_buf; |
1728 | int hlen = LL_RESERVED_SPACE(dev); | ||
1729 | int tlen = dev->needed_tailroom; | ||
1726 | int err, len, payload_len, full_len; | 1730 | int err, len, payload_len, full_len; |
1727 | u8 ra[8] = { IPPROTO_ICMPV6, 0, | 1731 | u8 ra[8] = { IPPROTO_ICMPV6, 0, |
1728 | IPV6_TLV_ROUTERALERT, 2, 0, 0, | 1732 | IPV6_TLV_ROUTERALERT, 2, 0, 0, |
@@ -1744,7 +1748,7 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) | |||
1744 | IPSTATS_MIB_OUT, full_len); | 1748 | IPSTATS_MIB_OUT, full_len); |
1745 | rcu_read_unlock(); | 1749 | rcu_read_unlock(); |
1746 | 1750 | ||
1747 | skb = sock_alloc_send_skb(sk, LL_ALLOCATED_SPACE(dev) + full_len, 1, &err); | 1751 | skb = sock_alloc_send_skb(sk, hlen + tlen + full_len, 1, &err); |
1748 | 1752 | ||
1749 | if (skb == NULL) { | 1753 | if (skb == NULL) { |
1750 | rcu_read_lock(); | 1754 | rcu_read_lock(); |
@@ -1754,7 +1758,7 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) | |||
1754 | return; | 1758 | return; |
1755 | } | 1759 | } |
1756 | 1760 | ||
1757 | skb_reserve(skb, LL_RESERVED_SPACE(dev)); | 1761 | skb_reserve(skb, hlen); |
1758 | 1762 | ||
1759 | if (ipv6_get_lladdr(dev, &addr_buf, IFA_F_TENTATIVE)) { | 1763 | if (ipv6_get_lladdr(dev, &addr_buf, IFA_F_TENTATIVE)) { |
1760 | /* <draft-ietf-magma-mld-source-05.txt>: | 1764 | /* <draft-ietf-magma-mld-source-05.txt>: |
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 4a2098222625..d699ddcad4ce 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c | |||
@@ -446,6 +446,8 @@ struct sk_buff *ndisc_build_skb(struct net_device *dev, | |||
446 | struct sock *sk = net->ipv6.ndisc_sk; | 446 | struct sock *sk = net->ipv6.ndisc_sk; |
447 | struct sk_buff *skb; | 447 | struct sk_buff *skb; |
448 | struct icmp6hdr *hdr; | 448 | struct icmp6hdr *hdr; |
449 | int hlen = LL_RESERVED_SPACE(dev); | ||
450 | int tlen = dev->needed_tailroom; | ||
449 | int len; | 451 | int len; |
450 | int err; | 452 | int err; |
451 | u8 *opt; | 453 | u8 *opt; |
@@ -459,7 +461,7 @@ struct sk_buff *ndisc_build_skb(struct net_device *dev, | |||
459 | 461 | ||
460 | skb = sock_alloc_send_skb(sk, | 462 | skb = sock_alloc_send_skb(sk, |
461 | (MAX_HEADER + sizeof(struct ipv6hdr) + | 463 | (MAX_HEADER + sizeof(struct ipv6hdr) + |
462 | len + LL_ALLOCATED_SPACE(dev)), | 464 | len + hlen + tlen), |
463 | 1, &err); | 465 | 1, &err); |
464 | if (!skb) { | 466 | if (!skb) { |
465 | ND_PRINTK0(KERN_ERR | 467 | ND_PRINTK0(KERN_ERR |
@@ -468,7 +470,7 @@ struct sk_buff *ndisc_build_skb(struct net_device *dev, | |||
468 | return NULL; | 470 | return NULL; |
469 | } | 471 | } |
470 | 472 | ||
471 | skb_reserve(skb, LL_RESERVED_SPACE(dev)); | 473 | skb_reserve(skb, hlen); |
472 | ip6_nd_hdr(sk, skb, dev, saddr, daddr, IPPROTO_ICMPV6, len); | 474 | ip6_nd_hdr(sk, skb, dev, saddr, daddr, IPPROTO_ICMPV6, len); |
473 | 475 | ||
474 | skb->transport_header = skb->tail; | 476 | skb->transport_header = skb->tail; |
@@ -1533,6 +1535,7 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, | |||
1533 | struct inet6_dev *idev; | 1535 | struct inet6_dev *idev; |
1534 | struct flowi6 fl6; | 1536 | struct flowi6 fl6; |
1535 | u8 *opt; | 1537 | u8 *opt; |
1538 | int hlen, tlen; | ||
1536 | int rd_len; | 1539 | int rd_len; |
1537 | int err; | 1540 | int err; |
1538 | u8 ha_buf[MAX_ADDR_LEN], *ha = NULL; | 1541 | u8 ha_buf[MAX_ADDR_LEN], *ha = NULL; |
@@ -1590,9 +1593,11 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, | |||
1590 | rd_len &= ~0x7; | 1593 | rd_len &= ~0x7; |
1591 | len += rd_len; | 1594 | len += rd_len; |
1592 | 1595 | ||
1596 | hlen = LL_RESERVED_SPACE(dev); | ||
1597 | tlen = dev->needed_tailroom; | ||
1593 | buff = sock_alloc_send_skb(sk, | 1598 | buff = sock_alloc_send_skb(sk, |
1594 | (MAX_HEADER + sizeof(struct ipv6hdr) + | 1599 | (MAX_HEADER + sizeof(struct ipv6hdr) + |
1595 | len + LL_ALLOCATED_SPACE(dev)), | 1600 | len + hlen + tlen), |
1596 | 1, &err); | 1601 | 1, &err); |
1597 | if (buff == NULL) { | 1602 | if (buff == NULL) { |
1598 | ND_PRINTK0(KERN_ERR | 1603 | ND_PRINTK0(KERN_ERR |
@@ -1601,7 +1606,7 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, | |||
1601 | goto release; | 1606 | goto release; |
1602 | } | 1607 | } |
1603 | 1608 | ||
1604 | skb_reserve(buff, LL_RESERVED_SPACE(dev)); | 1609 | skb_reserve(buff, hlen); |
1605 | ip6_nd_hdr(sk, buff, dev, &saddr_buf, &ipv6_hdr(skb)->saddr, | 1610 | ip6_nd_hdr(sk, buff, dev, &saddr_buf, &ipv6_hdr(skb)->saddr, |
1606 | IPPROTO_ICMPV6, len); | 1611 | IPPROTO_ICMPV6, len); |
1607 | 1612 | ||
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 204f2e833f04..a1aa869a9ce7 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c | |||
@@ -611,6 +611,8 @@ static int rawv6_send_hdrinc(struct sock *sk, void *from, int length, | |||
611 | struct sk_buff *skb; | 611 | struct sk_buff *skb; |
612 | int err; | 612 | int err; |
613 | struct rt6_info *rt = (struct rt6_info *)*dstp; | 613 | struct rt6_info *rt = (struct rt6_info *)*dstp; |
614 | int hlen = LL_RESERVED_SPACE(rt->dst.dev); | ||
615 | int tlen = rt->dst.dev->needed_tailroom; | ||
614 | 616 | ||
615 | if (length > rt->dst.dev->mtu) { | 617 | if (length > rt->dst.dev->mtu) { |
616 | ipv6_local_error(sk, EMSGSIZE, fl6, rt->dst.dev->mtu); | 618 | ipv6_local_error(sk, EMSGSIZE, fl6, rt->dst.dev->mtu); |
@@ -620,11 +622,11 @@ static int rawv6_send_hdrinc(struct sock *sk, void *from, int length, | |||
620 | goto out; | 622 | goto out; |
621 | 623 | ||
622 | skb = sock_alloc_send_skb(sk, | 624 | skb = sock_alloc_send_skb(sk, |
623 | length + LL_ALLOCATED_SPACE(rt->dst.dev) + 15, | 625 | length + hlen + tlen + 15, |
624 | flags & MSG_DONTWAIT, &err); | 626 | flags & MSG_DONTWAIT, &err); |
625 | if (skb == NULL) | 627 | if (skb == NULL) |
626 | goto error; | 628 | goto error; |
627 | skb_reserve(skb, LL_RESERVED_SPACE(rt->dst.dev)); | 629 | skb_reserve(skb, hlen); |
628 | 630 | ||
629 | skb->priority = sk->sk_priority; | 631 | skb->priority = sk->sk_priority; |
630 | skb->mark = sk->sk_mark; | 632 | skb->mark = sk->sk_mark; |