Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pull arpv4 module out of ipv4. #155

Merged
merged 28 commits into from
Jul 29, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
d41e00b
Initialize arpv4 outside ipv4; arp takes time/clock args, not ipv4
yomimono Jun 16, 2015
15e3502
build stacks with independent arp module
yomimono Jun 16, 2015
a686b73
make, expose, build arpv4-unix, arpv4_wire, & arpv4
yomimono Jun 16, 2015
dd0d94b
travis: pin mirage-types & mirage to yomimono fork, separate_arp branch
yomimono Jun 16, 2015
348dd2c
vnetif_common: use arp functors/impl in building stack
yomimono Jun 16, 2015
50682b5
require package mirage-clock-unix for tests
yomimono Jun 17, 2015
97a5dfb
Add some tests for ARP.
yomimono Jun 19, 2015
bc5ccd7
Use an Arp module with a sped-up clock for tests.
yomimono Jun 19, 2015
f84594f
use a Fast_clock to test expiry.
yomimono Jun 19, 2015
80aa8dc
test_arp: adjust some timeouts downward
yomimono Jun 19, 2015
404cb78
add UPDATE_GCC_BINUTILS
yomimono Jun 23, 2015
c7c6ae9
Initialize arpv4 outside ipv4; arp takes time/clock args, not ipv4
yomimono Jun 16, 2015
ef8d3f4
build stacks with independent arp module
yomimono Jun 16, 2015
aa593a8
make, expose, build arpv4-unix, arpv4_wire, & arpv4
yomimono Jun 16, 2015
40babf4
travis: pin mirage-types & mirage to yomimono fork, separate_arp branch
yomimono Jun 16, 2015
561e9af
vnetif_common: use arp functors/impl in building stack
yomimono Jun 16, 2015
1c82cec
require package mirage-clock-unix for tests
yomimono Jun 17, 2015
0defa31
Add some tests for ARP.
yomimono Jun 19, 2015
a7e48a5
Use an Arp module with a sped-up clock for tests.
yomimono Jun 19, 2015
7303351
use a Fast_clock to test expiry.
yomimono Jun 19, 2015
ef10ce0
test_arp: adjust some timeouts downward
yomimono Jun 19, 2015
5fe474f
add UPDATE_GCC_BINUTILS
yomimono Jun 23, 2015
647a569
arpv4: express macaddr = Macaddr.t
yomimono Jul 2, 2015
eae339e
prettyprint now uses formatter & returns unit io
yomimono Jul 2, 2015
5d6da63
Merge branch 'separate_arp' of https://github.com/yomimono/mirage-tcpi…
yomimono Jul 2, 2015
bda1739
Merge branch 'master' of http://www.github.com/mirage/mirage-tcpip in…
yomimono Jul 14, 2015
e4f35d8
pp and to_repr per V1_LWT
yomimono Jul 17, 2015
0c168b3
test_arp: fix pp call
yomimono Jul 23, 2015
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
language: c
script: bash -ex .travis-ci.sh
env:
- UPDATE_GCC_BINUTILS=1 OCAML_VERSION=4.02 PACKAGE=tcpip MIRAGE_MODE=unix
- UPDATE_GCC_BINUTILS=1 OCAML_VERSION=4.01 PACKAGE=tcpip MIRAGE_MODE=xen
- OCAML_VERSION=4.02 PACKAGE=tcpip MIRAGE_MODE=unix PINS="mirage-types:https://github.com/yomimono/mirage.git#separate_arp mirage:https://github.com/yomimono/mirage.git#separate_arp"
- UPDATE_GCC_BINUTILS=1 OCAML_VERSION=4.01 PACKAGE=tcpip MIRAGE_MODE=xen PINS="mirage-types:https://github.com/yomimono/mirage.git#separate_arp mirage:https://github.com/yomimono/mirage.git#separate_arp"
25 changes: 23 additions & 2 deletions _oasis
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,20 @@ Library ethif
Modules: Ethif
BuildDepends: tcpip,io-page,mirage-types,ipaddr,cstruct,lwt

Library arpv4
CompiledObject: best
Path: lib
Findlibparent: tcpip
Findlibname: arpv4
Modules: Arpv4, Arpv4_wire
BuildDepends: tcpip,io-page,mirage-types,ipaddr,cstruct,lwt,cstruct.syntax

Library ipv4
CompiledObject: best
Path: lib
Findlibparent: tcpip
Findlibname: ipv4
Modules: Ipv4, Arpv4
Modules: Ipv4
BuildDepends: io-page,mirage-types,ipaddr,cstruct,lwt,tcpip

Library ipv6
Expand Down Expand Up @@ -109,6 +117,7 @@ Library "tcpip-stack-direct"
cstruct,
lwt,
tcpip.ethif,
tcpip.arpv4,
tcpip.udp,
tcpip.tcp,
tcpip.dhcpv4
Expand All @@ -124,6 +133,17 @@ Library "ethif-unix"
lwt,
lwt.unix

Library "arpv4-unix"
CompiledObject: best
Path: unix
Findlibparent: tcpip
Findlibname: arpv4-unix
Modules: Arpv4_unix
BuildDepends: tcpip.ethif,
mirage-net-unix,
lwt,
lwt.unix

Library "ipv4-unix"
CompiledObject: best
Path: unix
Expand Down Expand Up @@ -297,9 +317,10 @@ Executable test
install: false
Path: lib_test/
MainIs: test.ml
Custom: true
BuildDepends: alcotest, oUnit, lwt, lwt.unix, io-page.unix,
mirage-profile, mirage-flow, mirage-vnetif,
mirage-console.unix, tcpip.ethif, tcpip.tcp, pcap-format
mirage-console.unix, mirage-clock-unix, tcpip.ethif, tcpip.tcp, pcap-format

Test test
Run$: flag(tests)
Expand Down
13 changes: 12 additions & 1 deletion _tags
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# OASIS_START
# DO NOT EDIT (digest: 6b9cf3043caf636197595a91784e90f6)
# DO NOT EDIT (digest: b9afd8f7c25862ce87cac4dd55d2c26b)
# Ignore VCS directories, you can use the same kind of rule outside
# OASIS_START/STOP if you want to exclude directories that contains
# useless stuff for the build process
Expand Down Expand Up @@ -32,6 +32,8 @@ true: annot, bin_annot
<lib/tcpip_xen.{cma,cmxa}>: use_libtcpip_xen_stubs
# Library ethif
"lib/ethif.cmxs": use_ethif
# Library arpv4
"lib/arpv4.cmxs": use_arpv4
# Library ipv4
"lib/ipv4.cmxs": use_ipv4
# Library ipv6
Expand Down Expand Up @@ -78,11 +80,13 @@ true: annot, bin_annot
"lib/tcpip-stack-direct.cmxs": use_tcpip-stack-direct
<lib/*.ml{,i,y}>: pkg_bytes
<lib/*.ml{,i,y}>: pkg_cstruct
<lib/*.ml{,i,y}>: pkg_cstruct.syntax
<lib/*.ml{,i,y}>: pkg_io-page
<lib/*.ml{,i,y}>: pkg_ipaddr
<lib/*.ml{,i,y}>: pkg_lwt
<lib/*.ml{,i,y}>: pkg_mirage-profile
<lib/*.ml{,i,y}>: pkg_mirage-types
<lib/*.ml{,i,y}>: use_arpv4
<lib/*.ml{,i,y}>: use_dhcpv4
<lib/*.ml{,i,y}>: use_ethif
<lib/*.ml{,i,y}>: use_ipv4
Expand All @@ -92,6 +96,8 @@ true: annot, bin_annot
<lib/*.ml{,i,y}>: use_udp
# Library ethif-unix
"unix/ethif-unix.cmxs": use_ethif-unix
# Library arpv4-unix
"unix/arpv4-unix.cmxs": use_arpv4-unix
# Library ipv4-unix
"unix/ipv4-unix.cmxs": use_ipv4-unix
# Library ipv6-unix
Expand All @@ -115,11 +121,13 @@ true: annot, bin_annot
# Library tcpip-stack-unix
"unix/tcpip-stack-unix.cmxs": use_tcpip-stack-unix
<unix/*.ml{,i,y}>: pkg_channel
<unix/*.ml{,i,y}>: pkg_cstruct.syntax
<unix/*.ml{,i,y}>: pkg_mirage-clock-unix
<unix/*.ml{,i,y}>: pkg_mirage-console.unix
<unix/*.ml{,i,y}>: pkg_mirage-net-unix
<unix/*.ml{,i,y}>: pkg_mirage-types.lwt
<unix/*.ml{,i,y}>: pkg_mirage-unix
<unix/*.ml{,i,y}>: use_arpv4
<unix/*.ml{,i,y}>: use_dhcpv4
<unix/*.ml{,i,y}>: use_ethif
<unix/*.ml{,i,y}>: use_ethif-unix
Expand Down Expand Up @@ -161,6 +169,7 @@ true: annot, bin_annot
<lib_test/test.{native,byte}>: pkg_ipaddr
<lib_test/test.{native,byte}>: pkg_lwt
<lib_test/test.{native,byte}>: pkg_lwt.unix
<lib_test/test.{native,byte}>: pkg_mirage-clock-unix
<lib_test/test.{native,byte}>: pkg_mirage-console.unix
<lib_test/test.{native,byte}>: pkg_mirage-flow
<lib_test/test.{native,byte}>: pkg_mirage-profile
Expand All @@ -181,6 +190,7 @@ true: annot, bin_annot
<lib_test/*.ml{,i,y}>: pkg_ipaddr
<lib_test/*.ml{,i,y}>: pkg_lwt
<lib_test/*.ml{,i,y}>: pkg_lwt.unix
<lib_test/*.ml{,i,y}>: pkg_mirage-clock-unix
<lib_test/*.ml{,i,y}>: pkg_mirage-console.unix
<lib_test/*.ml{,i,y}>: pkg_mirage-flow
<lib_test/*.ml{,i,y}>: pkg_mirage-profile
Expand All @@ -193,6 +203,7 @@ true: annot, bin_annot
<lib_test/*.ml{,i,y}>: use_ipv6
<lib_test/*.ml{,i,y}>: use_tcp
<lib_test/*.ml{,i,y}>: use_tcpip
<lib_test/test.{native,byte}>: custom
# OASIS_STOP
true: annot, bin_annot, principal, strict_sequence, debug
<tcp/pcb.ml>: pkg_cstruct.syntax
Expand Down
26 changes: 24 additions & 2 deletions lib/META
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# OASIS_START
# DO NOT EDIT (digest: 6aa06eed53e9ce5c406bb78c559f0b39)
# DO NOT EDIT (digest: b312e78e8475ee39ff695adf9eb35d35)
version = "2.5.1"
description = "Ethernet, TCP/IPv4 and DHCPv4 library"
requires = "io-page mirage-types ipaddr cstruct mirage-profile bytes"
Expand Down Expand Up @@ -162,7 +162,7 @@ package "stack-direct" (
version = "2.5.1"
description = "Ethernet, TCP/IPv4 and DHCPv4 library"
requires =
"io-page mirage-types ipaddr cstruct lwt tcpip.ethif tcpip.udp tcpip.tcp tcpip.dhcpv4"
"io-page mirage-types ipaddr cstruct lwt tcpip.ethif tcpip.arpv4 tcpip.udp tcpip.tcp tcpip.dhcpv4"
archive(byte) = "tcpip-stack-direct.cma"
archive(byte, plugin) = "tcpip-stack-direct.cma"
archive(native) = "tcpip-stack-direct.cmxa"
Expand Down Expand Up @@ -246,5 +246,27 @@ package "dhcpv4" (
archive(native, plugin) = "dhcpv4.cmxs"
exists_if = "dhcpv4.cma"
)

package "arpv4-unix" (
version = "2.5.1"
description = "Ethernet, TCP/IPv4 and DHCPv4 library"
requires = "tcpip.ethif mirage-net-unix lwt lwt.unix"
archive(byte) = "arpv4-unix.cma"
archive(byte, plugin) = "arpv4-unix.cma"
archive(native) = "arpv4-unix.cmxa"
archive(native, plugin) = "arpv4-unix.cmxs"
exists_if = "arpv4-unix.cma"
)

package "arpv4" (
version = "2.5.1"
description = "Ethernet, TCP/IPv4 and DHCPv4 library"
requires = "tcpip io-page mirage-types ipaddr cstruct lwt cstruct.syntax"
archive(byte) = "arpv4.cma"
archive(byte, plugin) = "arpv4.cma"
archive(native) = "arpv4.cmxa"
archive(native, plugin) = "arpv4.cmxs"
exists_if = "arpv4.cma"
)
# OASIS_STOP

60 changes: 26 additions & 34 deletions lib/arpv4.ml
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@ module Make (Ethif : V1_LWT.ETHIF) (Clock : V1.CLOCK) (Time : V1_LWT.TIME) = str
tpa: Ipaddr.V4.t;
}

(* TODO implement the full ARP state machine (pending, failed, timer thread, etc) *)

type result = [ `Ok of Macaddr.t | `Timeout ]

type entry =
Expand All @@ -42,25 +40,14 @@ module Make (Ethif : V1_LWT.ETHIF) (Clock : V1.CLOCK) (Time : V1_LWT.TIME) = str
mutable bound_ips: Ipaddr.V4.t list;
}

cstruct arp {
uint8_t dst[6];
uint8_t src[6];
uint16_t ethertype;
uint16_t htype;
uint16_t ptype;
uint8_t hlen;
uint8_t plen;
uint16_t op;
uint8_t sha[6];
uint32_t spa;
uint8_t tha[6];
uint32_t tpa
} as big_endian

cenum op {
Op_request = 1;
Op_reply
} as uint16_t
type 'a io = 'a Lwt.t
type buffer = Cstruct.t
type ipaddr = Ipaddr.V4.t
type macaddr = Macaddr.t
type ethif = Ethif.t
type repr = string
type id = t
type error

let arp_timeout = 60. (* age entries out of cache after this many seconds *)
let probe_repeat_delay = 1.5 (* per rfc5227, 2s >= probe_repeat_delay >= 1s *)
Expand All @@ -77,17 +64,18 @@ module Make (Ethif : V1_LWT.ETHIF) (Clock : V1.CLOCK) (Time : V1_LWT.TIME) = str
List.iter (Hashtbl.remove t.cache) expired;
Time.sleep arp_timeout >>= tick t

(* Prettyprint cache contents *)
let prettyprint t =
printf "ARP info:\n";
Hashtbl.iter (fun ip entry ->
printf "%s -> %s\n%!"
(Ipaddr.V4.to_string ip)
(match entry with
| Pending _ -> "I"
| Confirmed (_, mac) -> sprintf "V(%s)" (Macaddr.to_string mac)
)
) t.cache
let to_repr t =
let print ip entry acc =
let key = Ipaddr.V4.to_string ip in
match entry with
| Pending _ -> acc ^ "\n" ^ key ^ " -> " ^ "Pending"
| Confirmed (time, mac) -> Printf.sprintf "%s\n%s -> Confirmed (%s) (expires %f)\n%!"
acc key (Macaddr.to_string mac) time
in
Lwt.return (Hashtbl.fold print t.cache "")

let pp fmt repr =
Format.fprintf fmt "%s" repr

let notify t ip mac =
let now = Clock.time () in
Expand All @@ -105,6 +93,7 @@ module Make (Ethif : V1_LWT.ETHIF) (Clock : V1.CLOCK) (Time : V1_LWT.TIME) = str

(* Input handler for an ARP packet, registered through attach() *)
let rec input t frame =
let open Arpv4_wire in
MProf.Trace.label "arpv4.input";
match get_arp_op frame with
|1 -> (* Request *)
Expand Down Expand Up @@ -134,6 +123,7 @@ module Make (Ethif : V1_LWT.ETHIF) (Clock : V1.CLOCK) (Time : V1_LWT.TIME) = str
Lwt.return_unit

and output t arp =
let open Arpv4_wire in
(* Obtain a buffer to write into *)
let buf = Io_page.to_cstruct (Io_page.get 1) in
(* Write the ARP packet *)
Expand Down Expand Up @@ -233,10 +223,12 @@ module Make (Ethif : V1_LWT.ETHIF) (Clock : V1.CLOCK) (Time : V1_LWT.TIME) = str
Lwt.async (retry 0);
response

let create ethif =
let connect ethif =
let cache = Hashtbl.create 7 in
let bound_ips = [] in
let t = { ethif; cache; bound_ips } in
Lwt.async (tick t);
t
Lwt.return (`Ok t)

let disconnect t = Lwt.return_unit (* TODO: should kill tick *)
end
5 changes: 5 additions & 0 deletions lib/arpv4.mldylib
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# OASIS_START
# DO NOT EDIT (digest: 5194760ef3cd01243f8b4b4dc5e5d3b9)
Arpv4
Arpv4_wire
# OASIS_STOP
42 changes: 4 additions & 38 deletions lib/arpv4.mli
Original file line number Diff line number Diff line change
Expand Up @@ -15,45 +15,11 @@
*
*)

(** INTERNAL: ARP protocol. *)

module Make (Ethif : V1_LWT.ETHIF) (Clock : V1.CLOCK) (Time : V1_LWT.TIME) : sig
include V1_LWT.ARP

(** Type of an ARP record. ARP records are included in Ethif.t
values. They contain, among other bits, a list of bound IPs, and a
IPv4 -> MAC hashtbl. *)
type t

(** [create ~get_etherbuf ~output ~get_mac] creates a value of type
[t]. *)
val create: Ethif.t -> t

(** [set_ips arp] sets the bound IP address list, which will xmit a
GARP packet also. *)
val set_ips: t -> Ipaddr.V4.t list -> unit Lwt.t

(** [get_ips arp] gets the bound IP address list in the [arp]
value. *)
val get_ips: t -> Ipaddr.V4.t list

(** [add_ip arp ip] adds [ip] to the bound IP address list in the
[arp] value, which will xmit a GARP packet also. *)
val add_ip: t -> Ipaddr.V4.t -> unit Lwt.t

(** [remove_ip arp ip] removes [ip] to the bound IP address list in
the [arp] value, which will xmit a GARP packet also. *)
val remove_ip: t -> Ipaddr.V4.t -> unit Lwt.t

(** [input arp frame] will handle an ethernet frame containing an ARP
packet. If it is a response, it will update its cache, otherwise
will try to satisfy the request. *)
val input: t -> Cstruct.t -> unit Lwt.t

(** [query arp ip] queries the cache in [arp] for an ARP entry
corresponding to [ip], which may result in the sender sleeping
waiting for a response. *)
val query: t -> Ipaddr.V4.t -> [ `Ok of Macaddr.t | `Timeout ] Lwt.t
type ethif = Ethif.t

(** Prettyprint cache contents *)
val prettyprint: t -> unit
(** [connect] creates a value of type [t]. *)
val connect : ethif -> [> `Ok of t | `Error of error ] Lwt.t
end
5 changes: 5 additions & 0 deletions lib/arpv4.mllib
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# OASIS_START
# DO NOT EDIT (digest: 5194760ef3cd01243f8b4b4dc5e5d3b9)
Arpv4
Arpv4_wire
# OASIS_STOP
19 changes: 19 additions & 0 deletions lib/arpv4_wire.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
cstruct arp {
uint8_t dst[6];
uint8_t src[6];
uint16_t ethertype;
uint16_t htype;
uint16_t ptype;
uint8_t hlen;
uint8_t plen;
uint16_t op;
uint8_t sha[6];
uint32_t spa;
uint8_t tha[6];
uint32_t tpa
} as big_endian

cenum op {
Op_request = 1;
Op_reply
} as uint16_t
Loading