diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c index cb31878e01..fe67f189b8 100644 --- a/pimd/pim_iface.c +++ b/pimd/pim_iface.c @@ -137,6 +137,7 @@ struct pim_interface *pim_if_new(struct interface *ifp, bool igmp, bool pim, /* BSM config on interface: true by default */ pim_ifp->bsm_enable = true; pim_ifp->ucast_bsm_accept = true; + pim_ifp->am_i_dr = false; /* RFC 3376: 8.3. Query Response Interval diff --git a/pimd/pim_iface.h b/pimd/pim_iface.h index 570bf5eac3..13aaf8d3b2 100644 --- a/pimd/pim_iface.h +++ b/pimd/pim_iface.h @@ -133,6 +133,7 @@ struct pim_interface { /* Turn on Active-Active for this interface */ bool activeactive; + bool am_i_dr; int64_t pim_ifstat_start; /* start timestamp for stats */ uint64_t pim_ifstat_bsm_rx; diff --git a/pimd/pim_neighbor.c b/pimd/pim_neighbor.c index ca7ca11402..fa0e823f47 100644 --- a/pimd/pim_neighbor.c +++ b/pimd/pim_neighbor.c @@ -40,6 +40,7 @@ #include "pim_join.h" #include "pim_jp_agg.h" #include "pim_bfd.h" +#include "pim_register.h" static void dr_election_by_addr(struct interface *ifp) { @@ -141,6 +142,16 @@ int pim_if_dr_election(struct interface *ifp) pim_if_update_join_desired(pim_ifp); pim_if_update_could_assert(ifp); pim_if_update_assert_tracking_desired(ifp); + + if (PIM_I_am_DR(pim_ifp)) + pim_ifp->am_i_dr = true; + else { + if (pim_ifp->am_i_dr == true) { + pim_reg_del_on_couldreg_fail(ifp); + pim_ifp->am_i_dr = false; + } + } + return 1; } diff --git a/pimd/pim_pim.c b/pimd/pim_pim.c index 8d7a921cf4..641008b3ff 100644 --- a/pimd/pim_pim.c +++ b/pimd/pim_pim.c @@ -474,6 +474,7 @@ void pim_sock_reset(struct interface *ifp) pim_ifp->pim_dr_num_nondrpri_neighbors = 0; /* neighbors without dr_pri */ pim_ifp->pim_dr_addr = pim_ifp->primary_address; + pim_ifp->am_i_dr = true; pim_ifstat_reset(ifp); } diff --git a/pimd/pim_register.c b/pimd/pim_register.c index 19baecb9c2..92c3033718 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -498,3 +498,32 @@ int pim_register_recv(struct interface *ifp, struct in_addr dest_addr, return 0; } + +/* + * This routine scan all upstream and update register state and remove pimreg + * when couldreg becomes false. + */ +void pim_reg_del_on_couldreg_fail(struct interface *ifp) +{ + struct pim_interface *pim_ifp = ifp->info; + struct pim_instance *pim; + struct pim_upstream *up; + + if (!pim_ifp) + return; + + pim = pim_ifp->pim; + + frr_each (rb_pim_upstream, &pim->upstream_head, up) { + if (ifp != up->rpf.source_nexthop.interface) + continue; + + if (!pim_upstream_could_register(up) + && (up->reg_state != PIM_REG_NOINFO)) { + pim_channel_del_oif(up->channel_oil, pim->regiface, + PIM_OIF_FLAG_PROTO_PIM, __func__); + THREAD_OFF(up->t_rs_timer); + up->reg_state = PIM_REG_NOINFO; + } + } +} diff --git a/pimd/pim_register.h b/pimd/pim_register.h index c5a28fee41..caaacd9d54 100644 --- a/pimd/pim_register.h +++ b/pimd/pim_register.h @@ -43,5 +43,6 @@ void pim_register_stop_send(struct interface *ifp, struct prefix_sg *sg, struct in_addr src, struct in_addr originator); void pim_register_join(struct pim_upstream *up); void pim_null_register_send(struct pim_upstream *up); +void pim_reg_del_on_couldreg_fail(struct interface *ifp); #endif diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index efa58c1b1f..7cd2f9d0bc 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -515,7 +515,7 @@ static void forward_off(struct pim_upstream *up) } /* scan iface channel list */ } -static int pim_upstream_could_register(struct pim_upstream *up) +int pim_upstream_could_register(struct pim_upstream *up) { struct pim_interface *pim_ifp = NULL; diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h index ca693ee73f..b3379c67b2 100644 --- a/pimd/pim_upstream.h +++ b/pimd/pim_upstream.h @@ -394,4 +394,5 @@ void pim_upstream_update_use_rpt(struct pim_upstream *up, uint32_t pim_up_mlag_local_cost(struct pim_upstream *up); uint32_t pim_up_mlag_peer_cost(struct pim_upstream *up); void pim_upstream_reeval_use_rpt(struct pim_instance *pim); +int pim_upstream_could_register(struct pim_upstream *up); #endif /* PIM_UPSTREAM_H */