Skip to content

Commit

Permalink
Merge pull request #174 from virtualopensystems/non-zero-copy
Browse files Browse the repository at this point in the history
Handle non zero copy case in virtio device
  • Loading branch information
lukego committed May 20, 2014
2 parents b110f87 + f112a7a commit 77d2a92
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 9 deletions.
4 changes: 2 additions & 2 deletions src/apps/vhost/vhost_user.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,13 +136,13 @@ int vhost_user_receive(int sock, struct vhost_user_msg *msg, int *fds,
return ret;
}

void* vhost_user_map_guest_memory(int fd, int size)
void* vhost_user_map_guest_memory(int fd, uint64_t size)
{
void *ptr = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
return ptr == MAP_FAILED ? 0 : ptr;
}

int vhost_user_unmap_guest_memory(void *ptr, int size)
int vhost_user_unmap_guest_memory(void *ptr, uint64_t size)
{
return munmap(ptr, size);
}
Expand Down
4 changes: 2 additions & 2 deletions src/apps/vhost/vhost_user.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,6 @@ int vhost_user_connect(const char *path);
int vhost_user_send(int sock, struct vhost_user_msg *msg);
int vhost_user_receive(int sock, struct vhost_user_msg *msg, int *fds,
int *nfds);
void* vhost_user_map_guest_memory(int fd, int size);
int vhost_user_unmap_guest_memory(void *ptr, int size);
void* vhost_user_map_guest_memory(int fd, uint64_t size);
int vhost_user_unmap_guest_memory(void *ptr, uint64_t size);
int vhost_user_sync_shm(void *ptr, size_t size);
50 changes: 45 additions & 5 deletions src/lib/virtio/net_device.lua
Original file line number Diff line number Diff line change
Expand Up @@ -176,18 +176,53 @@ end
-- Prepared argument for writing a 1 to an eventfd.
local eventfd_one = ffi.new("uint64_t[1]", {1})

function VirtioNetDevice:more_vm_buffers ()
return freelist.nfree(self.vring_transmit_buffers) > 2
end

-- return the buffer from a iovec, ensuring it originates from the vm
function VirtioNetDevice:vm_buffer (iovec)
local should_continue = true
local b = iovec.buffer
-- check if this is a zero-copy packet
if b.origin.type ~= C.BUFFER_ORIGIN_VIRTIO then
-- get buffer from the once supplied by the VM
local old_b = b
b = freelist.remove(self.vring_transmit_buffers)
--assert(iovec.offset + iovec.length <= b.size)

-- copy the whole buffer data, including offset
ffi.copy(b.pointer, old_b.pointer, iovec.offset + iovec.length)
buffer.free(old_b)
iovec.buffer = b

if not self:more_vm_buffers() then
-- no more buffers, stop the loop
should_continue = false
end
end
return should_continue, b
end

-- Transmit packets from the app input queue to the VM.
function VirtioNetDevice:transmit_packets_to_vm ()
local l = self.owner.input.rx
if not l then return end
while not link.empty(l) do
local should_continue = not self.not_enough_vm_bufers

while (not link.empty(l)) and should_continue do
local p = link.receive(l)
local iovec = p.iovecs[0]
local b = iovec.buffer
local virtio_hdr = b.origin.info.virtio.header_pointer

--assert(b.origin.type == C.BUFFER_ORIGIN_VIRTIO)
-- ensure all data is in a single buffer
if p.niovecs > 1 then
packet.coalesce(p)
end

local iovec = p.iovecs[0]
should_continue, b = self:vm_buffer(iovec)

-- fill in the virtio header
local virtio_hdr = b.origin.info.virtio.header_pointer
ffi.copy(virtio_hdr, p.info, packet_info_size)

local used = self.txring.used.ring[self.txused%self.tx_vring_num]
Expand All @@ -200,6 +235,11 @@ function VirtioNetDevice:transmit_packets_to_vm ()
packet.deref(p)
end

if not should_continue then
-- not enough buffers detected, verify once again
self.not_enough_vm_bufers = not self:more_vm_buffers()
end

if self.txring.used.idx ~= self.txused then
self.txring.used.idx = self.txused
C.write(self.callfd[0], eventfd_one, 8)
Expand Down

0 comments on commit 77d2a92

Please sign in to comment.