]> git.proxmox.com Git - mirror_frr.git/blobdiff - bfdd/bfdd_nb_config.c
Merge pull request #11765 from lyq140/patch-pimDoc
[mirror_frr.git] / bfdd / bfdd_nb_config.c
index fe6a0b7905694e09a0282ca7ecd8a6c1f3475aa1..c1a2ad7bb43e065b921426a3820305e9d2f2c400 100644 (file)
@@ -45,46 +45,104 @@ static void bfd_session_get_key(bool mhop, const struct lyd_node *dnode,
        if (yang_dnode_exists(dnode, "./source-addr"))
                strtosa(yang_dnode_get_string(dnode, "./source-addr"), &lsa);
 
-       ifname = yang_dnode_get_string(dnode, "./interface");
        vrfname = yang_dnode_get_string(dnode, "./vrf");
 
-       if (strcmp(ifname, "*") == 0)
-               ifname = NULL;
+       if (!mhop) {
+               ifname = yang_dnode_get_string(dnode, "./interface");
+               if (strcmp(ifname, "*") == 0)
+                       ifname = NULL;
+       }
 
        /* Generate the corresponding key. */
        gen_bfd_key(bk, &psa, &lsa, mhop, ifname, vrfname);
 }
 
-static int bfd_session_create(enum nb_event event, const struct lyd_node *dnode,
-                             union nb_resource *resource, bool mhop)
+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 *dest;
        const char *ifname;
+       const char *vrfname;
        struct bfd_key bk;
        struct prefix p;
 
-       switch (event) {
+       switch (args->event) {
        case NB_EV_VALIDATE:
+               yang_dnode_get_prefix(&p, args->dnode, "./dest-addr");
+
+               if (mhop) {
+                       /*
+                        * Do not allow IPv6 link-local address for multihop.
+                        */
+                       if (p.family == AF_INET6
+                           && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
+                               snprintf(
+                                       args->errmsg, args->errmsg_len,
+                                       "Cannot use link-local address for multihop sessions");
+                               return NB_ERR_VALIDATION;
+                       }
+                       return NB_OK;
+               }
+
                /*
                 * When `dest-addr` is IPv6 and link-local we must
                 * require interface name, otherwise we can't figure
                 * which interface to use to send the packets.
                 */
-               yang_dnode_get_prefix(&p, dnode, "./dest-addr");
-
-               ifname = yang_dnode_get_string(dnode, "./interface");
+               ifname = yang_dnode_get_string(args->dnode, "./interface");
 
                if (p.family == AF_INET6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)
                    && strcmp(ifname, "*") == 0) {
-                       zlog_warn(
-                               "%s: when using link-local you must specify an interface.",
-                               __func__);
+                       snprintf(
+                               args->errmsg, args->errmsg_len,
+                               "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");
+
+               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:
-               bfd_session_get_key(mhop, dnode, &bk);
+               bfd_session_get_key(mhop, args->dnode, &bk);
                bs = bfd_key_lookup(bk);
 
                /* This session was already configured by another daemon. */
@@ -93,14 +151,14 @@ static int bfd_session_create(enum nb_event event, const struct lyd_node *dnode,
                        SET_FLAG(bs->flags, BFD_SESS_FLAG_CONFIG);
                        bs->refcount++;
 
-                       resource->ptr = bs;
+                       args->resource->ptr = bs;
                        break;
                }
 
                bs = bfd_session_new();
 
                /* Fill the session key. */
-               bfd_session_get_key(mhop, dnode, &bs->key);
+               bfd_session_get_key(mhop, args->dnode, &bs->key);
 
                /* Set configuration flags. */
                bs->refcount = 1;
@@ -110,23 +168,23 @@ static int bfd_session_create(enum nb_event event, const struct lyd_node *dnode,
                if (bs->key.family == AF_INET6)
                        SET_FLAG(bs->flags, BFD_SESS_FLAG_IPV6);
 
-               resource->ptr = bs;
+               args->resource->ptr = bs;
                break;
 
        case NB_EV_APPLY:
-               bs = resource->ptr;
+               bs = args->resource->ptr;
 
                /* Only attempt to registrate if freshly allocated. */
                if (bs->discrs.my_discr == 0 && bs_registrate(bs) == NULL)
                        return NB_ERR_RESOURCE;
 
-               nb_running_set_entry(dnode, bs);
+               nb_running_set_entry(args->dnode, bs);
                break;
 
        case NB_EV_ABORT:
-               bs = resource->ptr;
+               bs = args->resource->ptr;
                if (bs->refcount <= 1)
-                       bfd_session_free(resource->ptr);
+                       bfd_session_free(bs);
                break;
        }
 
@@ -178,7 +236,15 @@ static int bfd_session_destroy(enum nb_event event,
  */
 int bfdd_bfd_create(struct nb_cb_create_args *args)
 {
-       /* NOTHING */
+       if (args->event != NB_EV_APPLY)
+               return NB_OK;
+
+       /*
+        * Set any non-NULL value to be able to call
+        * nb_running_unset_entry in bfdd_bfd_destroy.
+        */
+       nb_running_set_entry(args->dnode, (void *)0x1);
+
        return NB_OK;
 }
 
@@ -194,7 +260,14 @@ int bfdd_bfd_destroy(struct nb_cb_destroy_args *args)
                return NB_OK;
 
        case NB_EV_APPLY:
+               /*
+                * We need to call this to unset pointers from
+                * the child nodes - sessions and profiles.
+                */
+               nb_running_unset_entry(args->dnode);
+
                bfd_sessions_remove_manual();
+               bfd_profiles_remove();
                break;
 
        case NB_EV_ABORT:
@@ -260,13 +333,9 @@ int bfdd_bfd_profile_desired_transmission_interval_modify(
        struct nb_cb_modify_args *args)
 {
        struct bfd_profile *bp;
-       uint32_t min_tx;
 
        switch (args->event) {
        case NB_EV_VALIDATE:
-               min_tx = yang_dnode_get_uint32(args->dnode, NULL);
-               if (min_tx < 10000 || min_tx > 60000000)
-                       return NB_ERR_VALIDATION;
                break;
 
        case NB_EV_PREPARE:
@@ -274,12 +343,8 @@ int bfdd_bfd_profile_desired_transmission_interval_modify(
                break;
 
        case NB_EV_APPLY:
-               min_tx = yang_dnode_get_uint32(args->dnode, NULL);
                bp = nb_running_get_entry(args->dnode, NULL, true);
-               if (bp->min_tx == min_tx)
-                       return NB_OK;
-
-               bp->min_tx = min_tx;
+               bp->min_tx = yang_dnode_get_uint32(args->dnode, NULL);
                bfd_profile_update(bp);
                break;
 
@@ -298,13 +363,9 @@ int bfdd_bfd_profile_required_receive_interval_modify(
        struct nb_cb_modify_args *args)
 {
        struct bfd_profile *bp;
-       uint32_t min_rx;
 
        switch (args->event) {
        case NB_EV_VALIDATE:
-               min_rx = yang_dnode_get_uint32(args->dnode, NULL);
-               if (min_rx < 10000 || min_rx > 60000000)
-                       return NB_ERR_VALIDATION;
                break;
 
        case NB_EV_PREPARE:
@@ -312,12 +373,8 @@ int bfdd_bfd_profile_required_receive_interval_modify(
                break;
 
        case NB_EV_APPLY:
-               min_rx = yang_dnode_get_uint32(args->dnode, NULL);
                bp = nb_running_get_entry(args->dnode, NULL, true);
-               if (bp->min_rx == min_rx)
-                       return NB_OK;
-
-               bp->min_rx = min_rx;
+               bp->min_rx = yang_dnode_get_uint32(args->dnode, NULL);
                bfd_profile_update(bp);
                break;
 
@@ -335,17 +392,12 @@ int bfdd_bfd_profile_required_receive_interval_modify(
 int bfdd_bfd_profile_administrative_down_modify(struct nb_cb_modify_args *args)
 {
        struct bfd_profile *bp;
-       bool shutdown;
 
        if (args->event != NB_EV_APPLY)
                return NB_OK;
 
-       shutdown = yang_dnode_get_bool(args->dnode, NULL);
        bp = nb_running_get_entry(args->dnode, NULL, true);
-       if (bp->admin_shutdown == shutdown)
-               return NB_OK;
-
-       bp->admin_shutdown = shutdown;
+       bp->admin_shutdown = yang_dnode_get_bool(args->dnode, NULL);
        bfd_profile_update(bp);
 
        return NB_OK;
@@ -357,17 +409,12 @@ int bfdd_bfd_profile_administrative_down_modify(struct nb_cb_modify_args *args)
 int bfdd_bfd_profile_passive_mode_modify(struct nb_cb_modify_args *args)
 {
        struct bfd_profile *bp;
-       bool passive;
 
        if (args->event != NB_EV_APPLY)
                return NB_OK;
 
-       passive = yang_dnode_get_bool(args->dnode, NULL);
        bp = nb_running_get_entry(args->dnode, NULL, true);
-       if (bp->passive == passive)
-               return NB_OK;
-
-       bp->passive = passive;
+       bp->passive = yang_dnode_get_bool(args->dnode, NULL);
        bfd_profile_update(bp);
 
        return NB_OK;
@@ -379,17 +426,12 @@ int bfdd_bfd_profile_passive_mode_modify(struct nb_cb_modify_args *args)
 int bfdd_bfd_profile_minimum_ttl_modify(struct nb_cb_modify_args *args)
 {
        struct bfd_profile *bp;
-       uint8_t minimum_ttl;
 
        if (args->event != NB_EV_APPLY)
                return NB_OK;
 
-       minimum_ttl = yang_dnode_get_uint8(args->dnode, NULL);
        bp = nb_running_get_entry(args->dnode, NULL, true);
-       if (bp->minimum_ttl == minimum_ttl)
-               return NB_OK;
-
-       bp->minimum_ttl = minimum_ttl;
+       bp->minimum_ttl = yang_dnode_get_uint8(args->dnode, NULL);
        bfd_profile_update(bp);
 
        return NB_OK;
@@ -432,19 +474,15 @@ int bfdd_bfd_profile_echo_mode_modify(struct nb_cb_modify_args *args)
 }
 
 /*
- * XPath: /frr-bfdd:bfdd/bfd/profile/desired-echo-echo-transmission-interval
+ * XPath: /frr-bfdd:bfdd/bfd/profile/desired-echo-transmission-interval
  */
 int bfdd_bfd_profile_desired_echo_transmission_interval_modify(
        struct nb_cb_modify_args *args)
 {
        struct bfd_profile *bp;
-       uint32_t min_rx;
 
        switch (args->event) {
        case NB_EV_VALIDATE:
-               min_rx = yang_dnode_get_uint32(args->dnode, NULL);
-               if (min_rx < 10000 || min_rx > 60000000)
-                       return NB_ERR_VALIDATION;
                break;
 
        case NB_EV_PREPARE:
@@ -452,12 +490,38 @@ int bfdd_bfd_profile_desired_echo_transmission_interval_modify(
                break;
 
        case NB_EV_APPLY:
-               min_rx = yang_dnode_get_uint32(args->dnode, NULL);
                bp = nb_running_get_entry(args->dnode, NULL, true);
-               if (bp->min_echo_rx == min_rx)
-                       return NB_OK;
+               bp->min_echo_tx = yang_dnode_get_uint32(args->dnode, NULL);
+               bfd_profile_update(bp);
+               break;
+
+       case NB_EV_ABORT:
+               /* NOTHING */
+               break;
+       }
+
+       return NB_OK;
+}
+
+/*
+ * XPath: /frr-bfdd:bfdd/bfd/profile/required-echo-receive-interval
+ */
+int bfdd_bfd_profile_required_echo_receive_interval_modify(
+       struct nb_cb_modify_args *args)
+{
+       struct bfd_profile *bp;
+
+       switch (args->event) {
+       case NB_EV_VALIDATE:
+               break;
 
-               bp->min_echo_rx = min_rx;
+       case NB_EV_PREPARE:
+               /* NOTHING */
+               break;
+
+       case NB_EV_APPLY:
+               bp = nb_running_get_entry(args->dnode, NULL, true);
+               bp->min_echo_rx = yang_dnode_get_uint32(args->dnode, NULL);
                bfd_profile_update(bp);
                break;
 
@@ -474,8 +538,7 @@ int bfdd_bfd_profile_desired_echo_transmission_interval_modify(
  */
 int bfdd_bfd_sessions_single_hop_create(struct nb_cb_create_args *args)
 {
-       return bfd_session_create(args->event, args->dnode, args->resource,
-                                 false);
+       return bfd_session_create(args, false);
 }
 
 int bfdd_bfd_sessions_single_hop_destroy(struct nb_cb_destroy_args *args)
@@ -565,13 +628,10 @@ int bfdd_bfd_sessions_single_hop_detection_multiplier_modify(
 int bfdd_bfd_sessions_single_hop_desired_transmission_interval_modify(
        struct nb_cb_modify_args *args)
 {
-       uint32_t tx_interval = yang_dnode_get_uint32(args->dnode, NULL);
        struct bfd_session *bs;
 
        switch (args->event) {
        case NB_EV_VALIDATE:
-               if (tx_interval < 10000 || tx_interval > 60000000)
-                       return NB_ERR_VALIDATION;
                break;
 
        case NB_EV_PREPARE:
@@ -580,10 +640,8 @@ int bfdd_bfd_sessions_single_hop_desired_transmission_interval_modify(
 
        case NB_EV_APPLY:
                bs = nb_running_get_entry(args->dnode, NULL, true);
-               if (tx_interval == bs->timers.desired_min_tx)
-                       return NB_OK;
-
-               bs->peer_profile.min_tx = tx_interval;
+               bs->peer_profile.min_tx =
+                       yang_dnode_get_uint32(args->dnode, NULL);
                bfd_session_apply(bs);
                break;
 
@@ -601,13 +659,10 @@ int bfdd_bfd_sessions_single_hop_desired_transmission_interval_modify(
 int bfdd_bfd_sessions_single_hop_required_receive_interval_modify(
        struct nb_cb_modify_args *args)
 {
-       uint32_t rx_interval = yang_dnode_get_uint32(args->dnode, NULL);
        struct bfd_session *bs;
 
        switch (args->event) {
        case NB_EV_VALIDATE:
-               if (rx_interval < 10000 || rx_interval > 60000000)
-                       return NB_ERR_VALIDATION;
                break;
 
        case NB_EV_PREPARE:
@@ -616,10 +671,8 @@ int bfdd_bfd_sessions_single_hop_required_receive_interval_modify(
 
        case NB_EV_APPLY:
                bs = nb_running_get_entry(args->dnode, NULL, true);
-               if (rx_interval == bs->timers.required_min_rx)
-                       return NB_OK;
-
-               bs->peer_profile.min_rx = rx_interval;
+               bs->peer_profile.min_rx =
+                       yang_dnode_get_uint32(args->dnode, NULL);
                bfd_session_apply(bs);
                break;
 
@@ -724,13 +777,10 @@ int bfdd_bfd_sessions_single_hop_echo_mode_modify(
 int bfdd_bfd_sessions_single_hop_desired_echo_transmission_interval_modify(
        struct nb_cb_modify_args *args)
 {
-       uint32_t echo_interval = yang_dnode_get_uint32(args->dnode, NULL);
        struct bfd_session *bs;
 
        switch (args->event) {
        case NB_EV_VALIDATE:
-               if (echo_interval < 10000 || echo_interval > 60000000)
-                       return NB_ERR_VALIDATION;
                break;
 
        case NB_EV_PREPARE:
@@ -739,10 +789,40 @@ int bfdd_bfd_sessions_single_hop_desired_echo_transmission_interval_modify(
 
        case NB_EV_APPLY:
                bs = nb_running_get_entry(args->dnode, NULL, true);
-               if (echo_interval == bs->timers.required_min_echo)
-                       return NB_OK;
+               bs->peer_profile.min_echo_tx =
+                       yang_dnode_get_uint32(args->dnode, NULL);
+               bfd_session_apply(bs);
+               break;
+
+       case NB_EV_ABORT:
+               /* NOTHING */
+               break;
+       }
+
+       return NB_OK;
+}
+
+/*
+ * XPath:
+ * /frr-bfdd:bfdd/bfd/sessions/single-hop/required-echo-receive-interval
+ */
+int bfdd_bfd_sessions_single_hop_required_echo_receive_interval_modify(
+       struct nb_cb_modify_args *args)
+{
+       struct bfd_session *bs;
+
+       switch (args->event) {
+       case NB_EV_VALIDATE:
+               break;
 
-               bs->peer_profile.min_echo_rx = echo_interval;
+       case NB_EV_PREPARE:
+               /* NOTHING */
+               break;
+
+       case NB_EV_APPLY:
+               bs = nb_running_get_entry(args->dnode, NULL, true);
+               bs->peer_profile.min_echo_rx =
+                       yang_dnode_get_uint32(args->dnode, NULL);
                bfd_session_apply(bs);
                break;
 
@@ -759,8 +839,7 @@ int bfdd_bfd_sessions_single_hop_desired_echo_transmission_interval_modify(
  */
 int bfdd_bfd_sessions_multi_hop_create(struct nb_cb_create_args *args)
 {
-       return bfd_session_create(args->event, args->dnode, args->resource,
-                                 true);
+       return bfd_session_create(args, true);
 }
 
 int bfdd_bfd_sessions_multi_hop_destroy(struct nb_cb_destroy_args *args)