dpdk librte_vhost

vhost-user/Qemu之间的消息解析:

VHOST_USER_GET_FEATURES:vhost-user收到此消息,需要将自己所支持的特性,用”|”组成u64的值,放在VhostUserMsg里面的u64回复给Qemu,这里面的features包含GSO/GRO等信息

VHOST_USER_SET_FEATURES:vhost-user收到此消息,消息体中带有u64的前端支持的features,前后端都支持的features生效

VHOST_USER_SET_MEM_TABLE: 主要做共享内存的映射

  • 判断nregions是否超过最大值,目前是8片
  • 如果dev->mem已经映射过,判断是否跟之前一致,若一致则关闭每个region的fd
  • 如果映射过,且与之前不一致,则free掉旧的,重新映射
  • 清空iotlb
  • 分配dev->guest_pages在普通堆上
  • 开始填充memory regions:对于每一片内存,一一对应

因此:

mmap_addr = mmap(…, (size + mmap_offset), …, fd, …);
host_user_addr = mmap_addr + mmap_offset;

如果virtqueue里面的desc/avail/used vring是空,则后面VHOST_USER_SET_VRING_ADDR会做vring地址从qva_to_vva()的转换。

如果virtqueue里面的desc/avalil/used vring非空,就说明之前初始化过,这次memory table更新,需要重新更新virtqueue。

/* Converts QEMU virtual address to Vhost virtual address. */
static uint64_t qva_to_vva(struct virtio_net *dev, uint64_t qva, uint64_t *len)
{
    struct rte_vhost_mem_region *r;
    uint32_t i;
    if (unlikely(!dev || !dev->mem))
        goto out_error;
    /* Find the region where the address lives. */
    for (i = 0; i < dev->mem->nregions; i++) {
        r = &dev->mem->regions[i];
       if (qva >= r->guest_user_addr && qva < r->guest_user_addr + r->size) {
            if (unlikely(*len > r->guest_user_addr + r->size - qva))
                *len = r->guest_user_addr + r->size - qva;
            return qva - r->guest_user_addr + r->host_user_addr;
        }
    }
out_error:
    *len = 0;
    return 0;
}

根据上面从qemu得到的内存信息,更新virtqueue, 需要将qemu发送下来的desc vring/avail vring/used vring的地址通过qva_to_vva()转换成vhost-user看到的地址对于qva_to_vva()也比较好理解,根据qemu传下来的vring地址,和memory regions的地址,找到在哪一片region;然后在region的偏移量offset = qva - guest_user_addr;在vhost-user中看到的地址就是这一片region的起始地址host_user_addr + offset; 至此,VHOST_USER_SET_MEM_TABLE就结束了。

VHOST_USER_SET_VRING_NUM:队列深度,desc数量

VHOST_USER_SET_VRING_ADDR:将qemu空间的desc/avail/used vring的地址转换成vhost-user空间中的virtual memory

VHOST_USER_SET_VRING_BASE:qemu告诉vhost-user,avail vring让vhost-user开始使用的位置。index是rx queue or tx queue,num是idx

VHOST_USER_SET_VRING_ENABLE:enable队列,同样是使用vhost_vring_state的数据结构,index代表rx queue还是tx queue,num代表enable/disable

virtio-device收发报文

  • virtio-device发送报文(virtio-device -> NIC):

    available ring就是由virtio-device从avail ring中读取报文描述符,把报文拷贝到mbuf中。used ring就是virtio-device在从avail ring中读取报文后,会把用完的描述符放入used ring中。

  • virtio-device接收报文(NIC -> virtio-device):

    avail ring是virtio-device从avail ring中读取可用的描述符。used ring是virtio-device会把要发送的报文从mbuf拷贝到描述符指向的地址中,并将描述符id放入used ring[]中,virtio-net通过used ring来读取收到的报文。

Copyright © Jason 2019-2024 all right reserved,powered by Gitbook本书发布时间: 2021-12-06 21:08:08

results matching ""

    No results matching ""