JustKernel
Ray Of Hope
QEMU Networking Vhost-user & Transport Infiniband – series 3, vring implementation
This description and understanding is based on the vhost-user implementation and the vapp sample application shared by the VirtualOpenSystems.
vhost_client.c new_vhost_client()
{
vhost_client = new client(); //create a new clietn.
vhost_client->page_size = VHOST_CLIENT_PAGE_SIZE;
vhost_client->memory.nregions = VHOST_CLIENT_VRING_NUM; 2 : 1 for tx and 1 for Rx.
each region is backed by the socket and mapped to each individual client and server address space.
for each nregion
{
create a shared memory. sdm = init_shm(“vhost.sock”, page_size, idx//0 and 1 for each nregion)
init_shm(char * path, size, idx)
{
path = concatenate vhost.sock and idx //path = vhost.sock0 and vhost.sock1 for each nregion.
fd = shm_open()
init_shm_from_fd(fd, size)
} //for init_shm
init_shm_from_fd
{
void * mmaped_memory = mmap(size, fd, 0); map the shared memory to clinet address space.
} // for init_shm_from_fd
vhost_client->memory.regions[idx].guest_phys_addr = (uintptr_t) shm;
vhost_client->memory.regions[idx].memory_size = vhost_client->page_size;
vhost_client->memory.regions[idx].userspace_addr = (uintptr_t) shm;
// init vrings on the shm(throung memory regions)
vring_table_from_memory_region(vhost_client->vring_table_shm, VHOST_CLIENT_VRING_NUM, &vhost_client->memory)
} //for for loop
}//for new_vhost_clietn
vring_table_from_memory_Region(struct vhost_vring * vring_table[], size_t vring_table_num, VhostUserMemory *memory)
{
for i < 2
vring = new_vring(memory->regions[i].guesT_phys_address);
}
new_vring(void * vring_base)
{
struct vhost_vring * (struct vhost_vring*) vring_base)
uintptr_t ptr = (uintptr_t) ((char*)vring + sizeof(struct vhost_vring));
// Layout the descriptor table
for (i = 0; i < VHOST_VRING_SIZE; i++) {
// align the pointer
ptr = ALIGN(ptr, BUFFER_ALIGNMENT);
vring->desc[i].addr = ptr;
vring->desc[i].len = BUFFER_SIZE;
vring->desc[i].flags = VIRTIO_DESC_F_WRITE;
vring->desc[i].next = i+1;
ptr += vring->desc[i].len;
}
}
vhost_client.c init_vhost_client()
{
/* copies the fds of the shared areas. Shared areas contain vrings.
share the fds with server so that server can also open these shared area and map to its own address spac.e
vhost_ioctl(vhost_client->client, VHOST_USER_SET_MEM_TABLE, &vhost_client->memory);
vhost_user_send_fds(client->sock, &msg, fds, fd_num) // this function calls sendmsg to sed messages to the server. message contains fds.
}
server.c recv_sock_server // call in handler vhost_user_recv_fds; read data from fds
vhost_server.c .
set_mem_table(ServerMsg *msg)
for (idx = 0; idx < msg->msg.memory.nregions; idx++) {
if (msg->fds[idx] > 0) {
VhostServerMemoryRegion *region = &vhost_server->memory.regions[idx];
region->guest_phys_addr = msg->msg.memory.regions[idx].guest_phys_addr;
region->memory_size = msg->msg.memory.regions[idx].memory_size;
region->userspace_addr = msg->msg.memory.regions[idx].userspace_addr;
assert(idx < msg->fd_num);
assert(msg->fds[idx] > 0);
region->mmap_addr = //this is the mmapped address int he server address space.
(uintptr_t) init_shm_from_fd(msg->fds[idx], region->memory_size); //these are the fds that were opened
by the client.
vhost_server->memory.nregions++;
}
}
Now vrings are shared between client and server. So a packet transferred from the guest running on client machine can reach to Server (host) with ZERO copy transfer. Now I am working on transferring the packet from Server host to Server guest.
In actual scenario, assume client as QEMU and server as any usermode process like snabbswitch or any third party application etc.
Thanks
Anshul makkar
anshul_makkar@justkernel.com
Tags: qemu, vhost-net, virtio-net, vring
Leave a Reply