summaryrefslogtreecommitdiffstats
path: root/bgpd
diff options
context:
space:
mode:
authorDaniel Walton <dwalton@cumulusnetworks.com>2017-07-31 23:22:23 +0200
committerDaniel Walton <dwalton@cumulusnetworks.com>2017-07-31 23:22:23 +0200
commit40520c3649dc9d556b3a11f1d60e84130cebf487 (patch)
tree22a1ee7b22142e9fe49caec66da2bcfa7bce6aa4 /bgpd
parentMerge pull request #866 from opensourcerouting/ldpd-config-issues (diff)
downloadfrr-40520c3649dc9d556b3a11f1d60e84130cebf487.tar.xz
frr-40520c3649dc9d556b3a11f1d60e84130cebf487.zip
bgpd: peer hash expands until we are out of memory
Signed-off-by: Daniel Walton <dwalton@cumulusnetworks.com> swpX peers all start out with the same sockunion so initially they all go into the same hash bucket. Once IPv6 ND has worked its magic they will have different sockunions and will go in different buckets...life is good. Until then though, we are in a phase where all swpX peers have the same socknunion. Once we have HASH_THRESHOLD (10) swpX peers and call hash_get for a new swpX peer the hash code calls hash_expand(). This happens because there are more than HASH_THRESHOLD entries in a single bucket so the logic is "expand the hash to spread things out"...in our case expanding doesn't spread out the swpX peers because all of their sockunions are the same. I looked at having peer_hash_make and peer_hash_same consider the ifname of the swpX peer but that is a large change that we don't want to make at the moment. So the fix is to put a cap on how large we are willing to let the hash table get. By default there is no limit but if max_size is set we will not allow the hash to expand above that.
Diffstat (limited to 'bgpd')
-rw-r--r--bgpd/bgpd.c5
-rw-r--r--bgpd/bgpd.h1
2 files changed, 4 insertions, 2 deletions
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index a0e2d6749..b4e000f8b 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -746,7 +746,7 @@ static unsigned int peer_hash_key_make(void *p)
return sockunion_hash(&peer->su);
}
-static int peer_hash_cmp(const void *p1, const void *p2)
+static int peer_hash_same(const void *p1, const void *p2)
{
const struct peer *peer1 = p1;
const struct peer *peer2 = p2;
@@ -2757,7 +2757,8 @@ static struct bgp *bgp_create(as_t *as, const char *name,
XSTRDUP(MTYPE_BGP_PEER_HOST, "Static announcement");
bgp->peer = list_new();
bgp->peer->cmp = (int (*)(void *, void *))peer_cmp;
- bgp->peerhash = hash_create(peer_hash_key_make, peer_hash_cmp, NULL);
+ bgp->peerhash = hash_create(peer_hash_key_make, peer_hash_same, NULL);
+ bgp->peerhash->max_size = BGP_PEER_MAX_HASH_SIZE;
bgp->group = list_new();
bgp->group->cmp = (int (*)(void *, void *))peer_group_cmp;
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index 67b8289c7..ff5e709da 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -36,6 +36,7 @@
#include "bitfield.h"
#define BGP_MAX_HOSTNAME 64 /* Linux max, is larger than most other sys */
+#define BGP_PEER_MAX_HASH_SIZE 16384
/* Default interval for IPv6 RAs when triggered by BGP unnumbered neighbor. */
#define BGP_UNNUM_DEFAULT_RA_INTERVAL 10