diff options
author | Igor Ryzhov <iryzhov@nfware.com> | 2021-03-03 21:10:19 +0100 |
---|---|---|
committer | Igor Ryzhov <iryzhov@nfware.com> | 2021-03-03 21:10:19 +0100 |
commit | 632f36100c2d36e17446f384e430e8eecfa03d6e (patch) | |
tree | ea204f0c937a58f5fa0c6024bac4a797b9bc17e2 /bfdd | |
parent | bfdd: actually return validation error instead of logging (diff) | |
download | frr-632f36100c2d36e17446f384e430e8eecfa03d6e.tar.xz frr-632f36100c2d36e17446f384e430e8eecfa03d6e.zip |
bfdd: forbid creation of the same peer with and without interface name
Currently it is possible to configure the same peer with and without
interface name:
```
bfd
peer 1.1.1.1
!
peer 1.1.1.1 interface enp0s3
!
```
There are multiple problems with that:
1. Both nodes actually control the same BFD session. So the config is
either duplicated or, even worse, different - and there is no way to
say which one actually works.
2. When the user deletes both nodes, the session is not actually freed,
because its refcount is always greater than 1.
Such configuration must be forbidden. User should either have single
node with wildcard name or multiple nodes with actual names.
Signed-off-by: Igor Ryzhov <iryzhov@nfware.com>
Diffstat (limited to 'bfdd')
-rw-r--r-- | bfdd/bfdd_nb_config.c | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/bfdd/bfdd_nb_config.c b/bfdd/bfdd_nb_config.c index b8065c605..c8dd5cc3f 100644 --- a/bfdd/bfdd_nb_config.c +++ b/bfdd/bfdd_nb_config.c @@ -55,10 +55,35 @@ static void bfd_session_get_key(bool mhop, const struct lyd_node *dnode, gen_bfd_key(bk, &psa, &lsa, mhop, ifname, vrfname); } +struct session_iter { + int count; + bool wildcard; +}; + +static int session_iter_cb(const struct lyd_node *dnode, void *arg) +{ + struct session_iter *iter = arg; + const char *ifname; + + ifname = yang_dnode_get_string(dnode, "./interface"); + + if (strmatch(ifname, "*")) + iter->wildcard = true; + + iter->count++; + + return YANG_ITER_CONTINUE; +} + static int bfd_session_create(struct nb_cb_create_args *args, bool mhop) { + const struct lyd_node *sess_dnode; + struct session_iter iter; struct bfd_session *bs; + const char *source; + const char *dest; const char *ifname; + const char *vrfname; struct bfd_key bk; struct prefix p; @@ -80,6 +105,33 @@ static int bfd_session_create(struct nb_cb_create_args *args, bool mhop) "When using link-local you must specify an interface"); return NB_ERR_VALIDATION; } + + iter.count = 0; + iter.wildcard = false; + + sess_dnode = yang_dnode_get_parent(args->dnode, "sessions"); + + dest = yang_dnode_get_string(args->dnode, "./dest-addr"); + vrfname = yang_dnode_get_string(args->dnode, "./vrf"); + + if (mhop) { + source = yang_dnode_get_string(args->dnode, "./source-addr"); + + yang_dnode_iterate(session_iter_cb, &iter, sess_dnode, + "./multi-hop[source-addr='%s'][dest-addr='%s'][vrf='%s']", + source, dest, vrfname); + } else { + yang_dnode_iterate(session_iter_cb, &iter, sess_dnode, + "./single-hop[dest-addr='%s'][vrf='%s']", + dest, vrfname); + } + + if (iter.wildcard && iter.count > 1) { + snprintf( + args->errmsg, args->errmsg_len, + "It is not allowed to configure the same peer with and without ifname"); + return NB_ERR_VALIDATION; + } break; case NB_EV_PREPARE: |