diff options
author | David Gibson <david@gibson.dropbear.id.au> | 2025-04-01 19:57:09 +1100 |
---|---|---|
committer | Stefano Brivio <sbrivio@redhat.com> | 2025-04-02 11:30:26 +0200 |
commit | 76e554d9ec8dc80c1856621e17e45be811d198d0 (patch) | |
tree | d277e6e7ffd83de5f286ab80b9eb5bb261e750b4 | |
parent | 8aa2d90c8d95d0fa1dad7027fdf92b48a1bbf3c6 (diff) | |
download | passt-76e554d9ec8dc80c1856621e17e45be811d198d0.tar passt-76e554d9ec8dc80c1856621e17e45be811d198d0.tar.gz passt-76e554d9ec8dc80c1856621e17e45be811d198d0.tar.bz2 passt-76e554d9ec8dc80c1856621e17e45be811d198d0.tar.lz passt-76e554d9ec8dc80c1856621e17e45be811d198d0.tar.xz passt-76e554d9ec8dc80c1856621e17e45be811d198d0.tar.zst passt-76e554d9ec8dc80c1856621e17e45be811d198d0.zip |
udp: Simplify updates to UDP flow timestamp
Since UDP has no built in knowledge of connections, the only way we
know when we're done with a UDP flow is a timeout with no activity.
To keep track of this struct udp_flow includes a timestamp to record
the last time we saw traffic on the flow.
For data from listening sockets and from tap, this is done implicitly via
udp_flow_from_{sock,tap}() but for reply sockets it's done explicitly.
However, that logic is duplicated between the vhost-user and "buf" paths.
Make it common in udp_reply_sock_handler() instead.
Technically this is a behavioural change: previously if we got an EPOLLIN
event, but there wasn't actually any data we wouldn't update the timestamp,
now we will. This should be harmless: if there's an EPOLLIN we expect
there to be data, and even if there isn't the worst we can do is mildly
delay the cleanup of a stale flow.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
-rw-r--r-- | udp.c | 15 | ||||
-rw-r--r-- | udp_vu.c | 9 | ||||
-rw-r--r-- | udp_vu.h | 3 |
3 files changed, 8 insertions, 19 deletions
@@ -758,27 +758,21 @@ void udp_listen_sock_handler(const struct ctx *c, * @c: Execution context * @s: Socket to read data from * @tosidx: Flow & side to forward data from @s to - * @now: Current timestamp * * Return: true on success, false if can't forward from socket to flow's pif * * #syscalls recvmmsg */ static bool udp_buf_reply_sock_data(const struct ctx *c, - int s, flow_sidx_t tosidx, - const struct timespec *now) + int s, flow_sidx_t tosidx) { const struct flowside *toside = flowside_at_sidx(tosidx); - struct udp_flow *uflow = udp_at_sidx(tosidx); uint8_t topif = pif_at_sidx(tosidx); int n, i; if ((n = udp_sock_recv(c, s, udp_mh_recv)) <= 0) return true; - flow_trace(uflow, "Received %d datagrams on reply socket", n); - uflow->ts = now->tv_sec; - for (i = 0; i < n; i++) { if (pif_is_socket(topif)) udp_splice_prepare(udp_mh_recv, i); @@ -825,10 +819,13 @@ void udp_reply_sock_handler(const struct ctx *c, union epoll_ref ref, int s = ref.fd; bool ret; + flow_trace(uflow, "Received data on reply socket"); + uflow->ts = now->tv_sec; + if (c->mode == MODE_VU) - ret = udp_vu_reply_sock_data(c, s, tosidx, now); + ret = udp_vu_reply_sock_data(c, s, tosidx); else - ret = udp_buf_reply_sock_data(c, s, tosidx, now); + ret = udp_buf_reply_sock_data(c, s, tosidx); if (!ret) { flow_err(uflow, "Unable to forward UDP"); @@ -275,22 +275,17 @@ void udp_vu_listen_sock_data(const struct ctx *c, union epoll_ref ref, * @c: Execution context * @s: Socket to read data from * @tosidx: Flow & side to forward data from @s to - * @now: Current timestamp * * Return: true on success, false if can't forward from socket to flow's pif */ -bool udp_vu_reply_sock_data(const struct ctx *c, int s, flow_sidx_t tosidx, - const struct timespec *now) +bool udp_vu_reply_sock_data(const struct ctx *c, int s, flow_sidx_t tosidx) { const struct flowside *toside = flowside_at_sidx(tosidx); bool v6 = !(inany_v4(&toside->eaddr) && inany_v4(&toside->oaddr)); - struct udp_flow *uflow = udp_at_sidx(tosidx); struct vu_dev *vdev = c->vdev; struct vu_virtq *vq = &vdev->vq[VHOST_USER_RX_QUEUE]; int i; - ASSERT(uflow); - if (pif_at_sidx(tosidx) != PIF_TAP) return false; @@ -301,8 +296,6 @@ bool udp_vu_reply_sock_data(const struct ctx *c, int s, flow_sidx_t tosidx, iov_used = udp_vu_sock_recv(c, s, v6, &dlen); if (iov_used <= 0) break; - flow_trace(uflow, "Received 1 datagram on reply socket"); - uflow->ts = now->tv_sec; udp_vu_prepare(c, toside, dlen); if (*c->pcap) { @@ -8,7 +8,6 @@ void udp_vu_listen_sock_data(const struct ctx *c, union epoll_ref ref, const struct timespec *now); -bool udp_vu_reply_sock_data(const struct ctx *c, int s, flow_sidx_t tosidx, - const struct timespec *now); +bool udp_vu_reply_sock_data(const struct ctx *c, int s, flow_sidx_t tosidx); #endif /* UDP_VU_H */ |