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