mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-04 04:04:19 +00:00
udp: expose inet cork to udp
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 <willemb@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
a9537c937c
commit
1cd7884dfd
@ -171,7 +171,7 @@ struct sk_buff *ip_make_skb(struct sock *sk, struct flowi4 *fl4,
|
|||||||
int len, int odd, struct sk_buff *skb),
|
int len, int odd, struct sk_buff *skb),
|
||||||
void *from, int length, int transhdrlen,
|
void *from, int length, int transhdrlen,
|
||||||
struct ipcm_cookie *ipc, struct rtable **rtp,
|
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)
|
static inline struct sk_buff *ip_finish_skb(struct sock *sk, struct flowi4 *fl4)
|
||||||
{
|
{
|
||||||
|
@ -950,6 +950,7 @@ struct sk_buff *ip6_make_skb(struct sock *sk,
|
|||||||
void *from, int length, int transhdrlen,
|
void *from, int length, int transhdrlen,
|
||||||
struct ipcm6_cookie *ipc6, struct flowi6 *fl6,
|
struct ipcm6_cookie *ipc6, struct flowi6 *fl6,
|
||||||
struct rt6_info *rt, unsigned int flags,
|
struct rt6_info *rt, unsigned int flags,
|
||||||
|
struct inet_cork_full *cork,
|
||||||
const struct sockcm_cookie *sockc);
|
const struct sockcm_cookie *sockc);
|
||||||
|
|
||||||
static inline struct sk_buff *ip6_finish_skb(struct sock *sk)
|
static inline struct sk_buff *ip6_finish_skb(struct sock *sk)
|
||||||
|
@ -1470,9 +1470,8 @@ struct sk_buff *ip_make_skb(struct sock *sk,
|
|||||||
int len, int odd, struct sk_buff *skb),
|
int len, int odd, struct sk_buff *skb),
|
||||||
void *from, int length, int transhdrlen,
|
void *from, int length, int transhdrlen,
|
||||||
struct ipcm_cookie *ipc, struct rtable **rtp,
|
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;
|
struct sk_buff_head queue;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
@ -1481,22 +1480,22 @@ struct sk_buff *ip_make_skb(struct sock *sk,
|
|||||||
|
|
||||||
__skb_queue_head_init(&queue);
|
__skb_queue_head_init(&queue);
|
||||||
|
|
||||||
cork.flags = 0;
|
cork->flags = 0;
|
||||||
cork.addr = 0;
|
cork->addr = 0;
|
||||||
cork.opt = NULL;
|
cork->opt = NULL;
|
||||||
err = ip_setup_cork(sk, &cork, ipc, rtp);
|
err = ip_setup_cork(sk, cork, ipc, rtp);
|
||||||
if (err)
|
if (err)
|
||||||
return ERR_PTR(err);
|
return ERR_PTR(err);
|
||||||
|
|
||||||
err = __ip_append_data(sk, fl4, &queue, &cork,
|
err = __ip_append_data(sk, fl4, &queue, cork,
|
||||||
¤t->task_frag, getfrag,
|
¤t->task_frag, getfrag,
|
||||||
from, length, transhdrlen, flags);
|
from, length, transhdrlen, flags);
|
||||||
if (err) {
|
if (err) {
|
||||||
__ip_flush_pending_frames(sk, &queue, &cork);
|
__ip_flush_pending_frames(sk, &queue, cork);
|
||||||
return ERR_PTR(err);
|
return ERR_PTR(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
return __ip_make_skb(sk, fl4, &queue, &cork);
|
return __ip_make_skb(sk, fl4, &queue, cork);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1030,9 +1030,11 @@ int udp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
|
|||||||
|
|
||||||
/* Lockless fast path for the non-corking case. */
|
/* Lockless fast path for the non-corking case. */
|
||||||
if (!corkreq) {
|
if (!corkreq) {
|
||||||
|
struct inet_cork cork;
|
||||||
|
|
||||||
skb = ip_make_skb(sk, fl4, getfrag, msg, ulen,
|
skb = ip_make_skb(sk, fl4, getfrag, msg, ulen,
|
||||||
sizeof(struct udphdr), &ipc, &rt,
|
sizeof(struct udphdr), &ipc, &rt,
|
||||||
msg->msg_flags);
|
&cork, msg->msg_flags);
|
||||||
err = PTR_ERR(skb);
|
err = PTR_ERR(skb);
|
||||||
if (!IS_ERR_OR_NULL(skb))
|
if (!IS_ERR_OR_NULL(skb))
|
||||||
err = udp_send_skb(skb, fl4);
|
err = udp_send_skb(skb, fl4);
|
||||||
|
@ -1755,9 +1755,9 @@ struct sk_buff *ip6_make_skb(struct sock *sk,
|
|||||||
void *from, int length, int transhdrlen,
|
void *from, int length, int transhdrlen,
|
||||||
struct ipcm6_cookie *ipc6, struct flowi6 *fl6,
|
struct ipcm6_cookie *ipc6, struct flowi6 *fl6,
|
||||||
struct rt6_info *rt, unsigned int flags,
|
struct rt6_info *rt, unsigned int flags,
|
||||||
|
struct inet_cork_full *cork,
|
||||||
const struct sockcm_cookie *sockc)
|
const struct sockcm_cookie *sockc)
|
||||||
{
|
{
|
||||||
struct inet_cork_full cork;
|
|
||||||
struct inet6_cork v6_cork;
|
struct inet6_cork v6_cork;
|
||||||
struct sk_buff_head queue;
|
struct sk_buff_head queue;
|
||||||
int exthdrlen = (ipc6->opt ? ipc6->opt->opt_flen : 0);
|
int exthdrlen = (ipc6->opt ? ipc6->opt->opt_flen : 0);
|
||||||
@ -1768,27 +1768,27 @@ struct sk_buff *ip6_make_skb(struct sock *sk,
|
|||||||
|
|
||||||
__skb_queue_head_init(&queue);
|
__skb_queue_head_init(&queue);
|
||||||
|
|
||||||
cork.base.flags = 0;
|
cork->base.flags = 0;
|
||||||
cork.base.addr = 0;
|
cork->base.addr = 0;
|
||||||
cork.base.opt = NULL;
|
cork->base.opt = NULL;
|
||||||
cork.base.dst = NULL;
|
cork->base.dst = NULL;
|
||||||
v6_cork.opt = 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) {
|
if (err) {
|
||||||
ip6_cork_release(&cork, &v6_cork);
|
ip6_cork_release(cork, &v6_cork);
|
||||||
return ERR_PTR(err);
|
return ERR_PTR(err);
|
||||||
}
|
}
|
||||||
if (ipc6->dontfrag < 0)
|
if (ipc6->dontfrag < 0)
|
||||||
ipc6->dontfrag = inet6_sk(sk)->dontfrag;
|
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,
|
||||||
¤t->task_frag, getfrag, from,
|
¤t->task_frag, getfrag, from,
|
||||||
length + exthdrlen, transhdrlen + exthdrlen,
|
length + exthdrlen, transhdrlen + exthdrlen,
|
||||||
flags, ipc6, sockc);
|
flags, ipc6, sockc);
|
||||||
if (err) {
|
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 ERR_PTR(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
return __ip6_make_skb(sk, &queue, &cork, &v6_cork);
|
return __ip6_make_skb(sk, &queue, cork, &v6_cork);
|
||||||
}
|
}
|
||||||
|
@ -1324,12 +1324,13 @@ int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
|
|||||||
|
|
||||||
/* Lockless fast path for the non-corking case */
|
/* Lockless fast path for the non-corking case */
|
||||||
if (!corkreq) {
|
if (!corkreq) {
|
||||||
|
struct inet_cork_full cork;
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
|
|
||||||
skb = ip6_make_skb(sk, getfrag, msg, ulen,
|
skb = ip6_make_skb(sk, getfrag, msg, ulen,
|
||||||
sizeof(struct udphdr), &ipc6,
|
sizeof(struct udphdr), &ipc6,
|
||||||
&fl6, (struct rt6_info *)dst,
|
&fl6, (struct rt6_info *)dst,
|
||||||
msg->msg_flags, &sockc);
|
msg->msg_flags, &cork, &sockc);
|
||||||
err = PTR_ERR(skb);
|
err = PTR_ERR(skb);
|
||||||
if (!IS_ERR_OR_NULL(skb))
|
if (!IS_ERR_OR_NULL(skb))
|
||||||
err = udp_v6_send_skb(skb, &fl6);
|
err = udp_v6_send_skb(skb, &fl6);
|
||||||
|
Loading…
Reference in New Issue
Block a user