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