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