From 95b3b36cd93a3922770c35ee7297d86a8888c66c Mon Sep 17 00:00:00 2001 From: Martin Stein Date: Wed, 13 Jul 2022 19:11:15 +0200 Subject: [PATCH] nic_router: update checksums only once per packet The NIC router used to update IPv4 and layer 4 checksums of a packet for each interface it was sent to (say, all interfaces of the domain the packet was routed to). However, there was and is no technical reason for not doing it only once and then iterating over the interfaces with the already updated packet. This is what this commit does in an intent to raise the router's performance. Ref #4555 --- repos/os/src/server/nic_router/interface.cc | 65 ++++++++++----------- repos/os/src/server/nic_router/interface.h | 17 +++--- 2 files changed, 37 insertions(+), 45 deletions(-) diff --git a/repos/os/src/server/nic_router/interface.cc b/repos/os/src/server/nic_router/interface.cc index 45397450a9..79a27de36c 100644 --- a/repos/os/src/server/nic_router/interface.cc +++ b/repos/os/src/server/nic_router/interface.cc @@ -293,28 +293,26 @@ void Interface::_destroy_link(Link &link) } -void Interface::_pass_prot(Ethernet_frame ð, - Size_guard &size_guard, - Ipv4_packet &ip, - L3_protocol const prot, - void *const prot_base, - size_t const prot_size) +void Interface::_pass_prot_to_domain(Domain &domain, + Ethernet_frame ð, + Size_guard &size_guard, + Ipv4_packet &ip, + L3_protocol const prot, + void *const prot_base, + size_t const prot_size) { - eth.src(_router_mac); - if (!_domain().use_arp()) { - eth.dst(_router_mac); - } - _update_checksum(prot, prot_base, prot_size, ip.src(), ip.dst(), ip.total_length()); - _pass_ip(eth, size_guard, ip); -} + _update_checksum( + prot, prot_base, prot_size, ip.src(), ip.dst(), ip.total_length()); - -void Interface::_pass_ip(Ethernet_frame ð, - Size_guard &size_guard, - Ipv4_packet &ip) -{ ip.update_checksum(); - send(eth, size_guard); + domain.interfaces().for_each([&] (Interface &interface) + { + eth.src(interface._router_mac); + if (!domain.use_arp()) { + eth.dst(interface._router_mac); + } + interface.send(eth, size_guard); + }); } @@ -606,9 +604,9 @@ void Interface::_nat_link_and_pass(Ethernet_frame ð, Link_side_id const remote_id = { ip.dst(), _dst_port(prot, prot_base), ip.src(), _src_port(prot, prot_base) }; _new_link(prot, local_id, remote_port_alloc, remote_domain, remote_id); - remote_domain.interfaces().for_each([&] (Interface &interface) { - interface._pass_prot(eth, size_guard, ip, prot, prot_base, prot_size); - }); + _pass_prot_to_domain( + remote_domain, eth, size_guard, ip, prot, prot_base, prot_size); + } catch (Port_allocator_guard::Out_of_indices) { switch (prot) { case L3_protocol::TCP: _tcp_stats.refused_for_ports++; break; @@ -1001,11 +999,10 @@ void Interface::_handle_icmp_query(Ethernet_frame ð, ip.dst(remote_side.src_ip()); _src_port(prot, prot_base, remote_side.dst_port()); _dst_port(prot, prot_base, remote_side.src_port()); + _pass_prot_to_domain( + remote_domain, eth, size_guard, ip, prot, prot_base, + prot_size); - remote_domain.interfaces().for_each([&] (Interface &interface) { - interface._pass_prot( - eth, size_guard, ip, prot, prot_base, prot_size); - }); _link_packet(prot, prot_base, link, client); done = true; }, @@ -1249,11 +1246,10 @@ void Interface::_handle_ip(Ethernet_frame ð, ip.dst(remote_side.src_ip()); _src_port(prot, prot_base, remote_side.dst_port()); _dst_port(prot, prot_base, remote_side.src_port()); + _pass_prot_to_domain( + remote_domain, eth, size_guard, ip, prot, prot_base, + prot_size); - remote_domain.interfaces().for_each([&] (Interface &interface) { - interface._pass_prot( - eth, size_guard, ip, prot, prot_base, prot_size); - }); _link_packet(prot, prot_base, link, client); done = true; }, @@ -1330,11 +1326,10 @@ void Interface::_handle_ip(Ethernet_frame ð, Domain &remote_domain = rule.domain(); _adapt_eth(eth, ip.dst(), pkt, remote_domain); - remote_domain.interfaces().for_each( - [&] (Interface &interface) { - interface._pass_ip(eth, size_guard, ip); - } - ); + ip.update_checksum(); + remote_domain.interfaces().for_each([&] (Interface &interface) { + interface.send(eth, size_guard); + }); done = true; }, [&] /* handle_no_match */ () { } diff --git a/repos/os/src/server/nic_router/interface.h b/repos/os/src/server/nic_router/interface.h index 4c670b7164..7e585767e5 100644 --- a/repos/os/src/server/nic_router/interface.h +++ b/repos/os/src/server/nic_router/interface.h @@ -276,16 +276,13 @@ class Net::Interface : private Interface_list::Element Size_guard &size_guard, Domain &local_domain); - void _pass_prot(Ethernet_frame ð, - Size_guard &size_guard, - Ipv4_packet &ip, - L3_protocol const prot, - void *const prot_base, - Genode::size_t const prot_size); - - void _pass_ip(Ethernet_frame ð, - Size_guard &size_guard, - Ipv4_packet &ip); + void _pass_prot_to_domain(Domain &domain, + Ethernet_frame ð, + Size_guard &size_guard, + Ipv4_packet &ip, + L3_protocol const prot, + void *const prot_base, + Genode::size_t const prot_size); void _handle_pkt();