pimd: MUTE flag to suppress traffic forwarding on non-DF

If an mroute loses DF election (with the MLAG peer) it has to stop
forwarding traffic on active-active devices such as ipmr-lo used
for vxlan traffic termination. To acheive that this commit
introduces a concept of OIF muting. That way we can let the PIM and
IGMP state machines play out and silence OIFs after the fact.

Relevant outputs:
=================
1. muted OIFs are displayed with the M flag in "pim state" -
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
root@TORC12:~# net show pim state |grep "27.0.0.13"|grep 100
1         27.0.0.13        239.1.1.100      uplink-1          ipmr-lo(   *M)
root@TORC12:~#
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
2. And supressed altogether in the mroute output -
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
root@TORC12:~# net show mroute |grep "27.0.0.13"|grep 100
27.0.0.13       239.1.1.100     none   uplink-1         none             0    --:--:--
root@TORC12:~#
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

Signed-off-by: Anuradha Karuppiah <anuradhak@cumulusnetworks.com>
This commit is contained in:
Anuradha Karuppiah 2019-11-15 09:16:15 -08:00
parent 1b249e7097
commit 5923b7396e
4 changed files with 134 additions and 22 deletions

View File

@ -1988,7 +1988,7 @@ static void pim_show_state(struct pim_instance *pim, struct vty *vty,
json = json_object_new_object();
} else {
vty_out(vty,
"Codes: J -> Pim Join, I -> IGMP Report, S -> Source, * -> Inherited from (*,G), V -> VxLAN");
"Codes: J -> Pim Join, I -> IGMP Report, S -> Source, * -> Inherited from (*,G), V -> VxLAN, M -> Muted");
vty_out(vty,
"\nInstalled Source Group IIF OIL\n");
}
@ -2117,25 +2117,7 @@ static void pim_show_state(struct pim_instance *pim, struct vty *vty,
} else {
if (first_oif) {
first_oif = 0;
vty_out(vty, "%s(%c%c%c%c)", out_ifname,
(c_oil->oif_flags[oif_vif_index]
& PIM_OIF_FLAG_PROTO_IGMP)
? 'I'
: ' ',
(c_oil->oif_flags[oif_vif_index]
& PIM_OIF_FLAG_PROTO_PIM)
? 'J'
: ' ',
(c_oil->oif_flags[oif_vif_index]
& PIM_OIF_FLAG_PROTO_VXLAN)
? 'V'
: ' ',
(c_oil->oif_flags[oif_vif_index]
& PIM_OIF_FLAG_PROTO_STAR)
? '*'
: ' ');
} else
vty_out(vty, ", %s(%c%c%c%c)",
vty_out(vty, "%s(%c%c%c%c%c)",
out_ifname,
(c_oil->oif_flags[oif_vif_index]
& PIM_OIF_FLAG_PROTO_IGMP)
@ -2152,6 +2134,33 @@ static void pim_show_state(struct pim_instance *pim, struct vty *vty,
(c_oil->oif_flags[oif_vif_index]
& PIM_OIF_FLAG_PROTO_STAR)
? '*'
: ' ',
(c_oil->oif_flags[oif_vif_index]
& PIM_OIF_FLAG_MUTE)
? 'M'
: ' ');
} else
vty_out(vty, ", %s(%c%c%c%c%c)",
out_ifname,
(c_oil->oif_flags[oif_vif_index]
& PIM_OIF_FLAG_PROTO_IGMP)
? 'I'
: ' ',
(c_oil->oif_flags[oif_vif_index]
& PIM_OIF_FLAG_PROTO_PIM)
? 'J'
: ' ',
(c_oil->oif_flags[oif_vif_index]
& PIM_OIF_FLAG_PROTO_VXLAN)
? 'V'
: ' ',
(c_oil->oif_flags[oif_vif_index]
& PIM_OIF_FLAG_PROTO_STAR)
? '*'
: ' ',
(c_oil->oif_flags[oif_vif_index]
& PIM_OIF_FLAG_MUTE)
? 'M'
: ' ');
}
}
@ -5292,6 +5301,11 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty,
if (ttl < 1)
continue;
/* do not display muted OIFs */
if (c_oil->oif_flags[oif_vif_index]
& PIM_OIF_FLAG_MUTE)
continue;
ifp_out = pim_if_find_by_vif_index(pim, oif_vif_index);
pim_time_uptime(
mroute_uptime, sizeof(mroute_uptime),

View File

@ -31,6 +31,7 @@
#include "pim_str.h"
#include "pim_iface.h"
#include "pim_time.h"
#include "pim_vxlan.h"
// struct list *pim_channel_oil_list = NULL;
// struct hash *pim_channel_oil_hash = NULL;
@ -311,7 +312,8 @@ int pim_channel_del_oif(struct channel_oil *channel_oil, struct interface *oif,
channel_oil->oif_flags[pim_ifp->mroute_vif_index] &= ~proto_mask;
if (channel_oil->oif_flags[pim_ifp->mroute_vif_index]) {
if (channel_oil->oif_flags[pim_ifp->mroute_vif_index] &
PIM_OIF_FLAG_PROTO_ANY) {
if (PIM_DEBUG_MROUTE) {
char group_str[INET_ADDRSTRLEN];
char source_str[INET_ADDRSTRLEN];
@ -333,6 +335,8 @@ int pim_channel_del_oif(struct channel_oil *channel_oil, struct interface *oif,
}
channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] = 0;
/* clear mute; will be re-evaluated when the OIF becomes valid again */
channel_oil->oif_flags[pim_ifp->mroute_vif_index] &= ~PIM_OIF_FLAG_MUTE;
if (pim_mroute_add(channel_oil, __PRETTY_FUNCTION__)) {
if (PIM_DEBUG_MROUTE) {
@ -373,6 +377,77 @@ int pim_channel_del_oif(struct channel_oil *channel_oil, struct interface *oif,
}
static bool pim_channel_eval_oif_mute(struct channel_oil *c_oil,
struct pim_interface *pim_ifp)
{
struct pim_interface *pim_reg_ifp;
struct pim_interface *vxlan_ifp;
bool do_mute = false;
struct pim_instance *pim = c_oil->pim;
if (!c_oil->up)
return do_mute;
pim_reg_ifp = pim->regiface->info;
if (pim_ifp == pim_reg_ifp) {
/* suppress pimreg in the OIL if the mroute is not supposed to
* trigger register encapsulated data
*/
if (PIM_UPSTREAM_FLAG_TEST_NO_PIMREG_DATA(c_oil->up->flags))
do_mute = true;
return do_mute;
}
vxlan_ifp = pim_vxlan_get_term_ifp(pim);
if (pim_ifp == vxlan_ifp) {
/* 1. vxlan termination device must never be added to the
* origination mroute (and that can actually happen because
* of XG inheritance from the termination mroute) otherwise
* traffic will end up looping.
* PS: This check has also been extended to non-orig mroutes
* that have a local SIP as such mroutes can move back and
* forth between orig<=>non-orig type.
* 2. vxlan termination device should be removed from the non-DF
* to prevent duplicates to the overlay rxer
*/
if (PIM_UPSTREAM_FLAG_TEST_SRC_VXLAN_ORIG(c_oil->up->flags) ||
PIM_UPSTREAM_FLAG_TEST_MLAG_NON_DF(c_oil->up->flags) ||
pim_vxlan_is_local_sip(c_oil->up))
do_mute = true;
return do_mute;
}
return do_mute;
}
void pim_channel_update_oif_mute(struct channel_oil *c_oil,
struct pim_interface *pim_ifp)
{
bool old_mute;
bool new_mute;
/* If pim_ifp is not a part of the OIL there is nothing to do */
if (!c_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index])
return;
old_mute = !!(c_oil->oif_flags[pim_ifp->mroute_vif_index] &
PIM_OIF_FLAG_MUTE);
new_mute = pim_channel_eval_oif_mute(c_oil, pim_ifp);
if (old_mute == new_mute)
return;
if (new_mute)
c_oil->oif_flags[pim_ifp->mroute_vif_index] |=
PIM_OIF_FLAG_MUTE;
else
c_oil->oif_flags[pim_ifp->mroute_vif_index] &=
~PIM_OIF_FLAG_MUTE;
pim_mroute_add(c_oil, __PRETTY_FUNCTION__);
}
int pim_channel_add_oif(struct channel_oil *channel_oil, struct interface *oif,
uint32_t proto_mask, const char *caller)
{
@ -517,6 +592,18 @@ int pim_channel_add_oif(struct channel_oil *channel_oil, struct interface *oif,
channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] =
PIM_MROUTE_MIN_TTL;
/* Some OIFs are held in a muted state i.e. the PIM state machine
* decided to include the OIF but additional status check such as
* MLAG DF role prevent it from being activated for traffic
* forwarding.
*/
if (pim_channel_eval_oif_mute(channel_oil, pim_ifp))
channel_oil->oif_flags[pim_ifp->mroute_vif_index] |=
PIM_OIF_FLAG_MUTE;
else
channel_oil->oif_flags[pim_ifp->mroute_vif_index] &=
~PIM_OIF_FLAG_MUTE;
/* channel_oil->oil.mfcc_parent != MAXVIFS indicate this entry is not
* valid to get installed in kernel.
*/
@ -581,5 +668,5 @@ int pim_channel_oil_empty(struct channel_oil *c_oil)
inited = 1;
}
return !memcmp(c_oil->oif_flags, zero, MAXVIFS * sizeof(uint32_t));
return !memcmp(c_oil->oil.mfcc_ttls, zero, MAXVIFS * sizeof(uint32_t));
}

View File

@ -21,6 +21,7 @@
#define PIM_OIL_H
#include "pim_mroute.h"
#include "pim_iface.h"
/*
* Where did we get this (S,G) from?
@ -38,6 +39,8 @@
(PIM_OIF_FLAG_PROTO_IGMP | PIM_OIF_FLAG_PROTO_PIM \
| PIM_OIF_FLAG_PROTO_STAR | PIM_OIF_FLAG_PROTO_VXLAN)
/* OIF is present in the OIL but must not be used for forwarding traffic */
#define PIM_OIF_FLAG_MUTE (1 << 4)
/*
* We need a pimreg vif id from the kernel.
* Since ifindex == vif id for most cases and the number
@ -127,4 +130,7 @@ int pim_channel_del_oif(struct channel_oil *c_oil, struct interface *oif,
int pim_channel_oil_empty(struct channel_oil *c_oil);
char *pim_channel_oil_dump(struct channel_oil *c_oil, char *buf, size_t size);
void pim_channel_update_oif_mute(struct channel_oil *c_oil,
struct pim_interface *pim_ifp);
#endif /* PIM_OIL_H */

View File

@ -292,6 +292,7 @@ static void pim_vxlan_orig_mr_up_add(struct pim_vxlan_sg *vxlan_sg)
struct pim_upstream *up;
int flags = 0;
struct prefix nht_p;
struct pim_instance *pim = vxlan_sg->pim;
if (vxlan_sg->up) {
/* nothing to do */
@ -349,6 +350,10 @@ static void pim_vxlan_orig_mr_up_add(struct pim_vxlan_sg *vxlan_sg)
pim_upstream_ref(up, flags, __PRETTY_FUNCTION__);
vxlan_sg->up = up;
pim_vxlan_orig_mr_up_iif_update(vxlan_sg);
/* mute pimreg on origination mroutes */
if (pim->regiface)
pim_channel_update_oif_mute(up->channel_oil,
pim->regiface->info);
} else {
up = pim_upstream_add(vxlan_sg->pim, &vxlan_sg->sg,
vxlan_sg->iif, flags,