#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
{
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);
}
}
(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(
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.
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",
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 */