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