Module Mkernel.Net

type t

The type of network interfaces.

type mac = private string

The type of the hardware addres (MAC) of an ethernet interface.

type cfg = {
  1. mac : mac;
  2. mtu : int;
}
val read_bigstring : t -> ?off:int -> ?len:int -> bigstring -> int

read_bigstring t ?off ?len bstr reads len (defaults to Bigarray.Array1.dim bstr - off) bytes from the net device t, storing them in byte sequence bstr, starting at position off (defaults to 0) in bstr. Return the number of bytes actually read.

read_bigstring attempts an initial read. If it fails, we give the scheduler the opportunity to execute another task. The current task will be resumed as soon as bytes are available in the given net-device t.

val read_bytes : t -> ?off:int -> ?len:int -> bytes -> int

read_bytes is read_bigstring but for bytes. However, this function uses an internal buffer (of a fixed size) which transmits the bytes from the net-device to the byte given by the user. If the byte given by the user is larger than the internal buffer, several actual reads are made.

This means that a single read_bytes can give the scheduler several opportunities to execute other tasks.

Writing to a net device according to the backend.

Depending on the backend used (Solo5/hvt or Unikraft & Solo5/virtio), writing to a TAP interface may involve an intermediate "queue" between the unikernel (which fills this queue) and the tender (which consumes this queue). This feature allows for a process on the tender side that attempts to write without interruption (and thus improves performance).

In this case, unlike Solo5/hvt, writing is not necessarily effective between the unikernel and the TAP interface. However, this effectiveness also involves the tender's point of view, which is not taken into account (deliberately) in this documentation.

Furthermore, from the point of view of the unikernel, OCaml and Miou (and only on that side), the write is effective.

val write_bigstring : t -> ?off:int -> ?len:int -> bigstring -> unit

write_bigstring t ?off ?len bstr writes len (defaults to Bigarray.Array1.dim bstr - off) bytes to the net device t, taking them from byte sequence bstr, starting at position off (defaults to 0) in bstr.

write_bigstring is currently writing directly to the net device t. In other words, the write is effective and does not give the scheduler the opportunity to execute another task during the write. It is therefore an atomic operation. Writing cannot fail.

val write_string : t -> ?off:int -> ?len:int -> string -> unit

Like write_bigstring, but for string.

val write_into : t -> len:int -> fn:(bigstring -> int) -> unit

Depending on the backend used, an underlying allocation may be performed to write a new Ethernet frame. In the case of Unikraft, for example, we need to allocate a buffer that will be added to Unikraft's internal queue so that it can be written to the TAP interface. The same applies to Solo5 and its virtio support.

write_into has the same characteristic as write_bigstring, i.e. it is an atomic operation that does not give the scheduler the opportunity to execute another task.

In this specific case, write_into is more useful than write_bigstring because it prepares the allocation and lets the user write to the allocated buffer via the given fn function.

val connect : string -> (t * cfg, [> `Msg of string ]) result

connect name returns a net device according to the given name. It must correspond to the name given as an argument to the Solo5 tender. For example, if the invocation of our unikernel with Solo5 corresponds to:

  $ solo5-hvt --net:service=tap0 -- unikernel.hvt

The name of the block would be: "service".