@@ -122,7 +122,7 @@ let get_arp ?backend () =
122122 in
123123 V. connect backend >> = fun netif ->
124124 E. connect netif >> = fun ethif ->
125- A. connect ~probe_delay: (Duration. of_ms 2 ) ethif >> = fun arp ->
125+ A. connect ~probe_delay: (Duration. of_ms 1 ) ethif >> = fun arp ->
126126 Lwt. return { backend; netif; ethif; arp }
127127
128128(* we almost always want two stacks on the same backend *)
@@ -322,32 +322,44 @@ let os_linux_bsd () =
322322 | Error _ -> false
323323
324324let entries_expire () =
325- (* this test fails on windows and macOS for unknown reasons. please, if you
326- happen to have your hands on such a machine, investigate the issue. *)
327- if not (os_linux_bsd () ) then
328- Lwt. return_unit
329- else
330- two_arp () >> = fun (listen , speak ) ->
331- A. set_ips listen.arp [ second_ip ] >> = fun () ->
332- (* here's what we expect listener to emit once its cache entry has expired *)
333- let expected_arp_query =
334- Arp_packet. ({operation = Request ;
335- source_mac = V. mac listen.netif;
336- target_mac = Macaddr. broadcast;
337- source_ip = second_ip; target_ip = first_ip})
325+ two_arp () >> = fun (listen , speak ) ->
326+ A. set_ips listen.arp [ second_ip ] >> = fun () ->
327+ (* here's what we expect listener to emit once its cache entry has expired *)
328+ let expected_arp_query =
329+ Arp_packet. ({operation = Request ;
330+ source_mac = V. mac listen.netif;
331+ target_mac = Macaddr. broadcast;
332+ source_ip = second_ip; target_ip = first_ip})
333+ in
334+ (* Start ARP listener that will stay active throughout the test *)
335+ let listener = start_arp_listener listen () in
336+ Lwt. async (fun () -> V. listen listen.netif ~header_size listener > |= fun _ -> () );
337+ (* Establish cache entry using synchronized query/reply pattern *)
338+ (* Don't set speak's IP to avoid GARP interference *)
339+ let for_listener = arp_reply ~from_netif: speak.netif ~to_netif: listen.netif
340+ ~from_ip: first_ip ~to_ip: second_ip in
341+ let establish_entry =
342+ let query = A. query listen.arp first_ip >> = function
343+ | Ok mac when Macaddr. compare mac (V. mac speak.netif) = 0 -> Lwt. return_unit
344+ | Ok mac -> failf " got unexpected MAC %a, expected %a"
345+ Macaddr. pp mac Macaddr. pp (V. mac speak.netif)
346+ | Error e -> failf " query failed: %a" A. pp_error e
338347 in
339- (* query for IP to accept responses *)
340- Lwt. async (fun () -> A. query listen.arp first_ip > |= ignore) ;
341- Lwt. async (fun () -> V. listen listen.netif ~header_size (start_arp_listener listen () ) > |= fun _ -> () );
342- let test =
343- Mirage_sleep. ns (Duration. of_ms 10 ) >> = fun () ->
344- set_and_check ~listener: listen.arp ~claimant: speak first_ip >> = fun () ->
345- (* sleep for 5s to make sure we hit `tick` often enough *)
346- Mirage_sleep. ns (Duration. of_sec 5 ) >> = fun () ->
347- (* asking now should generate a query *)
348- not_in_cache ~listen: speak.netif expected_arp_query listen.arp first_ip
348+ let send_reply =
349+ E. write speak.ethif (V. mac listen.netif) `ARP ~size for_listener > |= function
350+ | Ok _ -> ()
351+ | Error _ -> failf " ethernet write failed"
349352 in
350- timeout ~time: 7000 test
353+ query >> = fun () -> send_reply
354+ in
355+ timeout ~time: 1000 establish_entry >> = fun () ->
356+ (* Wait for cache entry to expire. Entry is removed after timeout (800 ticks *
357+ 1ms = 1600ms) from initial creation. *)
358+ (* CI for BSD/MacOS has slower ticks, wait longer *)
359+ let delay = if os_linux_bsd () then 5 else 14 in
360+ Mirage_sleep. ns (Duration. of_sec delay) >> = fun () ->
361+ (* Querying now should generate an ARP request since entry should be removed *)
362+ timeout ~time: 1000 (not_in_cache ~listen: speak.netif expected_arp_query listen.arp first_ip)
351363
352364(* RFC isn't strict on how many times to try, so we'll just say any number
353365 greater than 1 is fine *)
0 commit comments