git: cba9f88105c2 - main - netinet6: embed struct mld_ifsoftc into struct in6_ifextra

From: Gleb Smirnoff <glebius_at_FreeBSD.org>
Date: Fri, 23 Jan 2026 22:36:43 UTC
The branch main has been updated by glebius:

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

commit cba9f88105c268f73fa2a92ca4479cc15b8a3338
Author:     Gleb Smirnoff <glebius@FreeBSD.org>
AuthorDate: 2026-01-23 22:18:12 +0000
Commit:     Gleb Smirnoff <glebius@FreeBSD.org>
CommitDate: 2026-01-23 22:18:12 +0000

    netinet6: embed struct mld_ifsoftc into struct in6_ifextra
    
    In mld_domifdetach() don't search the global list.
    
    Reviewed by:            tuexen
    Differential Revision:  https://reviews.freebsd.org/D54727
---
 sys/netinet6/in6.c       |  3 +--
 sys/netinet6/in6_var.h   | 16 +++++++++++++-
 sys/netinet6/ip6_input.c |  1 -
 sys/netinet6/mld6.c      | 54 ++++++++++++------------------------------------
 sys/netinet6/mld6_var.h  | 22 ++------------------
 5 files changed, 31 insertions(+), 65 deletions(-)

diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c
index 45a7256cfc9e..e1504400d55b 100644
--- a/sys/netinet6/in6.c
+++ b/sys/netinet6/in6.c
@@ -2613,11 +2613,10 @@ in6_ifarrival(void *arg __unused, struct ifnet *ifp)
 	COUNTER_ARRAY_ALLOC(ext->icmp6_ifstat,
 	    sizeof(struct icmp6_ifstat) / sizeof(uint64_t), M_WAITOK);
 	nd6_ifattach(ifp);
+	mld_domifattach(ifp);
 	scope6_ifattach(ifp);
 
 	ext->lltable = in6_lltattach(ifp);
-
-	ext->mld_ifinfo = mld_domifattach(ifp);
 }
 EVENTHANDLER_DEFINE(ifnet_arrival_event, in6_ifarrival, NULL,
     EVENTHANDLER_PRI_ANY);
diff --git a/sys/netinet6/in6_var.h b/sys/netinet6/in6_var.h
index a8ae343ffaed..894628b796d1 100644
--- a/sys/netinet6/in6_var.h
+++ b/sys/netinet6/in6_var.h
@@ -506,6 +506,21 @@ struct in6_ifextra {
 	u_int		nd_dad_failures;
 	uint8_t		nd_curhoplimit;
 
+	struct mld_ifsoftc {
+		/* Timers and invervals measured in seconds. */
+		LIST_ENTRY(mld_ifsoftc) mli_link;
+		struct ifnet *mli_ifp;  /* interface this instance belongs to */
+		uint32_t mli_version;   /* MLDv1 Host Compatibility Mode */
+		uint32_t mli_v1_timer;  /* MLDv1 Querier Present timer */
+		uint32_t mli_v2_timer;  /* MLDv2 General Query timer */
+		uint32_t mli_flags;     /* MLD per-interface flags */
+		uint32_t mli_rv;        /* MLDv2 Robustness Variable */
+		uint32_t mli_qi;        /* MLDv2 Query Interval */
+		uint32_t mli_qri;       /* MLDv2 Query Response Interval */
+		uint32_t mli_uri;       /* MLDv2 Unsolicited Report Interval */
+		struct mbufq     mli_gq; /* queue of general query responses */
+	} mld_ifsoftc;
+
 	struct scope6_id {
 		/*
 		 * 16 is correspondent to 4bit multicast scope field. i.e. from
@@ -516,7 +531,6 @@ struct in6_ifextra {
 	} scope6_id;
 
 	struct lltable *lltable;
-	struct mld_ifsoftc *mld_ifinfo;
 };
 
 #define	LLTABLE6(ifp)	((ifp)->if_inet6->lltable)
diff --git a/sys/netinet6/ip6_input.c b/sys/netinet6/ip6_input.c
index 62e03a189650..d914bfbcbdbf 100644
--- a/sys/netinet6/ip6_input.c
+++ b/sys/netinet6/ip6_input.c
@@ -390,7 +390,6 @@ ip6_destroy(void *unused __unused)
 		}
 		/* IF_ADDR_UNLOCK(ifp); */
 		in6_ifdetach_destroy(ifp);
-		mld_domifdetach(ifp);
 	}
 	IFNET_RUNLOCK();
 
diff --git a/sys/netinet6/mld6.c b/sys/netinet6/mld6.c
index 8e2bbf8adc01..f14d2c76ffda 100644
--- a/sys/netinet6/mld6.c
+++ b/sys/netinet6/mld6.c
@@ -99,7 +99,6 @@
 #define KTR_MLD KTR_INET6
 #endif
 
-static void	mli_delete_locked(struct ifnet *);
 static void	mld_dispatch_packet(struct mbuf *);
 static void	mld_dispatch_queue(struct mbufq *, int);
 static void	mld_final_leave(struct in6_multi *, struct mld_ifsoftc *);
@@ -465,21 +464,21 @@ mld_is_addr_reported(const struct in6_addr *addr)
  * Attach MLD when PF_INET6 is attached to an interface.  Assumes that the
  * current VNET is set by the caller.
  */
-struct mld_ifsoftc *
+void
 mld_domifattach(struct ifnet *ifp)
 {
-	struct mld_ifsoftc *mli;
+	struct mld_ifsoftc *mli = MLD_IFINFO(ifp);
 
 	CTR3(KTR_MLD, "%s: called for ifp %p(%s)", __func__, ifp, if_name(ifp));
 
-	mli = malloc(sizeof(struct mld_ifsoftc), M_MLD, M_WAITOK | M_ZERO);
-	mli->mli_ifp = ifp;
-	mli->mli_version = MLD_VERSION_2;
-	mli->mli_flags = 0;
-	mli->mli_rv = MLD_RV_INIT;
-	mli->mli_qi = MLD_QI_INIT;
-	mli->mli_qri = MLD_QRI_INIT;
-	mli->mli_uri = MLD_URI_INIT;
+	*mli = (struct mld_ifsoftc){
+		.mli_ifp = ifp,
+		.mli_version = MLD_VERSION_2,
+		.mli_rv = MLD_RV_INIT,
+		.mli_qi = MLD_QI_INIT,
+		.mli_qri = MLD_QRI_INIT,
+		.mli_uri = MLD_URI_INIT,
+	};
 	mbufq_init(&mli->mli_gq, MLD_MAX_RESPONSE_PACKETS);
 	if ((ifp->if_flags & IFF_MULTICAST) == 0)
 		mli->mli_flags |= MLIF_SILENT;
@@ -489,8 +488,6 @@ mld_domifattach(struct ifnet *ifp)
 	MLD_LOCK();
 	LIST_INSERT_HEAD(&V_mli_head, mli, mli_link);
 	MLD_UNLOCK();
-
-	return (mli);
 }
 
 /*
@@ -552,44 +549,19 @@ mld_ifdetach(struct ifnet *ifp, struct in6_multi_head *inmh)
 /*
  * Hook for domifdetach.
  * Runs after link-layer cleanup; free MLD state.
- *
- * SMPng: Normally called with LLTABLE_LOCK held.
  */
 void
 mld_domifdetach(struct ifnet *ifp)
 {
+	struct mld_ifsoftc *mli = MLD_IFINFO(ifp);
 
 	CTR3(KTR_MLD, "%s: called for ifp %p(%s)",
 	    __func__, ifp, if_name(ifp));
 
 	MLD_LOCK();
-	mli_delete_locked(ifp);
+	LIST_REMOVE(mli, mli_link);
 	MLD_UNLOCK();
-}
-
-static void
-mli_delete_locked(struct ifnet *ifp)
-{
-	struct mld_ifsoftc *mli, *tmli;
-
-	CTR3(KTR_MLD, "%s: freeing mld_ifsoftc for ifp %p(%s)",
-	    __func__, ifp, if_name(ifp));
-
-	MLD_LOCK_ASSERT();
-
-	LIST_FOREACH_SAFE(mli, &V_mli_head, mli_link, tmli) {
-		if (mli->mli_ifp == ifp) {
-			/*
-			 * Free deferred General Query responses.
-			 */
-			mbufq_drain(&mli->mli_gq);
-
-			LIST_REMOVE(mli, mli_link);
-
-			free(mli, M_MLD);
-			return;
-		}
-	}
+	mbufq_drain(&mli->mli_gq);
 }
 
 /*
diff --git a/sys/netinet6/mld6_var.h b/sys/netinet6/mld6_var.h
index d75ac2450c10..a063771f4dc8 100644
--- a/sys/netinet6/mld6_var.h
+++ b/sys/netinet6/mld6_var.h
@@ -120,23 +120,6 @@ struct mld_ifinfo {
 };
 
 #ifdef _KERNEL
-/*
- * Per-link MLD state.
- */
-struct mld_ifsoftc {
-	LIST_ENTRY(mld_ifsoftc) mli_link;
-	struct ifnet *mli_ifp;	/* interface this instance belongs to */
-	uint32_t mli_version;	/* MLDv1 Host Compatibility Mode */
-	uint32_t mli_v1_timer;	/* MLDv1 Querier Present timer (s) */
-	uint32_t mli_v2_timer;	/* MLDv2 General Query (interface) timer (s)*/
-	uint32_t mli_flags;	/* MLD per-interface flags */
-	uint32_t mli_rv;	/* MLDv2 Robustness Variable */
-	uint32_t mli_qi;	/* MLDv2 Query Interval (s) */
-	uint32_t mli_qri;	/* MLDv2 Query Response Interval (s) */
-	uint32_t mli_uri;	/* MLDv2 Unsolicited Report Interval (s) */
-	struct mbufq	 mli_gq;	/* queue of general query responses */
-};
-
 #define MLD_RANDOM_DELAY(X)		(arc4random() % (X) + 1)
 #define MLD_MAX_STATE_CHANGES		24 /* Max pending changes per group */
 
@@ -155,12 +138,11 @@ struct mld_ifsoftc {
 /*
  * Per-link MLD context.
  */
-#define MLD_IFINFO(ifp)	((ifp)->if_inet6->mld_ifinfo)
+#define MLD_IFINFO(ifp)	(&(ifp)->if_inet6->mld_ifsoftc)
 
 struct in6_multi_head;
 int	mld_change_state(struct in6_multi *, const int);
-struct mld_ifsoftc *
-	mld_domifattach(struct ifnet *);
+void	mld_domifattach(struct ifnet *);
 void	mld_domifdetach(struct ifnet *);
 void	mld_ifdetach(struct ifnet *, struct in6_multi_head *);
 int	mld_input(struct mbuf **, int, int);