From 5ef92a2b20914efda1d2bdff65a17c58f9ec8dca Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Thu, 11 Apr 2019 13:29:47 +0200 Subject: [PATCH] bfdd: avoid creating duplicate peer contexts when configuring bfd peers, some parameters may or may not be taken into account to search for a previous context. This has as consequence that the result is different with the order of vty commands: bfd peer 4.5.6.7 vrf AAAA local-address 1.2.3.5 end peer 4.5.6.7 vrf AAAA <--- should not create new session end Similarly, the user thinks it has overwritten some key parameters like local address, whereas it is wrong. here, some informational message should be present. bfd peer 4.5.6.7 vrf AAAA end peer 4.5.6.7 vrf AAAA local-address 1.2.3.5 <--- should inform that the key lookup 1.2.3.5 is wrong end Signed-off-by: Philippe Guibert --- bfdd/bfd.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 80 insertions(+), 7 deletions(-) diff --git a/bfdd/bfd.c b/bfdd/bfd.c index 06ab5ea409..a2e84e928d 100644 --- a/bfdd/bfd.c +++ b/bfdd/bfd.c @@ -1322,32 +1322,105 @@ 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 (bsp == NULL && bs.key.family == AF_INET) { + if (bs.key.family == AF_INET) { memset(&bs.key.local, 0, sizeof(bs.key.local)); bsp = hash_lookup(bfd_key_hash, &bs); + if (bsp) { + char addr_buf[INET6_ADDRSTRLEN]; + + inet_ntop(bs.key.family, &key.local, addr_buf, + sizeof(addr_buf)); + log_debug(" peer %s found, but loc-addr %s ignored", + peer_buf, addr_buf); + return bsp; + } } - /* Handle cases where ifname is optional. */ bs.key = key; - if (bsp == NULL && bs.key.ifname[0]) { + /* 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) { + log_debug(" peer %s found, but ifp %s ignored", + peer_buf, key.ifname); + return bsp; + } + } - /* Handle cases where local-address and ifname are optional. */ - if (bsp == NULL && bs.key.family == AF_INET) { - memset(&bs.key.local, 0, sizeof(bs.key.local)); - bsp = hash_lookup(bfd_key_hash, &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) { + char addr_buf[INET6_ADDRSTRLEN]; + + inet_ntop(bs.key.family, &bs.key.local, addr_buf, + sizeof(addr_buf)); + log_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 + */ + 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; + log_debug(" peer %s found, but ifp" + " and/or loc-addr params ignored"); + } return bsp; } -- 2.39.5