From 1a56229386463b6ea8542f2c7238224626402994 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Sun, 11 Nov 2018 07:31:59 -0600 Subject: [PATCH] net/mld: Resolve and issue with sending reports from multiple groups in the same polling cycle. --- net/mld/mld.h | 15 +++++++++++++++ net/mld/mld_poll.c | 42 ++++++++++++++++++---------------------- net/mld/mld_query.c | 47 ++++++++++++++++----------------------------- net/mld/mld_send.c | 29 ++++++++++++++++++++++++++-- net/mld/mld_timer.c | 21 -------------------- 5 files changed, 78 insertions(+), 76 deletions(-) diff --git a/net/mld/mld.h b/net/mld/mld.h index 48de7311bd..fddd1f6b23 100644 --- a/net/mld/mld.h +++ b/net/mld/mld.h @@ -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 * diff --git a/net/mld/mld_poll.c b/net/mld/mld_poll.c index 8c08362929..32e8a753be 100644 --- a/net/mld/mld_poll.c +++ b/net/mld/mld_poll.c @@ -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; } } diff --git a/net/mld/mld_query.c b/net/mld/mld_query.c index 2da2b4c264..0c37c1ebb2 100644 --- a/net/mld/mld_query.c +++ b/net/mld/mld_query.c @@ -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); + } } } diff --git a/net/mld/mld_send.c b/net/mld/mld_send.c index 55460921c5..d0eef7ae2a 100644 --- a/net/mld/mld_send.c +++ b/net/mld/mld_send.c @@ -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; + } +} diff --git a/net/mld/mld_timer.c b/net/mld/mld_timer.c index 7053edeb82..335688293d 100644 --- a/net/mld/mld_timer.c +++ b/net/mld/mld_timer.c @@ -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 *