mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-20 17:52:52 +00:00
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
This commit is contained in:
parent
01c9c32573
commit
95b3b36cd9
@ -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 */ () { }
|
||||
|
@ -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();
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user