diff options
Diffstat (limited to 'pimd/pim_rp.c')
| -rw-r--r-- | pimd/pim_rp.c | 135 |
1 files changed, 125 insertions, 10 deletions
diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c index 851a861a95..5c7561f586 100644 --- a/pimd/pim_rp.c +++ b/pimd/pim_rp.c @@ -30,6 +30,7 @@ #include "vrf.h" #include "plist.h" #include "nexthop.h" +#include "table.h" #include "pimd.h" #include "pim_vty.h" @@ -96,17 +97,36 @@ int pim_rp_list_cmp(void *v1, void *v2) void pim_rp_init(struct pim_instance *pim) { struct rp_info *rp_info; + struct route_node *rn; pim->rp_list = list_new(); + if (!pim->rp_list) { + zlog_err("Unable to alloc rp_list"); + return; + } pim->rp_list->del = (void (*)(void *))pim_rp_info_free; pim->rp_list->cmp = pim_rp_list_cmp; + pim->rp_table = route_table_init(); + if (!pim->rp_table) { + zlog_err("Unable to alloc rp_table"); + list_delete(pim->rp_list); + return; + } + rp_info = XCALLOC(MTYPE_PIM_RP, sizeof(*rp_info)); - if (!rp_info) + if (!rp_info) { + zlog_err("Unable to alloc rp_info"); + route_table_finish(pim->rp_table); + list_delete(pim->rp_list); return; + } if (!str2prefix("224.0.0.0/4", &rp_info->group)) { + zlog_err("Unable to convert 224.0.0.0/4 to prefix"); + list_delete(pim->rp_list); + route_table_finish(pim->rp_table); XFREE(MTYPE_PIM_RP, rp_info); return; } @@ -116,6 +136,20 @@ void pim_rp_init(struct pim_instance *pim) rp_info->rp.rpf_addr.u.prefix4.s_addr = INADDR_NONE; listnode_add(pim->rp_list, rp_info); + + rn = route_node_get(pim->rp_table, &rp_info->group); + if (!rn) { + zlog_err("Failure to get route node for pim->rp_table"); + list_delete(pim->rp_list); + route_table_finish(pim->rp_table); + XFREE(MTYPE_PIM_RP, rp_info); + return; + } + + rn->info = rp_info; + if (PIM_DEBUG_TRACE) + zlog_debug("Allocated: %p for rp_info: %p(224.0.0.0/4) Lock: %d", + rn, rp_info, rn->lock); } void pim_rp_free(struct pim_instance *pim) @@ -189,23 +223,58 @@ static struct rp_info *pim_rp_find_match_group(struct pim_instance *pim, struct prefix *group) { struct listnode *node; + struct rp_info *best = NULL; struct rp_info *rp_info; struct prefix_list *plist; + struct prefix *p, *bp; + struct route_node *rn; + bp = NULL; for (ALL_LIST_ELEMENTS_RO(pim->rp_list, node, rp_info)) { if (rp_info->plist) { plist = prefix_list_lookup(AFI_IP, rp_info->plist); - if (plist - && prefix_list_apply(plist, group) == PREFIX_PERMIT) - return rp_info; - } else { - if (prefix_match(&rp_info->group, group)) - return rp_info; + if (prefix_list_apply_which_prefix(plist, &p, group) == PREFIX_DENY) + continue; + + if (!best) { + best = rp_info; + bp = p; + continue; + } + + if (bp && bp->prefixlen < p->prefixlen) { + best = rp_info; + bp = p; + } } } - return NULL; + rn = route_node_match(pim->rp_table, group); + if (!rn) { + zlog_err("%s: BUG We should have found default group information\n", + __PRETTY_FUNCTION__); + return best; + } + + rp_info = rn->info; + if (PIM_DEBUG_TRACE) { + char buf[PREFIX_STRLEN]; + + route_unlock_node(rn); + zlog_debug("Lookedup: %p for rp_info: %p(%s) Lock: %d", + rn, rp_info, + prefix2str(&rp_info->group, buf, sizeof(buf)), + rn->lock); + } + + if (!best) + return rp_info; + + if (rp_info->group.prefixlen < best->group.prefixlen) + best = rp_info; + + return best; } /* @@ -293,6 +362,7 @@ int pim_rp_new(struct pim_instance *pim, const char *rp, char buffer[BUFSIZ]; struct prefix nht_p; struct pim_nexthop_cache pnc; + struct route_node *rn; rp_info = XCALLOC(MTYPE_PIM_RP, sizeof(*rp_info)); if (!rp_info) @@ -357,6 +427,7 @@ int pim_rp_new(struct pim_instance *pim, const char *rp, rp_info->plist = XSTRDUP(MTYPE_PIM_FILTER_NAME, plist); } else { + if (!str2prefix("224.0.0.0/4", &group_all)) { XFREE(MTYPE_PIM_RP, rp_info); return PIM_GROUP_BAD_ADDRESS; @@ -452,8 +523,8 @@ int pim_rp_new(struct pim_instance *pim, const char *rp, * For all others * though we must return PIM_GROUP_OVERLAP */ - if (!prefix_same(&group_all, - &tmp_rp_info->group)) { + if (prefix_same(&rp_info->group, + &tmp_rp_info->group)) { XFREE(MTYPE_PIM_RP, rp_info); return PIM_GROUP_OVERLAP; } @@ -462,6 +533,23 @@ int pim_rp_new(struct pim_instance *pim, const char *rp, } listnode_add_sort(pim->rp_list, rp_info); + rn = route_node_get(pim->rp_table, &rp_info->group); + if (!rn) { + char buf[PREFIX_STRLEN]; + zlog_err("Failure to get route node for pim->rp_table: %s", + prefix2str(&rp_info->group, buf, sizeof(buf))); + return PIM_MALLOC_FAIL; + } + rn->info = rp_info; + + if (PIM_DEBUG_TRACE) { + char buf[PREFIX_STRLEN]; + + zlog_debug("Allocated: %p for rp_info: %p(%s) Lock: %d", + rn, rp_info, + prefix2str(&rp_info->group, buf, sizeof(buf)), + rn->lock); + } /* Register addr with Zebra NHT */ nht_p.family = AF_INET; @@ -504,6 +592,8 @@ int pim_rp_del(struct pim_instance *pim, const char *rp, struct rp_info *rp_all; int result; struct prefix nht_p; + struct route_node *rn; + bool was_plist = false; if (group_range == NULL) result = str2prefix("224.0.0.0/4", &group); @@ -528,6 +618,7 @@ int pim_rp_del(struct pim_instance *pim, const char *rp, if (rp_info->plist) { XFREE(MTYPE_PIM_FILTER_NAME, rp_info->plist); rp_info->plist = NULL; + was_plist = true; } /* Deregister addr with Zebra NHT */ @@ -555,7 +646,31 @@ int pim_rp_del(struct pim_instance *pim, const char *rp, } listnode_delete(pim->rp_list, rp_info); + + if (!was_plist) { + rn = route_node_get(pim->rp_table, &rp_info->group); + if (rn) { + if (rn->info != rp_info) + zlog_err("WTF matey"); + + if (PIM_DEBUG_TRACE) { + char buf[PREFIX_STRLEN]; + + zlog_debug("%s:Found for Freeing: %p for rp_info: %p(%s) Lock: %d", + __PRETTY_FUNCTION__, + rn, rp_info, + prefix2str(&rp_info->group, buf, sizeof(buf)), + rn->lock); + } + rn->info = NULL; + route_unlock_node(rn); + route_unlock_node(rn); + } + } + pim_rp_refresh_group_to_rp_mapping(pim); + + XFREE(MTYPE_PIM_RP, rp_info); return PIM_SUCCESS; } |
