mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-05-29 21:23:06 +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();
|
json = json_object_new_object();
|
||||||
} else {
|
} else {
|
||||||
vty_out(vty,
|
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,
|
vty_out(vty,
|
||||||
"\nInstalled Source Group IIF OIL\n");
|
"\nInstalled Source Group IIF OIL\n");
|
||||||
}
|
}
|
||||||
@ -2117,25 +2117,7 @@ static void pim_show_state(struct pim_instance *pim, struct vty *vty,
|
|||||||
} else {
|
} else {
|
||||||
if (first_oif) {
|
if (first_oif) {
|
||||||
first_oif = 0;
|
first_oif = 0;
|
||||||
vty_out(vty, "%s(%c%c%c%c)", out_ifname,
|
vty_out(vty, "%s(%c%c%c%c%c)",
|
||||||
(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)",
|
|
||||||
out_ifname,
|
out_ifname,
|
||||||
(c_oil->oif_flags[oif_vif_index]
|
(c_oil->oif_flags[oif_vif_index]
|
||||||
& PIM_OIF_FLAG_PROTO_IGMP)
|
& 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]
|
(c_oil->oif_flags[oif_vif_index]
|
||||||
& PIM_OIF_FLAG_PROTO_STAR)
|
& 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)
|
if (ttl < 1)
|
||||||
continue;
|
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);
|
ifp_out = pim_if_find_by_vif_index(pim, oif_vif_index);
|
||||||
pim_time_uptime(
|
pim_time_uptime(
|
||||||
mroute_uptime, sizeof(mroute_uptime),
|
mroute_uptime, sizeof(mroute_uptime),
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
#include "pim_str.h"
|
#include "pim_str.h"
|
||||||
#include "pim_iface.h"
|
#include "pim_iface.h"
|
||||||
#include "pim_time.h"
|
#include "pim_time.h"
|
||||||
|
#include "pim_vxlan.h"
|
||||||
|
|
||||||
// struct list *pim_channel_oil_list = NULL;
|
// struct list *pim_channel_oil_list = NULL;
|
||||||
// struct hash *pim_channel_oil_hash = 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;
|
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) {
|
if (PIM_DEBUG_MROUTE) {
|
||||||
char group_str[INET_ADDRSTRLEN];
|
char group_str[INET_ADDRSTRLEN];
|
||||||
char source_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;
|
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_mroute_add(channel_oil, __PRETTY_FUNCTION__)) {
|
||||||
if (PIM_DEBUG_MROUTE) {
|
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,
|
int pim_channel_add_oif(struct channel_oil *channel_oil, struct interface *oif,
|
||||||
uint32_t proto_mask, const char *caller)
|
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] =
|
channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] =
|
||||||
PIM_MROUTE_MIN_TTL;
|
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
|
/* channel_oil->oil.mfcc_parent != MAXVIFS indicate this entry is not
|
||||||
* valid to get installed in kernel.
|
* valid to get installed in kernel.
|
||||||
*/
|
*/
|
||||||
@ -581,5 +668,5 @@ int pim_channel_oil_empty(struct channel_oil *c_oil)
|
|||||||
inited = 1;
|
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
|
#define PIM_OIL_H
|
||||||
|
|
||||||
#include "pim_mroute.h"
|
#include "pim_mroute.h"
|
||||||
|
#include "pim_iface.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Where did we get this (S,G) from?
|
* 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_IGMP | PIM_OIF_FLAG_PROTO_PIM \
|
||||||
| PIM_OIF_FLAG_PROTO_STAR | PIM_OIF_FLAG_PROTO_VXLAN)
|
| 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.
|
* We need a pimreg vif id from the kernel.
|
||||||
* Since ifindex == vif id for most cases and the number
|
* 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);
|
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);
|
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 */
|
#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;
|
struct pim_upstream *up;
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
struct prefix nht_p;
|
struct prefix nht_p;
|
||||||
|
struct pim_instance *pim = vxlan_sg->pim;
|
||||||
|
|
||||||
if (vxlan_sg->up) {
|
if (vxlan_sg->up) {
|
||||||
/* nothing to do */
|
/* 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__);
|
pim_upstream_ref(up, flags, __PRETTY_FUNCTION__);
|
||||||
vxlan_sg->up = up;
|
vxlan_sg->up = up;
|
||||||
pim_vxlan_orig_mr_up_iif_update(vxlan_sg);
|
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 {
|
} else {
|
||||||
up = pim_upstream_add(vxlan_sg->pim, &vxlan_sg->sg,
|
up = pim_upstream_add(vxlan_sg->pim, &vxlan_sg->sg,
|
||||||
vxlan_sg->iif, flags,
|
vxlan_sg->iif, flags,
|
||||||
|
Loading…
Reference in New Issue
Block a user