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