Skip to content

Commit

Permalink
pim6d: MLD conformance querier-non-querier transition fix
Browse files Browse the repository at this point in the history
Problem:
ANVL Conformance test case 7.31 failed because DUT after
receiving MLD Done msg and a query message with lower adddress,
DUT did not keep on sending the group specific queries since it moved
to non-querier state.

As per RFC 2710 s4 p7, DUT is supposed to keep sending the group
specific queries until either it receives the membership report or
there is no response even after last member query is sent.

Fix:
Whenever group specific queries are sent out we are checking if
the self node is querier, if not it does not sends this query out.
This check is preventing the continuation of the last queries
which must be sent out although the self node is not the querier.
Hence removing the check from the api gm_trigger_specific_query
and adding in the caller to make sure this event is only added
for queriers. This will make sure the last member queries are sent out
even during the transition phase.
Also earlier this event was getting added for non-querier
as well which is redundant since queries were not required to be sent
out by non-queriers.

Issue: #13539

Signed-off-by: Mobashshera Rasool <[email protected]>
  • Loading branch information
mobash-rasool committed Jun 28, 2023
1 parent 4d1f3d5 commit f3dca82
Showing 1 changed file with 20 additions and 5 deletions.
25 changes: 20 additions & 5 deletions pimd/pim6_mld.c
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,7 @@ static const char *const gm_states[] = {
static void gm_sg_update(struct gm_sg *sg, bool has_expired)
{
struct gm_if *gm_ifp = sg->iface;
struct pim_interface *pim_ifp = gm_ifp->ifp->info;
enum gm_sg_state prev, desired;
bool new_join;
struct gm_sg *grp = NULL;
Expand Down Expand Up @@ -404,9 +405,12 @@ static void gm_sg_update(struct gm_sg *sg, bool has_expired)
gm_sg_timer_start(gm_ifp, sg, timers.expire_wait);

EVENT_OFF(sg->t_sg_query);
sg->n_query = gm_ifp->cur_lmqc;
sg->query_sbit = false;
gm_trigger_specific(sg);
/* Trigger the specific queries only for querier. */
if (IPV6_ADDR_SAME(&gm_ifp->querier, &pim_ifp->ll_lowest)) {
sg->n_query = gm_ifp->cur_lmqc;
gm_trigger_specific(sg);
}
}
}
prev = sg->state;
Expand Down Expand Up @@ -1924,7 +1928,6 @@ static void gm_t_gsq_pend(struct event *t)
static void gm_trigger_specific(struct gm_sg *sg)
{
struct gm_if *gm_ifp = sg->iface;
struct pim_interface *pim_ifp = gm_ifp->ifp->info;
struct gm_gsq_pending *pend_gsq, ref = {};

sg->n_query--;
Expand All @@ -1933,8 +1936,20 @@ static void gm_trigger_specific(struct gm_sg *sg)
gm_ifp->cur_query_intv_trig,
&sg->t_sg_query);

if (!IPV6_ADDR_SAME(&gm_ifp->querier, &pim_ifp->ll_lowest))
return;
/* As per RFC 2271, s6 p14:
* E.g. a router that starts as a Querier, receives a
* Done message for a group and then receives a Query from a router with
* a lower address (causing a transition to the Non-Querier state)
* continues to send multicast-address-specific queries for the group in
* question until it either receives a Report or its timer expires, at
* which time it starts performing the actions of a Non-Querier for this
* group.
*/
/* Therefore here we do not need to check if this router is querier or
* not. This is called only for querier, hence it will work even if the
* router transitions from querier to non-querier.
*/

if (gm_ifp->pim->gm_socket == -1)
return;

Expand Down

0 comments on commit f3dca82

Please sign in to comment.