summaryrefslogtreecommitdiffstats
path: root/pimd/pim_oil.c
diff options
context:
space:
mode:
authorAnuradha Karuppiah <anuradhak@cumulusnetworks.com>2019-11-15 18:16:15 +0100
committerAnuradha Karuppiah <anuradhak@cumulusnetworks.com>2019-11-15 18:16:15 +0100
commit5923b7396e4fb6a0d11d5f61a384c9737b06a6ac (patch)
tree3940c544c3e7fdb22bfe7350e8be3ea0bff8cb1f /pimd/pim_oil.c
parentpimd: update add_oif and del_oif debugs to print caller (diff)
downloadfrr-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.c91
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));
}