]> git.proxmox.com Git - mirror_frr.git/blame - pimd/pim_bsm.c
*: Rename `struct thread` to `struct event`
[mirror_frr.git] / pimd / pim_bsm.c
CommitLineData
acddc0ed 1// SPDX-License-Identifier: GPL-2.0-or-later
361b5843 2/*
3 * pim_bsm.c: PIM BSM handling routines
4 *
5 * Copyright (C) 2018-19 Vmware, Inc.
6 * Saravanan K
361b5843 7 */
2618a52e
DL
8
9#ifdef HAVE_CONFIG_H
10#include "config.h"
11#endif
12
361b5843 13#include "if.h"
14#include "pimd.h"
15#include "pim_iface.h"
361b5843 16#include "pim_instance.h"
e34e07e6 17#include "pim_neighbor.h"
361b5843 18#include "pim_rpf.h"
19#include "pim_hello.h"
20#include "pim_pim.h"
21#include "pim_nht.h"
22#include "pim_bsm.h"
23#include "pim_time.h"
62596d9a 24#include "pim_zebra.h"
c6ced474 25#include "pim_util.h"
361b5843 26
27/* Functions forward declaration */
28static void pim_bs_timer_start(struct bsm_scope *scope, int bs_timeout);
a5164e97 29static void pim_g2rp_timer_start(struct bsm_rpinfo *bsrp, int hold_time);
30static inline void pim_g2rp_timer_restart(struct bsm_rpinfo *bsrp,
31 int hold_time);
23255dfd 32
33/* Memory Types */
bf8d3d6a 34DEFINE_MTYPE_STATIC(PIMD, PIM_BSGRP_NODE, "PIM BSR advertised grp info");
fdab2940 35DEFINE_MTYPE_STATIC(PIMD, PIM_BSRP_INFO, "PIM BSR advertised RP info");
d4a4525c 36DEFINE_MTYPE_STATIC(PIMD, PIM_BSM_FRAG, "PIM BSM fragment");
bf8d3d6a 37DEFINE_MTYPE_STATIC(PIMD, PIM_BSM_PKT_VAR_MEM, "PIM BSM Packet");
361b5843 38
79d97386 39/* All bsm packets forwarded shall be fit within ip mtu less iphdr(max) */
40#define MAX_IP_HDR_LEN 24
41
16c926c8 42/* pim_bsm_write_config - Write the interface pim bsm configuration.*/
d0e418b4 43void pim_bsm_write_config(struct vty *vty, struct interface *ifp)
16c926c8 44{
45 struct pim_interface *pim_ifp = ifp->info;
46
47 if (pim_ifp) {
48 if (!pim_ifp->bsm_enable)
d17b6892 49 vty_out(vty, " no " PIM_AF_NAME " pim bsm\n");
16c926c8 50 if (!pim_ifp->ucast_bsm_accept)
d17b6892 51 vty_out(vty, " no " PIM_AF_NAME " pim unicast-bsm\n");
16c926c8 52 }
53}
54
fdab2940
DL
55static void pim_bsm_rpinfo_free(struct bsm_rpinfo *bsrp_info)
56{
57 THREAD_OFF(bsrp_info->g2rp_timer);
58 XFREE(MTYPE_PIM_BSRP_INFO, bsrp_info);
59}
60
b09bd804 61static void pim_bsm_rpinfos_free(struct bsm_rpinfos_head *head)
fdab2940
DL
62{
63 struct bsm_rpinfo *bsrp_info;
64
65 while ((bsrp_info = bsm_rpinfos_pop(head)))
66 pim_bsm_rpinfo_free(bsrp_info);
67}
68
b09bd804 69static void pim_free_bsgrp_data(struct bsgrp_node *bsgrp_node)
361b5843 70{
fdab2940
DL
71 pim_bsm_rpinfos_free(bsgrp_node->bsrp_list);
72 pim_bsm_rpinfos_free(bsgrp_node->partial_bsrp_list);
361b5843 73 XFREE(MTYPE_PIM_BSGRP_NODE, bsgrp_node);
74}
75
b09bd804 76static void pim_free_bsgrp_node(struct route_table *rt, struct prefix *grp)
c295e391 77{
78 struct route_node *rn;
79
80 rn = route_node_lookup(rt, grp);
81 if (rn) {
82 rn->info = NULL;
83 route_unlock_node(rn);
84 route_unlock_node(rn);
85 }
86}
87
d4a4525c 88static void pim_bsm_frag_free(struct bsm_frag *bsfrag)
361b5843 89{
d4a4525c
DL
90 XFREE(MTYPE_PIM_BSM_FRAG, bsfrag);
91}
92
b09bd804 93static void pim_bsm_frags_free(struct bsm_scope *scope)
d4a4525c
DL
94{
95 struct bsm_frag *bsfrag;
96
97 while ((bsfrag = bsm_frags_pop(scope->bsm_frags)))
98 pim_bsm_frag_free(bsfrag);
361b5843 99}
100
fdab2940
DL
101int pim_bsm_rpinfo_cmp(const struct bsm_rpinfo *node1,
102 const struct bsm_rpinfo *node2)
7b3e6ba1 103{
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
107 * higher precedance.
108 * Step-3 : If Hash val is same then highest rp address will
109 * become elected RP.
110 */
111 if (node1->rp_prio < node2->rp_prio)
112 return -1;
113 if (node1->rp_prio > node2->rp_prio)
114 return 1;
115 if (node1->hash < node2->hash)
116 return 1;
117 if (node1->hash > node2->hash)
118 return -1;
1407e40f 119 return pim_addr_cmp(node2->rp_address, node1->rp_address);
7b3e6ba1 120}
121
7b3e6ba1 122static struct bsgrp_node *pim_bsm_new_bsgrp_node(struct route_table *rt,
123 struct prefix *grp)
124{
125 struct route_node *rn;
126 struct bsgrp_node *bsgrp;
127
128 rn = route_node_get(rt, grp);
129 if (!rn) {
15569c58 130 zlog_warn("%s: route node creation failed", __func__);
7b3e6ba1 131 return NULL;
132 }
133 bsgrp = XCALLOC(MTYPE_PIM_BSGRP_NODE, sizeof(struct bsgrp_node));
134
7b3e6ba1 135 rn->info = bsgrp;
fdab2940
DL
136 bsm_rpinfos_init(bsgrp->bsrp_list);
137 bsm_rpinfos_init(bsgrp->partial_bsrp_list);
7b3e6ba1 138
139 prefix_copy(&bsgrp->group, grp);
140 return bsgrp;
141}
142
e6685141 143static void pim_on_bs_timer(struct event *t)
23255dfd 144{
c843f56d 145 struct route_node *rn;
146 struct bsm_scope *scope;
147 struct bsgrp_node *bsgrp_node;
148 struct bsm_rpinfo *bsrp;
c843f56d 149
150 scope = THREAD_ARG(t);
151 THREAD_OFF(scope->bs_timer);
152
153 if (PIM_DEBUG_BSM)
154 zlog_debug("%s: Bootstrap Timer expired for scope: %d",
15569c58 155 __func__, scope->sz_id);
c843f56d 156
5f010b12 157 pim_nht_bsr_del(scope->pim, scope->current_bsr);
c843f56d 158 /* Reset scope zone data */
159 scope->accept_nofwd_bsm = false;
160 scope->state = ACCEPT_ANY;
e309769a 161 scope->current_bsr = PIMADDR_ANY;
c843f56d 162 scope->current_bsr_prio = 0;
163 scope->current_bsr_first_ts = 0;
164 scope->current_bsr_last_ts = 0;
165 scope->bsm_frag_tag = 0;
d4a4525c 166 pim_bsm_frags_free(scope);
c843f56d 167
168 for (rn = route_top(scope->bsrp_table); rn; rn = route_next(rn)) {
169
170 bsgrp_node = (struct bsgrp_node *)rn->info;
171 if (!bsgrp_node) {
172 if (PIM_DEBUG_BSM)
15569c58 173 zlog_debug("%s: bsgrp_node is null", __func__);
c843f56d 174 continue;
175 }
176 /* Give grace time for rp to continue for another hold time */
fdab2940
DL
177 bsrp = bsm_rpinfos_first(bsgrp_node->bsrp_list);
178 if (bsrp)
c843f56d 179 pim_g2rp_timer_restart(bsrp, bsrp->rp_holdtime);
fdab2940 180
c843f56d 181 /* clear pending list */
fdab2940
DL
182 pim_bsm_rpinfos_free(bsgrp_node->partial_bsrp_list);
183 bsgrp_node->pend_rp_cnt = 0;
c843f56d 184 }
23255dfd 185}
186
b09bd804 187static void pim_bs_timer_stop(struct bsm_scope *scope)
23255dfd 188{
189 if (PIM_DEBUG_BSM)
15569c58
DA
190 zlog_debug("%s : BS timer being stopped of sz: %d", __func__,
191 scope->sz_id);
23255dfd 192 THREAD_OFF(scope->bs_timer);
193}
194
195static void pim_bs_timer_start(struct bsm_scope *scope, int bs_timeout)
196{
197 if (!scope) {
198 if (PIM_DEBUG_BSM)
15569c58 199 zlog_debug("%s : Invalid scope(NULL).", __func__);
23255dfd 200 return;
201 }
202 THREAD_OFF(scope->bs_timer);
203 if (PIM_DEBUG_BSM)
15569c58
DA
204 zlog_debug(
205 "%s : starting bs timer for scope %d with timeout %d secs",
206 __func__, scope->sz_id, bs_timeout);
23255dfd 207 thread_add_timer(router->master, pim_on_bs_timer, scope, bs_timeout,
208 &scope->bs_timer);
209}
210
5acde1cf 211static inline void pim_bs_timer_restart(struct bsm_scope *scope, int bs_timeout)
212{
213 pim_bs_timer_start(scope, bs_timeout);
214}
215
361b5843 216void pim_bsm_proc_init(struct pim_instance *pim)
217{
218 memset(&pim->global_scope, 0, sizeof(struct bsm_scope));
219
220 pim->global_scope.sz_id = PIM_GBL_SZ_ID;
221 pim->global_scope.bsrp_table = route_table_init();
222 pim->global_scope.accept_nofwd_bsm = true;
223 pim->global_scope.state = NO_INFO;
224 pim->global_scope.pim = pim;
d4a4525c 225 bsm_frags_init(pim->global_scope.bsm_frags);
361b5843 226 pim_bs_timer_start(&pim->global_scope, PIM_BS_TIME);
227}
228
229void pim_bsm_proc_free(struct pim_instance *pim)
230{
231 struct route_node *rn;
232 struct bsgrp_node *bsgrp;
233
234 pim_bs_timer_stop(&pim->global_scope);
d4a4525c 235 pim_bsm_frags_free(&pim->global_scope);
361b5843 236
d0e418b4 237 for (rn = route_top(pim->global_scope.bsrp_table); rn;
238 rn = route_next(rn)) {
361b5843 239 bsgrp = rn->info;
240 if (!bsgrp)
241 continue;
242 pim_free_bsgrp_data(bsgrp);
243 }
244
4d19a911 245 route_table_finish(pim->global_scope.bsrp_table);
361b5843 246}
247
c295e391 248static bool is_hold_time_elapsed(void *data)
249{
250 struct bsm_rpinfo *bsrp;
251
252 bsrp = data;
253
254 if (bsrp->elapse_time < bsrp->rp_holdtime)
255 return false;
256 else
257 return true;
258}
259
e6685141 260static void pim_on_g2rp_timer(struct event *t)
a5164e97 261{
c295e391 262 struct bsm_rpinfo *bsrp;
263 struct bsm_rpinfo *bsrp_node;
264 struct bsgrp_node *bsgrp_node;
c295e391 265 struct pim_instance *pim;
266 struct rp_info *rp_info;
267 struct route_node *rn;
268 uint16_t elapse;
9dca52b9 269 pim_addr bsrp_addr;
c295e391 270
271 bsrp = THREAD_ARG(t);
272 THREAD_OFF(bsrp->g2rp_timer);
273 bsgrp_node = bsrp->bsgrp_node;
274
275 /* elapse time is the hold time of expired node */
276 elapse = bsrp->rp_holdtime;
277 bsrp_addr = bsrp->rp_address;
278
279 /* update elapse for all bsrp nodes */
fdab2940 280 frr_each_safe (bsm_rpinfos, bsgrp_node->bsrp_list, bsrp_node) {
c295e391 281 bsrp_node->elapse_time += elapse;
282
fdab2940
DL
283 if (is_hold_time_elapsed(bsrp_node)) {
284 bsm_rpinfos_del(bsgrp_node->bsrp_list, bsrp_node);
285 pim_bsm_rpinfo_free(bsrp_node);
286 }
287 }
c295e391 288
289 /* Get the next elected rp node */
fdab2940 290 bsrp = bsm_rpinfos_first(bsgrp_node->bsrp_list);
c295e391 291 pim = bsgrp_node->scope->pim;
292 rn = route_node_lookup(pim->rp_table, &bsgrp_node->group);
293
294 if (!rn) {
5e81f5dd 295 zlog_warn("%s: Route node doesn't exist", __func__);
cc9f21da 296 return;
c295e391 297 }
298
299 rp_info = (struct rp_info *)rn->info;
300
301 if (!rp_info) {
302 route_unlock_node(rn);
cc9f21da 303 return;
c295e391 304 }
305
306 if (rp_info->rp_src != RP_SRC_STATIC) {
307 /* If new rp available, change it else delete the existing */
308 if (bsrp) {
c295e391 309 pim_g2rp_timer_start(
310 bsrp, (bsrp->rp_holdtime - bsrp->elapse_time));
49b7b2c4 311 pim_rp_change(pim, bsrp->rp_address, bsgrp_node->group,
c295e391 312 RP_SRC_BSR);
313 } else {
314 pim_rp_del(pim, bsrp_addr, bsgrp_node->group, NULL,
315 RP_SRC_BSR);
316 }
317 }
318
fdab2940
DL
319 if (!bsm_rpinfos_count(bsgrp_node->bsrp_list)
320 && !bsm_rpinfos_count(bsgrp_node->partial_bsrp_list)) {
c295e391 321 pim_free_bsgrp_node(pim->global_scope.bsrp_table,
322 &bsgrp_node->group);
323 pim_free_bsgrp_data(bsgrp_node);
324 }
a5164e97 325}
326
327static void pim_g2rp_timer_start(struct bsm_rpinfo *bsrp, int hold_time)
328{
329 if (!bsrp) {
330 if (PIM_DEBUG_BSM)
15569c58 331 zlog_debug("%s : Invalid brsp(NULL).", __func__);
a5164e97 332 return;
333 }
334 THREAD_OFF(bsrp->g2rp_timer);
2dbe669b 335 if (PIM_DEBUG_BSM)
a5164e97 336 zlog_debug(
11e1593f 337 "%s : starting g2rp timer for grp: %pFX - rp: %pPAs with timeout %d secs(Actual Hold time : %d secs)",
338 __func__, &bsrp->bsgrp_node->group, &bsrp->rp_address,
339 hold_time, bsrp->rp_holdtime);
a5164e97 340
341 thread_add_timer(router->master, pim_on_g2rp_timer, bsrp, hold_time,
342 &bsrp->g2rp_timer);
343}
344
345static inline void pim_g2rp_timer_restart(struct bsm_rpinfo *bsrp,
346 int hold_time)
347{
348 pim_g2rp_timer_start(bsrp, hold_time);
349}
350
20fd30e5 351static void pim_g2rp_timer_stop(struct bsm_rpinfo *bsrp)
352{
353 if (!bsrp)
354 return;
355
2dbe669b 356 if (PIM_DEBUG_BSM)
11e1593f 357 zlog_debug("%s : stopping g2rp timer for grp: %pFX - rp: %pPAs",
2dbe669b 358 __func__, &bsrp->bsgrp_node->group,
ee2bbf7c 359 &bsrp->rp_address);
20fd30e5 360
361 THREAD_OFF(bsrp->g2rp_timer);
362}
363
364static bool is_hold_time_zero(void *data)
365{
366 struct bsm_rpinfo *bsrp;
367
368 bsrp = data;
369
370 if (bsrp->rp_holdtime)
371 return false;
372 else
373 return true;
374}
375
376static void pim_instate_pend_list(struct bsgrp_node *bsgrp_node)
377{
378 struct bsm_rpinfo *active;
379 struct bsm_rpinfo *pend;
20fd30e5 380 struct rp_info *rp_info;
381 struct route_node *rn;
382 struct pim_instance *pim;
383 struct rp_info *rp_all;
384 struct prefix group_all;
385 bool had_rp_node = true;
386
387 pim = bsgrp_node->scope->pim;
fdab2940 388 active = bsm_rpinfos_first(bsgrp_node->bsrp_list);
20fd30e5 389
390 /* Remove nodes with hold time 0 & check if list still has a head */
5f1808ac
DS
391 frr_each_safe (bsm_rpinfos, bsgrp_node->partial_bsrp_list, pend) {
392 if (is_hold_time_zero(pend)) {
fdab2940 393 bsm_rpinfos_del(bsgrp_node->partial_bsrp_list, pend);
5f1808ac
DS
394 pim_bsm_rpinfo_free(pend);
395 }
396 }
fdab2940
DL
397
398 pend = bsm_rpinfos_first(bsgrp_node->partial_bsrp_list);
20fd30e5 399
c6ced474 400 if (!pim_get_all_mcast_group(&group_all))
20fd30e5 401 return;
402
403 rp_all = pim_rp_find_match_group(pim, &group_all);
404 rn = route_node_lookup(pim->rp_table, &bsgrp_node->group);
405
406 if (pend)
407 pim_g2rp_timer_start(pend, pend->rp_holdtime);
408
409 /* if rp node doesn't exist or exist but not configured(rp_all),
410 * install the rp from head(if exists) of partial list. List is
411 * is sorted such that head is the elected RP for the group.
412 */
cc144e8b 413 if (!rn || (prefix_same(&rp_all->group, &bsgrp_node->group) &&
414 pim_rpf_addr_is_inaddr_any(&rp_all->rp))) {
20fd30e5 415 if (PIM_DEBUG_BSM)
15569c58 416 zlog_debug("%s: Route node doesn't exist", __func__);
20fd30e5 417 if (pend)
418 pim_rp_new(pim, pend->rp_address, bsgrp_node->group,
419 NULL, RP_SRC_BSR);
420 had_rp_node = false;
421 } else {
422 rp_info = (struct rp_info *)rn->info;
423 if (!rp_info) {
424 route_unlock_node(rn);
425 if (pend)
426 pim_rp_new(pim, pend->rp_address,
427 bsgrp_node->group, NULL, RP_SRC_BSR);
428 had_rp_node = false;
429 }
430 }
431
432 /* We didn't have rp node and pending list is empty(unlikely), cleanup*/
433 if ((!had_rp_node) && (!pend)) {
434 pim_free_bsgrp_node(bsgrp_node->scope->bsrp_table,
435 &bsgrp_node->group);
436 pim_free_bsgrp_data(bsgrp_node);
437 return;
438 }
439
440 if ((had_rp_node) && (rp_info->rp_src != RP_SRC_STATIC)) {
441 /* This means we searched and got rp node, needs unlock */
442 route_unlock_node(rn);
443
444 if (active && pend) {
11e1593f 445 if (pim_addr_cmp(active->rp_address, pend->rp_address))
20fd30e5 446 pim_rp_change(pim, pend->rp_address,
447 bsgrp_node->group, RP_SRC_BSR);
448 }
449
450 /* Possible when the first BSM has group with 0 rp count */
451 if ((!active) && (!pend)) {
452 if (PIM_DEBUG_BSM) {
453 zlog_debug(
454 "%s: Both bsrp and partial list are empty",
15569c58 455 __func__);
20fd30e5 456 }
457 pim_free_bsgrp_node(bsgrp_node->scope->bsrp_table,
458 &bsgrp_node->group);
459 pim_free_bsgrp_data(bsgrp_node);
460 return;
461 }
462
463 /* Possible when a group with 0 rp count received in BSM */
464 if ((active) && (!pend)) {
465 pim_rp_del(pim, active->rp_address, bsgrp_node->group,
466 NULL, RP_SRC_BSR);
467 pim_free_bsgrp_node(bsgrp_node->scope->bsrp_table,
468 &bsgrp_node->group);
469 if (PIM_DEBUG_BSM) {
470 zlog_debug("%s:Pend List is null,del grp node",
15569c58 471 __func__);
20fd30e5 472 }
473 pim_free_bsgrp_data(bsgrp_node);
474 return;
475 }
476 }
477
478 if ((had_rp_node) && (rp_info->rp_src == RP_SRC_STATIC)) {
479 /* We need to unlock rn this case */
480 route_unlock_node(rn);
481 /* there is a chance that static rp exist and bsrp cleaned
482 * so clean bsgrp node if pending list empty
483 */
484 if (!pend) {
485 if (PIM_DEBUG_BSM)
486 zlog_debug(
487 "%s: Partial list is empty, static rp exists",
15569c58 488 __func__);
20fd30e5 489 pim_free_bsgrp_node(bsgrp_node->scope->bsrp_table,
490 &bsgrp_node->group);
491 pim_free_bsgrp_data(bsgrp_node);
492 return;
493 }
494 }
495
496 /* swap the list & delete all nodes in partial list (old bsrp_list)
497 * before swap
498 * active is head of bsrp list
499 * pend is head of partial list
500 * After swap
501 * active is head of partial list
502 * pend is head of bsrp list
503 * So check appriate head after swap and clean the new partial list
504 */
fdab2940
DL
505 bsm_rpinfos_swap_all(bsgrp_node->bsrp_list,
506 bsgrp_node->partial_bsrp_list);
20fd30e5 507
fdab2940 508 if (active)
20fd30e5 509 pim_g2rp_timer_stop(active);
fdab2940 510 pim_bsm_rpinfos_free(bsgrp_node->partial_bsrp_list);
20fd30e5 511}
512
e309769a 513static bool is_preferred_bsr(struct pim_instance *pim, pim_addr bsr,
5acde1cf 514 uint32_t bsr_prio)
515{
e309769a 516 if (!pim_addr_cmp(bsr, pim->global_scope.current_bsr))
5acde1cf 517 return true;
518
519 if (bsr_prio > pim->global_scope.current_bsr_prio)
520 return true;
521
522 else if (bsr_prio == pim->global_scope.current_bsr_prio) {
e309769a 523 if (pim_addr_cmp(bsr, pim->global_scope.current_bsr) >= 0)
5acde1cf 524 return true;
525 else
526 return false;
527 } else
528 return false;
529}
530
e309769a 531static void pim_bsm_update(struct pim_instance *pim, pim_addr bsr,
5acde1cf 532 uint32_t bsr_prio)
533{
11e1593f 534 if (pim_addr_cmp(bsr, pim->global_scope.current_bsr)) {
5f010b12 535 pim_nht_bsr_del(pim, pim->global_scope.current_bsr);
4efdb9c6 536 pim_nht_bsr_add(pim, bsr);
5acde1cf 537
5acde1cf 538 pim->global_scope.current_bsr = bsr;
539 pim->global_scope.current_bsr_first_ts =
540 pim_time_monotonic_sec();
541 pim->global_scope.state = ACCEPT_PREFERRED;
542 }
543 pim->global_scope.current_bsr_prio = bsr_prio;
544 pim->global_scope.current_bsr_last_ts = pim_time_monotonic_sec();
545}
546
b09bd804
DL
547void pim_bsm_clear(struct pim_instance *pim)
548{
549 struct route_node *rn;
550 struct route_node *rpnode;
551 struct bsgrp_node *bsgrp;
b63192cf 552 pim_addr nht_p;
b09bd804
DL
553 struct prefix g_all;
554 struct rp_info *rp_all;
555 struct pim_upstream *up;
556 struct rp_info *rp_info;
62596d9a 557 bool upstream_updated = false;
b09bd804 558
5f010b12 559 pim_nht_bsr_del(pim, pim->global_scope.current_bsr);
b09bd804
DL
560
561 /* Reset scope zone data */
562 pim->global_scope.accept_nofwd_bsm = false;
563 pim->global_scope.state = ACCEPT_ANY;
e309769a 564 pim->global_scope.current_bsr = PIMADDR_ANY;
b09bd804
DL
565 pim->global_scope.current_bsr_prio = 0;
566 pim->global_scope.current_bsr_first_ts = 0;
567 pim->global_scope.current_bsr_last_ts = 0;
568 pim->global_scope.bsm_frag_tag = 0;
569 pim_bsm_frags_free(&pim->global_scope);
570
571 pim_bs_timer_stop(&pim->global_scope);
572
573 for (rn = route_top(pim->global_scope.bsrp_table); rn;
574 rn = route_next(rn)) {
575 bsgrp = rn->info;
576 if (!bsgrp)
577 continue;
578
579 rpnode = route_node_lookup(pim->rp_table, &bsgrp->group);
580
581 if (!rpnode) {
582 pim_free_bsgrp_node(bsgrp->scope->bsrp_table,
583 &bsgrp->group);
584 pim_free_bsgrp_data(bsgrp);
585 continue;
586 }
587
588 rp_info = (struct rp_info *)rpnode->info;
589
590 if ((!rp_info) || (rp_info->rp_src != RP_SRC_BSR)) {
591 pim_free_bsgrp_node(bsgrp->scope->bsrp_table,
592 &bsgrp->group);
593 pim_free_bsgrp_data(bsgrp);
594 continue;
595 }
596
597 /* Deregister addr with Zebra NHT */
b63192cf 598 nht_p = rp_info->rp.rpf_addr;
b09bd804
DL
599
600 if (PIM_DEBUG_PIM_NHT_RP) {
b63192cf 601 zlog_debug("%s: Deregister RP addr %pPA with Zebra ",
b09bd804
DL
602 __func__, &nht_p);
603 }
604
e6e53006 605 pim_delete_tracked_nexthop(pim, nht_p, NULL, rp_info);
b09bd804 606
c6ced474 607 if (!pim_get_all_mcast_group(&g_all))
b09bd804
DL
608 return;
609
610 rp_all = pim_rp_find_match_group(pim, &g_all);
611
612 if (rp_all == rp_info) {
b63192cf 613 rp_all->rp.rpf_addr = PIMADDR_ANY;
b09bd804
DL
614 rp_all->i_am_rp = 0;
615 } else {
616 /* Delete the rp_info from rp-list */
617 listnode_delete(pim->rp_list, rp_info);
618
619 /* Delete the rp node from rp_table */
620 rpnode->info = NULL;
621 route_unlock_node(rpnode);
622 route_unlock_node(rpnode);
623 XFREE(MTYPE_PIM_RP, rp_info);
624 }
625
626 pim_free_bsgrp_node(bsgrp->scope->bsrp_table, &bsgrp->group);
627 pim_free_bsgrp_data(bsgrp);
628 }
629 pim_rp_refresh_group_to_rp_mapping(pim);
630
631
632 frr_each (rb_pim_upstream, &pim->upstream_head, up) {
633 /* Find the upstream (*, G) whose upstream address is same as
634 * the RP
635 */
2a27f13b 636 if (!pim_addr_is_any(up->sg.src))
b09bd804
DL
637 continue;
638
639 struct prefix grp;
640 struct rp_info *trp_info;
641
c631920c 642 pim_addr_to_prefix(&grp, up->sg.grp);
b09bd804
DL
643 trp_info = pim_rp_find_match_group(pim, &grp);
644
645 /* RP not found for the group grp */
cc144e8b 646 if (pim_rpf_addr_is_inaddr_any(&trp_info->rp)) {
b09bd804
DL
647 pim_upstream_rpf_clear(pim, up);
648 pim_rp_set_upstream_addr(pim, &up->upstream_addr,
649 up->sg.src, up->sg.grp);
650 } else {
651 /* RP found for the group grp */
652 pim_upstream_update(pim, up);
62596d9a 653 upstream_updated = true;
b09bd804
DL
654 }
655 }
62596d9a
MR
656
657 if (upstream_updated)
658 pim_zebra_update_all_interfaces(pim);
b09bd804
DL
659}
660
79d97386 661static bool pim_bsm_send_intf(uint8_t *buf, int len, struct interface *ifp,
29fd9fca 662 pim_addr dst_addr)
79d97386 663{
664 struct pim_interface *pim_ifp;
665
666 pim_ifp = ifp->info;
667
668 if (!pim_ifp) {
669 if (PIM_DEBUG_BSM)
670 zlog_debug("%s: Pim interface not available for %s",
15569c58 671 __func__, ifp->name);
79d97386 672 return false;
673 }
674
675 if (pim_ifp->pim_sock_fd == -1) {
676 if (PIM_DEBUG_BSM)
677 zlog_debug("%s: Pim sock not available for %s",
15569c58 678 __func__, ifp->name);
79d97386 679 return false;
680 }
681
3bb29c4e 682 if (pim_msg_send(pim_ifp->pim_sock_fd, pim_ifp->primary_address,
ac5c9346 683 dst_addr, buf, len, ifp)) {
3bb29c4e 684 zlog_warn("%s: Could not send BSM message on interface: %s",
15569c58 685 __func__, ifp->name);
3bb29c4e
DS
686 return false;
687 }
688
ac5c9346 689 if (!pim_ifp->pim_passive_enable)
690 pim_ifp->pim_ifstat_bsm_tx++;
691
79d97386 692 pim_ifp->pim->bsm_sent++;
693 return true;
694}
695
40270c35 696static bool pim_bsm_frag_send(uint8_t *buf, uint32_t len, struct interface *ifp,
29fd9fca 697 uint32_t pim_mtu, pim_addr dst_addr, bool no_fwd)
40270c35 698{
145e4c38 699 struct pim_interface *pim_ifp = ifp->info;
40270c35 700 struct bsmmsg_grpinfo *grpinfo, *curgrp;
701 uint8_t *firstgrp_ptr;
702 uint8_t *pkt;
703 uint8_t *pak_start;
704 uint32_t parsed_len = 0;
705 uint32_t this_pkt_rem;
706 uint32_t copy_byte_count;
707 uint32_t this_pkt_len;
708 uint8_t total_rp_cnt;
709 uint8_t this_rp_cnt;
710 uint8_t frag_rp_cnt;
711 uint8_t rp_fit_cnt;
712 bool pak_pending = false;
713
714 /* MTU passed here is PIM MTU (IP MTU less IP Hdr) */
715 if (pim_mtu < (PIM_MIN_BSM_LEN)) {
716 zlog_warn(
f79f7a7b 717 "%s: mtu(pim mtu: %d) size less than minimum bootstrap len",
15569c58 718 __func__, pim_mtu);
40270c35 719 if (PIM_DEBUG_BSM)
720 zlog_debug(
f79f7a7b 721 "%s: mtu (pim mtu:%d) less than minimum bootstrap len",
15569c58 722 __func__, pim_mtu);
40270c35 723 return false;
724 }
725
726 pak_start = XCALLOC(MTYPE_PIM_BSM_PKT_VAR_MEM, pim_mtu);
727
40270c35 728 pkt = pak_start;
729
730 /* Fill PIM header later before sending packet to calc checksum */
731 pkt += PIM_MSG_HEADER_LEN;
732 buf += PIM_MSG_HEADER_LEN;
733
734 /* copy bsm header to new packet at offset of pim hdr */
735 memcpy(pkt, buf, PIM_BSM_HDR_LEN);
736 pkt += PIM_BSM_HDR_LEN;
737 buf += PIM_BSM_HDR_LEN;
738 parsed_len += (PIM_MSG_HEADER_LEN + PIM_BSM_HDR_LEN);
739
740 /* Store the position of first grp ptr, which can be reused for
741 * next packet to start filling group. old bsm header and pim hdr
742 * remains. So need not be filled again for next packet onwards.
743 */
744 firstgrp_ptr = pkt;
745
746 /* we received mtu excluding IP hdr len as param
747 * now this_pkt_rem is mtu excluding
748 * PIM_BSM_HDR_LEN + PIM_MSG_HEADER_LEN
749 */
750 this_pkt_rem = pim_mtu - (PIM_BSM_HDR_LEN + PIM_MSG_HEADER_LEN);
751
752 /* For each group till the packet length parsed */
753 while (parsed_len < len) {
754 /* pkt ---> fragment's current pointer
755 * buf ---> input buffer's current pointer
756 * mtu ---> size of the pim packet - PIM header
757 * curgrp ---> current group on the fragment
758 * grpinfo ---> current group on the input buffer
759 * this_pkt_rem ---> bytes remaing on the current fragment
760 * rp_fit_cnt ---> num of rp for current grp that
761 * fits this frag
762 * total_rp_cnt ---> total rp present for the group in the buf
763 * frag_rp_cnt ---> no of rp for the group to be fit in
764 * the frag
765 * this_rp_cnt ---> how many rp have we parsed
766 */
767 grpinfo = (struct bsmmsg_grpinfo *)buf;
768 memcpy(pkt, buf, PIM_BSM_GRP_LEN);
769 curgrp = (struct bsmmsg_grpinfo *)pkt;
770 parsed_len += PIM_BSM_GRP_LEN;
771 pkt += PIM_BSM_GRP_LEN;
772 buf += PIM_BSM_GRP_LEN;
773 this_pkt_rem -= PIM_BSM_GRP_LEN;
774
775 /* initialize rp count and total_rp_cnt before the rp loop */
776 this_rp_cnt = 0;
777 total_rp_cnt = grpinfo->frag_rp_count;
778
779 /* Loop till all RPs for the group parsed */
780 while (this_rp_cnt < total_rp_cnt) {
781 /* All RP from a group processed here.
782 * group is pointed by grpinfo.
783 * At this point make sure buf pointing to a RP
784 * within a group
785 */
786 rp_fit_cnt = this_pkt_rem / PIM_BSM_RP_LEN;
787
788 /* calculate how many rp am i going to copy in
789 * this frag
790 */
791 if (rp_fit_cnt > (total_rp_cnt - this_rp_cnt))
792 frag_rp_cnt = total_rp_cnt - this_rp_cnt;
793 else
794 frag_rp_cnt = rp_fit_cnt;
795
796 /* populate the frag rp count for the current grp */
797 curgrp->frag_rp_count = frag_rp_cnt;
798 copy_byte_count = frag_rp_cnt * PIM_BSM_RP_LEN;
799
800 /* copy all the rp that we are fitting in this
801 * frag for the grp
802 */
803 memcpy(pkt, buf, copy_byte_count);
804 this_rp_cnt += frag_rp_cnt;
805 buf += copy_byte_count;
806 pkt += copy_byte_count;
807 parsed_len += copy_byte_count;
808 this_pkt_rem -= copy_byte_count;
809
810 /* Either we couldn't fit all rp for the group or the
811 * mtu reached
812 */
813 if ((this_rp_cnt < total_rp_cnt)
814 || (this_pkt_rem
815 < (PIM_BSM_GRP_LEN + PIM_BSM_RP_LEN))) {
816 /* No space to fit in more rp, send this pkt */
817 this_pkt_len = pim_mtu - this_pkt_rem;
145e4c38
DL
818 pim_msg_build_header(
819 pim_ifp->primary_address, dst_addr,
820 pak_start, this_pkt_len,
821 PIM_MSG_TYPE_BOOTSTRAP, no_fwd);
40270c35 822 pim_bsm_send_intf(pak_start, this_pkt_len, ifp,
823 dst_addr);
824
825 /* Construct next fragment. Reuse old packet */
826 pkt = firstgrp_ptr;
827 this_pkt_rem = pim_mtu - (PIM_BSM_HDR_LEN
828 + PIM_MSG_HEADER_LEN);
829
f5267398
DS
830 /* If pkt can't accommodate next group + at
831 * least one rp, we must break out of this inner
832 * loop and process next RP
40270c35 833 */
834 if (total_rp_cnt == this_rp_cnt)
835 break;
836
837 /* If some more RPs for the same group pending,
838 * fill grp hdr
839 */
840 memcpy(pkt, (uint8_t *)grpinfo,
841 PIM_BSM_GRP_LEN);
842 curgrp = (struct bsmmsg_grpinfo *)pkt;
843 pkt += PIM_BSM_GRP_LEN;
844 this_pkt_rem -= PIM_BSM_GRP_LEN;
845 pak_pending = false;
846 } else {
847 /* We filled something but not yet sent out */
848 pak_pending = true;
849 }
850 } /* while RP count */
851 } /*while parsed len */
852
853 /* Send if we have any unsent packet */
854 if (pak_pending) {
855 this_pkt_len = pim_mtu - this_pkt_rem;
145e4c38
DL
856 pim_msg_build_header(pim_ifp->primary_address, dst_addr,
857 pak_start, this_pkt_len,
40270c35 858 PIM_MSG_TYPE_BOOTSTRAP, no_fwd);
859 pim_bsm_send_intf(pak_start, (pim_mtu - this_pkt_rem), ifp,
860 dst_addr);
861 }
862 XFREE(MTYPE_PIM_BSM_PKT_VAR_MEM, pak_start);
863 return true;
864}
865
79d97386 866static void pim_bsm_fwd_whole_sz(struct pim_instance *pim, uint8_t *buf,
867 uint32_t len, int sz)
868{
869 struct interface *ifp;
870 struct pim_interface *pim_ifp;
29fd9fca 871 pim_addr dst_addr;
79d97386 872 uint32_t pim_mtu;
2951a7a4
QY
873 bool no_fwd = false;
874 bool ret = false;
79d97386 875
876 /* For now only global scope zone is supported, so send on all
877 * pim interfaces in the vrf
878 */
879 dst_addr = qpim_all_pim_routers_addr;
880 FOR_ALL_INTERFACES (pim->vrf, ifp) {
881 pim_ifp = ifp->info;
882 if ((!pim_ifp) || (!pim_ifp->bsm_enable))
883 continue;
9255f21e 884
885 /*
886 * RFC 5059 Sec 3.4:
887 * When a Bootstrap message is forwarded, it is forwarded out
888 * of every multicast-capable interface that has PIM neighbors.
889 *
890 * So skipping pim interfaces with no neighbors.
891 */
892 if (listcount(pim_ifp->pim_neighbor_list) == 0)
893 continue;
894
79d97386 895 pim_hello_require(ifp);
896 pim_mtu = ifp->mtu - MAX_IP_HDR_LEN;
897 if (pim_mtu < len) {
40270c35 898 ret = pim_bsm_frag_send(buf, len, ifp, pim_mtu,
899 dst_addr, no_fwd);
900 if (PIM_DEBUG_BSM)
901 zlog_debug("%s: pim_bsm_frag_send returned %s",
15569c58 902 __func__, ret ? "TRUE" : "FALSE");
79d97386 903 } else {
145e4c38
DL
904 pim_msg_build_header(pim_ifp->primary_address, dst_addr,
905 buf, len, PIM_MSG_TYPE_BOOTSTRAP,
79d97386 906 no_fwd);
907 if (!pim_bsm_send_intf(buf, len, ifp, dst_addr)) {
908 if (PIM_DEBUG_BSM)
909 zlog_debug(
2951a7a4 910 "%s: pim_bsm_send_intf returned false",
15569c58 911 __func__);
79d97386 912 }
913 }
914 }
915}
916
6bb2ef35 917bool pim_bsm_new_nbr_fwd(struct pim_neighbor *neigh, struct interface *ifp)
918{
29fd9fca 919 pim_addr dst_addr;
6bb2ef35 920 struct pim_interface *pim_ifp;
921 struct bsm_scope *scope;
d4a4525c 922 struct bsm_frag *bsfrag;
6bb2ef35 923 uint32_t pim_mtu;
924 bool no_fwd = true;
925 bool ret = false;
926
9bb93fa0
DL
927 if (PIM_DEBUG_BSM)
928 zlog_debug("%s: New neighbor %pPA seen on %s", __func__,
929 &neigh->source_addr, ifp->name);
6bb2ef35 930
931 pim_ifp = ifp->info;
932
933 /* DR only forwards BSM packet */
034db86b 934 if (!pim_addr_cmp(pim_ifp->pim_dr_addr, pim_ifp->primary_address)) {
6bb2ef35 935 if (PIM_DEBUG_BSM)
936 zlog_debug(
937 "%s: It is not DR, so don't forward BSM packet",
5e81f5dd 938 __func__);
6bb2ef35 939 }
940
941 if (!pim_ifp->bsm_enable) {
942 if (PIM_DEBUG_BSM)
5e81f5dd
DS
943 zlog_debug("%s: BSM proc not enabled on %s", __func__,
944 ifp->name);
6bb2ef35 945 return ret;
946 }
947
948 scope = &pim_ifp->pim->global_scope;
949
d4a4525c 950 if (!bsm_frags_count(scope->bsm_frags)) {
6bb2ef35 951 if (PIM_DEBUG_BSM)
952 zlog_debug("%s: BSM list for the scope is empty",
5e81f5dd 953 __func__);
6bb2ef35 954 return ret;
955 }
956
957 if (!pim_ifp->ucast_bsm_accept) {
958 dst_addr = qpim_all_pim_routers_addr;
959 if (PIM_DEBUG_BSM)
cefd2343 960 zlog_debug("%s: Sending BSM mcast to %pPA", __func__,
961 &neigh->source_addr);
6bb2ef35 962 } else {
963 dst_addr = neigh->source_addr;
964 if (PIM_DEBUG_BSM)
cefd2343 965 zlog_debug("%s: Sending BSM ucast to %pPA", __func__,
966 &neigh->source_addr);
6bb2ef35 967 }
968 pim_mtu = ifp->mtu - MAX_IP_HDR_LEN;
969 pim_hello_require(ifp);
970
d4a4525c
DL
971 frr_each (bsm_frags, scope->bsm_frags, bsfrag) {
972 if (pim_mtu < bsfrag->size) {
973 ret = pim_bsm_frag_send(bsfrag->data, bsfrag->size, ifp,
974 pim_mtu, dst_addr, no_fwd);
6bb2ef35 975 if (!ret) {
976 if (PIM_DEBUG_BSM)
977 zlog_debug(
978 "%s: pim_bsm_frag_send failed",
5e81f5dd 979 __func__);
6bb2ef35 980 }
981 } else {
982 /* Pim header needs to be constructed */
145e4c38
DL
983 pim_msg_build_header(pim_ifp->primary_address, dst_addr,
984 bsfrag->data, bsfrag->size,
6bb2ef35 985 PIM_MSG_TYPE_BOOTSTRAP, no_fwd);
d4a4525c
DL
986 ret = pim_bsm_send_intf(bsfrag->data, bsfrag->size, ifp,
987 dst_addr);
6bb2ef35 988 if (!ret) {
989 if (PIM_DEBUG_BSM)
990 zlog_debug(
991 "%s: pim_bsm_frag_send failed",
5e81f5dd 992 __func__);
6bb2ef35 993 }
994 }
995 }
996 return ret;
997}
998
d0e418b4 999struct bsgrp_node *pim_bsm_get_bsgrp_node(struct bsm_scope *scope,
1000 struct prefix *grp)
1001{
1002 struct route_node *rn;
1003 struct bsgrp_node *bsgrp;
1004
1005 rn = route_node_lookup(scope->bsrp_table, grp);
1006 if (!rn) {
1007 if (PIM_DEBUG_BSM)
1008 zlog_debug("%s: Route node doesn't exist for the group",
15569c58 1009 __func__);
d0e418b4 1010 return NULL;
1011 }
1012 bsgrp = rn->info;
1013 route_unlock_node(rn);
1014
1015 return bsgrp;
1016}
5acde1cf 1017
c0590b1c 1018static uint32_t hash_calc_on_grp_rp(struct prefix group, pim_addr rp,
7b3e6ba1 1019 uint8_t hashmasklen)
1020{
1021 uint64_t temp;
1022 uint32_t hash;
1023 uint32_t grpaddr;
1024 uint32_t rp_add;
1025 uint32_t mask = 0xffffffff;
1026
1027 /* mask to be made zero if hashmasklen is 0 because mask << 32
1028 * may not give 0. hashmasklen can be 0 to 32.
1029 */
1030 if (hashmasklen == 0)
1031 mask = 0;
1032
1033 /* in_addr stores ip in big endian, hence network byte order
1034 * convert to uint32 before processing hash
1035 */
c0590b1c 1036#if PIM_IPV == 4
7b3e6ba1 1037 grpaddr = ntohl(group.u.prefix4.s_addr);
c0590b1c 1038#else
1039 grpaddr = group.u.prefix6.s6_addr32[0] ^ group.u.prefix6.s6_addr32[1] ^
1040 group.u.prefix6.s6_addr32[2] ^ group.u.prefix6.s6_addr32[3];
1041#endif
7b3e6ba1 1042 /* Avoid shifting by 32 bit on a 32 bit register */
1043 if (hashmasklen)
1044 grpaddr = grpaddr & ((mask << (32 - hashmasklen)));
1045 else
1046 grpaddr = grpaddr & mask;
1407e40f 1047
c0590b1c 1048#if PIM_IPV == 4
7b3e6ba1 1049 rp_add = ntohl(rp.s_addr);
c0590b1c 1050#else
1051 rp_add = rp.s6_addr32[0] ^ rp.s6_addr32[1] ^ rp.s6_addr32[2] ^
1052 rp.s6_addr32[3];
1053#endif
29f7fc87
DS
1054 temp = 1103515245 * ((1103515245 * (uint64_t)grpaddr + 12345) ^ rp_add)
1055 + 12345;
7b3e6ba1 1056 hash = temp & (0x7fffffff);
1057 return hash;
1058}
1059
1060static bool pim_install_bsm_grp_rp(struct pim_instance *pim,
1061 struct bsgrp_node *grpnode,
1062 struct bsmmsg_rpinfo *rp)
1063{
1064 struct bsm_rpinfo *bsm_rpinfo;
1065 uint8_t hashMask_len = pim->global_scope.hashMasklen;
1066
1067 /*memory allocation for bsm_rpinfo */
fdab2940 1068 bsm_rpinfo = XCALLOC(MTYPE_PIM_BSRP_INFO, sizeof(*bsm_rpinfo));
7b3e6ba1 1069
7b3e6ba1 1070 bsm_rpinfo->rp_prio = rp->rp_pri;
1071 bsm_rpinfo->rp_holdtime = rp->rp_holdtime;
1407e40f 1072 bsm_rpinfo->rp_address = rp->rpaddr.addr;
7b3e6ba1 1073 bsm_rpinfo->elapse_time = 0;
1074
1075 /* Back pointer to the group node. */
1076 bsm_rpinfo->bsgrp_node = grpnode;
1077
1078 /* update hash for this rp node */
1079 bsm_rpinfo->hash = hash_calc_on_grp_rp(grpnode->group, rp->rpaddr.addr,
1080 hashMask_len);
fdab2940 1081 if (bsm_rpinfos_add(grpnode->partial_bsrp_list, bsm_rpinfo) == NULL) {
7b3e6ba1 1082 if (PIM_DEBUG_BSM)
1083 zlog_debug(
63efca0e 1084 "%s, bs_rpinfo node added to the partial bs_rplist.",
15569c58 1085 __func__);
7b3e6ba1 1086 return true;
1087 }
1088
1089 if (PIM_DEBUG_BSM)
63efca0e 1090 zlog_debug("%s: list node not added", __func__);
7b3e6ba1 1091
fdab2940 1092 XFREE(MTYPE_PIM_BSRP_INFO, bsm_rpinfo);
7b3e6ba1 1093 return false;
1094}
1095
1096static void pim_update_pending_rp_cnt(struct bsm_scope *sz,
1097 struct bsgrp_node *bsgrp,
1098 uint16_t bsm_frag_tag,
1099 uint32_t total_rp_count)
1100{
1101 if (bsgrp->pend_rp_cnt) {
1102 /* received bsm is different packet ,
1103 * it is not same fragment.
1104 */
1105 if (bsm_frag_tag != bsgrp->frag_tag) {
1106 if (PIM_DEBUG_BSM)
1107 zlog_debug(
63efca0e 1108 "%s,Received a new BSM ,so clear the pending bs_rpinfo list.",
15569c58 1109 __func__);
fdab2940 1110 pim_bsm_rpinfos_free(bsgrp->partial_bsrp_list);
7b3e6ba1 1111 bsgrp->pend_rp_cnt = total_rp_count;
1112 }
1113 } else
1114 bsgrp->pend_rp_cnt = total_rp_count;
1115
1116 bsgrp->frag_tag = bsm_frag_tag;
1117}
1118
1119/* Parsing BSR packet and adding to partial list of corresponding bsgrp node */
1120static bool pim_bsm_parse_install_g2rp(struct bsm_scope *scope, uint8_t *buf,
1121 int buflen, uint16_t bsm_frag_tag)
1122{
1123 struct bsmmsg_grpinfo grpinfo;
1124 struct bsmmsg_rpinfo rpinfo;
1125 struct prefix group;
1126 struct bsgrp_node *bsgrp = NULL;
1127 int frag_rp_cnt = 0;
1128 int offset = 0;
1129 int ins_count = 0;
81a688bc 1130 pim_addr grp_addr;
7b3e6ba1 1131
1132 while (buflen > offset) {
b1945363
DS
1133 if (offset + (int)sizeof(struct bsmmsg_grpinfo) > buflen) {
1134 if (PIM_DEBUG_BSM)
1135 zlog_debug(
1136 "%s: buflen received %d is less than the internal data structure of the packet would suggest",
15569c58 1137 __func__, buflen);
b1945363
DS
1138 return false;
1139 }
7b3e6ba1 1140 /* Extract Group tlv from BSM */
1141 memcpy(&grpinfo, buf, sizeof(struct bsmmsg_grpinfo));
81a688bc 1142 grp_addr = grpinfo.group.addr;
7b3e6ba1 1143
81a688bc 1144 if (PIM_DEBUG_BSM)
7b3e6ba1 1145 zlog_debug(
81a688bc 1146 "%s, Group %pPAs Rpcount:%d Fragment-Rp-count:%d",
1147 __func__, &grp_addr, grpinfo.rp_count,
7b3e6ba1 1148 grpinfo.frag_rp_count);
7b3e6ba1 1149
1150 buf += sizeof(struct bsmmsg_grpinfo);
1151 offset += sizeof(struct bsmmsg_grpinfo);
1152
81a688bc 1153 group.family = PIM_AF;
1154 if (grpinfo.group.mask > PIM_MAX_BITLEN) {
b1945363 1155 if (PIM_DEBUG_BSM)
15569c58 1156 zlog_debug(
81a688bc 1157 "%s, prefix length specified: %d is too long",
15569c58 1158 __func__, grpinfo.group.mask);
b1945363
DS
1159 return false;
1160 }
81a688bc 1161
1162 pim_addr_to_prefix(&group, grp_addr);
7b3e6ba1 1163 group.prefixlen = grpinfo.group.mask;
7b3e6ba1 1164
1165 /* Get the Group node for the BSM rp table */
1166 bsgrp = pim_bsm_get_bsgrp_node(scope, &group);
1167
43038bd5
DL
1168 if (grpinfo.rp_count == 0) {
1169 struct bsm_rpinfo *old_rpinfo;
1170
1171 /* BSR explicitly no longer has RPs for this group */
1172 if (!bsgrp)
1173 continue;
1174
81a688bc 1175 if (PIM_DEBUG_BSM)
1176 zlog_debug(
1177 "%s, Rp count is zero for group: %pPAs",
1178 __func__, &grp_addr);
43038bd5
DL
1179
1180 old_rpinfo = bsm_rpinfos_first(bsgrp->bsrp_list);
1181 if (old_rpinfo)
1182 pim_rp_del(scope->pim, old_rpinfo->rp_address,
1183 group, NULL, RP_SRC_BSR);
1184
1185 pim_free_bsgrp_node(scope->bsrp_table, &bsgrp->group);
1186 pim_free_bsgrp_data(bsgrp);
1187 continue;
1188 }
1189
7b3e6ba1 1190 if (!bsgrp) {
1191 if (PIM_DEBUG_BSM)
63efca0e
DL
1192 zlog_debug("%s, Create new BSM Group node.",
1193 __func__);
7b3e6ba1 1194
1195 /* create a new node to be added to the tree. */
1196 bsgrp = pim_bsm_new_bsgrp_node(scope->bsrp_table,
1197 &group);
1198
1199 if (!bsgrp) {
1200 zlog_debug(
63efca0e 1201 "%s, Failed to get the BSM group node.",
15569c58 1202 __func__);
7b3e6ba1 1203 continue;
1204 }
1205
1206 bsgrp->scope = scope;
1207 }
1208
1209 pim_update_pending_rp_cnt(scope, bsgrp, bsm_frag_tag,
1210 grpinfo.rp_count);
1211 frag_rp_cnt = grpinfo.frag_rp_count;
1212 ins_count = 0;
1213
1214 while (frag_rp_cnt--) {
b1945363
DS
1215 if (offset + (int)sizeof(struct bsmmsg_rpinfo)
1216 > buflen) {
1217 if (PIM_DEBUG_BSM)
1218 zlog_debug(
1219 "%s, buflen received: %u is less than the internal data structure of the packet would suggest",
15569c58 1220 __func__, buflen);
b1945363
DS
1221 return false;
1222 }
1223
7b3e6ba1 1224 /* Extract RP address tlv from BSM */
1225 memcpy(&rpinfo, buf, sizeof(struct bsmmsg_rpinfo));
1226 rpinfo.rp_holdtime = ntohs(rpinfo.rp_holdtime);
1227 buf += sizeof(struct bsmmsg_rpinfo);
1228 offset += sizeof(struct bsmmsg_rpinfo);
1229
1230 if (PIM_DEBUG_BSM) {
1407e40f 1231 pim_addr rp_addr;
7b3e6ba1 1232
1407e40f 1233 rp_addr = rpinfo.rpaddr.addr;
7b3e6ba1 1234 zlog_debug(
1407e40f 1235 "%s, Rp address - %pPAs; pri:%d hold:%d",
1236 __func__, &rp_addr, rpinfo.rp_pri,
15569c58 1237 rpinfo.rp_holdtime);
7b3e6ba1 1238 }
1239
1240 /* Call Install api to update grp-rp mappings */
1241 if (pim_install_bsm_grp_rp(scope->pim, bsgrp, &rpinfo))
1242 ins_count++;
1243 }
1244
1245 bsgrp->pend_rp_cnt -= ins_count;
1246
1247 if (!bsgrp->pend_rp_cnt) {
1248 if (PIM_DEBUG_BSM)
1249 zlog_debug(
1250 "%s, Recvd all the rps for this group, so bsrp list with penidng rp list.",
15569c58 1251 __func__);
20fd30e5 1252 /* replace the bsrp_list with pending list */
1253 pim_instate_pend_list(bsgrp);
7b3e6ba1 1254 }
1255 }
1256 return true;
1257}
1258
76bfa030 1259int pim_bsm_process(struct interface *ifp, pim_sgaddr *sg, uint8_t *buf,
5acde1cf 1260 uint32_t buf_size, bool no_fwd)
1261{
1262 struct bsm_hdr *bshdr;
79d97386 1263 int sz = PIM_GBL_SZ_ID;
5acde1cf 1264 struct bsmmsg_grpinfo *msg_grp;
1265 struct pim_interface *pim_ifp = NULL;
d4a4525c 1266 struct bsm_frag *bsfrag;
5acde1cf 1267 struct pim_instance *pim;
5acde1cf 1268 uint16_t frag_tag;
cefb7247 1269 pim_addr bsr_addr;
2951a7a4 1270 bool empty_bsm = false;
5acde1cf 1271
1272 /* BSM Packet acceptance validation */
1273 pim_ifp = ifp->info;
1274 if (!pim_ifp) {
1275 if (PIM_DEBUG_BSM)
1276 zlog_debug("%s: multicast not enabled on interface %s",
15569c58 1277 __func__, ifp->name);
5acde1cf 1278 return -1;
1279 }
1280
fd3eb43d 1281 if (pim_ifp->pim_passive_enable) {
1282 if (PIM_DEBUG_PIM_PACKETS)
1283 zlog_debug(
1284 "skip receiving PIM message on passive interface %s",
1285 ifp->name);
1286 return 0;
1287 }
1288
5acde1cf 1289 pim_ifp->pim_ifstat_bsm_rx++;
1290 pim = pim_ifp->pim;
1291 pim->bsm_rcvd++;
1292
1293 /* Drop if bsm processing is disabled on interface */
1294 if (!pim_ifp->bsm_enable) {
15569c58
DA
1295 zlog_warn("%s: BSM not enabled on interface %s", __func__,
1296 ifp->name);
5acde1cf 1297 pim_ifp->pim_ifstat_bsm_cfg_miss++;
1298 pim->bsm_dropped++;
1299 return -1;
1300 }
1301
d83a854b 1302 if (buf_size < (PIM_MSG_HEADER_LEN + sizeof(struct bsm_hdr))) {
b1945363 1303 if (PIM_DEBUG_BSM)
15569c58
DA
1304 zlog_debug(
1305 "%s: received buffer length of %d which is too small to properly decode",
1306 __func__, buf_size);
b1945363
DS
1307 return -1;
1308 }
1309
5acde1cf 1310 bshdr = (struct bsm_hdr *)(buf + PIM_MSG_HEADER_LEN);
1ae87bdd 1311 if (bshdr->hm_len > PIM_MAX_BITLEN) {
1312 zlog_warn(
1313 "Bad hashmask length for %s; got %hhu, expected value in range 0-32",
1314 PIM_AF_NAME, bshdr->hm_len);
817f8933
QY
1315 pim->bsm_dropped++;
1316 return -1;
1317 }
5acde1cf 1318 pim->global_scope.hashMasklen = bshdr->hm_len;
1319 frag_tag = ntohs(bshdr->frag_tag);
cefb7247
DL
1320 /* NB: bshdr->bsr_addr.addr is packed/unaligned => memcpy */
1321 memcpy(&bsr_addr, &bshdr->bsr_addr.addr, sizeof(bsr_addr));
5acde1cf 1322
1323 /* Identify empty BSM */
1324 if ((buf_size - PIM_BSM_HDR_LEN - PIM_MSG_HEADER_LEN) < PIM_BSM_GRP_LEN)
1325 empty_bsm = true;
1326
1327 if (!empty_bsm) {
1328 msg_grp = (struct bsmmsg_grpinfo *)(buf + PIM_MSG_HEADER_LEN
1329 + PIM_BSM_HDR_LEN);
1330 /* Currently we don't support scope zoned BSM */
1331 if (msg_grp->group.sz) {
1332 if (PIM_DEBUG_BSM)
1333 zlog_debug(
1334 "%s : Administratively scoped range BSM received",
15569c58 1335 __func__);
5acde1cf 1336 pim_ifp->pim_ifstat_bsm_invalid_sz++;
1337 pim->bsm_dropped++;
1338 return -1;
1339 }
1340 }
1341
1342 /* Drop if bsr is not preferred bsr */
cefb7247 1343 if (!is_preferred_bsr(pim, bsr_addr, bshdr->bsr_prio)) {
5acde1cf 1344 if (PIM_DEBUG_BSM)
1345 zlog_debug("%s : Received a non-preferred BSM",
15569c58 1346 __func__);
5acde1cf 1347 pim->bsm_dropped++;
1348 return -1;
1349 }
1350
1351 if (no_fwd) {
1352 /* only accept no-forward BSM if quick refresh on startup */
1353 if ((pim->global_scope.accept_nofwd_bsm)
1354 || (frag_tag == pim->global_scope.bsm_frag_tag)) {
1355 pim->global_scope.accept_nofwd_bsm = false;
1356 } else {
1357 if (PIM_DEBUG_BSM)
1358 zlog_debug(
1ae87bdd 1359 "%s : nofwd_bsm received on %pPAs when accpt_nofwd_bsm false",
cefb7247 1360 __func__, &bsr_addr);
5acde1cf 1361 pim->bsm_dropped++;
1362 pim_ifp->pim_ifstat_ucast_bsm_cfg_miss++;
1363 return -1;
1364 }
1365 }
1366
f0e91749 1367 if (!pim_addr_cmp(sg->grp, qpim_all_pim_routers_addr)) {
4efdb9c6
DL
1368 /* Multicast BSMs are only accepted if source interface & IP
1369 * match RPF towards the BSR's IP address, or they have
1370 * no-forward set
1371 */
cefb7247
DL
1372 if (!no_fwd &&
1373 !pim_nht_bsr_rpf_check(pim, bsr_addr, ifp, sg->src)) {
4efdb9c6
DL
1374 if (PIM_DEBUG_BSM)
1375 zlog_debug(
1ae87bdd 1376 "BSM check: RPF to BSR %pPAs is not %pPA%%%s",
cefb7247 1377 &bsr_addr, &sg->src, ifp->name);
4efdb9c6
DL
1378 pim->bsm_dropped++;
1379 return -1;
5acde1cf 1380 }
76bfa030 1381 } else if (if_address_is_local(&sg->grp, PIM_AF, pim->vrf->vrf_id)) {
5acde1cf 1382 /* Unicast BSM received - if ucast bsm not enabled on
1383 * the interface, drop it
1384 */
1385 if (!pim_ifp->ucast_bsm_accept) {
1386 if (PIM_DEBUG_BSM)
1387 zlog_debug(
1388 "%s : Unicast BSM not enabled on interface %s",
15569c58 1389 __func__, ifp->name);
5acde1cf 1390 pim_ifp->pim_ifstat_ucast_bsm_cfg_miss++;
1391 pim->bsm_dropped++;
1392 return -1;
1393 }
1394
1395 } else {
1396 if (PIM_DEBUG_BSM)
1397 zlog_debug("%s : Invalid destination address",
15569c58 1398 __func__);
5acde1cf 1399 pim->bsm_dropped++;
1400 return -1;
1401 }
1402
1403 if (empty_bsm) {
1404 if (PIM_DEBUG_BSM)
15569c58 1405 zlog_debug("%s : Empty Pref BSM received", __func__);
5acde1cf 1406 }
7b3e6ba1 1407 /* Parse Update bsm rp table and install/uninstall rp if required */
1408 if (!pim_bsm_parse_install_g2rp(
1409 &pim_ifp->pim->global_scope,
1410 (buf + PIM_BSM_HDR_LEN + PIM_MSG_HEADER_LEN),
1411 (buf_size - PIM_BSM_HDR_LEN - PIM_MSG_HEADER_LEN),
1412 frag_tag)) {
1413 if (PIM_DEBUG_BSM) {
63efca0e 1414 zlog_debug("%s, Parsing BSM failed.", __func__);
7b3e6ba1 1415 }
1416 pim->bsm_dropped++;
1417 return -1;
1418 }
5acde1cf 1419 /* Restart the bootstrap timer */
1420 pim_bs_timer_restart(&pim_ifp->pim->global_scope,
1421 PIM_BSR_DEFAULT_TIMEOUT);
1422
1423 /* If new BSM received, clear the old bsm database */
1424 if (pim_ifp->pim->global_scope.bsm_frag_tag != frag_tag) {
1425 if (PIM_DEBUG_BSM) {
1426 zlog_debug("%s: Current frag tag: %d Frag teg rcvd: %d",
15569c58 1427 __func__,
5acde1cf 1428 pim_ifp->pim->global_scope.bsm_frag_tag,
1429 frag_tag);
1430 }
d4a4525c 1431 pim_bsm_frags_free(&pim_ifp->pim->global_scope);
5acde1cf 1432 pim_ifp->pim->global_scope.bsm_frag_tag = frag_tag;
1433 }
1434
1435 /* update the scope information from bsm */
cefb7247 1436 pim_bsm_update(pim, bsr_addr, bshdr->bsr_prio);
79d97386 1437
1438 if (!no_fwd) {
1439 pim_bsm_fwd_whole_sz(pim_ifp->pim, buf, buf_size, sz);
d4a4525c
DL
1440 bsfrag = XCALLOC(MTYPE_PIM_BSM_FRAG,
1441 sizeof(struct bsm_frag) + buf_size);
79d97386 1442
d4a4525c
DL
1443 bsfrag->size = buf_size;
1444 memcpy(bsfrag->data, buf, buf_size);
1445 bsm_frags_add_tail(pim_ifp->pim->global_scope.bsm_frags,
1446 bsfrag);
79d97386 1447 }
1448
5acde1cf 1449 return 0;
1450}