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