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 */ 242744d920SPeter Maydell #include "qemu/osdep.h" 255c361cc3SMark McLoughlin 265c361cc3SMark McLoughlin #include <libvdeplug.h> 275c361cc3SMark McLoughlin 281422e32dSPaolo Bonzini #include "net/net.h" 29a245fc18SPaolo Bonzini #include "clients.h" 305c361cc3SMark McLoughlin #include "qemu-common.h" 311de7afc9SPaolo Bonzini #include "qemu/option.h" 323f124b68SLiming Wang #include "qemu/main-loop.h" 33*7587855cSJulia Suvorova via Qemu-devel #include "qapi/error.h" 345c361cc3SMark McLoughlin 355c361cc3SMark McLoughlin typedef struct VDEState { 364e68f7a0SStefan 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; 43d32fcad3SScott Feldman uint8_t buf[NET_BUFSIZE]; 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 524e68f7a0SStefan 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 644e68f7a0SStefan 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 = { 72f394b2e2SEric Blake .type = NET_CLIENT_DRIVER_VDE, 73b4e859c6SMark McLoughlin .size = sizeof(VDEState), 74b4e859c6SMark McLoughlin .receive = vde_receive, 75b4e859c6SMark McLoughlin .cleanup = vde_cleanup, 76b4e859c6SMark McLoughlin }; 77b4e859c6SMark McLoughlin 784e68f7a0SStefan Hajnoczi static int net_vde_init(NetClientState *peer, const char *model, 795c361cc3SMark McLoughlin const char *name, const char *sock, 80*7587855cSJulia Suvorova via Qemu-devel int port, const char *group, int mode, Error **errp) 815c361cc3SMark McLoughlin { 824e68f7a0SStefan 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){ 96*7587855cSJulia Suvorova via Qemu-devel error_setg_errno(errp, errno, "Could not open vde"); 975c361cc3SMark McLoughlin return -1; 985c361cc3SMark McLoughlin } 99b4e859c6SMark McLoughlin 100ab5f3f84SStefan Hajnoczi nc = qemu_new_net_client(&net_vde_info, peer, model, name); 101b4e859c6SMark McLoughlin 102b4e859c6SMark McLoughlin snprintf(nc->info_str, sizeof(nc->info_str), "sock=%s,fd=%d", 103b4e859c6SMark McLoughlin sock, vde_datafd(vde)); 104b4e859c6SMark McLoughlin 105b4e859c6SMark McLoughlin s = DO_UPCAST(VDEState, nc, nc); 106b4e859c6SMark McLoughlin 107b4e859c6SMark McLoughlin s->vde = vde; 108b4e859c6SMark McLoughlin 1095c361cc3SMark McLoughlin qemu_set_fd_handler(vde_datafd(s->vde), vde_to_qemu, NULL, s); 110b4e859c6SMark McLoughlin 1115c361cc3SMark McLoughlin return 0; 1125c361cc3SMark McLoughlin } 1135c361cc3SMark McLoughlin 114cebea510SKővágó, Zoltán int net_init_vde(const Netdev *netdev, const char *name, 115a30ecde6SMarkus Armbruster NetClientState *peer, Error **errp) 1165c361cc3SMark McLoughlin { 1174a917c39SLaszlo Ersek const NetdevVdeOptions *vde; 1185c361cc3SMark McLoughlin 119f394b2e2SEric Blake assert(netdev->type == NET_CLIENT_DRIVER_VDE); 120f394b2e2SEric Blake vde = &netdev->u.vde; 1215c361cc3SMark McLoughlin 1224a917c39SLaszlo Ersek /* missing optional values have been initialized to "all bits zero" */ 123d33d93b2SStefan Hajnoczi if (net_vde_init(peer, "vde", name, vde->sock, vde->port, vde->group, 124*7587855cSJulia Suvorova via Qemu-devel vde->has_mode ? vde->mode : 0700, errp) == -1) { 1255c361cc3SMark McLoughlin return -1; 1265c361cc3SMark McLoughlin } 1275c361cc3SMark McLoughlin 1285c361cc3SMark McLoughlin return 0; 1295c361cc3SMark McLoughlin } 130