mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-07 19:34:56 +00:00
nic_router: incremental L4 checksum updates
The checksums for forwarded/routed UDP, TCP and ICMP, used to be always re-calculated from scratch in the NIC router although the router changes only a few packet fields. This commit replaces the old approach whereever sensible with an algorithm for incremental checksum updates suggested in RFC 1071. The goal is to improve router performance. Ref #4555
This commit is contained in:
parent
b6d15fa3ab
commit
9a37ccfe29
@ -114,6 +114,8 @@ class Net::Icmp_packet
|
||||
|
||||
void update_checksum(Genode::size_t data_sz);
|
||||
|
||||
void update_checksum(Internet_checksum_diff const &icd);
|
||||
|
||||
bool checksum_error(Genode::size_t data_sz) const;
|
||||
|
||||
|
||||
@ -157,6 +159,9 @@ class Net::Icmp_packet
|
||||
void query_id(Genode::uint16_t v) { _rest_of_header_u16[0] = host_to_big_endian(v); }
|
||||
void query_seq(Genode::uint16_t v) { _rest_of_header_u16[1] = host_to_big_endian(v); }
|
||||
|
||||
void type_and_code(Type t, Code c, Internet_checksum_diff &icd);
|
||||
void query_id(Genode::uint16_t v, Internet_checksum_diff &icd);
|
||||
|
||||
|
||||
/*********
|
||||
** log **
|
||||
|
@ -76,6 +76,11 @@ namespace Net {
|
||||
Packed_uint16 const *old_data_ptr,
|
||||
Genode::size_t data_sz);
|
||||
|
||||
/**
|
||||
* Update this modifier by adding up another modifier
|
||||
*/
|
||||
void add_up_diff(Internet_checksum_diff const &icd);
|
||||
|
||||
/**
|
||||
* Return the given checksum with this modifier applied
|
||||
*/
|
||||
|
@ -98,6 +98,9 @@ class Net::Ipv4_packet
|
||||
|
||||
void update_checksum(Internet_checksum_diff const &icd);
|
||||
|
||||
void update_checksum(Internet_checksum_diff const &icd,
|
||||
Internet_checksum_diff &caused_icd);
|
||||
|
||||
bool checksum_error() const;
|
||||
|
||||
private:
|
||||
|
@ -72,6 +72,8 @@ class Net::Tcp_packet
|
||||
Ipv4_address ip_dst,
|
||||
size_t tcp_size);
|
||||
|
||||
void update_checksum(Internet_checksum_diff const &icd);
|
||||
|
||||
|
||||
/***************
|
||||
** Accessors **
|
||||
@ -99,6 +101,9 @@ class Net::Tcp_packet
|
||||
void src_port(Port p) { _src_port = host_to_big_endian(p.value); }
|
||||
void dst_port(Port p) { _dst_port = host_to_big_endian(p.value); }
|
||||
|
||||
void src_port(Port p, Internet_checksum_diff &icd);
|
||||
void dst_port(Port p, Internet_checksum_diff &icd);
|
||||
|
||||
|
||||
/*********
|
||||
** log **
|
||||
|
@ -84,6 +84,8 @@ class Net::Udp_packet
|
||||
void update_checksum(Ipv4_address ip_src,
|
||||
Ipv4_address ip_dst);
|
||||
|
||||
void update_checksum(Internet_checksum_diff const &icd);
|
||||
|
||||
bool checksum_error(Ipv4_address ip_src,
|
||||
Ipv4_address ip_dst) const;
|
||||
|
||||
@ -103,6 +105,9 @@ class Net::Udp_packet
|
||||
void src_port_big_endian(Genode::uint16_t v) { _src_port = v; }
|
||||
void dst_port_big_endian(Genode::uint16_t v) { _dst_port = v; }
|
||||
|
||||
void src_port(Port p, Internet_checksum_diff &icd);
|
||||
void dst_port(Port p, Internet_checksum_diff &icd);
|
||||
|
||||
|
||||
/*********
|
||||
** log **
|
||||
|
@ -34,7 +34,33 @@ void Icmp_packet::update_checksum(size_t data_sz)
|
||||
}
|
||||
|
||||
|
||||
void Icmp_packet::update_checksum(Internet_checksum_diff const &icd)
|
||||
{
|
||||
_checksum = icd.apply_to(_checksum);
|
||||
}
|
||||
|
||||
|
||||
bool Icmp_packet::checksum_error(size_t data_sz) const
|
||||
{
|
||||
return internet_checksum((Packed_uint16 *)this, sizeof(Icmp_packet) + data_sz);
|
||||
}
|
||||
|
||||
|
||||
void Icmp_packet::query_id(uint16_t v, Internet_checksum_diff &icd)
|
||||
{
|
||||
uint16_t const v_be { host_to_big_endian(v) };
|
||||
icd.add_up_diff((
|
||||
Packed_uint16 *)&v_be, (Packed_uint16 *)&_rest_of_header_u16[0], 2);
|
||||
|
||||
_rest_of_header_u16[0] = v_be;
|
||||
}
|
||||
|
||||
|
||||
void Icmp_packet::type_and_code(Type t, Code c, Internet_checksum_diff &icd)
|
||||
{
|
||||
uint16_t const old_type_and_code { *(uint16_t*)this };
|
||||
type(t);
|
||||
code(c);
|
||||
icd.add_up_diff(
|
||||
(Packed_uint16 *)&_type, (Packed_uint16 *)&old_type_and_code, 2);
|
||||
}
|
||||
|
@ -96,6 +96,12 @@ uint16_t Net::internet_checksum_pseudo_ip(Packed_uint16 const *data_ptr,
|
||||
** Internet_checksum_diff **
|
||||
****************************/
|
||||
|
||||
void Internet_checksum_diff::add_up_diff(Internet_checksum_diff const &icd)
|
||||
{
|
||||
_value += icd._value;
|
||||
}
|
||||
|
||||
|
||||
void Internet_checksum_diff::add_up_diff(Packed_uint16 const *new_data_ptr,
|
||||
Packed_uint16 const *old_data_ptr,
|
||||
size_t data_sz)
|
||||
|
@ -176,3 +176,15 @@ void Ipv4_packet::update_checksum(Internet_checksum_diff const &icd)
|
||||
{
|
||||
_checksum = icd.apply_to(_checksum);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Ipv4_packet::update_checksum(Internet_checksum_diff const &icd,
|
||||
Internet_checksum_diff &caused_icd)
|
||||
{
|
||||
uint16_t const new_checksum { icd.apply_to(_checksum) };
|
||||
caused_icd.add_up_diff(
|
||||
(Packed_uint16 *)&new_checksum, (Packed_uint16 *)&_checksum, 2);
|
||||
|
||||
_checksum = new_checksum;
|
||||
}
|
||||
|
@ -47,3 +47,25 @@ void Net::Tcp_packet::update_checksum(Ipv4_address ip_src,
|
||||
host_to_big_endian((uint16_t)tcp_size),
|
||||
Ipv4_packet::Protocol::TCP, ip_src, ip_dst);
|
||||
}
|
||||
|
||||
|
||||
void Net::Tcp_packet::update_checksum(Internet_checksum_diff const &icd)
|
||||
{
|
||||
_checksum = icd.apply_to(_checksum);
|
||||
}
|
||||
|
||||
|
||||
void Net::Tcp_packet::src_port(Port p, Internet_checksum_diff &icd)
|
||||
{
|
||||
uint16_t const p_be { host_to_big_endian(p.value) };
|
||||
icd.add_up_diff((Packed_uint16 *)&p_be, (Packed_uint16 *)&_src_port, 2);
|
||||
_src_port = p_be;
|
||||
}
|
||||
|
||||
|
||||
void Net::Tcp_packet::dst_port(Port p, Internet_checksum_diff &icd)
|
||||
{
|
||||
uint16_t const p_be { host_to_big_endian(p.value) };
|
||||
icd.add_up_diff((Packed_uint16 *)&p_be, (Packed_uint16 *)&_dst_port, 2);
|
||||
_dst_port = p_be;
|
||||
}
|
||||
|
@ -41,9 +41,31 @@ void Net::Udp_packet::update_checksum(Ipv4_address ip_src,
|
||||
}
|
||||
|
||||
|
||||
void Net::Udp_packet::update_checksum(Internet_checksum_diff const &icd)
|
||||
{
|
||||
_checksum = icd.apply_to(_checksum);
|
||||
}
|
||||
|
||||
|
||||
bool Net::Udp_packet::checksum_error(Ipv4_address ip_src,
|
||||
Ipv4_address ip_dst) const
|
||||
{
|
||||
return internet_checksum_pseudo_ip((Packed_uint16 *)this, length(), _length,
|
||||
Ipv4_packet::Protocol::UDP, ip_src, ip_dst);
|
||||
}
|
||||
|
||||
|
||||
void Net::Udp_packet::src_port(Port p, Internet_checksum_diff &icd)
|
||||
{
|
||||
uint16_t const p_be { host_to_big_endian(p.value) };
|
||||
icd.add_up_diff((Packed_uint16 *)&p_be, (Packed_uint16 *)&_src_port, 2);
|
||||
_src_port = p_be;
|
||||
}
|
||||
|
||||
|
||||
void Net::Udp_packet::dst_port(Port p, Internet_checksum_diff &icd)
|
||||
{
|
||||
uint16_t const p_be { host_to_big_endian(p.value) };
|
||||
icd.add_up_diff((Packed_uint16 *)&p_be, (Packed_uint16 *)&_dst_port, 2);
|
||||
_dst_port = p_be;
|
||||
}
|
||||
|
@ -155,25 +155,21 @@ static void _link_packet(L3_protocol const prot,
|
||||
}
|
||||
|
||||
|
||||
static void _update_checksum(L3_protocol const prot,
|
||||
void *const prot_base,
|
||||
size_t const prot_size,
|
||||
Ipv4_address const src,
|
||||
Ipv4_address const dst,
|
||||
size_t const ip_size)
|
||||
static void _l4_update_checksum(L3_protocol const prot,
|
||||
void *const prot_base,
|
||||
Internet_checksum_diff const &prot_icd)
|
||||
{
|
||||
switch (prot) {
|
||||
case L3_protocol::TCP:
|
||||
((Tcp_packet *)prot_base)->update_checksum(src, dst, prot_size);
|
||||
((Tcp_packet *)prot_base)->update_checksum(prot_icd);
|
||||
return;
|
||||
case L3_protocol::UDP:
|
||||
((Udp_packet *)prot_base)->update_checksum(src, dst);
|
||||
((Udp_packet *)prot_base)->update_checksum(prot_icd);
|
||||
return;
|
||||
case L3_protocol::ICMP:
|
||||
{
|
||||
Icmp_packet &icmp = *(Icmp_packet *)prot_base;
|
||||
icmp.update_checksum(ip_size - sizeof(Ipv4_packet) -
|
||||
sizeof(Icmp_packet));
|
||||
icmp.update_checksum(prot_icd);
|
||||
return;
|
||||
}
|
||||
default: throw Interface::Bad_transport_protocol(); }
|
||||
@ -190,14 +186,15 @@ static Port _dst_port(L3_protocol const prot, void *const prot_base)
|
||||
}
|
||||
|
||||
|
||||
static void _dst_port(L3_protocol const prot,
|
||||
void *const prot_base,
|
||||
Port const port)
|
||||
static void _dst_port(L3_protocol const prot,
|
||||
void *const prot_base,
|
||||
Internet_checksum_diff &prot_icd,
|
||||
Port const port)
|
||||
{
|
||||
switch (prot) {
|
||||
case L3_protocol::TCP: (*(Tcp_packet *)prot_base).dst_port(port); return;
|
||||
case L3_protocol::UDP: (*(Udp_packet *)prot_base).dst_port(port); return;
|
||||
case L3_protocol::ICMP: (*(Icmp_packet *)prot_base).query_id(port.value); return;
|
||||
case L3_protocol::TCP: (*(Tcp_packet *)prot_base).dst_port(port, prot_icd); return;
|
||||
case L3_protocol::UDP: (*(Udp_packet *)prot_base).dst_port(port, prot_icd); return;
|
||||
case L3_protocol::ICMP: (*(Icmp_packet *)prot_base).query_id(port.value, prot_icd); return;
|
||||
default: throw Interface::Bad_transport_protocol(); }
|
||||
}
|
||||
|
||||
@ -212,14 +209,15 @@ static Port _src_port(L3_protocol const prot, void *const prot_base)
|
||||
}
|
||||
|
||||
|
||||
static void _src_port(L3_protocol const prot,
|
||||
void *const prot_base,
|
||||
Port const port)
|
||||
static void _src_port(L3_protocol const prot,
|
||||
void *const prot_base,
|
||||
Internet_checksum_diff &prot_icd,
|
||||
Port const port)
|
||||
{
|
||||
switch (prot) {
|
||||
case L3_protocol::TCP: ((Tcp_packet *)prot_base)->src_port(port); return;
|
||||
case L3_protocol::UDP: ((Udp_packet *)prot_base)->src_port(port); return;
|
||||
case L3_protocol::ICMP: ((Icmp_packet *)prot_base)->query_id(port.value); return;
|
||||
case L3_protocol::TCP: ((Tcp_packet *)prot_base)->src_port(port, prot_icd); return;
|
||||
case L3_protocol::UDP: ((Udp_packet *)prot_base)->src_port(port, prot_icd); return;
|
||||
case L3_protocol::ICMP: ((Icmp_packet *)prot_base)->query_id(port.value, prot_icd); return;
|
||||
default: throw Interface::Bad_transport_protocol(); }
|
||||
}
|
||||
|
||||
@ -301,11 +299,9 @@ void Interface::_pass_prot_to_domain(Domain &domain,
|
||||
Internet_checksum_diff const &ip_icd,
|
||||
L3_protocol const prot,
|
||||
void *const prot_base,
|
||||
size_t const prot_size)
|
||||
Internet_checksum_diff const &prot_icd)
|
||||
{
|
||||
_update_checksum(
|
||||
prot, prot_base, prot_size, ip.src(), ip.dst(), ip.total_length());
|
||||
|
||||
_l4_update_checksum(prot, prot_base, prot_icd);
|
||||
ip.update_checksum(ip_icd);
|
||||
domain.interfaces().for_each([&] (Interface &interface)
|
||||
{
|
||||
@ -584,7 +580,7 @@ void Interface::_nat_link_and_pass(Ethernet_frame ð,
|
||||
Internet_checksum_diff &ip_icd,
|
||||
L3_protocol const prot,
|
||||
void *const prot_base,
|
||||
size_t const prot_size,
|
||||
Internet_checksum_diff &prot_icd,
|
||||
Link_side_id const &local_id,
|
||||
Domain &local_domain,
|
||||
Domain &remote_domain)
|
||||
@ -598,8 +594,13 @@ void Interface::_nat_link_and_pass(Ethernet_frame ð,
|
||||
if(_config().verbose()) {
|
||||
log("[", local_domain, "] using NAT rule: ", nat); }
|
||||
|
||||
_src_port(prot, prot_base, nat.port_alloc(prot).alloc());
|
||||
ip.src(remote_domain.ip_config().interface().address, ip_icd);
|
||||
_src_port(prot, prot_base, prot_icd, nat.port_alloc(prot).alloc());
|
||||
Internet_checksum_diff icd { };
|
||||
ip.src(remote_domain.ip_config().interface().address, icd);
|
||||
ip_icd.add_up_diff(icd);
|
||||
if (prot == L3_protocol::TCP || prot == L3_protocol::UDP) {
|
||||
prot_icd.add_up_diff(icd);
|
||||
}
|
||||
remote_port_alloc = nat.port_alloc(prot);
|
||||
},
|
||||
[&] /* no_match */ () { }
|
||||
@ -609,7 +610,7 @@ void Interface::_nat_link_and_pass(Ethernet_frame ð,
|
||||
_new_link(prot, local_id, remote_port_alloc, remote_domain, remote_id);
|
||||
_pass_prot_to_domain(
|
||||
remote_domain, eth, size_guard, ip, ip_icd, prot, prot_base,
|
||||
prot_size);
|
||||
prot_icd);
|
||||
|
||||
} catch (Port_allocator_guard::Out_of_indices) {
|
||||
switch (prot) {
|
||||
@ -945,11 +946,11 @@ void Interface::handle_interface_link_state()
|
||||
}
|
||||
|
||||
|
||||
void Interface::_send_icmp_echo_reply(Ethernet_frame ð,
|
||||
Ipv4_packet &ip,
|
||||
Icmp_packet &icmp,
|
||||
size_t icmp_sz,
|
||||
Size_guard &size_guard)
|
||||
void Interface::_send_icmp_echo_reply(Ethernet_frame ð,
|
||||
Ipv4_packet &ip,
|
||||
Icmp_packet &icmp,
|
||||
Internet_checksum_diff &icmp_icd,
|
||||
Size_guard &size_guard)
|
||||
{
|
||||
/* adapt Ethernet header */
|
||||
Mac_address const eth_src = eth.src();
|
||||
@ -962,8 +963,9 @@ void Interface::_send_icmp_echo_reply(Ethernet_frame ð,
|
||||
ip.dst(ip_src);
|
||||
|
||||
/* adapt ICMP header */
|
||||
icmp.type(Icmp_packet::Type::ECHO_REPLY);
|
||||
icmp.code(Icmp_packet::Code::ECHO_REPLY);
|
||||
icmp.type_and_code(Icmp_packet::Type::ECHO_REPLY,
|
||||
Icmp_packet::Code::ECHO_REPLY,
|
||||
icmp_icd);
|
||||
|
||||
/*
|
||||
* Update checksums and send
|
||||
@ -971,7 +973,7 @@ void Interface::_send_icmp_echo_reply(Ethernet_frame ð,
|
||||
* Skip updating the IPv4 checksum because we have only swapped SRC and
|
||||
* DST and these changes cancel each other out in checksum calculation.
|
||||
*/
|
||||
icmp.update_checksum(icmp_sz - sizeof(Icmp_packet));
|
||||
icmp.update_checksum(icmp_icd);
|
||||
send(eth, size_guard);
|
||||
}
|
||||
|
||||
@ -983,7 +985,7 @@ void Interface::_handle_icmp_query(Ethernet_frame ð,
|
||||
Packet_descriptor const &pkt,
|
||||
L3_protocol prot,
|
||||
void *prot_base,
|
||||
size_t prot_size,
|
||||
Internet_checksum_diff &prot_icd,
|
||||
Domain &local_domain)
|
||||
{
|
||||
Link_side_id const local_id = { ip.src(), _src_port(prot, prot_base),
|
||||
@ -1004,13 +1006,18 @@ void Interface::_handle_icmp_query(Ethernet_frame ð,
|
||||
" link: ", link);
|
||||
}
|
||||
_adapt_eth(eth, remote_side.src_ip(), pkt, remote_domain);
|
||||
ip.src(remote_side.dst_ip(), ip_icd);
|
||||
ip.dst(remote_side.src_ip(), ip_icd);
|
||||
_src_port(prot, prot_base, remote_side.dst_port());
|
||||
_dst_port(prot, prot_base, remote_side.src_port());
|
||||
Internet_checksum_diff icd { };
|
||||
ip.src(remote_side.dst_ip(), icd);
|
||||
ip.dst(remote_side.src_ip(), icd);
|
||||
ip_icd.add_up_diff(icd);
|
||||
if (prot == L3_protocol::TCP || prot == L3_protocol::UDP) {
|
||||
prot_icd.add_up_diff(icd);
|
||||
}
|
||||
_src_port(prot, prot_base, prot_icd, remote_side.dst_port());
|
||||
_dst_port(prot, prot_base, prot_icd, remote_side.src_port());
|
||||
_pass_prot_to_domain(
|
||||
remote_domain, eth, size_guard, ip, ip_icd, prot,
|
||||
prot_base, prot_size);
|
||||
prot_base, prot_icd);
|
||||
|
||||
_link_packet(prot, prot_base, link, client);
|
||||
done = true;
|
||||
@ -1032,7 +1039,7 @@ void Interface::_handle_icmp_query(Ethernet_frame ð,
|
||||
Domain &remote_domain = rule.domain();
|
||||
_adapt_eth(eth, local_id.dst_ip, pkt, remote_domain);
|
||||
_nat_link_and_pass(eth, size_guard, ip, ip_icd, prot, prot_base,
|
||||
prot_size, local_id, local_domain,
|
||||
prot_icd, local_id, local_domain,
|
||||
remote_domain);
|
||||
|
||||
done = true;
|
||||
@ -1054,7 +1061,7 @@ void Interface::_handle_icmp_error(Ethernet_frame ð,
|
||||
Packet_descriptor const &pkt,
|
||||
Domain &local_domain,
|
||||
Icmp_packet &icmp,
|
||||
size_t icmp_sz)
|
||||
Internet_checksum_diff &icmp_icd)
|
||||
{
|
||||
Ipv4_packet &embed_ip { icmp.data<Ipv4_packet>(size_guard) };
|
||||
Internet_checksum_diff embed_ip_icd { };
|
||||
@ -1092,14 +1099,18 @@ void Interface::_handle_icmp_error(Ethernet_frame ð,
|
||||
ip.dst(remote_side.src_ip(), ip_icd);
|
||||
|
||||
/* adapt source and destination of embedded IP and transport packet */
|
||||
embed_ip.src(remote_side.src_ip(), embed_ip_icd);
|
||||
embed_ip.dst(remote_side.dst_ip(), embed_ip_icd);
|
||||
_src_port(embed_prot, embed_prot_base, remote_side.src_port());
|
||||
_dst_port(embed_prot, embed_prot_base, remote_side.dst_port());
|
||||
Internet_checksum_diff icd { };
|
||||
embed_ip.src(remote_side.src_ip(), icd);
|
||||
embed_ip.dst(remote_side.dst_ip(), icd);
|
||||
embed_ip_icd.add_up_diff(icd);
|
||||
|
||||
_src_port(embed_prot, embed_prot_base, icd, remote_side.src_port());
|
||||
_dst_port(embed_prot, embed_prot_base, icd, remote_side.dst_port());
|
||||
|
||||
/* update checksum of both IP headers and the ICMP header */
|
||||
embed_ip.update_checksum(embed_ip_icd);
|
||||
icmp.update_checksum(icmp_sz - sizeof(Icmp_packet));
|
||||
embed_ip.update_checksum(embed_ip_icd, icd);
|
||||
icmp_icd.add_up_diff(icd);
|
||||
icmp.update_checksum(icmp_icd);
|
||||
ip.update_checksum(ip_icd);
|
||||
|
||||
/* send adapted packet to all interfaces of remote domain */
|
||||
@ -1126,7 +1137,7 @@ void Interface::_handle_icmp(Ethernet_frame ð,
|
||||
Packet_descriptor const &pkt,
|
||||
L3_protocol prot,
|
||||
void *prot_base,
|
||||
size_t prot_size,
|
||||
Internet_checksum_diff &prot_icd,
|
||||
Domain &local_domain,
|
||||
Ipv4_address_prefix const &local_intf)
|
||||
{
|
||||
@ -1143,14 +1154,14 @@ void Interface::_handle_icmp(Ethernet_frame ð,
|
||||
if(_config().verbose()) {
|
||||
log("[", local_domain, "] act as ICMP Echo server"); }
|
||||
|
||||
_send_icmp_echo_reply(eth, ip, icmp, prot_size, size_guard);
|
||||
_send_icmp_echo_reply(eth, ip, icmp, prot_icd, size_guard);
|
||||
return;
|
||||
}
|
||||
/* try to act as ICMP router */
|
||||
switch (icmp.type()) {
|
||||
case Icmp_packet::Type::ECHO_REPLY:
|
||||
case Icmp_packet::Type::ECHO_REQUEST: _handle_icmp_query(eth, size_guard, ip, ip_icd, pkt, prot, prot_base, prot_size, local_domain); break;
|
||||
case Icmp_packet::Type::DST_UNREACHABLE: _handle_icmp_error(eth, size_guard, ip, ip_icd, pkt, local_domain, icmp, prot_size); break;
|
||||
case Icmp_packet::Type::ECHO_REQUEST: _handle_icmp_query(eth, size_guard, ip, ip_icd, pkt, prot, prot_base, prot_icd, local_domain); break;
|
||||
case Icmp_packet::Type::DST_UNREACHABLE: _handle_icmp_error(eth, size_guard, ip, ip_icd, pkt, local_domain, icmp, prot_icd); break;
|
||||
default: Drop_packet("unhandled type in ICMP"); }
|
||||
}
|
||||
|
||||
@ -1190,9 +1201,9 @@ void Interface::_handle_ip(Ethernet_frame ð,
|
||||
/* try to route via transport layer rules */
|
||||
bool done { false };
|
||||
try {
|
||||
L3_protocol const prot = ip.protocol();
|
||||
size_t const prot_size = size_guard.unconsumed();
|
||||
void *const prot_base = _prot_base(prot, size_guard, ip);
|
||||
L3_protocol const prot { ip.protocol() };
|
||||
void *const prot_base { _prot_base(prot, size_guard, ip) };
|
||||
Internet_checksum_diff prot_icd { };
|
||||
|
||||
/* try handling DHCP requests before trying any routing */
|
||||
if (prot == L3_protocol::UDP) {
|
||||
@ -1235,7 +1246,7 @@ void Interface::_handle_ip(Ethernet_frame ð,
|
||||
}
|
||||
else if (prot == L3_protocol::ICMP) {
|
||||
_handle_icmp(eth, size_guard, ip, ip_icd, pkt, prot, prot_base,
|
||||
prot_size, local_domain, local_intf);
|
||||
prot_icd, local_domain, local_intf);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1258,13 +1269,20 @@ void Interface::_handle_ip(Ethernet_frame ð,
|
||||
" link: ", link);
|
||||
}
|
||||
_adapt_eth(eth, remote_side.src_ip(), pkt, remote_domain);
|
||||
ip.src(remote_side.dst_ip(), ip_icd);
|
||||
ip.dst(remote_side.src_ip(), ip_icd);
|
||||
_src_port(prot, prot_base, remote_side.dst_port());
|
||||
_dst_port(prot, prot_base, remote_side.src_port());
|
||||
|
||||
Internet_checksum_diff icd { };
|
||||
ip.src(remote_side.dst_ip(), icd);
|
||||
ip.dst(remote_side.src_ip(), icd);
|
||||
ip_icd.add_up_diff(icd);
|
||||
if (prot == L3_protocol::TCP || prot == L3_protocol::UDP) {
|
||||
prot_icd.add_up_diff(icd);
|
||||
}
|
||||
_src_port(prot, prot_base, prot_icd, remote_side.dst_port());
|
||||
_dst_port(prot, prot_base, prot_icd, remote_side.src_port());
|
||||
|
||||
_pass_prot_to_domain(
|
||||
remote_domain, eth, size_guard, ip, ip_icd, prot,
|
||||
prot_base, prot_size);
|
||||
prot_base, prot_icd);
|
||||
|
||||
_link_packet(prot, prot_base, link, client);
|
||||
done = true;
|
||||
@ -1288,13 +1306,19 @@ void Interface::_handle_ip(Ethernet_frame ð,
|
||||
}
|
||||
Domain &remote_domain = rule.domain();
|
||||
_adapt_eth(eth, rule.to_ip(), pkt, remote_domain);
|
||||
ip.dst(rule.to_ip(), ip_icd);
|
||||
|
||||
Internet_checksum_diff icd { };
|
||||
ip.dst(rule.to_ip(), icd);
|
||||
ip_icd.add_up_diff(icd);
|
||||
if (prot == L3_protocol::TCP || prot == L3_protocol::UDP) {
|
||||
prot_icd.add_up_diff(icd);
|
||||
}
|
||||
if (!(rule.to_port() == Port(0))) {
|
||||
_dst_port(prot, prot_base, rule.to_port());
|
||||
_dst_port(prot, prot_base, prot_icd, rule.to_port());
|
||||
}
|
||||
_nat_link_and_pass(
|
||||
eth, size_guard, ip, ip_icd, prot, prot_base,
|
||||
prot_size, local_id, local_domain, remote_domain);
|
||||
prot_icd, local_id, local_domain, remote_domain);
|
||||
|
||||
done = true;
|
||||
},
|
||||
@ -1319,7 +1343,7 @@ void Interface::_handle_ip(Ethernet_frame ð,
|
||||
Domain &remote_domain = permit_rule.domain();
|
||||
_adapt_eth(eth, local_id.dst_ip, pkt, remote_domain);
|
||||
_nat_link_and_pass(
|
||||
eth, size_guard, ip, ip_icd, prot, prot_base, prot_size,
|
||||
eth, size_guard, ip, ip_icd, prot, prot_base, prot_icd,
|
||||
local_id, local_domain, remote_domain);
|
||||
|
||||
done = true;
|
||||
|
@ -189,11 +189,11 @@ class Net::Interface : private Interface_list::Element
|
||||
Genode::uint32_t xid,
|
||||
Ipv4_address_prefix const &local_intf);
|
||||
|
||||
void _send_icmp_echo_reply(Ethernet_frame ð,
|
||||
Ipv4_packet &ip,
|
||||
Icmp_packet &icmp,
|
||||
Genode::size_t icmp_sz,
|
||||
Size_guard &size_guard);
|
||||
void _send_icmp_echo_reply(Ethernet_frame ð,
|
||||
Ipv4_packet &ip,
|
||||
Icmp_packet &icmp,
|
||||
Internet_checksum_diff &icmp_icd,
|
||||
Size_guard &size_guard);
|
||||
|
||||
Forward_rule_tree &_forward_rules(Domain &local_domain,
|
||||
L3_protocol const prot) const;
|
||||
@ -234,7 +234,7 @@ class Net::Interface : private Interface_list::Element
|
||||
Packet_descriptor const &pkt,
|
||||
L3_protocol prot,
|
||||
void *prot_base,
|
||||
Genode::size_t prot_size,
|
||||
Internet_checksum_diff &prot_icd,
|
||||
Domain &local_domain);
|
||||
|
||||
void _handle_icmp_error(Ethernet_frame ð,
|
||||
@ -244,7 +244,7 @@ class Net::Interface : private Interface_list::Element
|
||||
Packet_descriptor const &pkt,
|
||||
Domain &local_domain,
|
||||
Icmp_packet &icmp,
|
||||
Genode::size_t icmp_sz);
|
||||
Internet_checksum_diff &icmp_icd);
|
||||
|
||||
void _handle_icmp(Ethernet_frame ð,
|
||||
Size_guard &size_guard,
|
||||
@ -253,7 +253,7 @@ class Net::Interface : private Interface_list::Element
|
||||
Packet_descriptor const &pkt,
|
||||
L3_protocol prot,
|
||||
void *prot_base,
|
||||
Genode::size_t prot_size,
|
||||
Internet_checksum_diff &prot_icd,
|
||||
Domain &local_domain,
|
||||
Ipv4_address_prefix const &local_intf);
|
||||
|
||||
@ -268,7 +268,7 @@ class Net::Interface : private Interface_list::Element
|
||||
Internet_checksum_diff &ip_icd,
|
||||
L3_protocol const prot,
|
||||
void *const prot_base,
|
||||
Genode::size_t const prot_size,
|
||||
Internet_checksum_diff &prot_icd,
|
||||
Link_side_id const &local_id,
|
||||
Domain &local_domain,
|
||||
Domain &remote_domain);
|
||||
@ -287,7 +287,7 @@ class Net::Interface : private Interface_list::Element
|
||||
Internet_checksum_diff const &ip_icd,
|
||||
L3_protocol const prot,
|
||||
void *const prot_base,
|
||||
Genode::size_t const prot_size);
|
||||
Internet_checksum_diff const &prot_icd);
|
||||
|
||||
void _handle_pkt();
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user