From 46a9ea8bfa753472e786268ed97444b41ce94fa8 Mon Sep 17 00:00:00 2001 From: saravanank Date: Thu, 19 Mar 2020 18:05:11 -0700 Subject: [PATCH] pimd: When DR becomes non DR, couldreg state events not handled. RCA: Upstreams which are in register state other than noinfo, doesnt remove register tunnel from oif after it becomes nonDR Fix: scan upstreams with iif as the old dr and check if couldReg becomes false. If couldreg becomes false from true, remove regiface and stop reg timer. Do not disturb the entry. Later the entry shall be removed by kat expiry. Signed-off-by: Saravanan K --- pimd/pim_iface.c | 1 + pimd/pim_iface.h | 1 + pimd/pim_neighbor.c | 11 +++++++++++ pimd/pim_pim.c | 1 + pimd/pim_register.c | 29 +++++++++++++++++++++++++++++ pimd/pim_register.h | 1 + pimd/pim_upstream.c | 2 +- pimd/pim_upstream.h | 1 + 8 files changed, 46 insertions(+), 1 deletion(-) 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 */