Coverage Report

Created: 2025-10-08 06:07

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