net/mld: Resolve and issue with sending reports from multiple groups in the same polling cycle.

This commit is contained in:
Gregory Nutt 2018-11-11 07:31:59 -06:00
parent 2b3ec4172d
commit 1a56229386
5 changed files with 78 additions and 76 deletions

View File

@ -131,6 +131,7 @@
#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)
@ -138,6 +139,7 @@
#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)
@ -145,6 +147,7 @@
#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)
@ -152,6 +155,7 @@
#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)
#define IS_MLD_RPTPEND(f) (((f) & MLD_RPTPEND) != 0)
/* Debug ********************************************************************/
@ -418,6 +422,17 @@ void mld_poll(FAR struct net_driver_s *dev);
void mld_send(FAR struct net_driver_s *dev, FAR struct mld_group_s *group,
uint8_t msgtype);
/****************************************************************************
* Name: mld_report_msgtype
*
* Description:
* Determine which type of Report to send, MLDv1 or MLDv2, depending on
* current state of compatibility mode flag.
*
****************************************************************************/
uint8_t mld_report_msgtype(FAR struct mld_group_s *group);
/****************************************************************************
* Name: mld_joingroup
*

View File

@ -49,29 +49,6 @@
#include "devif/devif.h"
#include "mld/mld.h"
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: mld_sched_send
*
* Description:
* Construct and send the MLD message.
*
* Returned Value:
* Returns a non-zero value if an MLD message is sent.
*
* Assumptions:
* This function ust be called with the network locked.
*
****************************************************************************/
static inline void mld_sched_send(FAR struct net_driver_s *dev,
FAR struct mld_group_s *group)
{
}
/****************************************************************************
* Public Functions
****************************************************************************/
@ -127,11 +104,30 @@ void mld_poll(FAR struct net_driver_s *dev)
if (IS_MLD_WAITMSG(group->flags))
{
mldinfo("Awakening waiter\n");
CLR_MLD_WAITMSG(group->flags);
nxsem_post(&group->sem);
}
/* And break out of the loop */
break;
}
/* No.. does this message have a pending report still to be sent? */
else if (IS_MLD_RPTPEND(group->flags))
{
/* Yes.. create the MLD message in the driver buffer */
mld_send(dev, group, mld_report_msgtype(group));
/* Indicate that the report is no longer pending */
CLR_MLD_RPTPEND(group->flags);
/* And break out of the loop */
break;
}
}

View File

@ -133,27 +133,6 @@ static void mld_setup_v1compat(FAR struct mld_group_s *group,
}
}
/****************************************************************************
* Name: mld_report_msgtype
*
* Description:
* Determine which type of Report to send, MLDv1 or MLDv2, depending on
* current state of compatibility mode flag.
*
****************************************************************************/
static inline uint8_t mld_report_msgtype(FAR struct mld_group_s *group)
{
if (IS_MLD_V1COMPAT(group->flags))
{
return MLD_SEND_V1REPORT;
}
else
{
return MLD_SEND_V2REPORT;
}
}
/****************************************************************************
* Name: mld_mrc2mrd
*
@ -416,10 +395,6 @@ int mld_query(FAR struct net_driver_s *dev,
* 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
*
* REVISIT: This is a design flaw: Only a single report can be sent
* in this context because there is no mechanism to preserve the
* incoming request nor to queue multiple outgoing reports.
*/
for (member = (FAR struct mld_group_s *)dev->d_mld_grplist.head;
@ -430,16 +405,28 @@ int mld_query(FAR struct net_driver_s *dev,
if (!net_ipv6addr_cmp(member->grpaddr, g_ipv6_allnodes))
{
/* Check MLDv1 compatibility mode */
mld_setup_v1compat(member, query, mldv1);
/* Send one report and break out of the loop */
/* Have we already sent a report from this loop? */
mld_send(dev, member, mld_report_msgtype(member));
rptsent = true;
break;
if (rptsent)
{
/* Yes.. Just mark that a report as pending. The pending
* flag will checked on the next driver poll.
*/
SET_MLD_RPTPEND(member->flags);
}
else
{
/* No.. Send one report now. */
mld_send(dev, member, mld_report_msgtype(member));
rptsent = true;
CLR_MLD_RPTPEND(member->flags);
}
}
}

View File

@ -304,8 +304,12 @@ void mld_send(FAR struct net_driver_s *dev, FAR struct mld_group_s *group,
MLD_STATINCR(g_netstats.mld.query_sent);
#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.
/* 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;
@ -390,3 +394,24 @@ void mld_send(FAR struct net_driver_s *dev, FAR struct mld_group_s *group,
mld_dumppkt((FAR const uint8_t *)IPv6BUF, MLD_HDRLEN + mldsize);
}
/****************************************************************************
* Name: mld_report_msgtype
*
* Description:
* Determine which type of Report to send, MLDv1 or MLDv2, depending on
* current state of compatibility mode flag.
*
****************************************************************************/
uint8_t mld_report_msgtype(FAR struct mld_group_s *group)
{
if (IS_MLD_V1COMPAT(group->flags))
{
return MLD_SEND_V1REPORT;
}
else
{
return MLD_SEND_V2REPORT;
}
}

View File

@ -59,27 +59,6 @@
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: mld_report_msgtype
*
* Description:
* Determine which type of Report to send, MLDv1 or MLDv2, depending on
* current state of compatibility mode flag.
*
****************************************************************************/
static inline uint8_t mld_report_msgtype(FAR struct mld_group_s *group)
{
if (IS_MLD_V1COMPAT(group->flags))
{
return MLD_SEND_V1REPORT;
}
else
{
return MLD_SEND_V2REPORT;
}
}
/****************************************************************************
* Name: mld_polldog_work
*