diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-10-25 13:25:22 +0200 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-10-25 13:25:22 +0200 |
commit | 8a9ea3237e7eb5c25f09e429ad242ae5a3d5ea22 (patch) | |
tree | a0a63398a9983667d52cbbbf4e2405b4f22b1d83 /net/ipv6/ip6_output.c | |
parent | 1be025d3cb40cd295123af2c394f7229ef9b30ca (diff) | |
parent | 8b3408f8ee994973869d8ba32c5bf482bc4ddca4 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next: (1745 commits)
dp83640: free packet queues on remove
dp83640: use proper function to free transmit time stamping packets
ipv6: Do not use routes from locally generated RAs
|PATCH net-next] tg3: add tx_dropped counter
be2net: don't create multiple RX/TX rings in multi channel mode
be2net: don't create multiple TXQs in BE2
be2net: refactor VF setup/teardown code into be_vf_setup/clear()
be2net: add vlan/rx-mode/flow-control config to be_setup()
net_sched: cls_flow: use skb_header_pointer()
ipv4: avoid useless call of the function check_peer_pmtu
TCP: remove TCP_DEBUG
net: Fix driver name for mdio-gpio.c
ipv4: tcp: fix TOS value in ACK messages sent from TIME_WAIT
rtnetlink: Add missing manual netlink notification in dev_change_net_namespaces
ipv4: fix ipsec forward performance regression
jme: fix irq storm after suspend/resume
route: fix ICMP redirect validation
net: hold sock reference while processing tx timestamps
tcp: md5: add more const attributes
Add ethtool -g support to virtio_net
...
Fix up conflicts in:
- drivers/net/Kconfig:
The split-up generated a trivial conflict with removal of a
stale reference to Documentation/networking/net-modules.txt.
Remove it from the new location instead.
- fs/sysfs/dir.c:
Fairly nasty conflicts with the sysfs rb-tree usage, conflicting
with Eric Biederman's changes for tagged directories.
Diffstat (limited to 'net/ipv6/ip6_output.c')
-rw-r--r-- | net/ipv6/ip6_output.c | 28 |
1 files changed, 18 insertions, 10 deletions
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 4c882cf4e8a..1c9bf8b5c30 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -1193,6 +1193,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, struct sk_buff *skb; unsigned int maxfraglen, fragheaderlen; int exthdrlen; + int dst_exthdrlen; int hh_len; int mtu; int copy; @@ -1248,7 +1249,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, np->cork.hop_limit = hlimit; np->cork.tclass = tclass; mtu = np->pmtudisc == IPV6_PMTUDISC_PROBE ? - rt->dst.dev->mtu : dst_mtu(rt->dst.path); + rt->dst.dev->mtu : dst_mtu(&rt->dst); if (np->frag_size < mtu) { if (np->frag_size) mtu = np->frag_size; @@ -1259,16 +1260,17 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, cork->length = 0; sk->sk_sndmsg_page = NULL; sk->sk_sndmsg_off = 0; - exthdrlen = rt->dst.header_len + (opt ? opt->opt_flen : 0) - - rt->rt6i_nfheader_len; + exthdrlen = (opt ? opt->opt_flen : 0) - rt->rt6i_nfheader_len; length += exthdrlen; transhdrlen += exthdrlen; + dst_exthdrlen = rt->dst.header_len; } else { rt = (struct rt6_info *)cork->dst; fl6 = &inet->cork.fl.u.ip6; opt = np->cork.opt; transhdrlen = 0; exthdrlen = 0; + dst_exthdrlen = 0; mtu = cork->fragsize; } @@ -1368,6 +1370,8 @@ alloc_new_skb: else alloclen = datalen + fragheaderlen; + alloclen += dst_exthdrlen; + /* * The last fragment gets additional space at tail. * Note: we overallocate on fragments with MSG_MODE @@ -1419,9 +1423,9 @@ alloc_new_skb: /* * Find where to start putting bytes */ - data = skb_put(skb, fraglen); - skb_set_network_header(skb, exthdrlen); - data += fragheaderlen; + data = skb_put(skb, fraglen + dst_exthdrlen); + skb_set_network_header(skb, exthdrlen + dst_exthdrlen); + data += fragheaderlen + dst_exthdrlen; skb->transport_header = (skb->network_header + fragheaderlen); if (fraggap) { @@ -1434,6 +1438,7 @@ alloc_new_skb: pskb_trim_unique(skb_prev, maxfraglen); } copy = datalen - transhdrlen - fraggap; + if (copy < 0) { err = -EINVAL; kfree_skb(skb); @@ -1448,6 +1453,7 @@ alloc_new_skb: length -= datalen - fraggap; transhdrlen = 0; exthdrlen = 0; + dst_exthdrlen = 0; csummode = CHECKSUM_NONE; /* @@ -1480,13 +1486,13 @@ alloc_new_skb: if (page && (left = PAGE_SIZE - off) > 0) { if (copy >= left) copy = left; - if (page != frag->page) { + if (page != skb_frag_page(frag)) { if (i == MAX_SKB_FRAGS) { err = -EMSGSIZE; goto error; } - get_page(page); skb_fill_page_desc(skb, i, page, sk->sk_sndmsg_off, 0); + skb_frag_ref(skb, i); frag = &skb_shinfo(skb)->frags[i]; } } else if(i < MAX_SKB_FRAGS) { @@ -1506,12 +1512,14 @@ alloc_new_skb: err = -EMSGSIZE; goto error; } - if (getfrag(from, page_address(frag->page)+frag->page_offset+frag->size, offset, copy, skb->len, skb) < 0) { + if (getfrag(from, + skb_frag_address(frag) + skb_frag_size(frag), + offset, copy, skb->len, skb) < 0) { err = -EFAULT; goto error; } sk->sk_sndmsg_off += copy; - frag->size += copy; + skb_frag_size_add(frag, copy); skb->len += copy; skb->data_len += copy; skb->truesize += copy; |