]> git.proxmox.com Git - mirror_frr.git/blob - pimd/pim_rp.c
ospf6d : Transformation changes for ospf6 vrf support.
[mirror_frr.git] / pimd / pim_rp.c
1 /*
2 * PIM for Quagga
3 * Copyright (C) 2015 Cumulus Networks, Inc.
4 * Donald Sharp
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20 #include <zebra.h>
21
22 #include "lib/json.h"
23 #include "log.h"
24 #include "network.h"
25 #include "if.h"
26 #include "linklist.h"
27 #include "prefix.h"
28 #include "memory.h"
29 #include "vty.h"
30 #include "vrf.h"
31 #include "plist.h"
32 #include "nexthop.h"
33 #include "table.h"
34 #include "lib_errors.h"
35
36 #include "pimd.h"
37 #include "pim_vty.h"
38 #include "pim_str.h"
39 #include "pim_iface.h"
40 #include "pim_rp.h"
41 #include "pim_str.h"
42 #include "pim_rpf.h"
43 #include "pim_sock.h"
44 #include "pim_memory.h"
45 #include "pim_iface.h"
46 #include "pim_msdp.h"
47 #include "pim_nht.h"
48 #include "pim_mroute.h"
49 #include "pim_oil.h"
50 #include "pim_zebra.h"
51 #include "pim_bsm.h"
52
53 /* Cleanup pim->rpf_hash each node data */
54 void pim_rp_list_hash_clean(void *data)
55 {
56 struct pim_nexthop_cache *pnc = (struct pim_nexthop_cache *)data;
57
58 list_delete(&pnc->rp_list);
59
60 hash_clean(pnc->upstream_hash, NULL);
61 hash_free(pnc->upstream_hash);
62 pnc->upstream_hash = NULL;
63 if (pnc->nexthop)
64 nexthops_free(pnc->nexthop);
65
66 XFREE(MTYPE_PIM_NEXTHOP_CACHE, pnc);
67 }
68
69 static void pim_rp_info_free(struct rp_info *rp_info)
70 {
71 XFREE(MTYPE_PIM_FILTER_NAME, rp_info->plist);
72
73 XFREE(MTYPE_PIM_RP, rp_info);
74 }
75
76 int pim_rp_list_cmp(void *v1, void *v2)
77 {
78 struct rp_info *rp1 = (struct rp_info *)v1;
79 struct rp_info *rp2 = (struct rp_info *)v2;
80
81 /*
82 * Sort by RP IP address
83 */
84 if (rp1->rp.rpf_addr.u.prefix4.s_addr
85 < rp2->rp.rpf_addr.u.prefix4.s_addr)
86 return -1;
87
88 if (rp1->rp.rpf_addr.u.prefix4.s_addr
89 > rp2->rp.rpf_addr.u.prefix4.s_addr)
90 return 1;
91
92 /*
93 * Sort by group IP address
94 */
95 if (rp1->group.u.prefix4.s_addr < rp2->group.u.prefix4.s_addr)
96 return -1;
97
98 if (rp1->group.u.prefix4.s_addr > rp2->group.u.prefix4.s_addr)
99 return 1;
100
101 return 0;
102 }
103
104 void pim_rp_init(struct pim_instance *pim)
105 {
106 struct rp_info *rp_info;
107 struct route_node *rn;
108
109 pim->rp_list = list_new();
110 pim->rp_list->del = (void (*)(void *))pim_rp_info_free;
111 pim->rp_list->cmp = pim_rp_list_cmp;
112
113 pim->rp_table = route_table_init();
114
115 rp_info = XCALLOC(MTYPE_PIM_RP, sizeof(*rp_info));
116
117 if (!str2prefix("224.0.0.0/4", &rp_info->group)) {
118 flog_err(EC_LIB_DEVELOPMENT,
119 "Unable to convert 224.0.0.0/4 to prefix");
120 list_delete(&pim->rp_list);
121 route_table_finish(pim->rp_table);
122 XFREE(MTYPE_PIM_RP, rp_info);
123 return;
124 }
125 rp_info->group.family = AF_INET;
126 rp_info->rp.rpf_addr.family = AF_INET;
127 rp_info->rp.rpf_addr.prefixlen = IPV4_MAX_PREFIXLEN;
128 rp_info->rp.rpf_addr.u.prefix4.s_addr = INADDR_NONE;
129
130 listnode_add(pim->rp_list, rp_info);
131
132 rn = route_node_get(pim->rp_table, &rp_info->group);
133 rn->info = rp_info;
134 if (PIM_DEBUG_PIM_TRACE)
135 zlog_debug(
136 "Allocated: %p for rp_info: %p(224.0.0.0/4) Lock: %d",
137 rn, rp_info, rn->lock);
138 }
139
140 void pim_rp_free(struct pim_instance *pim)
141 {
142 if (pim->rp_list)
143 list_delete(&pim->rp_list);
144 if (pim->rp_table)
145 route_table_finish(pim->rp_table);
146 pim->rp_table = NULL;
147 }
148
149 /*
150 * Given an RP's prefix-list, return the RP's rp_info for that prefix-list
151 */
152 static struct rp_info *pim_rp_find_prefix_list(struct pim_instance *pim,
153 struct in_addr rp,
154 const char *plist)
155 {
156 struct listnode *node;
157 struct rp_info *rp_info;
158
159 for (ALL_LIST_ELEMENTS_RO(pim->rp_list, node, rp_info)) {
160 if (rp.s_addr == rp_info->rp.rpf_addr.u.prefix4.s_addr
161 && rp_info->plist && strcmp(rp_info->plist, plist) == 0) {
162 return rp_info;
163 }
164 }
165
166 return NULL;
167 }
168
169 /*
170 * Return true if plist is used by any rp_info
171 */
172 static int pim_rp_prefix_list_used(struct pim_instance *pim, const char *plist)
173 {
174 struct listnode *node;
175 struct rp_info *rp_info;
176
177 for (ALL_LIST_ELEMENTS_RO(pim->rp_list, node, rp_info)) {
178 if (rp_info->plist && strcmp(rp_info->plist, plist) == 0) {
179 return 1;
180 }
181 }
182
183 return 0;
184 }
185
186 /*
187 * Given an RP's address, return the RP's rp_info that is an exact match for
188 * 'group'
189 */
190 static struct rp_info *pim_rp_find_exact(struct pim_instance *pim,
191 struct in_addr rp,
192 const struct prefix *group)
193 {
194 struct listnode *node;
195 struct rp_info *rp_info;
196
197 for (ALL_LIST_ELEMENTS_RO(pim->rp_list, node, rp_info)) {
198 if (rp.s_addr == rp_info->rp.rpf_addr.u.prefix4.s_addr
199 && prefix_same(&rp_info->group, group))
200 return rp_info;
201 }
202
203 return NULL;
204 }
205
206 /*
207 * Given a group, return the rp_info for that group
208 */
209 struct rp_info *pim_rp_find_match_group(struct pim_instance *pim,
210 const struct prefix *group)
211 {
212 struct listnode *node;
213 struct rp_info *best = NULL;
214 struct rp_info *rp_info;
215 struct prefix_list *plist;
216 const struct prefix *p, *bp;
217 struct route_node *rn;
218
219 bp = NULL;
220 for (ALL_LIST_ELEMENTS_RO(pim->rp_list, node, rp_info)) {
221 if (rp_info->plist) {
222 plist = prefix_list_lookup(AFI_IP, rp_info->plist);
223
224 if (prefix_list_apply_which_prefix(plist, &p, group)
225 == PREFIX_DENY)
226 continue;
227
228 if (!best) {
229 best = rp_info;
230 bp = p;
231 continue;
232 }
233
234 if (bp && bp->prefixlen < p->prefixlen) {
235 best = rp_info;
236 bp = p;
237 }
238 }
239 }
240
241 rn = route_node_match(pim->rp_table, group);
242 if (!rn) {
243 flog_err(
244 EC_LIB_DEVELOPMENT,
245 "%s: BUG We should have found default group information\n",
246 __func__);
247 return best;
248 }
249
250 rp_info = rn->info;
251 if (PIM_DEBUG_PIM_TRACE) {
252 char buf[PREFIX_STRLEN];
253
254 zlog_debug("Lookedup: %p for rp_info: %p(%s) Lock: %d", rn,
255 rp_info,
256 prefix2str(&rp_info->group, buf, sizeof(buf)),
257 rn->lock);
258 }
259
260 route_unlock_node(rn);
261
262 if (!best)
263 return rp_info;
264
265 if (rp_info->group.prefixlen < best->group.prefixlen)
266 best = rp_info;
267
268 return best;
269 }
270
271 /*
272 * When the user makes "ip pim rp" configuration changes or if they change the
273 * prefix-list(s) used by these statements we must tickle the upstream state
274 * for each group to make them re-lookup who their RP should be.
275 *
276 * This is a placeholder function for now.
277 */
278 static void pim_rp_refresh_group_to_rp_mapping(struct pim_instance *pim)
279 {
280 pim_msdp_i_am_rp_changed(pim);
281 pim_upstream_reeval_use_rpt(pim);
282 }
283
284 void pim_rp_prefix_list_update(struct pim_instance *pim,
285 struct prefix_list *plist)
286 {
287 struct listnode *node;
288 struct rp_info *rp_info;
289 int refresh_needed = 0;
290
291 for (ALL_LIST_ELEMENTS_RO(pim->rp_list, node, rp_info)) {
292 if (rp_info->plist
293 && strcmp(rp_info->plist, prefix_list_name(plist)) == 0) {
294 refresh_needed = 1;
295 break;
296 }
297 }
298
299 if (refresh_needed)
300 pim_rp_refresh_group_to_rp_mapping(pim);
301 }
302
303 static int pim_rp_check_interface_addrs(struct rp_info *rp_info,
304 struct pim_interface *pim_ifp)
305 {
306 struct listnode *node;
307 struct pim_secondary_addr *sec_addr;
308
309 if (pim_ifp->primary_address.s_addr
310 == rp_info->rp.rpf_addr.u.prefix4.s_addr)
311 return 1;
312
313 if (!pim_ifp->sec_addr_list) {
314 return 0;
315 }
316
317 for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, node, sec_addr)) {
318 if (prefix_same(&sec_addr->addr, &rp_info->rp.rpf_addr)) {
319 return 1;
320 }
321 }
322
323 return 0;
324 }
325
326 static void pim_rp_check_interfaces(struct pim_instance *pim,
327 struct rp_info *rp_info)
328 {
329 struct interface *ifp;
330
331 rp_info->i_am_rp = 0;
332 FOR_ALL_INTERFACES (pim->vrf, ifp) {
333 struct pim_interface *pim_ifp = ifp->info;
334
335 if (!pim_ifp)
336 continue;
337
338 if (pim_rp_check_interface_addrs(rp_info, pim_ifp)) {
339 rp_info->i_am_rp = 1;
340 }
341 }
342 }
343
344 void pim_upstream_update(struct pim_instance *pim, struct pim_upstream *up)
345 {
346 struct pim_rpf old_rpf;
347 enum pim_rpf_result rpf_result;
348 struct in_addr old_upstream_addr;
349 struct in_addr new_upstream_addr;
350 struct prefix nht_p;
351
352 old_upstream_addr = up->upstream_addr;
353 pim_rp_set_upstream_addr(pim, &new_upstream_addr, up->sg.src,
354 up->sg.grp);
355
356 if (PIM_DEBUG_PIM_TRACE)
357 zlog_debug("%s: pim upstream update for old upstream %s",
358 __func__, inet_ntoa(old_upstream_addr));
359
360 if (old_upstream_addr.s_addr == new_upstream_addr.s_addr)
361 return;
362
363 /* Lets consider a case, where a PIM upstream has a better RP as a
364 * result of a new RP configuration with more precise group range.
365 * This upstream has to be added to the upstream hash of new RP's
366 * NHT(pnc) and has to be removed from old RP's NHT upstream hash
367 */
368 if (old_upstream_addr.s_addr != INADDR_ANY) {
369 /* Deregister addr with Zebra NHT */
370 nht_p.family = AF_INET;
371 nht_p.prefixlen = IPV4_MAX_BITLEN;
372 nht_p.u.prefix4 = old_upstream_addr;
373 if (PIM_DEBUG_PIM_TRACE) {
374 char buf[PREFIX2STR_BUFFER];
375
376 prefix2str(&nht_p, buf, sizeof(buf));
377 zlog_debug(
378 "%s: Deregister upstream %s addr %s with Zebra NHT",
379 __func__, up->sg_str, buf);
380 }
381 pim_delete_tracked_nexthop(pim, &nht_p, up, NULL, false);
382 }
383
384 /* Update the upstream address */
385 up->upstream_addr = new_upstream_addr;
386
387 old_rpf.source_nexthop.interface = up->rpf.source_nexthop.interface;
388
389 rpf_result = pim_rpf_update(pim, up, &old_rpf, __func__);
390 if (rpf_result == PIM_RPF_FAILURE)
391 pim_mroute_del(up->channel_oil, __func__);
392
393 /* update kernel multicast forwarding cache (MFC) */
394 if (up->rpf.source_nexthop.interface && up->channel_oil)
395 pim_upstream_mroute_iif_update(up->channel_oil, __func__);
396
397 if (rpf_result == PIM_RPF_CHANGED ||
398 (rpf_result == PIM_RPF_FAILURE &&
399 old_rpf.source_nexthop.interface))
400 pim_zebra_upstream_rpf_changed(pim, up, &old_rpf);
401
402 pim_zebra_update_all_interfaces(pim);
403 }
404
405 int pim_rp_new_config(struct pim_instance *pim, const char *rp,
406 const char *group_range, const char *plist)
407 {
408 int result = 0;
409 struct prefix group;
410 struct in_addr rp_addr;
411
412 if (group_range == NULL)
413 result = str2prefix("224.0.0.0/4", &group);
414 else {
415 result = str2prefix(group_range, &group);
416 if (result) {
417 struct prefix temp;
418
419 prefix_copy(&temp, &group);
420 apply_mask(&temp);
421 if (!prefix_same(&group, &temp))
422 return PIM_GROUP_BAD_ADDR_MASK_COMBO;
423 }
424 }
425
426 if (!result)
427 return PIM_GROUP_BAD_ADDRESS;
428
429 result = inet_pton(AF_INET, rp, &rp_addr);
430
431 if (result <= 0)
432 return PIM_RP_BAD_ADDRESS;
433
434 result = pim_rp_new(pim, rp_addr, group, plist, RP_SRC_STATIC);
435 return result;
436 }
437
438 int pim_rp_new(struct pim_instance *pim, struct in_addr rp_addr,
439 struct prefix group, const char *plist,
440 enum rp_source rp_src_flag)
441 {
442 int result = 0;
443 char rp[INET_ADDRSTRLEN];
444 struct rp_info *rp_info;
445 struct rp_info *rp_all;
446 struct prefix group_all;
447 struct listnode *node, *nnode;
448 struct rp_info *tmp_rp_info;
449 char buffer[BUFSIZ];
450 struct prefix nht_p;
451 struct route_node *rn;
452 struct pim_upstream *up;
453
454 if (rp_addr.s_addr == INADDR_ANY ||
455 rp_addr.s_addr == INADDR_NONE)
456 return PIM_RP_BAD_ADDRESS;
457
458 rp_info = XCALLOC(MTYPE_PIM_RP, sizeof(*rp_info));
459
460 rp_info->rp.rpf_addr.family = AF_INET;
461 rp_info->rp.rpf_addr.prefixlen = IPV4_MAX_PREFIXLEN;
462 rp_info->rp.rpf_addr.u.prefix4 = rp_addr;
463 prefix_copy(&rp_info->group, &group);
464 rp_info->rp_src = rp_src_flag;
465
466 inet_ntop(AF_INET, &rp_info->rp.rpf_addr.u.prefix4, rp, sizeof(rp));
467
468 if (plist) {
469 /*
470 * Return if the prefix-list is already configured for this RP
471 */
472 if (pim_rp_find_prefix_list(pim, rp_info->rp.rpf_addr.u.prefix4,
473 plist)) {
474 XFREE(MTYPE_PIM_RP, rp_info);
475 return PIM_SUCCESS;
476 }
477
478 /*
479 * Barf if the prefix-list is already configured for an RP
480 */
481 if (pim_rp_prefix_list_used(pim, plist)) {
482 XFREE(MTYPE_PIM_RP, rp_info);
483 return PIM_RP_PFXLIST_IN_USE;
484 }
485
486 /*
487 * Free any existing rp_info entries for this RP
488 */
489 for (ALL_LIST_ELEMENTS(pim->rp_list, node, nnode,
490 tmp_rp_info)) {
491 if (rp_info->rp.rpf_addr.u.prefix4.s_addr
492 == tmp_rp_info->rp.rpf_addr.u.prefix4.s_addr) {
493 if (tmp_rp_info->plist)
494 pim_rp_del_config(pim, rp, NULL,
495 tmp_rp_info->plist);
496 else
497 pim_rp_del_config(
498 pim, rp,
499 prefix2str(&tmp_rp_info->group,
500 buffer, BUFSIZ),
501 NULL);
502 }
503 }
504
505 rp_info->plist = XSTRDUP(MTYPE_PIM_FILTER_NAME, plist);
506 } else {
507
508 if (!str2prefix("224.0.0.0/4", &group_all)) {
509 XFREE(MTYPE_PIM_RP, rp_info);
510 return PIM_GROUP_BAD_ADDRESS;
511 }
512 rp_all = pim_rp_find_match_group(pim, &group_all);
513
514 /*
515 * Barf if group is a non-multicast subnet
516 */
517 if (!prefix_match(&rp_all->group, &rp_info->group)) {
518 XFREE(MTYPE_PIM_RP, rp_info);
519 return PIM_GROUP_BAD_ADDRESS;
520 }
521
522 /*
523 * Remove any prefix-list rp_info entries for this RP
524 */
525 for (ALL_LIST_ELEMENTS(pim->rp_list, node, nnode,
526 tmp_rp_info)) {
527 if (tmp_rp_info->plist
528 && rp_info->rp.rpf_addr.u.prefix4.s_addr
529 == tmp_rp_info->rp.rpf_addr.u.prefix4
530 .s_addr) {
531 pim_rp_del_config(pim, rp, NULL,
532 tmp_rp_info->plist);
533 }
534 }
535
536 /*
537 * Take over the 224.0.0.0/4 group if the rp is INADDR_NONE
538 */
539 if (prefix_same(&rp_all->group, &rp_info->group)
540 && pim_rpf_addr_is_inaddr_none(&rp_all->rp)) {
541 rp_all->rp.rpf_addr = rp_info->rp.rpf_addr;
542 rp_all->rp_src = rp_src_flag;
543 XFREE(MTYPE_PIM_RP, rp_info);
544
545 /* Register addr with Zebra NHT */
546 nht_p.family = AF_INET;
547 nht_p.prefixlen = IPV4_MAX_BITLEN;
548 nht_p.u.prefix4 =
549 rp_all->rp.rpf_addr.u.prefix4; // RP address
550 if (PIM_DEBUG_PIM_NHT_RP) {
551 char buf[PREFIX2STR_BUFFER];
552 char buf1[PREFIX2STR_BUFFER];
553 prefix2str(&nht_p, buf, sizeof(buf));
554 prefix2str(&rp_all->group, buf1, sizeof(buf1));
555 zlog_debug(
556 "%s: NHT Register rp_all addr %s grp %s ",
557 __func__, buf, buf1);
558 }
559
560 frr_each (rb_pim_upstream, &pim->upstream_head, up) {
561 /* Find (*, G) upstream whose RP is not
562 * configured yet
563 */
564 if ((up->upstream_addr.s_addr == INADDR_ANY)
565 && (up->sg.src.s_addr == INADDR_ANY)) {
566 struct prefix grp;
567 struct rp_info *trp_info;
568
569 grp.family = AF_INET;
570 grp.prefixlen = IPV4_MAX_BITLEN;
571 grp.u.prefix4 = up->sg.grp;
572 trp_info = pim_rp_find_match_group(
573 pim, &grp);
574 if (trp_info == rp_all)
575 pim_upstream_update(pim, up);
576 }
577 }
578
579 pim_rp_check_interfaces(pim, rp_all);
580 pim_rp_refresh_group_to_rp_mapping(pim);
581 pim_find_or_track_nexthop(pim, &nht_p, NULL, rp_all,
582 false, NULL);
583
584 if (!pim_ecmp_nexthop_lookup(pim,
585 &rp_all->rp.source_nexthop,
586 &nht_p, &rp_all->group, 1))
587 return PIM_RP_NO_PATH;
588 return PIM_SUCCESS;
589 }
590
591 /*
592 * Return if the group is already configured for this RP
593 */
594 tmp_rp_info = pim_rp_find_exact(
595 pim, rp_info->rp.rpf_addr.u.prefix4, &rp_info->group);
596 if (tmp_rp_info) {
597 if ((tmp_rp_info->rp_src != rp_src_flag)
598 && (rp_src_flag == RP_SRC_STATIC))
599 tmp_rp_info->rp_src = rp_src_flag;
600 XFREE(MTYPE_PIM_RP, rp_info);
601 return result;
602 }
603
604 /*
605 * Barf if this group is already covered by some other RP
606 */
607 tmp_rp_info = pim_rp_find_match_group(pim, &rp_info->group);
608
609 if (tmp_rp_info) {
610 if (tmp_rp_info->plist) {
611 XFREE(MTYPE_PIM_RP, rp_info);
612 return PIM_GROUP_PFXLIST_OVERLAP;
613 } else {
614 /*
615 * If the only RP that covers this group is an
616 * RP configured for
617 * 224.0.0.0/4 that is fine, ignore that one.
618 * For all others
619 * though we must return PIM_GROUP_OVERLAP
620 */
621 if (prefix_same(&rp_info->group,
622 &tmp_rp_info->group)) {
623 if ((rp_src_flag == RP_SRC_STATIC)
624 && (tmp_rp_info->rp_src
625 == RP_SRC_STATIC)) {
626 XFREE(MTYPE_PIM_RP, rp_info);
627 return PIM_GROUP_OVERLAP;
628 }
629
630 result = pim_rp_change(
631 pim,
632 rp_info->rp.rpf_addr.u.prefix4,
633 tmp_rp_info->group,
634 rp_src_flag);
635 XFREE(MTYPE_PIM_RP, rp_info);
636 return result;
637 }
638 }
639 }
640 }
641
642 listnode_add_sort(pim->rp_list, rp_info);
643 rn = route_node_get(pim->rp_table, &rp_info->group);
644 rn->info = rp_info;
645
646 if (PIM_DEBUG_PIM_TRACE) {
647 char buf[PREFIX_STRLEN];
648
649 zlog_debug("Allocated: %p for rp_info: %p(%s) Lock: %d", rn,
650 rp_info,
651 prefix2str(&rp_info->group, buf, sizeof(buf)),
652 rn->lock);
653 }
654
655 frr_each (rb_pim_upstream, &pim->upstream_head, up) {
656 if (up->sg.src.s_addr == INADDR_ANY) {
657 struct prefix grp;
658 struct rp_info *trp_info;
659
660 grp.family = AF_INET;
661 grp.prefixlen = IPV4_MAX_BITLEN;
662 grp.u.prefix4 = up->sg.grp;
663 trp_info = pim_rp_find_match_group(pim, &grp);
664
665 if (trp_info == rp_info)
666 pim_upstream_update(pim, up);
667 }
668 }
669
670 pim_rp_check_interfaces(pim, rp_info);
671 pim_rp_refresh_group_to_rp_mapping(pim);
672
673 /* Register addr with Zebra NHT */
674 nht_p.family = AF_INET;
675 nht_p.prefixlen = IPV4_MAX_BITLEN;
676 nht_p.u.prefix4 = rp_info->rp.rpf_addr.u.prefix4;
677 if (PIM_DEBUG_PIM_NHT_RP) {
678 char buf[PREFIX2STR_BUFFER];
679 char buf1[PREFIX2STR_BUFFER];
680 prefix2str(&nht_p, buf, sizeof(buf));
681 prefix2str(&rp_info->group, buf1, sizeof(buf1));
682 zlog_debug("%s: NHT Register RP addr %s grp %s with Zebra ",
683 __func__, buf, buf1);
684 }
685 pim_find_or_track_nexthop(pim, &nht_p, NULL, rp_info, false, NULL);
686 if (!pim_ecmp_nexthop_lookup(pim, &rp_info->rp.source_nexthop, &nht_p,
687 &rp_info->group, 1))
688 return PIM_RP_NO_PATH;
689
690 return PIM_SUCCESS;
691 }
692
693 int pim_rp_del_config(struct pim_instance *pim, const char *rp,
694 const char *group_range, const char *plist)
695 {
696 struct prefix group;
697 struct in_addr rp_addr;
698 int result;
699
700 if (group_range == NULL)
701 result = str2prefix("224.0.0.0/4", &group);
702 else
703 result = str2prefix(group_range, &group);
704
705 if (!result)
706 return PIM_GROUP_BAD_ADDRESS;
707
708 result = inet_pton(AF_INET, rp, &rp_addr);
709 if (result <= 0)
710 return PIM_RP_BAD_ADDRESS;
711
712 result = pim_rp_del(pim, rp_addr, group, plist, RP_SRC_STATIC);
713 return result;
714 }
715
716 int pim_rp_del(struct pim_instance *pim, struct in_addr rp_addr,
717 struct prefix group, const char *plist,
718 enum rp_source rp_src_flag)
719 {
720 struct prefix g_all;
721 struct rp_info *rp_info;
722 struct rp_info *rp_all;
723 struct prefix nht_p;
724 struct route_node *rn;
725 bool was_plist = false;
726 struct rp_info *trp_info;
727 struct pim_upstream *up;
728 struct bsgrp_node *bsgrp = NULL;
729 struct bsm_rpinfo *bsrp = NULL;
730 char grp_str[PREFIX2STR_BUFFER];
731 char rp_str[INET_ADDRSTRLEN];
732
733 if (!inet_ntop(AF_INET, &rp_addr, rp_str, sizeof(rp_str)))
734 snprintf(rp_str, sizeof(rp_str), "<rp?>");
735 prefix2str(&group, grp_str, sizeof(grp_str));
736
737 if (plist)
738 rp_info = pim_rp_find_prefix_list(pim, rp_addr, plist);
739 else
740 rp_info = pim_rp_find_exact(pim, rp_addr, &group);
741
742 if (!rp_info)
743 return PIM_RP_NOT_FOUND;
744
745 if (rp_info->plist) {
746 XFREE(MTYPE_PIM_FILTER_NAME, rp_info->plist);
747 was_plist = true;
748 }
749
750 if (PIM_DEBUG_PIM_TRACE)
751 zlog_debug("%s: Delete RP %s for the group %s", __func__,
752 rp_str, grp_str);
753
754 /* While static RP is getting deleted, we need to check if dynamic RP
755 * present for the same group in BSM RP table, then install the dynamic
756 * RP for the group node into the main rp table
757 */
758 if (rp_src_flag == RP_SRC_STATIC) {
759 bsgrp = pim_bsm_get_bsgrp_node(&pim->global_scope, &group);
760
761 if (bsgrp) {
762 bsrp = listnode_head(bsgrp->bsrp_list);
763 if (bsrp) {
764 if (PIM_DEBUG_PIM_TRACE) {
765 char bsrp_str[INET_ADDRSTRLEN];
766
767 if (!inet_ntop(AF_INET, bsrp, bsrp_str,
768 sizeof(bsrp_str)))
769 snprintf(bsrp_str,
770 sizeof(bsrp_str),
771 "<bsrp?>");
772
773 zlog_debug(
774 "%s: BSM RP %s found for the group %s",
775 __func__, bsrp_str, grp_str);
776 }
777 return pim_rp_change(pim, bsrp->rp_address,
778 group, RP_SRC_BSR);
779 }
780 } else {
781 if (PIM_DEBUG_PIM_TRACE)
782 zlog_debug(
783 "%s: BSM RP not found for the group %s",
784 __func__, grp_str);
785 }
786 }
787
788 /* Deregister addr with Zebra NHT */
789 nht_p.family = AF_INET;
790 nht_p.prefixlen = IPV4_MAX_BITLEN;
791 nht_p.u.prefix4 = rp_info->rp.rpf_addr.u.prefix4;
792 if (PIM_DEBUG_PIM_NHT_RP) {
793 char buf[PREFIX2STR_BUFFER];
794 prefix2str(&nht_p, buf, sizeof(buf));
795 zlog_debug("%s: Deregister RP addr %s with Zebra ", __func__,
796 buf);
797 }
798 pim_delete_tracked_nexthop(pim, &nht_p, NULL, rp_info, false);
799
800 if (!str2prefix("224.0.0.0/4", &g_all))
801 return PIM_RP_BAD_ADDRESS;
802
803 rp_all = pim_rp_find_match_group(pim, &g_all);
804
805 if (rp_all == rp_info) {
806 frr_each (rb_pim_upstream, &pim->upstream_head, up) {
807 /* Find the upstream (*, G) whose upstream address is
808 * same as the deleted RP
809 */
810 if ((up->upstream_addr.s_addr
811 == rp_info->rp.rpf_addr.u.prefix4.s_addr)
812 && (up->sg.src.s_addr == INADDR_ANY)) {
813 struct prefix grp;
814 grp.family = AF_INET;
815 grp.prefixlen = IPV4_MAX_BITLEN;
816 grp.u.prefix4 = up->sg.grp;
817 trp_info = pim_rp_find_match_group(pim, &grp);
818 if (trp_info == rp_all) {
819 pim_upstream_rpf_clear(pim, up);
820 up->upstream_addr.s_addr = INADDR_ANY;
821 }
822 }
823 }
824 rp_all->rp.rpf_addr.family = AF_INET;
825 rp_all->rp.rpf_addr.u.prefix4.s_addr = INADDR_NONE;
826 rp_all->i_am_rp = 0;
827 return PIM_SUCCESS;
828 }
829
830 listnode_delete(pim->rp_list, rp_info);
831
832 if (!was_plist) {
833 rn = route_node_get(pim->rp_table, &rp_info->group);
834 if (rn) {
835 if (rn->info != rp_info)
836 flog_err(
837 EC_LIB_DEVELOPMENT,
838 "Expected rn->info to be equal to rp_info");
839
840 if (PIM_DEBUG_PIM_TRACE) {
841 char buf[PREFIX_STRLEN];
842
843 zlog_debug(
844 "%s:Found for Freeing: %p for rp_info: %p(%s) Lock: %d",
845 __func__, rn, rp_info,
846 prefix2str(&rp_info->group, buf,
847 sizeof(buf)),
848 rn->lock);
849 }
850 rn->info = NULL;
851 route_unlock_node(rn);
852 route_unlock_node(rn);
853 }
854 }
855
856 pim_rp_refresh_group_to_rp_mapping(pim);
857
858 frr_each (rb_pim_upstream, &pim->upstream_head, up) {
859 /* Find the upstream (*, G) whose upstream address is same as
860 * the deleted RP
861 */
862 if ((up->upstream_addr.s_addr
863 == rp_info->rp.rpf_addr.u.prefix4.s_addr)
864 && (up->sg.src.s_addr == INADDR_ANY)) {
865 struct prefix grp;
866
867 grp.family = AF_INET;
868 grp.prefixlen = IPV4_MAX_BITLEN;
869 grp.u.prefix4 = up->sg.grp;
870
871 trp_info = pim_rp_find_match_group(pim, &grp);
872
873 /* RP not found for the group grp */
874 if (pim_rpf_addr_is_inaddr_none(&trp_info->rp)) {
875 pim_upstream_rpf_clear(pim, up);
876 pim_rp_set_upstream_addr(
877 pim, &up->upstream_addr, up->sg.src,
878 up->sg.grp);
879 }
880
881 /* RP found for the group grp */
882 else
883 pim_upstream_update(pim, up);
884 }
885 }
886
887 XFREE(MTYPE_PIM_RP, rp_info);
888 return PIM_SUCCESS;
889 }
890
891 int pim_rp_change(struct pim_instance *pim, struct in_addr new_rp_addr,
892 struct prefix group, enum rp_source rp_src_flag)
893 {
894 struct prefix nht_p;
895 struct route_node *rn;
896 int result = 0;
897 struct rp_info *rp_info = NULL;
898 struct pim_upstream *up;
899
900 rn = route_node_lookup(pim->rp_table, &group);
901 if (!rn) {
902 result = pim_rp_new(pim, new_rp_addr, group, NULL, rp_src_flag);
903 return result;
904 }
905
906 rp_info = rn->info;
907
908 if (!rp_info) {
909 route_unlock_node(rn);
910 result = pim_rp_new(pim, new_rp_addr, group, NULL, rp_src_flag);
911 return result;
912 }
913
914 if (rp_info->rp.rpf_addr.u.prefix4.s_addr == new_rp_addr.s_addr) {
915 if (rp_info->rp_src != rp_src_flag) {
916 rp_info->rp_src = rp_src_flag;
917 route_unlock_node(rn);
918 return PIM_SUCCESS;
919 }
920 }
921
922 nht_p.family = AF_INET;
923 nht_p.prefixlen = IPV4_MAX_BITLEN;
924
925 /* Deregister old RP addr with Zebra NHT */
926 if (rp_info->rp.rpf_addr.u.prefix4.s_addr != INADDR_ANY) {
927 nht_p.u.prefix4 = rp_info->rp.rpf_addr.u.prefix4;
928 if (PIM_DEBUG_PIM_NHT_RP) {
929 char buf[PREFIX2STR_BUFFER];
930
931 prefix2str(&nht_p, buf, sizeof(buf));
932 zlog_debug("%s: Deregister RP addr %s with Zebra ",
933 __func__, buf);
934 }
935 pim_delete_tracked_nexthop(pim, &nht_p, NULL, rp_info, false);
936 }
937
938 pim_rp_nexthop_del(rp_info);
939 listnode_delete(pim->rp_list, rp_info);
940 /* Update the new RP address*/
941 rp_info->rp.rpf_addr.u.prefix4 = new_rp_addr;
942 rp_info->rp_src = rp_src_flag;
943 rp_info->i_am_rp = 0;
944
945 listnode_add_sort(pim->rp_list, rp_info);
946
947 frr_each (rb_pim_upstream, &pim->upstream_head, up) {
948 if (up->sg.src.s_addr == INADDR_ANY) {
949 struct prefix grp;
950 struct rp_info *trp_info;
951
952 grp.family = AF_INET;
953 grp.prefixlen = IPV4_MAX_BITLEN;
954 grp.u.prefix4 = up->sg.grp;
955 trp_info = pim_rp_find_match_group(pim, &grp);
956
957 if (trp_info == rp_info)
958 pim_upstream_update(pim, up);
959 }
960 }
961
962 /* Register new RP addr with Zebra NHT */
963 nht_p.u.prefix4 = rp_info->rp.rpf_addr.u.prefix4;
964 if (PIM_DEBUG_PIM_NHT_RP) {
965 char buf[PREFIX2STR_BUFFER];
966 char buf1[PREFIX2STR_BUFFER];
967
968 prefix2str(&nht_p, buf, sizeof(buf));
969 prefix2str(&rp_info->group, buf1, sizeof(buf1));
970 zlog_debug("%s: NHT Register RP addr %s grp %s with Zebra ",
971 __func__, buf, buf1);
972 }
973
974 pim_find_or_track_nexthop(pim, &nht_p, NULL, rp_info, false, NULL);
975 if (!pim_ecmp_nexthop_lookup(pim, &rp_info->rp.source_nexthop, &nht_p,
976 &rp_info->group, 1)) {
977 route_unlock_node(rn);
978 return PIM_RP_NO_PATH;
979 }
980
981 pim_rp_check_interfaces(pim, rp_info);
982
983 route_unlock_node(rn);
984
985 pim_rp_refresh_group_to_rp_mapping(pim);
986
987 return result;
988 }
989
990 void pim_rp_setup(struct pim_instance *pim)
991 {
992 struct listnode *node;
993 struct rp_info *rp_info;
994 struct prefix nht_p;
995
996 for (ALL_LIST_ELEMENTS_RO(pim->rp_list, node, rp_info)) {
997 if (rp_info->rp.rpf_addr.u.prefix4.s_addr == INADDR_NONE)
998 continue;
999
1000 nht_p.family = AF_INET;
1001 nht_p.prefixlen = IPV4_MAX_BITLEN;
1002 nht_p.u.prefix4 = rp_info->rp.rpf_addr.u.prefix4;
1003
1004 pim_find_or_track_nexthop(pim, &nht_p, NULL, rp_info, false,
1005 NULL);
1006 if (!pim_ecmp_nexthop_lookup(pim, &rp_info->rp.source_nexthop,
1007 &nht_p, &rp_info->group, 1))
1008 if (PIM_DEBUG_PIM_NHT_RP)
1009 zlog_debug(
1010 "Unable to lookup nexthop for rp specified");
1011 }
1012 }
1013
1014 /*
1015 * Checks to see if we should elect ourself the actual RP when new if
1016 * addresses are added against an interface.
1017 */
1018 void pim_rp_check_on_if_add(struct pim_interface *pim_ifp)
1019 {
1020 struct listnode *node;
1021 struct rp_info *rp_info;
1022 bool i_am_rp_changed = false;
1023 struct pim_instance *pim = pim_ifp->pim;
1024
1025 if (pim->rp_list == NULL)
1026 return;
1027
1028 for (ALL_LIST_ELEMENTS_RO(pim->rp_list, node, rp_info)) {
1029 if (pim_rpf_addr_is_inaddr_none(&rp_info->rp))
1030 continue;
1031
1032 /* if i_am_rp is already set nothing to be done (adding new
1033 * addresses
1034 * is not going to make a difference). */
1035 if (rp_info->i_am_rp) {
1036 continue;
1037 }
1038
1039 if (pim_rp_check_interface_addrs(rp_info, pim_ifp)) {
1040 i_am_rp_changed = true;
1041 rp_info->i_am_rp = 1;
1042 if (PIM_DEBUG_PIM_NHT_RP) {
1043 char rp[PREFIX_STRLEN];
1044 pim_addr_dump("<rp?>", &rp_info->rp.rpf_addr,
1045 rp, sizeof(rp));
1046 zlog_debug("%s: %s: i am rp", __func__, rp);
1047 }
1048 }
1049 }
1050
1051 if (i_am_rp_changed) {
1052 pim_msdp_i_am_rp_changed(pim);
1053 pim_upstream_reeval_use_rpt(pim);
1054 }
1055 }
1056
1057 /* up-optimized re-evaluation of "i_am_rp". this is used when ifaddresses
1058 * are removed. Removing numbers is an uncommon event in an active network
1059 * so I have made no attempt to optimize it. */
1060 void pim_i_am_rp_re_evaluate(struct pim_instance *pim)
1061 {
1062 struct listnode *node;
1063 struct rp_info *rp_info;
1064 bool i_am_rp_changed = false;
1065 int old_i_am_rp;
1066
1067 if (pim->rp_list == NULL)
1068 return;
1069
1070 for (ALL_LIST_ELEMENTS_RO(pim->rp_list, node, rp_info)) {
1071 if (pim_rpf_addr_is_inaddr_none(&rp_info->rp))
1072 continue;
1073
1074 old_i_am_rp = rp_info->i_am_rp;
1075 pim_rp_check_interfaces(pim, rp_info);
1076
1077 if (old_i_am_rp != rp_info->i_am_rp) {
1078 i_am_rp_changed = true;
1079 if (PIM_DEBUG_PIM_NHT_RP) {
1080 char rp[PREFIX_STRLEN];
1081 pim_addr_dump("<rp?>", &rp_info->rp.rpf_addr,
1082 rp, sizeof(rp));
1083 if (rp_info->i_am_rp) {
1084 zlog_debug("%s: %s: i am rp", __func__,
1085 rp);
1086 } else {
1087 zlog_debug("%s: %s: i am no longer rp",
1088 __func__, rp);
1089 }
1090 }
1091 }
1092 }
1093
1094 if (i_am_rp_changed) {
1095 pim_msdp_i_am_rp_changed(pim);
1096 pim_upstream_reeval_use_rpt(pim);
1097 }
1098 }
1099
1100 /*
1101 * I_am_RP(G) is true if the group-to-RP mapping indicates that
1102 * this router is the RP for the group.
1103 *
1104 * Since we only have static RP, all groups are part of this RP
1105 */
1106 int pim_rp_i_am_rp(struct pim_instance *pim, struct in_addr group)
1107 {
1108 struct prefix g;
1109 struct rp_info *rp_info;
1110
1111 memset(&g, 0, sizeof(g));
1112 g.family = AF_INET;
1113 g.prefixlen = 32;
1114 g.u.prefix4 = group;
1115
1116 rp_info = pim_rp_find_match_group(pim, &g);
1117
1118 if (rp_info)
1119 return rp_info->i_am_rp;
1120
1121 return 0;
1122 }
1123
1124 /*
1125 * RP(G)
1126 *
1127 * Return the RP that the Group belongs too.
1128 */
1129 struct pim_rpf *pim_rp_g(struct pim_instance *pim, struct in_addr group)
1130 {
1131 struct prefix g;
1132 struct rp_info *rp_info;
1133
1134 memset(&g, 0, sizeof(g));
1135 g.family = AF_INET;
1136 g.prefixlen = 32;
1137 g.u.prefix4 = group;
1138
1139 rp_info = pim_rp_find_match_group(pim, &g);
1140
1141 if (rp_info) {
1142 struct prefix nht_p;
1143
1144 /* Register addr with Zebra NHT */
1145 nht_p.family = AF_INET;
1146 nht_p.prefixlen = IPV4_MAX_BITLEN;
1147 nht_p.u.prefix4 = rp_info->rp.rpf_addr.u.prefix4;
1148 if (PIM_DEBUG_PIM_NHT_RP) {
1149 char buf[PREFIX2STR_BUFFER];
1150 char buf1[PREFIX2STR_BUFFER];
1151 prefix2str(&nht_p, buf, sizeof(buf));
1152 prefix2str(&rp_info->group, buf1, sizeof(buf1));
1153 zlog_debug(
1154 "%s: NHT Register RP addr %s grp %s with Zebra",
1155 __func__, buf, buf1);
1156 }
1157 pim_find_or_track_nexthop(pim, &nht_p, NULL, rp_info, false,
1158 NULL);
1159 pim_rpf_set_refresh_time(pim);
1160 (void)pim_ecmp_nexthop_lookup(pim, &rp_info->rp.source_nexthop,
1161 &nht_p, &rp_info->group, 1);
1162 return (&rp_info->rp);
1163 }
1164
1165 // About to Go Down
1166 return NULL;
1167 }
1168
1169 /*
1170 * Set the upstream IP address we want to talk to based upon
1171 * the rp configured and the source address
1172 *
1173 * If we have don't have a RP configured and the source address is *
1174 * then set the upstream addr as INADDR_ANY and return failure.
1175 *
1176 */
1177 int pim_rp_set_upstream_addr(struct pim_instance *pim, struct in_addr *up,
1178 struct in_addr source, struct in_addr group)
1179 {
1180 struct rp_info *rp_info;
1181 struct prefix g;
1182
1183 memset(&g, 0, sizeof(g));
1184 g.family = AF_INET;
1185 g.prefixlen = 32;
1186 g.u.prefix4 = group;
1187
1188 rp_info = pim_rp_find_match_group(pim, &g);
1189
1190 if (!rp_info || ((pim_rpf_addr_is_inaddr_none(&rp_info->rp))
1191 && (source.s_addr == INADDR_ANY))) {
1192 if (PIM_DEBUG_PIM_NHT_RP)
1193 zlog_debug("%s: Received a (*,G) with no RP configured",
1194 __func__);
1195 up->s_addr = INADDR_ANY;
1196 return 0;
1197 }
1198
1199 *up = (source.s_addr == INADDR_ANY) ? rp_info->rp.rpf_addr.u.prefix4
1200 : source;
1201
1202 return 1;
1203 }
1204
1205 int pim_rp_config_write(struct pim_instance *pim, struct vty *vty,
1206 const char *spaces)
1207 {
1208 struct listnode *node;
1209 struct rp_info *rp_info;
1210 char rp_buffer[32];
1211 char group_buffer[32];
1212 int count = 0;
1213
1214 for (ALL_LIST_ELEMENTS_RO(pim->rp_list, node, rp_info)) {
1215 if (pim_rpf_addr_is_inaddr_none(&rp_info->rp))
1216 continue;
1217
1218 if (rp_info->rp_src == RP_SRC_BSR)
1219 continue;
1220
1221 if (rp_info->plist)
1222 vty_out(vty, "%sip pim rp %s prefix-list %s\n", spaces,
1223 inet_ntop(AF_INET,
1224 &rp_info->rp.rpf_addr.u.prefix4,
1225 rp_buffer, 32),
1226 rp_info->plist);
1227 else
1228 vty_out(vty, "%sip pim rp %s %s\n", spaces,
1229 inet_ntop(AF_INET,
1230 &rp_info->rp.rpf_addr.u.prefix4,
1231 rp_buffer, 32),
1232 prefix2str(&rp_info->group, group_buffer, 32));
1233 count++;
1234 }
1235
1236 return count;
1237 }
1238
1239 bool pim_rp_check_is_my_ip_address(struct pim_instance *pim,
1240 struct in_addr dest_addr)
1241 {
1242 if (if_lookup_exact_address(&dest_addr, AF_INET, pim->vrf_id))
1243 return true;
1244
1245 return false;
1246 }
1247
1248 void pim_rp_show_information(struct pim_instance *pim, struct vty *vty, bool uj)
1249 {
1250 struct rp_info *rp_info;
1251 struct rp_info *prev_rp_info = NULL;
1252 struct listnode *node;
1253 char source[7];
1254
1255 json_object *json = NULL;
1256 json_object *json_rp_rows = NULL;
1257 json_object *json_row = NULL;
1258
1259 if (uj)
1260 json = json_object_new_object();
1261 else
1262 vty_out(vty,
1263 "RP address group/prefix-list OIF I am RP Source\n");
1264 for (ALL_LIST_ELEMENTS_RO(pim->rp_list, node, rp_info)) {
1265 if (!pim_rpf_addr_is_inaddr_none(&rp_info->rp)) {
1266 char buf[48];
1267
1268 if (rp_info->rp_src == RP_SRC_STATIC)
1269 strlcpy(source, "Static", sizeof(source));
1270 else if (rp_info->rp_src == RP_SRC_BSR)
1271 strlcpy(source, "BSR", sizeof(source));
1272 else
1273 strlcpy(source, "None", sizeof(source));
1274 if (uj) {
1275 /*
1276 * If we have moved on to a new RP then add the
1277 * entry for the previous RP
1278 */
1279 if (prev_rp_info
1280 && prev_rp_info->rp.rpf_addr.u.prefix4
1281 .s_addr
1282 != rp_info->rp.rpf_addr.u.prefix4
1283 .s_addr) {
1284 json_object_object_add(
1285 json,
1286 inet_ntoa(prev_rp_info->rp
1287 .rpf_addr.u
1288 .prefix4),
1289 json_rp_rows);
1290 json_rp_rows = NULL;
1291 }
1292
1293 if (!json_rp_rows)
1294 json_rp_rows = json_object_new_array();
1295
1296 json_row = json_object_new_object();
1297 json_object_string_add(
1298 json_row, "rpAddress",
1299 inet_ntoa(rp_info->rp.rpf_addr.u
1300 .prefix4));
1301 if (rp_info->rp.source_nexthop.interface)
1302 json_object_string_add(
1303 json_row, "outboundInterface",
1304 rp_info->rp.source_nexthop
1305 .interface->name);
1306 else
1307 json_object_string_add(
1308 json_row, "outboundInterface",
1309 "Unknown");
1310 if (rp_info->i_am_rp)
1311 json_object_boolean_true_add(json_row,
1312 "iAmRP");
1313 else
1314 json_object_boolean_false_add(json_row,
1315 "iAmRP");
1316
1317 if (rp_info->plist)
1318 json_object_string_add(json_row,
1319 "prefixList",
1320 rp_info->plist);
1321 else
1322 json_object_string_add(
1323 json_row, "group",
1324 prefix2str(&rp_info->group, buf,
1325 48));
1326 json_object_string_add(json_row, "source",
1327 source);
1328
1329 json_object_array_add(json_rp_rows, json_row);
1330 } else {
1331 vty_out(vty, "%-15s ",
1332 inet_ntoa(rp_info->rp.rpf_addr.u
1333 .prefix4));
1334
1335 if (rp_info->plist)
1336 vty_out(vty, "%-18s ", rp_info->plist);
1337 else
1338 vty_out(vty, "%-18s ",
1339 prefix2str(&rp_info->group, buf,
1340 48));
1341
1342 if (rp_info->rp.source_nexthop.interface)
1343 vty_out(vty, "%-16s ",
1344 rp_info->rp.source_nexthop
1345 .interface->name);
1346 else
1347 vty_out(vty, "%-16s ", "(Unknown)");
1348
1349 if (rp_info->i_am_rp)
1350 vty_out(vty, "yes");
1351 else
1352 vty_out(vty, "no");
1353
1354 vty_out(vty, "%14s\n", source);
1355 }
1356 prev_rp_info = rp_info;
1357 }
1358 }
1359
1360 if (uj) {
1361 if (prev_rp_info && json_rp_rows)
1362 json_object_object_add(
1363 json,
1364 inet_ntoa(prev_rp_info->rp.rpf_addr.u.prefix4),
1365 json_rp_rows);
1366
1367 vty_out(vty, "%s\n", json_object_to_json_string_ext(
1368 json, JSON_C_TO_STRING_PRETTY));
1369 json_object_free(json);
1370 }
1371 }
1372
1373 void pim_resolve_rp_nh(struct pim_instance *pim, struct pim_neighbor *nbr)
1374 {
1375 struct listnode *node = NULL;
1376 struct rp_info *rp_info = NULL;
1377 struct nexthop *nh_node = NULL;
1378 struct prefix nht_p;
1379 struct pim_nexthop_cache pnc;
1380
1381 for (ALL_LIST_ELEMENTS_RO(pim->rp_list, node, rp_info)) {
1382 if (rp_info->rp.rpf_addr.u.prefix4.s_addr == INADDR_NONE)
1383 continue;
1384
1385 nht_p.family = AF_INET;
1386 nht_p.prefixlen = IPV4_MAX_BITLEN;
1387 nht_p.u.prefix4 = rp_info->rp.rpf_addr.u.prefix4;
1388 memset(&pnc, 0, sizeof(struct pim_nexthop_cache));
1389 if (!pim_find_or_track_nexthop(pim, &nht_p, NULL, rp_info,
1390 false, &pnc))
1391 continue;
1392
1393 for (nh_node = pnc.nexthop; nh_node; nh_node = nh_node->next) {
1394 if (nh_node->gate.ipv4.s_addr != 0)
1395 continue;
1396
1397 struct interface *ifp1 = if_lookup_by_index(
1398 nh_node->ifindex, pim->vrf_id);
1399
1400 if (nbr->interface != ifp1)
1401 continue;
1402
1403 nh_node->gate.ipv4 = nbr->source_addr;
1404 if (PIM_DEBUG_PIM_NHT_RP) {
1405 char str[PREFIX_STRLEN];
1406 char str1[INET_ADDRSTRLEN];
1407 pim_inet4_dump("<nht_nbr?>", nbr->source_addr,
1408 str1, sizeof(str1));
1409 pim_addr_dump("<nht_addr?>", &nht_p, str,
1410 sizeof(str));
1411 zlog_debug(
1412 "%s: addr %s new nexthop addr %s interface %s",
1413 __func__, str, str1, ifp1->name);
1414 }
1415 }
1416 }
1417 }