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