From da72c9fdc34c6d7cc5128886ab898e3cd080ff05 Mon Sep 17 00:00:00 2001 From: anuradhak Date: Mon, 28 Nov 2016 10:12:21 -0800 Subject: [PATCH] pim-nexthop: mroute and pim-upstream rpf are falling out of sync. Currently the mroute-IIF and upstream RPF-IIF/neigh are resolved separately. This must change i.e. be merged together for a couple of reasons - 1. In the case of ECMP we will use a load-share mechanism (based on G or SG) to pick an RPF neighbor in 3.2.1 (to use the load-sharing cap of anycast-RP). Using a different resolution mechanism for mroute-IIF will simply not work. 2. In a non-CLOS topology it is actually possible to have routers that do not participate in PIM. In this case the tree will be set up using different routers than the ones chosen for the mroute IIF. And traffic will not be forwarded. This change is however too big for 3.2.0. So to handle CM-13714 I have simply forced rpf update on neigh add which fixes the specific problem seen on link flap in a clos (it is not very efficient but traffic recovers). In problem state - (jessie-30-dev-switch-amd64-sbuild)root@spine-1:/home/cumulus# ip mr (0.0.0.0, 225.1.1.1) Iif: lo Oifs: swp3 lo (20.0.11.253, 225.1.1.1) Iif: swp1 Oifs: swp3 (jessie-30-dev-switch-amd64-sbuild)root@spine-1:/home/cumulus# vtysh -c "show ip pim upstream" Iif Source Group State Uptime JoinTimer RSTimer KATimer RefCnt lo * 225.1.1.1 Joined 00:08:44 00:00:15 --:--:-- --:--:-- 1 swp2 20.0.11.253 225.1.1.1 Joined 00:08:35 00:00:56 --:--:-- 00:02:59 1 (jessie-30-dev-switch-amd64-sbuild)root@spine-1:/home/cumulus# Signed-off-by: Anuradha Karuppiah Acked-by: Donald Sharp --- pimd/pim_neighbor.c | 17 +++++++++++++++++ pimd/pim_zebra.c | 2 +- pimd/pim_zebra.h | 1 + 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/pimd/pim_neighbor.c b/pimd/pim_neighbor.c index 1b58b98502..a8a60f6f38 100644 --- a/pimd/pim_neighbor.c +++ b/pimd/pim_neighbor.c @@ -37,6 +37,7 @@ #include "pim_upstream.h" #include "pim_ifchannel.h" #include "pim_rp.h" +#include "pim_zebra.h" static void dr_election_by_addr(struct interface *ifp) { @@ -421,6 +422,18 @@ pim_neighbor_find_if (struct interface *ifp) return listnode_head (pim_ifp->pim_neighbor_list); } +/* rpf info associated with an upstream entry needs to be re-evaluated + * when an RPF neighbor comes or goes */ +static void +pim_neighbor_rpf_update(void) +{ + /* XXX: for the time being piggyback on the timer used on rib changes + * to scan and update the rpf nexthop. This is expensive processing + * and we should be able to optimize neighbor changes differently than + * nexthop changes. */ + sched_rpf_cache_refresh(); +} + struct pim_neighbor *pim_neighbor_add(struct interface *ifp, struct in_addr source_addr, pim_hello_options hello_options, @@ -483,6 +496,8 @@ struct pim_neighbor *pim_neighbor_add(struct interface *ifp, pim_upstream_find_new_rpf(); pim_rp_setup (); + + pim_neighbor_rpf_update(); return neigh; } @@ -595,6 +610,8 @@ void pim_neighbor_delete(struct interface *ifp, listnode_delete(pim_ifp->pim_neighbor_list, neigh); pim_neighbor_free(neigh); + + pim_neighbor_rpf_update(); } void pim_neighbor_delete_all(struct interface *ifp, diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index 294d8bba25..9239f875c4 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -545,7 +545,7 @@ static int on_rpf_cache_refresh(struct thread *t) return 0; } -static void sched_rpf_cache_refresh() +void sched_rpf_cache_refresh(void) { ++qpim_rpf_cache_refresh_requests; diff --git a/pimd/pim_zebra.h b/pimd/pim_zebra.h index ae79ed815a..767cdf0541 100644 --- a/pimd/pim_zebra.h +++ b/pimd/pim_zebra.h @@ -39,4 +39,5 @@ void igmp_source_forward_stop(struct igmp_source *source); void pim_forward_start(struct pim_ifchannel *ch); void pim_forward_stop(struct pim_ifchannel *ch); +void sched_rpf_cache_refresh(void); #endif /* PIM_ZEBRA_H */ -- 2.39.5