From 52b260bae45967953c7b12e43ea8f940fc0b6d07 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Mon, 21 Aug 2023 11:55:42 +0200 Subject: [PATCH] MINOR: server/ssl: maintain an index of the last known valid SSL session When a thread creates a new session for a server, if none was known yet, we assign the thread id (hence the reused_sess index) to a shared variable so that other threads will later be able to find it when they don't have one yet. For now we only set and clear the pointer upon session creation, we do not yet pick it. Note that we could have done it per thread-group, so as to avoid any cross-thread exchanges, but it's anticipated that this is essentially used during startup, at a moment where the cost of inter-thread contention is very low compared to the ability to restart at full speed, which explains why instead we store a single entry. --- include/haproxy/server-t.h | 1 + src/ssl_sock.c | 15 +++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/include/haproxy/server-t.h b/include/haproxy/server-t.h index 068d56d21..03f6899a9 100644 --- a/include/haproxy/server-t.h +++ b/include/haproxy/server-t.h @@ -390,6 +390,7 @@ struct server { char *sni; /* SNI used for the session */ __decl_thread(HA_RWLOCK_T sess_lock); } * reused_sess; + uint last_ssl_sess_tid; /* last tid+1 having updated reused_sess (0=none, >0=tid+1) */ struct ckch_inst *inst; /* Instance of the ckch_store in which the certificate was loaded (might be null if server has no certificate) */ __decl_thread(HA_RWLOCK_T lock); /* lock the cache and SSL_CTX during commit operations */ diff --git a/src/ssl_sock.c b/src/ssl_sock.c index 4aae83b23..679ae2e78 100644 --- a/src/ssl_sock.c +++ b/src/ssl_sock.c @@ -4261,6 +4261,7 @@ static int ssl_sess_new_srv_cb(SSL *ssl, SSL_SESSION *sess) { struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index); struct server *s; + uint old_tid; s = __objt_server(conn->target); @@ -4306,6 +4307,16 @@ static int ssl_sess_new_srv_cb(SSL *ssl, SSL_SESSION *sess) /* done updating the session */ + /* Now we'll try to add or remove this entry as a valid one: + * - if no entry is set and we have one, let's share it + * - if our entry was set and we have no more, let's clear it + */ + old_tid = HA_ATOMIC_LOAD(&s->ssl_ctx.last_ssl_sess_tid); // 0=none, >0 = tid + 1 + if (!s->ssl_ctx.reused_sess[tid].ptr && old_tid == tid + 1) + HA_ATOMIC_CAS(&s->ssl_ctx.last_ssl_sess_tid, &old_tid, 0); // no more valid + else if (s->ssl_ctx.reused_sess[tid].ptr && !old_tid) + HA_ATOMIC_CAS(&s->ssl_ctx.last_ssl_sess_tid, &old_tid, tid + 1); + if (s->ssl_ctx.reused_sess[tid].sni) { /* if the new sni is empty or isn' t the same as the old one */ if ((!sni) || strcmp(s->ssl_ctx.reused_sess[tid].sni, sni) != 0) { @@ -4328,6 +4339,10 @@ static int ssl_sess_new_srv_cb(SSL *ssl, SSL_SESSION *sess) HA_RWLOCK_WRUNLOCK(SSL_SERVER_LOCK, &s->ssl_ctx.reused_sess[tid].sess_lock); } + old_tid = HA_ATOMIC_LOAD(&s->ssl_ctx.last_ssl_sess_tid); // 0=none, >0 = tid + 1 + if (old_tid == tid + 1) + HA_ATOMIC_CAS(&s->ssl_ctx.last_ssl_sess_tid, &old_tid, 0); // no more valid + HA_RWLOCK_RDUNLOCK(SSL_SERVER_LOCK, &s->ssl_ctx.lock); }