package mirage-vnetif

  1. Overview
  2. Docs
Virtual network interface and software switch for Mirage

Install

Dune Dependency

Authors

Maintainers

Sources

mirage-vnetif-0.4.1.tbz
sha256=9049f14348e26838dde7906c23763d0ea415937895c2510811ae62c76e9e6301
md5=5b8e5c8fd0b1eb93d5296b03d62eb0b7

Description

Provides the module Vnetif which can be used as a replacement for the regular Netif implementation in Xen and Unix. Stacks built using Vnetif are connected to a software switch that allows the stacks to communicate as if they were connected to the same LAN.

An example of a unikernel that communicates with itself over Vnetif can be seen here. An iperf-like performance test is available here. The examples can be compiled for Unix and Xen and do not need access to a real network interface.

Install

opam install mirage-vnetif

Getting started

First, construct a TCP/IP stack based on vnetif:

  module S = struct
    module B = Basic_backend.Make
    module V = Vnetif.Make(B)
    module E = Ethif.Make(V)
    module I = Ipv4.Make(E)(Clock)(OS.Time)
    module U = Udp.Make(I)
    module T = Tcp.Flow.Make(I)(OS.Time)(Clock)(Random)
    module S = Tcpip_stack_direct.Make(C)(OS.Time)(Random)(V)(E)(I)(U)(T)
    include S
  end

Since we don't have the mirage-tool to help us we have to construct the stack manually. This code would usually be generated in main.ml by mirage configure --xen/unix.

let or_error name fn t =
    fn t
    >>= function
        | `Error e -> fail (Failure ("Error starting " ^ name))
        | `Ok t -> return t 

let create_stack c backend ip netmask gw =
    or_error "backend" S.V.connect backend >>= fun netif ->
    or_error "ethif" S.E.connect netif >>= fun ethif ->
    or_error "ipv4" S.I.connect ethif >>= fun ipv4 ->
    or_error "udpv4" S.U.connect ipv4 >>= fun udpv4 ->
    or_error "tcpv4" S.T.connect ipv4 >>= fun tcpv4 ->
    let config = {
        Mirage_types_lwt.name = "stack";
        Mirage_types_lwt.console = c; 
        Mirage_types_lwt.interface = netif;
        Mirage_types_lwt.mode = `IPv4 (ip, netmask, gw);
    } in
    or_error "stack" (S.connect config ethif ipv4 udpv4) tcpv4

We can now create multiple stacks that talk over the same backend. Basic_backend.create accepts two optional parameters:

  • use_async_readers makes the write calls non-blocking. This is necessary to use Vnetif with the Mirage TCP/IP stack.
  • yield specifies the yield function to use in non-blocking mode. In a unikernel this is typically OS.Time.sleep 0.0, but in a Unix process Lwt_main.yield () can be used instead.

let () =

    (* create async backend with OS.Time.sleep 0.0 as yield *)
    let backend = Basic_backend.create ~use_async_readers:true 
        ~yield:(fun() -> OS.Time.sleep 0.0 ) () in

    let netmask = Ipaddr.V4.of_string_exn "255.255.255.0"  in
    let gw = Ipaddr.V4.of_string_exn "10.0.0.1" in

    let server_ip = Ipaddr.V4.of_string_exn "10.0.0.100" in
    create_stack c backend server_ip netmask [gw] >>= fun server_stack ->

    let client_ip = Ipaddr.V4.of_string_exn "10.0.0.101" in
    create_stack c backend server_ip netmask [gw] >>= fun client_stack ->

The stacks can now be used as regular Mirage TCP/IP stacks, e.g.:

S.listen_tcpv4 server_stack ~port:80 (fun f -> ...);
S.listen s1

Build examples

mirage configure --xen/--unix
make

Tags

org:mirage

Published: 11 Jan 2019

README

mirage-vnetif -- Virtual network interface and software switch for Mirage

Provides the module Vnetif which can be used as a replacement for the regular Netif implementation in Xen and Unix. Stacks built using Vnetif are connected to a software switch that allows the stacks to communicate as if they were connected to the same LAN.

An example of a unikernel that communicates with itself over Vnetif can be seen here. An iperf-like performance test is available here. The examples can be compiled for Unix and Xen and do not need access to a real network interface.

Install

opam install mirage-vnetif

Getting started

First, construct a TCP/IP stack based on vnetif:

  module S = struct
    module B = Basic_backend.Make
    module V = Vnetif.Make(B)
    module E = Ethif.Make(V)
    module I = Ipv4.Make(E)(Clock)(OS.Time)
    module U = Udp.Make(I)
    module T = Tcp.Flow.Make(I)(OS.Time)(Clock)(Random)
    module S = Tcpip_stack_direct.Make(C)(OS.Time)(Random)(V)(E)(I)(U)(T)
    include S
  end

Since we don't have the mirage-tool to help us we have to construct the stack manually. This code would usually be generated in main.ml by mirage configure --xen/unix.

let or_error name fn t =
    fn t
    >>= function
        | `Error e -> fail (Failure ("Error starting " ^ name))
        | `Ok t -> return t 

let create_stack c backend ip netmask gw =
    or_error "backend" S.V.connect backend >>= fun netif ->
    or_error "ethif" S.E.connect netif >>= fun ethif ->
    or_error "ipv4" S.I.connect ethif >>= fun ipv4 ->
    or_error "udpv4" S.U.connect ipv4 >>= fun udpv4 ->
    or_error "tcpv4" S.T.connect ipv4 >>= fun tcpv4 ->
    let config = {
        Mirage_types_lwt.name = "stack";
        Mirage_types_lwt.console = c; 
        Mirage_types_lwt.interface = netif;
        Mirage_types_lwt.mode = `IPv4 (ip, netmask, gw);
    } in
    or_error "stack" (S.connect config ethif ipv4 udpv4) tcpv4

We can now create multiple stacks that talk over the same backend. Basic_backend.create accepts two optional parameters:

  • use_async_readers makes the write calls non-blocking. This is necessary to use Vnetif with the Mirage TCP/IP stack.

  • yield specifies the yield function to use in non-blocking mode. In a unikernel this is typically OS.Time.sleep 0.0, but in a Unix process Lwt_main.yield () can be used instead.


let () =

    (* create async backend with OS.Time.sleep 0.0 as yield *)
    let backend = Basic_backend.create ~use_async_readers:true 
        ~yield:(fun() -> OS.Time.sleep 0.0 ) () in

    let netmask = Ipaddr.V4.of_string_exn "255.255.255.0"  in
    let gw = Ipaddr.V4.of_string_exn "10.0.0.1" in

    let server_ip = Ipaddr.V4.of_string_exn "10.0.0.100" in
    create_stack c backend server_ip netmask [gw] >>= fun server_stack ->

    let client_ip = Ipaddr.V4.of_string_exn "10.0.0.101" in
    create_stack c backend server_ip netmask [gw] >>= fun client_stack ->

The stacks can now be used as regular Mirage TCP/IP stacks, e.g.:

S.listen_tcpv4 server_stack ~port:80 (fun f -> ...);
S.listen s1

Build examples

mirage configure --xen/--unix
make

Dependencies (14)

  1. result
  2. logs
  3. duration
  4. mirage-profile
  5. io-page
  6. macaddr
  7. ipaddr >= "3.0.0"
  8. cstruct >= "2.4.0" & < "6.1.0"
  9. mirage-net-lwt >= "1.0.0" & < "2.0.0"
  10. mirage-clock-lwt >= "1.2.0"
  11. mirage-time-lwt >= "1.0.0"
  12. lwt
  13. jbuilder >= "1.0+beta7"
  14. ocaml >= "4.04.2"

Dev Dependencies

None

Used by (4)

  1. arp-mirage < "2.2.0"
  2. capnp-rpc-mirage
  3. tcpip >= "3.0.0" & < "4.0.0"
  4. vpnkit >= "0.1.1"

Conflicts

None

OCaml

Innovation. Community. Security.