nic_router: advanced timeout configuration

Replace former rtt_sec attribute of the <config> tag by more specific
(and still optional) attributes for timeouts used in the NIC router
(these are also the default values):

<config dhcp_discover_timeout_sec="10"
        dhcp_request_timeout_sec="10"
        dhcp_offer_timeout_sec="10"
        udp_idle_timeout_sec="30"
        tcp_idle_timeout_sec="600"
        tcp_max_segm_lifetime_sec="30">

Details about the new attributes can be found in the README of the router.

Issue #2590
This commit is contained in:
Martin Stein 2017-11-28 15:03:28 +01:00 committed by Christian Helmuth
parent 564e6a6885
commit 3cdcb528ff
10 changed files with 91 additions and 46 deletions

View File

@ -66,7 +66,7 @@ append config {
<start name="nic_router" caps="200" priority="-1">
<resource name="RAM" quantum="10M"/>
<provides><service name="Nic"/></provides>
<config rtt_sec="6" verbose="no">
<config verbose="no">
<policy label_prefix="udp_client_1" domain="udp_client_1" />
<policy label_prefix="http_client_3" domain="http_client_3" />

View File

@ -83,7 +83,13 @@ append config {
<start name="nic_router" caps="200" priority="-1">
<resource name="RAM" quantum="10M"/>
<provides><service name="Nic"/></provides>
<config rtt_sec="12" verbose="no">
<config verbose="no"
dhcp_discover_timeout_sec="3"
dhcp_request_timeout_sec="3"
dhcp_offer_timeout_sec="3"
udp_idle_timeout_sec="30"
tcp_idle_timeout_sec="30"
tcp_max_segm_lifetime_sec="15">
<policy label_prefix="udp_client_1" domain="udp_client_1" />
<policy label_prefix="http_client_3" domain="http_client_3" />

View File

@ -211,31 +211,36 @@ the case if the transfer includes NAT no matter of what kind or for which
side.
It is desirable to discard a link state as soon as it is not needed anymore.
The more precise the algorithm for that, the more efficient can NIC sessions
use their resources (ports, RAM), and the less is the risk for DoS attacks.
In order to meet this requirement, the router needs to know the round-trip
time of the exchange behind a link state. This value is given through the
attribute 'rtt_sec' in the router's configuration:
The more precise this is done, the more efficient can NIC sessions use their
resources (ports, RAM), and the less is the risk for DoS attacks. Therefore,
the NIC router keeps track of the idle time of a link. Idle time means the
time passed since the last packet was routed using that link regardless of
the direction or content of that packet. The amount of idle time at which
the NIC router shall discard a link state can be configured in the <config>
tag of the router for each link type separately:
! <config rtt_sec="3"> ... </config>
! <config udp_idle_timeout_sec="30"
! tcp_idle_timeout_sec="50">
This would set the round-trip time to three seconds. The value is used for all
link states so you should choose it with care. If it is too low, replies that
normally need no routing rule may get lost. If it is too high, link states are
held longer than necessary.
This would set the maximum UDP idle time to 30 and the maximum TCP idle time
to 50 seconds. You should choose these values with care. If they are too low,
replies that normally need no routing rule may get lost. If it is too high,
link states are held longer than necessary.
In general, each link state is discarded after a duration of the round-trip
time without a matching packet. For UDP link states, this is the only rule and
better known as hole punching. It allows peers to keep alive a UDP
pseudo-connection through the router by frequently sending empty packets. The
need for such a pseudo-connection arises from the router's demand to support
NAT for UDP transfers and the consequence of keeping the corresponding mapping
information.
For UDP link states, this timeout is the only condition that leads to a
discard. This is better known as hole punching. It allows peers to keep alive
a UDP pseudo-connection through the router by frequently sending empty packets.
The need for such a pseudo-connection arises from the router's demand to
support NAT for UDP transfers and the consequence of keeping the corresponding
mapping information.
The lifetime management of TCP link states, in contrast, is more complex. In
addition to the common timeout, they may be discarded even if they still
receive packets. This is the case when the router observed the four-way
termination handshake of TCP and the round-trip time has passed.
addition to the common timeout, they may be discarded also after the router
observed the four-way termination handshake of TCP plus a duration of two
times the maximum segment lifetime. The maximum segment lifetime can be be set
in the <config> tag too:
! <config tcp_max_segm_lifetime_sec="20">
Configuring NAT
@ -297,9 +302,13 @@ assignment in seconds. The IPv4 address range must be in the subnet
defined by the interface attribute of the domain tag and must not cover
the IPv4 address in this attribute. The dns_server attribute gives the
IPv4 address of the DNS server that might also be in another subnet.
The lifetime of an offered assignment is the configured round-trip time of
the router while ip_lease_time_sec is applied only when the offer is
acknowledged by the client in time.
The lifetime of an assignment that was yet only offered to the client
can be configured for all domains in the <config> tag of the router:
! <config dhcp_offer_timeout_sec="6">
The timeout ip_lease_time_sec is applied only when the offer is acknowledged
by the client in time.
Configuring DHCP client functionality
@ -319,6 +328,13 @@ and all other router functionality is disabled for the domain. A domain cannot
act as DHCP client and DHCP server at once. So, a 'domain' tag must either
have an 'interface' attribute or must not contain a 'dhcp-server' tag.
The timeouts when waiting for the reply of DHCP discover messages and for DHCP
request messages can be configured for all domains in the <config> tag of the
router:
! <config dhcp_discover_timeout_sec="10"
! dhcp_request_timeout_sec="6">
Examples
########

View File

@ -49,7 +49,12 @@ Configuration::Configuration(Xml_node const node,
Allocator &alloc)
:
_alloc(alloc), _verbose(node.attribute_value("verbose", false)),
_rtt(read_sec_attr(node, "rtt_sec", DEFAULT_RTT_SEC)),
_dhcp_discover_timeout(read_sec_attr(node, "dhcp_discover_timeout_sec", DEFAULT_DHCP_DISCOVER_TIMEOUT_SEC)),
_dhcp_request_timeout (read_sec_attr(node, "dhcp_request_timeout_sec", DEFAULT_DHCP_REQUEST_TIMEOUT_SEC )),
_dhcp_offer_timeout (read_sec_attr(node, "dhcp_offer_timeout_sec", DEFAULT_DHCP_OFFER_TIMEOUT_SEC )),
_udp_idle_timeout (read_sec_attr(node, "udp_idle_timeout_sec", DEFAULT_UDP_IDLE_TIMEOUT_SEC )),
_tcp_idle_timeout (read_sec_attr(node, "tcp_idle_timeout_sec", DEFAULT_TCP_IDLE_TIMEOUT_SEC )),
_tcp_max_segm_lifetime(read_sec_attr(node, "tcp_max_segm_lifetime_sec", DEFAULT_TCP_MAX_SEGM_LIFETIME_SEC)),
_node(node)
{
/* read domains */

View File

@ -31,13 +31,23 @@ class Net::Configuration
Genode::Allocator &_alloc;
bool const _verbose;
Genode::Microseconds const _rtt;
Genode::Microseconds const _dhcp_discover_timeout;
Genode::Microseconds const _dhcp_request_timeout;
Genode::Microseconds const _dhcp_offer_timeout;
Genode::Microseconds const _udp_idle_timeout;
Genode::Microseconds const _tcp_idle_timeout;
Genode::Microseconds const _tcp_max_segm_lifetime;
Domain_tree _domains;
Genode::Xml_node const _node;
public:
enum { DEFAULT_RTT_SEC = 6 };
enum { DEFAULT_DHCP_DISCOVER_TIMEOUT_SEC = 10 };
enum { DEFAULT_DHCP_REQUEST_TIMEOUT_SEC = 10 };
enum { DEFAULT_DHCP_OFFER_TIMEOUT_SEC = 10 };
enum { DEFAULT_UDP_IDLE_TIMEOUT_SEC = 30 };
enum { DEFAULT_TCP_IDLE_TIMEOUT_SEC = 600 };
enum { DEFAULT_TCP_MAX_SEGM_LIFETIME_SEC = 30 };
Configuration(Genode::Xml_node const node, Genode::Allocator &alloc);
@ -46,10 +56,15 @@ class Net::Configuration
** Accessors **
***************/
bool verbose() const { return _verbose; }
Genode::Microseconds rtt() const { return _rtt; }
Domain_tree &domains() { return _domains; }
Genode::Xml_node node() const { return _node; }
bool verbose() const { return _verbose; }
Genode::Microseconds dhcp_discover_timeout() const { return _dhcp_discover_timeout; }
Genode::Microseconds dhcp_request_timeout() const { return _dhcp_request_timeout; }
Genode::Microseconds dhcp_offer_timeout() const { return _dhcp_offer_timeout; }
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; }
Domain_tree &domains() { return _domains; }
Genode::Xml_node node() const { return _node; }
};
#endif /* _CONFIGURATION_H_ */

View File

@ -41,7 +41,7 @@ Dhcp_client::Dhcp_client(Genode::Allocator &alloc,
void Dhcp_client::discover()
{
_set_state(State::SELECT, _config().rtt());
_set_state(State::SELECT, _config().dhcp_discover_timeout());
_send(Message_type::DISCOVER, Ipv4_address(), Ipv4_address());
}
@ -132,7 +132,7 @@ void Dhcp_client::_handle_dhcp_reply(Dhcp_packet &dhcp)
if (msg_type != Message_type::OFFER) {
throw Packet_ignored("DHCP client expects an offer");
}
_set_state(State::REQUEST, _config().rtt());
_set_state(State::REQUEST, _config().dhcp_request_timeout());
_send(Message_type::REQUEST, dhcp.yiaddr(),
dhcp.option<Dhcp_packet::Server_ipv4>().value());
break;

View File

@ -430,7 +430,7 @@ void Interface::_handle_dhcp_request(Ethernet_frame &eth,
throw Bad_dhcp_request();
} else {
allocation.lifetime(_config().rtt());
allocation.lifetime(_config().dhcp_offer_timeout());
_send_dhcp_reply(dhcp_srv, eth.src(),
allocation.ip(),
Dhcp_packet::Message_type::OFFER,
@ -501,7 +501,7 @@ void Interface::_handle_dhcp_request(Ethernet_frame &eth,
Dhcp_allocation &allocation = *new (_alloc)
Dhcp_allocation(*this, dhcp_srv.alloc_ip(),
dhcp.client_mac(), _timer,
_config().rtt());
_config().dhcp_offer_timeout());
_dhcp_allocations.insert(&allocation);
if (_config().verbose()) {

View File

@ -117,14 +117,15 @@ Link::Link(Interface &cln_interface,
Link_side_id const &srv_id,
Timer::Connection &timer,
Configuration &config,
L3_protocol const protocol)
L3_protocol const protocol,
Microseconds const close_timeout)
:
_config(config),
_client(cln_interface, cln_id, *this),
_server_port_alloc(srv_port_alloc),
_server(srv_interface, srv_id, *this),
_close_timeout(timer, *this, &Link::_handle_close_timeout),
_close_timeout_us(_config.rtt()),
_close_timeout_us(close_timeout),
_protocol(protocol)
{
_close_timeout.schedule(_close_timeout_us);
@ -172,14 +173,14 @@ Tcp_link::Tcp_link(Interface &cln_interface,
L3_protocol const protocol)
:
Link(cln_interface, cln_id, srv_port_alloc, srv_interface, srv_id, timer,
config, protocol)
config, protocol, config.tcp_idle_timeout())
{ }
void Tcp_link::_fin_acked()
{
if (_server_fin_acked && _client_fin_acked) {
_close_timeout.schedule(_close_timeout_us);
_close_timeout.schedule(Microseconds(config().tcp_max_segm_lifetime().value << 1));
_closed = true;
}
}
@ -233,5 +234,5 @@ Udp_link::Udp_link(Interface &cln_interface,
L3_protocol const protocol)
:
Link(cln_interface, cln_id, srv_port_alloc, srv_interface, srv_id, timer,
config, protocol)
config, protocol, config.udp_idle_timeout())
{ }

View File

@ -147,7 +147,8 @@ class Net::Link : public Link_list::Element
Link_side_id const &srv_id,
Timer::Connection &timer,
Configuration &config,
L3_protocol const protocol);
L3_protocol const protocol,
Genode::Microseconds const close_timeout);
void dissolve();
@ -163,8 +164,9 @@ class Net::Link : public Link_list::Element
** Accessors **
***************/
Link_side &client() { return _client; }
Link_side &server() { return _server; }
Link_side &client() { return _client; }
Link_side &server() { return _server; }
Configuration &config() { return _config; }
};

View File

@ -98,7 +98,7 @@ append_if [expr $use_net] config {
<binary name="nic_router"/>
<resource name="RAM" quantum="10M"/>
<provides><service name="Nic"/></provides>
<config rtt_sec="6" verbose="yes">
<config verbose="yes">
<policy label_prefix="router2" domain="router2"/>
@ -126,7 +126,7 @@ append_if [expr $use_net] config {
<binary name="nic_router"/>
<resource name="RAM" quantum="10M"/>
<provides><service name="Nic"/></provides>
<config rtt_sec="6" verbose="yes">
<config verbose="yes">
<policy label_prefix="vbox1" domain="vbox"/>