]> git.puffer.fish Git - mirror/frr.git/commitdiff
pimd: Allow more immediate null registers to be sent in the vxlan code
authorDonald Sharp <sharpd@nvidia.com>
Sat, 12 Aug 2023 04:14:00 +0000 (00:14 -0400)
committerDonald Sharp <sharpd@nvidia.com>
Sat, 12 Aug 2023 15:48:15 +0000 (11:48 -0400)
When a pim vxlan S,G is created, the code attempts to send out a NULL
register.  This is used to build the S,G tree from the RP to the
FHR.  Upon initial startup it is not unusual for the pim vxlan state
be fully ready to go but the RP is still not reachable.  Let's add
a bit of a pump prime that allows the vxlan code to re-attempt to
send the null register for vxlan S,G's that the RP's outgoing
interface changed from unknown to an actual interface.

Signed-off-by: Donald Sharp <sharpd@nvidia.com>
pimd/pim_nht.c
pimd/pim_vxlan.c
pimd/pim_vxlan.h

index 5f0f2a5933dc8bc043b9a7fee011b9df21bb740c..10d80312e25431a9d603c87b68d5f231dea82030 100644 (file)
@@ -31,6 +31,8 @@
 #include "pim_zlookup.h"
 #include "pim_rp.h"
 #include "pim_addr.h"
+#include "pim_register.h"
+#include "pim_vxlan.h"
 
 /**
  * pim_sendmsg_zebra_rnh -- Format and send a nexthop register/Unregister
@@ -399,17 +401,28 @@ static void pim_update_rp_nh(struct pim_instance *pim,
 {
        struct listnode *node = NULL;
        struct rp_info *rp_info = NULL;
+       struct interface *ifp;
 
        /*Traverse RP list and update each RP Nexthop info */
        for (ALL_LIST_ELEMENTS_RO(pnc->rp_list, node, rp_info)) {
                if (pim_rpf_addr_is_inaddr_any(&rp_info->rp))
                        continue;
 
+               ifp = rp_info->rp.source_nexthop.interface;
                // Compute PIM RPF using cached nexthop
                if (!pim_ecmp_nexthop_lookup(pim, &rp_info->rp.source_nexthop,
                                             rp_info->rp.rpf_addr,
                                             &rp_info->group, 1))
                        pim_rp_nexthop_del(rp_info);
+
+               /*
+                * If we transition from no path to a path
+                * we need to search through all the vxlan's
+                * that use this rp and send NULL registers
+                * for all the vxlan S,G streams
+                */
+               if (!ifp && rp_info->rp.source_nexthop.interface)
+                       pim_vxlan_rp_info_is_alive(pim, &rp_info->rp);
        }
 }
 
@@ -436,6 +449,16 @@ static int pim_update_upstream_nh_helper(struct hash_bucket *bucket, void *arg)
                (rpf_result == PIM_RPF_FAILURE && old.source_nexthop.interface))
                pim_zebra_upstream_rpf_changed(pim, up, &old);
 
+       /*
+        * If we are a VXLAN source and we are transitioning from not
+        * having an outgoing interface to having an outgoing interface
+        * let's immediately send the null pim register
+        */
+       if (!old.source_nexthop.interface && up->rpf.source_nexthop.interface &&
+           PIM_UPSTREAM_FLAG_TEST_SRC_VXLAN_ORIG(up->flags) &&
+           (up->reg_state == PIM_REG_NOINFO || up->reg_state == PIM_REG_JOIN)) {
+               pim_null_register_send(up);
+       }
 
        if (PIM_DEBUG_PIM_NHT) {
                zlog_debug(
index 8df3c90f006c5b51a0e096f123a4bb64877005a6..9650da89a8ab747138206c5d73e2193fb9454a33 100644 (file)
@@ -32,6 +32,41 @@ static void pim_vxlan_work_timer_setup(bool start);
 static void pim_vxlan_set_peerlink_rif(struct pim_instance *pim,
                        struct interface *ifp);
 
+/*
+ * The rp info has gone from no path to having a
+ * path.  Let's immediately send out the null pim register
+ * as that else we will be sitting for up to 60 seconds waiting
+ * for it too pop.  Which is not cool.
+ */
+void pim_vxlan_rp_info_is_alive(struct pim_instance *pim,
+                               struct pim_rpf *rpg_changed)
+{
+       struct listnode *listnode;
+       struct pim_vxlan_sg *vxlan_sg;
+       struct pim_rpf *rpg;
+
+       /*
+        * No vxlan here, move along, nothing to see
+        */
+       if (!vxlan_info.work_list)
+               return;
+
+       for (listnode = vxlan_info.work_list->head; listnode;
+            listnode = listnode->next) {
+               vxlan_sg = listgetdata(listnode);
+
+               rpg = RP(pim, vxlan_sg->up->sg.grp);
+
+               /*
+                * If the rp is the same we should send
+                */
+               if (rpg == rpg_changed) {
+                       zlog_debug("VXLAN RP INFO is alive sending");
+                       pim_null_register_send(vxlan_sg->up);
+               }
+       }
+}
+
 /*************************** vxlan work list **********************************
  * A work list is maintained for staggered generation of pim null register
  * messages for vxlan SG entries that are in a reg_join state.
@@ -66,6 +101,7 @@ static void pim_vxlan_do_reg_work(void)
 
        for (; listnode; listnode = listnode->next) {
                vxlan_sg = (struct pim_vxlan_sg *)listnode->data;
+
                if (vxlan_sg->up && (vxlan_sg->up->reg_state == PIM_REG_JOIN)) {
                        if (PIM_DEBUG_VXLAN)
                                zlog_debug("vxlan SG %s periodic NULL register",
index 9a135ca6b8337a88b203ef7484a9c5628b813691..5039bf65409785d97628137a7dd5fb74ab299054 100644 (file)
@@ -135,6 +135,9 @@ extern bool pim_vxlan_do_mlag_reg(void);
 extern void pim_vxlan_inherit_mlag_flags(struct pim_instance *pim,
                struct pim_upstream *up, bool inherit);
 
+extern void pim_vxlan_rp_info_is_alive(struct pim_instance *pim,
+                                      struct pim_rpf *rpg_changed);
+
 /* Shutdown of PIM stop the thread */
 extern void pim_vxlan_terminate(void);
 #endif /* PIM_VXLAN_H */