[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Receiving Network Packets with Mirage/kFreeBSD

On Thu, Aug 16, 2012 at 03:13:27PM +0200, PALI Gabor Janos wrote:
> - After loading the built kernel module and starting up the evaluation of
>   the Netif.create function, Mirage asks for a list of available Ethernet
>   interfaces from the FreeBSD kernel and then assigns an lwt thread to each of
>   them by "plugging".
> - Plugged interfaces are stored in a linked list and have their ng_ether(4)
>   hook (called from ether_input()) activated and pointed to
>   netif_ether_input().  At the same time, there is a shared ring buffer
>   created for each of them in Mirage then passed to the C function
>   responsible for administering the list of plugged interfaces,
>   caml_plug_vif().
> - Shared ring buffers are created as Io_pages by allocating page-aligned,
>   contiguous, multi-page memory areas via FreeBSD's contigmalloc(9).  These
>   are directly accessible in Mirage as character arrays.
> - Each shared ring buffer is currently of size 33 pages, and operates with
>   2048-byte slots.  The buffers start with a header that maintains all the
>   required meta information, like next position, available items, size of
>   stored items.

This all sounds spot on design-wise, by the way!  

> - Each packet arriving on any of the plugged interfaces is placed to the next
>   available slot of the corresponding shared ring buffer with m_copydata().
> - In parallel with this in Mirage, the rx_poll function is run in loop that
>   polls for available packets in the shared ring buffer.
> - When rx_poll finds unprocessed packets then it runs the user-specified
>   function on them, e.g. print the size of the packet in basic/netif.  It is
>   implemented by passing a view on the Io_page, i.e. without copying.  After
>   the user function has finished, the packet is removed from the ring.
> - When no packets are available on the polled interface, rx_poll sleeps for a
>   millisecond.

What are your thoughts on a non-spinning interface here?  Can each ring
buffer also have an 'event channel' assigned to it, and then a single
select loop can block on all the event channels?  This isn't a huge deal
for the initial prototype where spinning is acceptable.

> Let me add that shared rings do not do locking at the moment, but if you are
> happy with the design I could proceed with implementing it.  (However, I am
> not completely sure how to share locks between OCaml and C.)

It's best to have a C interface which does an atomic test-and-set onto an
OCaml array, which can then be tested from within the Lwt/kFreeBSD
Activations code.  The OCaml code is guaranteed to not be running when
it's in a C-binding (assuming a single thread), so this should simplify

Anil Madhavapeddy                                 http://anil.recoil.org



Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.