summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--vtysh/vtysh.c48
-rw-r--r--vtysh/vtysh.h2
2 files changed, 47 insertions, 3 deletions
diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c
index ca372778d6..90c387b48c 100644
--- a/vtysh/vtysh.c
+++ b/vtysh/vtysh.c
@@ -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 {
@@ -490,6 +509,13 @@ static int vtysh_execute_func(const char *line, int pager)
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;
for (vc = &vtysh_client[i]; vc;
vc = vc->next)
@@ -3117,6 +3143,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)
{
diff --git a/vtysh/vtysh.h b/vtysh/vtysh.h
index ccfdd6557b..cbfc1b5b23 100644
--- a/vtysh/vtysh.h
+++ b/vtysh/vtysh.h
@@ -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