From: Liu Ping Fan <pingf...@linux.vnet.ibm.com> Signed-off-by: Liu Ping Fan <pingf...@linux.vnet.ibm.com> --- hw/dataplane/virtio-net.c | 22 +++++++++++ hw/dataplane/virtio-net.h | 6 +++ include/net/tap.h | 6 +++ net/tap.c | 92 ++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 125 insertions(+), 1 deletions(-)
diff --git a/hw/dataplane/virtio-net.c b/hw/dataplane/virtio-net.c index 9a1795d..c3aac08 100644 --- a/hw/dataplane/virtio-net.c +++ b/hw/dataplane/virtio-net.c @@ -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); +} diff --git a/hw/dataplane/virtio-net.h b/hw/dataplane/virtio-net.h index e50b2de..5d6bd34 100644 --- a/hw/dataplane/virtio-net.h +++ b/hw/dataplane/virtio-net.h @@ -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 diff --git a/include/net/tap.h b/include/net/tap.h index bb7efb5..3f78d15 100644 --- a/include/net/tap.h +++ b/include/net/tap.h @@ -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); diff --git a/net/tap.c b/net/tap.c index eb40c42..b6bfed4 100644 --- a/net/tap.c +++ b/net/tap.c @@ -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) -- 1.7.4.4