diff --git a/conf/plugins/ha.opt b/conf/plugins/ha.opt index 277987d5a..6aa142167 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 a6373d8fd..ec335d9d4 100644 --- a/src/libcharon/plugins/ha/ha_socket.c +++ b/src/libcharon/plugins/ha/ha_socket.c @@ -28,6 +28,13 @@ #include #include +/** + * 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) {