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