3 * Copyright (C) 2015 Cumulus Networks, Inc.
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.
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.
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
34 #include "lib_errors.h"
39 #include "pim_iface.h"
44 #include "pim_memory.h"
45 #include "pim_iface.h"
48 #include "pim_mroute.h"
50 #include "pim_zebra.h"
53 /* Cleanup pim->rpf_hash each node data */
54 void pim_rp_list_hash_clean(void *data
)
56 struct pim_nexthop_cache
*pnc
= (struct pim_nexthop_cache
*)data
;
58 list_delete(&pnc
->rp_list
);
60 hash_clean(pnc
->upstream_hash
, NULL
);
61 hash_free(pnc
->upstream_hash
);
62 pnc
->upstream_hash
= NULL
;
64 nexthops_free(pnc
->nexthop
);
66 XFREE(MTYPE_PIM_NEXTHOP_CACHE
, pnc
);
69 static void pim_rp_info_free(struct rp_info
*rp_info
)
71 XFREE(MTYPE_PIM_FILTER_NAME
, rp_info
->plist
);
73 XFREE(MTYPE_PIM_RP
, rp_info
);
76 int pim_rp_list_cmp(void *v1
, void *v2
)
78 struct rp_info
*rp1
= (struct rp_info
*)v1
;
79 struct rp_info
*rp2
= (struct rp_info
*)v2
;
82 * Sort by RP IP address
84 if (rp1
->rp
.rpf_addr
.u
.prefix4
.s_addr
85 < rp2
->rp
.rpf_addr
.u
.prefix4
.s_addr
)
88 if (rp1
->rp
.rpf_addr
.u
.prefix4
.s_addr
89 > rp2
->rp
.rpf_addr
.u
.prefix4
.s_addr
)
93 * Sort by group IP address
95 if (rp1
->group
.u
.prefix4
.s_addr
< rp2
->group
.u
.prefix4
.s_addr
)
98 if (rp1
->group
.u
.prefix4
.s_addr
> rp2
->group
.u
.prefix4
.s_addr
)
104 void pim_rp_init(struct pim_instance
*pim
)
106 struct rp_info
*rp_info
;
107 struct route_node
*rn
;
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
;
113 pim
->rp_table
= route_table_init();
115 rp_info
= XCALLOC(MTYPE_PIM_RP
, sizeof(*rp_info
));
117 if (!str2prefix("224.0.0.0/4", &rp_info
->group
)) {
118 flog_err(EC_LIB_DEVELOPMENT
,
119 "Unable to convert 224.0.0.0/4 to prefix");
120 list_delete(&pim
->rp_list
);
121 route_table_finish(pim
->rp_table
);
122 XFREE(MTYPE_PIM_RP
, rp_info
);
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
;
130 listnode_add(pim
->rp_list
, rp_info
);
132 rn
= route_node_get(pim
->rp_table
, &rp_info
->group
);
134 if (PIM_DEBUG_PIM_TRACE
)
136 "Allocated: %p for rp_info: %p(224.0.0.0/4) Lock: %d",
137 rn
, rp_info
, rn
->lock
);
140 void pim_rp_free(struct pim_instance
*pim
)
143 list_delete(&pim
->rp_list
);
145 route_table_finish(pim
->rp_table
);
146 pim
->rp_table
= NULL
;
150 * Given an RP's prefix-list, return the RP's rp_info for that prefix-list
152 static struct rp_info
*pim_rp_find_prefix_list(struct pim_instance
*pim
,
156 struct listnode
*node
;
157 struct rp_info
*rp_info
;
159 for (ALL_LIST_ELEMENTS_RO(pim
->rp_list
, node
, rp_info
)) {
160 if (rp
.s_addr
== rp_info
->rp
.rpf_addr
.u
.prefix4
.s_addr
161 && rp_info
->plist
&& strcmp(rp_info
->plist
, plist
) == 0) {
170 * Return true if plist is used by any rp_info
172 static int pim_rp_prefix_list_used(struct pim_instance
*pim
, const char *plist
)
174 struct listnode
*node
;
175 struct rp_info
*rp_info
;
177 for (ALL_LIST_ELEMENTS_RO(pim
->rp_list
, node
, rp_info
)) {
178 if (rp_info
->plist
&& strcmp(rp_info
->plist
, plist
) == 0) {
187 * Given an RP's address, return the RP's rp_info that is an exact match for
190 static struct rp_info
*pim_rp_find_exact(struct pim_instance
*pim
,
192 const struct prefix
*group
)
194 struct listnode
*node
;
195 struct rp_info
*rp_info
;
197 for (ALL_LIST_ELEMENTS_RO(pim
->rp_list
, node
, rp_info
)) {
198 if (rp
.s_addr
== rp_info
->rp
.rpf_addr
.u
.prefix4
.s_addr
199 && prefix_same(&rp_info
->group
, group
))
207 * Given a group, return the rp_info for that group
209 struct rp_info
*pim_rp_find_match_group(struct pim_instance
*pim
,
210 const struct prefix
*group
)
212 struct listnode
*node
;
213 struct rp_info
*best
= NULL
;
214 struct rp_info
*rp_info
;
215 struct prefix_list
*plist
;
216 const struct prefix
*p
, *bp
;
217 struct route_node
*rn
;
220 for (ALL_LIST_ELEMENTS_RO(pim
->rp_list
, node
, rp_info
)) {
221 if (rp_info
->plist
) {
222 plist
= prefix_list_lookup(AFI_IP
, rp_info
->plist
);
224 if (prefix_list_apply_which_prefix(plist
, &p
, group
)
234 if (bp
&& bp
->prefixlen
< p
->prefixlen
) {
241 rn
= route_node_match(pim
->rp_table
, group
);
245 "%s: BUG We should have found default group information\n",
251 if (PIM_DEBUG_PIM_TRACE
) {
252 char buf
[PREFIX_STRLEN
];
254 zlog_debug("Lookedup: %p for rp_info: %p(%s) Lock: %d", rn
,
256 prefix2str(&rp_info
->group
, buf
, sizeof(buf
)),
260 route_unlock_node(rn
);
265 if (rp_info
->group
.prefixlen
< best
->group
.prefixlen
)
272 * When the user makes "ip pim rp" configuration changes or if they change the
273 * prefix-list(s) used by these statements we must tickle the upstream state
274 * for each group to make them re-lookup who their RP should be.
276 * This is a placeholder function for now.
278 static void pim_rp_refresh_group_to_rp_mapping(struct pim_instance
*pim
)
280 pim_msdp_i_am_rp_changed(pim
);
281 pim_upstream_reeval_use_rpt(pim
);
284 void pim_rp_prefix_list_update(struct pim_instance
*pim
,
285 struct prefix_list
*plist
)
287 struct listnode
*node
;
288 struct rp_info
*rp_info
;
289 int refresh_needed
= 0;
291 for (ALL_LIST_ELEMENTS_RO(pim
->rp_list
, node
, rp_info
)) {
293 && strcmp(rp_info
->plist
, prefix_list_name(plist
)) == 0) {
300 pim_rp_refresh_group_to_rp_mapping(pim
);
303 static int pim_rp_check_interface_addrs(struct rp_info
*rp_info
,
304 struct pim_interface
*pim_ifp
)
306 struct listnode
*node
;
307 struct pim_secondary_addr
*sec_addr
;
309 if (pim_ifp
->primary_address
.s_addr
310 == rp_info
->rp
.rpf_addr
.u
.prefix4
.s_addr
)
313 if (!pim_ifp
->sec_addr_list
) {
317 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->sec_addr_list
, node
, sec_addr
)) {
318 if (prefix_same(&sec_addr
->addr
, &rp_info
->rp
.rpf_addr
)) {
326 static void pim_rp_check_interfaces(struct pim_instance
*pim
,
327 struct rp_info
*rp_info
)
329 struct interface
*ifp
;
331 rp_info
->i_am_rp
= 0;
332 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
333 struct pim_interface
*pim_ifp
= ifp
->info
;
338 if (pim_rp_check_interface_addrs(rp_info
, pim_ifp
)) {
339 rp_info
->i_am_rp
= 1;
344 void pim_upstream_update(struct pim_instance
*pim
, struct pim_upstream
*up
)
346 struct pim_rpf old_rpf
;
347 enum pim_rpf_result rpf_result
;
348 struct in_addr old_upstream_addr
;
349 struct in_addr new_upstream_addr
;
352 old_upstream_addr
= up
->upstream_addr
;
353 pim_rp_set_upstream_addr(pim
, &new_upstream_addr
, up
->sg
.src
,
356 if (PIM_DEBUG_PIM_TRACE
)
357 zlog_debug("%s: pim upstream update for old upstream %s",
358 __func__
, inet_ntoa(old_upstream_addr
));
360 if (old_upstream_addr
.s_addr
== new_upstream_addr
.s_addr
)
363 /* Lets consider a case, where a PIM upstream has a better RP as a
364 * result of a new RP configuration with more precise group range.
365 * This upstream has to be added to the upstream hash of new RP's
366 * NHT(pnc) and has to be removed from old RP's NHT upstream hash
368 if (old_upstream_addr
.s_addr
!= INADDR_ANY
) {
369 /* Deregister addr with Zebra NHT */
370 nht_p
.family
= AF_INET
;
371 nht_p
.prefixlen
= IPV4_MAX_BITLEN
;
372 nht_p
.u
.prefix4
= old_upstream_addr
;
373 if (PIM_DEBUG_PIM_TRACE
) {
374 char buf
[PREFIX2STR_BUFFER
];
376 prefix2str(&nht_p
, buf
, sizeof(buf
));
378 "%s: Deregister upstream %s addr %s with Zebra NHT",
379 __func__
, up
->sg_str
, buf
);
381 pim_delete_tracked_nexthop(pim
, &nht_p
, up
, NULL
, false);
384 /* Update the upstream address */
385 up
->upstream_addr
= new_upstream_addr
;
387 old_rpf
.source_nexthop
.interface
= up
->rpf
.source_nexthop
.interface
;
389 rpf_result
= pim_rpf_update(pim
, up
, &old_rpf
, __func__
);
390 if (rpf_result
== PIM_RPF_FAILURE
)
391 pim_mroute_del(up
->channel_oil
, __func__
);
393 /* update kernel multicast forwarding cache (MFC) */
394 if (up
->rpf
.source_nexthop
.interface
&& up
->channel_oil
)
395 pim_upstream_mroute_iif_update(up
->channel_oil
, __func__
);
397 if (rpf_result
== PIM_RPF_CHANGED
||
398 (rpf_result
== PIM_RPF_FAILURE
&&
399 old_rpf
.source_nexthop
.interface
))
400 pim_zebra_upstream_rpf_changed(pim
, up
, &old_rpf
);
402 pim_zebra_update_all_interfaces(pim
);
405 int pim_rp_new_config(struct pim_instance
*pim
, const char *rp
,
406 const char *group_range
, const char *plist
)
410 struct in_addr rp_addr
;
412 if (group_range
== NULL
)
413 result
= str2prefix("224.0.0.0/4", &group
);
415 result
= str2prefix(group_range
, &group
);
419 prefix_copy(&temp
, &group
);
421 if (!prefix_same(&group
, &temp
))
422 return PIM_GROUP_BAD_ADDR_MASK_COMBO
;
427 return PIM_GROUP_BAD_ADDRESS
;
429 result
= inet_pton(AF_INET
, rp
, &rp_addr
);
432 return PIM_RP_BAD_ADDRESS
;
434 result
= pim_rp_new(pim
, rp_addr
, group
, plist
, RP_SRC_STATIC
);
438 int pim_rp_new(struct pim_instance
*pim
, struct in_addr rp_addr
,
439 struct prefix group
, const char *plist
,
440 enum rp_source rp_src_flag
)
443 char rp
[INET_ADDRSTRLEN
];
444 struct rp_info
*rp_info
;
445 struct rp_info
*rp_all
;
446 struct prefix group_all
;
447 struct listnode
*node
, *nnode
;
448 struct rp_info
*tmp_rp_info
;
451 struct route_node
*rn
;
452 struct pim_upstream
*up
;
454 if (rp_addr
.s_addr
== INADDR_ANY
||
455 rp_addr
.s_addr
== INADDR_NONE
)
456 return PIM_RP_BAD_ADDRESS
;
458 rp_info
= XCALLOC(MTYPE_PIM_RP
, sizeof(*rp_info
));
460 rp_info
->rp
.rpf_addr
.family
= AF_INET
;
461 rp_info
->rp
.rpf_addr
.prefixlen
= IPV4_MAX_PREFIXLEN
;
462 rp_info
->rp
.rpf_addr
.u
.prefix4
= rp_addr
;
463 prefix_copy(&rp_info
->group
, &group
);
464 rp_info
->rp_src
= rp_src_flag
;
466 inet_ntop(AF_INET
, &rp_info
->rp
.rpf_addr
.u
.prefix4
, rp
, sizeof(rp
));
470 * Return if the prefix-list is already configured for this RP
472 if (pim_rp_find_prefix_list(pim
, rp_info
->rp
.rpf_addr
.u
.prefix4
,
474 XFREE(MTYPE_PIM_RP
, rp_info
);
479 * Barf if the prefix-list is already configured for an RP
481 if (pim_rp_prefix_list_used(pim
, plist
)) {
482 XFREE(MTYPE_PIM_RP
, rp_info
);
483 return PIM_RP_PFXLIST_IN_USE
;
487 * Free any existing rp_info entries for this RP
489 for (ALL_LIST_ELEMENTS(pim
->rp_list
, node
, nnode
,
491 if (rp_info
->rp
.rpf_addr
.u
.prefix4
.s_addr
492 == tmp_rp_info
->rp
.rpf_addr
.u
.prefix4
.s_addr
) {
493 if (tmp_rp_info
->plist
)
494 pim_rp_del_config(pim
, rp
, NULL
,
499 prefix2str(&tmp_rp_info
->group
,
505 rp_info
->plist
= XSTRDUP(MTYPE_PIM_FILTER_NAME
, plist
);
508 if (!str2prefix("224.0.0.0/4", &group_all
)) {
509 XFREE(MTYPE_PIM_RP
, rp_info
);
510 return PIM_GROUP_BAD_ADDRESS
;
512 rp_all
= pim_rp_find_match_group(pim
, &group_all
);
515 * Barf if group is a non-multicast subnet
517 if (!prefix_match(&rp_all
->group
, &rp_info
->group
)) {
518 XFREE(MTYPE_PIM_RP
, rp_info
);
519 return PIM_GROUP_BAD_ADDRESS
;
523 * Remove any prefix-list rp_info entries for this RP
525 for (ALL_LIST_ELEMENTS(pim
->rp_list
, node
, nnode
,
527 if (tmp_rp_info
->plist
528 && rp_info
->rp
.rpf_addr
.u
.prefix4
.s_addr
529 == tmp_rp_info
->rp
.rpf_addr
.u
.prefix4
531 pim_rp_del_config(pim
, rp
, NULL
,
537 * Take over the 224.0.0.0/4 group if the rp is INADDR_NONE
539 if (prefix_same(&rp_all
->group
, &rp_info
->group
)
540 && pim_rpf_addr_is_inaddr_none(&rp_all
->rp
)) {
541 rp_all
->rp
.rpf_addr
= rp_info
->rp
.rpf_addr
;
542 rp_all
->rp_src
= rp_src_flag
;
543 XFREE(MTYPE_PIM_RP
, rp_info
);
545 /* Register addr with Zebra NHT */
546 nht_p
.family
= AF_INET
;
547 nht_p
.prefixlen
= IPV4_MAX_BITLEN
;
549 rp_all
->rp
.rpf_addr
.u
.prefix4
; // RP address
550 if (PIM_DEBUG_PIM_NHT_RP
) {
551 char buf
[PREFIX2STR_BUFFER
];
552 char buf1
[PREFIX2STR_BUFFER
];
553 prefix2str(&nht_p
, buf
, sizeof(buf
));
554 prefix2str(&rp_all
->group
, buf1
, sizeof(buf1
));
556 "%s: NHT Register rp_all addr %s grp %s ",
557 __func__
, buf
, buf1
);
560 frr_each (rb_pim_upstream
, &pim
->upstream_head
, up
) {
561 /* Find (*, G) upstream whose RP is not
564 if ((up
->upstream_addr
.s_addr
== INADDR_ANY
)
565 && (up
->sg
.src
.s_addr
== INADDR_ANY
)) {
567 struct rp_info
*trp_info
;
569 grp
.family
= AF_INET
;
570 grp
.prefixlen
= IPV4_MAX_BITLEN
;
571 grp
.u
.prefix4
= up
->sg
.grp
;
572 trp_info
= pim_rp_find_match_group(
574 if (trp_info
== rp_all
)
575 pim_upstream_update(pim
, up
);
579 pim_rp_check_interfaces(pim
, rp_all
);
580 pim_rp_refresh_group_to_rp_mapping(pim
);
581 pim_find_or_track_nexthop(pim
, &nht_p
, NULL
, rp_all
,
584 if (!pim_ecmp_nexthop_lookup(pim
,
585 &rp_all
->rp
.source_nexthop
,
586 &nht_p
, &rp_all
->group
, 1))
587 return PIM_RP_NO_PATH
;
592 * Return if the group is already configured for this RP
594 tmp_rp_info
= pim_rp_find_exact(
595 pim
, rp_info
->rp
.rpf_addr
.u
.prefix4
, &rp_info
->group
);
597 if ((tmp_rp_info
->rp_src
!= rp_src_flag
)
598 && (rp_src_flag
== RP_SRC_STATIC
))
599 tmp_rp_info
->rp_src
= rp_src_flag
;
600 XFREE(MTYPE_PIM_RP
, rp_info
);
605 * Barf if this group is already covered by some other RP
607 tmp_rp_info
= pim_rp_find_match_group(pim
, &rp_info
->group
);
610 if (tmp_rp_info
->plist
) {
611 XFREE(MTYPE_PIM_RP
, rp_info
);
612 return PIM_GROUP_PFXLIST_OVERLAP
;
615 * If the only RP that covers this group is an
617 * 224.0.0.0/4 that is fine, ignore that one.
619 * though we must return PIM_GROUP_OVERLAP
621 if (prefix_same(&rp_info
->group
,
622 &tmp_rp_info
->group
)) {
623 if ((rp_src_flag
== RP_SRC_STATIC
)
624 && (tmp_rp_info
->rp_src
626 XFREE(MTYPE_PIM_RP
, rp_info
);
627 return PIM_GROUP_OVERLAP
;
630 result
= pim_rp_change(
632 rp_info
->rp
.rpf_addr
.u
.prefix4
,
635 XFREE(MTYPE_PIM_RP
, rp_info
);
642 listnode_add_sort(pim
->rp_list
, rp_info
);
643 rn
= route_node_get(pim
->rp_table
, &rp_info
->group
);
646 if (PIM_DEBUG_PIM_TRACE
) {
647 char buf
[PREFIX_STRLEN
];
649 zlog_debug("Allocated: %p for rp_info: %p(%s) Lock: %d", rn
,
651 prefix2str(&rp_info
->group
, buf
, sizeof(buf
)),
655 frr_each (rb_pim_upstream
, &pim
->upstream_head
, up
) {
656 if (up
->sg
.src
.s_addr
== INADDR_ANY
) {
658 struct rp_info
*trp_info
;
660 grp
.family
= AF_INET
;
661 grp
.prefixlen
= IPV4_MAX_BITLEN
;
662 grp
.u
.prefix4
= up
->sg
.grp
;
663 trp_info
= pim_rp_find_match_group(pim
, &grp
);
665 if (trp_info
== rp_info
)
666 pim_upstream_update(pim
, up
);
670 pim_rp_check_interfaces(pim
, rp_info
);
671 pim_rp_refresh_group_to_rp_mapping(pim
);
673 /* Register addr with Zebra NHT */
674 nht_p
.family
= AF_INET
;
675 nht_p
.prefixlen
= IPV4_MAX_BITLEN
;
676 nht_p
.u
.prefix4
= rp_info
->rp
.rpf_addr
.u
.prefix4
;
677 if (PIM_DEBUG_PIM_NHT_RP
) {
678 char buf
[PREFIX2STR_BUFFER
];
679 char buf1
[PREFIX2STR_BUFFER
];
680 prefix2str(&nht_p
, buf
, sizeof(buf
));
681 prefix2str(&rp_info
->group
, buf1
, sizeof(buf1
));
682 zlog_debug("%s: NHT Register RP addr %s grp %s with Zebra ",
683 __func__
, buf
, buf1
);
685 pim_find_or_track_nexthop(pim
, &nht_p
, NULL
, rp_info
, false, NULL
);
686 if (!pim_ecmp_nexthop_lookup(pim
, &rp_info
->rp
.source_nexthop
, &nht_p
,
688 return PIM_RP_NO_PATH
;
693 int pim_rp_del_config(struct pim_instance
*pim
, const char *rp
,
694 const char *group_range
, const char *plist
)
697 struct in_addr rp_addr
;
700 if (group_range
== NULL
)
701 result
= str2prefix("224.0.0.0/4", &group
);
703 result
= str2prefix(group_range
, &group
);
706 return PIM_GROUP_BAD_ADDRESS
;
708 result
= inet_pton(AF_INET
, rp
, &rp_addr
);
710 return PIM_RP_BAD_ADDRESS
;
712 result
= pim_rp_del(pim
, rp_addr
, group
, plist
, RP_SRC_STATIC
);
716 int pim_rp_del(struct pim_instance
*pim
, struct in_addr rp_addr
,
717 struct prefix group
, const char *plist
,
718 enum rp_source rp_src_flag
)
721 struct rp_info
*rp_info
;
722 struct rp_info
*rp_all
;
724 struct route_node
*rn
;
725 bool was_plist
= false;
726 struct rp_info
*trp_info
;
727 struct pim_upstream
*up
;
728 struct bsgrp_node
*bsgrp
= NULL
;
729 struct bsm_rpinfo
*bsrp
= NULL
;
730 char grp_str
[PREFIX2STR_BUFFER
];
731 char rp_str
[INET_ADDRSTRLEN
];
733 if (!inet_ntop(AF_INET
, &rp_addr
, rp_str
, sizeof(rp_str
)))
734 snprintf(rp_str
, sizeof(rp_str
), "<rp?>");
735 prefix2str(&group
, grp_str
, sizeof(grp_str
));
738 rp_info
= pim_rp_find_prefix_list(pim
, rp_addr
, plist
);
740 rp_info
= pim_rp_find_exact(pim
, rp_addr
, &group
);
743 return PIM_RP_NOT_FOUND
;
745 if (rp_info
->plist
) {
746 XFREE(MTYPE_PIM_FILTER_NAME
, rp_info
->plist
);
750 if (PIM_DEBUG_PIM_TRACE
)
751 zlog_debug("%s: Delete RP %s for the group %s", __func__
,
754 /* While static RP is getting deleted, we need to check if dynamic RP
755 * present for the same group in BSM RP table, then install the dynamic
756 * RP for the group node into the main rp table
758 if (rp_src_flag
== RP_SRC_STATIC
) {
759 bsgrp
= pim_bsm_get_bsgrp_node(&pim
->global_scope
, &group
);
762 bsrp
= listnode_head(bsgrp
->bsrp_list
);
764 if (PIM_DEBUG_PIM_TRACE
) {
765 char bsrp_str
[INET_ADDRSTRLEN
];
767 if (!inet_ntop(AF_INET
, bsrp
, bsrp_str
,
774 "%s: BSM RP %s found for the group %s",
775 __func__
, bsrp_str
, grp_str
);
777 return pim_rp_change(pim
, bsrp
->rp_address
,
781 if (PIM_DEBUG_PIM_TRACE
)
783 "%s: BSM RP not found for the group %s",
788 /* Deregister addr with Zebra NHT */
789 nht_p
.family
= AF_INET
;
790 nht_p
.prefixlen
= IPV4_MAX_BITLEN
;
791 nht_p
.u
.prefix4
= rp_info
->rp
.rpf_addr
.u
.prefix4
;
792 if (PIM_DEBUG_PIM_NHT_RP
) {
793 char buf
[PREFIX2STR_BUFFER
];
794 prefix2str(&nht_p
, buf
, sizeof(buf
));
795 zlog_debug("%s: Deregister RP addr %s with Zebra ", __func__
,
798 pim_delete_tracked_nexthop(pim
, &nht_p
, NULL
, rp_info
, false);
800 if (!str2prefix("224.0.0.0/4", &g_all
))
801 return PIM_RP_BAD_ADDRESS
;
803 rp_all
= pim_rp_find_match_group(pim
, &g_all
);
805 if (rp_all
== rp_info
) {
806 frr_each (rb_pim_upstream
, &pim
->upstream_head
, up
) {
807 /* Find the upstream (*, G) whose upstream address is
808 * same as the deleted RP
810 if ((up
->upstream_addr
.s_addr
811 == rp_info
->rp
.rpf_addr
.u
.prefix4
.s_addr
)
812 && (up
->sg
.src
.s_addr
== INADDR_ANY
)) {
814 grp
.family
= AF_INET
;
815 grp
.prefixlen
= IPV4_MAX_BITLEN
;
816 grp
.u
.prefix4
= up
->sg
.grp
;
817 trp_info
= pim_rp_find_match_group(pim
, &grp
);
818 if (trp_info
== rp_all
) {
819 pim_upstream_rpf_clear(pim
, up
);
820 up
->upstream_addr
.s_addr
= INADDR_ANY
;
824 rp_all
->rp
.rpf_addr
.family
= AF_INET
;
825 rp_all
->rp
.rpf_addr
.u
.prefix4
.s_addr
= INADDR_NONE
;
830 listnode_delete(pim
->rp_list
, rp_info
);
833 rn
= route_node_get(pim
->rp_table
, &rp_info
->group
);
835 if (rn
->info
!= rp_info
)
838 "Expected rn->info to be equal to rp_info");
840 if (PIM_DEBUG_PIM_TRACE
) {
841 char buf
[PREFIX_STRLEN
];
844 "%s:Found for Freeing: %p for rp_info: %p(%s) Lock: %d",
845 __func__
, rn
, rp_info
,
846 prefix2str(&rp_info
->group
, buf
,
851 route_unlock_node(rn
);
852 route_unlock_node(rn
);
856 pim_rp_refresh_group_to_rp_mapping(pim
);
858 frr_each (rb_pim_upstream
, &pim
->upstream_head
, up
) {
859 /* Find the upstream (*, G) whose upstream address is same as
862 if ((up
->upstream_addr
.s_addr
863 == rp_info
->rp
.rpf_addr
.u
.prefix4
.s_addr
)
864 && (up
->sg
.src
.s_addr
== INADDR_ANY
)) {
867 grp
.family
= AF_INET
;
868 grp
.prefixlen
= IPV4_MAX_BITLEN
;
869 grp
.u
.prefix4
= up
->sg
.grp
;
871 trp_info
= pim_rp_find_match_group(pim
, &grp
);
873 /* RP not found for the group grp */
874 if (pim_rpf_addr_is_inaddr_none(&trp_info
->rp
)) {
875 pim_upstream_rpf_clear(pim
, up
);
876 pim_rp_set_upstream_addr(
877 pim
, &up
->upstream_addr
, up
->sg
.src
,
881 /* RP found for the group grp */
883 pim_upstream_update(pim
, up
);
887 XFREE(MTYPE_PIM_RP
, rp_info
);
891 int pim_rp_change(struct pim_instance
*pim
, struct in_addr new_rp_addr
,
892 struct prefix group
, enum rp_source rp_src_flag
)
895 struct route_node
*rn
;
897 struct rp_info
*rp_info
= NULL
;
898 struct pim_upstream
*up
;
900 rn
= route_node_lookup(pim
->rp_table
, &group
);
902 result
= pim_rp_new(pim
, new_rp_addr
, group
, NULL
, rp_src_flag
);
909 route_unlock_node(rn
);
910 result
= pim_rp_new(pim
, new_rp_addr
, group
, NULL
, rp_src_flag
);
914 if (rp_info
->rp
.rpf_addr
.u
.prefix4
.s_addr
== new_rp_addr
.s_addr
) {
915 if (rp_info
->rp_src
!= rp_src_flag
) {
916 rp_info
->rp_src
= rp_src_flag
;
917 route_unlock_node(rn
);
922 nht_p
.family
= AF_INET
;
923 nht_p
.prefixlen
= IPV4_MAX_BITLEN
;
925 /* Deregister old RP addr with Zebra NHT */
926 if (rp_info
->rp
.rpf_addr
.u
.prefix4
.s_addr
!= INADDR_ANY
) {
927 nht_p
.u
.prefix4
= rp_info
->rp
.rpf_addr
.u
.prefix4
;
928 if (PIM_DEBUG_PIM_NHT_RP
) {
929 char buf
[PREFIX2STR_BUFFER
];
931 prefix2str(&nht_p
, buf
, sizeof(buf
));
932 zlog_debug("%s: Deregister RP addr %s with Zebra ",
935 pim_delete_tracked_nexthop(pim
, &nht_p
, NULL
, rp_info
, false);
938 pim_rp_nexthop_del(rp_info
);
939 listnode_delete(pim
->rp_list
, rp_info
);
940 /* Update the new RP address*/
941 rp_info
->rp
.rpf_addr
.u
.prefix4
= new_rp_addr
;
942 rp_info
->rp_src
= rp_src_flag
;
943 rp_info
->i_am_rp
= 0;
945 listnode_add_sort(pim
->rp_list
, rp_info
);
947 frr_each (rb_pim_upstream
, &pim
->upstream_head
, up
) {
948 if (up
->sg
.src
.s_addr
== INADDR_ANY
) {
950 struct rp_info
*trp_info
;
952 grp
.family
= AF_INET
;
953 grp
.prefixlen
= IPV4_MAX_BITLEN
;
954 grp
.u
.prefix4
= up
->sg
.grp
;
955 trp_info
= pim_rp_find_match_group(pim
, &grp
);
957 if (trp_info
== rp_info
)
958 pim_upstream_update(pim
, up
);
962 /* Register new RP addr with Zebra NHT */
963 nht_p
.u
.prefix4
= rp_info
->rp
.rpf_addr
.u
.prefix4
;
964 if (PIM_DEBUG_PIM_NHT_RP
) {
965 char buf
[PREFIX2STR_BUFFER
];
966 char buf1
[PREFIX2STR_BUFFER
];
968 prefix2str(&nht_p
, buf
, sizeof(buf
));
969 prefix2str(&rp_info
->group
, buf1
, sizeof(buf1
));
970 zlog_debug("%s: NHT Register RP addr %s grp %s with Zebra ",
971 __func__
, buf
, buf1
);
974 pim_find_or_track_nexthop(pim
, &nht_p
, NULL
, rp_info
, false, NULL
);
975 if (!pim_ecmp_nexthop_lookup(pim
, &rp_info
->rp
.source_nexthop
, &nht_p
,
976 &rp_info
->group
, 1)) {
977 route_unlock_node(rn
);
978 return PIM_RP_NO_PATH
;
981 pim_rp_check_interfaces(pim
, rp_info
);
983 route_unlock_node(rn
);
985 pim_rp_refresh_group_to_rp_mapping(pim
);
990 void pim_rp_setup(struct pim_instance
*pim
)
992 struct listnode
*node
;
993 struct rp_info
*rp_info
;
996 for (ALL_LIST_ELEMENTS_RO(pim
->rp_list
, node
, rp_info
)) {
997 if (rp_info
->rp
.rpf_addr
.u
.prefix4
.s_addr
== INADDR_NONE
)
1000 nht_p
.family
= AF_INET
;
1001 nht_p
.prefixlen
= IPV4_MAX_BITLEN
;
1002 nht_p
.u
.prefix4
= rp_info
->rp
.rpf_addr
.u
.prefix4
;
1004 pim_find_or_track_nexthop(pim
, &nht_p
, NULL
, rp_info
, false,
1006 if (!pim_ecmp_nexthop_lookup(pim
, &rp_info
->rp
.source_nexthop
,
1007 &nht_p
, &rp_info
->group
, 1))
1008 if (PIM_DEBUG_PIM_NHT_RP
)
1010 "Unable to lookup nexthop for rp specified");
1015 * Checks to see if we should elect ourself the actual RP when new if
1016 * addresses are added against an interface.
1018 void pim_rp_check_on_if_add(struct pim_interface
*pim_ifp
)
1020 struct listnode
*node
;
1021 struct rp_info
*rp_info
;
1022 bool i_am_rp_changed
= false;
1023 struct pim_instance
*pim
= pim_ifp
->pim
;
1025 if (pim
->rp_list
== NULL
)
1028 for (ALL_LIST_ELEMENTS_RO(pim
->rp_list
, node
, rp_info
)) {
1029 if (pim_rpf_addr_is_inaddr_none(&rp_info
->rp
))
1032 /* if i_am_rp is already set nothing to be done (adding new
1034 * is not going to make a difference). */
1035 if (rp_info
->i_am_rp
) {
1039 if (pim_rp_check_interface_addrs(rp_info
, pim_ifp
)) {
1040 i_am_rp_changed
= true;
1041 rp_info
->i_am_rp
= 1;
1042 if (PIM_DEBUG_PIM_NHT_RP
) {
1043 char rp
[PREFIX_STRLEN
];
1044 pim_addr_dump("<rp?>", &rp_info
->rp
.rpf_addr
,
1046 zlog_debug("%s: %s: i am rp", __func__
, rp
);
1051 if (i_am_rp_changed
) {
1052 pim_msdp_i_am_rp_changed(pim
);
1053 pim_upstream_reeval_use_rpt(pim
);
1057 /* up-optimized re-evaluation of "i_am_rp". this is used when ifaddresses
1058 * are removed. Removing numbers is an uncommon event in an active network
1059 * so I have made no attempt to optimize it. */
1060 void pim_i_am_rp_re_evaluate(struct pim_instance
*pim
)
1062 struct listnode
*node
;
1063 struct rp_info
*rp_info
;
1064 bool i_am_rp_changed
= false;
1067 if (pim
->rp_list
== NULL
)
1070 for (ALL_LIST_ELEMENTS_RO(pim
->rp_list
, node
, rp_info
)) {
1071 if (pim_rpf_addr_is_inaddr_none(&rp_info
->rp
))
1074 old_i_am_rp
= rp_info
->i_am_rp
;
1075 pim_rp_check_interfaces(pim
, rp_info
);
1077 if (old_i_am_rp
!= rp_info
->i_am_rp
) {
1078 i_am_rp_changed
= true;
1079 if (PIM_DEBUG_PIM_NHT_RP
) {
1080 char rp
[PREFIX_STRLEN
];
1081 pim_addr_dump("<rp?>", &rp_info
->rp
.rpf_addr
,
1083 if (rp_info
->i_am_rp
) {
1084 zlog_debug("%s: %s: i am rp", __func__
,
1087 zlog_debug("%s: %s: i am no longer rp",
1094 if (i_am_rp_changed
) {
1095 pim_msdp_i_am_rp_changed(pim
);
1096 pim_upstream_reeval_use_rpt(pim
);
1101 * I_am_RP(G) is true if the group-to-RP mapping indicates that
1102 * this router is the RP for the group.
1104 * Since we only have static RP, all groups are part of this RP
1106 int pim_rp_i_am_rp(struct pim_instance
*pim
, struct in_addr group
)
1109 struct rp_info
*rp_info
;
1111 memset(&g
, 0, sizeof(g
));
1114 g
.u
.prefix4
= group
;
1116 rp_info
= pim_rp_find_match_group(pim
, &g
);
1119 return rp_info
->i_am_rp
;
1127 * Return the RP that the Group belongs too.
1129 struct pim_rpf
*pim_rp_g(struct pim_instance
*pim
, struct in_addr group
)
1132 struct rp_info
*rp_info
;
1134 memset(&g
, 0, sizeof(g
));
1137 g
.u
.prefix4
= group
;
1139 rp_info
= pim_rp_find_match_group(pim
, &g
);
1142 struct prefix nht_p
;
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
;
1148 if (PIM_DEBUG_PIM_NHT_RP
) {
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
));
1154 "%s: NHT Register RP addr %s grp %s with Zebra",
1155 __func__
, buf
, buf1
);
1157 pim_find_or_track_nexthop(pim
, &nht_p
, NULL
, rp_info
, false,
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);
1162 return (&rp_info
->rp
);
1170 * Set the upstream IP address we want to talk to based upon
1171 * the rp configured and the source address
1173 * If we have don't have a RP configured and the source address is *
1174 * then set the upstream addr as INADDR_ANY and return failure.
1177 int pim_rp_set_upstream_addr(struct pim_instance
*pim
, struct in_addr
*up
,
1178 struct in_addr source
, struct in_addr group
)
1180 struct rp_info
*rp_info
;
1183 memset(&g
, 0, sizeof(g
));
1186 g
.u
.prefix4
= group
;
1188 rp_info
= pim_rp_find_match_group(pim
, &g
);
1190 if (!rp_info
|| ((pim_rpf_addr_is_inaddr_none(&rp_info
->rp
))
1191 && (source
.s_addr
== INADDR_ANY
))) {
1192 if (PIM_DEBUG_PIM_NHT_RP
)
1193 zlog_debug("%s: Received a (*,G) with no RP configured",
1195 up
->s_addr
= INADDR_ANY
;
1199 *up
= (source
.s_addr
== INADDR_ANY
) ? rp_info
->rp
.rpf_addr
.u
.prefix4
1205 int pim_rp_config_write(struct pim_instance
*pim
, struct vty
*vty
,
1208 struct listnode
*node
;
1209 struct rp_info
*rp_info
;
1211 char group_buffer
[32];
1214 for (ALL_LIST_ELEMENTS_RO(pim
->rp_list
, node
, rp_info
)) {
1215 if (pim_rpf_addr_is_inaddr_none(&rp_info
->rp
))
1218 if (rp_info
->rp_src
== RP_SRC_BSR
)
1222 vty_out(vty
, "%sip pim rp %s prefix-list %s\n", spaces
,
1224 &rp_info
->rp
.rpf_addr
.u
.prefix4
,
1228 vty_out(vty
, "%sip pim rp %s %s\n", spaces
,
1230 &rp_info
->rp
.rpf_addr
.u
.prefix4
,
1232 prefix2str(&rp_info
->group
, group_buffer
, 32));
1239 bool pim_rp_check_is_my_ip_address(struct pim_instance
*pim
,
1240 struct in_addr dest_addr
)
1242 if (if_lookup_exact_address(&dest_addr
, AF_INET
, pim
->vrf_id
))
1248 void pim_rp_show_information(struct pim_instance
*pim
, struct vty
*vty
, bool uj
)
1250 struct rp_info
*rp_info
;
1251 struct rp_info
*prev_rp_info
= NULL
;
1252 struct listnode
*node
;
1255 json_object
*json
= NULL
;
1256 json_object
*json_rp_rows
= NULL
;
1257 json_object
*json_row
= NULL
;
1260 json
= json_object_new_object();
1263 "RP address group/prefix-list OIF I am RP Source\n");
1264 for (ALL_LIST_ELEMENTS_RO(pim
->rp_list
, node
, rp_info
)) {
1265 if (!pim_rpf_addr_is_inaddr_none(&rp_info
->rp
)) {
1268 if (rp_info
->rp_src
== RP_SRC_STATIC
)
1269 strlcpy(source
, "Static", sizeof(source
));
1270 else if (rp_info
->rp_src
== RP_SRC_BSR
)
1271 strlcpy(source
, "BSR", sizeof(source
));
1273 strlcpy(source
, "None", sizeof(source
));
1276 * If we have moved on to a new RP then add the
1277 * entry for the previous RP
1280 && prev_rp_info
->rp
.rpf_addr
.u
.prefix4
1282 != rp_info
->rp
.rpf_addr
.u
.prefix4
1284 json_object_object_add(
1286 inet_ntoa(prev_rp_info
->rp
1290 json_rp_rows
= NULL
;
1294 json_rp_rows
= json_object_new_array();
1296 json_row
= json_object_new_object();
1297 json_object_string_add(
1298 json_row
, "rpAddress",
1299 inet_ntoa(rp_info
->rp
.rpf_addr
.u
1301 if (rp_info
->rp
.source_nexthop
.interface
)
1302 json_object_string_add(
1303 json_row
, "outboundInterface",
1304 rp_info
->rp
.source_nexthop
1307 json_object_string_add(
1308 json_row
, "outboundInterface",
1310 if (rp_info
->i_am_rp
)
1311 json_object_boolean_true_add(json_row
,
1314 json_object_boolean_false_add(json_row
,
1318 json_object_string_add(json_row
,
1322 json_object_string_add(
1324 prefix2str(&rp_info
->group
, buf
,
1326 json_object_string_add(json_row
, "source",
1329 json_object_array_add(json_rp_rows
, json_row
);
1331 vty_out(vty
, "%-15s ",
1332 inet_ntoa(rp_info
->rp
.rpf_addr
.u
1336 vty_out(vty
, "%-18s ", rp_info
->plist
);
1338 vty_out(vty
, "%-18s ",
1339 prefix2str(&rp_info
->group
, buf
,
1342 if (rp_info
->rp
.source_nexthop
.interface
)
1343 vty_out(vty
, "%-16s ",
1344 rp_info
->rp
.source_nexthop
1347 vty_out(vty
, "%-16s ", "(Unknown)");
1349 if (rp_info
->i_am_rp
)
1350 vty_out(vty
, "yes");
1354 vty_out(vty
, "%14s\n", source
);
1356 prev_rp_info
= rp_info
;
1361 if (prev_rp_info
&& json_rp_rows
)
1362 json_object_object_add(
1364 inet_ntoa(prev_rp_info
->rp
.rpf_addr
.u
.prefix4
),
1367 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
1368 json
, JSON_C_TO_STRING_PRETTY
));
1369 json_object_free(json
);
1373 void pim_resolve_rp_nh(struct pim_instance
*pim
, struct pim_neighbor
*nbr
)
1375 struct listnode
*node
= NULL
;
1376 struct rp_info
*rp_info
= NULL
;
1377 struct nexthop
*nh_node
= NULL
;
1378 struct prefix nht_p
;
1379 struct pim_nexthop_cache pnc
;
1381 for (ALL_LIST_ELEMENTS_RO(pim
->rp_list
, node
, rp_info
)) {
1382 if (rp_info
->rp
.rpf_addr
.u
.prefix4
.s_addr
== INADDR_NONE
)
1385 nht_p
.family
= AF_INET
;
1386 nht_p
.prefixlen
= IPV4_MAX_BITLEN
;
1387 nht_p
.u
.prefix4
= rp_info
->rp
.rpf_addr
.u
.prefix4
;
1388 memset(&pnc
, 0, sizeof(struct pim_nexthop_cache
));
1389 if (!pim_find_or_track_nexthop(pim
, &nht_p
, NULL
, rp_info
,
1393 for (nh_node
= pnc
.nexthop
; nh_node
; nh_node
= nh_node
->next
) {
1394 if (nh_node
->gate
.ipv4
.s_addr
!= 0)
1397 struct interface
*ifp1
= if_lookup_by_index(
1398 nh_node
->ifindex
, pim
->vrf_id
);
1400 if (nbr
->interface
!= ifp1
)
1403 nh_node
->gate
.ipv4
= nbr
->source_addr
;
1404 if (PIM_DEBUG_PIM_NHT_RP
) {
1405 char str
[PREFIX_STRLEN
];
1406 char str1
[INET_ADDRSTRLEN
];
1407 pim_inet4_dump("<nht_nbr?>", nbr
->source_addr
,
1408 str1
, sizeof(str1
));
1409 pim_addr_dump("<nht_addr?>", &nht_p
, str
,
1412 "%s: addr %s new nexthop addr %s interface %s",
1413 __func__
, str
, str1
, ifp1
->name
);