From a66e04338e2f13e7182e43f4b6964b941e4eb504 Mon Sep 17 00:00:00 2001 From: Amaury Denoyelle Date: Wed, 5 Apr 2023 18:16:28 +0200 Subject: [PATCH] MINOR: protocol: define new callback set_affinity Define a new protocol callback set_affinity. This function is used during listener_accept() to notify about a rebind on a new thread just before pushing the connection on the selected thread queue. If the callback fails, accept is done locally. This change will be useful for protocols with state allocated before accept is done. For the moment, only QUIC protocol is concerned. This will allow to rebind the quic_conn to a new thread depending on its load. This should be backported up to 2.7 after a period of observation. --- include/haproxy/protocol-t.h | 1 + src/listener.c | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/include/haproxy/protocol-t.h b/include/haproxy/protocol-t.h index b0765cf87..e49a239ce 100644 --- a/include/haproxy/protocol-t.h +++ b/include/haproxy/protocol-t.h @@ -113,6 +113,7 @@ struct protocol { void (*ignore_events)(struct connection *conn, int event_type); /* unsubscribe from socket events */ int (*get_src)(struct connection *conn, struct sockaddr *, socklen_t); /* retrieve connection's source address; -1=fail */ int (*get_dst)(struct connection *conn, struct sockaddr *, socklen_t); /* retrieve connection's dest address; -1=fail */ + int (*set_affinity)(struct connection *conn, int new_tid); /* functions acting on the receiver */ int (*rx_suspend)(struct receiver *rx); /* temporarily suspend this receiver for a soft restart */ diff --git a/src/listener.c b/src/listener.c index 5fe714ba5..07c7f92ea 100644 --- a/src/listener.c +++ b/src/listener.c @@ -1194,6 +1194,13 @@ void listener_accept(struct listener *l) t1 += (t2 << 16); } while (unlikely(!_HA_ATOMIC_CAS(&l->thr_idx, &t0, t1))); + if (l->rx.proto && l->rx.proto->set_affinity) { + if (l->rx.proto->set_affinity(cli_conn, base + t)) { + /* Failed migration, stay on the same thread. */ + goto local_accept; + } + } + /* We successfully selected the best thread "t" for this * connection. We use deferred accepts even if it's the * local thread because tests show that it's the best