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