Module IPv4

IPv4 protocol layer.

This module handles IPv4 packet encoding, decoding, fragmentation, and reassembly. It maintains a routing table (via ARPv4) to resolve destination IPv4 addresses to MAC addresses.

Zero-copy and payload types.

When an IPv4 packet arrives, it may or may not have been fragmented in transit. The payload type reflects this:

Upper layers (TCP, UDP) handle both cases transparently.

Route discovery.

write may need to resolve the destination's MAC address via ARPv4. This involves sending an ARP request and waiting for a reply, which constitutes an "interruption" (the current Miou task may be suspended). An internal cache avoids repeated lookups. If you already know the MAC address, use write_directly which never interrupts.

module Flag : sig ... end
module Packet : sig ... end
type t

The IPv4 protocol state. Maintains the routing/ARP cache, fragmentation reassembly state, and configured addresses.

val tags : t -> Logs.Tag.set

When IPv4 sends logs, it can attach information such as the source IPv4 and the destination to which the logs relate. The user can obtain this information through the Logs API (and tags) and display it in order to better characterize the information that IPv4 can send (especially with regard to debugging).

type packet = {
  1. src : Ipaddr.V4.t;
  2. dst : Ipaddr.V4.t;
  3. protocol : int;
  4. uid : int;
}

Metadata about a received IPv4 packet, passed to upper-layer handlers.

  • protocol: the upper-layer protocol (6 = TCP, 17 = UDP, 1 = ICMP).
  • uid: the IP identification field.
and payload =
  1. | Slice of Slice_bstr.t
  2. | String of string

The payload of a received IPv4 packet. See the module documentation for the distinction between Slice (zero-copy, non-fragmented) and String (reassembled from fragments).

val create : ?to_expire:int -> Ethernet.t -> ARPv4.t -> ?gateway:Ipaddr.V4.t -> ?handler:((packet * payload) -> unit) -> Ipaddr.V4.Prefix.t -> (t, [> `MTU_too_small ]) result

create ?to_expire eth arpv4 ?gateway ?handler cidr creates a new IPv4 protocol handler.

  • to_expire (nanoseconds): how long to keep fragments in the reassembly cache before discarding them (defaults to 10 seconds).
  • eth: the Ethernet layer used for frame I/O.
  • arpv4: the ARPv4 state for address resolution.
  • gateway: the default IPv4 gateway. If absent, only On-Link destinations can be reached.
  • handler: the function called when a complete IPv4 packet is received (and reassembled if fragmented). Typically installed later via set_handler.
  • cidr: the local IPv4 address and prefix (e.g. 10.0.0.2/24).

Returns `MTU_too_small if the Ethernet MTU is too small for IPv4.

val src : t -> dst:Ipaddr.V4.t -> Ipaddr.V4.t

It is morally possible for a unikernel to have several IPv4 addresses, each of which can communicate with certain destinations (depending on the routes discovered). In this case, the user is able to determine the source IPv4 address required to communicate with the given destination.

In practice, the implementation is configured to have only one IPv4 address. This assertion is therefore true:

let open Ipaddr in
let dst0 = V4.of_octets (Mirage_crypto_rng.generate 4) |> Result.get_ok in
let src0 = Mnet.IPv4.src ipv4 ~dst:dst0 in
let dst1 = V4.of_octets (Mirage_crypto_rng.generate 4) |> Result.get_ok in
let src1 = Mnet.IPv4.src ipv4 ~dst:dst1 in
assert (V4.compare src0 src1 = 0)
val addresses : t -> Ipaddr.V4.Prefix.t list

addresses t returns the addresses on which the given state t is mounted.

module Writer : sig ... end

Efficient IPv4 payload composition.

val write_directly : t -> ?ttl:int -> Ipaddr.V4.t -> (Ipaddr.V4.t * Macaddr.t) -> protocol:int -> Writer.t -> unit

write_directly ipv4 ?ttl src (dst, macaddr) ~protocol w writes a new IPv4 packet w effectively (without interruption) (fragmented or not) to the specified destination macaddr.

val write : t -> ?ttl:int -> ?src:Ipaddr.V4.t -> Ipaddr.V4.t -> protocol:int -> Writer.t -> (unit, [> `Route_not_found ]) result

write ipv4 ?ttl ?src dst ~protocol w writes a new IPv4 packet w (fragmented or not) to the specified destination dst. This function may have an interruption to discover the route to send the given packet to dst (an underlying cache exists for such discovery).

val attempt_to_discover_destination : t -> Ipaddr.V4.t -> Macaddr.t option

attempt_to_discover_destination ipv4 dst attempts to return the MAC address to which we would like to send a packet if we wish to send it to dst.

val input : t -> Slice_bstr.t Ethernet.packet -> unit

input ipv4 pkt is the function to install as an IPv4 handler for an Ethernet daemon. It analyze incoming IPv4 packets and update the given state ipv4.

val set_handler : t -> ((packet * payload) -> unit) -> unit

When a packet is received (and reassembled if it has been fragmented), the handler is called with the IPv4 information (source, destination and protocol, see packet) so that the upper layer (such as TCP) can process it. set_handler allows you to modify this handler in order to direct incoming packets to a specific process.