summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnuradha Karuppiah <anuradhak@cumulusnetworks.com>2020-02-06 09:30:43 -0800
committerAnuradha Karuppiah <anuradhak@cumulusnetworks.com>2020-02-14 09:18:30 -0800
commitf03999caa6a5d88bc6b9441f4039915ea6f67bf8 (patch)
tree4ad5cfcf9f9d87a613c5c3f95dc31634ed895bac
parent95586137e6662f9cdeede87dc75e70ab70877360 (diff)
pimd: increase RPF metric via the peerlink_rif by plus-10
The RPF cost is incremented by 10 if the RPF interface is the peerlink-rif. This is used to force the MLAG switch with the lowest cost to the RPF to become the MLAG DF. If a switch has to go via the peerlink-rif to get to the RP or source it simplly cannot be the designated forwarder. Signed-off-by: Anuradha Karuppiah <anuradhak@cumulusnetworks.com>
-rw-r--r--pimd/pim_rpf.c1
-rw-r--r--pimd/pim_upstream.c8
-rw-r--r--pimd/pim_upstream.h6
-rw-r--r--pimd/pim_vxlan.c63
4 files changed, 75 insertions, 3 deletions
diff --git a/pimd/pim_rpf.c b/pimd/pim_rpf.c
index 889e0704c4..b27374e302 100644
--- a/pimd/pim_rpf.c
+++ b/pimd/pim_rpf.c
@@ -36,6 +36,7 @@
#include "pim_time.h"
#include "pim_nht.h"
#include "pim_oil.h"
+#include "pim_mlag.h"
static struct in_addr pim_rpf_find_rpf_addr(struct pim_upstream *up);
diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c
index 8f7e1741e7..6ef0290adf 100644
--- a/pimd/pim_upstream.c
+++ b/pimd/pim_upstream.c
@@ -921,6 +921,14 @@ uint32_t pim_up_mlag_local_cost(struct pim_upstream *up)
if (!(pim_up_mlag_is_local(up)))
return router->infinite_assert_metric.route_metric;
+ if ((up->rpf.source_nexthop.interface ==
+ up->pim->vxlan.peerlink_rif) &&
+ (up->rpf.source_nexthop.mrib_route_metric <
+ (router->infinite_assert_metric.route_metric -
+ PIM_UPSTREAM_MLAG_PEERLINK_PLUS_METRIC)))
+ return up->rpf.source_nexthop.mrib_route_metric +
+ PIM_UPSTREAM_MLAG_PEERLINK_PLUS_METRIC;
+
return up->rpf.source_nexthop.mrib_route_metric;
}
diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h
index 1c1f180083..0e718a3c31 100644
--- a/pimd/pim_upstream.h
+++ b/pimd/pim_upstream.h
@@ -157,6 +157,12 @@
#define PIM_UPSTREAM_FLAG_UNSET_SRC_NOCACHE(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_SRC_NOCACHE)
#define PIM_UPSTREAM_FLAG_UNSET_USE_RPT(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_USE_RPT)
+/* The RPF cost is incremented by 10 if the RPF interface is the peerlink-rif.
+ * This is used to force the MLAG switch with the lowest cost to the RPF
+ * to become the MLAG DF.
+ */
+#define PIM_UPSTREAM_MLAG_PEERLINK_PLUS_METRIC 10
+
enum pim_upstream_state {
PIM_UPSTREAM_NOTJOINED,
PIM_UPSTREAM_JOINED,
diff --git a/pimd/pim_vxlan.c b/pimd/pim_vxlan.c
index 58d988e920..abfea538e1 100644
--- a/pimd/pim_vxlan.c
+++ b/pimd/pim_vxlan.c
@@ -477,13 +477,14 @@ static void pim_vxlan_orig_mr_del(struct pim_vxlan_sg *vxlan_sg)
static void pim_vxlan_orig_mr_iif_update(struct hash_backet *backet, void *arg)
{
- struct interface *ifp = (struct interface *)arg;
+ struct interface *ifp;
struct pim_vxlan_sg *vxlan_sg = (struct pim_vxlan_sg *)backet->data;
struct interface *old_iif = vxlan_sg->iif;
if (!pim_vxlan_is_orig_mroute(vxlan_sg))
return;
+ ifp = pim_vxlan_orig_mr_iif_get(vxlan_sg->pim);
if (PIM_DEBUG_VXLAN)
zlog_debug("vxlan SG %s iif changed from %s to %s",
vxlan_sg->sg_str,
@@ -895,7 +896,63 @@ static void pim_vxlan_set_default_iif(struct pim_instance *pim,
*/
if (pim->vxlan.sg_hash)
hash_iterate(pim->vxlan.sg_hash,
- pim_vxlan_orig_mr_iif_update, ifp);
+ pim_vxlan_orig_mr_iif_update, NULL);
+}
+
+static void pim_vxlan_up_cost_update(struct pim_instance *pim,
+ struct pim_upstream *up,
+ struct interface *old_peerlink_rif)
+{
+ if (!PIM_UPSTREAM_FLAG_TEST_MLAG_VXLAN(up->flags))
+ return;
+
+ if (up->rpf.source_nexthop.interface &&
+ ((up->rpf.source_nexthop.interface ==
+ pim->vxlan.peerlink_rif) ||
+ (up->rpf.source_nexthop.interface ==
+ old_peerlink_rif))) {
+ if (PIM_DEBUG_VXLAN)
+ zlog_debug("RPF cost adjust for %s on peerlink-rif (old: %s, new: %s) change",
+ up->sg_str,
+ old_peerlink_rif ?
+ old_peerlink_rif->name : "-",
+ pim->vxlan.peerlink_rif ?
+ pim->vxlan.peerlink_rif->name : "-");
+ pim_mlag_up_local_add(pim, up);
+ }
+}
+
+static void pim_vxlan_term_mr_cost_update(struct hash_backet *backet,
+ void *arg)
+{
+ struct interface *old_peerlink_rif = (struct interface *)arg;
+ struct pim_vxlan_sg *vxlan_sg = (struct pim_vxlan_sg *)backet->data;
+ struct pim_upstream *up;
+ struct listnode *listnode;
+ struct pim_upstream *child;
+
+ if (pim_vxlan_is_orig_mroute(vxlan_sg))
+ return;
+
+ /* Lookup all XG and SG entries with RPF-interface peerlink_rif */
+ up = vxlan_sg->up;
+ if (!up)
+ return;
+
+ pim_vxlan_up_cost_update(vxlan_sg->pim, up,
+ old_peerlink_rif);
+
+ for (ALL_LIST_ELEMENTS_RO(up->sources, listnode,
+ child))
+ pim_vxlan_up_cost_update(vxlan_sg->pim, child,
+ old_peerlink_rif);
+}
+
+static void pim_vxlan_sg_peerlink_rif_update(struct hash_backet *backet,
+ void *arg)
+{
+ pim_vxlan_orig_mr_iif_update(backet, NULL);
+ pim_vxlan_term_mr_cost_update(backet, arg);
}
static void pim_vxlan_set_peerlink_rif(struct pim_instance *pim,
@@ -928,7 +985,7 @@ static void pim_vxlan_set_peerlink_rif(struct pim_instance *pim,
*/
if (pim->vxlan.sg_hash)
hash_iterate(pim->vxlan.sg_hash,
- pim_vxlan_orig_mr_iif_update, ifp);
+ pim_vxlan_sg_peerlink_rif_update, old_iif);
}
void pim_vxlan_add_vif(struct interface *ifp)