pimd: Add ability to lookup RP group by table.

This feature does this:

Add the ability to store the non-prefix static RP
entries into a table.  Then to lookup the G to
find the RP in that table, finding the longest
prefix match across both prefix-lists and
static RP's.

Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
This commit is contained in:
Donald Sharp 2017-08-31 09:08:12 -04:00
parent b77b155068
commit 89b680829e
3 changed files with 101 additions and 6 deletions

View File

@ -5070,7 +5070,7 @@ static int pim_rp_cmd_worker(struct pim_instance *pim, struct vty *vty,
} }
if (result == PIM_GROUP_OVERLAP) { if (result == PIM_GROUP_OVERLAP) {
vty_out(vty, "%% Group range specified cannot overlap\n"); vty_out(vty, "%% Group range specified cannot exact match another\n");
return CMD_WARNING_CONFIG_FAILED; return CMD_WARNING_CONFIG_FAILED;
} }

View File

@ -76,7 +76,11 @@ struct pim_instance {
struct hash *upstream_hash; struct hash *upstream_hash;
struct timer_wheel *upstream_sg_wheel; struct timer_wheel *upstream_sg_wheel;
/*
* RP information
*/
struct list *rp_list; struct list *rp_list;
struct route_table *rp_table;
int iface_vif_index[MAXVIFS]; int iface_vif_index[MAXVIFS];

View File

@ -30,6 +30,7 @@
#include "vrf.h" #include "vrf.h"
#include "plist.h" #include "plist.h"
#include "nexthop.h" #include "nexthop.h"
#include "table.h"
#include "pimd.h" #include "pimd.h"
#include "pim_vty.h" #include "pim_vty.h"
@ -96,6 +97,7 @@ int pim_rp_list_cmp(void *v1, void *v2)
void pim_rp_init(struct pim_instance *pim) void pim_rp_init(struct pim_instance *pim)
{ {
struct rp_info *rp_info; struct rp_info *rp_info;
struct route_node *rn;
pim->rp_list = list_new(); pim->rp_list = list_new();
if (!pim->rp_list) { if (!pim->rp_list) {
@ -105,10 +107,18 @@ void pim_rp_init(struct pim_instance *pim)
pim->rp_list->del = (void (*)(void *))pim_rp_info_free; pim->rp_list->del = (void (*)(void *))pim_rp_info_free;
pim->rp_list->cmp = pim_rp_list_cmp; 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)); rp_info = XCALLOC(MTYPE_PIM_RP, sizeof(*rp_info));
if (!rp_info) { if (!rp_info) {
zlog_err("Unable to alloc rp_info"); zlog_err("Unable to alloc rp_info");
route_table_finish(pim->rp_table);
list_delete(pim->rp_list); list_delete(pim->rp_list);
return; return;
} }
@ -116,6 +126,7 @@ void pim_rp_init(struct pim_instance *pim)
if (!str2prefix("224.0.0.0/4", &rp_info->group)) { if (!str2prefix("224.0.0.0/4", &rp_info->group)) {
zlog_err("Unable to convert 224.0.0.0/4 to prefix"); zlog_err("Unable to convert 224.0.0.0/4 to prefix");
list_delete(pim->rp_list); list_delete(pim->rp_list);
route_table_finish(pim->rp_table);
XFREE(MTYPE_PIM_RP, rp_info); XFREE(MTYPE_PIM_RP, rp_info);
return; return;
} }
@ -125,6 +136,20 @@ void pim_rp_init(struct pim_instance *pim)
rp_info->rp.rpf_addr.u.prefix4.s_addr = INADDR_NONE; rp_info->rp.rpf_addr.u.prefix4.s_addr = INADDR_NONE;
listnode_add(pim->rp_list, rp_info); 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) void pim_rp_free(struct pim_instance *pim)
@ -202,6 +227,7 @@ static struct rp_info *pim_rp_find_match_group(struct pim_instance *pim,
struct rp_info *rp_info; struct rp_info *rp_info;
struct prefix_list *plist; struct prefix_list *plist;
struct prefix *p, *bp; struct prefix *p, *bp;
struct route_node *rn;
for (ALL_LIST_ELEMENTS_RO(pim->rp_list, node, rp_info)) { for (ALL_LIST_ELEMENTS_RO(pim->rp_list, node, rp_info)) {
if (rp_info->plist) { if (rp_info->plist) {
@ -220,12 +246,33 @@ static struct rp_info *pim_rp_find_match_group(struct pim_instance *pim,
best = rp_info; best = rp_info;
bp = p; bp = p;
} }
} else {
if (prefix_match(&rp_info->group, group))
return rp_info;
} }
} }
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; return best;
} }
@ -314,6 +361,7 @@ int pim_rp_new(struct pim_instance *pim, const char *rp,
char buffer[BUFSIZ]; char buffer[BUFSIZ];
struct prefix nht_p; struct prefix nht_p;
struct pim_nexthop_cache pnc; struct pim_nexthop_cache pnc;
struct route_node *rn;
rp_info = XCALLOC(MTYPE_PIM_RP, sizeof(*rp_info)); rp_info = XCALLOC(MTYPE_PIM_RP, sizeof(*rp_info));
if (!rp_info) if (!rp_info)
@ -378,6 +426,7 @@ int pim_rp_new(struct pim_instance *pim, const char *rp,
rp_info->plist = XSTRDUP(MTYPE_PIM_FILTER_NAME, plist); rp_info->plist = XSTRDUP(MTYPE_PIM_FILTER_NAME, plist);
} else { } else {
if (!str2prefix("224.0.0.0/4", &group_all)) { if (!str2prefix("224.0.0.0/4", &group_all)) {
XFREE(MTYPE_PIM_RP, rp_info); XFREE(MTYPE_PIM_RP, rp_info);
return PIM_GROUP_BAD_ADDRESS; return PIM_GROUP_BAD_ADDRESS;
@ -473,8 +522,8 @@ int pim_rp_new(struct pim_instance *pim, const char *rp,
* For all others * For all others
* though we must return PIM_GROUP_OVERLAP * though we must return PIM_GROUP_OVERLAP
*/ */
if (!prefix_same(&group_all, if (prefix_same(&rp_info->group,
&tmp_rp_info->group)) { &tmp_rp_info->group)) {
XFREE(MTYPE_PIM_RP, rp_info); XFREE(MTYPE_PIM_RP, rp_info);
return PIM_GROUP_OVERLAP; return PIM_GROUP_OVERLAP;
} }
@ -483,6 +532,23 @@ int pim_rp_new(struct pim_instance *pim, const char *rp,
} }
listnode_add_sort(pim->rp_list, rp_info); 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 */ /* Register addr with Zebra NHT */
nht_p.family = AF_INET; nht_p.family = AF_INET;
@ -525,6 +591,8 @@ int pim_rp_del(struct pim_instance *pim, const char *rp,
struct rp_info *rp_all; struct rp_info *rp_all;
int result; int result;
struct prefix nht_p; struct prefix nht_p;
struct route_node *rn;
bool was_plist = false;
if (group_range == NULL) if (group_range == NULL)
result = str2prefix("224.0.0.0/4", &group); result = str2prefix("224.0.0.0/4", &group);
@ -549,6 +617,7 @@ int pim_rp_del(struct pim_instance *pim, const char *rp,
if (rp_info->plist) { if (rp_info->plist) {
XFREE(MTYPE_PIM_FILTER_NAME, rp_info->plist); XFREE(MTYPE_PIM_FILTER_NAME, rp_info->plist);
rp_info->plist = NULL; rp_info->plist = NULL;
was_plist = true;
} }
/* Deregister addr with Zebra NHT */ /* Deregister addr with Zebra NHT */
@ -574,6 +643,28 @@ int pim_rp_del(struct pim_instance *pim, const char *rp,
} }
listnode_delete(pim->rp_list, rp_info); 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); pim_rp_refresh_group_to_rp_mapping(pim);
XFREE(MTYPE_PIM_RP, rp_info); XFREE(MTYPE_PIM_RP, rp_info);