mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-21 02:01:38 +00:00
nic_router: limit packets handled per signal
Make it configurable how many packets get handled at a max per signal to prevent DoS attacks by clients. Issue #2953
This commit is contained in:
parent
b48c917984
commit
3db7181104
@ -494,6 +494,21 @@ Whether to log most important changes in the state of a domain (number of NIC
|
||||
sessions connected, current IPv4 config).
|
||||
|
||||
|
||||
Other configuration attributes
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
If possible, the NIC router normally handles multiple packets from a NIC
|
||||
session per signal. However, if one NIC session has a high packet rate and a
|
||||
big buffer, this can lead to starvation of the other NIC sessions. Thus, the
|
||||
maximum number of packets handled per signal is limited by default. This limit
|
||||
can be configured as follows (default value shown):
|
||||
|
||||
! <config max_packets_per_signal="32">
|
||||
|
||||
When set to zero, the limit is deactivated, meaning that the router always
|
||||
handles all available packets of a NIC session.
|
||||
|
||||
|
||||
Examples
|
||||
~~~~~~~~
|
||||
|
||||
|
@ -129,6 +129,7 @@
|
||||
</xs:element><!-- domain -->
|
||||
|
||||
</xs:choice>
|
||||
<xs:attribute name="max_packets_per_signal" type="xs:nonNegativeInteger" />
|
||||
<xs:attribute name="verbose" type="Boolean" />
|
||||
<xs:attribute name="verbose_packets" type="Boolean" />
|
||||
<xs:attribute name="verbose_packet_drop" type="Boolean" />
|
||||
|
@ -65,18 +65,19 @@ Configuration::Configuration(Env &env,
|
||||
Interface_list &interfaces)
|
||||
:
|
||||
_alloc(alloc),
|
||||
_verbose (node.attribute_value("verbose", false)),
|
||||
_verbose_packets (node.attribute_value("verbose_packets", false)),
|
||||
_verbose_packet_drop (node.attribute_value("verbose_packet_drop", false)),
|
||||
_verbose_domain_state (node.attribute_value("verbose_domain_state", false)),
|
||||
_icmp_echo_server (node.attribute_value("icmp_echo_server", true)),
|
||||
_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 )),
|
||||
_icmp_idle_timeout (read_sec_attr(node, "icmp_idle_timeout_sec", DEFAULT_ICMP_IDLE_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)),
|
||||
_max_packets_per_signal(node.attribute_value("max_packets_per_signal", (unsigned long)DEFAULT_MAX_PACKETS_PER_SIGNAL)),
|
||||
_verbose (node.attribute_value("verbose", false)),
|
||||
_verbose_packets (node.attribute_value("verbose_packets", false)),
|
||||
_verbose_packet_drop (node.attribute_value("verbose_packet_drop", false)),
|
||||
_verbose_domain_state (node.attribute_value("verbose_domain_state", false)),
|
||||
_icmp_echo_server (node.attribute_value("icmp_echo_server", true)),
|
||||
_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 )),
|
||||
_icmp_idle_timeout (read_sec_attr(node, "icmp_idle_timeout_sec", DEFAULT_ICMP_IDLE_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)
|
||||
{
|
||||
/* do parts of domain initialization that do not lookup other domains */
|
||||
|
@ -34,6 +34,7 @@ class Net::Configuration
|
||||
using Mac_string = Genode::String<17>;
|
||||
|
||||
Genode::Allocator &_alloc;
|
||||
unsigned long const _max_packets_per_signal { 0 };
|
||||
bool const _verbose { false };
|
||||
bool const _verbose_packets { false };
|
||||
bool const _verbose_packet_drop { false };
|
||||
@ -68,6 +69,7 @@ class Net::Configuration
|
||||
enum { DEFAULT_UDP_IDLE_TIMEOUT_SEC = 30 };
|
||||
enum { DEFAULT_TCP_IDLE_TIMEOUT_SEC = 600 };
|
||||
enum { DEFAULT_TCP_MAX_SEGM_LIFETIME_SEC = 30 };
|
||||
enum { DEFAULT_MAX_PACKETS_PER_SIGNAL = 32 };
|
||||
|
||||
Configuration(Genode::Xml_node const node,
|
||||
Genode::Allocator &alloc);
|
||||
@ -86,21 +88,22 @@ class Net::Configuration
|
||||
** Accessors **
|
||||
***************/
|
||||
|
||||
bool verbose() const { return _verbose; }
|
||||
bool verbose_packets() const { return _verbose_packets; }
|
||||
bool verbose_packet_drop() const { return _verbose_packet_drop; }
|
||||
bool verbose_domain_state() const { return _verbose_domain_state; }
|
||||
bool icmp_echo_server() const { return _icmp_echo_server; }
|
||||
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 icmp_idle_timeout() const { return _icmp_idle_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; }
|
||||
Report &report() { return _report(); }
|
||||
Genode::Xml_node node() const { return _node; }
|
||||
unsigned long max_packets_per_signal() const { return _max_packets_per_signal; }
|
||||
bool verbose() const { return _verbose; }
|
||||
bool verbose_packets() const { return _verbose_packets; }
|
||||
bool verbose_packet_drop() const { return _verbose_packet_drop; }
|
||||
bool verbose_domain_state() const { return _verbose_domain_state; }
|
||||
bool icmp_echo_server() const { return _icmp_echo_server; }
|
||||
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 icmp_idle_timeout() const { return _icmp_idle_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; }
|
||||
Report &report() { return _report(); }
|
||||
Genode::Xml_node node() const { return _node; }
|
||||
};
|
||||
|
||||
#endif /* _CONFIGURATION_H_ */
|
||||
|
@ -1278,16 +1278,33 @@ void Interface::_handle_arp(Ethernet_frame ð,
|
||||
}
|
||||
|
||||
|
||||
void Interface::_handle_pkt()
|
||||
{
|
||||
Packet_descriptor const pkt = _sink.get_packet();
|
||||
Size_guard size_guard(pkt.size());
|
||||
try {
|
||||
_handle_eth(_sink.packet_content(pkt), size_guard, pkt);
|
||||
_ack_packet(pkt);
|
||||
}
|
||||
catch (Packet_postponed) { }
|
||||
}
|
||||
|
||||
|
||||
void Interface::_ready_to_submit()
|
||||
{
|
||||
while (_sink.packet_avail()) {
|
||||
Packet_descriptor const pkt = _sink.get_packet();
|
||||
Size_guard size_guard(pkt.size());
|
||||
try {
|
||||
_handle_eth(_sink.packet_content(pkt), size_guard, pkt);
|
||||
_ack_packet(pkt);
|
||||
unsigned long const max_pkts = _config().max_packets_per_signal();
|
||||
if (max_pkts) {
|
||||
for (unsigned long i = 0; _sink.packet_avail(); i++) {
|
||||
|
||||
if (i >= max_pkts) {
|
||||
Signal_transmitter(_sink_submit).submit();
|
||||
break;
|
||||
}
|
||||
_handle_pkt();
|
||||
}
|
||||
catch (Packet_postponed) { }
|
||||
} else {
|
||||
while (_sink.packet_avail()) {
|
||||
_handle_pkt(); }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -239,6 +239,8 @@ class Net::Interface : private Interface_list::Element
|
||||
Size_guard &size_guard,
|
||||
Ipv4_packet &ip);
|
||||
|
||||
void _handle_pkt();
|
||||
|
||||
void _continue_handle_eth(Domain const &domain,
|
||||
Packet_descriptor const &pkt);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user