diff options
Diffstat (limited to 'pimd/pim_rp.c')
| -rw-r--r-- | pimd/pim_rp.c | 48 |
1 files changed, 35 insertions, 13 deletions
diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c index a31fec036f..3e3b6dddb5 100644 --- a/pimd/pim_rp.c +++ b/pimd/pim_rp.c @@ -124,7 +124,7 @@ void pim_rp_init(struct pim_instance *pim) } rp_info->group.family = AF_INET; rp_info->rp.rpf_addr.family = AF_INET; - rp_info->rp.rpf_addr.prefixlen = IPV4_MAX_PREFIXLEN; + rp_info->rp.rpf_addr.prefixlen = IPV4_MAX_BITLEN; rp_info->rp.rpf_addr.u.prefix4.s_addr = INADDR_NONE; listnode_add(pim->rp_list, rp_info); @@ -139,11 +139,12 @@ void pim_rp_init(struct pim_instance *pim) void pim_rp_free(struct pim_instance *pim) { - if (pim->rp_list) - list_delete(&pim->rp_list); if (pim->rp_table) route_table_finish(pim->rp_table); pim->rp_table = NULL; + + if (pim->rp_list) + list_delete(&pim->rp_list); } /* @@ -204,6 +205,26 @@ static struct rp_info *pim_rp_find_exact(struct pim_instance *pim, } /* + * XXX: long-term issue: we don't actually have a good "ip address-list" + * implementation. ("access-list XYZ" is the closest but honestly it's + * kinda garbage.) + * + * So it's using a prefix-list to match an address here, which causes very + * unexpected results for the user since prefix-lists by default only match + * when the prefix length is an exact match too. i.e. you'd have to add the + * "le 32" and do "ip prefix-list foo permit 10.0.0.0/24 le 32" + * + * To avoid this pitfall, this code uses "address_mode = true" for the prefix + * list match (this is the only user for that.) + * + * In the long run, we need to add a "ip address-list", but that's a wholly + * separate bag of worms, and existing configs using ip prefix-list would + * drop into the UX pitfall. + */ + +#include "lib/plist_int.h" + +/* * Given a group, return the rp_info for that group */ struct rp_info *pim_rp_find_match_group(struct pim_instance *pim, @@ -213,7 +234,8 @@ struct rp_info *pim_rp_find_match_group(struct pim_instance *pim, struct rp_info *best = NULL; struct rp_info *rp_info; struct prefix_list *plist; - const struct prefix *p, *bp; + const struct prefix *bp; + const struct prefix_list_entry *entry; struct route_node *rn; bp = NULL; @@ -221,19 +243,19 @@ struct rp_info *pim_rp_find_match_group(struct pim_instance *pim, if (rp_info->plist) { plist = prefix_list_lookup(AFI_IP, rp_info->plist); - if (prefix_list_apply_which_prefix(plist, &p, group) - == PREFIX_DENY) + if (prefix_list_apply_ext(plist, &entry, group, true) + == PREFIX_DENY || !entry) continue; if (!best) { best = rp_info; - bp = p; + bp = &entry->prefix; continue; } - if (bp && bp->prefixlen < p->prefixlen) { + if (bp && bp->prefixlen < entry->prefix.prefixlen) { best = rp_info; - bp = p; + bp = &entry->prefix; } } } @@ -417,7 +439,7 @@ int pim_rp_new(struct pim_instance *pim, struct in_addr rp_addr, rp_info = XCALLOC(MTYPE_PIM_RP, sizeof(*rp_info)); rp_info->rp.rpf_addr.family = AF_INET; - rp_info->rp.rpf_addr.prefixlen = IPV4_MAX_PREFIXLEN; + rp_info->rp.rpf_addr.prefixlen = IPV4_MAX_BITLEN; rp_info->rp.rpf_addr.u.prefix4 = rp_addr; prefix_copy(&rp_info->group, &group); rp_info->rp_src = rp_src_flag; @@ -1036,7 +1058,7 @@ int pim_rp_i_am_rp(struct pim_instance *pim, struct in_addr group) memset(&g, 0, sizeof(g)); g.family = AF_INET; - g.prefixlen = 32; + g.prefixlen = IPV4_MAX_BITLEN; g.u.prefix4 = group; rp_info = pim_rp_find_match_group(pim, &g); @@ -1059,7 +1081,7 @@ struct pim_rpf *pim_rp_g(struct pim_instance *pim, struct in_addr group) memset(&g, 0, sizeof(g)); g.family = AF_INET; - g.prefixlen = 32; + g.prefixlen = IPV4_MAX_BITLEN; g.u.prefix4 = group; rp_info = pim_rp_find_match_group(pim, &g); @@ -1103,7 +1125,7 @@ int pim_rp_set_upstream_addr(struct pim_instance *pim, struct in_addr *up, memset(&g, 0, sizeof(g)); g.family = AF_INET; - g.prefixlen = 32; + g.prefixlen = IPV4_MAX_BITLEN; g.u.prefix4 = group; rp_info = pim_rp_find_match_group(pim, &g); |
