udp_vu_sock_info() uses MSG_PEEK to look ahead at the next datagram to be received and gets its source address. Currently we only use it in the vhost-user path, but there's nothing inherently vhost-user specific about it. We have upcoming uses for it elsewhere so rename and move to udp.c. While we're there, polish its error reporting a litle. Signed-off-by: David Gibson <david(a)gibson.dropbear.id.au> --- udp.c | 25 +++++++++++++++++++++++++ udp_internal.h | 1 + udp_vu.c | 19 +------------------ 3 files changed, 27 insertions(+), 18 deletions(-) diff --git a/udp.c b/udp.c index 8125cfcb..6b72c30f 100644 --- a/udp.c +++ b/udp.c @@ -629,6 +629,31 @@ static int udp_sock_errs(const struct ctx *c, union epoll_ref ref) return n_err; } +/** + * udp_peek_addr() - Get source address for next packet + * @s: Socket to get information from + * @src: Socket address (output) + * + * Return: 0 on success, -1 otherwise + */ +int udp_peek_addr(int s, union sockaddr_inany *src) +{ + struct msghdr msg = { + .msg_name = src, + .msg_namelen = sizeof(*src), + }; + int rc; + + rc = recvmsg(s, &msg, MSG_PEEK | MSG_DONTWAIT); + if (rc < 0) { + if (errno != EAGAIN && errno != EWOULDBLOCK) + warn_perror("Error peeking at socket address"); + return rc; + } + return 0; +} + + /** * udp_sock_recv() - Receive datagrams from a socket * @c: Execution context diff --git a/udp_internal.h b/udp_internal.h index 02724e59..43a61094 100644 --- a/udp_internal.h +++ b/udp_internal.h @@ -30,5 +30,6 @@ size_t udp_update_hdr4(struct iphdr *ip4h, struct udp_payload_t *bp, size_t udp_update_hdr6(struct ipv6hdr *ip6h, struct udp_payload_t *bp, const struct flowside *toside, size_t dlen, bool no_udp_csum); +int udp_peek_addr(int s, union sockaddr_inany *src); #endif /* UDP_INTERNAL_H */ diff --git a/udp_vu.c b/udp_vu.c index 4153b6c1..5faf1e1d 100644 --- a/udp_vu.c +++ b/udp_vu.c @@ -57,23 +57,6 @@ static size_t udp_vu_hdrlen(bool v6) return hdrlen; } -/** - * udp_vu_sock_info() - get socket information - * @s: Socket to get information from - * @s_in: Socket address (output) - * - * Return: 0 if socket address can be read, -1 otherwise - */ -static int udp_vu_sock_info(int s, union sockaddr_inany *s_in) -{ - struct msghdr msg = { - .msg_name = s_in, - .msg_namelen = sizeof(union sockaddr_inany), - }; - - return recvmsg(s, &msg, MSG_PEEK | MSG_DONTWAIT); -} - /** * udp_vu_sock_recv() - Receive datagrams from socket into vhost-user buffers * @c: Execution context @@ -230,7 +213,7 @@ void udp_vu_listen_sock_data(const struct ctx *c, union epoll_ref ref, int iov_used; bool v6; - if (udp_vu_sock_info(ref.fd, &s_in) < 0) + if (udp_peek_addr(ref.fd, &s_in) < 0) break; sidx = udp_flow_from_sock(c, ref, &s_in, now); -- 2.49.0