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