]> git.proxmox.com Git - mirror_frr.git/blame - pimd/pim_rp.c
Merge pull request #9496 from idryzhov/vrf-cmd-init-unused-arg
[mirror_frr.git] / pimd / pim_rp.c
CommitLineData
8f5f5e91
DS
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.
896014f4
DL
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
8f5f5e91
DS
19 */
20#include <zebra.h>
21
9bf3c633 22#include "lib/json.h"
54b97c74 23#include "log.h"
8f5f5e91 24#include "network.h"
744d91b3 25#include "if.h"
36d6bd7d
DS
26#include "linklist.h"
27#include "prefix.h"
28#include "memory.h"
00d07c6f
DS
29#include "vty.h"
30#include "vrf.h"
dfe43e25 31#include "plist.h"
cba44481 32#include "nexthop.h"
89b68082 33#include "table.h"
3613d898 34#include "lib_errors.h"
8f5f5e91
DS
35
36#include "pimd.h"
75a26779 37#include "pim_vty.h"
54b97c74 38#include "pim_str.h"
7176984f 39#include "pim_iface.h"
8f5f5e91 40#include "pim_rp.h"
ed66602c
DS
41#include "pim_str.h"
42#include "pim_rpf.h"
13afbd05 43#include "pim_sock.h"
36d6bd7d 44#include "pim_memory.h"
00d07c6f 45#include "pim_iface.h"
7667c556 46#include "pim_msdp.h"
1bc98276 47#include "pim_nht.h"
28309df0
SP
48#include "pim_mroute.h"
49#include "pim_oil.h"
50#include "pim_zebra.h"
d0e418b4 51#include "pim_bsm.h"
36d6bd7d 52
c2cf4b02
DS
53/* Cleanup pim->rpf_hash each node data */
54void pim_rp_list_hash_clean(void *data)
55{
7c591950 56 struct pim_nexthop_cache *pnc = (struct pim_nexthop_cache *)data;
c2cf4b02 57
6a154c88 58 list_delete(&pnc->rp_list);
6e1ef388 59
7c591950
DS
60 hash_clean(pnc->upstream_hash, NULL);
61 hash_free(pnc->upstream_hash);
62 pnc->upstream_hash = NULL;
1159c202
SP
63 if (pnc->nexthop)
64 nexthops_free(pnc->nexthop);
6e1ef388
DS
65
66 XFREE(MTYPE_PIM_NEXTHOP_CACHE, pnc);
c2cf4b02
DS
67}
68
d62a17ae 69static void pim_rp_info_free(struct rp_info *rp_info)
36d6bd7d 70{
0a22ddfb 71 XFREE(MTYPE_PIM_FILTER_NAME, rp_info->plist);
ff823fc9 72
d62a17ae 73 XFREE(MTYPE_PIM_RP, rp_info);
36d6bd7d
DS
74}
75
d62a17ae 76int pim_rp_list_cmp(void *v1, void *v2)
36d6bd7d 77{
d62a17ae 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;
36d6bd7d
DS
102}
103
d9c9a9ee 104void pim_rp_init(struct pim_instance *pim)
36d6bd7d 105{
d62a17ae 106 struct rp_info *rp_info;
89b68082 107 struct route_node *rn;
36d6bd7d 108
d9c9a9ee
DS
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;
36d6bd7d 112
89b68082 113 pim->rp_table = route_table_init();
89b68082 114
d62a17ae 115 rp_info = XCALLOC(MTYPE_PIM_RP, sizeof(*rp_info));
36d6bd7d 116
2e8345c1 117 if (!str2prefix("224.0.0.0/4", &rp_info->group)) {
450971aa 118 flog_err(EC_LIB_DEVELOPMENT,
1c50c1c0 119 "Unable to convert 224.0.0.0/4 to prefix");
6a154c88 120 list_delete(&pim->rp_list);
89b68082 121 route_table_finish(pim->rp_table);
2e8345c1
DS
122 XFREE(MTYPE_PIM_RP, rp_info);
123 return;
124 }
d62a17ae 125 rp_info->group.family = AF_INET;
126 rp_info->rp.rpf_addr.family = AF_INET;
936fbaef 127 rp_info->rp.rpf_addr.prefixlen = IPV4_MAX_BITLEN;
d62a17ae 128 rp_info->rp.rpf_addr.u.prefix4.s_addr = INADDR_NONE;
36d6bd7d 129
d9c9a9ee 130 listnode_add(pim->rp_list, rp_info);
89b68082
DS
131
132 rn = route_node_get(pim->rp_table, &rp_info->group);
89b68082 133 rn->info = rp_info;
23fc858a 134 if (PIM_DEBUG_PIM_TRACE)
996c9314
LB
135 zlog_debug(
136 "Allocated: %p for rp_info: %p(224.0.0.0/4) Lock: %d",
c10e14e9 137 rn, rp_info, route_node_get_lock_count(rn));
36d6bd7d
DS
138}
139
d9c9a9ee 140void pim_rp_free(struct pim_instance *pim)
36d6bd7d 141{
e4e52805
DS
142 if (pim->rp_table)
143 route_table_finish(pim->rp_table);
144 pim->rp_table = NULL;
906640db 145
146 if (pim->rp_list)
147 list_delete(&pim->rp_list);
36d6bd7d
DS
148}
149
dfe43e25
DW
150/*
151 * Given an RP's prefix-list, return the RP's rp_info for that prefix-list
152 */
d9c9a9ee
DS
153static struct rp_info *pim_rp_find_prefix_list(struct pim_instance *pim,
154 struct in_addr rp,
d62a17ae 155 const char *plist)
36d6bd7d 156{
d62a17ae 157 struct listnode *node;
158 struct rp_info *rp_info;
159
d9c9a9ee 160 for (ALL_LIST_ELEMENTS_RO(pim->rp_list, node, rp_info)) {
d62a17ae 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;
36d6bd7d
DS
168}
169
dfe43e25
DW
170/*
171 * Return true if plist is used by any rp_info
172 */
d9c9a9ee 173static int pim_rp_prefix_list_used(struct pim_instance *pim, const char *plist)
dfe43e25 174{
d62a17ae 175 struct listnode *node;
176 struct rp_info *rp_info;
177
d9c9a9ee 178 for (ALL_LIST_ELEMENTS_RO(pim->rp_list, node, rp_info)) {
d62a17ae 179 if (rp_info->plist && strcmp(rp_info->plist, plist) == 0) {
180 return 1;
181 }
182 }
183
184 return 0;
dfe43e25
DW
185}
186
187/*
d62a17ae 188 * Given an RP's address, return the RP's rp_info that is an exact match for
189 * 'group'
dfe43e25 190 */
d9c9a9ee
DS
191static struct rp_info *pim_rp_find_exact(struct pim_instance *pim,
192 struct in_addr rp,
123214ef 193 const struct prefix *group)
36d6bd7d 194{
d62a17ae 195 struct listnode *node;
196 struct rp_info *rp_info;
36d6bd7d 197
d9c9a9ee 198 for (ALL_LIST_ELEMENTS_RO(pim->rp_list, node, rp_info)) {
d62a17ae 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 }
54b97c74 203
d62a17ae 204 return NULL;
36d6bd7d
DS
205}
206
2b6b16fc
DL
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
dfe43e25
DW
227/*
228 * Given a group, return the rp_info for that group
229 */
28309df0 230struct rp_info *pim_rp_find_match_group(struct pim_instance *pim,
123214ef 231 const struct prefix *group)
36d6bd7d 232{
d62a17ae 233 struct listnode *node;
b77b1550 234 struct rp_info *best = NULL;
d62a17ae 235 struct rp_info *rp_info;
236 struct prefix_list *plist;
2b6b16fc
DL
237 const struct prefix *bp;
238 const struct prefix_list_entry *entry;
89b68082 239 struct route_node *rn;
d62a17ae 240
4646b86a 241 bp = NULL;
d9c9a9ee 242 for (ALL_LIST_ELEMENTS_RO(pim->rp_list, node, rp_info)) {
d62a17ae 243 if (rp_info->plist) {
244 plist = prefix_list_lookup(AFI_IP, rp_info->plist);
245
2b6b16fc
DL
246 if (prefix_list_apply_ext(plist, &entry, group, true)
247 == PREFIX_DENY || !entry)
b77b1550
DS
248 continue;
249
250 if (!best) {
251 best = rp_info;
2b6b16fc 252 bp = &entry->prefix;
b77b1550
DS
253 continue;
254 }
255
2b6b16fc 256 if (bp && bp->prefixlen < entry->prefix.prefixlen) {
b77b1550 257 best = rp_info;
2b6b16fc 258 bp = &entry->prefix;
b77b1550 259 }
d62a17ae 260 }
261 }
262
89b68082
DS
263 rn = route_node_match(pim->rp_table, group);
264 if (!rn) {
af4c2728 265 flog_err(
450971aa 266 EC_LIB_DEVELOPMENT,
1d5453d6 267 "%s: BUG We should have found default group information",
5e81f5dd 268 __func__);
89b68082
DS
269 return best;
270 }
271
272 rp_info = rn->info;
2dbe669b
DA
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,
c10e14e9 276 route_node_get_lock_count(rn));
89b68082 277
260c92c8 278 route_unlock_node(rn);
279
89b68082
DS
280 if (!best)
281 return rp_info;
282
283 if (rp_info->group.prefixlen < best->group.prefixlen)
284 best = rp_info;
285
b77b1550 286 return best;
36d6bd7d 287}
75a26779 288
dfe43e25
DW
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 */
e7016ceb 296void pim_rp_refresh_group_to_rp_mapping(struct pim_instance *pim)
dfe43e25 297{
472ad383 298 pim_msdp_i_am_rp_changed(pim);
a749b900 299 pim_upstream_reeval_use_rpt(pim);
dfe43e25
DW
300}
301
d9c9a9ee
DS
302void pim_rp_prefix_list_update(struct pim_instance *pim,
303 struct prefix_list *plist)
dfe43e25 304{
d62a17ae 305 struct listnode *node;
306 struct rp_info *rp_info;
307 int refresh_needed = 0;
308
d9c9a9ee 309 for (ALL_LIST_ELEMENTS_RO(pim->rp_list, node, rp_info)) {
d62a17ae 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)
472ad383 318 pim_rp_refresh_group_to_rp_mapping(pim);
dfe43e25
DW
319}
320
d62a17ae 321static int pim_rp_check_interface_addrs(struct rp_info *rp_info,
322 struct pim_interface *pim_ifp)
7176984f 323{
d62a17ae 324 struct listnode *node;
325 struct pim_secondary_addr *sec_addr;
7176984f 326
d62a17ae 327 if (pim_ifp->primary_address.s_addr
328 == rp_info->rp.rpf_addr.u.prefix4.s_addr)
329 return 1;
7176984f 330
d62a17ae 331 if (!pim_ifp->sec_addr_list) {
332 return 0;
333 }
7176984f 334
d62a17ae 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 }
7176984f 340
d62a17ae 341 return 0;
7176984f 342}
343
fec883d9
DS
344static void pim_rp_check_interfaces(struct pim_instance *pim,
345 struct rp_info *rp_info)
00d07c6f 346{
d62a17ae 347 struct interface *ifp;
00d07c6f 348
d62a17ae 349 rp_info->i_am_rp = 0;
451fda4f 350 FOR_ALL_INTERFACES (pim->vrf, ifp) {
d62a17ae 351 struct pim_interface *pim_ifp = ifp->info;
00d07c6f 352
d62a17ae 353 if (!pim_ifp)
354 continue;
00d07c6f 355
d62a17ae 356 if (pim_rp_check_interface_addrs(rp_info, pim_ifp)) {
357 rp_info->i_am_rp = 1;
358 }
359 }
00d07c6f
DS
360}
361
28309df0
SP
362void 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
23fc858a 374 if (PIM_DEBUG_PIM_TRACE)
ee2bbf7c
MS
375 zlog_debug("%s: pim upstream update for old upstream %pI4",
376 __func__, &old_upstream_addr);
28309df0
SP
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;
2dbe669b 391 if (PIM_DEBUG_PIM_TRACE)
15569c58 392 zlog_debug(
2dbe669b
DA
393 "%s: Deregister upstream %s addr %pFX with Zebra NHT",
394 __func__, up->sg_str, &nht_p);
4533b847 395 pim_delete_tracked_nexthop(pim, &nht_p, up, NULL, false);
28309df0
SP
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
8c55c132 403 rpf_result = pim_rpf_update(pim, up, &old_rpf, __func__);
28309df0 404 if (rpf_result == PIM_RPF_FAILURE)
15569c58 405 pim_mroute_del(up->channel_oil, __func__);
28309df0
SP
406
407 /* update kernel multicast forwarding cache (MFC) */
7984af18
AK
408 if (up->rpf.source_nexthop.interface && up->channel_oil)
409 pim_upstream_mroute_iif_update(up->channel_oil, __func__);
28309df0 410
b36576e4
AK
411 if (rpf_result == PIM_RPF_CHANGED ||
412 (rpf_result == PIM_RPF_FAILURE &&
413 old_rpf.source_nexthop.interface))
28309df0
SP
414 pim_zebra_upstream_rpf_changed(pim, up, &old_rpf);
415
416 pim_zebra_update_all_interfaces(pim);
417}
418
d0e418b4 419int pim_rp_new(struct pim_instance *pim, struct in_addr rp_addr,
420 struct prefix group, const char *plist,
421 enum rp_source rp_src_flag)
422{
423 int result = 0;
424 char rp[INET_ADDRSTRLEN];
d62a17ae 425 struct rp_info *rp_info;
426 struct rp_info *rp_all;
427 struct prefix group_all;
428 struct listnode *node, *nnode;
429 struct rp_info *tmp_rp_info;
430 char buffer[BUFSIZ];
431 struct prefix nht_p;
89b68082 432 struct route_node *rn;
28309df0 433 struct pim_upstream *up;
d62a17ae 434
1e0d1c25
DS
435 if (rp_addr.s_addr == INADDR_ANY ||
436 rp_addr.s_addr == INADDR_NONE)
437 return PIM_RP_BAD_ADDRESS;
438
d62a17ae 439 rp_info = XCALLOC(MTYPE_PIM_RP, sizeof(*rp_info));
d62a17ae 440
d62a17ae 441 rp_info->rp.rpf_addr.family = AF_INET;
936fbaef 442 rp_info->rp.rpf_addr.prefixlen = IPV4_MAX_BITLEN;
d0e418b4 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;
d62a17ae 446
d0e418b4 447 inet_ntop(AF_INET, &rp_info->rp.rpf_addr.u.prefix4, rp, sizeof(rp));
d62a17ae 448
449 if (plist) {
450 /*
451 * Return if the prefix-list is already configured for this RP
452 */
d9c9a9ee 453 if (pim_rp_find_prefix_list(pim, rp_info->rp.rpf_addr.u.prefix4,
d62a17ae 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 */
d9c9a9ee 462 if (pim_rp_prefix_list_used(pim, plist)) {
d62a17ae 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 */
d9c9a9ee 470 for (ALL_LIST_ELEMENTS(pim->rp_list, node, nnode,
d62a17ae 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)
d0e418b4 475 pim_rp_del_config(pim, rp, NULL,
476 tmp_rp_info->plist);
d62a17ae 477 else
d0e418b4 478 pim_rp_del_config(
fec883d9 479 pim, rp,
d62a17ae 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 {
89b68082 488
2e8345c1
DS
489 if (!str2prefix("224.0.0.0/4", &group_all)) {
490 XFREE(MTYPE_PIM_RP, rp_info);
491 return PIM_GROUP_BAD_ADDRESS;
492 }
d9c9a9ee 493 rp_all = pim_rp_find_match_group(pim, &group_all);
d62a17ae 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 */
d9c9a9ee 506 for (ALL_LIST_ELEMENTS(pim->rp_list, node, nnode,
d62a17ae 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) {
d0e418b4 512 pim_rp_del_config(pim, rp, NULL,
513 tmp_rp_info->plist);
d62a17ae 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;
d0e418b4 523 rp_all->rp_src = rp_src_flag;
d62a17ae 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
2dbe669b 531 if (PIM_DEBUG_PIM_NHT_RP)
d62a17ae 532 zlog_debug(
2dbe669b
DA
533 "%s: NHT Register rp_all addr %pFX grp %pFX ",
534 __func__, &nht_p, &rp_all->group);
28309df0 535
dd3364cb 536 frr_each (rb_pim_upstream, &pim->upstream_head, up) {
28309df0
SP
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;
d0e418b4 548 trp_info = pim_rp_find_match_group(
549 pim, &grp);
28309df0
SP
550 if (trp_info == rp_all)
551 pim_upstream_update(pim, up);
552 }
553 }
554
5bd51314
DS
555 pim_rp_check_interfaces(pim, rp_all);
556 pim_rp_refresh_group_to_rp_mapping(pim);
43763b11 557 pim_find_or_track_nexthop(pim, &nht_p, NULL, rp_all,
4533b847 558 false, NULL);
559
43763b11
DS
560 if (!pim_ecmp_nexthop_lookup(pim,
561 &rp_all->rp.source_nexthop,
562 &nht_p, &rp_all->group, 1))
563 return PIM_RP_NO_PATH;
d62a17ae 564 return PIM_SUCCESS;
565 }
566
567 /*
568 * Return if the group is already configured for this RP
569 */
d0e418b4 570 tmp_rp_info = pim_rp_find_exact(
571 pim, rp_info->rp.rpf_addr.u.prefix4, &rp_info->group);
572 if (tmp_rp_info) {
573 if ((tmp_rp_info->rp_src != rp_src_flag)
574 && (rp_src_flag == RP_SRC_STATIC))
575 tmp_rp_info->rp_src = rp_src_flag;
d62a17ae 576 XFREE(MTYPE_PIM_RP, rp_info);
d0e418b4 577 return result;
d62a17ae 578 }
579
580 /*
581 * Barf if this group is already covered by some other RP
582 */
d9c9a9ee 583 tmp_rp_info = pim_rp_find_match_group(pim, &rp_info->group);
d62a17ae 584
585 if (tmp_rp_info) {
586 if (tmp_rp_info->plist) {
587 XFREE(MTYPE_PIM_RP, rp_info);
588 return PIM_GROUP_PFXLIST_OVERLAP;
589 } else {
590 /*
591 * If the only RP that covers this group is an
592 * RP configured for
593 * 224.0.0.0/4 that is fine, ignore that one.
594 * For all others
595 * though we must return PIM_GROUP_OVERLAP
596 */
89b68082
DS
597 if (prefix_same(&rp_info->group,
598 &tmp_rp_info->group)) {
d0e418b4 599 if ((rp_src_flag == RP_SRC_STATIC)
600 && (tmp_rp_info->rp_src
601 == RP_SRC_STATIC)) {
602 XFREE(MTYPE_PIM_RP, rp_info);
603 return PIM_GROUP_OVERLAP;
604 }
605
606 result = pim_rp_change(
607 pim,
608 rp_info->rp.rpf_addr.u.prefix4,
609 tmp_rp_info->group,
610 rp_src_flag);
d62a17ae 611 XFREE(MTYPE_PIM_RP, rp_info);
d0e418b4 612 return result;
d62a17ae 613 }
614 }
615 }
616 }
617
d9c9a9ee 618 listnode_add_sort(pim->rp_list, rp_info);
89b68082 619 rn = route_node_get(pim->rp_table, &rp_info->group);
89b68082
DS
620 rn->info = rp_info;
621
2dbe669b
DA
622 if (PIM_DEBUG_PIM_TRACE)
623 zlog_debug("Allocated: %p for rp_info: %p(%pFX) Lock: %d", rn,
624 rp_info, &rp_info->group,
c10e14e9 625 route_node_get_lock_count(rn));
d62a17ae 626
dd3364cb 627 frr_each (rb_pim_upstream, &pim->upstream_head, up) {
28309df0
SP
628 if (up->sg.src.s_addr == INADDR_ANY) {
629 struct prefix grp;
630 struct rp_info *trp_info;
631
632 grp.family = AF_INET;
633 grp.prefixlen = IPV4_MAX_BITLEN;
634 grp.u.prefix4 = up->sg.grp;
635 trp_info = pim_rp_find_match_group(pim, &grp);
636
637 if (trp_info == rp_info)
638 pim_upstream_update(pim, up);
639 }
640 }
641
5bd51314
DS
642 pim_rp_check_interfaces(pim, rp_info);
643 pim_rp_refresh_group_to_rp_mapping(pim);
644
d62a17ae 645 /* Register addr with Zebra NHT */
646 nht_p.family = AF_INET;
647 nht_p.prefixlen = IPV4_MAX_BITLEN;
648 nht_p.u.prefix4 = rp_info->rp.rpf_addr.u.prefix4;
2dbe669b
DA
649 if (PIM_DEBUG_PIM_NHT_RP)
650 zlog_debug("%s: NHT Register RP addr %pFX grp %pFX with Zebra ",
651 __func__, &nht_p, &rp_info->group);
4533b847 652 pim_find_or_track_nexthop(pim, &nht_p, NULL, rp_info, false, NULL);
43763b11
DS
653 if (!pim_ecmp_nexthop_lookup(pim, &rp_info->rp.source_nexthop, &nht_p,
654 &rp_info->group, 1))
655 return PIM_RP_NO_PATH;
d62a17ae 656
d62a17ae 657 return PIM_SUCCESS;
75a26779
DS
658}
659
d0e418b4 660int pim_rp_del_config(struct pim_instance *pim, const char *rp,
661 const char *group_range, const char *plist)
75a26779 662{
d62a17ae 663 struct prefix group;
664 struct in_addr rp_addr;
d62a17ae 665 int result;
d62a17ae 666
667 if (group_range == NULL)
668 result = str2prefix("224.0.0.0/4", &group);
669 else
670 result = str2prefix(group_range, &group);
671
672 if (!result)
673 return PIM_GROUP_BAD_ADDRESS;
674
675 result = inet_pton(AF_INET, rp, &rp_addr);
676 if (result <= 0)
677 return PIM_RP_BAD_ADDRESS;
678
d0e418b4 679 result = pim_rp_del(pim, rp_addr, group, plist, RP_SRC_STATIC);
680 return result;
681}
682
683int pim_rp_del(struct pim_instance *pim, struct in_addr rp_addr,
684 struct prefix group, const char *plist,
685 enum rp_source rp_src_flag)
686{
687 struct prefix g_all;
688 struct rp_info *rp_info;
689 struct rp_info *rp_all;
690 struct prefix nht_p;
691 struct route_node *rn;
692 bool was_plist = false;
693 struct rp_info *trp_info;
694 struct pim_upstream *up;
d0e418b4 695 struct bsgrp_node *bsgrp = NULL;
696 struct bsm_rpinfo *bsrp = NULL;
d0e418b4 697 char rp_str[INET_ADDRSTRLEN];
698
699 if (!inet_ntop(AF_INET, &rp_addr, rp_str, sizeof(rp_str)))
772270f3 700 snprintf(rp_str, sizeof(rp_str), "<rp?>");
d0e418b4 701
d62a17ae 702 if (plist)
d9c9a9ee 703 rp_info = pim_rp_find_prefix_list(pim, rp_addr, plist);
d62a17ae 704 else
d9c9a9ee 705 rp_info = pim_rp_find_exact(pim, rp_addr, &group);
d62a17ae 706
707 if (!rp_info)
708 return PIM_RP_NOT_FOUND;
709
710 if (rp_info->plist) {
711 XFREE(MTYPE_PIM_FILTER_NAME, rp_info->plist);
89b68082 712 was_plist = true;
d62a17ae 713 }
714
23fc858a 715 if (PIM_DEBUG_PIM_TRACE)
2dbe669b
DA
716 zlog_debug("%s: Delete RP %s for the group %pFX", __func__,
717 rp_str, &group);
d0e418b4 718
719 /* While static RP is getting deleted, we need to check if dynamic RP
720 * present for the same group in BSM RP table, then install the dynamic
721 * RP for the group node into the main rp table
722 */
723 if (rp_src_flag == RP_SRC_STATIC) {
724 bsgrp = pim_bsm_get_bsgrp_node(&pim->global_scope, &group);
725
726 if (bsgrp) {
fdab2940 727 bsrp = bsm_rpinfos_first(bsgrp->bsrp_list);
d0e418b4 728 if (bsrp) {
23fc858a 729 if (PIM_DEBUG_PIM_TRACE) {
d0e418b4 730 char bsrp_str[INET_ADDRSTRLEN];
731
732 if (!inet_ntop(AF_INET, bsrp, bsrp_str,
733 sizeof(bsrp_str)))
772270f3
QY
734 snprintf(bsrp_str,
735 sizeof(bsrp_str),
736 "<bsrp?>");
d0e418b4 737
15569c58 738 zlog_debug(
2dbe669b
DA
739 "%s: BSM RP %s found for the group %pFX",
740 __func__, bsrp_str, &group);
d0e418b4 741 }
742 return pim_rp_change(pim, bsrp->rp_address,
743 group, RP_SRC_BSR);
744 }
745 } else {
23fc858a 746 if (PIM_DEBUG_PIM_TRACE)
d0e418b4 747 zlog_debug(
2dbe669b
DA
748 "%s: BSM RP not found for the group %pFX",
749 __func__, &group);
d0e418b4 750 }
751 }
752
d62a17ae 753 /* Deregister addr with Zebra NHT */
754 nht_p.family = AF_INET;
755 nht_p.prefixlen = IPV4_MAX_BITLEN;
756 nht_p.u.prefix4 = rp_info->rp.rpf_addr.u.prefix4;
2dbe669b
DA
757 if (PIM_DEBUG_PIM_NHT_RP)
758 zlog_debug("%s: Deregister RP addr %pFX with Zebra ", __func__,
759 &nht_p);
4533b847 760 pim_delete_tracked_nexthop(pim, &nht_p, NULL, rp_info, false);
d62a17ae 761
e691f179
DS
762 if (!str2prefix("224.0.0.0/4", &g_all))
763 return PIM_RP_BAD_ADDRESS;
764
d9c9a9ee 765 rp_all = pim_rp_find_match_group(pim, &g_all);
d62a17ae 766
767 if (rp_all == rp_info) {
dd3364cb 768 frr_each (rb_pim_upstream, &pim->upstream_head, up) {
8cfd7268
SP
769 /* Find the upstream (*, G) whose upstream address is
770 * same as the deleted RP
771 */
d0e418b4 772 if ((up->upstream_addr.s_addr
773 == rp_info->rp.rpf_addr.u.prefix4.s_addr)
774 && (up->sg.src.s_addr == INADDR_ANY)) {
8cfd7268
SP
775 struct prefix grp;
776 grp.family = AF_INET;
777 grp.prefixlen = IPV4_MAX_BITLEN;
778 grp.u.prefix4 = up->sg.grp;
779 trp_info = pim_rp_find_match_group(pim, &grp);
780 if (trp_info == rp_all) {
781 pim_upstream_rpf_clear(pim, up);
782 up->upstream_addr.s_addr = INADDR_ANY;
783 }
784 }
785 }
d62a17ae 786 rp_all->rp.rpf_addr.family = AF_INET;
787 rp_all->rp.rpf_addr.u.prefix4.s_addr = INADDR_NONE;
788 rp_all->i_am_rp = 0;
789 return PIM_SUCCESS;
790 }
791
d9c9a9ee 792 listnode_delete(pim->rp_list, rp_info);
89b68082
DS
793
794 if (!was_plist) {
795 rn = route_node_get(pim->rp_table, &rp_info->group);
796 if (rn) {
797 if (rn->info != rp_info)
af4c2728 798 flog_err(
450971aa 799 EC_LIB_DEVELOPMENT,
3613d898 800 "Expected rn->info to be equal to rp_info");
89b68082 801
2dbe669b 802 if (PIM_DEBUG_PIM_TRACE)
996c9314 803 zlog_debug(
2dbe669b
DA
804 "%s:Found for Freeing: %p for rp_info: %p(%pFX) Lock: %d",
805 __func__, rn, rp_info, &rp_info->group,
c10e14e9 806 route_node_get_lock_count(rn));
2dbe669b 807
89b68082
DS
808 rn->info = NULL;
809 route_unlock_node(rn);
810 route_unlock_node(rn);
811 }
812 }
813
472ad383 814 pim_rp_refresh_group_to_rp_mapping(pim);
093c928f 815
dd3364cb 816 frr_each (rb_pim_upstream, &pim->upstream_head, up) {
8cfd7268
SP
817 /* Find the upstream (*, G) whose upstream address is same as
818 * the deleted RP
819 */
d0e418b4 820 if ((up->upstream_addr.s_addr
821 == rp_info->rp.rpf_addr.u.prefix4.s_addr)
822 && (up->sg.src.s_addr == INADDR_ANY)) {
8cfd7268
SP
823 struct prefix grp;
824
825 grp.family = AF_INET;
826 grp.prefixlen = IPV4_MAX_BITLEN;
827 grp.u.prefix4 = up->sg.grp;
828
829 trp_info = pim_rp_find_match_group(pim, &grp);
830
831 /* RP not found for the group grp */
832 if (pim_rpf_addr_is_inaddr_none(&trp_info->rp)) {
833 pim_upstream_rpf_clear(pim, up);
d0e418b4 834 pim_rp_set_upstream_addr(
835 pim, &up->upstream_addr, up->sg.src,
836 up->sg.grp);
8cfd7268
SP
837 }
838
839 /* RP found for the group grp */
840 else
841 pim_upstream_update(pim, up);
842 }
843 }
844
093c928f 845 XFREE(MTYPE_PIM_RP, rp_info);
d62a17ae 846 return PIM_SUCCESS;
75a26779 847}
13afbd05 848
d0e418b4 849int pim_rp_change(struct pim_instance *pim, struct in_addr new_rp_addr,
850 struct prefix group, enum rp_source rp_src_flag)
851{
852 struct prefix nht_p;
853 struct route_node *rn;
854 int result = 0;
855 struct rp_info *rp_info = NULL;
856 struct pim_upstream *up;
d0e418b4 857
858 rn = route_node_lookup(pim->rp_table, &group);
859 if (!rn) {
860 result = pim_rp_new(pim, new_rp_addr, group, NULL, rp_src_flag);
861 return result;
862 }
863
864 rp_info = rn->info;
865
866 if (!rp_info) {
867 route_unlock_node(rn);
868 result = pim_rp_new(pim, new_rp_addr, group, NULL, rp_src_flag);
869 return result;
870 }
871
872 if (rp_info->rp.rpf_addr.u.prefix4.s_addr == new_rp_addr.s_addr) {
873 if (rp_info->rp_src != rp_src_flag) {
874 rp_info->rp_src = rp_src_flag;
875 route_unlock_node(rn);
876 return PIM_SUCCESS;
877 }
878 }
879
35a30302
DS
880 nht_p.family = AF_INET;
881 nht_p.prefixlen = IPV4_MAX_BITLEN;
882
d0e418b4 883 /* Deregister old RP addr with Zebra NHT */
884 if (rp_info->rp.rpf_addr.u.prefix4.s_addr != INADDR_ANY) {
d0e418b4 885 nht_p.u.prefix4 = rp_info->rp.rpf_addr.u.prefix4;
2dbe669b
DA
886 if (PIM_DEBUG_PIM_NHT_RP)
887 zlog_debug("%s: Deregister RP addr %pFX with Zebra ",
888 __func__, &nht_p);
d0e418b4 889 pim_delete_tracked_nexthop(pim, &nht_p, NULL, rp_info, false);
890 }
891
892 pim_rp_nexthop_del(rp_info);
893 listnode_delete(pim->rp_list, rp_info);
894 /* Update the new RP address*/
895 rp_info->rp.rpf_addr.u.prefix4 = new_rp_addr;
896 rp_info->rp_src = rp_src_flag;
897 rp_info->i_am_rp = 0;
898
899 listnode_add_sort(pim->rp_list, rp_info);
900
dd3364cb 901 frr_each (rb_pim_upstream, &pim->upstream_head, up) {
d0e418b4 902 if (up->sg.src.s_addr == INADDR_ANY) {
903 struct prefix grp;
904 struct rp_info *trp_info;
905
906 grp.family = AF_INET;
907 grp.prefixlen = IPV4_MAX_BITLEN;
908 grp.u.prefix4 = up->sg.grp;
909 trp_info = pim_rp_find_match_group(pim, &grp);
910
911 if (trp_info == rp_info)
912 pim_upstream_update(pim, up);
913 }
914 }
915
916 /* Register new RP addr with Zebra NHT */
917 nht_p.u.prefix4 = rp_info->rp.rpf_addr.u.prefix4;
2dbe669b
DA
918 if (PIM_DEBUG_PIM_NHT_RP)
919 zlog_debug("%s: NHT Register RP addr %pFX grp %pFX with Zebra ",
920 __func__, &nht_p, &rp_info->group);
d0e418b4 921
922 pim_find_or_track_nexthop(pim, &nht_p, NULL, rp_info, false, NULL);
923 if (!pim_ecmp_nexthop_lookup(pim, &rp_info->rp.source_nexthop, &nht_p,
924 &rp_info->group, 1)) {
925 route_unlock_node(rn);
926 return PIM_RP_NO_PATH;
927 }
928
929 pim_rp_check_interfaces(pim, rp_info);
930
931 route_unlock_node(rn);
932
933 pim_rp_refresh_group_to_rp_mapping(pim);
934
935 return result;
936}
937
fec883d9 938void pim_rp_setup(struct pim_instance *pim)
13afbd05 939{
d62a17ae 940 struct listnode *node;
941 struct rp_info *rp_info;
d62a17ae 942 struct prefix nht_p;
d62a17ae 943
d9c9a9ee 944 for (ALL_LIST_ELEMENTS_RO(pim->rp_list, node, rp_info)) {
d62a17ae 945 if (rp_info->rp.rpf_addr.u.prefix4.s_addr == INADDR_NONE)
946 continue;
947
948 nht_p.family = AF_INET;
949 nht_p.prefixlen = IPV4_MAX_BITLEN;
950 nht_p.u.prefix4 = rp_info->rp.rpf_addr.u.prefix4;
8cfd7268 951
4533b847 952 pim_find_or_track_nexthop(pim, &nht_p, NULL, rp_info, false,
953 NULL);
43763b11
DS
954 if (!pim_ecmp_nexthop_lookup(pim, &rp_info->rp.source_nexthop,
955 &nht_p, &rp_info->group, 1))
956 if (PIM_DEBUG_PIM_NHT_RP)
d62a17ae 957 zlog_debug(
43763b11 958 "Unable to lookup nexthop for rp specified");
d62a17ae 959 }
13afbd05
DS
960}
961
54b97c74 962/*
7176984f 963 * Checks to see if we should elect ourself the actual RP when new if
964 * addresses are added against an interface.
54b97c74 965 */
d62a17ae 966void pim_rp_check_on_if_add(struct pim_interface *pim_ifp)
54b97c74 967{
d62a17ae 968 struct listnode *node;
969 struct rp_info *rp_info;
970 bool i_am_rp_changed = false;
d9c9a9ee 971 struct pim_instance *pim = pim_ifp->pim;
d62a17ae 972
d9c9a9ee 973 if (pim->rp_list == NULL)
d62a17ae 974 return;
975
d9c9a9ee 976 for (ALL_LIST_ELEMENTS_RO(pim->rp_list, node, rp_info)) {
d62a17ae 977 if (pim_rpf_addr_is_inaddr_none(&rp_info->rp))
978 continue;
979
980 /* if i_am_rp is already set nothing to be done (adding new
981 * addresses
982 * is not going to make a difference). */
983 if (rp_info->i_am_rp) {
984 continue;
985 }
986
987 if (pim_rp_check_interface_addrs(rp_info, pim_ifp)) {
988 i_am_rp_changed = true;
989 rp_info->i_am_rp = 1;
3d225d48 990 if (PIM_DEBUG_PIM_NHT_RP) {
d62a17ae 991 char rp[PREFIX_STRLEN];
992 pim_addr_dump("<rp?>", &rp_info->rp.rpf_addr,
993 rp, sizeof(rp));
994 zlog_debug("%s: %s: i am rp", __func__, rp);
995 }
996 }
997 }
998
999 if (i_am_rp_changed) {
472ad383 1000 pim_msdp_i_am_rp_changed(pim);
a749b900 1001 pim_upstream_reeval_use_rpt(pim);
d62a17ae 1002 }
7176984f 1003}
36d6bd7d 1004
7176984f 1005/* up-optimized re-evaluation of "i_am_rp". this is used when ifaddresses
1006 * are removed. Removing numbers is an uncommon event in an active network
1007 * so I have made no attempt to optimize it. */
fec883d9 1008void pim_i_am_rp_re_evaluate(struct pim_instance *pim)
7176984f 1009{
d62a17ae 1010 struct listnode *node;
1011 struct rp_info *rp_info;
1012 bool i_am_rp_changed = false;
1013 int old_i_am_rp;
1014
d9c9a9ee 1015 if (pim->rp_list == NULL)
d62a17ae 1016 return;
1017
d9c9a9ee 1018 for (ALL_LIST_ELEMENTS_RO(pim->rp_list, node, rp_info)) {
d62a17ae 1019 if (pim_rpf_addr_is_inaddr_none(&rp_info->rp))
1020 continue;
1021
1022 old_i_am_rp = rp_info->i_am_rp;
fec883d9 1023 pim_rp_check_interfaces(pim, rp_info);
d62a17ae 1024
1025 if (old_i_am_rp != rp_info->i_am_rp) {
1026 i_am_rp_changed = true;
3d225d48 1027 if (PIM_DEBUG_PIM_NHT_RP) {
d62a17ae 1028 char rp[PREFIX_STRLEN];
1029 pim_addr_dump("<rp?>", &rp_info->rp.rpf_addr,
1030 rp, sizeof(rp));
1031 if (rp_info->i_am_rp) {
1032 zlog_debug("%s: %s: i am rp", __func__,
1033 rp);
1034 } else {
1035 zlog_debug("%s: %s: i am no longer rp",
1036 __func__, rp);
1037 }
1038 }
1039 }
1040 }
1041
1042 if (i_am_rp_changed) {
472ad383 1043 pim_msdp_i_am_rp_changed(pim);
a749b900 1044 pim_upstream_reeval_use_rpt(pim);
d62a17ae 1045 }
54b97c74
DS
1046}
1047
1048/*
1049 * I_am_RP(G) is true if the group-to-RP mapping indicates that
1050 * this router is the RP for the group.
1051 *
1052 * Since we only have static RP, all groups are part of this RP
1053 */
d9c9a9ee 1054int pim_rp_i_am_rp(struct pim_instance *pim, struct in_addr group)
54b97c74 1055{
d62a17ae 1056 struct prefix g;
1057 struct rp_info *rp_info;
36d6bd7d 1058
d62a17ae 1059 memset(&g, 0, sizeof(g));
1060 g.family = AF_INET;
12256b84 1061 g.prefixlen = IPV4_MAX_BITLEN;
d62a17ae 1062 g.u.prefix4 = group;
36d6bd7d 1063
d9c9a9ee 1064 rp_info = pim_rp_find_match_group(pim, &g);
36d6bd7d 1065
d62a17ae 1066 if (rp_info)
1067 return rp_info->i_am_rp;
36d6bd7d 1068
d62a17ae 1069 return 0;
54b97c74
DS
1070}
1071
71694057
DS
1072/*
1073 * RP(G)
1074 *
1075 * Return the RP that the Group belongs too.
1076 */
fec883d9 1077struct pim_rpf *pim_rp_g(struct pim_instance *pim, struct in_addr group)
71694057 1078{
d62a17ae 1079 struct prefix g;
1080 struct rp_info *rp_info;
1081
1082 memset(&g, 0, sizeof(g));
1083 g.family = AF_INET;
12256b84 1084 g.prefixlen = IPV4_MAX_BITLEN;
d62a17ae 1085 g.u.prefix4 = group;
1086
d9c9a9ee 1087 rp_info = pim_rp_find_match_group(pim, &g);
d62a17ae 1088
1089 if (rp_info) {
1090 struct prefix nht_p;
43763b11 1091
d62a17ae 1092 /* Register addr with Zebra NHT */
1093 nht_p.family = AF_INET;
1094 nht_p.prefixlen = IPV4_MAX_BITLEN;
1095 nht_p.u.prefix4 = rp_info->rp.rpf_addr.u.prefix4;
2dbe669b 1096 if (PIM_DEBUG_PIM_NHT_RP)
d62a17ae 1097 zlog_debug(
2dbe669b
DA
1098 "%s: NHT Register RP addr %pFX grp %pFX with Zebra",
1099 __func__, &nht_p, &rp_info->group);
4533b847 1100 pim_find_or_track_nexthop(pim, &nht_p, NULL, rp_info, false,
1101 NULL);
43763b11
DS
1102 pim_rpf_set_refresh_time(pim);
1103 (void)pim_ecmp_nexthop_lookup(pim, &rp_info->rp.source_nexthop,
1104 &nht_p, &rp_info->group, 1);
d62a17ae 1105 return (&rp_info->rp);
1106 }
1107
1108 // About to Go Down
1109 return NULL;
71694057
DS
1110}
1111
8f5f5e91
DS
1112/*
1113 * Set the upstream IP address we want to talk to based upon
1114 * the rp configured and the source address
1115 *
1116 * If we have don't have a RP configured and the source address is *
732c209c 1117 * then set the upstream addr as INADDR_ANY and return failure.
8f5f5e91
DS
1118 *
1119 */
d9c9a9ee
DS
1120int pim_rp_set_upstream_addr(struct pim_instance *pim, struct in_addr *up,
1121 struct in_addr source, struct in_addr group)
8f5f5e91 1122{
d62a17ae 1123 struct rp_info *rp_info;
1124 struct prefix g;
36d6bd7d 1125
d62a17ae 1126 memset(&g, 0, sizeof(g));
1127 g.family = AF_INET;
12256b84 1128 g.prefixlen = IPV4_MAX_BITLEN;
d62a17ae 1129 g.u.prefix4 = group;
36d6bd7d 1130
d9c9a9ee 1131 rp_info = pim_rp_find_match_group(pim, &g);
36d6bd7d 1132
b1945363
DS
1133 if (!rp_info || ((pim_rpf_addr_is_inaddr_none(&rp_info->rp))
1134 && (source.s_addr == INADDR_ANY))) {
3d225d48 1135 if (PIM_DEBUG_PIM_NHT_RP)
d62a17ae 1136 zlog_debug("%s: Received a (*,G) with no RP configured",
15569c58 1137 __func__);
732c209c 1138 up->s_addr = INADDR_ANY;
d62a17ae 1139 return 0;
1140 }
8f5f5e91 1141
d62a17ae 1142 *up = (source.s_addr == INADDR_ANY) ? rp_info->rp.rpf_addr.u.prefix4
1143 : source;
8f5f5e91 1144
d62a17ae 1145 return 1;
8f5f5e91 1146}
75a26779 1147
0c8b717e
DS
1148int pim_rp_config_write(struct pim_instance *pim, struct vty *vty,
1149 const char *spaces)
75a26779 1150{
d62a17ae 1151 struct listnode *node;
1152 struct rp_info *rp_info;
1153 char rp_buffer[32];
d62a17ae 1154 int count = 0;
1155
d9c9a9ee 1156 for (ALL_LIST_ELEMENTS_RO(pim->rp_list, node, rp_info)) {
d62a17ae 1157 if (pim_rpf_addr_is_inaddr_none(&rp_info->rp))
1158 continue;
1159
d0e418b4 1160 if (rp_info->rp_src == RP_SRC_BSR)
1161 continue;
1162
d62a17ae 1163 if (rp_info->plist)
0c8b717e 1164 vty_out(vty, "%sip pim rp %s prefix-list %s\n", spaces,
d62a17ae 1165 inet_ntop(AF_INET,
1166 &rp_info->rp.rpf_addr.u.prefix4,
1167 rp_buffer, 32),
1168 rp_info->plist);
1169 else
2dbe669b 1170 vty_out(vty, "%sip pim rp %s %pFX\n", spaces,
d62a17ae 1171 inet_ntop(AF_INET,
1172 &rp_info->rp.rpf_addr.u.prefix4,
1173 rp_buffer, 32),
2dbe669b 1174 &rp_info->group);
d62a17ae 1175 count++;
1176 }
1177
1178 return count;
75a26779
DS
1179}
1180
f43593d9
DS
1181bool pim_rp_check_is_my_ip_address(struct pim_instance *pim,
1182 struct in_addr dest_addr)
75a26779 1183{
d3cc1e45 1184 if (if_lookup_exact_address(&dest_addr, AF_INET, pim->vrf->vrf_id))
f43593d9 1185 return true;
d62a17ae 1186
f43593d9 1187 return false;
75a26779 1188}
00d07c6f 1189
088f1098 1190void pim_rp_show_information(struct pim_instance *pim, struct vty *vty, bool uj)
00d07c6f 1191{
d62a17ae 1192 struct rp_info *rp_info;
1193 struct rp_info *prev_rp_info = NULL;
1194 struct listnode *node;
025725f7 1195 char source[7];
ee2bbf7c 1196 char buf[PREFIX_STRLEN];
d62a17ae 1197
1198 json_object *json = NULL;
1199 json_object *json_rp_rows = NULL;
1200 json_object *json_row = NULL;
1201
1202 if (uj)
1203 json = json_object_new_object();
1204 else
1205 vty_out(vty,
d6593fc5 1206 "RP address group/prefix-list OIF I am RP Source\n");
d9c9a9ee 1207 for (ALL_LIST_ELEMENTS_RO(pim->rp_list, node, rp_info)) {
d62a17ae 1208 if (!pim_rpf_addr_is_inaddr_none(&rp_info->rp)) {
1209 char buf[48];
1210
025725f7 1211 if (rp_info->rp_src == RP_SRC_STATIC)
96e43299 1212 strlcpy(source, "Static", sizeof(source));
025725f7 1213 else if (rp_info->rp_src == RP_SRC_BSR)
96e43299 1214 strlcpy(source, "BSR", sizeof(source));
025725f7 1215 else
96e43299 1216 strlcpy(source, "None", sizeof(source));
d62a17ae 1217 if (uj) {
1218 /*
1219 * If we have moved on to a new RP then add the
1220 * entry for the previous RP
1221 */
1222 if (prev_rp_info
1223 && prev_rp_info->rp.rpf_addr.u.prefix4
1224 .s_addr
1225 != rp_info->rp.rpf_addr.u.prefix4
1226 .s_addr) {
1227 json_object_object_add(
1228 json,
ee2bbf7c
MS
1229 inet_ntop(AF_INET,
1230 &prev_rp_info->rp
d62a17ae 1231 .rpf_addr.u
ee2bbf7c
MS
1232 .prefix4,
1233 buf, sizeof(buf)),
d62a17ae 1234 json_rp_rows);
1235 json_rp_rows = NULL;
1236 }
1237
1238 if (!json_rp_rows)
1239 json_rp_rows = json_object_new_array();
1240
1241 json_row = json_object_new_object();
ac8e400c
SP
1242 json_object_string_add(
1243 json_row, "rpAddress",
ee2bbf7c
MS
1244 inet_ntop(AF_INET,
1245 &rp_info->rp.rpf_addr.u
1246 .prefix4,
1247 buf, sizeof(buf)));
d62a17ae 1248 if (rp_info->rp.source_nexthop.interface)
1249 json_object_string_add(
1250 json_row, "outboundInterface",
1251 rp_info->rp.source_nexthop
1252 .interface->name);
a7a5472e
SP
1253 else
1254 json_object_string_add(
1255 json_row, "outboundInterface",
1256 "Unknown");
d62a17ae 1257 if (rp_info->i_am_rp)
1258 json_object_boolean_true_add(json_row,
1259 "iAmRP");
a7a5472e
SP
1260 else
1261 json_object_boolean_false_add(json_row,
1262 "iAmRP");
d62a17ae 1263
1264 if (rp_info->plist)
1265 json_object_string_add(json_row,
1266 "prefixList",
1267 rp_info->plist);
1268 else
1269 json_object_string_add(
1270 json_row, "group",
1271 prefix2str(&rp_info->group, buf,
1272 48));
d0e418b4 1273 json_object_string_add(json_row, "source",
025725f7 1274 source);
d62a17ae 1275
1276 json_object_array_add(json_rp_rows, json_row);
1277 } else {
1278 vty_out(vty, "%-15s ",
ee2bbf7c
MS
1279 inet_ntop(AF_INET,
1280 &rp_info->rp.rpf_addr.u
1281 .prefix4,
1282 buf, sizeof(buf)));
d62a17ae 1283
1284 if (rp_info->plist)
1285 vty_out(vty, "%-18s ", rp_info->plist);
1286 else
2dbe669b
DA
1287 vty_out(vty, "%-18pFX ",
1288 &rp_info->group);
d62a17ae 1289
1290 if (rp_info->rp.source_nexthop.interface)
ff415346 1291 vty_out(vty, "%-16s ",
d62a17ae 1292 rp_info->rp.source_nexthop
1293 .interface->name);
1294 else
ff415346 1295 vty_out(vty, "%-16s ", "(Unknown)");
d62a17ae 1296
1297 if (rp_info->i_am_rp)
d6593fc5 1298 vty_out(vty, "yes");
d62a17ae 1299 else
025725f7 1300 vty_out(vty, "no");
d62a17ae 1301
025725f7 1302 vty_out(vty, "%14s\n", source);
1303 }
d62a17ae 1304 prev_rp_info = rp_info;
1305 }
1306 }
1307
1308 if (uj) {
1309 if (prev_rp_info && json_rp_rows)
1310 json_object_object_add(
1311 json,
ee2bbf7c
MS
1312 inet_ntop(AF_INET,
1313 &prev_rp_info->rp.rpf_addr.u.prefix4,
1314 buf, sizeof(buf)),
d62a17ae 1315 json_rp_rows);
1316
9d303b37
DL
1317 vty_out(vty, "%s\n", json_object_to_json_string_ext(
1318 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 1319 json_object_free(json);
1320 }
00d07c6f 1321}
cba44481 1322
c9cd7fbc 1323void pim_resolve_rp_nh(struct pim_instance *pim, struct pim_neighbor *nbr)
cba44481 1324{
d62a17ae 1325 struct listnode *node = NULL;
1326 struct rp_info *rp_info = NULL;
1327 struct nexthop *nh_node = NULL;
1328 struct prefix nht_p;
1329 struct pim_nexthop_cache pnc;
d62a17ae 1330
d9c9a9ee 1331 for (ALL_LIST_ELEMENTS_RO(pim->rp_list, node, rp_info)) {
d62a17ae 1332 if (rp_info->rp.rpf_addr.u.prefix4.s_addr == INADDR_NONE)
1333 continue;
1334
1335 nht_p.family = AF_INET;
1336 nht_p.prefixlen = IPV4_MAX_BITLEN;
1337 nht_p.u.prefix4 = rp_info->rp.rpf_addr.u.prefix4;
1338 memset(&pnc, 0, sizeof(struct pim_nexthop_cache));
fec883d9 1339 if (!pim_find_or_track_nexthop(pim, &nht_p, NULL, rp_info,
4533b847 1340 false, &pnc))
cb9c7c50
DS
1341 continue;
1342
1343 for (nh_node = pnc.nexthop; nh_node; nh_node = nh_node->next) {
3a6290bd 1344 if (nh_node->gate.ipv4.s_addr != INADDR_ANY)
cb9c7c50
DS
1345 continue;
1346
1347 struct interface *ifp1 = if_lookup_by_index(
d3cc1e45 1348 nh_node->ifindex, pim->vrf->vrf_id);
c9cd7fbc
DS
1349
1350 if (nbr->interface != ifp1)
cb9c7c50
DS
1351 continue;
1352
1353 nh_node->gate.ipv4 = nbr->source_addr;
3d225d48 1354 if (PIM_DEBUG_PIM_NHT_RP) {
cb9c7c50
DS
1355 char str[PREFIX_STRLEN];
1356 char str1[INET_ADDRSTRLEN];
1357 pim_inet4_dump("<nht_nbr?>", nbr->source_addr,
1358 str1, sizeof(str1));
1359 pim_addr_dump("<nht_addr?>", &nht_p, str,
1360 sizeof(str));
1361 zlog_debug(
1362 "%s: addr %s new nexthop addr %s interface %s",
5e81f5dd 1363 __func__, str, str1, ifp1->name);
d62a17ae 1364 }
1365 }
1366 }
cba44481 1367}