Commit 9d5e619e19 for strongswan.org

commit 9d5e619e1914824eb6493834d40772e2e222be9a
Author: Tobias Brunner <tobias@strongswan.org>
Date:   Wed Jul 1 11:43:15 2026 +0200

    ha: Make receive buffer size for the HA socket configurable

    If there are lots of SAs to be synced, the default might be too low
    and messages and SAs get dropped.  The new default is already 8 MiB,
    which should work fine for lots of SAs.  The code mirrors the one in
    the kernel-netlink plugin (but with a guard around SO_RCVBUFFORCE, even
    though this plugin is mostly used on Linux as well).

diff --git a/conf/plugins/ha.opt b/conf/plugins/ha.opt
index 277987d5a8..6aa1421674 100644
--- a/conf/plugins/ha.opt
+++ b/conf/plugins/ha.opt
@@ -9,6 +9,17 @@ charon.plugins.ha.buflen = 2048
 	also transmitted so depending on the DH group the HA messages can get quite
 	big (the default should be fine up to _modp4096_).

+charon.plugins.ha.receive_buffer_size = 8388608
+	Maximum receive buffer size for the HA socket in bytes.
+
+	Maximum receive buffer size for the HA socket in bytes. This value controls
+	how many bytes of HA messages can be queued to the socket. If set to 0, the
+	default from `/proc/sys/net/core/rmem_default` will apply. Note that the
+	kernel doubles the configured value to account for overhead. To exceed the
+	system-wide maximum from `/proc/sys/net/core/rmem_max`, special privileges
+	(CAP_NET_ADMIN) are necessary, otherwise, the kernel silently caps the
+	value.
+
 charon.plugins.ha.fifo_interface = yes

 charon.plugins.ha.heartbeat_delay = 1000
diff --git a/src/libcharon/plugins/ha/ha_socket.c b/src/libcharon/plugins/ha/ha_socket.c
index a6373d8fd3..ec335d9d4f 100644
--- a/src/libcharon/plugins/ha/ha_socket.c
+++ b/src/libcharon/plugins/ha/ha_socket.c
@@ -28,6 +28,13 @@
 #include <threading/thread.h>
 #include <processing/jobs/callback_job.h>

+/**
+ * Default receive buffer size
+ */
+#ifndef HA_SOCKET_RCVBUF_DEFAULT
+#define HA_SOCKET_RCVBUF_DEFAULT (8 * 1024 * 1024)
+#endif
+
 typedef struct private_ha_socket_t private_ha_socket_t;

 /**
@@ -174,6 +181,8 @@ METHOD(ha_socket_t, pull, ha_message_t*,
  */
 static bool open_socket(private_ha_socket_t *this)
 {
+	int rcvbuf_size = 0;
+
 	this->fd = socket(this->local->get_family(this->local), SOCK_DGRAM, 0);
 	if (this->fd == -1)
 	{
@@ -189,6 +198,26 @@ static bool open_socket(private_ha_socket_t *this)
 		this->fd = -1;
 		return FALSE;
 	}
+
+	rcvbuf_size = lib->settings->get_int(lib->settings,
+										 "%s.plugins.ha.receive_buffer_size",
+										 HA_SOCKET_RCVBUF_DEFAULT, lib->ns);
+	if (rcvbuf_size)
+	{
+#ifdef SO_RCVBUFFORCE
+		if (setsockopt(this->fd, SOL_SOCKET, SO_RCVBUFFORCE, &rcvbuf_size,
+					   sizeof(rcvbuf_size)) == -1)
+#endif
+		{
+			if (setsockopt(this->fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf_size,
+						   sizeof(rcvbuf_size)) == -1)
+			{
+				DBG1(DBG_CFG, "failed to set receive buffer size to %d: %s",
+					 rcvbuf_size, strerror(errno));
+			}
+		}
+	}
+
 	if (connect(this->fd, this->remote->get_sockaddr(this->remote),
 				*this->remote->get_sockaddr_len(this->remote)) == -1)
 	{