]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - net/ipv6/ip6_output.c
Pull miscellaneous into release branch
[linux-2.6-omap-h63xx.git] / net / ipv6 / ip6_output.c
index 15c4f6cee3e6e54daf41bec34d5015fb7a5fdf4b..8b67ca07467d48e0bb3e62da1ae19d7a6d5b156e 100644 (file)
@@ -257,6 +257,7 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
        ipv6_addr_copy(&hdr->daddr, first_hop);
 
        skb->priority = sk->sk_priority;
+       skb->mark = sk->sk_mark;
 
        mtu = dst_mtu(dst);
        if ((skb->len <= mtu) || ipfragok || skb_is_gso(skb)) {
@@ -620,7 +621,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
         * or if the skb it not generated by a local socket.  (This last
         * check should be redundant, but it's free.)
         */
-       if (!np || np->pmtudisc >= IPV6_PMTUDISC_DO) {
+       if (!skb->local_df) {
                skb->dev = skb->dst->dev;
                icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, skb->dev);
                IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_FRAGFAILS);
@@ -636,6 +637,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
 
        if (skb_shinfo(skb)->frag_list) {
                int first_len = skb_pagelen(skb);
+               int truesizes = 0;
 
                if (first_len - hlen > mtu ||
                    ((first_len - hlen) & 7) ||
@@ -658,7 +660,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
                                sock_hold(skb->sk);
                                frag->sk = skb->sk;
                                frag->destructor = sock_wfree;
-                               skb->truesize -= frag->truesize;
+                               truesizes += frag->truesize;
                        }
                }
 
@@ -689,6 +691,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
 
                first_len = skb_pagelen(skb);
                skb->data_len = first_len - skb_headlen(skb);
+               skb->truesize -= truesizes;
                skb->len = first_len;
                ipv6_hdr(skb)->payload_len = htons(first_len -
                                                   sizeof(struct ipv6hdr));
@@ -1417,6 +1420,10 @@ int ip6_push_pending_frames(struct sock *sk)
                tmp_skb->sk = NULL;
        }
 
+       /* Allow local fragmentation. */
+       if (np->pmtudisc < IPV6_PMTUDISC_DO)
+               skb->local_df = 1;
+
        ipv6_addr_copy(final_dst, &fl->fl6_dst);
        __skb_pull(skb, skb_network_header_len(skb));
        if (opt && opt->opt_flen)
@@ -1437,6 +1444,7 @@ int ip6_push_pending_frames(struct sock *sk)
        ipv6_addr_copy(&hdr->daddr, final_dst);
 
        skb->priority = sk->sk_priority;
+       skb->mark = sk->sk_mark;
 
        skb->dst = dst_clone(&rt->u.dst);
        IP6_INC_STATS(rt->rt6i_idev, IPSTATS_MIB_OUTREQUESTS);