From 7fa78220cb67b4b185aa31fae382ffeb5d4b0cec Mon Sep 17 00:00:00 2001
From: Libor Peltan <libor.peltan@nic.cz>
Date: Thu, 4 Nov 2021 11:47:39 +0100
Subject: [PATCH] xdp-tcp: remove conn from table immediately, free later

---
 src/libknot/xdp/tcp.c | 32 +++++++++++++++++++++++++++-----
 1 file changed, 27 insertions(+), 5 deletions(-)

diff --git a/src/libknot/xdp/tcp.c b/src/libknot/xdp/tcp.c
index 8723966e57..e771e54350 100644
--- a/src/libknot/xdp/tcp.c
+++ b/src/libknot/xdp/tcp.c
@@ -132,18 +132,36 @@ static knot_tcp_conn_t **tcp_table_re_lookup(knot_tcp_conn_t *conn,
 	return res;
 }
 
-static void tcp_table_del_conn(knot_tcp_conn_t **todel)
+static void del_conn(knot_tcp_conn_t *conn)
 {
-	knot_tcp_conn_t *conn = *todel;
 	if (conn != NULL) {
-		*todel = conn->next; // remove from conn-table linked list
-		rem_node(tcp_conn_node(conn)); // remove from timeout double-linked list
 		free(conn->inbuf.iov_base);
 		free(conn->outbufs.bufs);
 		free(conn);
 	}
 }
 
+static void tcp_table_remove_conn(knot_tcp_conn_t **todel)
+{
+	rem_node(tcp_conn_node(*todel)); // remove from timeout double-linked list
+	*todel = (*todel)->next; // remove from conn-table linked list
+}
+
+static void tcp_table_del_conn(knot_tcp_conn_t **todel)
+{
+	knot_tcp_conn_t *conn = *todel;
+	tcp_table_remove_conn(todel);
+	del_conn(conn);
+}
+
+static void tcp_table_remove(knot_tcp_conn_t **todel, knot_tcp_table_t *table)
+{
+	assert(table->usage > 0);
+	table->inbufs_total -= (*todel)->inbuf.iov_len;
+	tcp_table_remove_conn(todel);
+	table->usage--;
+}
+
 static void tcp_table_del(knot_tcp_conn_t **todel, knot_tcp_table_t *table)
 {
 	assert(table->usage > 0);
@@ -334,12 +352,14 @@ int knot_tcp_recv(knot_tcp_relay_t *relays, knot_xdp_msg_t *msgs, uint32_t count
 					relay->auto_answer = KNOT_XDP_MSG_RST;
 					relay->auto_seqno = msg->ackno;
 					relay->del_from = pconn;
+					tcp_table_remove(pconn, tcp_table);
 				} // else ignore. It would be better and possible, but no big value for the price of CPU.
 			} else {
 				if (conn->state == XDP_TCP_CLOSING1) {
 					relay->action = XDP_TCP_CLOSE;
 					relay->auto_answer = KNOT_XDP_MSG_ACK;
 					relay->del_from = pconn;
+					tcp_table_remove(pconn, tcp_table);
 				} else if (msg->payload.iov_len == 0) { // otherwise ignore FIN
 					relay->action = XDP_TCP_CLOSE;
 					relay->auto_answer = KNOT_XDP_MSG_FIN | KNOT_XDP_MSG_ACK;
@@ -563,6 +583,7 @@ int knot_tcp_sweep(knot_tcp_table_t *tcp_table,
 		    (free_outbuf > 0 && tcp_outbufs_usage(&conn->outbufs) > 0)) {
 			rl->answer = XDP_TCP_RESET;
 			rl->del_from = tcp_table_re_lookup(conn, tcp_table);
+			tcp_table_remove(rl->del_from, tcp_table);
 
 			free_inbuf -= conn->inbuf.iov_len;
 			free_outbuf -= tcp_outbufs_usage(&conn->outbufs);
@@ -594,9 +615,10 @@ int knot_tcp_sweep(knot_tcp_table_t *tcp_table,
 _public_
 void knot_tcp_cleanup(knot_tcp_table_t *tcp_table, knot_tcp_relay_t *relays, size_t n_relays)
 {
+	(void)tcp_table;
 	for (uint32_t i = 0; i < n_relays; i++) {
 		if (relays[i].del_from != NULL) {
-			tcp_table_del(relays[i].del_from, tcp_table);
+			del_conn(relays[i].conn);
 		}
 		free(relays[i].inbufs);
 	}
-- 
GitLab