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 */
 

Reply via email to