1414 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1515 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1616 *)
17+ open Lwt.Infix
1718
1819[@@@ warning " -52" ]
19- open Result
2020open Mirage_net
2121
22- let log fmt = Format. printf (" Netif: " ^^ fmt ^^ " \n %!" )
23-
24- let (>> = ) = Lwt. (>> = )
25- let (> |= ) = Lwt. (> |= )
22+ let src = Logs.Src. create " netif" ~doc: " Mirage unix network module"
23+ module Log = (val Logs. src_log src : Logs.LOG )
2624
2725type +'a io = 'a Lwt .t
2826
2927type t = {
3028 id : string ;
3129 dev : Lwt_unix .file_descr ;
3230 mutable active : bool ;
33- mutable mac : Macaddr .t ;
31+ mac : Macaddr .t ;
32+ mtu : int ;
3433 stats : Mirage_net .stats ;
3534}
3635
3736let fd t = t.dev
3837
3938type error = [
40- | Mirage_net .error
39+ | Mirage_net.Net . error
4140 | `Partial of string * int * Cstruct .t
4241 | `Exn of exn
4342]
4443
4544let pp_error ppf = function
46- | #Mirage_net. error as e -> Mirage_net. pp_error ppf e
45+ | #Mirage_net.Net. error as e -> Mirage_net.Net . pp_error ppf e
4746 | `Partial (id , len' , buffer ) ->
4847 Fmt. pf ppf " netif %s: partial write (%d, expected %d)"
4948 id len' buffer.Cstruct. len
5049 | `Exn e -> Fmt. exn ppf e
5150
52- let devices = Hashtbl. create 1
53-
5451let err_permission_denied devname =
5552 Printf. sprintf
5653 " Permission denied while opening the %s device. Please re-run using sudo."
@@ -63,34 +60,33 @@ let connect devname =
6360 let dev = Lwt_unix. of_unix_file_descr ~blocking: true fd in
6461 let mac = Macaddr. make_local (fun _ -> Random. int 256 ) in
6562 Tuntap. set_up_and_running devname;
66- log " plugging into %s with mac %s" devname (Macaddr. to_string mac);
63+ let mtu = Tuntap. get_mtu devname in
64+ Log. debug (fun m -> m " plugging into %s with mac %a and mtu %d"
65+ devname Macaddr. pp mac mtu);
6766 let active = true in
6867 let t = {
69- id= devname; dev; active; mac;
68+ id= devname; dev; active; mac; mtu;
7069 stats= { rx_bytes= 0L ;rx_pkts= 0l ; tx_bytes= 0L ; tx_pkts= 0l } }
7170 in
72- Hashtbl. add devices devname t;
73- log " connect %s" devname;
71+ Log. info (fun m -> m " connect %s with mac %a" devname Macaddr. pp mac);
7472 Lwt. return t
7573 with
7674 | Failure "tun[open]: Permission denied" ->
7775 Lwt. fail_with (err_permission_denied devname)
7876 | exn -> Lwt. fail exn
7977
8078let disconnect t =
81- log " disconnect %s" t.id;
79+ Log. info ( fun m -> m " disconnect %s" t.id) ;
8280 t.active < - false ;
8381 Lwt_unix. close t.dev >> = fun () ->
8482 Tuntap. closetap t.id;
8583 Lwt. return_unit
8684
8785type macaddr = Macaddr .t
88- type page_aligned_buffer = Io_page .t
8986type buffer = Cstruct .t
9087
9188(* Input a frame, and block if nothing is available *)
92- let rec read t page =
93- let buf = Io_page. to_cstruct page in
89+ let rec read t buf =
9490 let process () =
9591 Lwt. catch (fun () ->
9692 Lwt_cstruct. read t.dev buf > |= function
@@ -103,17 +99,17 @@ let rec read t page =
10399 Ok buf)
104100 (function
105101 | Unix. Unix_error (Unix. ENXIO, _ , _ ) ->
106- log " [read] device %s is down, stopping" t.id;
102+ Log. err ( fun m -> m " [read] device %s is down, stopping" t.id) ;
107103 Lwt. return (Error `Disconnected )
108104 | Lwt. Canceled ->
109- log " [read] user program requested cancellation of listen on %s" t.id;
105+ Log. err ( fun m -> m " [read] user program requested cancellation of listen on %s" t.id) ;
110106 Lwt. return (Error `Canceled )
111107 | exn ->
112- log " [read] error: %s, continuing" (Printexc. to_string exn );
108+ Log. err ( fun m -> m " [read] error: %s, continuing" (Printexc. to_string exn ) );
113109 Lwt. return (Error `Continue ))
114110 in
115111 process () >> = function
116- | Error `Continue -> read t page
112+ | Error `Continue -> read t buf
117113 | Error `Canceled -> Lwt. return (Error `Canceled )
118114 | Error `Disconnected -> Lwt. return (Error `Disconnected )
119115 | Ok buf -> Lwt. return (Ok buf)
@@ -122,51 +118,50 @@ let safe_apply f x =
122118 Lwt. catch
123119 (fun () -> f x)
124120 (fun exn ->
125- log " [listen] error while handling %s, continuing. bt: %s"
126- (Printexc. to_string exn ) (Printexc. get_backtrace () );
121+ Log. err ( fun m -> m " [listen] error while handling %s, continuing. bt: %s"
122+ (Printexc. to_string exn ) (Printexc. get_backtrace () ));
127123 Lwt. return_unit)
128124
125+
129126(* Loop and listen for packets permanently *)
130127(* this function has to be tail recursive, since it is called at the
131128 top level, otherwise memory of received packets and all reachable
132129 data is never claimed. take care when modifying, here be dragons! *)
133- let rec listen t fn =
130+ let rec listen t ~ header_size fn =
134131 match t.active with
135132 | true ->
136- let page = Io_page. get 1 in
133+ let buf = Cstruct. create (t.mtu + header_size) in
137134 let process () =
138- read t page > |= function
135+ read t buf > |= function
139136 | Ok buf -> Lwt. async (fun () -> safe_apply fn buf) ; Ok ()
140137 | Error `Canceled -> Error `Disconnected
141138 | Error `Disconnected -> t.active < - false ; Error `Disconnected
142139 in
143140 process () >> = (function
144- | Ok () -> (listen[@ tailcall]) t fn
141+ | Ok () -> (listen[@ tailcall]) t ~header_size fn
145142 | Error e -> Lwt. return (Error e))
146143 | false -> Lwt. return (Ok () )
147144
148145(* Transmit a packet from a Cstruct.t *)
149- let write t buffer =
150- let open Cstruct in
151- (* Unfortunately we peek inside the cstruct type here: *)
146+ let write t ~size fillf =
152147 (* This is the interface to the cruel Lwt world with exceptions, we've to guard *)
153- Lwt. catch (fun () ->
154- Lwt_bytes. write t.dev buffer.buffer buffer.off buffer.len > |= fun len' ->
155- t.stats.tx_pkts < - Int32. succ t.stats.tx_pkts;
156- t.stats.tx_bytes < - Int64. add t.stats.tx_bytes (Int64. of_int buffer.len);
157- if len' <> buffer.len then Error (`Partial (t.id, len', buffer))
158- else Ok () )
159- (fun exn -> Lwt. return (Error (`Exn exn )))
160-
161-
162- let writev t = function
163- | [] -> Lwt. return (Ok () )
164- | [page] -> write t page
165- | pages ->
166- write t @@ Cstruct. concat pages
148+ let buf = Cstruct. create size in
149+ let len = fillf buf in
150+ if len > size then
151+ Lwt. return (Error `Invalid_length )
152+ else
153+ Lwt. catch (fun () ->
154+ Lwt_bytes. write t.dev buf.Cstruct. buffer 0 len > |= fun len' ->
155+ t.stats.tx_pkts < - Int32. succ t.stats.tx_pkts;
156+ t.stats.tx_bytes < - Int64. add t.stats.tx_bytes (Int64. of_int len);
157+ if len' <> len then Error (`Partial (t.id, len', buf))
158+ else Ok () )
159+ (fun exn -> Lwt. return (Error (`Exn exn )))
167160
168161let mac t = t.mac
169162
163+ let mtu t = t.mtu
164+
170165let get_stats_counters t = t.stats
171166
172167let reset_stats_counters t =
0 commit comments