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