From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) by dpdk.org (Postfix) with ESMTP id 2F7B75A41 for ; Sat, 7 May 2016 08:36:20 +0200 (CEST) Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga102.jf.intel.com with ESMTP; 06 May 2016 23:36:19 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.24,589,1455004800"; d="scan'208";a="948085175" Received: from yliu-dev.sh.intel.com ([10.239.67.162]) by orsmga001.jf.intel.com with ESMTP; 06 May 2016 23:36:18 -0700 From: Yuanhan Liu To: dev@dpdk.org Cc: huawei.xie@intel.com, Yuanhan Liu Date: Fri, 6 May 2016 23:40:21 -0700 Message-Id: <1462603224-29510-4-git-send-email-yuanhan.liu@linux.intel.com> X-Mailer: git-send-email 1.9.0 In-Reply-To: <1462603224-29510-1-git-send-email-yuanhan.liu@linux.intel.com> References: <1462603224-29510-1-git-send-email-yuanhan.liu@linux.intel.com> Subject: [dpdk-dev] [PATCH 3/6] vhost: add reconnect ability X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: patches and discussions about DPDK List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 07 May 2016 06:36:20 -0000 Allow reconnecting on failure when both RTE_VHOST_USER_RECONNECT and RTE_VHOST_USER_CLIENT flags are set. Reconnecting means two things here: - when DPDK app starts first and QEMU (as the server) is not started, without reconnecting, DPDK app would simply fail on vhost-user registration. - when QEMU reboots, without reconnecting, you can't re-establish the connection without restarting DPDK app. This patch make it work well for both above cases. It simply creates a new thread, and keep trying calling "connect()", until it succeeds. Signed-off-by: Yuanhan Liu --- lib/librte_vhost/rte_virtio_net.h | 1 + lib/librte_vhost/vhost_user/vhost-net-user.c | 63 +++++++++++++++++++++++++--- 2 files changed, 59 insertions(+), 5 deletions(-) diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h index c84e7ab..f354d52 100644 --- a/lib/librte_vhost/rte_virtio_net.h +++ b/lib/librte_vhost/rte_virtio_net.h @@ -52,6 +52,7 @@ #include #define RTE_VHOST_USER_CLIENT (1ULL << 0) +#define RTE_VHOST_USER_RECONNECT (1ULL << 1) struct rte_mbuf; diff --git a/lib/librte_vhost/vhost_user/vhost-net-user.c b/lib/librte_vhost/vhost_user/vhost-net-user.c index aa98717..07bce6e 100644 --- a/lib/librte_vhost/vhost_user/vhost-net-user.c +++ b/lib/librte_vhost/vhost_user/vhost-net-user.c @@ -59,6 +59,7 @@ struct vhost_user_socket { char *path; int listenfd; int is_server; + int reconnect; }; struct vhost_user_connection { @@ -78,6 +79,7 @@ struct vhost_user { static void vhost_user_server_new_connection(int fd, void *data, int *remove); static void vhost_user_msg_handler(int fd, void *dat, int *remove); +static int vhost_user_create_client(struct vhost_user_socket *vsocket); static struct vhost_user vhost_user = { .fdset = { @@ -304,6 +306,8 @@ vhost_user_msg_handler(int connfd, void *dat, int *remove) vid = conn->vid; ret = read_vhost_message(connfd, &msg); if (ret <= 0 || msg.request >= VHOST_USER_MAX) { + struct vhost_user_socket *vsocket = conn->vsocket; + if (ret < 0) RTE_LOG(ERR, VHOST_CONFIG, "vhost read message failed\n"); @@ -319,6 +323,9 @@ vhost_user_msg_handler(int connfd, void *dat, int *remove) free(conn); vhost_destroy_device(vid); + if (vsocket->reconnect) + vhost_user_create_client(vsocket); + return; } @@ -470,6 +477,33 @@ err: return -1; } +struct reconnect_info { + struct sockaddr_un un; + int fd; + struct vhost_user_socket *vsocket; +}; + +static void * +vhost_user_client_reconnect(void *arg) +{ + struct reconnect_info *reconn = arg; + int ret; + + RTE_LOG(ERR, VHOST_CONFIG, "reconnecting...\n"); + while (1) { + ret = connect(reconn->fd, (struct sockaddr *)&reconn->un, + sizeof(reconn->un)); + if (ret == 0) + break; + sleep(1); + } + + vhost_user_add_connection(reconn->fd, reconn->vsocket); + free(reconn); + + return NULL; +} + static int vhost_user_create_client(struct vhost_user_socket *vsocket) { @@ -477,22 +511,40 @@ vhost_user_create_client(struct vhost_user_socket *vsocket) int ret; struct sockaddr_un un; const char *path = vsocket->path; + struct reconnect_info *reconn; + pthread_t tid; fd = create_unix_socket(path, &un, vsocket->is_server); if (fd < 0) return -1; ret = connect(fd, (struct sockaddr *)&un, sizeof(un)); - if (ret < 0) { - RTE_LOG(ERR, VHOST_CONFIG, "failed to connect to %s: %s\n", - path, strerror(errno)); + if (ret == 0) { + vhost_user_add_connection(fd, vsocket); + return 0; + } + + RTE_LOG(ERR, VHOST_CONFIG, + "failed to connect to %s: %s\n", + path, strerror(errno)); + + if (!vsocket->reconnect) { close(fd); return -1; } - vhost_user_add_connection(fd, vsocket); + /* Create a thread to try reconnecting, to not block the caller. */ + reconn = malloc(sizeof(*reconn)); + reconn->un = un; + reconn->fd = fd; + reconn->vsocket = vsocket; + ret = pthread_create(&tid, NULL, vhost_user_client_reconnect, reconn); + if (ret < 0) { + close(fd); + RTE_LOG(ERR, VHOST_CONFIG, "failed to create reconnect thread"); + } - return 0; + return ret; } /* @@ -524,6 +576,7 @@ rte_vhost_driver_register(const char *path, uint64_t flags) vsocket->path = strdup(path); if ((flags & RTE_VHOST_USER_CLIENT) != 0) { + vsocket->reconnect = !!(flags & RTE_VHOST_USER_RECONNECT); ret = vhost_user_create_client(vsocket); } else { vsocket->is_server = 1; -- 1.9.0