Skip to content

Commit 6d1dd5c

Browse files
committed
Merge pull request 'IPv4 routing improvements' (#16) from ipv4 into main
Reviewed-on: https://git.robur.coop/robur/mnet/pulls/16
2 parents 7e07437 + a487286 commit 6d1dd5c

File tree

4 files changed

+49
-39
lines changed

4 files changed

+49
-39
lines changed

src/TCP.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ let write_without_interruption_ipv4 state (src, dst, seg) =
124124
Log.warn (fun m -> m "A packet is kept in our internal queue");
125125
Queue.push (Ipaddr.V4 src, Ipaddr.V4 dst, seg) state.outs
126126
| Some macaddr ->
127-
IPv4.write_directly state.ipv4 ~src (dst, macaddr) ~protocol:6 pkt
127+
IPv4.write_directly state.ipv4 src (dst, macaddr) ~protocol:6 pkt
128128

129129
let write_ipv4 ipv4 (src, dst, seg) =
130130
let len = Utcp.Segment.length seg in

src/ipv4/IPv4.ml

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -250,10 +250,9 @@ let fixed pkt user's_fn len bstr =
250250
Bstr.set_uint16_be bstr 10 chk;
251251
20 + len
252252

253-
let write_directly t ?(ttl = 38) ?src (dst, macaddr) ~protocol p =
253+
let write_directly t ?(ttl = 38) src (dst, macaddr) ~protocol p =
254254
Log.debug (fun m ->
255255
m ~tags:t.tags "%a is-at %a" Ipaddr.V4.pp dst Macaddr.pp macaddr);
256-
let src = Option.value ~default:(Ipaddr.V4.Prefix.address t.cidr) src in
257256
let mtu = Ethernet.mtu t.eth in
258257
match p with
259258
| Writer.Fixed { total_length; fn= user's_fn } ->
@@ -306,21 +305,31 @@ let write_directly t ?(ttl = 38) ?src (dst, macaddr) ~protocol p =
306305
go 0 total_length (fn ())
307306

308307
let write t ?(ttl = 38) ?src dst ~protocol p =
308+
let src = Option.value ~default:(Ipaddr.V4.Prefix.address t.cidr) src in
309309
Log.debug (fun m -> m ~tags:t.tags "Asking where is %a" Ipaddr.V4.pp dst);
310-
match Routing.destination_macaddr t.cidr t.gateway t.arp dst with
310+
match Routing.destination_macaddr t.cidr t.gateway t.arp ~src ~dst with
311311
| Error (`Exn _ | `Timeout | `Clear) ->
312312
Log.err (fun m -> m ~tags:t.tags "no route found for %a" Ipaddr.V4.pp dst);
313313
Error `Route_not_found
314314
| Error `Gateway ->
315315
Log.debug (fun m ->
316-
m ~tags:t.tags "no gateway specified for writing IPv4 packets");
316+
m ~tags:t.tags
317+
"no gateway specified for writing IPv4 packets, dropping %a"
318+
Ipaddr.V4.pp dst);
319+
Ok ()
320+
| Error `Loopback ->
321+
Log.debug (fun m ->
322+
m ~tags:t.tags "not sending packet loopback (src %a dst %a)"
323+
Ipaddr.V4.pp src Ipaddr.V4.pp dst);
317324
Ok ()
318325
| Ok macaddr ->
319-
write_directly t ~ttl ?src (dst, macaddr) ~protocol p;
326+
write_directly t ~ttl src (dst, macaddr) ~protocol p;
320327
Ok ()
321328

322329
let attempt_to_discover_destination t dst =
323-
Routing.destination_macaddr_without_interruption t.cidr t.gateway t.arp dst
330+
let src = Ipaddr.V4.Prefix.address t.cidr in
331+
Routing.destination_macaddr_without_interruption t.cidr t.gateway t.arp ~src
332+
~dst
324333

325334
let input t pkt =
326335
match Packet.decode pkt.Ethernet.payload with

src/ipv4/IPv4.mli

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -170,12 +170,12 @@ end
170170
val write_directly :
171171
t
172172
-> ?ttl:int
173-
-> ?src:Ipaddr.V4.t
173+
-> Ipaddr.V4.t
174174
-> Ipaddr.V4.t * Macaddr.t
175175
-> protocol:int
176176
-> Writer.t
177177
-> unit
178-
(** [write_directly ipv4 ?ttl ?src (dst, macaddr) ~protocol w] writes a new IPv4
178+
(** [write_directly ipv4 ?ttl src (dst, macaddr) ~protocol w] writes a new IPv4
179179
packet [w] {b effectively} (without interruption) (fragmented or not) to the
180180
specified destination [macaddr]. *)
181181

src/ipv4/routing.ml

Lines changed: 31 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,36 @@
1-
let broadcast = Ok Macaddr.broadcast
1+
type r = Mac of Macaddr.t | Arp of Ipaddr.V4.t
22

3-
let macaddr_of_multicast ipaddr =
4-
let buf = Ipaddr.V4.to_octets ipaddr in
5-
let mac = Bytes.create 6 in
6-
Bytes.set_uint8 mac 0 0x01;
7-
Bytes.set_uint8 mac 1 0x00;
8-
Bytes.set_uint8 mac 2 0x5e;
9-
Bytes.set_uint8 mac 3 (String.get_uint8 buf 1 land 0x7f);
10-
Bytes.set_uint8 mac 4 (String.get_uint8 buf 2);
11-
Bytes.set_uint8 mac 5 (String.get_uint8 buf 3);
12-
Macaddr.of_octets_exn (Bytes.unsafe_to_string mac)
13-
14-
let destination_macaddr network gateway arp ipaddr =
15-
if
16-
Ipaddr.V4.(compare broadcast) ipaddr == 0
17-
|| Ipaddr.V4.(compare any) ipaddr == 0
18-
|| Ipaddr.V4.(compare (Prefix.broadcast network)) ipaddr == 0
19-
then broadcast
20-
else if Ipaddr.V4.is_multicast ipaddr then Ok (macaddr_of_multicast ipaddr)
21-
else if Ipaddr.V4.Prefix.mem ipaddr network then ARPv4.query arp ipaddr
3+
let routing network gateway ~src ~dst =
4+
if Ipaddr.V4.Prefix.(mem dst loopback) || Ipaddr.V4.Prefix.(mem src loopback)
5+
then
6+
(* avoid packets to or from 127.0.0.0/8 *)
7+
Error `Loopback
8+
else if
9+
Ipaddr.V4.(compare broadcast) dst == 0
10+
|| Ipaddr.V4.(compare (Prefix.broadcast network)) dst == 0
11+
then
12+
(* use broadcast mac *)
13+
Ok (Mac Macaddr.broadcast)
14+
else if Ipaddr.V4.is_multicast dst then
15+
(* filter multicast *)
16+
Ok (Mac (Ipaddr.V4.multicast_to_mac dst))
17+
else if Ipaddr.V4.Prefix.mem dst network then
18+
(* direct to this network *)
19+
Ok (Arp dst)
2220
else
21+
(* send to gateway *)
2322
match gateway with
2423
| None -> Error `Gateway
25-
| Some gateway -> ARPv4.query arp gateway
24+
| Some gateway -> Ok (Arp gateway)
25+
26+
let ( let* ) = Result.bind
27+
28+
let destination_macaddr network gateway arp ~src ~dst =
29+
let* it = routing network gateway ~src ~dst in
30+
match it with Mac x -> Ok x | Arp ip -> ARPv4.query arp ip
2631

27-
let destination_macaddr_without_interruption network gateway arp ipaddr =
28-
if
29-
Ipaddr.V4.(compare broadcast) ipaddr == 0
30-
|| Ipaddr.V4.(compare any) ipaddr == 0
31-
|| Ipaddr.V4.(compare (Prefix.broadcast network)) ipaddr == 0
32-
then Result.to_option broadcast
33-
else if Ipaddr.V4.is_multicast ipaddr then Some (macaddr_of_multicast ipaddr)
34-
else if Ipaddr.V4.Prefix.mem ipaddr network then ARPv4.ask arp ipaddr
35-
else match gateway with None -> None | Some gateway -> ARPv4.ask arp gateway
32+
let destination_macaddr_without_interruption network gateway arp ~src ~dst =
33+
match routing network gateway ~src ~dst with
34+
| Error _ -> None
35+
| Ok (Mac x) -> Some x
36+
| Ok (Arp ip) -> ARPv4.ask arp ip

0 commit comments

Comments
 (0)