[RFC 03/12] net/udp: add support msgdr::msg_ubuf
flat view
From: Pavel Begunkov <asml.silence@gmail.com>
Date: 2021-11-30 15:21:08
Also in:
io-uring, lkml
Subsystem:
networking [general], networking [ipv4/ipv6], the rest, user datagram protocol (udp) · Maintainers:
"David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, David Ahern, Ido Schimmel, Linus Torvalds, Willem de Bruijn
Make ipv4/udp to use ubuf_info passed in struct msghdr if it was specified. Signed-off-by: Pavel Begunkov <asml.silence@gmail.com> --- include/net/ip.h | 3 ++- net/ipv4/ip_output.c | 31 ++++++++++++++++++++++++------- net/ipv4/udp.c | 2 +- 3 files changed, 27 insertions(+), 9 deletions(-)
diff --git a/include/net/ip.h b/include/net/ip.h
index b71e88507c4a..e9c61b83a770 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h@@ -232,7 +232,8 @@ 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, - struct inet_cork *cork, unsigned int flags); + struct inet_cork *cork, unsigned int flags, + struct ubuf_info *uarg); int ip_queue_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl);
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 9bca57ef8b83..f9aab355d283 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c@@ -948,10 +948,10 @@ static int __ip_append_data(struct sock *sk, int getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb), void *from, int length, int transhdrlen, - unsigned int flags) + unsigned int flags, + struct ubuf_info *uarg) { struct inet_sock *inet = inet_sk(sk); - struct ubuf_info *uarg = NULL; struct sk_buff *skb; struct ip_options *opt = cork->opt;
@@ -967,6 +967,7 @@ static int __ip_append_data(struct sock *sk, unsigned int wmem_alloc_delta = 0; bool paged, extra_uref = false; u32 tskey = 0; + bool zc = false; skb = skb_peek_tail(queue);
@@ -1001,7 +1002,21 @@ static int __ip_append_data(struct sock *sk, (!exthdrlen || (rt->dst.dev->features & NETIF_F_HW_ESP_TX_CSUM))) csummode = CHECKSUM_PARTIAL; - if (flags & MSG_ZEROCOPY && length && sock_flag(sk, SOCK_ZEROCOPY)) { + if (uarg) { + if (skb_zcopy(skb) && uarg != skb_zcopy(skb)) + return -EINVAL; + + /* If it's not zerocopy, just drop uarg, the caller should + * be able to handle it. + */ + if (rt->dst.dev->features & NETIF_F_SG && + csummode == CHECKSUM_PARTIAL) { + paged = true; + zc = true; + } else { + uarg = NULL; + } + } else if (flags & MSG_ZEROCOPY && length && sock_flag(sk, SOCK_ZEROCOPY)) { uarg = msg_zerocopy_realloc(sk, length, skb_zcopy(skb)); if (!uarg) return -ENOBUFS;
@@ -1009,6 +1024,7 @@ static int __ip_append_data(struct sock *sk, if (rt->dst.dev->features & NETIF_F_SG && csummode == CHECKSUM_PARTIAL) { paged = true; + zc = true; } else { uarg->zerocopy = 0; skb_zcopy_set(skb, uarg, &extra_uref);
@@ -1172,7 +1188,7 @@ static int __ip_append_data(struct sock *sk, err = -EFAULT; goto error; } - } else if (!uarg || !uarg->zerocopy) { + } else if (!zc) { int i = skb_shinfo(skb)->nr_frags; err = -ENOMEM;
@@ -1309,7 +1325,7 @@ int ip_append_data(struct sock *sk, struct flowi4 *fl4, return __ip_append_data(sk, fl4, &sk->sk_write_queue, &inet->cork.base, sk_page_frag(sk), getfrag, - from, length, transhdrlen, flags); + from, length, transhdrlen, flags, NULL); } ssize_t ip_append_page(struct sock *sk, struct flowi4 *fl4, struct page *page,
@@ -1601,7 +1617,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, - struct inet_cork *cork, unsigned int flags) + struct inet_cork *cork, unsigned int flags, + struct ubuf_info *uarg) { struct sk_buff_head queue; int err;
@@ -1620,7 +1637,7 @@ struct sk_buff *ip_make_skb(struct sock *sk, err = __ip_append_data(sk, fl4, &queue, cork, ¤t->task_frag, getfrag, - from, length, transhdrlen, flags); + from, length, transhdrlen, flags, uarg); if (err) { __ip_flush_pending_frames(sk, &queue, cork); return ERR_PTR(err);
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 8bcecdd6aeda..8c514bff48d4 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c@@ -1247,7 +1247,7 @@ int udp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) skb = ip_make_skb(sk, fl4, getfrag, msg, ulen, sizeof(struct udphdr), &ipc, &rt, - &cork, msg->msg_flags); + &cork, msg->msg_flags, msg->msg_ubuf); err = PTR_ERR(skb); if (!IS_ERR_OR_NULL(skb)) err = udp_send_skb(skb, fl4, &cork);
--
2.34.0