]> git.proxmox.com Git - mirror_frr.git/blobdiff - pimd/pim_mroute.c
Merge pull request #4522 from LabNConsulting/working/master/issue4479
[mirror_frr.git] / pimd / pim_mroute.c
index 67b1a95f74789c8dac64d6f193c6e69a627e6279..2bdec12cd1a8f26e84efe823a0ba065e512d2ba7 100644 (file)
@@ -42,6 +42,7 @@
 #include "pim_zlookup.h"
 #include "pim_ssm.h"
 #include "pim_sock.h"
+#include "pim_vxlan.h"
 
 static void mroute_read_on(struct pim_instance *pim);
 
@@ -202,7 +203,8 @@ static int pim_mroute_msg_nocache(int fd, struct interface *ifp,
                 * and causing us to consider them.
                 */
                c_oil = pim_channel_oil_add(pim_ifp->pim, &sg,
-                                           pim_ifp->mroute_vif_index);
+                                           pim_ifp->mroute_vif_index,
+                                           __PRETTY_FUNCTION__);
                pim_mroute_add(c_oil, __PRETTY_FUNCTION__);
 
                return 0;
@@ -513,8 +515,7 @@ static int pim_mroute_msg_wrvifwhole(int fd, struct interface *ifp,
                if (!PIM_UPSTREAM_FLAG_TEST_FHR(up->flags)) {
                        // No if channel, but upstream we are at the RP.
                        if (pim_nexthop_lookup(pim_ifp->pim, &source,
-                                              up->upstream_register, 0)
-                           == 0) {
+                                              up->upstream_register, 0)) {
                                pim_register_stop_send(source.interface, &sg,
                                                       pim_ifp->primary_address,
                                                       up->upstream_register);
@@ -523,7 +524,8 @@ static int pim_mroute_msg_wrvifwhole(int fd, struct interface *ifp,
                        if (!up->channel_oil)
                                up->channel_oil = pim_channel_oil_add(
                                        pim_ifp->pim, &sg,
-                                       pim_ifp->mroute_vif_index);
+                                       pim_ifp->mroute_vif_index,
+                                       __PRETTY_FUNCTION__);
                        pim_upstream_inherited_olist(pim_ifp->pim, up);
                        if (!up->channel_oil->installed)
                                pim_mroute_add(up->channel_oil,
@@ -531,8 +533,8 @@ static int pim_mroute_msg_wrvifwhole(int fd, struct interface *ifp,
                } else {
                        if (I_am_RP(pim_ifp->pim, up->sg.grp)) {
                                if (pim_nexthop_lookup(pim_ifp->pim, &source,
-                                                      up->upstream_register, 0)
-                                   == 0)
+                                                      up->upstream_register,
+                                                      0))
                                        pim_register_stop_send(
                                                source.interface, &sg,
                                                pim_ifp->primary_address,
@@ -548,7 +550,8 @@ static int pim_mroute_msg_wrvifwhole(int fd, struct interface *ifp,
        }
 
        pim_ifp = ifp->info;
-       oil = pim_channel_oil_add(pim_ifp->pim, &sg, pim_ifp->mroute_vif_index);
+       oil = pim_channel_oil_add(pim_ifp->pim, &sg, pim_ifp->mroute_vif_index,
+                                 __PRETTY_FUNCTION__);
        if (!oil->installed)
                pim_mroute_add(oil, __PRETTY_FUNCTION__);
        if (pim_if_connected_to_source(ifp, sg.src)) {
@@ -897,6 +900,12 @@ int pim_mroute_add(struct channel_oil *c_oil, const char *name)
        int err;
        int orig = 0;
        int orig_iif_vif = 0;
+       struct pim_interface *pim_reg_ifp = NULL;
+       int orig_pimreg_ttl = 0;
+       bool pimreg_ttl_reset = false;
+       struct pim_interface *vxlan_ifp = NULL;
+       int orig_term_ttl = 0;
+       bool orig_term_ttl_reset = false;
 
        pim->mroute_add_last = pim_time_monotonic_sec();
        ++pim->mroute_add_events;
@@ -922,6 +931,37 @@ int pim_mroute_add(struct channel_oil *c_oil, const char *name)
                c_oil->oil.mfcc_ttls[c_oil->oil.mfcc_parent] = 1;
        }
 
+       if (c_oil->up) {
+               /* 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)) {
+                       pim_reg_ifp = pim->regiface->info;
+                       orig_pimreg_ttl =
+                               c_oil->oil.mfcc_ttls[pim_reg_ifp->mroute_vif_index];
+                       c_oil->oil.mfcc_ttls[pim_reg_ifp->mroute_vif_index] = 0;
+                       /* remember to flip it back after MFC programming */
+                       pimreg_ttl_reset = true;
+               }
+
+               vxlan_ifp = pim_vxlan_get_term_ifp(pim);
+               /* 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.
+                * 2. vxlan termination device should be removed from the non-DF
+                * to prevent duplicates to the overlay rxer
+                */
+               if (vxlan_ifp &&
+                       (PIM_UPSTREAM_FLAG_TEST_SRC_VXLAN_ORIG(c_oil->up->flags) ||
+                        PIM_UPSTREAM_FLAG_TEST_MLAG_NON_DF(c_oil->up->flags))) {
+                       orig_term_ttl_reset = true;
+                       orig_term_ttl =
+                               c_oil->oil.mfcc_ttls[vxlan_ifp->mroute_vif_index];
+                       c_oil->oil.mfcc_ttls[vxlan_ifp->mroute_vif_index] = 0;
+               }
+       }
+
        /*
         * If we have an unresolved cache entry for the S,G
         * it is owned by the pimreg for the incoming IIF
@@ -948,6 +988,16 @@ int pim_mroute_add(struct channel_oil *c_oil, const char *name)
        if (c_oil->oil.mfcc_origin.s_addr == INADDR_ANY)
                c_oil->oil.mfcc_ttls[c_oil->oil.mfcc_parent] = orig;
 
+       if (pimreg_ttl_reset) {
+               assert(pim_reg_ifp);
+               c_oil->oil.mfcc_ttls[pim_reg_ifp->mroute_vif_index] =
+                       orig_pimreg_ttl;
+       }
+
+       if (orig_term_ttl_reset)
+               c_oil->oil.mfcc_ttls[vxlan_ifp->mroute_vif_index] =
+                       orig_term_ttl;
+
        if (err) {
                zlog_warn(
                        "%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,MRT_ADD_MFC): errno=%d: %s",
@@ -964,6 +1014,8 @@ int pim_mroute_add(struct channel_oil *c_oil, const char *name)
        }
 
        c_oil->installed = 1;
+       c_oil->mroute_creation = pim_time_monotonic_sec();
+
        return 0;
 }
 
@@ -1030,7 +1082,7 @@ void pim_mroute_update_counters(struct channel_oil *c_oil)
                        sg.grp = c_oil->oil.mfcc_mcastgrp;
                        if (PIM_DEBUG_MROUTE)
                                zlog_debug(
-                                       "Channel(%s) is not installed no need to collect data from kernel",
+                                       "Channel%s is not installed no need to collect data from kernel",
                                        pim_str_sg_dump(&sg));
                }
                return;
@@ -1049,7 +1101,7 @@ void pim_mroute_update_counters(struct channel_oil *c_oil)
                        sg.grp = c_oil->oil.mfcc_mcastgrp;
 
                        zlog_warn(
-                               "ioctl(SIOCGETSGCNT=%lu) failure for (S,G)=(%s): errno=%d: %s",
+                               "ioctl(SIOCGETSGCNT=%lu) failure for (S,G)=%s: errno=%d: %s",
                                (unsigned long)SIOCGETSGCNT,
                                pim_str_sg_dump(&sg), errno,
                                safe_strerror(errno));