15c361cc3SMark McLoughlin /* 25c361cc3SMark McLoughlin * QEMU System Emulator 35c361cc3SMark McLoughlin * 45c361cc3SMark McLoughlin * Copyright (c) 2003-2008 Fabrice Bellard 55c361cc3SMark McLoughlin * 65c361cc3SMark McLoughlin * Permission is hereby granted, free of charge, to any person obtaining a copy 75c361cc3SMark McLoughlin * of this software and associated documentation files (the "Software"), to deal 85c361cc3SMark McLoughlin * in the Software without restriction, including without limitation the rights 95c361cc3SMark McLoughlin * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 105c361cc3SMark McLoughlin * copies of the Software, and to permit persons to whom the Software is 115c361cc3SMark McLoughlin * furnished to do so, subject to the following conditions: 125c361cc3SMark McLoughlin * 135c361cc3SMark McLoughlin * The above copyright notice and this permission notice shall be included in 145c361cc3SMark McLoughlin * all copies or substantial portions of the Software. 155c361cc3SMark McLoughlin * 165c361cc3SMark McLoughlin * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 175c361cc3SMark McLoughlin * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 185c361cc3SMark McLoughlin * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 195c361cc3SMark McLoughlin * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 205c361cc3SMark McLoughlin * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 215c361cc3SMark McLoughlin * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 225c361cc3SMark McLoughlin * THE SOFTWARE. 235c361cc3SMark McLoughlin */ 245c361cc3SMark McLoughlin #include "net/vde.h" 255c361cc3SMark McLoughlin 265c361cc3SMark McLoughlin #include "config-host.h" 275c361cc3SMark McLoughlin 285c361cc3SMark McLoughlin #include <libvdeplug.h> 295c361cc3SMark McLoughlin 305c361cc3SMark McLoughlin #include "net.h" 315c361cc3SMark McLoughlin #include "qemu-char.h" 325c361cc3SMark McLoughlin #include "qemu-common.h" 335c361cc3SMark McLoughlin #include "qemu-option.h" 345c361cc3SMark McLoughlin 355c361cc3SMark McLoughlin typedef struct VDEState { 36*4e68f7a0SStefan Hajnoczi NetClientState nc; 375c361cc3SMark McLoughlin VDECONN *vde; 385c361cc3SMark McLoughlin } VDEState; 395c361cc3SMark McLoughlin 405c361cc3SMark McLoughlin static void vde_to_qemu(void *opaque) 415c361cc3SMark McLoughlin { 425c361cc3SMark McLoughlin VDEState *s = opaque; 435c361cc3SMark McLoughlin uint8_t buf[4096]; 445c361cc3SMark McLoughlin int size; 455c361cc3SMark McLoughlin 465c361cc3SMark McLoughlin size = vde_recv(s->vde, (char *)buf, sizeof(buf), 0); 475c361cc3SMark McLoughlin if (size > 0) { 48b4e859c6SMark McLoughlin qemu_send_packet(&s->nc, buf, size); 495c361cc3SMark McLoughlin } 505c361cc3SMark McLoughlin } 515c361cc3SMark McLoughlin 52*4e68f7a0SStefan Hajnoczi static ssize_t vde_receive(NetClientState *nc, const uint8_t *buf, size_t size) 535c361cc3SMark McLoughlin { 54b4e859c6SMark McLoughlin VDEState *s = DO_UPCAST(VDEState, nc, nc); 555c361cc3SMark McLoughlin ssize_t ret; 565c361cc3SMark McLoughlin 575c361cc3SMark McLoughlin do { 585c361cc3SMark McLoughlin ret = vde_send(s->vde, (const char *)buf, size, 0); 595c361cc3SMark McLoughlin } while (ret < 0 && errno == EINTR); 605c361cc3SMark McLoughlin 615c361cc3SMark McLoughlin return ret; 625c361cc3SMark McLoughlin } 635c361cc3SMark McLoughlin 64*4e68f7a0SStefan Hajnoczi static void vde_cleanup(NetClientState *nc) 655c361cc3SMark McLoughlin { 66b4e859c6SMark McLoughlin VDEState *s = DO_UPCAST(VDEState, nc, nc); 675c361cc3SMark McLoughlin qemu_set_fd_handler(vde_datafd(s->vde), NULL, NULL, NULL); 685c361cc3SMark McLoughlin vde_close(s->vde); 695c361cc3SMark McLoughlin } 705c361cc3SMark McLoughlin 71b4e859c6SMark McLoughlin static NetClientInfo net_vde_info = { 722be64a68SLaszlo Ersek .type = NET_CLIENT_OPTIONS_KIND_VDE, 73b4e859c6SMark McLoughlin .size = sizeof(VDEState), 74b4e859c6SMark McLoughlin .receive = vde_receive, 75b4e859c6SMark McLoughlin .cleanup = vde_cleanup, 76b4e859c6SMark McLoughlin }; 77b4e859c6SMark McLoughlin 78*4e68f7a0SStefan Hajnoczi static int net_vde_init(NetClientState *peer, const char *model, 795c361cc3SMark McLoughlin const char *name, const char *sock, 805c361cc3SMark McLoughlin int port, const char *group, int mode) 815c361cc3SMark McLoughlin { 82*4e68f7a0SStefan Hajnoczi NetClientState *nc; 835c361cc3SMark McLoughlin VDEState *s; 84b4e859c6SMark McLoughlin VDECONN *vde; 855c361cc3SMark McLoughlin char *init_group = (char *)group; 865c361cc3SMark McLoughlin char *init_sock = (char *)sock; 875c361cc3SMark McLoughlin 885c361cc3SMark McLoughlin struct vde_open_args args = { 895c361cc3SMark McLoughlin .port = port, 905c361cc3SMark McLoughlin .group = init_group, 915c361cc3SMark McLoughlin .mode = mode, 925c361cc3SMark McLoughlin }; 935c361cc3SMark McLoughlin 94b4e859c6SMark McLoughlin vde = vde_open(init_sock, (char *)"QEMU", &args); 95b4e859c6SMark McLoughlin if (!vde){ 965c361cc3SMark McLoughlin return -1; 975c361cc3SMark McLoughlin } 98b4e859c6SMark McLoughlin 99ab5f3f84SStefan Hajnoczi nc = qemu_new_net_client(&net_vde_info, peer, model, name); 100b4e859c6SMark McLoughlin 101b4e859c6SMark McLoughlin snprintf(nc->info_str, sizeof(nc->info_str), "sock=%s,fd=%d", 102b4e859c6SMark McLoughlin sock, vde_datafd(vde)); 103b4e859c6SMark McLoughlin 104b4e859c6SMark McLoughlin s = DO_UPCAST(VDEState, nc, nc); 105b4e859c6SMark McLoughlin 106b4e859c6SMark McLoughlin s->vde = vde; 107b4e859c6SMark McLoughlin 1085c361cc3SMark McLoughlin qemu_set_fd_handler(vde_datafd(s->vde), vde_to_qemu, NULL, s); 109b4e859c6SMark McLoughlin 1105c361cc3SMark McLoughlin return 0; 1115c361cc3SMark McLoughlin } 1125c361cc3SMark McLoughlin 1131a0c0958SLaszlo Ersek int net_init_vde(const NetClientOptions *opts, const char *name, 114*4e68f7a0SStefan Hajnoczi NetClientState *peer) 1155c361cc3SMark McLoughlin { 1164a917c39SLaszlo Ersek const NetdevVdeOptions *vde; 1175c361cc3SMark McLoughlin 1184a917c39SLaszlo Ersek assert(opts->kind == NET_CLIENT_OPTIONS_KIND_VDE); 1194a917c39SLaszlo Ersek vde = opts->vde; 1205c361cc3SMark McLoughlin 1214a917c39SLaszlo Ersek /* missing optional values have been initialized to "all bits zero" */ 122d33d93b2SStefan Hajnoczi if (net_vde_init(peer, "vde", name, vde->sock, vde->port, vde->group, 1234a917c39SLaszlo Ersek vde->has_mode ? vde->mode : 0700) == -1) { 1245c361cc3SMark McLoughlin return -1; 1255c361cc3SMark McLoughlin } 1265c361cc3SMark McLoughlin 1275c361cc3SMark McLoughlin return 0; 1285c361cc3SMark McLoughlin } 129