xref: /openbmc/qemu/net/vde.c (revision 7587855c)
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