summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pimd/pim_cmd.c20
-rw-r--r--pimd/pim_oil.c91
-rw-r--r--pimd/pim_oil.h6
-rw-r--r--pimd/pim_vxlan.c5
4 files changed, 117 insertions, 5 deletions
diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c
index e5686a94f4..8e7f46d42c 100644
--- a/pimd/pim_cmd.c
+++ b/pimd/pim_cmd.c
@@ -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,7 +2117,8 @@ 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,
+ vty_out(vty, "%s(%c%c%c%c%c)",
+ out_ifname,
(c_oil->oif_flags[oif_vif_index]
& PIM_OIF_FLAG_PROTO_IGMP)
? 'I'
@@ -2133,9 +2134,13 @@ 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)",
+ 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 +2157,10 @@ 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'
: ' ');
}
}
@@ -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),
diff --git a/pimd/pim_oil.c b/pimd/pim_oil.c
index 7e88ea4fb6..64979ed7ed 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));
}
diff --git a/pimd/pim_oil.h b/pimd/pim_oil.h
index 3d4488a422..a371e2a7c6 100644
--- a/pimd/pim_oil.h
+++ b/pimd/pim_oil.h
@@ -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 */
diff --git a/pimd/pim_vxlan.c b/pimd/pim_vxlan.c
index 7e0958700b..4ca75e57ea 100644
--- a/pimd/pim_vxlan.c
+++ b/pimd/pim_vxlan.c
@@ -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,