@@ -246,6 +246,7 @@ static void rx_cb(EventHandler *handler, uint32_t events)
{
VirtIONet *n = handler->opaque;
+ tap_enable_read(n->nic->nc.peer);
event_notifier_test_and_clear(handler->notifier);
qemu_flush_queued_packets(&n->nic->nc);
}
@@ -388,6 +389,7 @@ void virtnet_dataplane_start(VirtIONet *n)
event_poll_add(&t->polltbl, n->dp->rx_handler, rx_e, rx_cb);
event_poll_add(&t->polltbl, n->dp->tx_handler, tx_e, tx_cb);
+ tap_create_epoll_event(n->nic->nc.peer);
}
void virtnet_dataplane_stop(VirtIONet *n)
@@ -398,6 +400,7 @@ void virtnet_dataplane_stop(VirtIONet *n)
event_poll_del_fd(&t->polltbl, event_notifier_get_fd(rx_e));
event_poll_del_fd(&t->polltbl, event_notifier_get_fd(tx_e));
+ tap_del_epoll_event(n->nic->nc.peer);
t->state = THREAD_EXIT;
event_notifier_set(&t->e);
@@ -420,3 +423,22 @@ void virtnet_dataplane_destroy(VirtIONet *n)
g_free(n->dp->tx_handler);
g_free(n->dp);
}
+
+void thread_add_event(WorkThread *t, uint32_t event_type, EventHandler *handler)
+{
+ event_poll_add_fd(&t->polltbl, handler->fd, event_type, handler);
+ event_notifier_set(&t->e);
+}
+
+void thread_del_event(WorkThread *t, EventHandler *handler)
+{
+ event_poll_del_fd(&t->polltbl, handler->fd);
+ event_notifier_set(&t->e);
+}
+
+void thread_modify_event(WorkThread *t, uint32_t event_type,
+ EventHandler *handler)
+{
+ event_poll_modify_fd(&t->polltbl, handler->fd, event_type, handler);
+ event_notifier_set(&t->e);
+}
@@ -23,4 +23,10 @@ typedef struct WorkThread {
} WorkThread;
extern WorkThread virt_net_thread;
+
+void thread_add_event(WorkThread *t, uint32_t event_type,
+ EventHandler *handler);
+void thread_del_event(WorkThread *t, EventHandler *handler);
+void thread_modify_event(WorkThread *t, uint32_t event_type,
+ EventHandler *handler);
#endif
@@ -29,6 +29,12 @@
#include "qemu-common.h"
#include "qapi-types.h"
+#ifdef CONFIG_VIRTIO_NET_DATA_PLANE
+int tap_create_epoll_event(NetClientState *nc);
+int tap_del_epoll_event(NetClientState *nc);
+void tap_enable_read(NetClientState *nc);
+#endif
+
int tap_has_ufo(NetClientState *nc);
int tap_has_vnet_hdr(NetClientState *nc);
int tap_has_vnet_hdr_len(NetClientState *nc, int len);
@@ -27,6 +27,7 @@
#include "config-host.h"
+#include <sys/epoll.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/wait.h>
@@ -43,6 +44,7 @@
#include "net/tap.h"
#include "hw/vhost_net.h"
+#include "hw/dataplane/virtio-net.h"
/* Maximum GSO packet size (64k) plus plenty of room for
* the ethernet and virtio_net headers
@@ -61,14 +63,22 @@ typedef struct TAPState {
unsigned int has_ufo: 1;
VHostNetState *vhost_net;
unsigned host_vnet_hdr_len;
+
+#ifdef CONFIG_VIRTIO_NET_DATA_PLANE
+ EventHandler tap_evt;
+ uint32_t tap_events;
+ bool start;
+#endif
} TAPState;
static int launch_script(const char *setup_script, const char *ifname, int fd);
-
+#ifndef CONFIG_VIRTIO_NET_DATA_PLANE
static int tap_can_send(void *opaque);
+#endif
static void tap_send(void *opaque);
static void tap_writable(void *opaque);
+#ifndef CONFIG_VIRTIO_NET_DATA_PLANE
static void tap_update_fd_handler(TAPState *s)
{
qemu_set_fd_handler2(s->fd,
@@ -77,18 +87,96 @@ static void tap_update_fd_handler(TAPState *s)
s->write_poll ? tap_writable : NULL,
s);
}
+#endif
static void tap_read_poll(TAPState *s, int enable)
{
+#ifdef CONFIG_VIRTIO_NET_DATA_PLANE
+ if (!s->start) {
+ return;
+ }
+ if (s->read_poll == !!enable) {
+ return;
+ }
+
+ s->read_poll = !!enable;
+ if (enable) {
+ s->tap_events |= EPOLLIN;
+ } else {
+ s->tap_events &= ~EPOLLIN;
+ }
+ thread_modify_event(&virt_net_thread, s->tap_events, &s->tap_evt);
+#else
s->read_poll = !!enable;
tap_update_fd_handler(s);
+#endif
}
static void tap_write_poll(TAPState *s, int enable)
{
+#ifdef CONFIG_VIRTIO_NET_DATA_PLANE
+ if (!s->start) {
+ return;
+ }
+ if (s->write_poll == !!enable) {
+ return;
+ }
+ s->write_poll = !!enable;
+ if (enable) {
+ s->tap_events |= EPOLLOUT;
+ } else {
+ s->tap_events &= ~EPOLLOUT;
+ }
+ thread_modify_event(&virt_net_thread, s->tap_events, &s->tap_evt);
+#else
s->write_poll = !!enable;
tap_update_fd_handler(s);
+#endif
+}
+
+#ifdef CONFIG_VIRTIO_NET_DATA_PLANE
+static void tap_epoll_handle(EventHandler *handler, uint32_t events)
+{
+ if (events & EPOLLIN) {
+ tap_send(handler->opaque);
+ }
+ if (events & EPOLLOUT) {
+ tap_writable(handler->opaque);
+ }
+}
+
+int tap_create_epoll_event(NetClientState *nc)
+{
+ TAPState *s = DO_UPCAST(TAPState, nc, nc);
+
+ s->tap_evt.callback = tap_epoll_handle;
+ s->tap_evt.opaque = s;
+ s->tap_evt.notifier = NULL;
+ s->tap_evt.fd = s->fd;
+
+ thread_add_event(&virt_net_thread, EPOLLIN|EPOLLOUT, &s->tap_evt);
+ s->start = true;
+ return 0;
+}
+
+int tap_del_epoll_event(NetClientState *nc)
+{
+ TAPState *s = DO_UPCAST(TAPState, nc, nc);
+
+ thread_del_event(&virt_net_thread, &s->tap_evt);
+ s->start = false;
+ return 0;
+}
+
+void tap_enable_read(NetClientState *nc)
+{
+ TAPState *s = DO_UPCAST(TAPState, nc, nc);
+
+ if (s->start) {
+ tap_read_poll(s, 1);
+ }
}
+#endif
static void tap_writable(void *opaque)
{
@@ -169,12 +257,14 @@ static ssize_t tap_receive(NetClientState *nc, const uint8_t *buf, size_t size)
return tap_write_packet(s, iov, 1);
}
+#ifndef CONFIG_VIRTIO_NET_DATA_PLANE
static int tap_can_send(void *opaque)
{
TAPState *s = opaque;
return qemu_can_send_packet(&s->nc);
}
+#endif
#ifndef __sun__
ssize_t tap_read_packet(int tapfd, uint8_t *buf, int maxlen)