From a7a48f5146d9a1784c8e1febc229f309814efa11 Mon Sep 17 00:00:00 2001
From: David Carlier <[email protected]>
Date: Fri, 17 Dec 2021 17:21:10 +0000
Subject: [PATCH 2/3] MEDIUM: socket Add support for the new reuseportbpf
directive.
It's an option supported from Linux 4.6, we purposely deactivate by default
even if SO_REUSEPORT is on, it might be benefitial only in few chosen
kernel versions/hardware cases in the end.
Starting with a basic BPF socket filter, pulling the processor id explicitly,
it could be eventually expanded if needs arise.
---
src/sock_inet.c | 35 +++++++++++++++++++++++++++++++++--
1 file changed, 33 insertions(+), 2 deletions(-)
diff --git a/src/sock_inet.c b/src/sock_inet.c
index fa04dfed0..d8c50c0b5 100644
--- a/src/sock_inet.c
+++ b/src/sock_inet.c
@@ -335,8 +335,39 @@ int sock_inet_bind_receiver(struct receiver *rx, char **errmsg)
/* OpenBSD and Linux 3.9 support this. As it's present in old libc versions of
* Linux, it might return an error that we will silently ignore.
*/
- if (!ext && (global.tune.options & GTUNE_USE_REUSEPORT))
- setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one));
+ if (!ext && (global.tune.options & GTUNE_USE_REUSEPORT)) {
+ int ret __maybe_unused;
+ ret = setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one));
+#ifdef SO_ATTACH_REUSEPORT_CBPF
+ /* Linux 4.6 supports this to have a tigher control over the SO_REUSEPORT algorithm
+ * here an attempt to guarantee for the socket to be bound to a particular cpu
+ * rather than the actual round robin distribution.
+ *
+ * option disabled by default as this might not necessarily translate to nicer performances,
+ * would need broader tests on various configurations, while kernel support evolves, to push otherwise.
+ */
+ if (ret != -1 && (global.tune.options & GTUNE_USE_REUSEPORTBPF)) {
+ static struct sock_filter hacode[2] = {
+ /* processor cpu id into A */
+ { BPF_LD | BPF_W | BPF_ABS, 0, 0, (uint32_t)(SKF_AD_OFF + SKF_AD_CPU) },
+ /* It could have been broadened as below, but it is a configuration bit */
+ /* modulo threads */
+ /* { BPF_ALU | BPF_MOD, 0, 0, (uint32_t)(<nbthreads>) }, */
+ /* returns A */
+ { BPF_RET | BPF_A, 0, 0, 0 },
+ };
+ static struct sock_fprog haprog = {
+ .filter = hacode,
+ .len = (sizeof(hacode) / sizeof(hacode[0])),
+ };
+
+ if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_REUSEPORT_CBPF, &haprog, sizeof(haprog)) == -1) {
+ err |= ERR_FATAL | ERR_ALERT;
+ memprintf(errmsg, "cannot do reuseport bpf");
+ }
+ }
+#endif
+ }
#endif
if (!ext && (rx->settings->options & RX_O_FOREIGN)) {
--
2.32.0