summaryrefslogtreecommitdiffstats
path: root/pimd/pim_rpf.c
diff options
context:
space:
mode:
authorAnuradha Karuppiah <anuradhak@cumulusnetworks.com>2020-02-06 18:30:36 +0100
committerAnuradha Karuppiah <anuradhak@cumulusnetworks.com>2020-02-14 18:18:30 +0100
commit05ca004b804b85343f450c99792b065254c5ccc3 (patch)
tree4d37c93a47c6ee36238b8c097a3e03c7aa625ea9 /pimd/pim_rpf.c
parentpimd: register with MLAG on the first VxLAN SG (diff)
downloadfrr-05ca004b804b85343f450c99792b065254c5ccc3.tar.xz
frr-05ca004b804b85343f450c99792b065254c5ccc3.zip
pim: DF election for tunnel termination mroutes in an anycast-VTEP setup
1. Upstream entries associated with tunnel termination mroutes are synced to the MLAG peer via the local MLAG daemon. 2. These entries are installed in the peer switch (via an upstream ref flag). 3. DF (Designated Forwarder) election is run per-upstream entry by both the MLAG switches - a. The switch with the lowest RPF cost is the DF winner b. If both switches have the same RPF cost the MLAG role is used as a tie breaker with the MLAG primary becoming the DF winner. 4. The DF winner terminates the multicast traffic by adding the tunnel termination device to the OIL. The non-DF suppresses the termination device from the OIL. Note: Before the PIM-MLAG interface was available hidden config was used to test the EVPN-PIM functionality with MLAG. I have removed the code to persist that config to avoid confusion. The hidden commands are still available. Signed-off-by: Anuradha Karuppiah <anuradhak@cumulusnetworks.com>
Diffstat (limited to 'pimd/pim_rpf.c')
-rw-r--r--pimd/pim_rpf.c44
1 files changed, 42 insertions, 2 deletions
diff --git a/pimd/pim_rpf.c b/pimd/pim_rpf.c
index 24519adb1..889e0704c 100644
--- a/pimd/pim_rpf.c
+++ b/pimd/pim_rpf.c
@@ -194,6 +194,32 @@ static int nexthop_mismatch(const struct pim_nexthop *nh1,
|| (nh1->mrib_route_metric != nh2->mrib_route_metric);
}
+static void pim_rpf_cost_change(struct pim_instance *pim,
+ struct pim_upstream *up, uint32_t old_cost)
+{
+ struct pim_rpf *rpf = &up->rpf;
+ uint32_t new_cost;
+
+ new_cost = pim_up_mlag_local_cost(up);
+ if (PIM_DEBUG_MLAG)
+ zlog_debug(
+ "%s: Cost_to_rp of upstream-%s changed to:%u, from:%u",
+ __func__, up->sg_str, new_cost, old_cost);
+
+ if (old_cost == new_cost)
+ return;
+
+ /* Cost changed, it might Impact MLAG DF election, update */
+ if (PIM_DEBUG_MLAG)
+ zlog_debug(
+ "%s: Cost_to_rp of upstream-%s changed to:%u",
+ __func__, up->sg_str,
+ rpf->source_nexthop.mrib_route_metric);
+
+ if (pim_up_mlag_is_local(up))
+ pim_mlag_up_local_add(pim, up);
+}
+
enum pim_rpf_result pim_rpf_update(struct pim_instance *pim,
struct pim_upstream *up, struct pim_rpf *old,
const char *caller)
@@ -203,6 +229,7 @@ enum pim_rpf_result pim_rpf_update(struct pim_instance *pim,
struct prefix nht_p;
struct prefix src, grp;
bool neigh_needed = true;
+ uint32_t saved_mrib_route_metric;
if (PIM_UPSTREAM_FLAG_TEST_STATIC_IIF(up->flags))
return PIM_RPF_OK;
@@ -215,6 +242,7 @@ enum pim_rpf_result pim_rpf_update(struct pim_instance *pim,
saved.source_nexthop = rpf->source_nexthop;
saved.rpf_addr = rpf->rpf_addr;
+ saved_mrib_route_metric = pim_up_mlag_local_cost(up);
if (old) {
old->source_nexthop = saved.source_nexthop;
old->rpf_addr = saved.rpf_addr;
@@ -236,8 +264,12 @@ enum pim_rpf_result pim_rpf_update(struct pim_instance *pim,
neigh_needed = false;
pim_find_or_track_nexthop(pim, &nht_p, up, NULL, false, NULL);
if (!pim_ecmp_nexthop_lookup(pim, &rpf->source_nexthop, &src, &grp,
- neigh_needed))
+ neigh_needed)) {
+ /* Route is Deleted in Zebra, reset the stored NH data */
+ pim_upstream_rpf_clear(pim, up);
+ pim_rpf_cost_change(pim, up, saved_mrib_route_metric);
return PIM_RPF_FAILURE;
+ }
rpf->rpf_addr.family = AF_INET;
rpf->rpf_addr.u.prefix4 = pim_rpf_find_rpf_addr(up);
@@ -290,10 +322,18 @@ enum pim_rpf_result pim_rpf_update(struct pim_instance *pim,
if (saved.rpf_addr.u.prefix4.s_addr != rpf->rpf_addr.u.prefix4.s_addr
|| saved.source_nexthop
.interface != rpf->source_nexthop.interface) {
-
+ pim_rpf_cost_change(pim, up, saved_mrib_route_metric);
return PIM_RPF_CHANGED;
}
+ if (PIM_DEBUG_MLAG)
+ zlog_debug(
+ "%s(%s): Cost_to_rp of upstream-%s changed to:%u",
+ __func__, caller, up->sg_str,
+ rpf->source_nexthop.mrib_route_metric);
+
+ pim_rpf_cost_change(pim, up, saved_mrib_route_metric);
+
return PIM_RPF_OK;
}