net/mld: Resolve and issue with sending reports from multiple groups in the same polling cycle.
This commit is contained in:
parent
2b3ec4172d
commit
1a56229386
5 changed files with 78 additions and 76 deletions
|
@ -131,6 +131,7 @@
|
||||||
#define MLD_LASTREPORT (1 << 3) /* We were the last to report */
|
#define MLD_LASTREPORT (1 << 3) /* We were the last to report */
|
||||||
#define MLD_SCHEDMSG (1 << 4) /* Outgoing message scheduled */
|
#define MLD_SCHEDMSG (1 << 4) /* Outgoing message scheduled */
|
||||||
#define MLD_WAITMSG (1 << 5) /* Block until message sent */
|
#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_QUERIER(f) do { (f) |= MLD_QUERIER; } while (0)
|
||||||
#define SET_MLD_STARTUP(f) do { (f) |= MLD_STARTUP; } 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_LASTREPORT(f) do { (f) |= MLD_LASTREPORT; } while (0)
|
||||||
#define SET_MLD_SCHEDMSG(f) do { (f) |= MLD_SCHEDMSG; } 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_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_QUERIER(f) do { (f) &= ~MLD_QUERIER; } while (0)
|
||||||
#define CLR_MLD_STARTUP(f) do { (f) &= ~MLD_STARTUP; } 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_LASTREPORT(f) do { (f) &= ~MLD_LASTREPORT; } while (0)
|
||||||
#define CLR_MLD_SCHEDMSG(f) do { (f) &= ~MLD_SCHEDMSG; } 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_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_QUERIER(f) (((f) & MLD_QUERIER) != 0)
|
||||||
#define IS_MLD_STARTUP(f) (((f) & MLD_STARTUP) != 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_LASTREPORT(f) (((f) & MLD_LASTREPORT) != 0)
|
||||||
#define IS_MLD_SCHEDMSG(f) (((f) & MLD_SCHEDMSG) != 0)
|
#define IS_MLD_SCHEDMSG(f) (((f) & MLD_SCHEDMSG) != 0)
|
||||||
#define IS_MLD_WAITMSG(f) (((f) & MLD_WAITMSG) != 0)
|
#define IS_MLD_WAITMSG(f) (((f) & MLD_WAITMSG) != 0)
|
||||||
|
#define IS_MLD_RPTPEND(f) (((f) & MLD_RPTPEND) != 0)
|
||||||
|
|
||||||
/* Debug ********************************************************************/
|
/* 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,
|
void mld_send(FAR struct net_driver_s *dev, FAR struct mld_group_s *group,
|
||||||
uint8_t msgtype);
|
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
|
* Name: mld_joingroup
|
||||||
*
|
*
|
||||||
|
|
|
@ -49,29 +49,6 @@
|
||||||
#include "devif/devif.h"
|
#include "devif/devif.h"
|
||||||
#include "mld/mld.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
|
* Public Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
@ -127,11 +104,30 @@ void mld_poll(FAR struct net_driver_s *dev)
|
||||||
if (IS_MLD_WAITMSG(group->flags))
|
if (IS_MLD_WAITMSG(group->flags))
|
||||||
{
|
{
|
||||||
mldinfo("Awakening waiter\n");
|
mldinfo("Awakening waiter\n");
|
||||||
|
|
||||||
|
CLR_MLD_WAITMSG(group->flags);
|
||||||
nxsem_post(&group->sem);
|
nxsem_post(&group->sem);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* And break out of the loop */
|
/* 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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
* 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
|
* packets. When the report is sent, it will clobber the incoming
|
||||||
* query. Any attempt to send an additional Report would also clobber
|
* query. Any attempt to send an additional Report would also clobber
|
||||||
* a preceding report
|
* 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;
|
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))
|
if (!net_ipv6addr_cmp(member->grpaddr, g_ipv6_allnodes))
|
||||||
{
|
{
|
||||||
|
|
||||||
/* Check MLDv1 compatibility mode */
|
/* Check MLDv1 compatibility mode */
|
||||||
|
|
||||||
mld_setup_v1compat(member, query, mldv1);
|
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));
|
if (rptsent)
|
||||||
rptsent = true;
|
{
|
||||||
break;
|
/* 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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
MLD_STATINCR(g_netstats.mld.query_sent);
|
||||||
|
|
||||||
#ifdef CONFIG_NET_MLD_ROUTER
|
#ifdef CONFIG_NET_MLD_ROUTER
|
||||||
/* Save the number of members that reported in the previous query cycle;
|
/* Save the number of members that reported in the previous query
|
||||||
* reset the number of members that have reported in the new query cycle.
|
* 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->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);
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -59,27 +59,6 @@
|
||||||
* Private Functions
|
* 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
|
* Name: mld_polldog_work
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in a new issue