diff --git a/repos/os/run/nic_router_disable_arp.run b/repos/os/run/nic_router_disable_arp.run new file mode 100644 index 0000000000..e71365752e --- /dev/null +++ b/repos/os/run/nic_router_disable_arp.run @@ -0,0 +1,102 @@ +if {![have_include power_on/qemu] || [have_spec foc] || [have_spec linux] || + [have_spec rpi3] || [expr [have_spec imx53] && [have_spec trustzone]]} { + + puts "Run script is not supported on this platform." + exit 0 +} + +create_boot_directory + +import_from_depot [depot_user]/src/[base_src] \ + [depot_user]/pkg/[drivers_nic_pkg] + +build { app/ping server/nic_router init } + +append config { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +} + +install_config $config + +build_boot_image { ping nic_router init } + +append qemu_args " -nographic " +append_qemu_nic_args + +set done_string ".*child \"ping\" exited with exit value 0.*\n" + +run_genode_until $done_string 10 + +grep_output { ARP } +compare_output_to {} diff --git a/repos/os/src/server/nic_router/README b/repos/os/src/server/nic_router/README index 9a78b6e88c..4fa7594159 100644 --- a/repos/os/src/server/nic_router/README +++ b/repos/os/src/server/nic_router/README @@ -532,6 +532,10 @@ sessions connected, current IPv4 config). Other configuration attributes ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Maximum number of packets handled per signal +-------------------------------------------- + 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 @@ -544,8 +548,28 @@ When set to zero, the limit is deactivated, meaning that the router always handles all available packets of a NIC session. +Disable requesting address resolutions via 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., +when being connected to an LTE modem that doesn't forward ARP. In order to +deal with such scenarios, one can disable ARP requests at a domain by setting +the flag 'use_arp' to 'no' (default is 'yes'): + +! +! +! + +Whenever the NIC router has to send a packet at a domain with 'use_arp="no"', +it will set the destination MAC-address of the packet to equal the source +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. + + Behavior regarding the NIC-session link state ---------------------------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ At downlinks, the NIC router applies a feedback-driven state machine for the link state in order to ensure that clients recognize state transitions. This @@ -593,6 +617,7 @@ automated run scripts: * libports/run/nic_router.run (basic functionality) * dde_linux/run/nic_router_uplinks.run (dynamically switching uplinks) * os/run/ping_nic_router.run (ICMP routing) +* os/run/nic_router_disable_arp.run ('use_arp' configuration flag) * os/run/nic_router_dhcp_unmanaged.run (DHCP + link states without a manager) * os/run/nic_router_dhcp_managed.run (DHCP + link states with a manager) * os/run/nic_router_flood.run (client misbehaving on protocol level) diff --git a/repos/os/src/server/nic_router/config.xsd b/repos/os/src/server/nic_router/config.xsd index c9773e028a..2a07c51955 100644 --- a/repos/os/src/server/nic_router/config.xsd +++ b/repos/os/src/server/nic_router/config.xsd @@ -138,6 +138,7 @@ + diff --git a/repos/os/src/server/nic_router/domain.cc b/repos/os/src/server/nic_router/domain.cc index 31073ad387..7b26e9379f 100644 --- a/repos/os/src/server/nic_router/domain.cc +++ b/repos/os/src/server/nic_router/domain.cc @@ -209,6 +209,7 @@ Domain::Domain(Configuration &config, Xml_node const node, Allocator &alloc) config.verbose_packet_drop()) }, _icmp_echo_server { node.attribute_value("icmp_echo_server", config.icmp_echo_server()) }, + _use_arp { _node.attribute_value("use_arp", true) }, _label { node.attribute_value("label", String<160>()).string() } { diff --git a/repos/os/src/server/nic_router/domain.h b/repos/os/src/server/nic_router/domain.h index c7ac7f7667..fe12759d85 100644 --- a/repos/os/src/server/nic_router/domain.h +++ b/repos/os/src/server/nic_router/domain.h @@ -119,6 +119,7 @@ class Net::Domain : public Domain_base, bool const _verbose_packets; bool const _verbose_packet_drop; bool const _icmp_echo_server; + bool const _use_arp; Genode::Session_label const _label; Domain_link_stats _udp_stats { }; Domain_link_stats _tcp_stats { }; @@ -209,6 +210,7 @@ class Net::Domain : public Domain_base, bool verbose_packets() const { return _verbose_packets; } bool verbose_packet_drop() const { return _verbose_packet_drop; } bool icmp_echo_server() const { return _icmp_echo_server; } + bool use_arp() const { return _use_arp; } Genode::Session_label const &label() const { return _label; } Ipv4_config const &ip_config() const { return *_ip_config; } List &ip_config_dependents() { return _ip_config_dependents; } diff --git a/repos/os/src/server/nic_router/interface.cc b/repos/os/src/server/nic_router/interface.cc index 851f1b7c40..84e04f4c50 100644 --- a/repos/os/src/server/nic_router/interface.cc +++ b/repos/os/src/server/nic_router/interface.cc @@ -282,6 +282,9 @@ void Interface::_pass_prot(Ethernet_frame ð, 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); } @@ -535,17 +538,21 @@ void Interface::_adapt_eth(Ethernet_frame ð, if (!remote_ip_cfg.valid) { throw Drop_packet("target domain has yet no IP config"); } - Ipv4_address const &hop_ip = remote_domain.next_hop(dst_ip); - try { eth.dst(remote_domain.arp_cache().find_by_ip(hop_ip).mac()); } - catch (Arp_cache::No_match) { - remote_domain.interfaces().for_each([&] (Interface &interface) { - interface._broadcast_arp_request(remote_ip_cfg.interface.address, - hop_ip); - }); - try { new (_alloc) Arp_waiter { *this, remote_domain, hop_ip, pkt }; } - catch (Out_of_ram) { throw Free_resources_and_retry_handle_eth(); } - catch (Out_of_caps) { throw Free_resources_and_retry_handle_eth(); } - throw Packet_postponed(); + if (remote_domain.use_arp()) { + + Ipv4_address const &hop_ip = remote_domain.next_hop(dst_ip); + try { eth.dst(remote_domain.arp_cache().find_by_ip(hop_ip).mac()); } + catch (Arp_cache::No_match) { + remote_domain.interfaces().for_each([&] (Interface &interface) { + interface._broadcast_arp_request(remote_ip_cfg.interface.address, + hop_ip); + }); + try { new (_alloc) Arp_waiter { *this, remote_domain, hop_ip, pkt }; } + catch (Out_of_ram) { throw Free_resources_and_retry_handle_eth(); } + catch (Out_of_caps) { throw Free_resources_and_retry_handle_eth(); } + throw Packet_postponed(); + } + } } diff --git a/tool/autopilot.list b/tool/autopilot.list index fff5382b88..b2f80af002 100644 --- a/tool/autopilot.list +++ b/tool/autopilot.list @@ -41,6 +41,7 @@ nic_bridge nic_bridge_stress nic_dump nic_router +nic_router_disable_arp nic_router_dhcp_managed nic_router_dhcp_unmanaged nic_router_flood