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