diff options
author | Christian Ehrhardt <christian.ehrhardt@canonical.com> | 2017-03-02 16:15:51 +0100 |
---|---|---|
committer | Christian Ehrhardt <christian.ehrhardt@canonical.com> | 2017-03-03 14:41:36 +0100 |
commit | ce3d555e43e3795b5d9507fcfc76b7a0a92fd0d6 (patch) | |
tree | 3a9e9f8f6a62c7146fb391eae34481b2af4f7ff2 /lib/librte_vhost | |
parent | 6b3e017e5d25f15da73f7700f7f2ac553ef1a2e9 (diff) |
Imported Upstream version 16.11.1
Change-Id: I1e965265578efaaf08e5628607f53d2386d2df9f
Signed-off-by: Christian Ehrhardt <christian.ehrhardt@canonical.com>
Diffstat (limited to 'lib/librte_vhost')
-rw-r--r-- | lib/librte_vhost/fd_man.c | 200 | ||||
-rw-r--r-- | lib/librte_vhost/fd_man.h | 2 | ||||
-rw-r--r-- | lib/librte_vhost/vhost.c | 1 | ||||
-rw-r--r-- | lib/librte_vhost/vhost_user.c | 13 | ||||
-rw-r--r-- | lib/librte_vhost/virtio_net.c | 7 |
5 files changed, 110 insertions, 113 deletions
diff --git a/lib/librte_vhost/fd_man.c b/lib/librte_vhost/fd_man.c index 2d3eeb7d..8a075da2 100644 --- a/lib/librte_vhost/fd_man.c +++ b/lib/librte_vhost/fd_man.c @@ -35,93 +35,91 @@ #include <stdio.h> #include <stdlib.h> #include <sys/socket.h> -#include <sys/select.h> #include <sys/time.h> #include <sys/types.h> #include <unistd.h> +#include <string.h> #include <rte_common.h> #include <rte_log.h> #include "fd_man.h" -/** - * Returns the index in the fdset for a given fd. - * If fd is -1, it means to search for a free entry. - * @return - * index for the fd, or -1 if fd isn't in the fdset. - */ +#define FDPOLLERR (POLLERR | POLLHUP | POLLNVAL) + static int -fdset_find_fd(struct fdset *pfdset, int fd) +get_last_valid_idx(struct fdset *pfdset, int last_valid_idx) { int i; - if (pfdset == NULL) - return -1; - - for (i = 0; i < MAX_FDS && pfdset->fd[i].fd != fd; i++) + for (i = last_valid_idx; i >= 0 && pfdset->fd[i].fd == -1; i--) ; - return i == MAX_FDS ? -1 : i; + return i; } -static int -fdset_find_free_slot(struct fdset *pfdset) +static void +fdset_move(struct fdset *pfdset, int dst, int src) { - return fdset_find_fd(pfdset, -1); + pfdset->fd[dst] = pfdset->fd[src]; + pfdset->rwfds[dst] = pfdset->rwfds[src]; } -static int -fdset_add_fd(struct fdset *pfdset, int idx, int fd, - fd_cb rcb, fd_cb wcb, void *dat) +/* + * Find deleted fd entries and remove them + */ +static void +fdset_shrink(struct fdset *pfdset) { - struct fdentry *pfdentry; + int i; + int last_valid_idx = get_last_valid_idx(pfdset, pfdset->num - 1); - if (pfdset == NULL || idx >= MAX_FDS || fd >= FD_SETSIZE) - return -1; + pthread_mutex_lock(&pfdset->fd_mutex); - pfdentry = &pfdset->fd[idx]; - pfdentry->fd = fd; - pfdentry->rcb = rcb; - pfdentry->wcb = wcb; - pfdentry->dat = dat; + for (i = 0; i < last_valid_idx; i++) { + if (pfdset->fd[i].fd != -1) + continue; - return 0; + fdset_move(pfdset, i, last_valid_idx); + last_valid_idx = get_last_valid_idx(pfdset, last_valid_idx - 1); + } + pfdset->num = last_valid_idx + 1; + + pthread_mutex_unlock(&pfdset->fd_mutex); } /** - * Fill the read/write fd_set with the fds in the fdset. + * Returns the index in the fdset for a given fd. * @return - * the maximum fds filled in the read/write fd_set. + * index for the fd, or -1 if fd isn't in the fdset. */ static int -fdset_fill(fd_set *rfset, fd_set *wfset, struct fdset *pfdset) +fdset_find_fd(struct fdset *pfdset, int fd) { - struct fdentry *pfdentry; - int i, maxfds = -1; - int num = MAX_FDS; + int i; - if (pfdset == NULL) - return -1; + for (i = 0; i < pfdset->num && pfdset->fd[i].fd != fd; i++) + ; - for (i = 0; i < num; i++) { - pfdentry = &pfdset->fd[i]; - if (pfdentry->fd != -1) { - int added = 0; - if (pfdentry->rcb && rfset) { - FD_SET(pfdentry->fd, rfset); - added = 1; - } - if (pfdentry->wcb && wfset) { - FD_SET(pfdentry->fd, wfset); - added = 1; - } - if (added) - maxfds = pfdentry->fd < maxfds ? - maxfds : pfdentry->fd; - } - } - return maxfds; + return i == pfdset->num ? -1 : i; +} + +static void +fdset_add_fd(struct fdset *pfdset, int idx, int fd, + fd_cb rcb, fd_cb wcb, void *dat) +{ + struct fdentry *pfdentry = &pfdset->fd[idx]; + struct pollfd *pfd = &pfdset->rwfds[idx]; + + pfdentry->fd = fd; + pfdentry->rcb = rcb; + pfdentry->wcb = wcb; + pfdentry->dat = dat; + + pfd->fd = fd; + pfd->events = rcb ? POLLIN : 0; + pfd->events |= wcb ? POLLOUT : 0; + pfd->revents = 0; } void @@ -151,16 +149,13 @@ fdset_add(struct fdset *pfdset, int fd, fd_cb rcb, fd_cb wcb, void *dat) return -1; pthread_mutex_lock(&pfdset->fd_mutex); - - /* Find a free slot in the list. */ - i = fdset_find_free_slot(pfdset); - if (i == -1 || fdset_add_fd(pfdset, i, fd, rcb, wcb, dat) < 0) { + i = pfdset->num < MAX_FDS ? pfdset->num++ : -1; + if (i == -1) { pthread_mutex_unlock(&pfdset->fd_mutex); return -2; } - pfdset->num++; - + fdset_add_fd(pfdset, i, fd, rcb, wcb, dat); pthread_mutex_unlock(&pfdset->fd_mutex); return 0; @@ -189,7 +184,6 @@ fdset_del(struct fdset *pfdset, int fd) pfdset->fd[i].fd = -1; pfdset->fd[i].rcb = pfdset->fd[i].wcb = NULL; pfdset->fd[i].dat = NULL; - pfdset->num--; i = -1; } pthread_mutex_unlock(&pfdset->fd_mutex); @@ -198,24 +192,6 @@ fdset_del(struct fdset *pfdset, int fd) return dat; } -/** - * Unregister the fd at the specified slot from the fdset. - */ -static void -fdset_del_slot(struct fdset *pfdset, int index) -{ - if (pfdset == NULL || index < 0 || index >= MAX_FDS) - return; - - pthread_mutex_lock(&pfdset->fd_mutex); - - pfdset->fd[index].fd = -1; - pfdset->fd[index].rcb = pfdset->fd[index].wcb = NULL; - pfdset->fd[index].dat = NULL; - pfdset->num--; - - pthread_mutex_unlock(&pfdset->fd_mutex); -} /** * This functions runs in infinite blocking loop until there is no fd in @@ -229,55 +205,64 @@ fdset_del_slot(struct fdset *pfdset, int index) void fdset_event_dispatch(struct fdset *pfdset) { - fd_set rfds, wfds; - int i, maxfds; + int i; + struct pollfd *pfd; struct fdentry *pfdentry; - int num = MAX_FDS; fd_cb rcb, wcb; void *dat; - int fd; + int fd, numfds; int remove1, remove2; - int ret; + int need_shrink; if (pfdset == NULL) return; while (1) { - struct timeval tv; - tv.tv_sec = 1; - tv.tv_usec = 0; - FD_ZERO(&rfds); - FD_ZERO(&wfds); - pthread_mutex_lock(&pfdset->fd_mutex); - - maxfds = fdset_fill(&rfds, &wfds, pfdset); - - pthread_mutex_unlock(&pfdset->fd_mutex); /* - * When select is blocked, other threads might unregister + * When poll is blocked, other threads might unregister * listenfds from and register new listenfds into fdset. - * When select returns, the entries for listenfds in the fdset + * When poll returns, the entries for listenfds in the fdset * might have been updated. It is ok if there is unwanted call * for new listenfds. */ - ret = select(maxfds + 1, &rfds, &wfds, NULL, &tv); - if (ret <= 0) - continue; + pthread_mutex_lock(&pfdset->fd_mutex); + numfds = pfdset->num; + pthread_mutex_unlock(&pfdset->fd_mutex); - for (i = 0; i < num; i++) { - remove1 = remove2 = 0; + poll(pfdset->rwfds, numfds, 1000 /* millisecs */); + + need_shrink = 0; + for (i = 0; i < numfds; i++) { pthread_mutex_lock(&pfdset->fd_mutex); + pfdentry = &pfdset->fd[i]; fd = pfdentry->fd; + pfd = &pfdset->rwfds[i]; + + if (fd < 0) { + need_shrink = 1; + pthread_mutex_unlock(&pfdset->fd_mutex); + continue; + } + + if (!pfd->revents) { + pthread_mutex_unlock(&pfdset->fd_mutex); + continue; + } + + remove1 = remove2 = 0; + rcb = pfdentry->rcb; wcb = pfdentry->wcb; dat = pfdentry->dat; pfdentry->busy = 1; + pthread_mutex_unlock(&pfdset->fd_mutex); - if (fd >= 0 && FD_ISSET(fd, &rfds) && rcb) + + if (rcb && pfd->revents & (POLLIN | FDPOLLERR)) rcb(fd, dat, &remove1); - if (fd >= 0 && FD_ISSET(fd, &wfds) && wcb) + if (wcb && pfd->revents & (POLLOUT | FDPOLLERR)) wcb(fd, dat, &remove2); pfdentry->busy = 0; /* @@ -292,8 +277,13 @@ fdset_event_dispatch(struct fdset *pfdset) * listen fd in another thread, we couldn't call * fd_set_del. */ - if (remove1 || remove2) - fdset_del_slot(pfdset, i); + if (remove1 || remove2) { + pfdentry->fd = -1; + need_shrink = 1; + } } + + if (need_shrink) + fdset_shrink(pfdset); } } diff --git a/lib/librte_vhost/fd_man.h b/lib/librte_vhost/fd_man.h index bd66ed1c..d319cac6 100644 --- a/lib/librte_vhost/fd_man.h +++ b/lib/librte_vhost/fd_man.h @@ -35,6 +35,7 @@ #define _FD_MAN_H_ #include <stdint.h> #include <pthread.h> +#include <poll.h> #define MAX_FDS 1024 @@ -49,6 +50,7 @@ struct fdentry { }; struct fdset { + struct pollfd rwfds[MAX_FDS]; struct fdentry fd[MAX_FDS]; pthread_mutex_t fd_mutex; int num; /* current fd number of this fdset */ diff --git a/lib/librte_vhost/vhost.c b/lib/librte_vhost/vhost.c index 31825b82..e4150934 100644 --- a/lib/librte_vhost/vhost.c +++ b/lib/librte_vhost/vhost.c @@ -250,6 +250,7 @@ vhost_new_device(void) if (i == MAX_VHOST_DEVICE) { RTE_LOG(ERR, VHOST_CONFIG, "Failed to find a free slot for new device.\n"); + rte_free(dev); return -1; } diff --git a/lib/librte_vhost/vhost_user.c b/lib/librte_vhost/vhost_user.c index 6b83c15f..0cb1c677 100644 --- a/lib/librte_vhost/vhost_user.c +++ b/lib/librte_vhost/vhost_user.c @@ -447,14 +447,14 @@ add_guest_pages(struct virtio_net *dev, struct virtio_memory_region *reg, reg_size -= size; while (reg_size > 0) { + size = RTE_MIN(reg_size, page_size); host_phys_addr = rte_mem_virt2phy((void *)(uintptr_t) host_user_addr); - add_one_guest_page(dev, guest_phys_addr, host_phys_addr, - page_size); + add_one_guest_page(dev, guest_phys_addr, host_phys_addr, size); - host_user_addr += page_size; - guest_phys_addr += page_size; - reg_size -= page_size; + host_user_addr += size; + guest_phys_addr += size; + reg_size -= size; } } @@ -567,7 +567,8 @@ vhost_user_set_mem_table(struct virtio_net *dev, struct VhostUserMsg *pmsg) reg->host_user_addr = (uint64_t)(uintptr_t)mmap_addr + mmap_offset; - add_guest_pages(dev, reg, alignment); + if (dev->dequeue_zero_copy) + add_guest_pages(dev, reg, alignment); RTE_LOG(INFO, VHOST_CONFIG, "guest memory region %u, size: 0x%" PRIx64 "\n" diff --git a/lib/librte_vhost/virtio_net.c b/lib/librte_vhost/virtio_net.c index 595f67c4..337470d6 100644 --- a/lib/librte_vhost/virtio_net.c +++ b/lib/librte_vhost/virtio_net.c @@ -195,6 +195,8 @@ copy_mbuf_to_desc(struct virtio_net *dev, struct vring_desc *descs, struct vring_desc *desc; uint64_t desc_addr; struct virtio_net_hdr_mrg_rxbuf virtio_hdr = {{0, 0, 0, 0, 0, 0}, 0}; + /* A counter to avoid desc dead loop chain */ + uint16_t nr_desc = 1; desc = &descs[desc_idx]; desc_addr = gpa_to_vva(dev, desc->addr); @@ -233,7 +235,7 @@ copy_mbuf_to_desc(struct virtio_net *dev, struct vring_desc *descs, /* Room in vring buffer is not enough */ return -1; } - if (unlikely(desc->next >= size)) + if (unlikely(desc->next >= size || ++nr_desc > size)) return -1; desc = &descs[desc->next]; @@ -677,6 +679,7 @@ parse_ethernet(struct rte_mbuf *m, uint16_t *l4_proto, void **l4_hdr) default: m->l3_len = 0; *l4_proto = 0; + *l4_hdr = NULL; break; } } @@ -713,7 +716,7 @@ vhost_dequeue_offload(struct virtio_net_hdr *hdr, struct rte_mbuf *m) } } - if (hdr->gso_type != VIRTIO_NET_HDR_GSO_NONE) { + if (l4_hdr && hdr->gso_type != VIRTIO_NET_HDR_GSO_NONE) { switch (hdr->gso_type & ~VIRTIO_NET_HDR_GSO_ECN) { case VIRTIO_NET_HDR_GSO_TCPV4: case VIRTIO_NET_HDR_GSO_TCPV6: |