aboutgitcodebugslistschat
path: root/udp_flow.c
diff options
context:
space:
mode:
authorDavid Gibson <david@gibson.dropbear.id.au>2024-09-06 15:17:06 +1000
committerStefano Brivio <sbrivio@redhat.com>2024-09-06 12:53:24 +0200
commit1166401c2f2b97961bdc285b336eed912b4f8bb1 (patch)
tree095cb89dbc43bcbb9680ec7a7fd85bfff0dffc32 /udp_flow.c
parent7ad9f9bd2bbda8d705e0c6faf5acf2792fce063c (diff)
downloadpasst-1166401c2f2b97961bdc285b336eed912b4f8bb1.tar
passt-1166401c2f2b97961bdc285b336eed912b4f8bb1.tar.gz
passt-1166401c2f2b97961bdc285b336eed912b4f8bb1.tar.bz2
passt-1166401c2f2b97961bdc285b336eed912b4f8bb1.tar.lz
passt-1166401c2f2b97961bdc285b336eed912b4f8bb1.tar.xz
passt-1166401c2f2b97961bdc285b336eed912b4f8bb1.tar.zst
passt-1166401c2f2b97961bdc285b336eed912b4f8bb1.zip
udp: Allow UDP flows to be prematurely closed
Unlike TCP, UDP has no in-band signalling for the end of a flow. So the only way we remove flows is on a timer if they have no activity for 180s. However, we've started to investigate some error conditions in which we want to prematurely abort / abandon a UDP flow. We can call udp_flow_close(), which will make the flow inert (sockets closed, no epoll events, can't be looked up in hash). However it will still wait 3 minutes to clear away the stale entry. Clean this up by adding an explicit 'closed' flag which will cause a flow to be more promptly cleaned up. We also publish udp_flow_close() so it can be called from other places to abort UDP flows(). Signed-off-by: David Gibson <david@gibson.dropbear.id.au> Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
Diffstat (limited to 'udp_flow.c')
-rw-r--r--udp_flow.c18
1 files changed, 17 insertions, 1 deletions
diff --git a/udp_flow.c b/udp_flow.c
index 1ff59a9..b81be2c 100644
--- a/udp_flow.c
+++ b/udp_flow.c
@@ -39,8 +39,11 @@ struct udp_flow *udp_at_sidx(flow_sidx_t sidx)
* @c: Execution context
* @uflow: UDP flow
*/
-static void udp_flow_close(const struct ctx *c, struct udp_flow *uflow)
+void udp_flow_close(const struct ctx *c, struct udp_flow *uflow)
{
+ if (uflow->closed)
+ return; /* Nothing to do */
+
if (uflow->s[INISIDE] >= 0) {
/* The listening socket needs to stay in epoll */
close(uflow->s[INISIDE]);
@@ -56,6 +59,8 @@ static void udp_flow_close(const struct ctx *c, struct udp_flow *uflow)
flow_hash_remove(c, FLOW_SIDX(uflow, INISIDE));
if (!pif_is_socket(uflow->f.pif[TGTSIDE]))
flow_hash_remove(c, FLOW_SIDX(uflow, TGTSIDE));
+
+ uflow->closed = true;
}
/**
@@ -257,6 +262,17 @@ flow_sidx_t udp_flow_from_tap(const struct ctx *c,
}
/**
+ * udp_flow_defer() - Deferred per-flow handling (clean up aborted flows)
+ * @uflow: Flow to handle
+ *
+ * Return: true if the connection is ready to free, false otherwise
+ */
+bool udp_flow_defer(const struct udp_flow *uflow)
+{
+ return uflow->closed;
+}
+
+/**
* udp_flow_timer() - Handler for timed events related to a given flow
* @c: Execution context
* @uflow: UDP flow