summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pimd/pim_bsm.c86
-rw-r--r--pimd/pim_bsm.h1
-rw-r--r--pimd/pim_hello.c13
3 files changed, 100 insertions, 0 deletions
diff --git a/pimd/pim_bsm.c b/pimd/pim_bsm.c
index 54a082ffeb..4ba8d08fe3 100644
--- a/pimd/pim_bsm.c
+++ b/pimd/pim_bsm.c
@@ -907,6 +907,92 @@ static void pim_bsm_fwd_whole_sz(struct pim_instance *pim, uint8_t *buf,
}
}
+bool pim_bsm_new_nbr_fwd(struct pim_neighbor *neigh, struct interface *ifp)
+{
+ struct in_addr dst_addr;
+ struct pim_interface *pim_ifp;
+ struct bsm_scope *scope;
+ struct listnode *bsm_ln;
+ struct bsm_info *bsminfo;
+ char neigh_src_str[INET_ADDRSTRLEN];
+ uint32_t pim_mtu;
+ bool no_fwd = true;
+ bool ret = false;
+
+ if (PIM_DEBUG_BSM) {
+ pim_inet4_dump("<src?>", neigh->source_addr, neigh_src_str,
+ sizeof(neigh_src_str));
+ zlog_debug("%s: New neighbor %s seen on %s",
+ __PRETTY_FUNCTION__, neigh_src_str, ifp->name);
+ }
+
+ pim_ifp = ifp->info;
+
+ /* DR only forwards BSM packet */
+ if (pim_ifp->pim_dr_addr.s_addr == pim_ifp->primary_address.s_addr) {
+ if (PIM_DEBUG_BSM)
+ zlog_debug(
+ "%s: It is not DR, so don't forward BSM packet",
+ __PRETTY_FUNCTION__);
+ }
+
+ if (!pim_ifp->bsm_enable) {
+ if (PIM_DEBUG_BSM)
+ zlog_debug("%s: BSM proc not enabled on %s",
+ __PRETTY_FUNCTION__, ifp->name);
+ return ret;
+ }
+
+ scope = &pim_ifp->pim->global_scope;
+
+ if (!scope->bsm_list->count) {
+ if (PIM_DEBUG_BSM)
+ zlog_debug("%s: BSM list for the scope is empty",
+ __PRETTY_FUNCTION__);
+ return ret;
+ }
+
+ if (!pim_ifp->ucast_bsm_accept) {
+ dst_addr = qpim_all_pim_routers_addr;
+ if (PIM_DEBUG_BSM)
+ zlog_debug("%s: Sending BSM mcast to %s",
+ __PRETTY_FUNCTION__, neigh_src_str);
+ } else {
+ dst_addr = neigh->source_addr;
+ if (PIM_DEBUG_BSM)
+ zlog_debug("%s: Sending BSM ucast to %s",
+ __PRETTY_FUNCTION__, neigh_src_str);
+ }
+ pim_mtu = ifp->mtu - MAX_IP_HDR_LEN;
+ pim_hello_require(ifp);
+
+ for (ALL_LIST_ELEMENTS_RO(scope->bsm_list, bsm_ln, bsminfo)) {
+ if (pim_mtu < bsminfo->size) {
+ ret = pim_bsm_frag_send(bsminfo->bsm, bsminfo->size,
+ ifp, pim_mtu, dst_addr, no_fwd);
+ if (!ret) {
+ if (PIM_DEBUG_BSM)
+ zlog_debug(
+ "%s: pim_bsm_frag_send failed",
+ __PRETTY_FUNCTION__);
+ }
+ } else {
+ /* Pim header needs to be constructed */
+ pim_msg_build_header(bsminfo->bsm, bsminfo->size,
+ PIM_MSG_TYPE_BOOTSTRAP, no_fwd);
+ ret = pim_bsm_send_intf(bsminfo->bsm, bsminfo->size,
+ ifp, dst_addr);
+ if (!ret) {
+ if (PIM_DEBUG_BSM)
+ zlog_debug(
+ "%s: pim_bsm_frag_send failed",
+ __PRETTY_FUNCTION__);
+ }
+ }
+ }
+ return ret;
+}
+
struct bsgrp_node *pim_bsm_get_bsgrp_node(struct bsm_scope *scope,
struct prefix *grp)
{
diff --git a/pimd/pim_bsm.h b/pimd/pim_bsm.h
index 79aa805767..0758c94f19 100644
--- a/pimd/pim_bsm.h
+++ b/pimd/pim_bsm.h
@@ -192,6 +192,7 @@ int pim_bsm_process(struct interface *ifp,
uint8_t *buf,
uint32_t buf_size,
bool no_fwd);
+bool pim_bsm_new_nbr_fwd(struct pim_neighbor *neigh, struct interface *ifp);
struct bsgrp_node *pim_bsm_get_bsgrp_node(struct bsm_scope *scope,
struct prefix *grp);
#endif
diff --git a/pimd/pim_hello.c b/pimd/pim_hello.c
index e482d321a4..721d153d76 100644
--- a/pimd/pim_hello.c
+++ b/pimd/pim_hello.c
@@ -31,6 +31,7 @@
#include "pim_iface.h"
#include "pim_neighbor.h"
#include "pim_upstream.h"
+#include "pim_bsm.h"
static void on_trace(const char *label, struct interface *ifp,
struct in_addr src)
@@ -367,6 +368,12 @@ int pim_hello_recv(struct interface *ifp, struct in_addr src_addr,
}
FREE_ADDR_LIST_THEN_RETURN(-8);
}
+ /* Forward BSM if required */
+ if (!pim_bsm_new_nbr_fwd(neigh, ifp)) {
+ if (PIM_DEBUG_PIM_HELLO)
+ zlog_debug("%s: forwarding bsm to new nbr failed",
+ __PRETTY_FUNCTION__);
+ }
/* actual addr list has been saved under neighbor */
return 0;
@@ -420,6 +427,12 @@ int pim_hello_recv(struct interface *ifp, struct in_addr src_addr,
}
FREE_ADDR_LIST_THEN_RETURN(-9);
}
+ /* Forward BSM if required */
+ if (!pim_bsm_new_nbr_fwd(neigh, ifp)) {
+ if (PIM_DEBUG_PIM_HELLO)
+ zlog_debug("%s: forwarding bsm to new nbr failed",
+ __PRETTY_FUNCTION__);
+ }
/* actual addr list is saved under neighbor */
return 0;