From: Willem de Bruijn <will...@google.com>

UDP segmentation offload needs access to inet_cork in the udp layer.
Pass the struct to ip(6)_make_skb instead of allocating it on the
stack in that function itself.

This patch is a noop otherwise.

Signed-off-by: Willem de Bruijn <will...@google.com>
---
 include/net/ip.h      |  2 +-
 include/net/ipv6.h    |  1 +
 net/ipv4/ip_output.c  | 17 ++++++++---------
 net/ipv4/udp.c        |  4 +++-
 net/ipv6/ip6_output.c | 20 ++++++++++----------
 net/ipv6/udp.c        |  3 ++-
 6 files changed, 25 insertions(+), 22 deletions(-)

diff --git a/include/net/ip.h b/include/net/ip.h
index ecffd843e7b8..5a0d2b660506 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -171,7 +171,7 @@ struct sk_buff *ip_make_skb(struct sock *sk, struct flowi4 
*fl4,
                                        int len, int odd, struct sk_buff *skb),
                            void *from, int length, int transhdrlen,
                            struct ipcm_cookie *ipc, struct rtable **rtp,
-                           unsigned int flags);
+                           struct inet_cork *cork, unsigned int flags);
 
 static inline struct sk_buff *ip_finish_skb(struct sock *sk, struct flowi4 
*fl4)
 {
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 68b167d98879..0dd722cab037 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -950,6 +950,7 @@ struct sk_buff *ip6_make_skb(struct sock *sk,
                             void *from, int length, int transhdrlen,
                             struct ipcm6_cookie *ipc6, struct flowi6 *fl6,
                             struct rt6_info *rt, unsigned int flags,
+                            struct inet_cork_full *cork,
                             const struct sockcm_cookie *sockc);
 
 static inline struct sk_buff *ip6_finish_skb(struct sock *sk)
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 4c11b810a447..83b14ea16654 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -1468,9 +1468,8 @@ struct sk_buff *ip_make_skb(struct sock *sk,
                                        int len, int odd, struct sk_buff *skb),
                            void *from, int length, int transhdrlen,
                            struct ipcm_cookie *ipc, struct rtable **rtp,
-                           unsigned int flags)
+                           struct inet_cork *cork, unsigned int flags)
 {
-       struct inet_cork cork;
        struct sk_buff_head queue;
        int err;
 
@@ -1479,22 +1478,22 @@ struct sk_buff *ip_make_skb(struct sock *sk,
 
        __skb_queue_head_init(&queue);
 
-       cork.flags = 0;
-       cork.addr = 0;
-       cork.opt = NULL;
-       err = ip_setup_cork(sk, &cork, ipc, rtp);
+       cork->flags = 0;
+       cork->addr = 0;
+       cork->opt = NULL;
+       err = ip_setup_cork(sk, cork, ipc, rtp);
        if (err)
                return ERR_PTR(err);
 
-       err = __ip_append_data(sk, fl4, &queue, &cork,
+       err = __ip_append_data(sk, fl4, &queue, cork,
                               &current->task_frag, getfrag,
                               from, length, transhdrlen, flags);
        if (err) {
-               __ip_flush_pending_frames(sk, &queue, &cork);
+               __ip_flush_pending_frames(sk, &queue, cork);
                return ERR_PTR(err);
        }
 
-       return __ip_make_skb(sk, fl4, &queue, &cork);
+       return __ip_make_skb(sk, fl4, &queue, cork);
 }
 
 /*
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 24b5c59b1c53..6b9d8017b319 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -1030,9 +1030,11 @@ int udp_sendmsg(struct sock *sk, struct msghdr *msg, 
size_t len)
 
        /* Lockless fast path for the non-corking case. */
        if (!corkreq) {
+               struct inet_cork cork;
+
                skb = ip_make_skb(sk, fl4, getfrag, msg, ulen,
                                  sizeof(struct udphdr), &ipc, &rt,
-                                 msg->msg_flags);
+                                 &cork, msg->msg_flags);
                err = PTR_ERR(skb);
                if (!IS_ERR_OR_NULL(skb))
                        err = udp_send_skb(skb, fl4);
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index a39b04f9fa6e..6751f4c375b9 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -1749,9 +1749,9 @@ struct sk_buff *ip6_make_skb(struct sock *sk,
                             void *from, int length, int transhdrlen,
                             struct ipcm6_cookie *ipc6, struct flowi6 *fl6,
                             struct rt6_info *rt, unsigned int flags,
+                            struct inet_cork_full *cork,
                             const struct sockcm_cookie *sockc)
 {
-       struct inet_cork_full cork;
        struct inet6_cork v6_cork;
        struct sk_buff_head queue;
        int exthdrlen = (ipc6->opt ? ipc6->opt->opt_flen : 0);
@@ -1762,27 +1762,27 @@ struct sk_buff *ip6_make_skb(struct sock *sk,
 
        __skb_queue_head_init(&queue);
 
-       cork.base.flags = 0;
-       cork.base.addr = 0;
-       cork.base.opt = NULL;
-       cork.base.dst = NULL;
+       cork->base.flags = 0;
+       cork->base.addr = 0;
+       cork->base.opt = NULL;
+       cork->base.dst = NULL;
        v6_cork.opt = NULL;
-       err = ip6_setup_cork(sk, &cork, &v6_cork, ipc6, rt, fl6);
+       err = ip6_setup_cork(sk, cork, &v6_cork, ipc6, rt, fl6);
        if (err) {
-               ip6_cork_release(&cork, &v6_cork);
+               ip6_cork_release(cork, &v6_cork);
                return ERR_PTR(err);
        }
        if (ipc6->dontfrag < 0)
                ipc6->dontfrag = inet6_sk(sk)->dontfrag;
 
-       err = __ip6_append_data(sk, fl6, &queue, &cork.base, &v6_cork,
+       err = __ip6_append_data(sk, fl6, &queue, &cork->base, &v6_cork,
                                &current->task_frag, getfrag, from,
                                length + exthdrlen, transhdrlen + exthdrlen,
                                flags, ipc6, sockc);
        if (err) {
-               __ip6_flush_pending_frames(sk, &queue, &cork, &v6_cork);
+               __ip6_flush_pending_frames(sk, &queue, cork, &v6_cork);
                return ERR_PTR(err);
        }
 
-       return __ip6_make_skb(sk, &queue, &cork, &v6_cork);
+       return __ip6_make_skb(sk, &queue, cork, &v6_cork);
 }
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 4ec76a87aeb8..824797f8d1ab 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -1324,12 +1324,13 @@ int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, 
size_t len)
 
        /* Lockless fast path for the non-corking case */
        if (!corkreq) {
+               struct inet_cork_full cork;
                struct sk_buff *skb;
 
                skb = ip6_make_skb(sk, getfrag, msg, ulen,
                                   sizeof(struct udphdr), &ipc6,
                                   &fl6, (struct rt6_info *)dst,
-                                  msg->msg_flags, &sockc);
+                                  msg->msg_flags, &cork, &sockc);
                err = PTR_ERR(skb);
                if (!IS_ERR_OR_NULL(skb))
                        err = udp_v6_send_skb(skb, &fl6);
-- 
2.17.0.484.g0c8726318c-goog

Reply via email to