Coverage Report

Created: 2026-01-01 06:18

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
827
#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
156k
{
57
156k
  EVENT_OFF(bsrp_info->g2rp_timer);
58
156k
  XFREE(MTYPE_PIM_BSRP_INFO, bsrp_info);
59
156k
}
60
61
static void pim_bsm_rpinfos_free(struct bsm_rpinfos_head *head)
62
117k
{
63
117k
  struct bsm_rpinfo *bsrp_info;
64
65
249k
  while ((bsrp_info = bsm_rpinfos_pop(head)))
66
131k
    pim_bsm_rpinfo_free(bsrp_info);
67
117k
}
68
69
static void pim_free_bsgrp_data(struct bsgrp_node *bsgrp_node)
70
29.9k
{
71
29.9k
  pim_bsm_rpinfos_free(bsgrp_node->bsrp_list);
72
29.9k
  pim_bsm_rpinfos_free(bsgrp_node->partial_bsrp_list);
73
29.9k
  XFREE(MTYPE_PIM_BSGRP_NODE, bsgrp_node);
74
29.9k
}
75
76
static void pim_free_bsgrp_node(struct route_table *rt, struct prefix *grp)
77
29.9k
{
78
29.9k
  struct route_node *rn;
79
80
29.9k
  rn = route_node_lookup(rt, grp);
81
29.9k
  if (rn) {
82
29.9k
    rn->info = NULL;
83
29.9k
    route_unlock_node(rn);
84
29.9k
    route_unlock_node(rn);
85
29.9k
  }
86
29.9k
}
87
88
static void pim_bsm_frag_free(struct bsm_frag *bsfrag)
89
657
{
90
657
  XFREE(MTYPE_PIM_BSM_FRAG, bsfrag);
91
657
}
92
93
static void pim_bsm_frags_free(struct bsm_scope *scope)
94
546
{
95
546
  struct bsm_frag *bsfrag;
96
97
1.20k
  while ((bsfrag = bsm_frags_pop(scope->bsm_frags)))
98
657
    pim_bsm_frag_free(bsfrag);
99
546
}
100
101
int pim_bsm_rpinfo_cmp(const struct bsm_rpinfo *node1,
102
           const struct bsm_rpinfo *node2)
103
9.99M
{
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
9.99M
  if (node1->rp_prio < node2->rp_prio)
112
7.84M
    return -1;
113
2.14M
  if (node1->rp_prio > node2->rp_prio)
114
24.9k
    return 1;
115
2.12M
  if (node1->hash < node2->hash)
116
45.6k
    return 1;
117
2.07M
  if (node1->hash > node2->hash)
118
1.87M
    return -1;
119
205k
  return pim_addr_cmp(node2->rp_address, node1->rp_address);
120
2.07M
}
121
122
static struct bsgrp_node *pim_bsm_new_bsgrp_node(struct route_table *rt,
123
             struct prefix *grp)
124
30.3k
{
125
30.3k
  struct route_node *rn;
126
30.3k
  struct bsgrp_node *bsgrp;
127
128
30.3k
  rn = route_node_get(rt, grp);
129
30.3k
  if (!rn) {
130
0
    zlog_warn("%s: route node creation failed", __func__);
131
0
    return NULL;
132
0
  }
133
30.3k
  bsgrp = XCALLOC(MTYPE_PIM_BSGRP_NODE, sizeof(struct bsgrp_node));
134
135
30.3k
  rn->info = bsgrp;
136
30.3k
  bsm_rpinfos_init(bsgrp->bsrp_list);
137
30.3k
  bsm_rpinfos_init(bsgrp->partial_bsrp_list);
138
139
30.3k
  prefix_copy(&bsgrp->group, grp);
140
30.3k
  return bsgrp;
141
30.3k
}
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
659
{
196
659
  if (!scope) {
197
0
    if (PIM_DEBUG_BSM)
198
0
      zlog_debug("%s : Invalid scope(NULL).", __func__);
199
0
    return;
200
0
  }
201
659
  EVENT_OFF(scope->bs_timer);
202
659
  if (PIM_DEBUG_BSM)
203
0
    zlog_debug(
204
659
      "%s : starting bs timer for scope %d with timeout %d secs",
205
659
      __func__, scope->sz_id, bs_timeout);
206
659
  event_add_timer(router->master, pim_on_bs_timer, scope, bs_timeout,
207
659
      &scope->bs_timer);
208
659
}
209
210
static inline void pim_bs_timer_restart(struct bsm_scope *scope, int bs_timeout)
211
658
{
212
658
  pim_bs_timer_start(scope, bs_timeout);
213
658
}
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
57.3k
{
328
57.3k
  if (!bsrp) {
329
0
    if (PIM_DEBUG_BSM)
330
0
      zlog_debug("%s : Invalid brsp(NULL).", __func__);
331
0
    return;
332
0
  }
333
57.3k
  EVENT_OFF(bsrp->g2rp_timer);
334
57.3k
  if (PIM_DEBUG_BSM)
335
0
    zlog_debug(
336
57.3k
      "%s : starting g2rp timer for grp: %pFX - rp: %pPAs with timeout  %d secs(Actual Hold time : %d secs)",
337
57.3k
      __func__, &bsrp->bsgrp_node->group, &bsrp->rp_address,
338
57.3k
      hold_time, bsrp->rp_holdtime);
339
340
57.3k
  event_add_timer(router->master, pim_on_g2rp_timer, bsrp, hold_time,
341
57.3k
      &bsrp->g2rp_timer);
342
57.3k
}
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
39.3k
{
352
39.3k
  if (!bsrp)
353
0
    return;
354
355
39.3k
  if (PIM_DEBUG_BSM)
356
0
    zlog_debug("%s : stopping g2rp timer for grp: %pFX - rp: %pPAs",
357
39.3k
         __func__, &bsrp->bsgrp_node->group,
358
39.3k
         &bsrp->rp_address);
359
360
39.3k
  EVENT_OFF(bsrp->g2rp_timer);
361
39.3k
}
362
363
static bool is_hold_time_zero(void *data)
364
84.3k
{
365
84.3k
  struct bsm_rpinfo *bsrp;
366
367
84.3k
  bsrp = data;
368
369
84.3k
  if (bsrp->rp_holdtime)
370
59.8k
    return false;
371
24.5k
  else
372
24.5k
    return true;
373
84.3k
}
374
375
static void pim_instate_pend_list(struct bsgrp_node *bsgrp_node)
376
80.8k
{
377
80.8k
  struct bsm_rpinfo *active;
378
80.8k
  struct bsm_rpinfo *pend;
379
80.8k
  struct rp_info *rp_info;
380
80.8k
  struct route_node *rn;
381
80.8k
  struct pim_instance *pim;
382
80.8k
  struct rp_info *rp_all;
383
80.8k
  struct prefix group_all;
384
80.8k
  bool had_rp_node = true;
385
386
80.8k
  pim = bsgrp_node->scope->pim;
387
80.8k
  active = bsm_rpinfos_first(bsgrp_node->bsrp_list);
388
389
  /* Remove nodes with hold time 0 & check if list still has a head */
390
84.3k
  frr_each_safe (bsm_rpinfos, bsgrp_node->partial_bsrp_list, pend) {
391
84.3k
    if (is_hold_time_zero(pend)) {
392
24.5k
      bsm_rpinfos_del(bsgrp_node->partial_bsrp_list, pend);
393
24.5k
      pim_bsm_rpinfo_free(pend);
394
24.5k
    }
395
84.3k
  }
396
397
80.8k
  pend = bsm_rpinfos_first(bsgrp_node->partial_bsrp_list);
398
399
80.8k
  if (!pim_get_all_mcast_group(&group_all))
400
0
    return;
401
402
80.8k
  rp_all = pim_rp_find_match_group(pim, &group_all);
403
80.8k
  rn = route_node_lookup(pim->rp_table, &bsgrp_node->group);
404
405
80.8k
  if (pend)
406
57.3k
    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
80.8k
  if (!rn || (prefix_same(&rp_all->group, &bsgrp_node->group) &&
413
35.3k
        pim_rpf_addr_is_inaddr_any(&rp_all->rp))) {
414
31.6k
    if (PIM_DEBUG_BSM)
415
0
      zlog_debug("%s: Route node doesn't exist", __func__);
416
31.6k
    if (pend)
417
20.2k
      pim_rp_new(pim, pend->rp_address, bsgrp_node->group,
418
20.2k
           NULL, RP_SRC_BSR);
419
31.6k
    had_rp_node = false;
420
49.2k
  } else {
421
49.2k
    rp_info = (struct rp_info *)rn->info;
422
49.2k
    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
49.2k
  }
430
431
  /* We didn't have rp node and pending list is empty(unlikely), cleanup*/
432
80.8k
  if ((!had_rp_node) && (!pend)) {
433
11.3k
    pim_free_bsgrp_node(bsgrp_node->scope->bsrp_table,
434
11.3k
            &bsgrp_node->group);
435
11.3k
    pim_free_bsgrp_data(bsgrp_node);
436
11.3k
    return;
437
11.3k
  }
438
439
69.4k
  if ((had_rp_node) && (rp_info->rp_src != RP_SRC_STATIC)) {
440
    /* This means we searched and got rp node, needs unlock */
441
49.2k
    route_unlock_node(rn);
442
443
49.2k
    if (active && pend) {
444
29.3k
      if (pim_addr_cmp(active->rp_address, pend->rp_address))
445
21.3k
        pim_rp_change(pim, pend->rp_address,
446
21.3k
                bsgrp_node->group, RP_SRC_BSR);
447
29.3k
    }
448
449
    /* Possible when the first BSM has group with 0 rp count */
450
49.2k
    if ((!active) && (!pend)) {
451
2.00k
      if (PIM_DEBUG_BSM) {
452
0
        zlog_debug(
453
0
          "%s: Both bsrp and partial list are empty",
454
0
          __func__);
455
0
      }
456
2.00k
      pim_free_bsgrp_node(bsgrp_node->scope->bsrp_table,
457
2.00k
              &bsgrp_node->group);
458
2.00k
      pim_free_bsgrp_data(bsgrp_node);
459
2.00k
      return;
460
2.00k
    }
461
462
    /* Possible when a group with 0 rp count received in BSM */
463
47.2k
    if ((active) && (!pend)) {
464
10.1k
      pim_rp_del(pim, active->rp_address, bsgrp_node->group,
465
10.1k
           NULL, RP_SRC_BSR);
466
10.1k
      pim_free_bsgrp_node(bsgrp_node->scope->bsrp_table,
467
10.1k
              &bsgrp_node->group);
468
10.1k
      if (PIM_DEBUG_BSM) {
469
0
        zlog_debug("%s:Pend List is null,del grp node",
470
0
             __func__);
471
0
      }
472
10.1k
      pim_free_bsgrp_data(bsgrp_node);
473
10.1k
      return;
474
10.1k
    }
475
47.2k
  }
476
477
57.3k
  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
57.3k
  bsm_rpinfos_swap_all(bsgrp_node->bsrp_list,
505
57.3k
           bsgrp_node->partial_bsrp_list);
506
507
57.3k
  if (active)
508
39.3k
    pim_g2rp_timer_stop(active);
509
57.3k
  pim_bsm_rpinfos_free(bsgrp_node->partial_bsrp_list);
510
57.3k
}
511
512
static bool is_preferred_bsr(struct pim_instance *pim, pim_addr bsr,
513
           uint32_t bsr_prio)
514
1.13k
{
515
1.13k
  if (!pim_addr_cmp(bsr, pim->global_scope.current_bsr))
516
1.11k
    return true;
517
518
21
  if (bsr_prio > pim->global_scope.current_bsr_prio)
519
4
    return true;
520
521
17
  else if (bsr_prio == pim->global_scope.current_bsr_prio) {
522
4
    if (pim_addr_cmp(bsr, pim->global_scope.current_bsr) >= 0)
523
0
      return true;
524
4
    else
525
4
      return false;
526
4
  } else
527
13
    return false;
528
21
}
529
530
static void pim_bsm_update(struct pim_instance *pim, pim_addr bsr,
531
         uint32_t bsr_prio)
532
658
{
533
658
  if (pim_addr_cmp(bsr, pim->global_scope.current_bsr)) {
534
3
    pim_nht_bsr_del(pim, pim->global_scope.current_bsr);
535
3
    pim_nht_bsr_add(pim, bsr);
536
537
3
    pim->global_scope.current_bsr = bsr;
538
3
    pim->global_scope.current_bsr_first_ts =
539
3
      pim_time_monotonic_sec();
540
3
    pim->global_scope.state = ACCEPT_PREFERRED;
541
3
  }
542
658
  pim->global_scope.current_bsr_prio = bsr_prio;
543
658
  pim->global_scope.current_bsr_last_ts = pim_time_monotonic_sec();
544
658
}
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
852
{
663
852
  struct pim_interface *pim_ifp;
664
665
852
  pim_ifp = ifp->info;
666
667
852
  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
852
  if (pim_ifp->pim_sock_fd == -1) {
675
852
    if (PIM_DEBUG_BSM)
676
0
      zlog_debug("%s: Pim sock not available for %s",
677
852
           __func__, ifp->name);
678
852
    return false;
679
852
  }
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
658
{
868
658
  struct interface *ifp;
869
658
  struct pim_interface *pim_ifp;
870
658
  pim_addr dst_addr;
871
658
  uint32_t pim_mtu;
872
658
  bool no_fwd = false;
873
658
  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
658
  dst_addr = qpim_all_pim_routers_addr;
879
1.31k
  FOR_ALL_INTERFACES (pim->vrf, ifp) {
880
1.31k
    pim_ifp = ifp->info;
881
1.31k
    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.31k
    if (listcount(pim_ifp->pim_neighbor_list) == 0)
892
658
      continue;
893
894
658
    pim_hello_require(ifp);
895
658
    pim_mtu = ifp->mtu - MAX_IP_HDR_LEN;
896
658
    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
658
    } else {
903
658
      pim_msg_build_header(pim_ifp->primary_address, dst_addr,
904
658
               buf, len, PIM_MSG_TYPE_BOOTSTRAP,
905
658
               no_fwd);
906
658
      if (!pim_bsm_send_intf(buf, len, ifp, dst_addr)) {
907
658
        if (PIM_DEBUG_BSM)
908
0
          zlog_debug(
909
658
            "%s: pim_bsm_send_intf returned false",
910
658
            __func__);
911
658
      }
912
658
    }
913
658
  }
914
658
}
915
916
bool pim_bsm_new_nbr_fwd(struct pim_neighbor *neigh, struct interface *ifp)
917
263
{
918
263
  pim_addr dst_addr;
919
263
  struct pim_interface *pim_ifp;
920
263
  struct bsm_scope *scope;
921
263
  struct bsm_frag *bsfrag;
922
263
  uint32_t pim_mtu;
923
263
  bool no_fwd = true;
924
263
  bool ret = false;
925
926
263
  if (PIM_DEBUG_BSM)
927
0
    zlog_debug("%s: New neighbor %pPA seen on %s", __func__,
928
263
         &neigh->source_addr, ifp->name);
929
930
263
  pim_ifp = ifp->info;
931
932
  /* DR only forwards BSM packet */
933
263
  if (!pim_addr_cmp(pim_ifp->pim_dr_addr, pim_ifp->primary_address)) {
934
1
    if (PIM_DEBUG_BSM)
935
0
      zlog_debug(
936
1
        "%s: It is not DR, so don't forward BSM packet",
937
1
        __func__);
938
1
  }
939
940
263
  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
263
  scope = &pim_ifp->pim->global_scope;
948
949
263
  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
169
  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
169
  } else {
962
169
    dst_addr = neigh->source_addr;
963
169
    if (PIM_DEBUG_BSM)
964
0
      zlog_debug("%s: Sending BSM ucast to %pPA", __func__,
965
169
           &neigh->source_addr);
966
169
  }
967
169
  pim_mtu = ifp->mtu - MAX_IP_HDR_LEN;
968
169
  pim_hello_require(ifp);
969
970
194
  frr_each (bsm_frags, scope->bsm_frags, bsfrag) {
971
194
    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
194
    } else {
981
      /* Pim header needs to be constructed */
982
194
      pim_msg_build_header(pim_ifp->primary_address, dst_addr,
983
194
               bsfrag->data, bsfrag->size,
984
194
               PIM_MSG_TYPE_BOOTSTRAP, no_fwd);
985
194
      ret = pim_bsm_send_intf(bsfrag->data, bsfrag->size, ifp,
986
194
            dst_addr);
987
194
      if (!ret) {
988
194
        if (PIM_DEBUG_BSM)
989
0
          zlog_debug(
990
194
            "%s: pim_bsm_frag_send failed",
991
194
            __func__);
992
194
      }
993
194
    }
994
194
  }
995
169
  return ret;
996
263
}
997
998
struct bsgrp_node *pim_bsm_get_bsgrp_node(struct bsm_scope *scope,
999
            struct prefix *grp)
1000
218k
{
1001
218k
  struct route_node *rn;
1002
218k
  struct bsgrp_node *bsgrp;
1003
1004
218k
  rn = route_node_lookup(scope->bsrp_table, grp);
1005
218k
  if (!rn) {
1006
33.1k
    if (PIM_DEBUG_BSM)
1007
0
      zlog_debug("%s: Route node doesn't exist for the group",
1008
33.1k
           __func__);
1009
33.1k
    return NULL;
1010
33.1k
  }
1011
185k
  bsgrp = rn->info;
1012
185k
  route_unlock_node(rn);
1013
1014
185k
  return bsgrp;
1015
218k
}
1016
1017
static uint32_t hash_calc_on_grp_rp(struct prefix group, pim_addr rp,
1018
            uint8_t hashmasklen)
1019
364k
{
1020
364k
  uint64_t temp;
1021
364k
  uint32_t hash;
1022
364k
  uint32_t grpaddr;
1023
364k
  uint32_t rp_add;
1024
364k
  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
364k
  if (hashmasklen == 0)
1030
340k
    mask = 0;
1031
1032
  /* in_addr stores ip in big endian, hence network byte order
1033
   * convert to uint32 before processing hash
1034
   */
1035
364k
#if PIM_IPV == 4
1036
364k
  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
364k
  if (hashmasklen)
1043
23.6k
    grpaddr = grpaddr & ((mask << (32 - hashmasklen)));
1044
340k
  else
1045
340k
    grpaddr = grpaddr & mask;
1046
1047
364k
#if PIM_IPV == 4
1048
364k
  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
364k
  temp = 1103515245 * ((1103515245 * (uint64_t)grpaddr + 12345) ^ rp_add)
1054
364k
         + 12345;
1055
364k
  hash = temp & (0x7fffffff);
1056
364k
  return hash;
1057
364k
}
1058
1059
static bool pim_install_bsm_grp_rp(struct pim_instance *pim,
1060
           struct bsgrp_node *grpnode,
1061
           struct bsmmsg_rpinfo *rp)
1062
364k
{
1063
364k
  struct bsm_rpinfo *bsm_rpinfo;
1064
364k
  uint8_t hashMask_len = pim->global_scope.hashMasklen;
1065
1066
  /*memory allocation for bsm_rpinfo */
1067
364k
  bsm_rpinfo = XCALLOC(MTYPE_PIM_BSRP_INFO, sizeof(*bsm_rpinfo));
1068
1069
364k
  bsm_rpinfo->rp_prio = rp->rp_pri;
1070
364k
  bsm_rpinfo->rp_holdtime = rp->rp_holdtime;
1071
364k
  bsm_rpinfo->rp_address = rp->rpaddr.addr;
1072
364k
  bsm_rpinfo->elapse_time = 0;
1073
1074
  /* Back pointer to the group node. */
1075
364k
  bsm_rpinfo->bsgrp_node = grpnode;
1076
1077
  /* update hash for this rp node */
1078
364k
  bsm_rpinfo->hash = hash_calc_on_grp_rp(grpnode->group, rp->rpaddr.addr,
1079
364k
                 hashMask_len);
1080
364k
  if (bsm_rpinfos_add(grpnode->partial_bsrp_list, bsm_rpinfo) == NULL) {
1081
159k
    if (PIM_DEBUG_BSM)
1082
0
      zlog_debug(
1083
159k
        "%s, bs_rpinfo node added to the partial bs_rplist.",
1084
159k
        __func__);
1085
159k
    return true;
1086
159k
  }
1087
1088
204k
  if (PIM_DEBUG_BSM)
1089
0
    zlog_debug("%s: list node not added", __func__);
1090
1091
204k
  XFREE(MTYPE_PIM_BSRP_INFO, bsm_rpinfo);
1092
204k
  return false;
1093
364k
}
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
209k
{
1100
209k
  if (bsgrp->pend_rp_cnt) {
1101
    /* received bsm is different packet ,
1102
     * it is not same fragment.
1103
     */
1104
126k
    if (bsm_frag_tag != bsgrp->frag_tag) {
1105
280
      if (PIM_DEBUG_BSM)
1106
0
        zlog_debug(
1107
280
          "%s,Received a new BSM ,so clear the pending bs_rpinfo list.",
1108
280
          __func__);
1109
280
      pim_bsm_rpinfos_free(bsgrp->partial_bsrp_list);
1110
280
      bsgrp->pend_rp_cnt = total_rp_count;
1111
280
    }
1112
126k
  } else
1113
83.3k
    bsgrp->pend_rp_cnt = total_rp_count;
1114
1115
209k
  bsgrp->frag_tag = bsm_frag_tag;
1116
209k
}
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.07k
{
1122
1.07k
  struct bsmmsg_grpinfo grpinfo;
1123
1.07k
  struct bsmmsg_rpinfo rpinfo;
1124
1.07k
  struct prefix group;
1125
1.07k
  struct bsgrp_node *bsgrp = NULL;
1126
1.07k
  int frag_rp_cnt = 0;
1127
1.07k
  int offset = 0;
1128
1.07k
  int ins_count = 0;
1129
1.07k
  pim_addr grp_addr;
1130
1131
219k
  while (buflen > offset) {
1132
218k
    if (offset + (int)sizeof(struct bsmmsg_grpinfo) > buflen) {
1133
125
      if (PIM_DEBUG_BSM)
1134
0
        zlog_debug(
1135
125
          "%s: buflen received %d is less than the internal data structure of the packet would suggest",
1136
125
          __func__, buflen);
1137
125
      return false;
1138
125
    }
1139
    /* Extract Group tlv from BSM */
1140
218k
    memcpy(&grpinfo, buf, sizeof(struct bsmmsg_grpinfo));
1141
218k
    grp_addr = grpinfo.group.addr;
1142
1143
218k
    if (PIM_DEBUG_BSM)
1144
0
      zlog_debug(
1145
218k
        "%s, Group %pPAs  Rpcount:%d Fragment-Rp-count:%d",
1146
218k
        __func__, &grp_addr, grpinfo.rp_count,
1147
218k
        grpinfo.frag_rp_count);
1148
1149
218k
    buf += sizeof(struct bsmmsg_grpinfo);
1150
218k
    offset += sizeof(struct bsmmsg_grpinfo);
1151
1152
218k
    group.family = PIM_AF;
1153
218k
    if (grpinfo.group.mask > PIM_MAX_BITLEN) {
1154
121
      if (PIM_DEBUG_BSM)
1155
0
        zlog_debug(
1156
121
          "%s, prefix length specified: %d is too long",
1157
121
          __func__, grpinfo.group.mask);
1158
121
      return false;
1159
121
    }
1160
1161
218k
    pim_addr_to_prefix(&group, grp_addr);
1162
218k
    group.prefixlen = grpinfo.group.mask;
1163
1164
    /* Get the Group node for the BSM rp table */
1165
218k
    bsgrp = pim_bsm_get_bsgrp_node(scope, &group);
1166
1167
218k
    if (grpinfo.rp_count == 0) {
1168
9.24k
      struct bsm_rpinfo *old_rpinfo;
1169
1170
      /* BSR explicitly no longer has RPs for this group */
1171
9.24k
      if (!bsgrp)
1172
2.80k
        continue;
1173
1174
6.44k
      if (PIM_DEBUG_BSM)
1175
0
        zlog_debug(
1176
6.44k
          "%s, Rp count is zero for group: %pPAs",
1177
6.44k
          __func__, &grp_addr);
1178
1179
6.44k
      old_rpinfo = bsm_rpinfos_first(bsgrp->bsrp_list);
1180
6.44k
      if (old_rpinfo)
1181
4.77k
        pim_rp_del(scope->pim, old_rpinfo->rp_address,
1182
4.77k
             group, NULL, RP_SRC_BSR);
1183
1184
6.44k
      pim_free_bsgrp_node(scope->bsrp_table, &bsgrp->group);
1185
6.44k
      pim_free_bsgrp_data(bsgrp);
1186
6.44k
      continue;
1187
9.24k
    }
1188
1189
209k
    if (!bsgrp) {
1190
30.3k
      if (PIM_DEBUG_BSM)
1191
0
        zlog_debug("%s, Create new  BSM Group node.",
1192
30.3k
             __func__);
1193
1194
      /* create a new node to be added to the tree. */
1195
30.3k
      bsgrp = pim_bsm_new_bsgrp_node(scope->bsrp_table,
1196
30.3k
                   &group);
1197
1198
30.3k
      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
30.3k
      bsgrp->scope = scope;
1206
30.3k
    }
1207
1208
209k
    pim_update_pending_rp_cnt(scope, bsgrp, bsm_frag_tag,
1209
209k
            grpinfo.rp_count);
1210
209k
    frag_rp_cnt = grpinfo.frag_rp_count;
1211
209k
    ins_count = 0;
1212
1213
573k
    while (frag_rp_cnt--) {
1214
364k
      if (offset + (int)sizeof(struct bsmmsg_rpinfo)
1215
364k
          > buflen) {
1216
166
        if (PIM_DEBUG_BSM)
1217
0
          zlog_debug(
1218
166
            "%s, buflen received: %u is less than the internal data structure of the packet would suggest",
1219
166
            __func__, buflen);
1220
166
        return false;
1221
166
      }
1222
1223
      /* Extract RP address tlv from BSM */
1224
364k
      memcpy(&rpinfo, buf, sizeof(struct bsmmsg_rpinfo));
1225
364k
      rpinfo.rp_holdtime = ntohs(rpinfo.rp_holdtime);
1226
364k
      buf += sizeof(struct bsmmsg_rpinfo);
1227
364k
      offset += sizeof(struct bsmmsg_rpinfo);
1228
1229
364k
      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
364k
      if (pim_install_bsm_grp_rp(scope->pim, bsgrp, &rpinfo))
1241
159k
        ins_count++;
1242
364k
    }
1243
1244
209k
    bsgrp->pend_rp_cnt -= ins_count;
1245
1246
209k
    if (!bsgrp->pend_rp_cnt) {
1247
80.8k
      if (PIM_DEBUG_BSM)
1248
0
        zlog_debug(
1249
80.8k
          "%s, Recvd all the rps for this group, so bsrp list with penidng rp list.",
1250
80.8k
          __func__);
1251
      /* replace the bsrp_list with pending list */
1252
80.8k
      pim_instate_pend_list(bsgrp);
1253
80.8k
    }
1254
209k
  }
1255
658
  return true;
1256
1.07k
}
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.14k
{
1261
1.14k
  struct bsm_hdr *bshdr;
1262
1.14k
  int sz = PIM_GBL_SZ_ID;
1263
1.14k
  struct bsmmsg_grpinfo *msg_grp;
1264
1.14k
  struct pim_interface *pim_ifp = NULL;
1265
1.14k
  struct bsm_frag *bsfrag;
1266
1.14k
  struct pim_instance *pim;
1267
1.14k
  uint16_t frag_tag;
1268
1.14k
  pim_addr bsr_addr;
1269
1.14k
  bool empty_bsm = false;
1270
1271
  /* BSM Packet acceptance validation */
1272
1.14k
  pim_ifp = ifp->info;
1273
1.14k
  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.14k
  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.14k
  pim_ifp->pim_ifstat_bsm_rx++;
1289
1.14k
  pim = pim_ifp->pim;
1290
1.14k
  pim->bsm_rcvd++;
1291
1292
  /* Drop if bsm processing is disabled on interface */
1293
1.14k
  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.14k
  if (buf_size < (PIM_MSG_HEADER_LEN + sizeof(struct bsm_hdr))) {
1302
8
    if (PIM_DEBUG_BSM)
1303
0
      zlog_debug(
1304
8
        "%s: received buffer length of %d which is too small to properly decode",
1305
8
        __func__, buf_size);
1306
8
    return -1;
1307
8
  }
1308
1309
1.13k
  bshdr = (struct bsm_hdr *)(buf + PIM_MSG_HEADER_LEN);
1310
1.13k
  if (bshdr->hm_len > PIM_MAX_BITLEN) {
1311
5
    zlog_warn(
1312
5
      "Bad hashmask length for %s; got %hhu, expected value in range 0-32",
1313
5
      PIM_AF_NAME, bshdr->hm_len);
1314
5
    pim->bsm_dropped++;
1315
5
    return -1;
1316
5
  }
1317
1.13k
  pim->global_scope.hashMasklen = bshdr->hm_len;
1318
1.13k
  frag_tag = ntohs(bshdr->frag_tag);
1319
  /* NB: bshdr->bsr_addr.addr is packed/unaligned => memcpy */
1320
1.13k
  memcpy(&bsr_addr, &bshdr->bsr_addr.addr, sizeof(bsr_addr));
1321
1322
  /* Identify empty BSM */
1323
1.13k
  if ((buf_size - PIM_BSM_HDR_LEN - PIM_MSG_HEADER_LEN) < PIM_BSM_GRP_LEN)
1324
66
    empty_bsm = true;
1325
1326
1.13k
  if (!empty_bsm) {
1327
1.06k
    msg_grp = (struct bsmmsg_grpinfo *)(buf + PIM_MSG_HEADER_LEN
1328
1.06k
                + PIM_BSM_HDR_LEN);
1329
    /* Currently we don't support scope zoned BSM */
1330
1.06k
    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.06k
  }
1340
1341
  /* Drop if bsr is not preferred bsr */
1342
1.13k
  if (!is_preferred_bsr(pim, bsr_addr, bshdr->bsr_prio)) {
1343
17
    if (PIM_DEBUG_BSM)
1344
0
      zlog_debug("%s : Received a non-preferred BSM",
1345
17
           __func__);
1346
17
    pim->bsm_dropped++;
1347
17
    return -1;
1348
17
  }
1349
1350
1.11k
  if (no_fwd) {
1351
    /* only accept no-forward BSM if quick refresh on startup */
1352
13
    if ((pim->global_scope.accept_nofwd_bsm)
1353
13
        || (frag_tag == pim->global_scope.bsm_frag_tag)) {
1354
0
      pim->global_scope.accept_nofwd_bsm = false;
1355
13
    } else {
1356
13
      if (PIM_DEBUG_BSM)
1357
0
        zlog_debug(
1358
13
          "%s : nofwd_bsm received on %pPAs when accpt_nofwd_bsm false",
1359
13
          __func__, &bsr_addr);
1360
13
      pim->bsm_dropped++;
1361
13
      pim_ifp->pim_ifstat_ucast_bsm_cfg_miss++;
1362
13
      return -1;
1363
13
    }
1364
13
  }
1365
1366
  /* BSM packet is seen, so resetting accept_nofwd_bsm to false */
1367
1.10k
  if (pim->global_scope.accept_nofwd_bsm)
1368
1
    pim->global_scope.accept_nofwd_bsm = false;
1369
1370
1.10k
  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.10k
  } 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.07k
    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.07k
  } else {
1399
30
    if (PIM_DEBUG_BSM)
1400
0
      zlog_debug("%s : Invalid destination address",
1401
30
           __func__);
1402
30
    pim->bsm_dropped++;
1403
30
    return -1;
1404
30
  }
1405
1406
1.07k
  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.07k
  if (!pim_bsm_parse_install_g2rp(
1412
1.07k
        &pim_ifp->pim->global_scope,
1413
1.07k
        (buf + PIM_BSM_HDR_LEN + PIM_MSG_HEADER_LEN),
1414
1.07k
        (buf_size - PIM_BSM_HDR_LEN - PIM_MSG_HEADER_LEN),
1415
1.07k
        frag_tag)) {
1416
412
    if (PIM_DEBUG_BSM) {
1417
0
      zlog_debug("%s, Parsing BSM failed.", __func__);
1418
0
    }
1419
412
    pim->bsm_dropped++;
1420
412
    return -1;
1421
412
  }
1422
  /* Restart the bootstrap timer */
1423
658
  pim_bs_timer_restart(&pim_ifp->pim->global_scope,
1424
658
           PIM_BSR_DEFAULT_TIMEOUT);
1425
1426
  /* If new BSM received, clear the old bsm database */
1427
658
  if (pim_ifp->pim->global_scope.bsm_frag_tag != frag_tag) {
1428
546
    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
546
    pim_bsm_frags_free(&pim_ifp->pim->global_scope);
1435
546
    pim_ifp->pim->global_scope.bsm_frag_tag = frag_tag;
1436
546
  }
1437
1438
  /* update the scope information from bsm */
1439
658
  pim_bsm_update(pim, bsr_addr, bshdr->bsr_prio);
1440
1441
658
  if (!no_fwd) {
1442
658
    pim_bsm_fwd_whole_sz(pim_ifp->pim, buf, buf_size, sz);
1443
658
    bsfrag = XCALLOC(MTYPE_PIM_BSM_FRAG,
1444
658
         sizeof(struct bsm_frag) + buf_size);
1445
1446
658
    bsfrag->size = buf_size;
1447
658
    memcpy(bsfrag->data, buf, buf_size);
1448
658
    bsm_frags_add_tail(pim_ifp->pim->global_scope.bsm_frags,
1449
658
           bsfrag);
1450
658
  }
1451
1452
658
  return 0;
1453
1.07k
}