git: b602ba1b5fd9 - main - net/iflib.c: move out scheduler-depended code into the hook

From: Konstantin Belousov <kib_at_FreeBSD.org>
Date: Thu, 29 Jan 2026 18:12:35 UTC
The branch main has been updated by kib:

URL: https://cgit.FreeBSD.org/src/commit/?id=b602ba1b5fd92bb226e32f5720885f856a5cb0bb

commit b602ba1b5fd92bb226e32f5720885f856a5cb0bb
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2026-01-22 13:38:20 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2026-01-29 18:11:56 +0000

    net/iflib.c: move out scheduler-depended code into the hook
    
    Add sched_find_l2_neighbor().  This really should be not
    scheduler-depended, in does not have anything to do with scheduler at
    all.  But for now keep the same code structure.
    
    Reviewed by:    olce
    Tested by:      pho
    Sponsored by:   The FreeBSD Foundation
    MFC after:      1 week
    Differential revision:  https://reviews.freebsd.org/D54831
---
 sys/kern/sched_4bsd.c |  7 +++++
 sys/kern/sched_shim.c |  1 +
 sys/kern/sched_ule.c  | 68 ++++++++++++++++++++++++++++++++++++++++++
 sys/net/iflib.c       | 82 ++-------------------------------------------------
 sys/sys/sched.h       |  8 +++++
 5 files changed, 87 insertions(+), 79 deletions(-)

diff --git a/sys/kern/sched_4bsd.c b/sys/kern/sched_4bsd.c
index 03e7b71d3fe6..11baf9d2bdfa 100644
--- a/sys/kern/sched_4bsd.c
+++ b/sys/kern/sched_4bsd.c
@@ -1854,6 +1854,12 @@ sched_4bsd_do_timer_accounting(void)
 #endif
 }
 
+static int
+sched_4bsd_find_l2_neighbor(int cpu)
+{
+	return (-1);
+}
+
 struct sched_instance sched_4bsd_instance = {
 #define	SLOT(name) .name = sched_4bsd_##name
 	SLOT(load),
@@ -1897,6 +1903,7 @@ struct sched_instance sched_4bsd_instance = {
 	SLOT(tdname),
 	SLOT(clear_tdname),
 	SLOT(do_timer_accounting),
+	SLOT(find_l2_neighbor),
 	SLOT(init),
 	SLOT(init_ap),
 	SLOT(setup),
diff --git a/sys/kern/sched_shim.c b/sys/kern/sched_shim.c
index d2f0b5749752..816d0b44bb52 100644
--- a/sys/kern/sched_shim.c
+++ b/sys/kern/sched_shim.c
@@ -94,6 +94,7 @@ DEFINE_SHIM0(sizeof_thread, int, sched_sizeof_thread)
 DEFINE_SHIM1(tdname, char *, sched_tdname, struct thread *, td)
 DEFINE_SHIM1(clear_tdname, void, sched_clear_tdname, struct thread *, td)
 DEFINE_SHIM0(do_timer_accounting, bool, sched_do_timer_accounting)
+DEFINE_SHIM1(find_l2_neighbor, int, sched_find_l2_neighbor, int, cpu)
 DEFINE_SHIM0(init_ap, void, schedinit_ap)
 
 static char sched_name[32] = "ULE";
diff --git a/sys/kern/sched_ule.c b/sys/kern/sched_ule.c
index 22257b2c0d7a..7a745619480d 100644
--- a/sys/kern/sched_ule.c
+++ b/sys/kern/sched_ule.c
@@ -3360,6 +3360,73 @@ sched_ule_do_timer_accounting(void)
 	return (true);
 }
 
+#ifdef SMP
+static int
+sched_ule_find_child_with_core(int cpu, struct cpu_group *grp)
+{
+	int i;
+
+	if (grp->cg_children == 0)
+		return (-1);
+
+	MPASS(grp->cg_child);
+	for (i = 0; i < grp->cg_children; i++) {
+		if (CPU_ISSET(cpu, &grp->cg_child[i].cg_mask))
+			return (i);
+	}
+
+	return (-1);
+}
+
+static int
+sched_ule_find_l2_neighbor(int cpu)
+{
+	struct cpu_group *grp;
+	int i;
+
+	grp = cpu_top;
+	if (grp == NULL)
+		return (-1);
+
+	/*
+	 * Find the smallest CPU group that contains the given core.
+	 */
+	i = 0;
+	while ((i = sched_ule_find_child_with_core(cpu, grp)) != -1) {
+		/*
+		 * If the smallest group containing the given CPU has less
+		 * than two members, we conclude the given CPU has no
+		 * L2 neighbor.
+		 */
+		if (grp->cg_child[i].cg_count <= 1)
+			return (-1);
+		grp = &grp->cg_child[i];
+	}
+
+	/* Must share L2. */
+	if (grp->cg_level > CG_SHARE_L2 || grp->cg_level == CG_SHARE_NONE)
+		return (-1);
+
+	/*
+	 * Select the first member of the set that isn't the reference
+	 * CPU, which at this point is guaranteed to exist.
+	 */
+	for (i = 0; i < CPU_SETSIZE; i++) {
+		if (CPU_ISSET(i, &grp->cg_mask) && i != cpu)
+			return (i);
+	}
+
+	/* Should never be reached */
+	return (-1);
+}
+#else
+static int
+sched_ule_find_l2_neighbor(int cpu)
+{
+	return (-1);
+}
+#endif
+
 struct sched_instance sched_ule_instance = {
 #define	SLOT(name) .name = sched_ule_##name
 	SLOT(load),
@@ -3403,6 +3470,7 @@ struct sched_instance sched_ule_instance = {
 	SLOT(tdname),
 	SLOT(clear_tdname),
 	SLOT(do_timer_accounting),
+	SLOT(find_l2_neighbor),
 	SLOT(init),
 	SLOT(init_ap),
 	SLOT(setup),
diff --git a/sys/net/iflib.c b/sys/net/iflib.c
index b0e4bb9470c9..8e2fd257ca74 100644
--- a/sys/net/iflib.c
+++ b/sys/net/iflib.c
@@ -29,7 +29,6 @@
 #include "opt_inet.h"
 #include "opt_inet6.h"
 #include "opt_acpi.h"
-#include "opt_sched.h"
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -40,8 +39,10 @@
 #include <sys/mutex.h>
 #include <sys/module.h>
 #include <sys/kobj.h>
+#include <sys/proc.h>
 #include <sys/rman.h>
 #include <sys/sbuf.h>
+#include <sys/sched.h>
 #include <sys/smp.h>
 #include <sys/socket.h>
 #include <sys/sockio.h>
@@ -4813,83 +4814,6 @@ cpuid_advance(if_ctx_t ctx, unsigned int cpuid, unsigned int n)
 	return (cpuid);
 }
 
-#if defined(SMP) && defined(SCHED_ULE)
-extern struct cpu_group *cpu_top;	/* CPU topology */
-
-static int
-find_child_with_core(int cpu, struct cpu_group *grp)
-{
-	int i;
-
-	if (grp->cg_children == 0)
-		return (-1);
-
-	MPASS(grp->cg_child);
-	for (i = 0; i < grp->cg_children; i++) {
-		if (CPU_ISSET(cpu, &grp->cg_child[i].cg_mask))
-			return (i);
-	}
-
-	return (-1);
-}
-
-
-/*
- * Find an L2 neighbor of the given CPU or return -1 if none found.  This
- * does not distinguish among multiple L2 neighbors if the given CPU has
- * more than one (it will always return the same result in that case).
- */
-static int
-find_l2_neighbor(int cpu)
-{
-	struct cpu_group *grp;
-	int i;
-
-	grp = cpu_top;
-	if (grp == NULL)
-		return (-1);
-
-	/*
-	 * Find the smallest CPU group that contains the given core.
-	 */
-	i = 0;
-	while ((i = find_child_with_core(cpu, grp)) != -1) {
-		/*
-		 * If the smallest group containing the given CPU has less
-		 * than two members, we conclude the given CPU has no
-		 * L2 neighbor.
-		 */
-		if (grp->cg_child[i].cg_count <= 1)
-			return (-1);
-		grp = &grp->cg_child[i];
-	}
-
-	/* Must share L2. */
-	if (grp->cg_level > CG_SHARE_L2 || grp->cg_level == CG_SHARE_NONE)
-		return (-1);
-
-	/*
-	 * Select the first member of the set that isn't the reference
-	 * CPU, which at this point is guaranteed to exist.
-	 */
-	for (i = 0; i < CPU_SETSIZE; i++) {
-		if (CPU_ISSET(i, &grp->cg_mask) && i != cpu)
-			return (i);
-	}
-
-	/* Should never be reached */
-	return (-1);
-}
-
-#else
-static int
-find_l2_neighbor(int cpu)
-{
-
-	return (-1);
-}
-#endif
-
 /*
  * CPU mapping behaviors
  * ---------------------
@@ -4942,7 +4866,7 @@ get_cpuid_for_queue(if_ctx_t ctx, unsigned int base_cpuid, unsigned int qid,
 			unsigned int rx_cpuid;
 
 			rx_cpuid = cpuid_advance(ctx, base_cpuid, qid);
-			l2_neighbor = find_l2_neighbor(rx_cpuid);
+			l2_neighbor = sched_find_l2_neighbor(rx_cpuid);
 			if (l2_neighbor != -1) {
 				return (l2_neighbor);
 			}
diff --git a/sys/sys/sched.h b/sys/sys/sched.h
index 9c78452432b4..3ba40fb191d3 100644
--- a/sys/sys/sched.h
+++ b/sys/sys/sched.h
@@ -243,6 +243,13 @@ void schedinit_ap(void);
 
 bool sched_do_timer_accounting(void);
 
+/*
+ * Find an L2 neighbor of the given CPU or return -1 if none found.  This
+ * does not distinguish among multiple L2 neighbors if the given CPU has
+ * more than one (it will always return the same result in that case).
+ */
+int sched_find_l2_neighbor(int cpu);
+
 struct sched_instance {
 	int	(*load)(void);
 	int	(*rr_interval)(void);
@@ -285,6 +292,7 @@ struct sched_instance {
 	char	*(*tdname)(struct thread *td);
 	void	(*clear_tdname)(struct thread *td);
 	bool	(*do_timer_accounting)(void);
+	int	(*find_l2_neighbor)(int cpuid);
 	void	(*init)(void);
 	void	(*init_ap)(void);
 	void	(*setup)(void);