@@ -68,9 +68,9 @@ static struct ether_addr base_eth_addr = {
};
struct vhost_queue {
+ int vid;
rte_atomic32_t allow_queuing;
rte_atomic32_t while_queuing;
- struct virtio_net *device;
struct pmd_internal *internal;
struct rte_mempool *mb_pool;
uint8_t port;
@@ -137,7 +137,7 @@ eth_vhost_rx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
goto out;
/* Dequeue packets from guest TX queue */
- nb_rx = rte_vhost_dequeue_burst(r->device,
+ nb_rx = rte_vhost_dequeue_burst(r->vid,
r->virtqueue_id, r->mb_pool, bufs, nb_bufs);
r->rx_pkts += nb_rx;
@@ -168,7 +168,7 @@ eth_vhost_tx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
goto out;
/* Enqueue packets to guest RX queue */
- nb_tx = rte_vhost_enqueue_burst(r->device,
+ nb_tx = rte_vhost_enqueue_burst(r->vid,
r->virtqueue_id, bufs, nb_bufs);
r->tx_pkts += nb_tx;
@@ -217,7 +217,7 @@ find_internal_resource(int vid)
}
static int
-new_device(struct virtio_net *dev)
+new_device(int vid)
{
struct rte_eth_dev *eth_dev;
struct internal_list *list;
@@ -228,23 +228,17 @@ new_device(struct virtio_net *dev)
int newnode;
#endif
- if (dev == NULL) {
- RTE_LOG(INFO, PMD, "Invalid argument\n");
- return -1;
- }
-
- list = find_internal_resource(dev->vid);
+ list = find_internal_resource(vid);
if (list == NULL) {
- RTE_LOG(INFO, PMD, "Invalid vid %d\n", dev->vid);
+ RTE_LOG(INFO, PMD, "Invalid vid %d\n", vid);
return -1;
}
eth_dev = list->eth_dev;
internal = eth_dev->data->dev_private;
- internal->vid = dev->vid;
#ifdef RTE_LIBRTE_VHOST_NUMA
- newnode = rte_vhost_get_numa_node(dev->vid);
+ newnode = rte_vhost_get_numa_node(vid);
if (newnode > 0)
eth_dev->data->numa_node = newnode;
#endif
@@ -253,7 +247,7 @@ new_device(struct virtio_net *dev)
vq = eth_dev->data->rx_queues[i];
if (vq == NULL)
continue;
- vq->device = dev;
+ vq->vid = vid;
vq->internal = internal;
vq->port = eth_dev->data->port_id;
}
@@ -261,15 +255,14 @@ new_device(struct virtio_net *dev)
vq = eth_dev->data->tx_queues[i];
if (vq == NULL)
continue;
- vq->device = dev;
+ vq->vid = vid;
vq->internal = internal;
vq->port = eth_dev->data->port_id;
}
- for (i = 0; i < rte_vhost_get_queue_num(dev->vid) * VIRTIO_QNUM; i++)
- rte_vhost_enable_guest_notification(dev, i, 0);
+ for (i = 0; i < rte_vhost_get_queue_num(vid) * VIRTIO_QNUM; i++)
+ rte_vhost_enable_guest_notification(vid, i, 0);
- dev->priv = eth_dev;
eth_dev->data->dev_link.link_status = ETH_LINK_UP;
for (i = 0; i < eth_dev->data->nb_rx_queues; i++) {
@@ -293,22 +286,19 @@ new_device(struct virtio_net *dev)
}
static void
-destroy_device(volatile struct virtio_net *dev)
+destroy_device(int vid)
{
+ struct internal_list *list;
struct rte_eth_dev *eth_dev;
struct vhost_queue *vq;
unsigned i;
- if (dev == NULL) {
- RTE_LOG(INFO, PMD, "Invalid argument\n");
- return;
- }
-
- eth_dev = (struct rte_eth_dev *)dev->priv;
- if (eth_dev == NULL) {
- RTE_LOG(INFO, PMD, "Failed to find a ethdev\n");
+ list = find_internal_resource(vid);
+ if (list == NULL) {
+ RTE_LOG(INFO, PMD, "Invalid vid %d\n", vid);
return;
}
+ eth_dev = list->eth_dev;
/* Wait until rx/tx_pkt_burst stops accessing vhost device */
for (i = 0; i < eth_dev->data->nb_rx_queues; i++) {
@@ -330,19 +320,17 @@ destroy_device(volatile struct virtio_net *dev)
eth_dev->data->dev_link.link_status = ETH_LINK_DOWN;
- dev->priv = NULL;
-
for (i = 0; i < eth_dev->data->nb_rx_queues; i++) {
vq = eth_dev->data->rx_queues[i];
if (vq == NULL)
continue;
- vq->device = NULL;
+ vq->vid = -1;
}
for (i = 0; i < eth_dev->data->nb_tx_queues; i++) {
vq = eth_dev->data->tx_queues[i];
if (vq == NULL)
continue;
- vq->device = NULL;
+ vq->vid = -1;
}
RTE_LOG(INFO, PMD, "Connection closed\n");
@@ -351,20 +339,15 @@ destroy_device(volatile struct virtio_net *dev)
}
static int
-vring_state_changed(struct virtio_net *dev, uint16_t vring, int enable)
+vring_state_changed(int vid, uint16_t vring, int enable)
{
struct rte_vhost_vring_state *state;
struct rte_eth_dev *eth_dev;
struct internal_list *list;
- if (dev == NULL) {
- RTE_LOG(ERR, PMD, "Invalid argument\n");
- return -1;
- }
-
- list = find_internal_resource(dev->vid);
+ list = find_internal_resource(vid);
if (list == NULL) {
- RTE_LOG(ERR, PMD, "Invalid vid %d\n", dev->vid);
+ RTE_LOG(ERR, PMD, "Invalid vid %d\n", vid);
return -1;
}
@@ -701,6 +701,19 @@ find_vhost_dev(struct ether_addr *mac)
return NULL;
}
+static inline struct vhost_dev *__attribute__((always_inline))
+find_vhost_dev_by_vid(int vid)
+{
+ struct vhost_dev *vdev;
+
+ TAILQ_FOREACH(vdev, &vhost_dev_list, next) {
+ if (vdev->ready == DEVICE_RX && vdev->vid == vid)
+ return vdev;
+ }
+
+ return NULL;
+}
+
/*
* This function learns the MAC address of the device and registers this along with a
* vlan tag to a VMDQ.
@@ -796,7 +809,7 @@ virtio_xmit(struct vhost_dev *dst_vdev, struct vhost_dev *src_vdev,
{
uint16_t ret;
- ret = rte_vhost_enqueue_burst(dst_vdev->dev, VIRTIO_RXQ, &m, 1);
+ ret = rte_vhost_enqueue_burst(dst_vdev->vid, VIRTIO_RXQ, &m, 1);
if (enable_stats) {
rte_atomic64_inc(&dst_vdev->stats.rx_total_atomic);
rte_atomic64_add(&dst_vdev->stats.rx_atomic, ret);
@@ -1042,7 +1055,6 @@ static inline void __attribute__((always_inline))
drain_eth_rx(struct vhost_dev *vdev)
{
uint16_t rx_count, enqueue_count;
- struct virtio_net *dev = vdev->dev;
struct rte_mbuf *pkts[MAX_PKT_BURST];
rx_count = rte_eth_rx_burst(ports[0], vdev->vmdq_rx_q,
@@ -1068,7 +1080,7 @@ drain_eth_rx(struct vhost_dev *vdev)
}
}
- enqueue_count = rte_vhost_enqueue_burst(dev, VIRTIO_RXQ,
+ enqueue_count = rte_vhost_enqueue_burst(vdev->vid, VIRTIO_RXQ,
pkts, rx_count);
if (enable_stats) {
rte_atomic64_add(&vdev->stats.rx_total_atomic, rx_count);
@@ -1085,7 +1097,7 @@ drain_virtio_tx(struct vhost_dev *vdev)
uint16_t count;
uint16_t i;
- count = rte_vhost_dequeue_burst(vdev->dev, VIRTIO_TXQ, mbuf_pool,
+ count = rte_vhost_dequeue_burst(vdev->vid, VIRTIO_TXQ, mbuf_pool,
pkts, MAX_PKT_BURST);
/* setup VMDq for the first packet */
@@ -1171,13 +1183,17 @@ switch_worker(void *arg __rte_unused)
* of dev->remove=1 which can cause an infinite loop in the rte_pause loop.
*/
static void
-destroy_device (volatile struct virtio_net *dev)
+destroy_device(int vid)
{
struct vhost_dev *vdev;
int lcore;
- vdev = (struct vhost_dev *)dev->priv;
- /*set the remove flag. */
+ vdev = find_vhost_dev_by_vid(vid);
+ if (!vdev) {
+ RTE_LOG(ERR, VHOST_CONFIG, "(%d) failed to find device\n", vid);
+ return;
+ }
+
vdev->remove = 1;
while(vdev->ready != DEVICE_SAFE_REMOVE) {
rte_pause();
@@ -1214,12 +1230,11 @@ destroy_device (volatile struct virtio_net *dev)
* and the allocated to a specific data core.
*/
static int
-new_device (struct virtio_net *dev)
+new_device(int vid)
{
int lcore, core_add = 0;
uint32_t device_num_min = num_devices;
struct vhost_dev *vdev;
- int vid = dev->vid;
vdev = rte_zmalloc("vhost device", sizeof(*vdev), RTE_CACHE_LINE_SIZE);
if (vdev == NULL) {
@@ -1228,8 +1243,6 @@ new_device (struct virtio_net *dev)
vid);
return -1;
}
- vdev->dev = dev;
- dev->priv = vdev;
vdev->vid = vid;
TAILQ_INSERT_TAIL(&vhost_dev_list, vdev, next);
@@ -1252,8 +1265,8 @@ new_device (struct virtio_net *dev)
lcore_info[vdev->coreid].device_num++;
/* Disable notifications. */
- rte_vhost_enable_guest_notification(dev, VIRTIO_RXQ, 0);
- rte_vhost_enable_guest_notification(dev, VIRTIO_TXQ, 0);
+ rte_vhost_enable_guest_notification(vid, VIRTIO_RXQ, 0);
+ rte_vhost_enable_guest_notification(vid, VIRTIO_TXQ, 0);
RTE_LOG(INFO, VHOST_DATA,
"(%d) device has been added to data core %d\n",
@@ -1309,7 +1322,7 @@ print_stats(void)
"RX total: %" PRIu64 "\n"
"RX dropped: %" PRIu64 "\n"
"RX successful: %" PRIu64 "\n",
- vdev->dev->vid,
+ vdev->vid,
tx_total, tx_dropped, tx,
rx_total, rx_dropped, rx);
}
@@ -178,23 +178,12 @@ struct virtio_memory {
*
*/
struct virtio_net_device_ops {
- int (*new_device)(struct virtio_net *); /**< Add device. */
- void (*destroy_device)(volatile struct virtio_net *); /**< Remove device. */
+ int (*new_device)(int vid); /**< Add device. */
+ void (*destroy_device)(int vid); /**< Remove device. */
- int (*vring_state_changed)(struct virtio_net *dev, uint16_t queue_id, int enable); /**< triggered when a vring is enabled or disabled */
+ int (*vring_state_changed)(int vid, uint16_t queue_id, int enable); /**< triggered when a vring is enabled or disabled */
};
-static inline uint16_t __attribute__((always_inline))
-rte_vring_available_entries(struct virtio_net *dev, uint16_t queue_id)
-{
- struct vhost_virtqueue *vq = dev->virtqueue[queue_id];
-
- if (!vq->enabled)
- return 0;
-
- return *(volatile uint16_t *)&vq->avail->idx - vq->last_used_idx_res;
-}
-
/**
* Function to convert guest physical addresses to vhost virtual addresses.
* This is used to convert guest virtio buffer addresses.
@@ -231,7 +220,7 @@ int rte_vhost_feature_enable(uint64_t feature_mask);
/* Returns currently supported vhost features */
uint64_t rte_vhost_feature_get(void);
-int rte_vhost_enable_guest_notification(struct virtio_net *dev, uint16_t queue_id, int enable);
+int rte_vhost_enable_guest_notification(int vid, uint16_t queue_id, int enable);
/* Register vhost driver. dev_name could be different for multiple instance support. */
int rte_vhost_driver_register(const char *dev_name);
@@ -286,8 +275,8 @@ int rte_vhost_get_numa_node(int vid);
* be received from the physical port or from another virtual device. A packet
* count is returned to indicate the number of packets that were succesfully
* added to the RX queue.
- * @param dev
- * virtio-net device
+ * @param vid
+ * virtio-net device ID
* @param queue_id
* virtio queue index in mq case
* @param pkts
@@ -297,14 +286,14 @@ int rte_vhost_get_numa_node(int vid);
* @return
* num of packets enqueued
*/
-uint16_t rte_vhost_enqueue_burst(struct virtio_net *dev, uint16_t queue_id,
+uint16_t rte_vhost_enqueue_burst(int vid, uint16_t queue_id,
struct rte_mbuf **pkts, uint16_t count);
/**
* This function gets guest buffers from the virtio device TX virtqueue,
* construct host mbufs, copies guest buffer content to host mbufs and
* store them in pkts to be processed.
- * @param dev
+ * @param vid
* virtio-net device
* @param queue_id
* virtio queue index in mq case
@@ -317,7 +306,8 @@ uint16_t rte_vhost_enqueue_burst(struct virtio_net *dev, uint16_t queue_id,
* @return
* num of packets dequeued
*/
-uint16_t rte_vhost_dequeue_burst(struct virtio_net *dev, uint16_t queue_id,
+uint16_t rte_vhost_dequeue_burst(int vid, uint16_t queue_id,
struct rte_mempool *mbuf_pool, struct rte_mbuf **pkts, uint16_t count);
+
#endif /* _VIRTIO_NET_H_ */
@@ -46,6 +46,7 @@
#include <rte_arp.h>
#include "vhost-net.h"
+#include "virtio-net.h"
#define MAX_PKT_BURST 32
#define VHOST_LOG_PAGE 4096
@@ -587,9 +588,14 @@ virtio_dev_merge_rx(struct virtio_net *dev, uint16_t queue_id,
}
uint16_t
-rte_vhost_enqueue_burst(struct virtio_net *dev, uint16_t queue_id,
+rte_vhost_enqueue_burst(int vid, uint16_t queue_id,
struct rte_mbuf **pkts, uint16_t count)
{
+ struct virtio_net *dev = get_device(vid);
+
+ if (!dev)
+ return 0;
+
if (dev->features & (1 << VIRTIO_NET_F_MRG_RXBUF))
return virtio_dev_merge_rx(dev, queue_id, pkts, count);
else
@@ -815,9 +821,10 @@ copy_desc_to_mbuf(struct virtio_net *dev, struct vhost_virtqueue *vq,
}
uint16_t
-rte_vhost_dequeue_burst(struct virtio_net *dev, uint16_t queue_id,
+rte_vhost_dequeue_burst(int vid, uint16_t queue_id,
struct rte_mempool *mbuf_pool, struct rte_mbuf **pkts, uint16_t count)
{
+ struct virtio_net *dev;
struct rte_mbuf *rarp_mbuf = NULL;
struct vhost_virtqueue *vq;
uint32_t desc_indexes[MAX_PKT_BURST];
@@ -826,6 +833,10 @@ rte_vhost_dequeue_burst(struct virtio_net *dev, uint16_t queue_id,
uint16_t free_entries;
uint16_t avail_idx;
+ dev = get_device(vid);
+ if (!dev)
+ return 0;
+
if (unlikely(!is_valid_virt_queue_idx(queue_id, 1, dev->virt_qp_nb))) {
RTE_LOG(ERR, VHOST_DATA, "(%d) %s: invalid virtqueue idx %d.\n",
dev->vid, __func__, queue_id);
@@ -117,7 +117,7 @@ user_set_mem_table(int vid, struct VhostUserMsg *pmsg)
/* Remove from the data plane. */
if (dev->flags & VIRTIO_DEV_RUNNING) {
dev->flags &= ~VIRTIO_DEV_RUNNING;
- notify_ops->destroy_device(dev);
+ notify_ops->destroy_device(vid);
}
if (dev->mem) {
@@ -279,6 +279,9 @@ user_set_vring_kick(int vid, struct VhostUserMsg *pmsg)
struct vhost_vring_file file;
struct virtio_net *dev = get_device(vid);
+ if (!dev)
+ return;
+
file.index = pmsg->payload.u64 & VHOST_USER_VRING_IDX_MASK;
if (pmsg->payload.u64 & VHOST_USER_VRING_NOFD_MASK)
file.fd = VIRTIO_INVALID_EVENTFD;
@@ -289,7 +292,7 @@ user_set_vring_kick(int vid, struct VhostUserMsg *pmsg)
vhost_set_vring_kick(vid, &file);
if (virtio_is_ready(dev) && !(dev->flags & VIRTIO_DEV_RUNNING)) {
- if (notify_ops->new_device(dev) == 0)
+ if (notify_ops->new_device(vid) == 0)
dev->flags |= VIRTIO_DEV_RUNNING;
}
}
@@ -307,7 +310,7 @@ user_get_vring_base(int vid,
return -1;
/* We have to stop the queue (virtio) if it is running. */
if (dev->flags & VIRTIO_DEV_RUNNING)
- notify_ops->destroy_device(dev);
+ notify_ops->destroy_device(vid);
/* Here we are safe to get the last used index */
vhost_get_vring_base(vid, state->index, state);
@@ -342,9 +345,8 @@ user_set_vring_enable(int vid,
"set queue enable: %d to qp idx: %d\n",
enable, state->index);
- if (notify_ops->vring_state_changed) {
- notify_ops->vring_state_changed(dev, state->index, enable);
- }
+ if (notify_ops->vring_state_changed)
+ notify_ops->vring_state_changed(vid, state->index, enable);
dev->virtqueue[state->index]->enabled = enable;
@@ -296,7 +296,7 @@ vhost_destroy_device(int vid)
if (dev->flags & VIRTIO_DEV_RUNNING) {
dev->flags &= ~VIRTIO_DEV_RUNNING;
- notify_ops->destroy_device(dev);
+ notify_ops->destroy_device(vid);
}
cleanup_device(dev, 1);
@@ -353,7 +353,7 @@ vhost_reset_owner(int vid)
if (dev->flags & VIRTIO_DEV_RUNNING) {
dev->flags &= ~VIRTIO_DEV_RUNNING;
- notify_ops->destroy_device(dev);
+ notify_ops->destroy_device(vid);
}
cleanup_device(dev, 0);
@@ -717,21 +717,26 @@ vhost_set_backend(int vid, struct vhost_vring_file *file)
if (!(dev->flags & VIRTIO_DEV_RUNNING)) {
if (dev->virtqueue[VIRTIO_TXQ]->backend != VIRTIO_DEV_STOPPED &&
dev->virtqueue[VIRTIO_RXQ]->backend != VIRTIO_DEV_STOPPED) {
- if (notify_ops->new_device(dev) < 0)
+ if (notify_ops->new_device(vid) < 0)
return -1;
dev->flags |= VIRTIO_DEV_RUNNING;
}
} else if (file->fd == VIRTIO_DEV_STOPPED) {
dev->flags &= ~VIRTIO_DEV_RUNNING;
- notify_ops->destroy_device(dev);
+ notify_ops->destroy_device(vid);
}
return 0;
}
-int rte_vhost_enable_guest_notification(struct virtio_net *dev,
- uint16_t queue_id, int enable)
+int
+rte_vhost_enable_guest_notification(int vid, uint16_t queue_id, int enable)
{
+ struct virtio_net *dev = get_device(vid);
+
+ if (!dev)
+ return -1;
+
if (enable) {
RTE_LOG(ERR, VHOST_CONFIG,
"guest notification isn't supported.\n");