Download raw body.
limit softnet threads to number of cpu
Hi,
Currently always 8 softnet threads are startet, but only up to
number of CPU are used. I would like to remove useless threads.
Problem is that softnet tasks must be initialized before autoconf
is running. Drivers need them to attach queues. But number of CPU
is known only after autoconf has discovert them.
So I split the code into softnet_init() and softnet_percpu(). The
latter removes task queues that are not needed. Threads have not
been created yet.
I have a follow up diff that pins softnet threads to specific CPU.
But that needs more testing. I would like to commit this thread
handling diff first.
ok?
bluhm
Index: kern/init_main.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/kern/init_main.c,v
diff -u -p -r1.329 init_main.c
--- kern/init_main.c 9 Jun 2025 10:57:46 -0000 1.329
+++ kern/init_main.c 2 Aug 2025 17:13:11 -0000
@@ -328,6 +328,7 @@ main(void *framep)
/* Initialize the interface/address trees */
ifinit();
+ softnet_init();
/* Lock the kernel on behalf of proc0. */
KERNEL_LOCK();
@@ -345,6 +346,9 @@ main(void *framep)
/* Per CPU memory allocation */
percpu_init();
+
+ /* Reduce softnet threads to number of CPU */
+ softnet_percpu();
/* Initialize the file systems. */
#if defined(NFSSERVER) || defined(NFSCLIENT)
Index: net/if.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/net/if.c,v
diff -u -p -r1.740 if.c
--- net/if.c 21 Jul 2025 20:36:41 -0000 1.740
+++ net/if.c 2 Aug 2025 17:14:51 -0000
@@ -237,7 +237,11 @@ struct softnet {
struct taskq *sn_taskq;
struct netstack sn_netstack;
} __aligned(64);
+#ifdef MULTIPROCESSOR
#define NET_TASKQ 8
+#else
+#define NET_TASKQ 1
+#endif
struct softnet softnets[NET_TASKQ];
struct task if_input_task_locked = TASK_INITIALIZER(if_netisr, NULL);
@@ -255,16 +259,22 @@ struct rwlock netlock = RWLOCK_INITIALIZ
void
ifinit(void)
{
- unsigned int i;
-
/*
* most machines boot with 4 or 5 interfaces, so size the initial map
* to accommodate this
*/
if_idxmap_init(8); /* 8 is a nice power of 2 for malloc */
+}
+void
+softnet_init(void)
+{
+ unsigned int i;
+
+ /* Number of CPU is unknown, but driver attach needs softnet tasks. */
for (i = 0; i < NET_TASKQ; i++) {
struct softnet *sn = &softnets[i];
+
snprintf(sn->sn_name, sizeof(sn->sn_name), "softnet%u", i);
sn->sn_taskq = taskq_create(sn->sn_name, 1, IPL_NET,
TASKQ_MPSAFE);
@@ -273,6 +283,31 @@ ifinit(void)
}
}
+#ifdef MULTIPROCESSOR
+
+void
+softnet_percpu(void)
+{
+ unsigned int i;
+
+ /* After attaching all CPUs and interfaces, remove useless threads. */
+ for (i = softnet_count(); i < NET_TASKQ; i++) {
+ struct softnet *sn = &softnets[i];
+
+ taskq_destroy(sn->sn_taskq);
+ sn->sn_taskq = NULL;
+ }
+}
+
+#else /* MULTIPROCESSOR */
+
+void
+softnet_percpu(void)
+{
+}
+
+#endif /* MULTIPROCESSOR */
+
static struct if_idxmap if_idxmap;
/*
@@ -3642,10 +3677,10 @@ unhandled_af(int af)
panic("unhandled af %d", af);
}
-int
-net_sn_count(void)
+unsigned int
+softnet_count(void)
{
- static int nsoftnets;
+ static unsigned int nsoftnets;
if (nsoftnets == 0)
nsoftnets = min(NET_TASKQ, ncpus);
@@ -3656,7 +3691,7 @@ net_sn_count(void)
struct softnet *
net_sn(unsigned int ifindex)
{
- return (&softnets[ifindex % net_sn_count()]);
+ return (&softnets[ifindex % softnet_count()]);
}
struct taskq *
@@ -3672,7 +3707,7 @@ net_tq_barriers(const char *wmesg)
struct refcnt r = REFCNT_INITIALIZER();
int i;
- for (i = 0; i < nitems(barriers); i++) {
+ for (i = 0; i < softnet_count(); i++) {
task_set(&barriers[i], (void (*)(void *))refcnt_rele_wake, &r);
refcnt_take(&r);
task_add(softnets[i].sn_taskq, &barriers[i]);
Index: net/if.h
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/net/if.h,v
diff -u -p -r1.220 if.h
--- net/if.h 19 Jul 2025 16:40:40 -0000 1.220
+++ net/if.h 2 Aug 2025 17:13:11 -0000
@@ -561,10 +561,13 @@ void if_congestion(void);
int if_congested(void);
__dead void unhandled_af(int);
int if_setlladdr(struct ifnet *, const uint8_t *);
+void softnet_init(void);
+void softnet_percpu(void);
+unsigned int
+ softnet_count(void);
struct taskq *
net_tq(unsigned int);
void net_tq_barriers(const char *);
-int net_sn_count(void);
#endif /* _KERNEL */
Index: net/if_loop.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/net/if_loop.c,v
diff -u -p -r1.102 if_loop.c
--- net/if_loop.c 7 Jul 2025 02:28:50 -0000 1.102
+++ net/if_loop.c 2 Aug 2025 17:13:11 -0000
@@ -178,8 +178,8 @@ loop_clone_create(struct if_clone *ifc,
rtable_l2set(0, 0, ifp->if_index);
} else
if_attach(ifp);
- if_attach_queues(ifp, net_sn_count());
- if_attach_iqueues(ifp, net_sn_count());
+ if_attach_queues(ifp, softnet_count());
+ if_attach_iqueues(ifp, softnet_count());
if_alloc_sadl(ifp);
#if NBPFILTER > 0
bpfattach(&ifp->if_bpf, ifp, DLT_LOOP, sizeof(u_int32_t));
limit softnet threads to number of cpu