mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-18 02:40:08 +00:00
nic_router: destroy timed out ARP waiters
The only object that is dynamically allocated by a network interface and that was not equipped with a self-destruct timeout was the ARP waiter. This commit closes this gap by adding a timeout to each ARP waiter that is set to 10 seconds by default but can be configured via the new <config> attribute 'arp_request_timeout_sec'. Ref #4729
This commit is contained in:
parent
20371d0445
commit
09b3fa389d
@ -843,8 +843,8 @@ When set to zero, the limit is deactivated, meaning that the router always
|
||||
handles all available packets of an interface.
|
||||
|
||||
|
||||
Disable requesting address resolutions via ARP
|
||||
----------------------------------------------
|
||||
Configuring ARP
|
||||
---------------
|
||||
|
||||
By default, the NIC router requests required IP-to-MAC address resolutions at a
|
||||
domain using ARP. However this may be a problem in certain environments, e.g.,
|
||||
@ -862,6 +862,14 @@ MAC-address of the packet (instead of requesting the destination MAC-address
|
||||
via ARP). This behavior was observed in common Linux-based systems at network
|
||||
interfaces with the 'NOARP' flag set.
|
||||
|
||||
If ARP is enabled, however, one can configure the request timeout through the
|
||||
following attribute (default value shown):
|
||||
|
||||
! <config arp_request_timeout_sec="10">
|
||||
|
||||
When the router does not receive a reply for a sent ARP request within this
|
||||
timeout, the packet that caused the ARP request and the ARP request state are
|
||||
dropped in order to re-use the resources.
|
||||
|
||||
Behavior regarding the NIC-session link state
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
@ -23,26 +23,42 @@ using namespace Genode;
|
||||
Arp_waiter::Arp_waiter(Interface &src,
|
||||
Domain &dst,
|
||||
Ipv4_address const &ip,
|
||||
Packet_descriptor const &packet)
|
||||
Packet_descriptor const &packet,
|
||||
Microseconds timeout,
|
||||
Cached_timer &timer)
|
||||
:
|
||||
_src_le(this), _src(src), _dst_le(this), _dst_ptr(&dst), _ip(ip),
|
||||
_packet(packet)
|
||||
_packet(packet), _timeout(timer, *this, &Arp_waiter::_handle_timeout, timeout)
|
||||
{
|
||||
_src.arp_stats().alive++;
|
||||
_src.own_arp_waiters().insert(&_src_le);
|
||||
_dst_ptr->foreign_arp_waiters().insert(&_dst_le);
|
||||
_timeout.schedule(timeout);
|
||||
}
|
||||
|
||||
|
||||
Arp_waiter::~Arp_waiter()
|
||||
{
|
||||
_dissolve();
|
||||
_src.arp_stats().alive--;
|
||||
_src.arp_stats().destroyed++;
|
||||
}
|
||||
|
||||
|
||||
void Arp_waiter::_dissolve()
|
||||
{
|
||||
_src.own_arp_waiters().remove(&_src_le);
|
||||
_dst_ptr->foreign_arp_waiters().remove(&_dst_le);
|
||||
}
|
||||
|
||||
|
||||
void Arp_waiter::_handle_timeout(Duration)
|
||||
{
|
||||
_dissolve();
|
||||
_src.timed_out_arp_waiters().insert(&_src_le);
|
||||
}
|
||||
|
||||
|
||||
void Arp_waiter::handle_config(Domain &dst)
|
||||
{
|
||||
_dst_ptr->foreign_arp_waiters().remove(&_dst_le);
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
/* local includes */
|
||||
#include <list.h>
|
||||
#include <lazy_one_shot_timeout.h>
|
||||
|
||||
/* Genode includes */
|
||||
#include <net/ipv4.h>
|
||||
@ -38,12 +39,13 @@ class Net::Arp_waiter
|
||||
{
|
||||
private:
|
||||
|
||||
Arp_waiter_list_element _src_le;
|
||||
Interface &_src;
|
||||
Arp_waiter_list_element _dst_le;
|
||||
Domain *_dst_ptr;
|
||||
Ipv4_address const _ip;
|
||||
Packet_descriptor const _packet;
|
||||
Arp_waiter_list_element _src_le;
|
||||
Interface &_src;
|
||||
Arp_waiter_list_element _dst_le;
|
||||
Domain *_dst_ptr;
|
||||
Ipv4_address const _ip;
|
||||
Packet_descriptor const _packet;
|
||||
Lazy_one_shot_timeout<Arp_waiter> _timeout;
|
||||
|
||||
/*
|
||||
* Noncopyable
|
||||
@ -51,12 +53,18 @@ class Net::Arp_waiter
|
||||
Arp_waiter(Arp_waiter const &);
|
||||
Arp_waiter &operator = (Arp_waiter const &);
|
||||
|
||||
void _handle_timeout(Genode::Duration);
|
||||
|
||||
void _dissolve();
|
||||
|
||||
public:
|
||||
|
||||
Arp_waiter(Interface &src,
|
||||
Domain &dst,
|
||||
Ipv4_address const &ip,
|
||||
Packet_descriptor const &packet);
|
||||
Packet_descriptor const &packet,
|
||||
Genode::Microseconds dissolve_timeout,
|
||||
Cached_timer &timer);
|
||||
|
||||
~Arp_waiter();
|
||||
|
||||
|
@ -189,6 +189,7 @@
|
||||
<xs:attribute name="dhcp_request_timeout_sec" type="Seconds" />
|
||||
<xs:attribute name="dhcp_offer_timeout_sec" type="Seconds" />
|
||||
<xs:attribute name="udp_idle_timeout_sec" type="Seconds" />
|
||||
<xs:attribute name="arp_request_timeout_sec" type="Seconds" />
|
||||
<xs:attribute name="tcp_idle_timeout_sec" type="Seconds" />
|
||||
<xs:attribute name="icmp_idle_timeout_sec" type="Seconds" />
|
||||
<xs:attribute name="tcp_max_segm_lifetime_sec" type="Seconds" />
|
||||
|
@ -46,6 +46,7 @@ Configuration::Configuration(Xml_node const node,
|
||||
_udp_idle_timeout { 0 },
|
||||
_tcp_idle_timeout { 0 },
|
||||
_tcp_max_segm_lifetime { 0 },
|
||||
_arp_request_timeout { 0 },
|
||||
_node { node }
|
||||
{ }
|
||||
|
||||
@ -105,6 +106,7 @@ Configuration::Configuration(Env &env,
|
||||
_udp_idle_timeout { read_sec_attr(node, "udp_idle_timeout_sec", 30) },
|
||||
_tcp_idle_timeout { read_sec_attr(node, "tcp_idle_timeout_sec", 600) },
|
||||
_tcp_max_segm_lifetime { read_sec_attr(node, "tcp_max_segm_lifetime_sec", 15) },
|
||||
_arp_request_timeout { read_sec_attr(node, "arp_request_timeout_sec", 10) },
|
||||
_node { node }
|
||||
{
|
||||
/* do parts of domain initialization that do not lookup other domains */
|
||||
|
@ -49,6 +49,7 @@ class Net::Configuration
|
||||
Genode::Microseconds const _udp_idle_timeout;
|
||||
Genode::Microseconds const _tcp_idle_timeout;
|
||||
Genode::Microseconds const _tcp_max_segm_lifetime;
|
||||
Genode::Microseconds const _arp_request_timeout;
|
||||
Genode::Constructible<Report> _report { };
|
||||
Genode::Reporter *_reporter_ptr { };
|
||||
Domain_dict _domains { };
|
||||
@ -105,6 +106,7 @@ class Net::Configuration
|
||||
Genode::Microseconds udp_idle_timeout() const { return _udp_idle_timeout; }
|
||||
Genode::Microseconds tcp_idle_timeout() const { return _tcp_idle_timeout; }
|
||||
Genode::Microseconds tcp_max_segm_lifetime() const { return _tcp_max_segm_lifetime; }
|
||||
Genode::Microseconds arp_request_timeout() const { return _arp_request_timeout; }
|
||||
Domain_dict &domains() { return _domains; }
|
||||
Genode::Xml_node node() const { return _node; }
|
||||
};
|
||||
|
@ -612,7 +612,7 @@ Packet_result Interface::_adapt_eth(Ethernet_frame ð,
|
||||
});
|
||||
retry_once<Out_of_ram, Out_of_caps>(
|
||||
[&] {
|
||||
new (_alloc) Arp_waiter { *this, remote_domain, hop_ip, pkt };
|
||||
new (_alloc) Arp_waiter { *this, remote_domain, hop_ip, pkt, _config_ptr->arp_request_timeout(), _timer };
|
||||
result = packet_postponed();
|
||||
},
|
||||
[&] { _try_emergency_free_quota(); },
|
||||
@ -1733,6 +1733,17 @@ void Interface::_destroy_released_dhcp_allocations(Domain &local_domain)
|
||||
}
|
||||
|
||||
|
||||
void Interface::_destroy_timed_out_arp_waiters()
|
||||
{
|
||||
while (Arp_waiter_list_element *le = _timed_out_arp_waiters.first()) {
|
||||
Arp_waiter &waiter = *le->object();
|
||||
_drop_packet(waiter.packet(), "ARP request timed out");
|
||||
_timed_out_arp_waiters.remove(le);
|
||||
destroy(_alloc, &waiter);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Packet_result Interface::_handle_eth(Ethernet_frame ð,
|
||||
Size_guard &size_guard,
|
||||
Packet_descriptor const &pkt,
|
||||
@ -1806,6 +1817,7 @@ Packet_result Interface::_handle_eth(void *const eth_base,
|
||||
_destroy_dissolved_links<Icmp_link>(_dissolved_icmp_links, _alloc);
|
||||
_destroy_dissolved_links<Udp_link>(_dissolved_udp_links, _alloc);
|
||||
_destroy_dissolved_links<Tcp_link>(_dissolved_tcp_links, _alloc);
|
||||
_destroy_timed_out_arp_waiters();
|
||||
_destroy_released_dhcp_allocations(domain);
|
||||
|
||||
/* log received packet if desired */
|
||||
@ -2089,6 +2101,7 @@ void Interface::handle_config_1(Configuration &config)
|
||||
_destroy_dissolved_links<Icmp_link>(_dissolved_icmp_links, _alloc);
|
||||
_destroy_dissolved_links<Udp_link> (_dissolved_udp_links, _alloc);
|
||||
_destroy_dissolved_links<Tcp_link> (_dissolved_tcp_links, _alloc);
|
||||
_destroy_timed_out_arp_waiters();
|
||||
_destroy_released_dhcp_allocations(old_domain);
|
||||
|
||||
/* do not consider to reuse IP config if the domains differ */
|
||||
|
@ -154,6 +154,7 @@ class Net::Interface : private Interface_list::Element
|
||||
Genode::Allocator &_alloc;
|
||||
Domain *_domain_ptr { };
|
||||
Arp_waiter_list _own_arp_waiters { };
|
||||
Arp_waiter_list _timed_out_arp_waiters { };
|
||||
Link_list _tcp_links { };
|
||||
Link_list _udp_links { };
|
||||
Link_list _icmp_links { };
|
||||
@ -196,6 +197,8 @@ class Net::Interface : private Interface_list::Element
|
||||
|
||||
void _try_emergency_free_quota();
|
||||
|
||||
void _destroy_timed_out_arp_waiters();
|
||||
|
||||
[[nodiscard]] Packet_result _new_dhcp_allocation(Ethernet_frame ð,
|
||||
Dhcp_packet &dhcp,
|
||||
Dhcp_server &dhcp_srv,
|
||||
@ -474,6 +477,7 @@ class Net::Interface : private Interface_list::Element
|
||||
Mac_address const &router_mac() const { return _router_mac; }
|
||||
Mac_address const &mac() const { return _mac; }
|
||||
Arp_waiter_list &own_arp_waiters() { return _own_arp_waiters; }
|
||||
Arp_waiter_list &timed_out_arp_waiters() { return _timed_out_arp_waiters; }
|
||||
Signal_context_capability pkt_stream_signal_handler() const { return _pkt_stream_signal_handler; }
|
||||
Interface_link_stats &udp_stats() { return _udp_stats; }
|
||||
Interface_link_stats &tcp_stats() { return _tcp_stats; }
|
||||
|
@ -31,7 +31,6 @@
|
||||
#define _LINK_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <timer_session/connection.h>
|
||||
#include <util/avl_tree.h>
|
||||
#include <util/list.h>
|
||||
#include <net/ipv4.h>
|
||||
|
Loading…
Reference in New Issue
Block a user