summaryrefslogtreecommitdiffstats
path: root/bfdd
diff options
context:
space:
mode:
authorPhilippe Guibert <philippe.guibert@6wind.com>2021-02-12 18:25:09 +0100
committerGitHub <noreply@github.com>2021-02-12 18:25:09 +0100
commit35da69f1545446ecd9981b5d5fd5f3b4d912e50a (patch)
tree6b1c0b2e324de9131ecdc90f3ce86be9d05984a4 /bfdd
parentMerge pull request #8065 from donaldsharp/foo_master (diff)
parentbfdd: fix session lookup (diff)
downloadfrr-35da69f1545446ecd9981b5d5fd5f3b4d912e50a.tar.xz
frr-35da69f1545446ecd9981b5d5fd5f3b4d912e50a.zip
Merge pull request #8006 from idryzhov/fix-bfd-lookup
bfdd: fix session lookup
Diffstat (limited to 'bfdd')
-rw-r--r--bfdd/bfd.c160
1 files changed, 45 insertions, 115 deletions
diff --git a/bfdd/bfd.c b/bfdd/bfd.c
index ca4bf9495..3e45bf0e0 100644
--- a/bfdd/bfd.c
+++ b/bfdd/bfd.c
@@ -1672,15 +1672,54 @@ static bool bfd_id_hash_cmp(const void *n1, const void *n2)
static unsigned int bfd_key_hash_do(const void *p)
{
const struct bfd_session *bs = p;
+ struct bfd_key key = bs->key;
- return jhash(&bs->key, sizeof(bs->key), 0);
+ /*
+ * Local address and interface name are optional and
+ * can be filled any time after session creation.
+ * Hash key should not depend on these fields.
+ */
+ memset(&key.local, 0, sizeof(key.local));
+ memset(key.ifname, 0, sizeof(key.ifname));
+
+ return jhash(&key, sizeof(key), 0);
}
static bool bfd_key_hash_cmp(const void *n1, const void *n2)
{
const struct bfd_session *bs1 = n1, *bs2 = n2;
- return memcmp(&bs1->key, &bs2->key, sizeof(bs1->key)) == 0;
+ if (bs1->key.family != bs2->key.family)
+ return false;
+ if (bs1->key.mhop != bs2->key.mhop)
+ return false;
+ if (memcmp(&bs1->key.peer, &bs2->key.peer, sizeof(bs1->key.peer)))
+ return false;
+ if (memcmp(bs1->key.vrfname, bs2->key.vrfname,
+ sizeof(bs1->key.vrfname)))
+ return false;
+
+ /*
+ * Local address is optional and can be empty.
+ * If both addresses are not empty and different,
+ * then the keys are different.
+ */
+ if (memcmp(&bs1->key.local, &zero_addr, sizeof(bs1->key.local))
+ && memcmp(&bs2->key.local, &zero_addr, sizeof(bs2->key.local))
+ && memcmp(&bs1->key.local, &bs2->key.local, sizeof(bs1->key.local)))
+ return false;
+
+ /*
+ * Interface name is optional and can be empty.
+ * If both names are not empty and different,
+ * then the keys are different.
+ */
+ if (bs1->key.ifname[0] && bs2->key.ifname[0]
+ && memcmp(bs1->key.ifname, bs2->key.ifname,
+ sizeof(bs1->key.ifname)))
+ return false;
+
+ return true;
}
@@ -1698,117 +1737,13 @@ struct bfd_session *bfd_id_lookup(uint32_t id)
return hash_lookup(bfd_id_hash, &bs);
}
-struct bfd_key_walk_partial_lookup {
- struct bfd_session *given;
- struct bfd_session *result;
-};
-
-/* ignore some parameters */
-static int bfd_key_lookup_ignore_partial_walker(struct hash_bucket *b,
- void *data)
-{
- struct bfd_key_walk_partial_lookup *ctx =
- (struct bfd_key_walk_partial_lookup *)data;
- struct bfd_session *given = ctx->given;
- struct bfd_session *parsed = b->data;
-
- if (given->key.family != parsed->key.family)
- return HASHWALK_CONTINUE;
- if (given->key.mhop != parsed->key.mhop)
- return HASHWALK_CONTINUE;
- if (memcmp(&given->key.peer, &parsed->key.peer,
- sizeof(struct in6_addr)))
- return HASHWALK_CONTINUE;
- if (memcmp(given->key.vrfname, parsed->key.vrfname, MAXNAMELEN))
- return HASHWALK_CONTINUE;
- ctx->result = parsed;
- /* ignore localaddr or interface */
- return HASHWALK_ABORT;
-}
-
struct bfd_session *bfd_key_lookup(struct bfd_key key)
{
- struct bfd_session bs, *bsp;
- struct bfd_key_walk_partial_lookup ctx;
- char peer_buf[INET6_ADDRSTRLEN];
-
- bs.key = key;
- bsp = hash_lookup(bfd_key_hash, &bs);
- if (bsp)
- return bsp;
-
- inet_ntop(bs.key.family, &bs.key.peer, peer_buf,
- sizeof(peer_buf));
- /* Handle cases where local-address is optional. */
- if (memcmp(&bs.key.local, &zero_addr, sizeof(bs.key.local))) {
- memset(&bs.key.local, 0, sizeof(bs.key.local));
- bsp = hash_lookup(bfd_key_hash, &bs);
- if (bsp) {
- if (bglobal.debug_peer_event) {
- char addr_buf[INET6_ADDRSTRLEN];
- inet_ntop(bs.key.family, &key.local, addr_buf,
- sizeof(addr_buf));
- zlog_debug(
- " peer %s found, but loc-addr %s ignored",
- peer_buf, addr_buf);
- }
- return bsp;
- }
- }
-
- bs.key = key;
- /* Handle cases where ifname is optional. */
- if (bs.key.ifname[0]) {
- memset(bs.key.ifname, 0, sizeof(bs.key.ifname));
- bsp = hash_lookup(bfd_key_hash, &bs);
- if (bsp) {
- if (bglobal.debug_peer_event)
- zlog_debug(" peer %s found, but ifp %s ignored",
- peer_buf, key.ifname);
- return bsp;
- }
- }
+ struct bfd_session bs;
- /* Handle cases where local-address and ifname are optional. */
- if (bs.key.family == AF_INET) {
- memset(&bs.key.local, 0, sizeof(bs.key.local));
- bsp = hash_lookup(bfd_key_hash, &bs);
- if (bsp) {
- if (bglobal.debug_peer_event) {
- char addr_buf[INET6_ADDRSTRLEN];
- inet_ntop(bs.key.family, &bs.key.local,
- addr_buf, sizeof(addr_buf));
- zlog_debug(
- " peer %s found, but ifp %s and loc-addr %s ignored",
- peer_buf, key.ifname, addr_buf);
- }
- return bsp;
- }
- }
bs.key = key;
- /* Handle case where a context more complex ctx is present.
- * input has no iface nor local-address, but a context may
- * exist.
- *
- * Only applies to IPv4, because IPv6 requires either
- * local-address or interface.
- */
- if (!bs.key.mhop && bs.key.family == AF_INET) {
- ctx.result = NULL;
- ctx.given = &bs;
- hash_walk(bfd_key_hash, &bfd_key_lookup_ignore_partial_walker,
- &ctx);
- /* change key */
- if (ctx.result) {
- bsp = ctx.result;
- if (bglobal.debug_peer_event)
- zlog_debug(
- " peer %s found, but ifp and/or loc-addr params ignored",
- peer_buf);
- }
- }
- return bsp;
+ return hash_lookup(bfd_key_hash, &bs);
}
/*
@@ -1832,16 +1767,11 @@ struct bfd_session *bfd_id_delete(uint32_t id)
struct bfd_session *bfd_key_delete(struct bfd_key key)
{
- struct bfd_session bs, *bsp;
+ struct bfd_session bs;
bs.key = key;
- bsp = hash_lookup(bfd_key_hash, &bs);
- if (bsp == NULL && key.ifname[0]) {
- memset(bs.key.ifname, 0, sizeof(bs.key.ifname));
- bsp = hash_lookup(bfd_key_hash, &bs);
- }
- return hash_release(bfd_key_hash, bsp);
+ return hash_release(bfd_key_hash, &bs);
}
/* Iteration functions. */