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>
This commit is contained in:
Anuradha Karuppiah 2020-02-06 09:30:43 -08:00
parent 95586137e6
commit f03999caa6
4 changed files with 75 additions and 3 deletions

View File

@ -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);

View File

@ -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;
}

View File

@ -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,

View File

@ -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)