diff options
-rwxr-xr-x | configure.ac | 18 | ||||
-rw-r--r-- | lib/plist.c | 21 | ||||
-rw-r--r-- | lib/plist.h | 16 | ||||
-rw-r--r-- | pimd/pim_cmd.c | 2 | ||||
-rw-r--r-- | pimd/pim_instance.h | 4 | ||||
-rw-r--r-- | pimd/pim_rp.c | 134 | ||||
-rw-r--r-- | pimd/pim_rpf.c | 8 |
7 files changed, 180 insertions, 23 deletions
diff --git a/configure.ac b/configure.ac index 63bde5fcd..2faaa7fc8 100755 --- a/configure.ac +++ b/configure.ac @@ -185,14 +185,6 @@ CC="${CC% -std=c99}" AC_C_FLAG([-std=gnu11], [CC="$ac_cc"], [CC="$CC -std=gnu11"]) -dnl if the user specified any CFLAGS, we don't add "-g -Os/-O2" here -if test "z$orig_cflags" = "z"; then - AC_C_FLAG([-g]) - AC_C_FLAG([-Os], [ - AC_C_FLAG([-O2]) - ]) -fi - dnl always want these CFLAGS AC_C_FLAG([-fno-omit-frame-pointer]) AC_C_FLAG([-funwind-tables]) @@ -438,6 +430,16 @@ AM_CONDITIONAL([FPM], [test "x$enable_fpm" = "xyes"]) if test "x${enable_dev_build}" = "xyes"; then AC_DEFINE(DEV_BUILD,,Build for development) + AC_C_FLAG([-g]) + AC_C_FLAG([-O0]) +else + dnl if the user specified any CFLAGS, we don't add "-g -Os/-O2" here + if test "z$orig_cflags" = "z"; then + AC_C_FLAG([-g]) + AC_C_FLAG([-Os], [ + AC_C_FLAG([-O2]) + ]) + fi fi AM_CONDITIONAL([DEV_BUILD], [test "x$enable_dev_build" = "xyes"]) diff --git a/lib/plist.c b/lib/plist.c index ebd628d72..da6406d33 100644 --- a/lib/plist.c +++ b/lib/plist.c @@ -679,7 +679,9 @@ static int prefix_list_entry_match(struct prefix_list_entry *pentry, return 1; } -enum prefix_list_type prefix_list_apply(struct prefix_list *plist, void *object) +enum prefix_list_type prefix_list_apply_which_prefix(struct prefix_list *plist, + struct prefix **which, + void *object) { struct prefix_list_entry *pentry, *pbest = NULL; @@ -689,11 +691,17 @@ enum prefix_list_type prefix_list_apply(struct prefix_list *plist, void *object) size_t validbits = p->prefixlen; struct pltrie_table *table; - if (plist == NULL) + if (plist == NULL) { + if (which) + *which = NULL; return PREFIX_DENY; + } - if (plist->count == 0) + if (plist->count == 0) { + if (which) + *which = NULL; return PREFIX_PERMIT; + } depth = plist->master->trie_depth; table = plist->trie; @@ -729,6 +737,13 @@ enum prefix_list_type prefix_list_apply(struct prefix_list *plist, void *object) break; } + if (which) { + if (pbest) + *which = &pbest->prefix; + else + *which = NULL; + } + if (pbest == NULL) return PREFIX_DENY; diff --git a/lib/plist.h b/lib/plist.h index 3eba3046a..bf06e74d3 100644 --- a/lib/plist.h +++ b/lib/plist.h @@ -50,7 +50,21 @@ extern void prefix_list_delete_hook(void (*func)(struct prefix_list *)); extern const char *prefix_list_name(struct prefix_list *); extern afi_t prefix_list_afi(struct prefix_list *); extern struct prefix_list *prefix_list_lookup(afi_t, const char *); -extern enum prefix_list_type prefix_list_apply(struct prefix_list *, void *); + +/* + * prefix_list_apply_which_prefix + * + * Allow calling function to learn which prefix + * caused the DENY or PERMIT. + * + * If no pointer is sent in, do not return anything. + * If it is a empty plist return a NULL pointer. + */ +extern enum prefix_list_type prefix_list_apply_which_prefix( + struct prefix_list *plist, + struct prefix **which, + void *object); +#define prefix_list_apply(A, B) prefix_list_apply_which_prefix((A), NULL, (B)) extern struct prefix_list *prefix_bgp_orf_lookup(afi_t, const char *); extern struct stream *prefix_bgp_orf_entry(struct stream *, diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index f330807b2..396b949e4 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -5068,7 +5068,7 @@ static int pim_rp_cmd_worker(struct pim_instance *pim, struct vty *vty, } 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; } diff --git a/pimd/pim_instance.h b/pimd/pim_instance.h index 0e91b4ca0..5422e8fe0 100644 --- a/pimd/pim_instance.h +++ b/pimd/pim_instance.h @@ -76,7 +76,11 @@ struct pim_instance { struct hash *upstream_hash; struct timer_wheel *upstream_sg_wheel; + /* + * RP information + */ struct list *rp_list; + struct route_table *rp_table; int iface_vif_index[MAXVIFS]; diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c index 851a861a9..54d0d2b7d 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,57 @@ 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; 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->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 +361,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 +426,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 +522,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 +532,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 +591,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 +617,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 +645,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; } diff --git a/pimd/pim_rpf.c b/pimd/pim_rpf.c index 36c6c894e..fd09b04b8 100644 --- a/pimd/pim_rpf.c +++ b/pimd/pim_rpf.c @@ -61,6 +61,14 @@ int pim_nexthop_lookup(struct pim_instance *pim, struct pim_nexthop *nexthop, int found = 0; int i = 0; + /* + * We should not attempt to lookup a + * 255.255.255.255 address, since + * it will never work + */ + if (addr.s_addr == INADDR_NONE) + return -1; + if ((nexthop->last_lookup.s_addr == addr.s_addr) && (nexthop->last_lookup_time > last_route_change_time)) { if (PIM_DEBUG_TRACE) { |