]> git.puffer.fish Git - mirror/frr.git/commitdiff
bfdd: forbid creation of the same peer with and without interface name
authorIgor Ryzhov <iryzhov@nfware.com>
Wed, 3 Mar 2021 20:10:19 +0000 (23:10 +0300)
committerIgor Ryzhov <iryzhov@nfware.com>
Wed, 3 Mar 2021 20:10:19 +0000 (23:10 +0300)
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>
bfdd/bfdd_nb_config.c

index b8065c60523650aa7cf9e0449ca2587af6e5214e..c8dd5cc3f63653dc79b750ed42e09477e935ce08 100644 (file)
@@ -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: