2 * pim_bsm.c: PIM BSM handling routines
4 * Copyright (C) 2018-19 Vmware, Inc.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; see the file COPYING; if not, write to the
19 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
24 #include "pim_iface.h"
25 #include "pim_instance.h"
27 #include "pim_hello.h"
33 /* Functions forward declaration */
34 static void pim_bs_timer_start(struct bsm_scope
*scope
, int bs_timeout
);
35 static void pim_g2rp_timer_start(struct bsm_rpinfo
*bsrp
, int hold_time
);
36 static inline void pim_g2rp_timer_restart(struct bsm_rpinfo
*bsrp
,
40 DEFINE_MTYPE_STATIC(PIMD
, PIM_BSGRP_NODE
, "PIM BSR advertised grp info")
41 DEFINE_MTYPE_STATIC(PIMD
, PIM_BSRP_NODE
, "PIM BSR advertised RP info")
42 DEFINE_MTYPE_STATIC(PIMD
, PIM_BSM_INFO
, "PIM BSM Info")
43 DEFINE_MTYPE_STATIC(PIMD
, PIM_BSM_PKT_VAR_MEM
, "PIM BSM Packet")
45 /* pim_bsm_write_config - Write the interface pim bsm configuration.*/
46 void pim_bsm_write_config(struct vty
*vty
, struct interface
*ifp
)
48 struct pim_interface
*pim_ifp
= ifp
->info
;
51 if (!pim_ifp
->bsm_enable
)
52 vty_out(vty
, " no ip pim bsm\n");
53 if (!pim_ifp
->ucast_bsm_accept
)
54 vty_out(vty
, " no ip pim unicast-bsm\n");
58 static void pim_free_bsgrp_data(struct bsgrp_node
*bsgrp_node
)
60 if (bsgrp_node
->bsrp_list
)
61 list_delete(&bsgrp_node
->bsrp_list
);
62 if (bsgrp_node
->partial_bsrp_list
)
63 list_delete(&bsgrp_node
->partial_bsrp_list
);
64 XFREE(MTYPE_PIM_BSGRP_NODE
, bsgrp_node
);
67 static void pim_free_bsgrp_node(struct route_table
*rt
, struct prefix
*grp
)
69 struct route_node
*rn
;
71 rn
= route_node_lookup(rt
, grp
);
74 route_unlock_node(rn
);
75 route_unlock_node(rn
);
79 static void pim_bsm_node_free(struct bsm_info
*bsm
)
82 XFREE(MTYPE_PIM_BSM_PKT_VAR_MEM
, bsm
->bsm
);
83 XFREE(MTYPE_PIM_BSM_INFO
, bsm
);
86 static int pim_g2rp_list_compare(struct bsm_rpinfo
*node1
,
87 struct bsm_rpinfo
*node2
)
90 * Step-1 : Loweset Rp priority will have higher precedance.
91 * Step-2 : If priority same then higher hash val will have
93 * Step-3 : If Hash val is same then highest rp address will
96 if (node1
->rp_prio
< node2
->rp_prio
)
98 if (node1
->rp_prio
> node2
->rp_prio
)
100 if (node1
->hash
< node2
->hash
)
102 if (node1
->hash
> node2
->hash
)
104 if (node1
->rp_address
.s_addr
< node2
->rp_address
.s_addr
)
106 if (node1
->rp_address
.s_addr
> node2
->rp_address
.s_addr
)
111 static void pim_free_bsrp_node(struct bsm_rpinfo
*bsrp_info
)
113 if (bsrp_info
->g2rp_timer
)
114 THREAD_OFF(bsrp_info
->g2rp_timer
);
115 XFREE(MTYPE_PIM_BSRP_NODE
, bsrp_info
);
118 static struct list
*pim_alloc_bsrp_list(void)
120 struct list
*new_list
= NULL
;
122 new_list
= list_new();
127 new_list
->cmp
= (int (*)(void *, void *))pim_g2rp_list_compare
;
128 new_list
->del
= (void (*)(void *))pim_free_bsrp_node
;
133 static struct bsgrp_node
*pim_bsm_new_bsgrp_node(struct route_table
*rt
,
136 struct route_node
*rn
;
137 struct bsgrp_node
*bsgrp
;
139 rn
= route_node_get(rt
, grp
);
141 zlog_warn("%s: route node creation failed",
142 __PRETTY_FUNCTION__
);
145 bsgrp
= XCALLOC(MTYPE_PIM_BSGRP_NODE
, sizeof(struct bsgrp_node
));
149 zlog_debug("%s: bsgrp alloc failed",
150 __PRETTY_FUNCTION__
);
151 route_unlock_node(rn
);
156 bsgrp
->bsrp_list
= pim_alloc_bsrp_list();
157 bsgrp
->partial_bsrp_list
= pim_alloc_bsrp_list();
159 if ((!bsgrp
->bsrp_list
) || (!bsgrp
->partial_bsrp_list
)) {
160 route_unlock_node(rn
);
161 pim_free_bsgrp_data(bsgrp
);
165 prefix_copy(&bsgrp
->group
, grp
);
169 static int pim_on_bs_timer(struct thread
*t
)
171 struct route_node
*rn
;
172 struct bsm_scope
*scope
;
173 struct bsgrp_node
*bsgrp_node
;
174 struct bsm_rpinfo
*bsrp
;
176 char buf
[PREFIX2STR_BUFFER
];
177 bool is_bsr_tracking
= true;
179 scope
= THREAD_ARG(t
);
180 THREAD_OFF(scope
->bs_timer
);
183 zlog_debug("%s: Bootstrap Timer expired for scope: %d",
184 __PRETTY_FUNCTION__
, scope
->sz_id
);
186 /* Remove next hop tracking for the bsr */
187 nht_p
.family
= AF_INET
;
188 nht_p
.prefixlen
= IPV4_MAX_BITLEN
;
189 nht_p
.u
.prefix4
= scope
->current_bsr
;
191 prefix2str(&nht_p
, buf
, sizeof(buf
));
192 zlog_debug("%s: Deregister BSR addr %s with Zebra NHT",
193 __PRETTY_FUNCTION__
, buf
);
195 pim_delete_tracked_nexthop(scope
->pim
, &nht_p
, NULL
, NULL
,
198 /* Reset scope zone data */
199 scope
->accept_nofwd_bsm
= false;
200 scope
->state
= ACCEPT_ANY
;
201 scope
->current_bsr
.s_addr
= INADDR_ANY
;
202 scope
->current_bsr_prio
= 0;
203 scope
->current_bsr_first_ts
= 0;
204 scope
->current_bsr_last_ts
= 0;
205 scope
->bsm_frag_tag
= 0;
206 list_delete_all_node(scope
->bsm_list
);
208 for (rn
= route_top(scope
->bsrp_table
); rn
; rn
= route_next(rn
)) {
210 bsgrp_node
= (struct bsgrp_node
*)rn
->info
;
213 zlog_debug("%s: bsgrp_node is null",
214 __PRETTY_FUNCTION__
);
217 /* Give grace time for rp to continue for another hold time */
218 if ((bsgrp_node
->bsrp_list
) && (bsgrp_node
->bsrp_list
->count
)) {
219 bsrp
= listnode_head(bsgrp_node
->bsrp_list
);
220 pim_g2rp_timer_restart(bsrp
, bsrp
->rp_holdtime
);
222 /* clear pending list */
223 if ((bsgrp_node
->partial_bsrp_list
)
224 && (bsgrp_node
->partial_bsrp_list
->count
)) {
225 list_delete_all_node(bsgrp_node
->partial_bsrp_list
);
226 bsgrp_node
->pend_rp_cnt
= 0;
232 static void pim_bs_timer_stop(struct bsm_scope
*scope
)
235 zlog_debug("%s : BS timer being stopped of sz: %d",
236 __PRETTY_FUNCTION__
, scope
->sz_id
);
237 THREAD_OFF(scope
->bs_timer
);
240 static void pim_bs_timer_start(struct bsm_scope
*scope
, int bs_timeout
)
244 zlog_debug("%s : Invalid scope(NULL).",
245 __PRETTY_FUNCTION__
);
248 THREAD_OFF(scope
->bs_timer
);
250 zlog_debug("%s : starting bs timer for scope %d with timeout %d secs",
251 __PRETTY_FUNCTION__
, scope
->sz_id
, bs_timeout
);
252 thread_add_timer(router
->master
, pim_on_bs_timer
, scope
, bs_timeout
,
256 static inline void pim_bs_timer_restart(struct bsm_scope
*scope
, int bs_timeout
)
258 pim_bs_timer_start(scope
, bs_timeout
);
261 void pim_bsm_proc_init(struct pim_instance
*pim
)
263 memset(&pim
->global_scope
, 0, sizeof(struct bsm_scope
));
265 pim
->global_scope
.sz_id
= PIM_GBL_SZ_ID
;
266 pim
->global_scope
.bsrp_table
= route_table_init();
267 pim
->global_scope
.accept_nofwd_bsm
= true;
268 pim
->global_scope
.state
= NO_INFO
;
269 pim
->global_scope
.pim
= pim
;
270 pim
->global_scope
.bsm_list
= list_new();
271 pim
->global_scope
.bsm_list
->del
= (void (*)(void *))pim_bsm_node_free
;
272 pim_bs_timer_start(&pim
->global_scope
, PIM_BS_TIME
);
275 void pim_bsm_proc_free(struct pim_instance
*pim
)
277 struct route_node
*rn
;
278 struct bsgrp_node
*bsgrp
;
280 pim_bs_timer_stop(&pim
->global_scope
);
282 if (pim
->global_scope
.bsm_list
)
283 list_delete(&pim
->global_scope
.bsm_list
);
285 for (rn
= route_top(pim
->global_scope
.bsrp_table
); rn
;
286 rn
= route_next(rn
)) {
290 pim_free_bsgrp_data(bsgrp
);
293 if (pim
->global_scope
.bsrp_table
)
294 route_table_finish(pim
->global_scope
.bsrp_table
);
297 static bool is_hold_time_elapsed(void *data
)
299 struct bsm_rpinfo
*bsrp
;
303 if (bsrp
->elapse_time
< bsrp
->rp_holdtime
)
309 static int pim_on_g2rp_timer(struct thread
*t
)
311 struct bsm_rpinfo
*bsrp
;
312 struct bsm_rpinfo
*bsrp_node
;
313 struct bsgrp_node
*bsgrp_node
;
314 struct listnode
*bsrp_ln
;
315 struct pim_instance
*pim
;
316 struct rp_info
*rp_info
;
317 struct route_node
*rn
;
319 struct in_addr bsrp_addr
;
321 bsrp
= THREAD_ARG(t
);
322 THREAD_OFF(bsrp
->g2rp_timer
);
323 bsgrp_node
= bsrp
->bsgrp_node
;
325 /* elapse time is the hold time of expired node */
326 elapse
= bsrp
->rp_holdtime
;
327 bsrp_addr
= bsrp
->rp_address
;
329 /* update elapse for all bsrp nodes */
330 for (ALL_LIST_ELEMENTS_RO(bsgrp_node
->bsrp_list
, bsrp_ln
, bsrp_node
))
331 bsrp_node
->elapse_time
+= elapse
;
333 /* remove the expired nodes from the list */
334 list_filter_out_nodes(bsgrp_node
->bsrp_list
, is_hold_time_elapsed
);
336 /* Get the next elected rp node */
337 bsrp
= listnode_head(bsgrp_node
->bsrp_list
);
338 pim
= bsgrp_node
->scope
->pim
;
339 rn
= route_node_lookup(pim
->rp_table
, &bsgrp_node
->group
);
342 zlog_warn("%s: Route node doesn't exist", __PRETTY_FUNCTION__
);
346 rp_info
= (struct rp_info
*)rn
->info
;
349 route_unlock_node(rn
);
353 if (rp_info
->rp_src
!= RP_SRC_STATIC
) {
354 /* If new rp available, change it else delete the existing */
356 bsrp_addr
= bsrp
->rp_address
;
357 pim_g2rp_timer_start(
358 bsrp
, (bsrp
->rp_holdtime
- bsrp
->elapse_time
));
359 pim_rp_change(pim
, bsrp_addr
, bsgrp_node
->group
,
362 pim_rp_del(pim
, bsrp_addr
, bsgrp_node
->group
, NULL
,
367 if ((!bsgrp_node
->bsrp_list
->count
)
368 && (!bsgrp_node
->partial_bsrp_list
->count
)) {
369 pim_free_bsgrp_node(pim
->global_scope
.bsrp_table
,
371 pim_free_bsgrp_data(bsgrp_node
);
377 static void pim_g2rp_timer_start(struct bsm_rpinfo
*bsrp
, int hold_time
)
381 zlog_debug("%s : Invalid brsp(NULL).",
382 __PRETTY_FUNCTION__
);
385 THREAD_OFF(bsrp
->g2rp_timer
);
390 "%s : starting g2rp timer for grp: %s - rp: %s with timeout %d secs(Actual Hold time : %d secs)",
392 prefix2str(&bsrp
->bsgrp_node
->group
, buf
, 48),
393 inet_ntoa(bsrp
->rp_address
), hold_time
,
397 thread_add_timer(router
->master
, pim_on_g2rp_timer
, bsrp
, hold_time
,
401 static inline void pim_g2rp_timer_restart(struct bsm_rpinfo
*bsrp
,
404 pim_g2rp_timer_start(bsrp
, hold_time
);
407 static void pim_g2rp_timer_stop(struct bsm_rpinfo
*bsrp
)
415 zlog_debug("%s : stopping g2rp timer for grp: %s - rp: %s",
417 prefix2str(&bsrp
->bsgrp_node
->group
, buf
, 48),
418 inet_ntoa(bsrp
->rp_address
));
421 THREAD_OFF(bsrp
->g2rp_timer
);
424 static bool is_hold_time_zero(void *data
)
426 struct bsm_rpinfo
*bsrp
;
430 if (bsrp
->rp_holdtime
)
436 static void pim_instate_pend_list(struct bsgrp_node
*bsgrp_node
)
438 struct bsm_rpinfo
*active
;
439 struct bsm_rpinfo
*pend
;
441 struct rp_info
*rp_info
;
442 struct route_node
*rn
;
443 struct pim_instance
*pim
;
444 struct rp_info
*rp_all
;
445 struct prefix group_all
;
446 bool had_rp_node
= true;
448 pim
= bsgrp_node
->scope
->pim
;
449 active
= listnode_head(bsgrp_node
->bsrp_list
);
451 /* Remove nodes with hold time 0 & check if list still has a head */
452 list_filter_out_nodes(bsgrp_node
->partial_bsrp_list
, is_hold_time_zero
);
453 pend
= listnode_head(bsgrp_node
->partial_bsrp_list
);
455 if (!str2prefix("224.0.0.0/4", &group_all
))
458 rp_all
= pim_rp_find_match_group(pim
, &group_all
);
459 rn
= route_node_lookup(pim
->rp_table
, &bsgrp_node
->group
);
462 pim_g2rp_timer_start(pend
, pend
->rp_holdtime
);
464 /* if rp node doesn't exist or exist but not configured(rp_all),
465 * install the rp from head(if exists) of partial list. List is
466 * is sorted such that head is the elected RP for the group.
468 if (!rn
|| (prefix_same(&rp_all
->group
, &bsgrp_node
->group
)
469 && pim_rpf_addr_is_inaddr_none(&rp_all
->rp
))) {
471 zlog_debug("%s: Route node doesn't exist",
472 __PRETTY_FUNCTION__
);
474 pim_rp_new(pim
, pend
->rp_address
, bsgrp_node
->group
,
478 rp_info
= (struct rp_info
*)rn
->info
;
480 route_unlock_node(rn
);
482 pim_rp_new(pim
, pend
->rp_address
,
483 bsgrp_node
->group
, NULL
, RP_SRC_BSR
);
488 /* We didn't have rp node and pending list is empty(unlikely), cleanup*/
489 if ((!had_rp_node
) && (!pend
)) {
490 pim_free_bsgrp_node(bsgrp_node
->scope
->bsrp_table
,
492 pim_free_bsgrp_data(bsgrp_node
);
496 if ((had_rp_node
) && (rp_info
->rp_src
!= RP_SRC_STATIC
)) {
497 /* This means we searched and got rp node, needs unlock */
498 route_unlock_node(rn
);
500 if (active
&& pend
) {
501 if ((active
->rp_address
.s_addr
502 != pend
->rp_address
.s_addr
))
503 pim_rp_change(pim
, pend
->rp_address
,
504 bsgrp_node
->group
, RP_SRC_BSR
);
507 /* Possible when the first BSM has group with 0 rp count */
508 if ((!active
) && (!pend
)) {
511 "%s: Both bsrp and partial list are empty",
512 __PRETTY_FUNCTION__
);
514 pim_free_bsgrp_node(bsgrp_node
->scope
->bsrp_table
,
516 pim_free_bsgrp_data(bsgrp_node
);
520 /* Possible when a group with 0 rp count received in BSM */
521 if ((active
) && (!pend
)) {
522 pim_rp_del(pim
, active
->rp_address
, bsgrp_node
->group
,
524 pim_free_bsgrp_node(bsgrp_node
->scope
->bsrp_table
,
527 zlog_debug("%s:Pend List is null,del grp node",
528 __PRETTY_FUNCTION__
);
530 pim_free_bsgrp_data(bsgrp_node
);
535 if ((had_rp_node
) && (rp_info
->rp_src
== RP_SRC_STATIC
)) {
536 /* We need to unlock rn this case */
537 route_unlock_node(rn
);
538 /* there is a chance that static rp exist and bsrp cleaned
539 * so clean bsgrp node if pending list empty
544 "%s: Partial list is empty, static rp exists",
545 __PRETTY_FUNCTION__
);
546 pim_free_bsgrp_node(bsgrp_node
->scope
->bsrp_table
,
548 pim_free_bsgrp_data(bsgrp_node
);
553 /* swap the list & delete all nodes in partial list (old bsrp_list)
555 * active is head of bsrp list
556 * pend is head of partial list
558 * active is head of partial list
559 * pend is head of bsrp list
560 * So check appriate head after swap and clean the new partial list
562 temp
= bsgrp_node
->bsrp_list
;
563 bsgrp_node
->bsrp_list
= bsgrp_node
->partial_bsrp_list
;
564 bsgrp_node
->partial_bsrp_list
= temp
;
567 pim_g2rp_timer_stop(active
);
568 list_delete_all_node(bsgrp_node
->partial_bsrp_list
);
572 static bool pim_bsr_rpf_check(struct pim_instance
*pim
, struct in_addr bsr
,
573 struct in_addr ip_src_addr
)
575 struct pim_nexthop nexthop
;
578 memset(&nexthop
, 0, sizeof(nexthop
));
580 /* New BSR recived */
581 if (bsr
.s_addr
!= pim
->global_scope
.current_bsr
.s_addr
) {
582 result
= pim_nexthop_match(pim
, bsr
, ip_src_addr
);
584 /* Nexthop lookup pass for the new BSR address */
589 char bsr_str
[INET_ADDRSTRLEN
];
591 pim_inet4_dump("<bsr?>", bsr
, bsr_str
, sizeof(bsr_str
));
592 zlog_debug("%s : No route to BSR address %s",
593 __PRETTY_FUNCTION__
, bsr_str
);
598 return pim_nexthop_match_nht_cache(pim
, bsr
, ip_src_addr
);
601 static bool is_preferred_bsr(struct pim_instance
*pim
, struct in_addr bsr
,
604 if (bsr
.s_addr
== pim
->global_scope
.current_bsr
.s_addr
)
607 if (bsr_prio
> pim
->global_scope
.current_bsr_prio
)
610 else if (bsr_prio
== pim
->global_scope
.current_bsr_prio
) {
611 if (bsr
.s_addr
>= pim
->global_scope
.current_bsr
.s_addr
)
619 static void pim_bsm_update(struct pim_instance
*pim
, struct in_addr bsr
,
622 struct pim_nexthop_cache pnc
;
624 if (bsr
.s_addr
!= pim
->global_scope
.current_bsr
.s_addr
) {
626 char buf
[PREFIX2STR_BUFFER
];
627 bool is_bsr_tracking
= true;
629 /* De-register old BSR and register new BSR with Zebra NHT */
630 nht_p
.family
= AF_INET
;
631 nht_p
.prefixlen
= IPV4_MAX_BITLEN
;
633 if (pim
->global_scope
.current_bsr
.s_addr
!= INADDR_ANY
) {
634 nht_p
.u
.prefix4
= pim
->global_scope
.current_bsr
;
636 prefix2str(&nht_p
, buf
, sizeof(buf
));
638 "%s: Deregister BSR addr %s with Zebra NHT",
639 __PRETTY_FUNCTION__
, buf
);
641 pim_delete_tracked_nexthop(pim
, &nht_p
, NULL
, NULL
,
645 nht_p
.u
.prefix4
= bsr
;
647 prefix2str(&nht_p
, buf
, sizeof(buf
));
649 "%s: NHT Register BSR addr %s with Zebra NHT",
650 __PRETTY_FUNCTION__
, buf
);
653 memset(&pnc
, 0, sizeof(struct pim_nexthop_cache
));
654 pim_find_or_track_nexthop(pim
, &nht_p
, NULL
, NULL
,
655 is_bsr_tracking
, &pnc
);
656 pim
->global_scope
.current_bsr
= bsr
;
657 pim
->global_scope
.current_bsr_first_ts
=
658 pim_time_monotonic_sec();
659 pim
->global_scope
.state
= ACCEPT_PREFERRED
;
661 pim
->global_scope
.current_bsr_prio
= bsr_prio
;
662 pim
->global_scope
.current_bsr_last_ts
= pim_time_monotonic_sec();
665 struct bsgrp_node
*pim_bsm_get_bsgrp_node(struct bsm_scope
*scope
,
668 struct route_node
*rn
;
669 struct bsgrp_node
*bsgrp
;
671 rn
= route_node_lookup(scope
->bsrp_table
, grp
);
674 zlog_debug("%s: Route node doesn't exist for the group",
675 __PRETTY_FUNCTION__
);
679 route_unlock_node(rn
);
684 static uint32_t hash_calc_on_grp_rp(struct prefix group
, struct in_addr rp
,
691 uint32_t mask
= 0xffffffff;
693 /* mask to be made zero if hashmasklen is 0 because mask << 32
694 * may not give 0. hashmasklen can be 0 to 32.
696 if (hashmasklen
== 0)
699 /* in_addr stores ip in big endian, hence network byte order
700 * convert to uint32 before processing hash
702 grpaddr
= ntohl(group
.u
.prefix4
.s_addr
);
703 /* Avoid shifting by 32 bit on a 32 bit register */
705 grpaddr
= grpaddr
& ((mask
<< (32 - hashmasklen
)));
707 grpaddr
= grpaddr
& mask
;
708 rp_add
= ntohl(rp
.s_addr
);
709 temp
= 1103515245 * ((1103515245 * grpaddr
+ 12345) ^ rp_add
) + 12345;
710 hash
= temp
& (0x7fffffff);
714 static bool pim_install_bsm_grp_rp(struct pim_instance
*pim
,
715 struct bsgrp_node
*grpnode
,
716 struct bsmmsg_rpinfo
*rp
)
718 struct bsm_rpinfo
*bsm_rpinfo
;
719 uint8_t hashMask_len
= pim
->global_scope
.hashMasklen
;
721 /*memory allocation for bsm_rpinfo */
722 bsm_rpinfo
= XCALLOC(MTYPE_PIM_BSRP_NODE
, sizeof(*bsm_rpinfo
));
726 zlog_debug("%s, Memory allocation failed.\r\n",
727 __PRETTY_FUNCTION__
);
731 bsm_rpinfo
->rp_prio
= rp
->rp_pri
;
732 bsm_rpinfo
->rp_holdtime
= rp
->rp_holdtime
;
733 memcpy(&bsm_rpinfo
->rp_address
, &rp
->rpaddr
.addr
,
734 sizeof(struct in_addr
));
735 bsm_rpinfo
->elapse_time
= 0;
737 /* Back pointer to the group node. */
738 bsm_rpinfo
->bsgrp_node
= grpnode
;
740 /* update hash for this rp node */
741 bsm_rpinfo
->hash
= hash_calc_on_grp_rp(grpnode
->group
, rp
->rpaddr
.addr
,
743 if (listnode_add_sort_nodup(grpnode
->partial_bsrp_list
, bsm_rpinfo
)) {
746 "%s, bs_rpinfo node added to the partial bs_rplist.\r\n",
747 __PRETTY_FUNCTION__
);
752 zlog_debug("%s: list node not added\n", __PRETTY_FUNCTION__
);
754 XFREE(MTYPE_PIM_BSRP_NODE
, bsm_rpinfo
);
758 static void pim_update_pending_rp_cnt(struct bsm_scope
*sz
,
759 struct bsgrp_node
*bsgrp
,
760 uint16_t bsm_frag_tag
,
761 uint32_t total_rp_count
)
763 if (bsgrp
->pend_rp_cnt
) {
764 /* received bsm is different packet ,
765 * it is not same fragment.
767 if (bsm_frag_tag
!= bsgrp
->frag_tag
) {
770 "%s,Received a new BSM ,so clear the pending bs_rpinfo list.\r\n",
771 __PRETTY_FUNCTION__
);
772 list_delete_all_node(bsgrp
->partial_bsrp_list
);
773 bsgrp
->pend_rp_cnt
= total_rp_count
;
776 bsgrp
->pend_rp_cnt
= total_rp_count
;
778 bsgrp
->frag_tag
= bsm_frag_tag
;
781 /* Parsing BSR packet and adding to partial list of corresponding bsgrp node */
782 static bool pim_bsm_parse_install_g2rp(struct bsm_scope
*scope
, uint8_t *buf
,
783 int buflen
, uint16_t bsm_frag_tag
)
785 struct bsmmsg_grpinfo grpinfo
;
786 struct bsmmsg_rpinfo rpinfo
;
788 struct bsgrp_node
*bsgrp
= NULL
;
793 while (buflen
> offset
) {
794 /* Extract Group tlv from BSM */
795 memcpy(&grpinfo
, buf
, sizeof(struct bsmmsg_grpinfo
));
798 char grp_str
[INET_ADDRSTRLEN
];
800 pim_inet4_dump("<Group?>", grpinfo
.group
.addr
, grp_str
,
803 "%s, Group %s Rpcount:%d Fragment-Rp-count:%d\r\n",
804 __PRETTY_FUNCTION__
, grp_str
, grpinfo
.rp_count
,
805 grpinfo
.frag_rp_count
);
808 buf
+= sizeof(struct bsmmsg_grpinfo
);
809 offset
+= sizeof(struct bsmmsg_grpinfo
);
811 if (grpinfo
.rp_count
== 0) {
813 char grp_str
[INET_ADDRSTRLEN
];
815 pim_inet4_dump("<Group?>", grpinfo
.group
.addr
,
816 grp_str
, sizeof(grp_str
));
818 "%s, Rp count is zero for group: %s\r\n",
819 __PRETTY_FUNCTION__
, grp_str
);
824 group
.family
= AF_INET
;
825 group
.prefixlen
= grpinfo
.group
.mask
;
826 group
.u
.prefix4
.s_addr
= grpinfo
.group
.addr
.s_addr
;
828 /* Get the Group node for the BSM rp table */
829 bsgrp
= pim_bsm_get_bsgrp_node(scope
, &group
);
834 "%s, Create new BSM Group node.\r\n",
835 __PRETTY_FUNCTION__
);
837 /* create a new node to be added to the tree. */
838 bsgrp
= pim_bsm_new_bsgrp_node(scope
->bsrp_table
,
843 "%s, Failed to get the BSM group node.\r\n",
844 __PRETTY_FUNCTION__
);
848 bsgrp
->scope
= scope
;
851 pim_update_pending_rp_cnt(scope
, bsgrp
, bsm_frag_tag
,
853 frag_rp_cnt
= grpinfo
.frag_rp_count
;
856 while (frag_rp_cnt
--) {
857 /* Extract RP address tlv from BSM */
858 memcpy(&rpinfo
, buf
, sizeof(struct bsmmsg_rpinfo
));
859 rpinfo
.rp_holdtime
= ntohs(rpinfo
.rp_holdtime
);
860 buf
+= sizeof(struct bsmmsg_rpinfo
);
861 offset
+= sizeof(struct bsmmsg_rpinfo
);
864 char rp_str
[INET_ADDRSTRLEN
];
866 pim_inet4_dump("<Rpaddr?>", rpinfo
.rpaddr
.addr
,
867 rp_str
, sizeof(rp_str
));
869 "%s, Rp address - %s; pri:%d hold:%d\r\n",
870 __PRETTY_FUNCTION__
, rp_str
,
871 rpinfo
.rp_pri
, rpinfo
.rp_holdtime
);
874 /* Call Install api to update grp-rp mappings */
875 if (pim_install_bsm_grp_rp(scope
->pim
, bsgrp
, &rpinfo
))
879 bsgrp
->pend_rp_cnt
-= ins_count
;
881 if (!bsgrp
->pend_rp_cnt
) {
884 "%s, Recvd all the rps for this group, so bsrp list with penidng rp list.",
885 __PRETTY_FUNCTION__
);
886 /* replace the bsrp_list with pending list */
887 pim_instate_pend_list(bsgrp
);
893 int pim_bsm_process(struct interface
*ifp
, struct ip
*ip_hdr
, uint8_t *buf
,
894 uint32_t buf_size
, bool no_fwd
)
896 struct bsm_hdr
*bshdr
;
897 struct bsmmsg_grpinfo
*msg_grp
;
898 struct pim_interface
*pim_ifp
= NULL
;
899 struct pim_instance
*pim
;
900 char bsr_str
[INET_ADDRSTRLEN
];
902 bool empty_bsm
= FALSE
;
904 /* BSM Packet acceptance validation */
908 zlog_debug("%s: multicast not enabled on interface %s",
909 __PRETTY_FUNCTION__
, ifp
->name
);
913 pim_ifp
->pim_ifstat_bsm_rx
++;
917 /* Drop if bsm processing is disabled on interface */
918 if (!pim_ifp
->bsm_enable
) {
919 zlog_warn("%s: BSM not enabled on interface %s",
920 __PRETTY_FUNCTION__
, ifp
->name
);
921 pim_ifp
->pim_ifstat_bsm_cfg_miss
++;
926 bshdr
= (struct bsm_hdr
*)(buf
+ PIM_MSG_HEADER_LEN
);
927 pim_inet4_dump("<bsr?>", bshdr
->bsr_addr
.addr
, bsr_str
,
929 pim
->global_scope
.hashMasklen
= bshdr
->hm_len
;
930 frag_tag
= ntohs(bshdr
->frag_tag
);
932 /* Identify empty BSM */
933 if ((buf_size
- PIM_BSM_HDR_LEN
- PIM_MSG_HEADER_LEN
) < PIM_BSM_GRP_LEN
)
937 msg_grp
= (struct bsmmsg_grpinfo
*)(buf
+ PIM_MSG_HEADER_LEN
939 /* Currently we don't support scope zoned BSM */
940 if (msg_grp
->group
.sz
) {
943 "%s : Administratively scoped range BSM received",
944 __PRETTY_FUNCTION__
);
945 pim_ifp
->pim_ifstat_bsm_invalid_sz
++;
951 /* Drop if bsr is not preferred bsr */
952 if (!is_preferred_bsr(pim
, bshdr
->bsr_addr
.addr
, bshdr
->bsr_prio
)) {
954 zlog_debug("%s : Received a non-preferred BSM",
955 __PRETTY_FUNCTION__
);
961 /* only accept no-forward BSM if quick refresh on startup */
962 if ((pim
->global_scope
.accept_nofwd_bsm
)
963 || (frag_tag
== pim
->global_scope
.bsm_frag_tag
)) {
964 pim
->global_scope
.accept_nofwd_bsm
= false;
968 "%s : nofwd_bsm received on %s when accpt_nofwd_bsm false",
969 __PRETTY_FUNCTION__
, bsr_str
);
971 pim_ifp
->pim_ifstat_ucast_bsm_cfg_miss
++;
976 /* Mulicast BSM received */
977 if (ip_hdr
->ip_dst
.s_addr
== qpim_all_pim_routers_addr
.s_addr
) {
979 if (!pim_bsr_rpf_check(pim
, bshdr
->bsr_addr
.addr
,
983 "%s : RPF check fail for BSR address %s",
984 __PRETTY_FUNCTION__
, bsr_str
);
989 } else if (if_lookup_exact_address(&ip_hdr
->ip_dst
, AF_INET
,
991 /* Unicast BSM received - if ucast bsm not enabled on
992 * the interface, drop it
994 if (!pim_ifp
->ucast_bsm_accept
) {
997 "%s : Unicast BSM not enabled on interface %s",
998 __PRETTY_FUNCTION__
, ifp
->name
);
999 pim_ifp
->pim_ifstat_ucast_bsm_cfg_miss
++;
1006 zlog_debug("%s : Invalid destination address",
1007 __PRETTY_FUNCTION__
);
1014 zlog_debug("%s : Empty Pref BSM received",
1015 __PRETTY_FUNCTION__
);
1017 /* Parse Update bsm rp table and install/uninstall rp if required */
1018 if (!pim_bsm_parse_install_g2rp(
1019 &pim_ifp
->pim
->global_scope
,
1020 (buf
+ PIM_BSM_HDR_LEN
+ PIM_MSG_HEADER_LEN
),
1021 (buf_size
- PIM_BSM_HDR_LEN
- PIM_MSG_HEADER_LEN
),
1023 if (PIM_DEBUG_BSM
) {
1024 zlog_debug("%s, Parsing BSM failed.\r\n",
1025 __PRETTY_FUNCTION__
);
1030 /* Restart the bootstrap timer */
1031 pim_bs_timer_restart(&pim_ifp
->pim
->global_scope
,
1032 PIM_BSR_DEFAULT_TIMEOUT
);
1034 /* If new BSM received, clear the old bsm database */
1035 if (pim_ifp
->pim
->global_scope
.bsm_frag_tag
!= frag_tag
) {
1036 if (PIM_DEBUG_BSM
) {
1037 zlog_debug("%s: Current frag tag: %d Frag teg rcvd: %d",
1038 __PRETTY_FUNCTION__
,
1039 pim_ifp
->pim
->global_scope
.bsm_frag_tag
,
1042 list_delete_all_node(pim_ifp
->pim
->global_scope
.bsm_list
);
1043 pim_ifp
->pim
->global_scope
.bsm_frag_tag
= frag_tag
;
1046 /* update the scope information from bsm */
1047 pim_bsm_update(pim
, bshdr
->bsr_addr
.addr
, bshdr
->bsr_prio
);