This is an automated email from the ASF dual-hosted git repository.
xiaoxiang781216 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
The following commit(s) were added to refs/heads/master by this push:
new 0e22bd5bd98 net/mld: Fix njoins accounting for the all-nodes group
0e22bd5bd98 is described below
commit 0e22bd5bd985fa3665f67dd3d92a9d83c8b7d519
Author: zhangshuai39 <[email protected]>
AuthorDate: Wed Jun 18 17:13:32 2025 +0800
net/mld: Fix njoins accounting for the all-nodes group
mld_devinit() allocates the all-nodes group (ff02::1) via mld_grpalloc(),
which leaves njoins at zero. But this host is implicitly a member of that
group: it is joined there rather than through mld_joingroup(), and is never
left. An application that does an IPV6_JOIN_GROUP/IPV6_LEAVE_GROUP pair on
ff02::1 therefore takes the "existing group" path in mld_joingroup() with
njoins == 0, and on non-router builds trips
DEBUGASSERT(group->njoins > 0)
in mld_join.c. Without CONFIG_DEBUG_ASSERTIONS the subsequent leave
decrements njoins from 0 and underflows the uint8_t counter to 255.
Account for the implicit member in mld_devinit() instead of initializing
njoins in mld_grpalloc(). A group may be allocated either because this
host is joining it, or -- in the Router case -- because another node
reported a group that this host has not joined (mld_report() ->
mld_grpallocfind()). Only the caller knows which, so mld_grpalloc() keeps
njoins at zero and each caller accounts for its own local member. This
matters for the Router case: forcing njoins to 1 there would make
mld_joingroup() skip mld_group_startup() on the first local join, and leave
njoins stuck at 1 after the last local leave so the Done is never scheduled.
Note that a group created purely by a remote Report is still only released
when a local leave brings njoins to zero while members and lstmbrs are both
zero. Periodic reaping of such groups per RFC 3810 is a separate, existing
gap and is not addressed here.
Signed-off-by: zhangshuai39 <[email protected]>
---
net/mld/mld.h | 3 ++-
net/mld/mld_group.c | 6 ++++++
net/mld/mld_initialize.c | 14 +++++++++++++-
3 files changed, 21 insertions(+), 2 deletions(-)
diff --git a/net/mld/mld.h b/net/mld/mld.h
index 83537df235d..0e0c10ed327 100644
--- a/net/mld/mld.h
+++ b/net/mld/mld.h
@@ -286,7 +286,8 @@ int mld_done(FAR struct net_driver_s *dev,
* Name: mld_grpalloc
*
* Description:
- * Allocate a new group from heap memory.
+ * Allocate a new group from heap memory. The new group has njoins == 0;
+ * the caller must account for a local member, if any.
*
****************************************************************************/
diff --git a/net/mld/mld_group.c b/net/mld/mld_group.c
index 17cbc3d7e76..988f7263991 100644
--- a/net/mld/mld_group.c
+++ b/net/mld/mld_group.c
@@ -94,6 +94,12 @@ static int mld_ngroups(FAR struct net_driver_s *dev)
* Description:
* Allocate a new group from heap memory.
*
+ * The new group has njoins == 0, i.e. no member on this host. A group
+ * may be allocated either because this host is joining it, or (in the
+ * Router case) because another node reported a group that this host has
+ * not joined. Only the caller knows which, so the caller must account
+ * for any local member by setting njoins itself.
+ *
* Assumptions:
* The network is locked.
*
diff --git a/net/mld/mld_initialize.c b/net/mld/mld_initialize.c
index 592e4c48619..31186ddf5c7 100644
--- a/net/mld/mld_initialize.c
+++ b/net/mld/mld_initialize.c
@@ -54,6 +54,8 @@
void mld_devinit(struct net_driver_s *dev)
{
+ FAR struct mld_group_s *group;
+
mldinfo("MLD initializing dev %p\n", dev);
/* Initialize the MLD state in the device structure */
@@ -69,7 +71,17 @@ void mld_devinit(struct net_driver_s *dev)
* probably is not relevant here.
*/
- mld_grpalloc(dev, g_ipv6_allnodes);
+ group = mld_grpalloc(dev, g_ipv6_allnodes);
+ if (group != NULL)
+ {
+ /* This host is implicitly a member of the all-nodes group: it is
+ * joined here rather than via mld_joingroup() and is never left.
+ * Account for that member so that a join/leave pair on this group
+ * from the application does not underflow njoins.
+ */
+
+ group->njoins = 1;
+ }
/* Allow the MLD messages at the MAC level */