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