1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * pim_bsm.c: PIM BSM handling routines
5 * Copyright (C) 2018-19 Vmware, Inc.
15 #include "pim_iface.h"
16 #include "pim_instance.h"
17 #include "pim_neighbor.h"
19 #include "pim_hello.h"
24 #include "pim_zebra.h"
27 /* Functions forward declaration */
28 static void pim_bs_timer_start(struct bsm_scope
*scope
, int bs_timeout
);
29 static void pim_g2rp_timer_start(struct bsm_rpinfo
*bsrp
, int hold_time
);
30 static inline void pim_g2rp_timer_restart(struct bsm_rpinfo
*bsrp
,
34 DEFINE_MTYPE_STATIC(PIMD
, PIM_BSGRP_NODE
, "PIM BSR advertised grp info");
35 DEFINE_MTYPE_STATIC(PIMD
, PIM_BSRP_INFO
, "PIM BSR advertised RP info");
36 DEFINE_MTYPE_STATIC(PIMD
, PIM_BSM_FRAG
, "PIM BSM fragment");
37 DEFINE_MTYPE_STATIC(PIMD
, PIM_BSM_PKT_VAR_MEM
, "PIM BSM Packet");
39 /* All bsm packets forwarded shall be fit within ip mtu less iphdr(max) */
40 #define MAX_IP_HDR_LEN 24
42 /* pim_bsm_write_config - Write the interface pim bsm configuration.*/
43 void pim_bsm_write_config(struct vty
*vty
, struct interface
*ifp
)
45 struct pim_interface
*pim_ifp
= ifp
->info
;
48 if (!pim_ifp
->bsm_enable
)
49 vty_out(vty
, " no " PIM_AF_NAME
" pim bsm\n");
50 if (!pim_ifp
->ucast_bsm_accept
)
51 vty_out(vty
, " no " PIM_AF_NAME
" pim unicast-bsm\n");
55 static void pim_bsm_rpinfo_free(struct bsm_rpinfo
*bsrp_info
)
57 EVENT_OFF(bsrp_info
->g2rp_timer
);
58 XFREE(MTYPE_PIM_BSRP_INFO
, bsrp_info
);
61 static void pim_bsm_rpinfos_free(struct bsm_rpinfos_head
*head
)
63 struct bsm_rpinfo
*bsrp_info
;
65 while ((bsrp_info
= bsm_rpinfos_pop(head
)))
66 pim_bsm_rpinfo_free(bsrp_info
);
69 static void pim_free_bsgrp_data(struct bsgrp_node
*bsgrp_node
)
71 pim_bsm_rpinfos_free(bsgrp_node
->bsrp_list
);
72 pim_bsm_rpinfos_free(bsgrp_node
->partial_bsrp_list
);
73 XFREE(MTYPE_PIM_BSGRP_NODE
, bsgrp_node
);
76 static void pim_free_bsgrp_node(struct route_table
*rt
, struct prefix
*grp
)
78 struct route_node
*rn
;
80 rn
= route_node_lookup(rt
, grp
);
83 route_unlock_node(rn
);
84 route_unlock_node(rn
);
88 static void pim_bsm_frag_free(struct bsm_frag
*bsfrag
)
90 XFREE(MTYPE_PIM_BSM_FRAG
, bsfrag
);
93 static void pim_bsm_frags_free(struct bsm_scope
*scope
)
95 struct bsm_frag
*bsfrag
;
97 while ((bsfrag
= bsm_frags_pop(scope
->bsm_frags
)))
98 pim_bsm_frag_free(bsfrag
);
101 int pim_bsm_rpinfo_cmp(const struct bsm_rpinfo
*node1
,
102 const struct bsm_rpinfo
*node2
)
104 /* RP election Algo :
105 * Step-1 : Loweset Rp priority will have higher precedance.
106 * Step-2 : If priority same then higher hash val will have
108 * Step-3 : If Hash val is same then highest rp address will
111 if (node1
->rp_prio
< node2
->rp_prio
)
113 if (node1
->rp_prio
> node2
->rp_prio
)
115 if (node1
->hash
< node2
->hash
)
117 if (node1
->hash
> node2
->hash
)
119 return pim_addr_cmp(node2
->rp_address
, node1
->rp_address
);
122 static struct bsgrp_node
*pim_bsm_new_bsgrp_node(struct route_table
*rt
,
125 struct route_node
*rn
;
126 struct bsgrp_node
*bsgrp
;
128 rn
= route_node_get(rt
, grp
);
130 zlog_warn("%s: route node creation failed", __func__
);
133 bsgrp
= XCALLOC(MTYPE_PIM_BSGRP_NODE
, sizeof(struct bsgrp_node
));
136 bsm_rpinfos_init(bsgrp
->bsrp_list
);
137 bsm_rpinfos_init(bsgrp
->partial_bsrp_list
);
139 prefix_copy(&bsgrp
->group
, grp
);
143 static void pim_on_bs_timer(struct event
*t
)
145 struct route_node
*rn
;
146 struct bsm_scope
*scope
;
147 struct bsgrp_node
*bsgrp_node
;
148 struct bsm_rpinfo
*bsrp
;
150 scope
= EVENT_ARG(t
);
151 EVENT_OFF(scope
->bs_timer
);
154 zlog_debug("%s: Bootstrap Timer expired for scope: %d",
155 __func__
, scope
->sz_id
);
157 pim_nht_bsr_del(scope
->pim
, scope
->current_bsr
);
158 /* Reset scope zone data */
159 scope
->state
= ACCEPT_ANY
;
160 scope
->current_bsr
= PIMADDR_ANY
;
161 scope
->current_bsr_prio
= 0;
162 scope
->current_bsr_first_ts
= 0;
163 scope
->current_bsr_last_ts
= 0;
164 scope
->bsm_frag_tag
= 0;
165 pim_bsm_frags_free(scope
);
167 for (rn
= route_top(scope
->bsrp_table
); rn
; rn
= route_next(rn
)) {
169 bsgrp_node
= (struct bsgrp_node
*)rn
->info
;
172 zlog_debug("%s: bsgrp_node is null", __func__
);
175 /* Give grace time for rp to continue for another hold time */
176 bsrp
= bsm_rpinfos_first(bsgrp_node
->bsrp_list
);
178 pim_g2rp_timer_restart(bsrp
, bsrp
->rp_holdtime
);
180 /* clear pending list */
181 pim_bsm_rpinfos_free(bsgrp_node
->partial_bsrp_list
);
182 bsgrp_node
->pend_rp_cnt
= 0;
186 static void pim_bs_timer_stop(struct bsm_scope
*scope
)
189 zlog_debug("%s : BS timer being stopped of sz: %d", __func__
,
191 EVENT_OFF(scope
->bs_timer
);
194 static void pim_bs_timer_start(struct bsm_scope
*scope
, int bs_timeout
)
198 zlog_debug("%s : Invalid scope(NULL).", __func__
);
201 EVENT_OFF(scope
->bs_timer
);
204 "%s : starting bs timer for scope %d with timeout %d secs",
205 __func__
, scope
->sz_id
, bs_timeout
);
206 event_add_timer(router
->master
, pim_on_bs_timer
, scope
, bs_timeout
,
210 static inline void pim_bs_timer_restart(struct bsm_scope
*scope
, int bs_timeout
)
212 pim_bs_timer_start(scope
, bs_timeout
);
215 void pim_bsm_proc_init(struct pim_instance
*pim
)
217 memset(&pim
->global_scope
, 0, sizeof(struct bsm_scope
));
219 pim
->global_scope
.sz_id
= PIM_GBL_SZ_ID
;
220 pim
->global_scope
.bsrp_table
= route_table_init();
221 pim
->global_scope
.accept_nofwd_bsm
= true;
222 pim
->global_scope
.state
= NO_INFO
;
223 pim
->global_scope
.pim
= pim
;
224 bsm_frags_init(pim
->global_scope
.bsm_frags
);
225 pim_bs_timer_start(&pim
->global_scope
, PIM_BS_TIME
);
228 void pim_bsm_proc_free(struct pim_instance
*pim
)
230 struct route_node
*rn
;
231 struct bsgrp_node
*bsgrp
;
233 pim_bs_timer_stop(&pim
->global_scope
);
234 pim_bsm_frags_free(&pim
->global_scope
);
236 for (rn
= route_top(pim
->global_scope
.bsrp_table
); rn
;
237 rn
= route_next(rn
)) {
241 pim_free_bsgrp_data(bsgrp
);
244 route_table_finish(pim
->global_scope
.bsrp_table
);
247 static bool is_hold_time_elapsed(void *data
)
249 struct bsm_rpinfo
*bsrp
;
253 if (bsrp
->elapse_time
< bsrp
->rp_holdtime
)
259 static void pim_on_g2rp_timer(struct event
*t
)
261 struct bsm_rpinfo
*bsrp
;
262 struct bsm_rpinfo
*bsrp_node
;
263 struct bsgrp_node
*bsgrp_node
;
264 struct pim_instance
*pim
;
265 struct rp_info
*rp_info
;
266 struct route_node
*rn
;
271 EVENT_OFF(bsrp
->g2rp_timer
);
272 bsgrp_node
= bsrp
->bsgrp_node
;
274 /* elapse time is the hold time of expired node */
275 elapse
= bsrp
->rp_holdtime
;
276 bsrp_addr
= bsrp
->rp_address
;
278 /* update elapse for all bsrp nodes */
279 frr_each_safe (bsm_rpinfos
, bsgrp_node
->bsrp_list
, bsrp_node
) {
280 bsrp_node
->elapse_time
+= elapse
;
282 if (is_hold_time_elapsed(bsrp_node
)) {
283 bsm_rpinfos_del(bsgrp_node
->bsrp_list
, bsrp_node
);
284 pim_bsm_rpinfo_free(bsrp_node
);
288 /* Get the next elected rp node */
289 bsrp
= bsm_rpinfos_first(bsgrp_node
->bsrp_list
);
290 pim
= bsgrp_node
->scope
->pim
;
291 rn
= route_node_lookup(pim
->rp_table
, &bsgrp_node
->group
);
294 zlog_warn("%s: Route node doesn't exist", __func__
);
298 rp_info
= (struct rp_info
*)rn
->info
;
301 route_unlock_node(rn
);
305 if (rp_info
->rp_src
!= RP_SRC_STATIC
) {
306 /* If new rp available, change it else delete the existing */
308 pim_g2rp_timer_start(
309 bsrp
, (bsrp
->rp_holdtime
- bsrp
->elapse_time
));
310 pim_rp_change(pim
, bsrp
->rp_address
, bsgrp_node
->group
,
313 pim_rp_del(pim
, bsrp_addr
, bsgrp_node
->group
, NULL
,
318 if (!bsm_rpinfos_count(bsgrp_node
->bsrp_list
)
319 && !bsm_rpinfos_count(bsgrp_node
->partial_bsrp_list
)) {
320 pim_free_bsgrp_node(pim
->global_scope
.bsrp_table
,
322 pim_free_bsgrp_data(bsgrp_node
);
326 static void pim_g2rp_timer_start(struct bsm_rpinfo
*bsrp
, int hold_time
)
330 zlog_debug("%s : Invalid brsp(NULL).", __func__
);
333 EVENT_OFF(bsrp
->g2rp_timer
);
336 "%s : starting g2rp timer for grp: %pFX - rp: %pPAs with timeout %d secs(Actual Hold time : %d secs)",
337 __func__
, &bsrp
->bsgrp_node
->group
, &bsrp
->rp_address
,
338 hold_time
, bsrp
->rp_holdtime
);
340 event_add_timer(router
->master
, pim_on_g2rp_timer
, bsrp
, hold_time
,
344 static inline void pim_g2rp_timer_restart(struct bsm_rpinfo
*bsrp
,
347 pim_g2rp_timer_start(bsrp
, hold_time
);
350 static void pim_g2rp_timer_stop(struct bsm_rpinfo
*bsrp
)
356 zlog_debug("%s : stopping g2rp timer for grp: %pFX - rp: %pPAs",
357 __func__
, &bsrp
->bsgrp_node
->group
,
360 EVENT_OFF(bsrp
->g2rp_timer
);
363 static bool is_hold_time_zero(void *data
)
365 struct bsm_rpinfo
*bsrp
;
369 if (bsrp
->rp_holdtime
)
375 static void pim_instate_pend_list(struct bsgrp_node
*bsgrp_node
)
377 struct bsm_rpinfo
*active
;
378 struct bsm_rpinfo
*pend
;
379 struct rp_info
*rp_info
;
380 struct route_node
*rn
;
381 struct pim_instance
*pim
;
382 struct rp_info
*rp_all
;
383 struct prefix group_all
;
384 bool had_rp_node
= true;
386 pim
= bsgrp_node
->scope
->pim
;
387 active
= bsm_rpinfos_first(bsgrp_node
->bsrp_list
);
389 /* Remove nodes with hold time 0 & check if list still has a head */
390 frr_each_safe (bsm_rpinfos
, bsgrp_node
->partial_bsrp_list
, pend
) {
391 if (is_hold_time_zero(pend
)) {
392 bsm_rpinfos_del(bsgrp_node
->partial_bsrp_list
, pend
);
393 pim_bsm_rpinfo_free(pend
);
397 pend
= bsm_rpinfos_first(bsgrp_node
->partial_bsrp_list
);
399 if (!pim_get_all_mcast_group(&group_all
))
402 rp_all
= pim_rp_find_match_group(pim
, &group_all
);
403 rn
= route_node_lookup(pim
->rp_table
, &bsgrp_node
->group
);
406 pim_g2rp_timer_start(pend
, pend
->rp_holdtime
);
408 /* if rp node doesn't exist or exist but not configured(rp_all),
409 * install the rp from head(if exists) of partial list. List is
410 * is sorted such that head is the elected RP for the group.
412 if (!rn
|| (prefix_same(&rp_all
->group
, &bsgrp_node
->group
) &&
413 pim_rpf_addr_is_inaddr_any(&rp_all
->rp
))) {
415 zlog_debug("%s: Route node doesn't exist", __func__
);
417 pim_rp_new(pim
, pend
->rp_address
, bsgrp_node
->group
,
421 rp_info
= (struct rp_info
*)rn
->info
;
423 route_unlock_node(rn
);
425 pim_rp_new(pim
, pend
->rp_address
,
426 bsgrp_node
->group
, NULL
, RP_SRC_BSR
);
431 /* We didn't have rp node and pending list is empty(unlikely), cleanup*/
432 if ((!had_rp_node
) && (!pend
)) {
433 pim_free_bsgrp_node(bsgrp_node
->scope
->bsrp_table
,
435 pim_free_bsgrp_data(bsgrp_node
);
439 if ((had_rp_node
) && (rp_info
->rp_src
!= RP_SRC_STATIC
)) {
440 /* This means we searched and got rp node, needs unlock */
441 route_unlock_node(rn
);
443 if (active
&& pend
) {
444 if (pim_addr_cmp(active
->rp_address
, pend
->rp_address
))
445 pim_rp_change(pim
, pend
->rp_address
,
446 bsgrp_node
->group
, RP_SRC_BSR
);
449 /* Possible when the first BSM has group with 0 rp count */
450 if ((!active
) && (!pend
)) {
453 "%s: Both bsrp and partial list are empty",
456 pim_free_bsgrp_node(bsgrp_node
->scope
->bsrp_table
,
458 pim_free_bsgrp_data(bsgrp_node
);
462 /* Possible when a group with 0 rp count received in BSM */
463 if ((active
) && (!pend
)) {
464 pim_rp_del(pim
, active
->rp_address
, bsgrp_node
->group
,
466 pim_free_bsgrp_node(bsgrp_node
->scope
->bsrp_table
,
469 zlog_debug("%s:Pend List is null,del grp node",
472 pim_free_bsgrp_data(bsgrp_node
);
477 if ((had_rp_node
) && (rp_info
->rp_src
== RP_SRC_STATIC
)) {
478 /* We need to unlock rn this case */
479 route_unlock_node(rn
);
480 /* there is a chance that static rp exist and bsrp cleaned
481 * so clean bsgrp node if pending list empty
486 "%s: Partial list is empty, static rp exists",
488 pim_free_bsgrp_node(bsgrp_node
->scope
->bsrp_table
,
490 pim_free_bsgrp_data(bsgrp_node
);
495 /* swap the list & delete all nodes in partial list (old bsrp_list)
497 * active is head of bsrp list
498 * pend is head of partial list
500 * active is head of partial list
501 * pend is head of bsrp list
502 * So check appriate head after swap and clean the new partial list
504 bsm_rpinfos_swap_all(bsgrp_node
->bsrp_list
,
505 bsgrp_node
->partial_bsrp_list
);
508 pim_g2rp_timer_stop(active
);
509 pim_bsm_rpinfos_free(bsgrp_node
->partial_bsrp_list
);
512 static bool is_preferred_bsr(struct pim_instance
*pim
, pim_addr bsr
,
515 if (!pim_addr_cmp(bsr
, pim
->global_scope
.current_bsr
))
518 if (bsr_prio
> pim
->global_scope
.current_bsr_prio
)
521 else if (bsr_prio
== pim
->global_scope
.current_bsr_prio
) {
522 if (pim_addr_cmp(bsr
, pim
->global_scope
.current_bsr
) >= 0)
530 static void pim_bsm_update(struct pim_instance
*pim
, pim_addr bsr
,
533 if (pim_addr_cmp(bsr
, pim
->global_scope
.current_bsr
)) {
534 pim_nht_bsr_del(pim
, pim
->global_scope
.current_bsr
);
535 pim_nht_bsr_add(pim
, bsr
);
537 pim
->global_scope
.current_bsr
= bsr
;
538 pim
->global_scope
.current_bsr_first_ts
=
539 pim_time_monotonic_sec();
540 pim
->global_scope
.state
= ACCEPT_PREFERRED
;
542 pim
->global_scope
.current_bsr_prio
= bsr_prio
;
543 pim
->global_scope
.current_bsr_last_ts
= pim_time_monotonic_sec();
546 void pim_bsm_clear(struct pim_instance
*pim
)
548 struct route_node
*rn
;
549 struct route_node
*rpnode
;
550 struct bsgrp_node
*bsgrp
;
553 struct rp_info
*rp_all
;
554 struct pim_upstream
*up
;
555 struct rp_info
*rp_info
;
556 bool upstream_updated
= false;
558 pim_nht_bsr_del(pim
, pim
->global_scope
.current_bsr
);
560 /* Reset scope zone data */
561 pim
->global_scope
.accept_nofwd_bsm
= false;
562 pim
->global_scope
.state
= ACCEPT_ANY
;
563 pim
->global_scope
.current_bsr
= PIMADDR_ANY
;
564 pim
->global_scope
.current_bsr_prio
= 0;
565 pim
->global_scope
.current_bsr_first_ts
= 0;
566 pim
->global_scope
.current_bsr_last_ts
= 0;
567 pim
->global_scope
.bsm_frag_tag
= 0;
568 pim_bsm_frags_free(&pim
->global_scope
);
570 pim_bs_timer_stop(&pim
->global_scope
);
572 for (rn
= route_top(pim
->global_scope
.bsrp_table
); rn
;
573 rn
= route_next(rn
)) {
578 rpnode
= route_node_lookup(pim
->rp_table
, &bsgrp
->group
);
581 pim_free_bsgrp_node(bsgrp
->scope
->bsrp_table
,
583 pim_free_bsgrp_data(bsgrp
);
587 rp_info
= (struct rp_info
*)rpnode
->info
;
589 if ((!rp_info
) || (rp_info
->rp_src
!= RP_SRC_BSR
)) {
590 pim_free_bsgrp_node(bsgrp
->scope
->bsrp_table
,
592 pim_free_bsgrp_data(bsgrp
);
596 /* Deregister addr with Zebra NHT */
597 nht_p
= rp_info
->rp
.rpf_addr
;
599 if (PIM_DEBUG_PIM_NHT_RP
) {
600 zlog_debug("%s: Deregister RP addr %pPA with Zebra ",
604 pim_delete_tracked_nexthop(pim
, nht_p
, NULL
, rp_info
);
606 if (!pim_get_all_mcast_group(&g_all
))
609 rp_all
= pim_rp_find_match_group(pim
, &g_all
);
611 if (rp_all
== rp_info
) {
612 rp_all
->rp
.rpf_addr
= PIMADDR_ANY
;
615 /* Delete the rp_info from rp-list */
616 listnode_delete(pim
->rp_list
, rp_info
);
618 /* Delete the rp node from rp_table */
620 route_unlock_node(rpnode
);
621 route_unlock_node(rpnode
);
622 XFREE(MTYPE_PIM_RP
, rp_info
);
625 pim_free_bsgrp_node(bsgrp
->scope
->bsrp_table
, &bsgrp
->group
);
626 pim_free_bsgrp_data(bsgrp
);
628 pim_rp_refresh_group_to_rp_mapping(pim
);
631 frr_each (rb_pim_upstream
, &pim
->upstream_head
, up
) {
632 /* Find the upstream (*, G) whose upstream address is same as
635 if (!pim_addr_is_any(up
->sg
.src
))
639 struct rp_info
*trp_info
;
641 pim_addr_to_prefix(&grp
, up
->sg
.grp
);
642 trp_info
= pim_rp_find_match_group(pim
, &grp
);
644 /* RP not found for the group grp */
645 if (pim_rpf_addr_is_inaddr_any(&trp_info
->rp
)) {
646 pim_upstream_rpf_clear(pim
, up
);
647 pim_rp_set_upstream_addr(pim
, &up
->upstream_addr
,
648 up
->sg
.src
, up
->sg
.grp
);
650 /* RP found for the group grp */
651 pim_upstream_update(pim
, up
);
652 upstream_updated
= true;
656 if (upstream_updated
)
657 pim_zebra_update_all_interfaces(pim
);
660 static bool pim_bsm_send_intf(uint8_t *buf
, int len
, struct interface
*ifp
,
663 struct pim_interface
*pim_ifp
;
669 zlog_debug("%s: Pim interface not available for %s",
670 __func__
, ifp
->name
);
674 if (pim_ifp
->pim_sock_fd
== -1) {
676 zlog_debug("%s: Pim sock not available for %s",
677 __func__
, ifp
->name
);
681 if (pim_msg_send(pim_ifp
->pim_sock_fd
, pim_ifp
->primary_address
,
682 dst_addr
, buf
, len
, ifp
)) {
683 zlog_warn("%s: Could not send BSM message on interface: %s",
684 __func__
, ifp
->name
);
688 if (!pim_ifp
->pim_passive_enable
)
689 pim_ifp
->pim_ifstat_bsm_tx
++;
691 pim_ifp
->pim
->bsm_sent
++;
695 static bool pim_bsm_frag_send(uint8_t *buf
, uint32_t len
, struct interface
*ifp
,
696 uint32_t pim_mtu
, pim_addr dst_addr
, bool no_fwd
)
698 struct pim_interface
*pim_ifp
= ifp
->info
;
699 struct bsmmsg_grpinfo
*grpinfo
, *curgrp
;
700 uint8_t *firstgrp_ptr
;
703 uint32_t parsed_len
= 0;
704 uint32_t this_pkt_rem
;
705 uint32_t copy_byte_count
;
706 uint32_t this_pkt_len
;
707 uint8_t total_rp_cnt
;
711 bool pak_pending
= false;
713 /* MTU passed here is PIM MTU (IP MTU less IP Hdr) */
714 if (pim_mtu
< (PIM_MIN_BSM_LEN
)) {
716 "%s: mtu(pim mtu: %d) size less than minimum bootstrap len",
720 "%s: mtu (pim mtu:%d) less than minimum bootstrap len",
725 pak_start
= XCALLOC(MTYPE_PIM_BSM_PKT_VAR_MEM
, pim_mtu
);
729 /* Fill PIM header later before sending packet to calc checksum */
730 pkt
+= PIM_MSG_HEADER_LEN
;
731 buf
+= PIM_MSG_HEADER_LEN
;
733 /* copy bsm header to new packet at offset of pim hdr */
734 memcpy(pkt
, buf
, PIM_BSM_HDR_LEN
);
735 pkt
+= PIM_BSM_HDR_LEN
;
736 buf
+= PIM_BSM_HDR_LEN
;
737 parsed_len
+= (PIM_MSG_HEADER_LEN
+ PIM_BSM_HDR_LEN
);
739 /* Store the position of first grp ptr, which can be reused for
740 * next packet to start filling group. old bsm header and pim hdr
741 * remains. So need not be filled again for next packet onwards.
745 /* we received mtu excluding IP hdr len as param
746 * now this_pkt_rem is mtu excluding
747 * PIM_BSM_HDR_LEN + PIM_MSG_HEADER_LEN
749 this_pkt_rem
= pim_mtu
- (PIM_BSM_HDR_LEN
+ PIM_MSG_HEADER_LEN
);
751 /* For each group till the packet length parsed */
752 while (parsed_len
< len
) {
753 /* pkt ---> fragment's current pointer
754 * buf ---> input buffer's current pointer
755 * mtu ---> size of the pim packet - PIM header
756 * curgrp ---> current group on the fragment
757 * grpinfo ---> current group on the input buffer
758 * this_pkt_rem ---> bytes remaing on the current fragment
759 * rp_fit_cnt ---> num of rp for current grp that
761 * total_rp_cnt ---> total rp present for the group in the buf
762 * frag_rp_cnt ---> no of rp for the group to be fit in
764 * this_rp_cnt ---> how many rp have we parsed
766 grpinfo
= (struct bsmmsg_grpinfo
*)buf
;
767 memcpy(pkt
, buf
, PIM_BSM_GRP_LEN
);
768 curgrp
= (struct bsmmsg_grpinfo
*)pkt
;
769 parsed_len
+= PIM_BSM_GRP_LEN
;
770 pkt
+= PIM_BSM_GRP_LEN
;
771 buf
+= PIM_BSM_GRP_LEN
;
772 this_pkt_rem
-= PIM_BSM_GRP_LEN
;
774 /* initialize rp count and total_rp_cnt before the rp loop */
776 total_rp_cnt
= grpinfo
->frag_rp_count
;
778 /* Loop till all RPs for the group parsed */
779 while (this_rp_cnt
< total_rp_cnt
) {
780 /* All RP from a group processed here.
781 * group is pointed by grpinfo.
782 * At this point make sure buf pointing to a RP
785 rp_fit_cnt
= this_pkt_rem
/ PIM_BSM_RP_LEN
;
787 /* calculate how many rp am i going to copy in
790 if (rp_fit_cnt
> (total_rp_cnt
- this_rp_cnt
))
791 frag_rp_cnt
= total_rp_cnt
- this_rp_cnt
;
793 frag_rp_cnt
= rp_fit_cnt
;
795 /* populate the frag rp count for the current grp */
796 curgrp
->frag_rp_count
= frag_rp_cnt
;
797 copy_byte_count
= frag_rp_cnt
* PIM_BSM_RP_LEN
;
799 /* copy all the rp that we are fitting in this
802 memcpy(pkt
, buf
, copy_byte_count
);
803 this_rp_cnt
+= frag_rp_cnt
;
804 buf
+= copy_byte_count
;
805 pkt
+= copy_byte_count
;
806 parsed_len
+= copy_byte_count
;
807 this_pkt_rem
-= copy_byte_count
;
809 /* Either we couldn't fit all rp for the group or the
812 if ((this_rp_cnt
< total_rp_cnt
)
814 < (PIM_BSM_GRP_LEN
+ PIM_BSM_RP_LEN
))) {
815 /* No space to fit in more rp, send this pkt */
816 this_pkt_len
= pim_mtu
- this_pkt_rem
;
817 pim_msg_build_header(
818 pim_ifp
->primary_address
, dst_addr
,
819 pak_start
, this_pkt_len
,
820 PIM_MSG_TYPE_BOOTSTRAP
, no_fwd
);
821 pim_bsm_send_intf(pak_start
, this_pkt_len
, ifp
,
824 /* Construct next fragment. Reuse old packet */
826 this_pkt_rem
= pim_mtu
- (PIM_BSM_HDR_LEN
827 + PIM_MSG_HEADER_LEN
);
829 /* If pkt can't accommodate next group + at
830 * least one rp, we must break out of this inner
831 * loop and process next RP
833 if (total_rp_cnt
== this_rp_cnt
)
836 /* If some more RPs for the same group pending,
839 memcpy(pkt
, (uint8_t *)grpinfo
,
841 curgrp
= (struct bsmmsg_grpinfo
*)pkt
;
842 pkt
+= PIM_BSM_GRP_LEN
;
843 this_pkt_rem
-= PIM_BSM_GRP_LEN
;
846 /* We filled something but not yet sent out */
849 } /* while RP count */
850 } /*while parsed len */
852 /* Send if we have any unsent packet */
854 this_pkt_len
= pim_mtu
- this_pkt_rem
;
855 pim_msg_build_header(pim_ifp
->primary_address
, dst_addr
,
856 pak_start
, this_pkt_len
,
857 PIM_MSG_TYPE_BOOTSTRAP
, no_fwd
);
858 pim_bsm_send_intf(pak_start
, (pim_mtu
- this_pkt_rem
), ifp
,
861 XFREE(MTYPE_PIM_BSM_PKT_VAR_MEM
, pak_start
);
865 static void pim_bsm_fwd_whole_sz(struct pim_instance
*pim
, uint8_t *buf
,
866 uint32_t len
, int sz
)
868 struct interface
*ifp
;
869 struct pim_interface
*pim_ifp
;
875 /* For now only global scope zone is supported, so send on all
876 * pim interfaces in the vrf
878 dst_addr
= qpim_all_pim_routers_addr
;
879 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
881 if ((!pim_ifp
) || (!pim_ifp
->bsm_enable
))
886 * When a Bootstrap message is forwarded, it is forwarded out
887 * of every multicast-capable interface that has PIM neighbors.
889 * So skipping pim interfaces with no neighbors.
891 if (listcount(pim_ifp
->pim_neighbor_list
) == 0)
894 pim_hello_require(ifp
);
895 pim_mtu
= ifp
->mtu
- MAX_IP_HDR_LEN
;
897 ret
= pim_bsm_frag_send(buf
, len
, ifp
, pim_mtu
,
900 zlog_debug("%s: pim_bsm_frag_send returned %s",
901 __func__
, ret
? "TRUE" : "FALSE");
903 pim_msg_build_header(pim_ifp
->primary_address
, dst_addr
,
904 buf
, len
, PIM_MSG_TYPE_BOOTSTRAP
,
906 if (!pim_bsm_send_intf(buf
, len
, ifp
, dst_addr
)) {
909 "%s: pim_bsm_send_intf returned false",
916 bool pim_bsm_new_nbr_fwd(struct pim_neighbor
*neigh
, struct interface
*ifp
)
919 struct pim_interface
*pim_ifp
;
920 struct bsm_scope
*scope
;
921 struct bsm_frag
*bsfrag
;
927 zlog_debug("%s: New neighbor %pPA seen on %s", __func__
,
928 &neigh
->source_addr
, ifp
->name
);
932 /* DR only forwards BSM packet */
933 if (!pim_addr_cmp(pim_ifp
->pim_dr_addr
, pim_ifp
->primary_address
)) {
936 "%s: It is not DR, so don't forward BSM packet",
940 if (!pim_ifp
->bsm_enable
) {
942 zlog_debug("%s: BSM proc not enabled on %s", __func__
,
947 scope
= &pim_ifp
->pim
->global_scope
;
949 if (!bsm_frags_count(scope
->bsm_frags
)) {
951 zlog_debug("%s: BSM list for the scope is empty",
956 if (!pim_ifp
->ucast_bsm_accept
) {
957 dst_addr
= qpim_all_pim_routers_addr
;
959 zlog_debug("%s: Sending BSM mcast to %pPA", __func__
,
960 &neigh
->source_addr
);
962 dst_addr
= neigh
->source_addr
;
964 zlog_debug("%s: Sending BSM ucast to %pPA", __func__
,
965 &neigh
->source_addr
);
967 pim_mtu
= ifp
->mtu
- MAX_IP_HDR_LEN
;
968 pim_hello_require(ifp
);
970 frr_each (bsm_frags
, scope
->bsm_frags
, bsfrag
) {
971 if (pim_mtu
< bsfrag
->size
) {
972 ret
= pim_bsm_frag_send(bsfrag
->data
, bsfrag
->size
, ifp
,
973 pim_mtu
, dst_addr
, no_fwd
);
977 "%s: pim_bsm_frag_send failed",
981 /* Pim header needs to be constructed */
982 pim_msg_build_header(pim_ifp
->primary_address
, dst_addr
,
983 bsfrag
->data
, bsfrag
->size
,
984 PIM_MSG_TYPE_BOOTSTRAP
, no_fwd
);
985 ret
= pim_bsm_send_intf(bsfrag
->data
, bsfrag
->size
, ifp
,
990 "%s: pim_bsm_frag_send failed",
998 struct bsgrp_node
*pim_bsm_get_bsgrp_node(struct bsm_scope
*scope
,
1001 struct route_node
*rn
;
1002 struct bsgrp_node
*bsgrp
;
1004 rn
= route_node_lookup(scope
->bsrp_table
, grp
);
1007 zlog_debug("%s: Route node doesn't exist for the group",
1012 route_unlock_node(rn
);
1017 static uint32_t hash_calc_on_grp_rp(struct prefix group
, pim_addr rp
,
1018 uint8_t hashmasklen
)
1024 uint32_t mask
= 0xffffffff;
1026 /* mask to be made zero if hashmasklen is 0 because mask << 32
1027 * may not give 0. hashmasklen can be 0 to 32.
1029 if (hashmasklen
== 0)
1032 /* in_addr stores ip in big endian, hence network byte order
1033 * convert to uint32 before processing hash
1036 grpaddr
= ntohl(group
.u
.prefix4
.s_addr
);
1038 grpaddr
= group
.u
.prefix6
.s6_addr32
[0] ^ group
.u
.prefix6
.s6_addr32
[1] ^
1039 group
.u
.prefix6
.s6_addr32
[2] ^ group
.u
.prefix6
.s6_addr32
[3];
1041 /* Avoid shifting by 32 bit on a 32 bit register */
1043 grpaddr
= grpaddr
& ((mask
<< (32 - hashmasklen
)));
1045 grpaddr
= grpaddr
& mask
;
1048 rp_add
= ntohl(rp
.s_addr
);
1050 rp_add
= rp
.s6_addr32
[0] ^ rp
.s6_addr32
[1] ^ rp
.s6_addr32
[2] ^
1053 temp
= 1103515245 * ((1103515245 * (uint64_t)grpaddr
+ 12345) ^ rp_add
)
1055 hash
= temp
& (0x7fffffff);
1059 static bool pim_install_bsm_grp_rp(struct pim_instance
*pim
,
1060 struct bsgrp_node
*grpnode
,
1061 struct bsmmsg_rpinfo
*rp
)
1063 struct bsm_rpinfo
*bsm_rpinfo
;
1064 uint8_t hashMask_len
= pim
->global_scope
.hashMasklen
;
1066 /*memory allocation for bsm_rpinfo */
1067 bsm_rpinfo
= XCALLOC(MTYPE_PIM_BSRP_INFO
, sizeof(*bsm_rpinfo
));
1069 bsm_rpinfo
->rp_prio
= rp
->rp_pri
;
1070 bsm_rpinfo
->rp_holdtime
= rp
->rp_holdtime
;
1071 bsm_rpinfo
->rp_address
= rp
->rpaddr
.addr
;
1072 bsm_rpinfo
->elapse_time
= 0;
1074 /* Back pointer to the group node. */
1075 bsm_rpinfo
->bsgrp_node
= grpnode
;
1077 /* update hash for this rp node */
1078 bsm_rpinfo
->hash
= hash_calc_on_grp_rp(grpnode
->group
, rp
->rpaddr
.addr
,
1080 if (bsm_rpinfos_add(grpnode
->partial_bsrp_list
, bsm_rpinfo
) == NULL
) {
1083 "%s, bs_rpinfo node added to the partial bs_rplist.",
1089 zlog_debug("%s: list node not added", __func__
);
1091 XFREE(MTYPE_PIM_BSRP_INFO
, bsm_rpinfo
);
1095 static void pim_update_pending_rp_cnt(struct bsm_scope
*sz
,
1096 struct bsgrp_node
*bsgrp
,
1097 uint16_t bsm_frag_tag
,
1098 uint32_t total_rp_count
)
1100 if (bsgrp
->pend_rp_cnt
) {
1101 /* received bsm is different packet ,
1102 * it is not same fragment.
1104 if (bsm_frag_tag
!= bsgrp
->frag_tag
) {
1107 "%s,Received a new BSM ,so clear the pending bs_rpinfo list.",
1109 pim_bsm_rpinfos_free(bsgrp
->partial_bsrp_list
);
1110 bsgrp
->pend_rp_cnt
= total_rp_count
;
1113 bsgrp
->pend_rp_cnt
= total_rp_count
;
1115 bsgrp
->frag_tag
= bsm_frag_tag
;
1118 /* Parsing BSR packet and adding to partial list of corresponding bsgrp node */
1119 static bool pim_bsm_parse_install_g2rp(struct bsm_scope
*scope
, uint8_t *buf
,
1120 int buflen
, uint16_t bsm_frag_tag
)
1122 struct bsmmsg_grpinfo grpinfo
;
1123 struct bsmmsg_rpinfo rpinfo
;
1124 struct prefix group
;
1125 struct bsgrp_node
*bsgrp
= NULL
;
1126 int frag_rp_cnt
= 0;
1131 while (buflen
> offset
) {
1132 if (offset
+ (int)sizeof(struct bsmmsg_grpinfo
) > buflen
) {
1135 "%s: buflen received %d is less than the internal data structure of the packet would suggest",
1139 /* Extract Group tlv from BSM */
1140 memcpy(&grpinfo
, buf
, sizeof(struct bsmmsg_grpinfo
));
1141 grp_addr
= grpinfo
.group
.addr
;
1145 "%s, Group %pPAs Rpcount:%d Fragment-Rp-count:%d",
1146 __func__
, &grp_addr
, grpinfo
.rp_count
,
1147 grpinfo
.frag_rp_count
);
1149 buf
+= sizeof(struct bsmmsg_grpinfo
);
1150 offset
+= sizeof(struct bsmmsg_grpinfo
);
1152 group
.family
= PIM_AF
;
1153 if (grpinfo
.group
.mask
> PIM_MAX_BITLEN
) {
1156 "%s, prefix length specified: %d is too long",
1157 __func__
, grpinfo
.group
.mask
);
1161 pim_addr_to_prefix(&group
, grp_addr
);
1162 group
.prefixlen
= grpinfo
.group
.mask
;
1164 /* Get the Group node for the BSM rp table */
1165 bsgrp
= pim_bsm_get_bsgrp_node(scope
, &group
);
1167 if (grpinfo
.rp_count
== 0) {
1168 struct bsm_rpinfo
*old_rpinfo
;
1170 /* BSR explicitly no longer has RPs for this group */
1176 "%s, Rp count is zero for group: %pPAs",
1177 __func__
, &grp_addr
);
1179 old_rpinfo
= bsm_rpinfos_first(bsgrp
->bsrp_list
);
1181 pim_rp_del(scope
->pim
, old_rpinfo
->rp_address
,
1182 group
, NULL
, RP_SRC_BSR
);
1184 pim_free_bsgrp_node(scope
->bsrp_table
, &bsgrp
->group
);
1185 pim_free_bsgrp_data(bsgrp
);
1191 zlog_debug("%s, Create new BSM Group node.",
1194 /* create a new node to be added to the tree. */
1195 bsgrp
= pim_bsm_new_bsgrp_node(scope
->bsrp_table
,
1200 "%s, Failed to get the BSM group node.",
1205 bsgrp
->scope
= scope
;
1208 pim_update_pending_rp_cnt(scope
, bsgrp
, bsm_frag_tag
,
1210 frag_rp_cnt
= grpinfo
.frag_rp_count
;
1213 while (frag_rp_cnt
--) {
1214 if (offset
+ (int)sizeof(struct bsmmsg_rpinfo
)
1218 "%s, buflen received: %u is less than the internal data structure of the packet would suggest",
1223 /* Extract RP address tlv from BSM */
1224 memcpy(&rpinfo
, buf
, sizeof(struct bsmmsg_rpinfo
));
1225 rpinfo
.rp_holdtime
= ntohs(rpinfo
.rp_holdtime
);
1226 buf
+= sizeof(struct bsmmsg_rpinfo
);
1227 offset
+= sizeof(struct bsmmsg_rpinfo
);
1229 if (PIM_DEBUG_BSM
) {
1232 rp_addr
= rpinfo
.rpaddr
.addr
;
1234 "%s, Rp address - %pPAs; pri:%d hold:%d",
1235 __func__
, &rp_addr
, rpinfo
.rp_pri
,
1236 rpinfo
.rp_holdtime
);
1239 /* Call Install api to update grp-rp mappings */
1240 if (pim_install_bsm_grp_rp(scope
->pim
, bsgrp
, &rpinfo
))
1244 bsgrp
->pend_rp_cnt
-= ins_count
;
1246 if (!bsgrp
->pend_rp_cnt
) {
1249 "%s, Recvd all the rps for this group, so bsrp list with penidng rp list.",
1251 /* replace the bsrp_list with pending list */
1252 pim_instate_pend_list(bsgrp
);
1258 int pim_bsm_process(struct interface
*ifp
, pim_sgaddr
*sg
, uint8_t *buf
,
1259 uint32_t buf_size
, bool no_fwd
)
1261 struct bsm_hdr
*bshdr
;
1262 int sz
= PIM_GBL_SZ_ID
;
1263 struct bsmmsg_grpinfo
*msg_grp
;
1264 struct pim_interface
*pim_ifp
= NULL
;
1265 struct bsm_frag
*bsfrag
;
1266 struct pim_instance
*pim
;
1269 bool empty_bsm
= false;
1271 /* BSM Packet acceptance validation */
1272 pim_ifp
= ifp
->info
;
1275 zlog_debug("%s: multicast not enabled on interface %s",
1276 __func__
, ifp
->name
);
1280 if (pim_ifp
->pim_passive_enable
) {
1281 if (PIM_DEBUG_PIM_PACKETS
)
1283 "skip receiving PIM message on passive interface %s",
1288 pim_ifp
->pim_ifstat_bsm_rx
++;
1292 /* Drop if bsm processing is disabled on interface */
1293 if (!pim_ifp
->bsm_enable
) {
1294 zlog_warn("%s: BSM not enabled on interface %s", __func__
,
1296 pim_ifp
->pim_ifstat_bsm_cfg_miss
++;
1301 if (buf_size
< (PIM_MSG_HEADER_LEN
+ sizeof(struct bsm_hdr
))) {
1304 "%s: received buffer length of %d which is too small to properly decode",
1305 __func__
, buf_size
);
1309 bshdr
= (struct bsm_hdr
*)(buf
+ PIM_MSG_HEADER_LEN
);
1310 if (bshdr
->hm_len
> PIM_MAX_BITLEN
) {
1312 "Bad hashmask length for %s; got %hhu, expected value in range 0-32",
1313 PIM_AF_NAME
, bshdr
->hm_len
);
1317 pim
->global_scope
.hashMasklen
= bshdr
->hm_len
;
1318 frag_tag
= ntohs(bshdr
->frag_tag
);
1319 /* NB: bshdr->bsr_addr.addr is packed/unaligned => memcpy */
1320 memcpy(&bsr_addr
, &bshdr
->bsr_addr
.addr
, sizeof(bsr_addr
));
1322 /* Identify empty BSM */
1323 if ((buf_size
- PIM_BSM_HDR_LEN
- PIM_MSG_HEADER_LEN
) < PIM_BSM_GRP_LEN
)
1327 msg_grp
= (struct bsmmsg_grpinfo
*)(buf
+ PIM_MSG_HEADER_LEN
1329 /* Currently we don't support scope zoned BSM */
1330 if (msg_grp
->group
.sz
) {
1333 "%s : Administratively scoped range BSM received",
1335 pim_ifp
->pim_ifstat_bsm_invalid_sz
++;
1341 /* Drop if bsr is not preferred bsr */
1342 if (!is_preferred_bsr(pim
, bsr_addr
, bshdr
->bsr_prio
)) {
1344 zlog_debug("%s : Received a non-preferred BSM",
1351 /* only accept no-forward BSM if quick refresh on startup */
1352 if ((pim
->global_scope
.accept_nofwd_bsm
)
1353 || (frag_tag
== pim
->global_scope
.bsm_frag_tag
)) {
1354 pim
->global_scope
.accept_nofwd_bsm
= false;
1358 "%s : nofwd_bsm received on %pPAs when accpt_nofwd_bsm false",
1359 __func__
, &bsr_addr
);
1361 pim_ifp
->pim_ifstat_ucast_bsm_cfg_miss
++;
1366 /* BSM packet is seen, so resetting accept_nofwd_bsm to false */
1367 if (pim
->global_scope
.accept_nofwd_bsm
)
1368 pim
->global_scope
.accept_nofwd_bsm
= false;
1370 if (!pim_addr_cmp(sg
->grp
, qpim_all_pim_routers_addr
)) {
1371 /* Multicast BSMs are only accepted if source interface & IP
1372 * match RPF towards the BSR's IP address, or they have
1376 !pim_nht_bsr_rpf_check(pim
, bsr_addr
, ifp
, sg
->src
)) {
1379 "BSM check: RPF to BSR %pPAs is not %pPA%%%s",
1380 &bsr_addr
, &sg
->src
, ifp
->name
);
1384 } else if (if_address_is_local(&sg
->grp
, PIM_AF
, pim
->vrf
->vrf_id
)) {
1385 /* Unicast BSM received - if ucast bsm not enabled on
1386 * the interface, drop it
1388 if (!pim_ifp
->ucast_bsm_accept
) {
1391 "%s : Unicast BSM not enabled on interface %s",
1392 __func__
, ifp
->name
);
1393 pim_ifp
->pim_ifstat_ucast_bsm_cfg_miss
++;
1400 zlog_debug("%s : Invalid destination address",
1408 zlog_debug("%s : Empty Pref BSM received", __func__
);
1410 /* Parse Update bsm rp table and install/uninstall rp if required */
1411 if (!pim_bsm_parse_install_g2rp(
1412 &pim_ifp
->pim
->global_scope
,
1413 (buf
+ PIM_BSM_HDR_LEN
+ PIM_MSG_HEADER_LEN
),
1414 (buf_size
- PIM_BSM_HDR_LEN
- PIM_MSG_HEADER_LEN
),
1416 if (PIM_DEBUG_BSM
) {
1417 zlog_debug("%s, Parsing BSM failed.", __func__
);
1422 /* Restart the bootstrap timer */
1423 pim_bs_timer_restart(&pim_ifp
->pim
->global_scope
,
1424 PIM_BSR_DEFAULT_TIMEOUT
);
1426 /* If new BSM received, clear the old bsm database */
1427 if (pim_ifp
->pim
->global_scope
.bsm_frag_tag
!= frag_tag
) {
1428 if (PIM_DEBUG_BSM
) {
1429 zlog_debug("%s: Current frag tag: %d Frag teg rcvd: %d",
1431 pim_ifp
->pim
->global_scope
.bsm_frag_tag
,
1434 pim_bsm_frags_free(&pim_ifp
->pim
->global_scope
);
1435 pim_ifp
->pim
->global_scope
.bsm_frag_tag
= frag_tag
;
1438 /* update the scope information from bsm */
1439 pim_bsm_update(pim
, bsr_addr
, bshdr
->bsr_prio
);
1442 pim_bsm_fwd_whole_sz(pim_ifp
->pim
, buf
, buf_size
, sz
);
1443 bsfrag
= XCALLOC(MTYPE_PIM_BSM_FRAG
,
1444 sizeof(struct bsm_frag
) + buf_size
);
1446 bsfrag
->size
= buf_size
;
1447 memcpy(bsfrag
->data
, buf
, buf_size
);
1448 bsm_frags_add_tail(pim_ifp
->pim
->global_scope
.bsm_frags
,