diff options
author | Anuradha Karuppiah <anuradhak@cumulusnetworks.com> | 2019-11-15 18:16:15 +0100 |
---|---|---|
committer | Anuradha Karuppiah <anuradhak@cumulusnetworks.com> | 2019-11-15 18:16:15 +0100 |
commit | 5923b7396e4fb6a0d11d5f61a384c9737b06a6ac (patch) | |
tree | 3940c544c3e7fdb22bfe7350e8be3ea0bff8cb1f /pimd/pim_oil.c | |
parent | pimd: update add_oif and del_oif debugs to print caller (diff) | |
download | frr-5923b7396e4fb6a0d11d5f61a384c9737b06a6ac.tar.xz frr-5923b7396e4fb6a0d11d5f61a384c9737b06a6ac.zip |
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>
Diffstat (limited to 'pimd/pim_oil.c')
-rw-r--r-- | pimd/pim_oil.c | 91 |
1 files changed, 89 insertions, 2 deletions
diff --git a/pimd/pim_oil.c b/pimd/pim_oil.c index 7e88ea4fb..64979ed7e 100644 --- a/pimd/pim_oil.c +++ b/pimd/pim_oil.c @@ -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)); } |