summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xconfigure.ac18
-rw-r--r--lib/plist.c21
-rw-r--r--lib/plist.h16
-rw-r--r--pimd/pim_cmd.c2
-rw-r--r--pimd/pim_instance.h4
-rw-r--r--pimd/pim_rp.c134
-rw-r--r--pimd/pim_rpf.c8
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) {