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"
301de7afc9SPaolo Bonzini #include "qemu/option.h"
313f124b68SLiming Wang #include "qemu/main-loop.h"
327587855cSJulia Suvorova via Qemu-devel #include "qapi/error.h"
335c361cc3SMark McLoughlin
345c361cc3SMark McLoughlin typedef struct VDEState {
354e68f7a0SStefan Hajnoczi NetClientState nc;
365c361cc3SMark McLoughlin VDECONN *vde;
375c361cc3SMark McLoughlin } VDEState;
385c361cc3SMark McLoughlin
vde_to_qemu(void * opaque)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
vde_receive(NetClientState * nc,const uint8_t * buf,size_t size)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
vde_cleanup(NetClientState * nc)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 = {
71f394b2e2SEric Blake .type = NET_CLIENT_DRIVER_VDE,
72b4e859c6SMark McLoughlin .size = sizeof(VDEState),
73b4e859c6SMark McLoughlin .receive = vde_receive,
74b4e859c6SMark McLoughlin .cleanup = vde_cleanup,
75b4e859c6SMark McLoughlin };
76b4e859c6SMark McLoughlin
net_vde_init(NetClientState * peer,const char * model,const char * name,const char * sock,int port,const char * group,int mode,Error ** errp)774e68f7a0SStefan Hajnoczi static int net_vde_init(NetClientState *peer, const char *model,
785c361cc3SMark McLoughlin const char *name, const char *sock,
797587855cSJulia Suvorova via Qemu-devel int port, const char *group, int mode, Error **errp)
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){
957587855cSJulia Suvorova via Qemu-devel error_setg_errno(errp, errno, "Could not open vde");
965c361cc3SMark McLoughlin return -1;
975c361cc3SMark McLoughlin }
98b4e859c6SMark McLoughlin
99ab5f3f84SStefan Hajnoczi nc = qemu_new_net_client(&net_vde_info, peer, model, name);
100b4e859c6SMark McLoughlin
101*53b85d95SLaurent Vivier qemu_set_info_str(nc, "sock=%s,fd=%d", sock, vde_datafd(vde));
102d89b4f83SJason Wang
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
net_init_vde(const Netdev * netdev,const char * name,NetClientState * peer,Error ** errp)112cebea510SKővágó, Zoltán int net_init_vde(const Netdev *netdev, const char *name,
113a30ecde6SMarkus Armbruster NetClientState *peer, Error **errp)
1145c361cc3SMark McLoughlin {
1154a917c39SLaszlo Ersek const NetdevVdeOptions *vde;
1165c361cc3SMark McLoughlin
117f394b2e2SEric Blake assert(netdev->type == NET_CLIENT_DRIVER_VDE);
118f394b2e2SEric Blake vde = &netdev->u.vde;
1195c361cc3SMark McLoughlin
1204a917c39SLaszlo Ersek /* missing optional values have been initialized to "all bits zero" */
121d33d93b2SStefan Hajnoczi if (net_vde_init(peer, "vde", name, vde->sock, vde->port, vde->group,
1227587855cSJulia Suvorova via Qemu-devel vde->has_mode ? vde->mode : 0700, errp) == -1) {
1235c361cc3SMark McLoughlin return -1;
1245c361cc3SMark McLoughlin }
1255c361cc3SMark McLoughlin
1265c361cc3SMark McLoughlin return 0;
1275c361cc3SMark McLoughlin }
128