]> git.puffer.fish Git - mirror/frr.git/commitdiff
lib: fix interface configuration after vrf change 9172/head
authorIgor Ryzhov <iryzhov@nfware.com>
Wed, 16 Jun 2021 11:07:30 +0000 (14:07 +0300)
committermergify-bot <noreply@mergify.io>
Sat, 24 Jul 2021 16:56:56 +0000 (16:56 +0000)
This commit fixes the following problem:

- enter the interface node
- move the interface to another VRF
- try to continue configuring the interface

It is not possible to continue configuration because the XPath stored in
the vty doesn't correspond with the actual state of the system anymore.

For example:
```
nfware# conf
nfware(config)# interface enp2s0

<-- move the enp2s0 to a different VRF -->

nfware(config-if)# ip router isis 1
% Failed to get iface dnode in candidate DB
```

To fix the issue, go through all connected vty shells and update the
stored XPath.

Suggested-by: Renato Westphal <renato@opensourcerouting.org>
Signed-off-by: Igor Ryzhov <iryzhov@nfware.com>
(cherry picked from commit 763725cd5e431cb4f4ec385e35b312cc7807163a)

lib/if.c
lib/vty.c
lib/vty.h

index b3803141df2eaad93cf039b4e6abc6495ae6055a..e37b4f55b00bb4e1cef7eb45e62b154fc186738d 100644 (file)
--- a/lib/if.c
+++ b/lib/if.c
@@ -266,20 +266,23 @@ void if_update_to_new_vrf(struct interface *ifp, vrf_id_t vrf_id)
                char oldpath[XPATH_MAXLEN];
                char newpath[XPATH_MAXLEN];
 
-               if_dnode = yang_dnode_getf(
-                       running_config->dnode,
-                       "/frr-interface:lib/interface[name='%s'][vrf='%s']/vrf",
-                       ifp->name, old_vrf->name);
+               snprintf(oldpath, sizeof(oldpath),
+                        "/frr-interface:lib/interface[name='%s'][vrf='%s']",
+                        ifp->name, old_vrf->name);
+               snprintf(newpath, sizeof(newpath),
+                        "/frr-interface:lib/interface[name='%s'][vrf='%s']",
+                        ifp->name, vrf->name);
+
+               if_dnode = yang_dnode_getf(running_config->dnode, "%s/vrf",
+                                          oldpath);
 
                if (if_dnode) {
-                       yang_dnode_get_path(lyd_parent(if_dnode), oldpath,
-                                           sizeof(oldpath));
                        yang_dnode_change_leaf(if_dnode, vrf->name);
-                       yang_dnode_get_path(lyd_parent(if_dnode), newpath,
-                                           sizeof(newpath));
                        nb_running_move_tree(oldpath, newpath);
                        running_config->version++;
                }
+
+               vty_update_xpath(oldpath, newpath);
        }
 }
 
index 6853fc33013bac1196006431b19717ccdad06173..50d116c564b2efe382322940707b6fe249117560 100644 (file)
--- a/lib/vty.c
+++ b/lib/vty.c
@@ -82,6 +82,9 @@ extern struct host host;
 /* Vector which store each vty structure. */
 static vector vtyvec;
 
+/* Vector for vtysh connections. */
+static vector vtyshvec;
+
 /* Vty timeout value. */
 static unsigned long vty_timeout_val = VTY_TIMEOUT_DEFAULT;
 
@@ -2038,6 +2041,7 @@ static int vtysh_accept(struct thread *thread)
        vty->wfd = sock;
        vty->type = VTY_SHELL_SERV;
        vty->node = VIEW_NODE;
+       vector_set_index(vtyshvec, sock, vty);
 
        vty_event(VTYSH_READ, vty);
 
@@ -2211,8 +2215,12 @@ void vty_close(struct vty *vty)
        }
 
        /* Unset vector. */
-       if (vty->fd != -1)
-               vector_unset(vtyvec, vty->fd);
+       if (vty->fd != -1) {
+               if (vty->type == VTY_SHELL_SERV)
+                       vector_unset(vtyshvec, vty->fd);
+               else
+                       vector_unset(vtyvec, vty->fd);
+       }
 
        if (vty->wfd > 0 && vty->type == VTY_FILE)
                fsync(vty->wfd);
@@ -2571,6 +2579,41 @@ void vty_log_fixed(char *buf, size_t len)
        }
 }
 
+static void update_xpath(struct vty *vty, const char *oldpath,
+                        const char *newpath)
+{
+       int i;
+
+       for (i = 0; i < vty->xpath_index; i++) {
+               if (!frrstr_startswith(vty->xpath[i], oldpath))
+                       break;
+
+               char *tmp = frrstr_replace(vty->xpath[i], oldpath, newpath);
+               strlcpy(vty->xpath[i], tmp, sizeof(vty->xpath[0]));
+               XFREE(MTYPE_TMP, tmp);
+       }
+}
+
+void vty_update_xpath(const char *oldpath, const char *newpath)
+{
+       struct vty *vty;
+       unsigned int i;
+
+       for (i = 0; i < vector_active(vtyshvec); i++) {
+               if ((vty = vector_slot(vtyshvec, i)) == NULL)
+                       continue;
+
+               update_xpath(vty, oldpath, newpath);
+       }
+
+       for (i = 0; i < vector_active(vtyvec); i++) {
+               if ((vty = vector_slot(vtyvec, i)) == NULL)
+                       continue;
+
+               update_xpath(vty, oldpath, newpath);
+       }
+}
+
 int vty_config_enter(struct vty *vty, bool private_config, bool exclusive)
 {
        if (exclusive && nb_running_lock(NB_CLIENT_CLI, vty)) {
@@ -3114,6 +3157,7 @@ void vty_init(struct thread_master *master_thread, bool do_command_logging)
        vty_save_cwd();
 
        vtyvec = vector_init(VECTOR_MIN_SIZE);
+       vtyshvec = vector_init(VECTOR_MIN_SIZE);
 
        vty_master = master_thread;
 
@@ -3165,4 +3209,8 @@ void vty_terminate(void)
                vtyvec = NULL;
                Vvty_serv_thread = NULL;
        }
+       if (vtyshvec) {
+               vector_free(vtyshvec);
+               vtyshvec = NULL;
+       }
 }
index 10fbb16a47eefc04517611289b5994eb9be730bd..70ec4fcd849744d900d616d5b648cfbf1de4069d 100644 (file)
--- a/lib/vty.h
+++ b/lib/vty.h
@@ -327,6 +327,7 @@ extern void vty_close(struct vty *);
 extern char *vty_get_cwd(void);
 extern void vty_log(const char *level, const char *proto, const char *msg,
                    struct timestamp_control *);
+extern void vty_update_xpath(const char *oldpath, const char *newpath);
 extern int vty_config_enter(struct vty *vty, bool private_config,
                            bool exclusive);
 extern void vty_config_exit(struct vty *);