mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-05-28 16:06:20 +00:00
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:
parent
1b249e7097
commit
5923b7396e
@ -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),
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user