mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-06-20 04:33:55 +00:00
dm: support VMs communication with virtio-console
Add feature that client uos can still connect to server uos after rebooting. Tracked-On: #3459 Signed-off-by: Gao Junhao <junhao.gao@intel.com> Reviewed-by: Jian Jun Chen <jian.jun.chen@intel.com> Acked-by: Yu Wang <yu1.wang@intel.com>
This commit is contained in:
parent
18ecdc123a
commit
ff299d5c50
@ -109,7 +109,9 @@ struct virtio_console_port {
|
|||||||
struct virtio_console_backend {
|
struct virtio_console_backend {
|
||||||
struct virtio_console_port *port;
|
struct virtio_console_port *port;
|
||||||
struct mevent *evp;
|
struct mevent *evp;
|
||||||
|
struct mevent *conn_evp;
|
||||||
int fd;
|
int fd;
|
||||||
|
int server_fd;
|
||||||
bool open;
|
bool open;
|
||||||
enum virtio_console_be_type be_type;
|
enum virtio_console_be_type be_type;
|
||||||
int pts_fd; /* only valid for PTY */
|
int pts_fd; /* only valid for PTY */
|
||||||
@ -428,6 +430,19 @@ virtio_console_reset_backend(struct virtio_console_backend *be)
|
|||||||
be->open = false;
|
be->open = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
virtio_console_socket_clear(struct virtio_console_backend *be)
|
||||||
|
{
|
||||||
|
if (be->conn_evp) {
|
||||||
|
mevent_delete(be->conn_evp);
|
||||||
|
be->conn_evp = NULL;
|
||||||
|
}
|
||||||
|
if (be->fd != -1) {
|
||||||
|
close(be->fd);
|
||||||
|
be->fd = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
virtio_console_backend_read(int fd __attribute__((unused)),
|
virtio_console_backend_read(int fd __attribute__((unused)),
|
||||||
enum ev_type t __attribute__((unused)),
|
enum ev_type t __attribute__((unused)),
|
||||||
@ -470,6 +485,11 @@ virtio_console_backend_read(int fd __attribute__((unused)),
|
|||||||
if (len == -1 && errno == EAGAIN)
|
if (len == -1 && errno == EAGAIN)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* when client uos reboot or shutdown,
|
||||||
|
* be->fd will be closed, then the return
|
||||||
|
* value of readv function will be 0 */
|
||||||
|
if (len == 0 || errno == ECONNRESET)
|
||||||
|
goto clear;
|
||||||
/* any other errors */
|
/* any other errors */
|
||||||
goto close;
|
goto close;
|
||||||
}
|
}
|
||||||
@ -478,11 +498,22 @@ virtio_console_backend_read(int fd __attribute__((unused)),
|
|||||||
} while (vq_has_descs(vq));
|
} while (vq_has_descs(vq));
|
||||||
|
|
||||||
vq_endchains(vq, 1);
|
vq_endchains(vq, 1);
|
||||||
|
return;
|
||||||
|
|
||||||
close:
|
close:
|
||||||
virtio_console_reset_backend(be);
|
virtio_console_reset_backend(be);
|
||||||
WPRINTF(("vtcon: be read failed and close! len = %d, errno = %d\n",
|
WPRINTF(("vtcon: be read failed and close! len = %d, errno = %d\n",
|
||||||
len, errno));
|
len, errno));
|
||||||
|
clear:
|
||||||
|
if (be->be_type == VIRTIO_CONSOLE_BE_SOCKET && (be->socket_type == NULL
|
||||||
|
|| !strcmp(be->socket_type,"server"))) {
|
||||||
|
virtio_console_socket_clear(be);
|
||||||
|
} else if (be->be_type == VIRTIO_CONSOLE_BE_SOCKET
|
||||||
|
&& !strcmp(be->socket_type,"client")) {
|
||||||
|
virtio_console_reset_backend(be);
|
||||||
|
WPRINTF(("vtcon: be read failed and close! len = %d, errno = %d\n",
|
||||||
|
len, errno));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -517,6 +548,13 @@ virtio_console_backend_write(struct virtio_console_port *port, void *arg,
|
|||||||
if (ret == -1 && (errno == EAGAIN || errno == ENOTCONN))
|
if (ret == -1 && (errno == EAGAIN || errno == ENOTCONN))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (ret == -1 && errno == EBADF) {
|
||||||
|
if (be->be_type == VIRTIO_CONSOLE_BE_SOCKET && (be->socket_type == NULL
|
||||||
|
|| !strcmp(be->socket_type,"server"))) {
|
||||||
|
virtio_console_socket_clear(be);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
virtio_console_reset_backend(be);
|
virtio_console_reset_backend(be);
|
||||||
WPRINTF(("vtcon: be write failed! errno = %d\n", errno));
|
WPRINTF(("vtcon: be write failed! errno = %d\n", errno));
|
||||||
}
|
}
|
||||||
@ -617,7 +655,6 @@ virtio_console_accept_new_connection(int fd __attribute__((unused)),
|
|||||||
{
|
{
|
||||||
|
|
||||||
int accepted_fd;
|
int accepted_fd;
|
||||||
int close_true;
|
|
||||||
uint32_t len;
|
uint32_t len;
|
||||||
struct sockaddr_un addr;
|
struct sockaddr_un addr;
|
||||||
struct virtio_console_backend *be = arg;
|
struct virtio_console_backend *be = arg;
|
||||||
@ -628,30 +665,18 @@ virtio_console_accept_new_connection(int fd __attribute__((unused)),
|
|||||||
addr.sun_path[sizeof(addr.sun_path) - 1] = '\0';
|
addr.sun_path[sizeof(addr.sun_path) - 1] = '\0';
|
||||||
|
|
||||||
len = sizeof(addr);
|
len = sizeof(addr);
|
||||||
accepted_fd = accept(be->fd, (struct sockaddr *)&addr, &len);
|
/* be->server_fd is kept for client uos reconnect again */
|
||||||
|
accepted_fd = accept(be->server_fd, (struct sockaddr *)&addr, &len);
|
||||||
if (accepted_fd == -1) {
|
if (accepted_fd == -1) {
|
||||||
WPRINTF(("accept error= %d, addr.sun_path=%s\n", errno, addr.sun_path));
|
WPRINTF(("accept error= %d, addr.sun_path=%s\n", errno, addr.sun_path));
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
/* close the fd associated with listening socket
|
|
||||||
* and reuse it for accepted socket.
|
|
||||||
*/
|
|
||||||
close_true = 1;
|
|
||||||
setsockopt(be->fd, SOL_SOCKET, SO_REUSEADDR, &close_true, sizeof(int));
|
|
||||||
close(be->fd);
|
|
||||||
be->fd = accepted_fd;
|
be->fd = accepted_fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (be->evp) {
|
be->conn_evp = mevent_add(be->fd, EVF_READ, virtio_console_backend_read, be,
|
||||||
/* close the event associated with listening socket
|
NULL, NULL);
|
||||||
* and reuse it for accepted socket.
|
if (be->conn_evp == NULL) {
|
||||||
*/
|
|
||||||
mevent_delete(be->evp);
|
|
||||||
}
|
|
||||||
|
|
||||||
be->evp = mevent_add(be->fd, EVF_READ, virtio_console_backend_read, be,
|
|
||||||
virtio_console_teardown_backend, be);
|
|
||||||
if (be->evp == NULL) {
|
|
||||||
WPRINTF(("accepted fd mevent_add failed\n"));
|
WPRINTF(("accepted fd mevent_add failed\n"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -745,21 +770,11 @@ virtio_console_config_backend(struct virtio_console_backend *be)
|
|||||||
WPRINTF(("Backend config: fcntl Error\n"));
|
WPRINTF(("Backend config: fcntl Error\n"));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
be->evp = mevent_add(fd, EVF_READ, virtio_console_accept_new_connection, be, NULL, NULL);
|
|
||||||
if (be->evp == NULL) {
|
|
||||||
WPRINTF(("Socket Accept mevent_add failed\n"));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
} else if (!strcmp(be->socket_type,"client")) {
|
} else if (!strcmp(be->socket_type,"client")) {
|
||||||
if (access(be->portpath,0)) {
|
if (access(be->portpath,0)) {
|
||||||
WPRINTF(("%s not exist\n", be->portpath));
|
WPRINTF(("%s not exist\n", be->portpath));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
* When the VM reset, client will not able to connect to server.
|
|
||||||
* But here only show some warning.
|
|
||||||
* TODO: implement re-connect function
|
|
||||||
*/
|
|
||||||
if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
|
if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
|
||||||
WPRINTF(("vtcon: connect error[%d] \n", errno));
|
WPRINTF(("vtcon: connect error[%d] \n", errno));
|
||||||
} else {
|
} else {
|
||||||
@ -866,6 +881,7 @@ virtio_console_add_backend(struct virtio_console *console, char *opt)
|
|||||||
}
|
}
|
||||||
|
|
||||||
be->fd = fd;
|
be->fd = fd;
|
||||||
|
be->server_fd = fd;
|
||||||
be->be_type = be_type;
|
be->be_type = be_type;
|
||||||
be->portpath = portpath;
|
be->portpath = portpath;
|
||||||
be->socket_type = socket_type;
|
be->socket_type = socket_type;
|
||||||
@ -885,17 +901,24 @@ virtio_console_add_backend(struct virtio_console *console, char *opt)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (virtio_console_backend_can_read(be_type)) {
|
if (virtio_console_backend_can_read(be_type)) {
|
||||||
if (isatty(fd)) {
|
if (be->be_type == VIRTIO_CONSOLE_BE_SOCKET && (be->socket_type == NULL
|
||||||
|
|| !strcmp(be->socket_type,"server"))) {
|
||||||
|
be->evp = mevent_add(fd, EVF_READ,
|
||||||
|
virtio_console_accept_new_connection, be,
|
||||||
|
virtio_console_teardown_backend, be);
|
||||||
|
}
|
||||||
|
else if (isatty(fd) || (be->be_type == VIRTIO_CONSOLE_BE_SOCKET
|
||||||
|
&& !strcmp(be->socket_type,"client"))) {
|
||||||
be->evp = mevent_add(fd, EVF_READ,
|
be->evp = mevent_add(fd, EVF_READ,
|
||||||
virtio_console_backend_read, be,
|
virtio_console_backend_read, be,
|
||||||
virtio_console_teardown_backend, be);
|
virtio_console_teardown_backend, be);
|
||||||
if (be->evp == NULL) {
|
|
||||||
WPRINTF(("vtcon: mevent_add failed\n"));
|
|
||||||
error = -1;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
console->ref_count++;
|
|
||||||
}
|
}
|
||||||
|
if (be->evp == NULL) {
|
||||||
|
WPRINTF(("vtcon: mevent_add failed\n"));
|
||||||
|
error = -1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
console->ref_count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtio_console_open_port(be->port, true);
|
virtio_console_open_port(be->port, true);
|
||||||
@ -952,6 +975,15 @@ virtio_console_close_backend(struct virtio_console_backend *be)
|
|||||||
case VIRTIO_CONSOLE_BE_STDIO:
|
case VIRTIO_CONSOLE_BE_STDIO:
|
||||||
virtio_console_restore_stdio();
|
virtio_console_restore_stdio();
|
||||||
break;
|
break;
|
||||||
|
case VIRTIO_CONSOLE_BE_SOCKET:
|
||||||
|
if (be->socket_type == NULL || !strcmp(be->socket_type,"server")) {
|
||||||
|
virtio_console_socket_clear(be);
|
||||||
|
if (be->server_fd > 0) {
|
||||||
|
close(be->server_fd);
|
||||||
|
be->server_fd = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user