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 "config-host.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" 335c361cc3SMark McLoughlin 345c361cc3SMark McLoughlin typedef struct VDEState { 354e68f7a0SStefan Hajnoczi NetClientState nc; 365c361cc3SMark McLoughlin VDECONN *vde; 375c361cc3SMark McLoughlin } VDEState; 385c361cc3SMark McLoughlin 395c361cc3SMark McLoughlin static void vde_to_qemu(void *opaque) 405c361cc3SMark McLoughlin { 415c361cc3SMark McLoughlin VDEState *s = opaque; 42d32fcad3SScott Feldman uint8_t buf[NET_BUFSIZE]; 435c361cc3SMark McLoughlin int size; 445c361cc3SMark McLoughlin 455c361cc3SMark McLoughlin size = vde_recv(s->vde, (char *)buf, sizeof(buf), 0); 465c361cc3SMark McLoughlin if (size > 0) { 47b4e859c6SMark McLoughlin qemu_send_packet(&s->nc, buf, size); 485c361cc3SMark McLoughlin } 495c361cc3SMark McLoughlin } 505c361cc3SMark McLoughlin 514e68f7a0SStefan Hajnoczi static ssize_t vde_receive(NetClientState *nc, const uint8_t *buf, size_t size) 525c361cc3SMark McLoughlin { 53b4e859c6SMark McLoughlin VDEState *s = DO_UPCAST(VDEState, nc, nc); 545c361cc3SMark McLoughlin ssize_t ret; 555c361cc3SMark McLoughlin 565c361cc3SMark McLoughlin do { 575c361cc3SMark McLoughlin ret = vde_send(s->vde, (const char *)buf, size, 0); 585c361cc3SMark McLoughlin } while (ret < 0 && errno == EINTR); 595c361cc3SMark McLoughlin 605c361cc3SMark McLoughlin return ret; 615c361cc3SMark McLoughlin } 625c361cc3SMark McLoughlin 634e68f7a0SStefan Hajnoczi static void vde_cleanup(NetClientState *nc) 645c361cc3SMark McLoughlin { 65b4e859c6SMark McLoughlin VDEState *s = DO_UPCAST(VDEState, nc, nc); 665c361cc3SMark McLoughlin qemu_set_fd_handler(vde_datafd(s->vde), NULL, NULL, NULL); 675c361cc3SMark McLoughlin vde_close(s->vde); 685c361cc3SMark McLoughlin } 695c361cc3SMark McLoughlin 70b4e859c6SMark McLoughlin static NetClientInfo net_vde_info = { 712be64a68SLaszlo Ersek .type = NET_CLIENT_OPTIONS_KIND_VDE, 72b4e859c6SMark McLoughlin .size = sizeof(VDEState), 73b4e859c6SMark McLoughlin .receive = vde_receive, 74b4e859c6SMark McLoughlin .cleanup = vde_cleanup, 75b4e859c6SMark McLoughlin }; 76b4e859c6SMark McLoughlin 774e68f7a0SStefan Hajnoczi static int net_vde_init(NetClientState *peer, const char *model, 785c361cc3SMark McLoughlin const char *name, const char *sock, 795c361cc3SMark McLoughlin int port, const char *group, int mode) 805c361cc3SMark McLoughlin { 814e68f7a0SStefan Hajnoczi NetClientState *nc; 825c361cc3SMark McLoughlin VDEState *s; 83b4e859c6SMark McLoughlin VDECONN *vde; 845c361cc3SMark McLoughlin char *init_group = (char *)group; 855c361cc3SMark McLoughlin char *init_sock = (char *)sock; 865c361cc3SMark McLoughlin 875c361cc3SMark McLoughlin struct vde_open_args args = { 885c361cc3SMark McLoughlin .port = port, 895c361cc3SMark McLoughlin .group = init_group, 905c361cc3SMark McLoughlin .mode = mode, 915c361cc3SMark McLoughlin }; 925c361cc3SMark McLoughlin 93b4e859c6SMark McLoughlin vde = vde_open(init_sock, (char *)"QEMU", &args); 94b4e859c6SMark McLoughlin if (!vde){ 955c361cc3SMark McLoughlin return -1; 965c361cc3SMark McLoughlin } 97b4e859c6SMark McLoughlin 98ab5f3f84SStefan Hajnoczi nc = qemu_new_net_client(&net_vde_info, peer, model, name); 99b4e859c6SMark McLoughlin 100b4e859c6SMark McLoughlin snprintf(nc->info_str, sizeof(nc->info_str), "sock=%s,fd=%d", 101b4e859c6SMark McLoughlin sock, vde_datafd(vde)); 102b4e859c6SMark McLoughlin 103b4e859c6SMark McLoughlin s = DO_UPCAST(VDEState, nc, nc); 104b4e859c6SMark McLoughlin 105b4e859c6SMark McLoughlin s->vde = vde; 106b4e859c6SMark McLoughlin 1075c361cc3SMark McLoughlin qemu_set_fd_handler(vde_datafd(s->vde), vde_to_qemu, NULL, s); 108b4e859c6SMark McLoughlin 1095c361cc3SMark McLoughlin return 0; 1105c361cc3SMark McLoughlin } 1115c361cc3SMark McLoughlin 1121a0c0958SLaszlo Ersek int net_init_vde(const NetClientOptions *opts, const char *name, 113*a30ecde6SMarkus Armbruster NetClientState *peer, Error **errp) 1145c361cc3SMark McLoughlin { 115*a30ecde6SMarkus Armbruster /* FIXME error_setg(errp, ...) on failure */ 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