]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - net/ipv4/ip_output.c
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/holtmann/bluet...
[karo-tx-linux.git] / net / ipv4 / ip_output.c
index 6cbeb2e108de6c07927560ef4b953346a78322b1..04b69896df5fc743021efd4d4a1705b7de146333 100644 (file)
@@ -89,6 +89,7 @@ __inline__ void ip_send_check(struct iphdr *iph)
        iph->check = 0;
        iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
 }
+EXPORT_SYMBOL(ip_send_check);
 
 int __ip_local_out(struct sk_buff *skb)
 {
@@ -172,7 +173,6 @@ int ip_build_and_send_pkt(struct sk_buff *skb, struct sock *sk,
        /* Send it out. */
        return ip_local_out(skb);
 }
-
 EXPORT_SYMBOL_GPL(ip_build_and_send_pkt);
 
 static inline int ip_finish_output2(struct sk_buff *skb)
@@ -403,6 +403,7 @@ no_route:
        kfree_skb(skb);
        return -EHOSTUNREACH;
 }
+EXPORT_SYMBOL(ip_queue_xmit);
 
 
 static void ip_copy_metadata(struct sk_buff *to, struct sk_buff *from)
@@ -411,7 +412,7 @@ static void ip_copy_metadata(struct sk_buff *to, struct sk_buff *from)
        to->priority = from->priority;
        to->protocol = from->protocol;
        skb_dst_drop(to);
-       skb_dst_set(to, dst_clone(skb_dst(from)));
+       skb_dst_copy(to, from);
        to->dev = from->dev;
        to->mark = from->mark;
 
@@ -442,11 +443,10 @@ static void ip_copy_metadata(struct sk_buff *to, struct sk_buff *from)
 int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
 {
        struct iphdr *iph;
-       int raw = 0;
        int ptr;
        struct net_device *dev;
        struct sk_buff *skb2;
-       unsigned int mtu, hlen, left, len, ll_rs, pad;
+       unsigned int mtu, hlen, left, len, ll_rs;
        int offset;
        __be16 not_last_frag;
        struct rtable *rt = skb_rtable(skb);
@@ -580,14 +580,12 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
 
 slow_path:
        left = skb->len - hlen;         /* Space per frame */
-       ptr = raw + hlen;               /* Where to start from */
+       ptr = hlen;             /* Where to start from */
 
        /* for bridged IP traffic encapsulated inside f.e. a vlan header,
         * we need to make room for the encapsulating header
         */
-       pad = nf_bridge_pad(skb);
-       ll_rs = LL_RESERVED_SPACE_EXTRA(rt->dst.dev, pad);
-       mtu -= pad;
+       ll_rs = LL_RESERVED_SPACE_EXTRA(rt->dst.dev, nf_bridge_pad(skb));
 
        /*
         *      Fragment the datagram.
@@ -697,7 +695,6 @@ fail:
        IP_INC_STATS(dev_net(dev), IPSTATS_MIB_FRAGFAILS);
        return err;
 }
-
 EXPORT_SYMBOL(ip_fragment);
 
 int
@@ -716,6 +713,7 @@ ip_generic_getfrag(void *from, char *to, int offset, int len, int odd, struct sk
        }
        return 0;
 }
+EXPORT_SYMBOL(ip_generic_getfrag);
 
 static inline __wsum
 csum_page(struct page *page, int offset, int copy)
@@ -873,8 +871,10 @@ int ip_append_data(struct sock *sk,
            !exthdrlen)
                csummode = CHECKSUM_PARTIAL;
 
+       skb = skb_peek_tail(&sk->sk_write_queue);
+
        inet->cork.length += length;
-       if (((length> mtu) || !skb_queue_empty(&sk->sk_write_queue)) &&
+       if (((length > mtu) || (skb && skb_is_gso(skb))) &&
            (sk->sk_protocol == IPPROTO_UDP) &&
            (rt->dst.dev->features & NETIF_F_UFO)) {
                err = ip_ufo_append_data(sk, getfrag, from, length, hh_len,
@@ -892,7 +892,7 @@ int ip_append_data(struct sock *sk,
         * adding appropriate IP header.
         */
 
-       if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL)
+       if (!skb)
                goto alloc_new_skb;
 
        while (length > 0) {
@@ -1121,7 +1121,8 @@ ssize_t   ip_append_page(struct sock *sk, struct page *page,
                return -EINVAL;
 
        inet->cork.length += size;
-       if ((sk->sk_protocol == IPPROTO_UDP) &&
+       if ((size + skb->len > mtu) &&
+           (sk->sk_protocol == IPPROTO_UDP) &&
            (rt->dst.dev->features & NETIF_F_UFO)) {
                skb_shinfo(skb)->gso_size = mtu - fragheaderlen;
                skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
@@ -1445,7 +1446,3 @@ void __init ip_init(void)
        igmp_mc_proc_init();
 #endif
 }
-
-EXPORT_SYMBOL(ip_generic_getfrag);
-EXPORT_SYMBOL(ip_queue_xmit);
-EXPORT_SYMBOL(ip_send_check);