diff options
Diffstat (limited to 'pimd/pim6_mld.c')
| -rw-r--r-- | pimd/pim6_mld.c | 49 |
1 files changed, 36 insertions, 13 deletions
diff --git a/pimd/pim6_mld.c b/pimd/pim6_mld.c index 5eedfb7dca..a39d182990 100644 --- a/pimd/pim6_mld.c +++ b/pimd/pim6_mld.c @@ -13,6 +13,7 @@ */ #include <zebra.h> +#include <netinet/icmp6.h> #include <netinet/ip6.h> #include "lib/memory.h" @@ -344,7 +345,8 @@ static const char *const gm_states[] = { }; /* clang-format on */ -CPP_NOTICE("TODO: S,G entries in EXCLUDE (i.e. prune) unsupported"); +/* TODO: S,G entries in EXCLUDE (i.e. prune) unsupported" */ + /* tib_sg_gm_prune() below is an "un-join", it doesn't prune S,G when *,G is * joined. Whether we actually want/need to support this is a separate * question - it is almost never used. In fact this is exactly what RFC5790 @@ -354,6 +356,7 @@ CPP_NOTICE("TODO: S,G entries in EXCLUDE (i.e. prune) unsupported"); 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; @@ -403,9 +406,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; @@ -645,7 +651,7 @@ static void gm_handle_v2_pass1(struct gm_packet_state *pkt, */ gm_packet_sg_drop(old_grp); gm_sg_update(grp, false); - CPP_NOTICE("need S,G PRUNE => NO_INFO transition here"); +/* TODO "need S,G PRUNE => NO_INFO transition here" */ } break; @@ -793,7 +799,8 @@ static void gm_handle_v2_pass2_excl(struct gm_packet_state *pkt, size_t offs) gm_sg_update(sg_grp, false); } -CPP_NOTICE("TODO: QRV/QQIC are not copied from queries to local state"); +/* TODO: QRV/QQIC are not copied from queries to local state" */ + /* on receiving a query, we need to update our robustness/query interval to * match, so we correctly process group/source specific queries after last * member leaves @@ -949,7 +956,8 @@ static void gm_handle_v1_report(struct gm_if *gm_ifp, item = gm_packet_sg_setup(pkt, grp, true, false); item->n_exclude = 0; - CPP_NOTICE("set v1-seen timer on grp here"); + +/* TODO "set v1-seen timer on grp here" */ /* } */ @@ -1012,7 +1020,9 @@ static void gm_handle_v1_leave(struct gm_if *gm_ifp, if (old_grp) { gm_packet_sg_drop(old_grp); gm_sg_update(grp, false); - CPP_NOTICE("need S,G PRUNE => NO_INFO transition here"); + +/* TODO "need S,G PRUNE => NO_INFO transition here" */ + } } @@ -1234,6 +1244,7 @@ static void gm_handle_q_groupsrc(struct gm_if *gm_ifp, for (i = 0; i < n_src; i++) { sg = gm_sg_find(gm_ifp, grp, srcs[i]); + GM_UPDATE_SG_STATE(sg); gm_sg_timer_start(gm_ifp, sg, timers->expire_wait); } } @@ -1308,6 +1319,7 @@ static void gm_handle_q_group(struct gm_if *gm_ifp, if (PIM_DEBUG_GM_TRACE) zlog_debug(log_ifp("*,%pPAs expiry timer starting"), &grp); + GM_UPDATE_SG_STATE(sg); gm_sg_timer_start(gm_ifp, sg, timers->expire_wait); sg = gm_sgs_next(gm_ifp->sgs, sg); @@ -1356,7 +1368,7 @@ static void gm_bump_querier(struct gm_if *gm_ifp) gm_ifp->n_startup = gm_ifp->cur_qrv; - event_execute(router->master, gm_t_query, gm_ifp, 0); + event_execute(router->master, gm_t_query, gm_ifp, 0, NULL); } static void gm_t_other_querier(struct event *t) @@ -1369,7 +1381,7 @@ static void gm_t_other_querier(struct event *t) gm_ifp->querier = pim_ifp->ll_lowest; gm_ifp->n_startup = gm_ifp->cur_qrv; - event_execute(router->master, gm_t_query, gm_ifp, 0); + event_execute(router->master, gm_t_query, gm_ifp, 0, NULL); } static void gm_handle_query(struct gm_if *gm_ifp, @@ -1919,7 +1931,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--; @@ -1928,8 +1939,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; @@ -2245,7 +2268,7 @@ static void gm_update_ll(struct interface *ifp) return; gm_ifp->n_startup = gm_ifp->cur_qrv; - event_execute(router->master, gm_t_query, gm_ifp, 0); + event_execute(router->master, gm_t_query, gm_ifp, 0, NULL); } void gm_ifp_update(struct interface *ifp) |
