Squashed commit of the following:

The MLD implementation did not follow the RFC correctly when it is the Querier.  The Querier should use a general query and get query messages from all members of all groups.  This would be driven by a single timer per sub-nset since all groups are queried at once. Instead, the design used a Multicast Address Specific Query with one timer per group and ignores groups that we are not members of.

    Similary, the MLDv1 compatibility timer should be a single, separate timer, not a per-group timer.

    net/mld: Group may be NULL when sending a general query
This commit is contained in:
Gregory Nutt
2018-11-11 11:38:29 -06:00
parent f14cf966c9
commit 8a3fc26b74
12 changed files with 564 additions and 368 deletions
+46 -19
View File
@@ -123,35 +123,45 @@
* Pre-processor Definitions
****************************************************************************/
/* Group flags */
/* Global flags */
#define MLD_QUERIER (1 << 0) /* Querier */
#define MLD_V1COMPAT (1 << 1) /* MLDv1 compatibility mode */
#define MLD_GENPEND (1 << 2) /* General query pending */
#define SET_MLD_QUERIER(f) do { (f) |= MLD_QUERIER; } while (0)
#define SET_MLD_V1COMPAT(f) do { (f) |= MLD_V1COMPAT; } while (0)
#define SET_MLD_GENPEND(f) do { (f) |= MLD_GENPEND; } while (0)
#define CLR_MLD_QUERIER(f) do { (f) &= ~MLD_QUERIER; } while (0)
#define CLR_MLD_V1COMPAT(f) do { (f) &= ~MLD_V1COMPAT; } while (0)
#define CLR_MLD_GENPEND(f) do { (f) &= ~MLD_GENPEND; } while (0)
#define IS_MLD_QUERIER(f) (((f) & MLD_QUERIER) != 0)
#define IS_MLD_V1COMPAT(f) (((f) & MLD_V1COMPAT) != 0)
#define IS_MLD_GENPEND(f) (((f) & MLD_GENPEND) != 0)
/* Group flags */
#define MLD_STARTUP (1 << 1) /* Startup unsolicited Reports */
#define MLD_V1COMPAT (1 << 2) /* Version 1 compatibility mode */
#define MLD_LASTREPORT (1 << 3) /* We were the last to report */
#define MLD_SCHEDMSG (1 << 4) /* Outgoing message scheduled */
#define MLD_WAITMSG (1 << 5) /* Block until message sent */
#define MLD_RPTPEND (1 << 6) /* Report pending */
#define SET_MLD_QUERIER(f) do { (f) |= MLD_QUERIER; } while (0)
#define SET_MLD_STARTUP(f) do { (f) |= MLD_STARTUP; } while (0)
#define SET_MLD_V1COMPAT(f) do { (f) |= MLD_V1COMPAT; } while (0)
#define SET_MLD_LASTREPORT(f) do { (f) |= MLD_LASTREPORT; } while (0)
#define SET_MLD_SCHEDMSG(f) do { (f) |= MLD_SCHEDMSG; } while (0)
#define SET_MLD_WAITMSG(f) do { (f) |= MLD_WAITMSG; } while (0)
#define SET_MLD_RPTPEND(f) do { (f) |= MLD_RPTPEND; } while (0)
#define CLR_MLD_QUERIER(f) do { (f) &= ~MLD_QUERIER; } while (0)
#define CLR_MLD_STARTUP(f) do { (f) &= ~MLD_STARTUP; } while (0)
#define CLR_MLD_V1COMPAT(f) do { (f) &= ~MLD_V1COMPAT; } while (0)
#define CLR_MLD_LASTREPORT(f) do { (f) &= ~MLD_LASTREPORT; } while (0)
#define CLR_MLD_SCHEDMSG(f) do { (f) &= ~MLD_SCHEDMSG; } while (0)
#define CLR_MLD_WAITMSG(f) do { (f) &= ~MLD_WAITMSG; } while (0)
#define CLR_MLD_RPTPEND(f) do { (f) &= ~MLD_RPTPEND; } while (0)
#define IS_MLD_QUERIER(f) (((f) & MLD_QUERIER) != 0)
#define IS_MLD_STARTUP(f) (((f) & MLD_STARTUP) != 0)
#define IS_MLD_V1COMPAT(f) (((f) & MLD_V1COMPAT) != 0)
#define IS_MLD_LASTREPORT(f) (((f) & MLD_LASTREPORT) != 0)
#define IS_MLD_SCHEDMSG(f) (((f) & MLD_SCHEDMSG) != 0)
#define IS_MLD_WAITMSG(f) (((f) & MLD_WAITMSG) != 0)
@@ -201,10 +211,6 @@ enum mld_msgtype_e
/* This structure represents one group member. There is a list of groups
* for each device interface structure.
*
* There will be a group for the all systems group address but this
* will not run the state machine as it is used to kick off reports
* from all the other groups
*/
typedef FAR struct wdog_s *WDOG_ID;
@@ -214,7 +220,6 @@ struct mld_group_s
net_ipv6addr_t grpaddr; /* Group IPv6 address */
struct work_s work; /* For deferred timeout operations */
WDOG_ID polldog; /* Timer used for periodic or delayed events */
WDOG_ID v1dog; /* MLDv1 compatibility mode timer */
sem_t sem; /* Used to wait for message transmission */
#ifdef CONFIG_NET_MLD_ROUTER
uint16_t members; /* Number of members currently reporting (excludes us) */
@@ -287,7 +292,7 @@ int mld_query(FAR struct net_driver_s *dev,
* Name: mld_report_v1
*
* Description:
* Called from icmpv6_input() when a Version 1 Multicast Listener Report is
* Called from icmpv6_input() when a MLDv1 Multicast Listener Report is
* received.
*
****************************************************************************/
@@ -363,6 +368,18 @@ FAR struct mld_group_s *mld_grpallocfind(FAR struct net_driver_s *dev,
void mld_grpfree(FAR struct net_driver_s *dev,
FAR struct mld_group_s *group);
/****************************************************************************
* Name: mld_new_pollcycle
*
* Description:
* Update accumulated membership at the beginning of each new poll cycle
*
****************************************************************************/
#ifdef CONFIG_NET_MLD_ROUTER
void mld_new_pollcycle(FAR struct net_driver_s *dev);
#endif
/****************************************************************************
* Name: mld_schedmsg
*
@@ -431,7 +448,7 @@ void mld_send(FAR struct net_driver_s *dev, FAR struct mld_group_s *group,
*
****************************************************************************/
uint8_t mld_report_msgtype(FAR struct mld_group_s *group);
uint8_t mld_report_msgtype(FAR struct net_driver_s *dev);
/****************************************************************************
* Name: mld_joingroup
@@ -474,14 +491,14 @@ int mld_joingroup(FAR const struct ipv6_mreq *mrec);
int mld_leavegroup(FAR const struct ipv6_mreq *mrec);
/****************************************************************************
* Name: mld_start_polltimer
* Name: mld_start_gentimer
*
* Description:
* Start the MLD poll timer.
* Start/Re-start the general query timer.
*
****************************************************************************/
void mld_start_polltimer(FAR struct mld_group_s *group, clock_t ticks);
void mld_start_gentimer(FAR struct net_driver_s *dev, clock_t ticks);
/****************************************************************************
* Name: mld_start_v1timer
@@ -491,7 +508,17 @@ void mld_start_polltimer(FAR struct mld_group_s *group, clock_t ticks);
*
****************************************************************************/
void mld_start_v1timer(FAR struct mld_group_s *group, clock_t ticks);
void mld_start_v1timer(FAR struct net_driver_s *dev, clock_t ticks);
/****************************************************************************
* Name: mld_start_polltimer
*
* Description:
* Start the MLD poll timer.
*
****************************************************************************/
void mld_start_polltimer(FAR struct mld_group_s *group, clock_t ticks);
/****************************************************************************
* Name: mld_addmcastmac
+54 -17
View File
@@ -109,31 +109,28 @@ FAR struct mld_group_s *mld_grpalloc(FAR struct net_driver_s *dev,
goto errout_with_sem;
}
group->v1dog = wd_create();
DEBUGASSERT(group->v1dog != NULL);
if (group->v1dog == NULL)
{
goto errout_with_polldog;
}
/* Save the interface index */
group->ifindex = dev->d_ifindex;
/* All routers start up as a Querier on each of their attached links. */
#ifndef CONFIG_CONFIG_NET_MLD_ROUTER
/* Start the query timer if we are the Querier and this is the first
* group member of the group.
*/
SET_MLD_QUERIER(group->flags);
if (dev->d_mld.grplist.head == NULL)
{
mld_start_gentimer(dev, MSEC2TICK(MLD_QUERY_MSEC));
}
#endif
/* Add the group structure to the list in the device structure */
sq_addfirst((FAR sq_entry_t *)group, &dev->d_mld_grplist);
sq_addfirst((FAR sq_entry_t *)group, &dev->d_mld.grplist);
}
return group;
errout_with_polldog:
wd_delete(group->polldog);
errout_with_sem:
(void)nxsem_destroy(&group->sem);
kmm_free(group);
@@ -160,7 +157,7 @@ FAR struct mld_group_s *mld_grpfind(FAR struct net_driver_s *dev,
addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6],
addr[7]);
for (group = (FAR struct mld_group_s *)dev->d_mld_grplist.head;
for (group = (FAR struct mld_group_s *)dev->d_mld.grplist.head;
group;
group = group->next)
{
@@ -222,11 +219,10 @@ void mld_grpfree(FAR struct net_driver_s *dev, FAR struct mld_group_s *group)
/* Cancel the timers */
wd_cancel(group->polldog);
wd_cancel(group->v1dog);
/* Remove the group structure from the group list in the device structure */
sq_rem((FAR sq_entry_t *)group, &dev->d_mld_grplist);
sq_rem((FAR sq_entry_t *)group, &dev->d_mld.grplist);
/* Destroy the wait semaphore */
@@ -235,12 +231,53 @@ void mld_grpfree(FAR struct net_driver_s *dev, FAR struct mld_group_s *group)
/* Destroy the timers */
wd_delete(group->polldog);
wd_delete(group->v1dog);
/* Then release the group structure resources. */
mldinfo("Call sched_kfree()\n");
kmm_free(group);
#ifndef CONFIG_CONFIG_NET_MLD_ROUTER
/* If there are no longer any groups, then stop the general query and v1
* compatibility timers.
*/
if (dev->d_mld.grplist.head == NULL)
{
wd_cancel(dev->d_mld.gendog);
wd_cancel(dev->d_mld.v1dog);
}
#endif
}
/****************************************************************************
* Name: mld_new_pollcycle
*
* Description:
* Update accumulated membership at the beginning of each new poll cycle
*
****************************************************************************/
#ifdef CONFIG_NET_MLD_ROUTER
void mld_new_pollcycle(FAR struct net_driver_s *dev)
{
FAR struct mld_group_s *member;
/* Update member ship in every group */
for (member = (FAR struct mld_group_s *)dev->d_mld.grplist.head;
member;
member = member->next)
{
/* Save the number of members that reported in the previous query
* cycle; reset the number of members that have reported in the new
* query cycle.
*/
member->lstmbrs = member->members;
member->members = 0;
}
}
#endif
#endif /* CONFIG_NET_MLD */
+20 -1
View File
@@ -38,9 +38,11 @@
#include <nuttx/config.h>
#include <string.h>
#include <assert.h>
#include <debug.h>
#include <nuttx/wdog.h>
#include <nuttx/net/netdev.h>
#include <nuttx/net/ip.h>
#include <nuttx/net/mld.h>
@@ -77,7 +79,18 @@ void mld_initialize(void)
void mld_devinit(struct net_driver_s *dev)
{
mldinfo("MLD initializing dev %p\n", dev);
DEBUGASSERT(dev->d_mld_grplist.head == NULL);
/* Initialize the MLD state in the device structure */
memset(&dev->d_mld, 0, sizeof(struct mld_netdev_s));
dev->d_mld.gendog = wd_create();
dev->d_mld.v1dog = wd_create();
DEBUGASSERT(dev->d_mld.gendog != NULL && dev->d_mld.v1dog != NULL);
/* All routers start up as a Querier on each of their attached links. */
SET_MLD_QUERIER(dev->d_mld.flags);
/* Add the all nodes address to the group */
@@ -88,4 +101,10 @@ void mld_devinit(struct net_driver_s *dev)
mld_addmcastmac(dev, g_ipv6_allnodes);
mld_addmcastmac(dev, g_ipv6_allrouters);
mld_addmcastmac(dev, g_ipv6_allmldv2routers);
#ifdef CONFIG_CONFIG_NET_MLD_ROUTER
/* Start the general query timer. */
mld_start_gentimer(dev, MSEC2TICK(MLD_QUERY_MSEC));
#endif
}
-1
View File
@@ -193,7 +193,6 @@ int mld_leavegroup(FAR const struct ipv6_mreq *mrec)
*/
wd_cancel(group->polldog);
wd_cancel(group->v1dog);
CLR_MLD_SCHEDMSG(group->flags);
CLR_MLD_WAITMSG(group->flags);
+21 -2
View File
@@ -78,9 +78,28 @@ void mld_poll(FAR struct net_driver_s *dev)
dev->d_len = 0;
dev->d_sndlen = 0;
/* Check if a general query is pending */
if (IS_MLD_GENPEND(dev->d_mld.flags))
{
/* Clear the pending flag */
CLR_MLD_GENPEND(dev->d_mld.flags);
/* Are we still the querier? */
if (IS_MLD_QUERIER(dev->d_mld.flags))
{
/* Yes, send the general query and return */
mld_send(dev, NULL, MLD_SEND_GENQUERY);
return;
}
}
/* Check each member of the group */
for (group = (FAR struct mld_group_s *)dev->d_mld_grplist.head;
for (group = (FAR struct mld_group_s *)dev->d_mld.grplist.head;
group;
group = group->next)
{
@@ -120,7 +139,7 @@ void mld_poll(FAR struct net_driver_s *dev)
{
/* Yes.. create the MLD message in the driver buffer */
mld_send(dev, group, mld_report_msgtype(group));
mld_send(dev, group, mld_report_msgtype(dev));
/* Indicate that the report is no longer pending */
+55 -103
View File
@@ -65,7 +65,7 @@
****************************************************************************/
/****************************************************************************
* Name: mld_setup_v1compat
* Name: mld_check_v1compat
*
* Description:
* If this is for MLDv1 query, then select MLDv1 compatibility mode and
@@ -74,21 +74,11 @@
*
****************************************************************************/
static void mld_setup_v1compat(FAR struct mld_group_s *group,
FAR const struct mld_mcast_listen_query_s *query,
bool mldv1)
static inline void mld_check_v1compat(FAR struct net_driver_s *dev,
bool mldv1)
{
unsigned int respmsec;
if (mldv1)
{
#if 0 /* REVISIT */
/* Get the QQI from the query. Since this is MLDv1, we know that
* the value is not encoded.
*/
respmsec = MSEC_PER_SEC * MLD_QQI_VALUE(query->qqic);
#else
/* REVISIT: I am confused. Per RFC 3810:
* "The Older Version Querier Present Timeout is the time-out for
* transitioning a host back to MLDv2 Host Compatibility Mode. When
@@ -103,34 +93,20 @@ static void mld_setup_v1compat(FAR struct mld_group_s *group,
* field. That is an MLDv2 extension.
*/
respmsec = MLD_QUERY_MSEC;
#endif
/* Select MLDv1 compatibility mode (might already be selected) */
SET_MLD_V1COMPAT(group->flags);
SET_MLD_V1COMPAT(dev->d_mld.flags);
/* Whenever a host changes its compatibility mode, it cancels all its
* pending responses and retransmission timers.
/* REVISIT: Whenever a host changes its compatibility mode, it cancels
* all its pending responses and retransmission timers. Logic Missing.
*/
wd_cancel(group->polldog);
/* REVISIT: We cannot cancel a pending message if there is a waiter.
* Some additional logic would be required to avoid a hang.
*/
if (!IS_MLD_WAITMSG(group->flags))
{
CLR_MLD_SCHEDMSG(group->flags);
}
/* And start the MLDv1 compatibility timer. If the timer is already
* running, this will reset the timer.
*/
mld_start_v1timer(group,
MSEC2TICK(MLD_V1PRESENT_MSEC((clock_t)respmsec)));
mld_start_v1timer(dev,
MSEC2TICK(MLD_V1PRESENT_MSEC((clock_t)MLD_QUERY_MSEC)));
}
}
@@ -197,21 +173,19 @@ static bool mld_cmpaddr(FAR struct net_driver_s *dev,
* Name: mld_check_querier
*
* Description:
* Check if we are still the querier for this group (assuming that we are
* currently the querier). This compares the IPv6 Source Address of the
* query against and the IPv6 address of the link. Ff the source address
* is numerically less than the link address, when we are no longer the
* querier.
* Check if we are still the querier (assuming that we are currently the
* querier). This compares the IPv6 Source Address of the query against
* the IPv6 address of the link. If the source address is numerically
* less than the link address, when we are no longer the querier.
*
****************************************************************************/
static void mld_check_querier(FAR struct net_driver_s *dev,
FAR struct ipv6_hdr_s *ipv6,
FAR struct mld_group_s *group)
FAR struct ipv6_hdr_s *ipv6)
{
/* Check if this member is a Querier */
if (IS_MLD_QUERIER(group->flags))
if (IS_MLD_QUERIER(dev->d_mld.flags))
{
/* This is a querier, check if the IPv6 source address is numerically
* less than the IPv6 address assigned to this link.
@@ -221,21 +195,17 @@ static void mld_check_querier(FAR struct net_driver_s *dev,
{
/* Switch to non-Querier mode */
CLR_MLD_QUERIER(group->flags);
CLR_MLD_QUERIER(dev->d_mld.flags);
}
}
/* Check if the member is a Non-Querier AND that we are past the start up
* phase (where the timer is used for a different purpose)?
*/
/* Check if the member is a Non-Querier. */
if (!IS_MLD_QUERIER(group->flags) && !IS_MLD_STARTUP(group->flags))
if (!IS_MLD_QUERIER(dev->d_mld.flags))
{
/* Yes.. cancel the poll timer and [re-]start the 'Other Querier
* Present' Timeout.
*/
/* Yes.. [re-]start the 'Other Querier Present' Timeout. */
mld_start_polltimer(group, MSEC2TICK(MLD_OQUERY_MSEC));
mld_start_gentimer(dev, MSEC2TICK(MLD_OQUERY_MSEC));
}
}
@@ -307,6 +277,13 @@ int mld_query(FAR struct net_driver_s *dev,
return -EINVAL;
}
/* Warn if we received a MLDv2 query in MLDv1 compatibility mode. */
if (!mldv1 && IS_MLD_V1COMPAT(dev->d_mld.flags))
{
mldwarn("WARNING: MLDv2 query received in MLDv1 compatibility mode\n");
}
/* There are three variants of the Query message (RFC 3810):
*
* 1. A "General Query" is sent by the Querier to learn which
@@ -352,64 +329,37 @@ int mld_query(FAR struct net_driver_s *dev,
mldinfo("General multicast query\n");
MLD_STATINCR(g_netstats.mld.gm_query_received);
/* Two passes through the member list. On the first, just check if we
* are still the querier for the qroup.
*/
/* Check if we are still the querier for this sub-net */
for (member = (FAR struct mld_group_s *)dev->d_mld_grplist.head;
member;
member = member->next)
{
/* Skip over the all systems group entry */
if (!net_ipv6addr_cmp(member->grpaddr, g_ipv6_allnodes))
{
/* Check if we are still the querier for this group */
mld_check_querier(dev, ipv6, member);
/* Warn if we received a MLDv2 query in MLDv1 compatibility
* mode.
*/
if (!mldv1 && IS_MLD_V1COMPAT(member->flags))
{
mldinfo("WARNING: MLDv2 query received in MLDv1 "
"compatibility mode\n");
}
mld_check_querier(dev, ipv6);
#ifdef CONFIG_NET_MLD_ROUTER
/* Save the number of members that reported in the previous
* query cycle; reset the number of members that have
* reported in the new query cycle.
*/
member->lstmbrs = member->members;
member->members = 0;
#endif
}
}
/* On the second time through, we send the Report in response to the
* query. This has to be done twice because because there is only
* a single packet buffer that is used for both incoming and outgoing
* packets. When the report is sent, it will clobber the incoming
* query. Any attempt to send an additional Report would also clobber
* a preceding report
/* Update accumulated membership at the beginning of each new poll
* cycle
*/
for (member = (FAR struct mld_group_s *)dev->d_mld_grplist.head;
member;
mld_new_pollcycle(dev)
#endif
/* Check MLDv1 compatibility mode */
mld_check_v1compat(dev, mldv1);
/* Send the Report in response to the query. This has to be done
* multiple times because because there is only a single packet buffer
* that is used for both incoming and outgoing packets. When the
* report is sent, it will clobber the incoming* query. Any attempt
* to send an additional Report would also clobber a preceding report
*/
for (member = (FAR struct mld_group_s *)dev->d_mld.grplist.head;
member != NULL;
member = member->next)
{
/* Skip over the all systems group entry */
if (!net_ipv6addr_cmp(member->grpaddr, g_ipv6_allnodes))
{
/* Check MLDv1 compatibility mode */
mld_setup_v1compat(member, query, mldv1);
/* Have we already sent a report from this loop? */
if (rptsent)
@@ -424,7 +374,7 @@ int mld_query(FAR struct net_driver_s *dev,
{
/* No.. Send one report now. */
mld_send(dev, member, mld_report_msgtype(member));
mld_send(dev, member, mld_report_msgtype(dev));
rptsent = true;
CLR_MLD_RPTPEND(member->flags);
}
@@ -458,7 +408,7 @@ int mld_query(FAR struct net_driver_s *dev,
/* Check if we are still the querier for this group */
mld_check_querier(dev, ipv6, group);
mld_check_querier(dev, ipv6);
#ifdef CONFIG_NET_MLD_ROUTER
/* Save the number of members that reported in the previous query cycle;
@@ -471,7 +421,7 @@ int mld_query(FAR struct net_driver_s *dev,
/* Warn if we received a MLDv2 query in MLDv1 compatibility mode. */
if (!mldv1 && IS_MLD_V1COMPAT(group->flags))
if (!mldv1 && IS_MLD_V1COMPAT(dev->d_mld.flags))
{
mldinfo("WARNING: MLDv2 query received in MLDv1 compatibility mode\n");
}
@@ -496,11 +446,12 @@ int mld_query(FAR struct net_driver_s *dev,
/* Check MLDv1 compatibility mode */
mld_setup_v1compat(group, query, mldv1);
mld_check_v1compat(dev, mldv1);
/* Send the report */
mld_send(dev, group, mld_report_msgtype(group));
mld_send(dev, group, mld_report_msgtype(dev));
CLR_MLD_RPTPEND(group->flags);
}
/* Not sent to all systems. Check for Unicast General Query */
@@ -512,11 +463,12 @@ int mld_query(FAR struct net_driver_s *dev,
/* Check MLDv1 compatibility mode */
mld_setup_v1compat(group, query, mldv1);
mld_check_v1compat(dev, mldv1);
/* Send the report */
mld_send(dev, group, mld_report_msgtype(group));
mld_send(dev, group, mld_report_msgtype(dev));
CLR_MLD_RPTPEND(group->flags);
}
else
{
+1 -1
View File
@@ -157,7 +157,7 @@ int mld_report(FAR struct net_driver_s *dev, FAR const net_ipv6addr_t grpaddr)
int mld_report_v1(FAR struct net_driver_s *dev,
FAR const struct mld_mcast_listen_report_v1_s *report)
{
mldinfo("Version 1 Multicast Listener Report\n");
mldinfo("MLDv1 Multicast Listener Report\n");
DEBUGASSERT(dev != NULL && report != NULL);
MLD_STATINCR(g_netstats.mld.v1report_received);
+23 -9
View File
@@ -120,6 +120,11 @@ void mld_send(FAR struct net_driver_s *dev, FAR struct mld_group_s *group,
FAR const uint16_t *destipaddr;
unsigned int mldsize;
/* Only a general query message can have a NULL group */
DEBUGASSERT(dev != NULL);
DEBUGASSERT(msgtype == MLD_SEND_GENQUERY || group != NULL);
/* Select IPv6 */
IFF_SET_IPv6(dev->d_flags);
@@ -131,7 +136,8 @@ void mld_send(FAR struct net_driver_s *dev, FAR struct mld_group_s *group,
case MLD_SEND_GENQUERY: /* Send General Query */
case MLD_SEND_MASQUERY: /* Send Multicast Address Specific (MAS) Query */
{
mldinfo("Send General Query, flags=%02x\n", group->flags);
mldinfo("Send General/MAS Query, flags=%02x\n",
group != NULL ? group->flags : dev->d_mld.flags);
mldsize = SIZEOF_MLD_MCAST_LISTEN_QUERY_S(0);
}
break;
@@ -290,7 +296,7 @@ void mld_send(FAR struct net_driver_s *dev, FAR struct mld_group_s *group,
/* Fields unique to the extended MLDv2 query */
if (!IS_MLD_V1COMPAT(group->flags))
if (!IS_MLD_V1COMPAT(dev->d_mld.flags))
{
query->flags = MLD_ROBUSTNESS;
query->qqic = MLD_QRESP_SEC;
@@ -307,13 +313,21 @@ void mld_send(FAR struct net_driver_s *dev, FAR struct mld_group_s *group,
/* Save the number of members that reported in the previous query
* cycle; reset the number of members that have reported in the
* new query cycle.
*
* REVISIT: This would have to be done for all groups, not just
* this one.
*/
group->lstmbrs = group->members;
group->members = 0;
if (msgtype == MLD_SEND_GENQUERY)
{
/* Update accumulated membership for all groups. */
mld_new_pollcycle(dev)
}
else
{
/* Updated accumulated membership only for this group */
group->lstmbrs = group->members;
group->members = 0;
}
#endif
}
break;
@@ -404,9 +418,9 @@ void mld_send(FAR struct net_driver_s *dev, FAR struct mld_group_s *group,
*
****************************************************************************/
uint8_t mld_report_msgtype(FAR struct mld_group_s *group)
uint8_t mld_report_msgtype(FAR struct net_driver_s *dev)
{
if (IS_MLD_V1COMPAT(group->flags))
if (IS_MLD_V1COMPAT(dev->d_mld.flags))
{
return MLD_SEND_V1REPORT;
}
+324 -199
View File
File diff suppressed because it is too large Load Diff