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