]> git.puffer.fish Git - matthieu/frr.git/commitdiff
vtysh: reconnect to daemons when connection lost
authorMladen Sablic <mladen.sablic@gmail.com>
Mon, 21 May 2018 18:00:51 +0000 (20:00 +0200)
committerMladen Sablic <mladen.sablic@gmail.com>
Mon, 21 May 2018 18:51:03 +0000 (20:51 +0200)
Functionality to let vtysh attempt to reconnect to daemons when
connection is lost (e.g. crash or restart).

Signed-off-by: Mladen Sablic <mladen.sablic@gmail.com>
vtysh/vtysh.c
vtysh/vtysh.h

index 30de9d7711b2b51e07f9ed9b64b4430f3321e8bc..6bd7611ead8e73ed39dc39acd6f158d668b4bfef 100644 (file)
@@ -86,6 +86,8 @@ struct vtysh_client vtysh_client[] = {
 enum vtysh_write_integrated vtysh_write_integrated =
        WRITE_INTEGRATED_UNSPECIFIED;
 
+static int vtysh_reconnect(struct vtysh_client *vclient);
+
 static void vclient_close(struct vtysh_client *vclient)
 {
        if (vclient->fd >= 0) {
@@ -93,7 +95,8 @@ static void vclient_close(struct vtysh_client *vclient)
                        "Warning: closing connection to %s because of an I/O error!\n",
                        vclient->name);
                close(vclient->fd);
-               vclient->fd = -1;
+               /* indicate as candidate for reconnect */
+               vclient->fd = VTYSH_WAS_ACTIVE;
        }
 }
 
@@ -120,12 +123,28 @@ static int vtysh_client_run(struct vtysh_client *vclient, const char *line,
        char *bufvalid, *end = NULL;
        char terminator[3] = {0, 0, 0};
 
+       /* vclinet was previously active, try to reconnect */
+       if (vclient->fd == VTYSH_WAS_ACTIVE) {
+               ret = vtysh_reconnect(vclient);
+               if (ret < 0)
+                       goto out_err;
+       }
+
        if (vclient->fd < 0)
                return CMD_SUCCESS;
 
        ret = write(vclient->fd, line, strlen(line) + 1);
-       if (ret <= 0)
-               goto out_err;
+       if (ret <= 0) {
+               /* close connection and try to reconnect */
+               vclient_close(vclient);
+               ret = vtysh_reconnect(vclient);
+               if (ret < 0)
+                       goto out_err;
+               /* retry line */
+               ret = write(vclient->fd, line, strlen(line) + 1);
+               if (ret <= 0)
+                       goto out_err;
+       }
 
        bufvalid = buf;
        do {
@@ -486,6 +505,13 @@ static int vtysh_execute_func(const char *line, int pager)
                struct vtysh_client *vc;
                for (i = 0; i < array_size(vtysh_client); i++) {
                        if (cmd->daemon & vtysh_client[i].flag) {
+                               if (vtysh_client[i].fd < 0
+                                   && (cmd->daemon == vtysh_client[i].flag)) {
+                                       for (vc = &vtysh_client[i]; vc;
+                                            vc = vc->next)
+                                               if (vc->fd < 0)
+                                                       vtysh_reconnect(vc);
+                               }
                                if (vtysh_client[i].fd < 0
                                    && (cmd->daemon == vtysh_client[i].flag)) {
                                        bool any_inst = false;
@@ -3114,6 +3140,22 @@ static int vtysh_connect(struct vtysh_client *vclient)
        return 0;
 }
 
+static int vtysh_reconnect(struct vtysh_client *vclient)
+{
+       int ret;
+
+       fprintf(stderr, "Warning: connecting to %s...", vclient->name);
+       ret = vtysh_connect(vclient);
+       if (ret < 0) {
+               fprintf(stderr, "failed!\n");
+               return ret;
+       }
+       fprintf(stderr, "success!\n");
+       if (vtysh_client_execute(vclient, "enable", NULL) < 0)
+               return -1;
+       return vtysh_execute_no_pager("end");
+}
+
 /* Return true if str ends with suffix, else return false */
 static int ends_with(const char *str, const char *suffix)
 {
index ccfdd6557b425da2fda33c42419c026330030e05..cbfc1b5b232ab34e37679683f218619d5ce30788 100644 (file)
@@ -40,6 +40,8 @@ DECLARE_MGROUP(MVTYSH)
 #define VTYSH_SHARPD    0x2000
 #define VTYSH_PBRD      0x4000
 
+#define VTYSH_WAS_ACTIVE (-2)
+
 /* commands in REALLYALL are crucial to correct vtysh operation */
 #define VTYSH_REALLYALL          ~0U
 /* watchfrr is not in ALL since library CLI functions should not be