From e0b7fb1929af99182729b5c6e72f407fe007b4b1 Mon Sep 17 00:00:00 2001 From: Martin Stein Date: Wed, 14 Nov 2018 19:06:10 +0100 Subject: [PATCH] nic_bridge: fixed MAC addresses Enable configuration of a fixed MAC address for each client. Fixes #3040 --- repos/libports/run/nic_bridge.run | 57 +++++++++++++++++-- repos/os/src/server/nic_bridge/README | 13 +++++ repos/os/src/server/nic_bridge/component.h | 33 +++++++---- repos/os/src/server/nic_bridge/config.xsd | 1 + .../os/src/server/nic_bridge/mac_allocator.h | 9 +++ repos/os/xsd/net_types.xsd | 2 +- 6 files changed, 98 insertions(+), 17 deletions(-) diff --git a/repos/libports/run/nic_bridge.run b/repos/libports/run/nic_bridge.run index b02f0e5a09..0f5ed1a1ae 100644 --- a/repos/libports/run/nic_bridge.run +++ b/repos/libports/run/nic_bridge.run @@ -51,23 +51,28 @@ append config { + + - - + + + - + + + @@ -83,7 +88,27 @@ append config { - + + + + + + + + + + + + + + + + + + + + + @@ -97,6 +122,22 @@ append config { + + + + + + + + + + + + + + + + } install_config $config @@ -132,4 +173,10 @@ append_if [have_spec lan9118] qemu_args " -net nic,model=lan9118 " append qemu_args " -net user " -run_genode_until ".*\"test-http_clnt\" exited with exit value 0.*\n" 40 +append done_string {.*?\[server_1 -> lwip] rcv .\[32mETH.\[0m 02:02:02:02:42:00} +append done_string {.*?\[server_2 -> lwip] rcv .\[32mETH.\[0m 02:02:02:02:23:00} +append done_string {.*?"client_." exited with exit value 0} +append done_string {.*?"client_." exited with exit value 0} +append done_string {.*?\n} + +run_genode_until $done_string 40 diff --git a/repos/os/src/server/nic_bridge/README b/repos/os/src/server/nic_bridge/README index d0f7c6e0c8..22814451fc 100644 --- a/repos/os/src/server/nic_bridge/README +++ b/repos/os/src/server/nic_bridge/README @@ -14,6 +14,19 @@ For example: Note that the least relevant byte will be ignored. NIC bridge will use it for enumerating its clients, starting from 0. +A fixed MAC can be configured per client of the NIC bridge using the '' +tag. For example: + +! +! ... +! +! +! +! + +Note that the fixed MAC addresses must not fall in the range that is used for +runtime MAC allocation. + Normally, NIC bridge is expected to be used in scenarios where an DHCP server is available. However, there are situations where the use of static IPs for virtual NICs is useful. For example, when using the NIC bridge to create a diff --git a/repos/os/src/server/nic_bridge/component.h b/repos/os/src/server/nic_bridge/component.h index 2e46275910..b466fb4ff0 100644 --- a/repos/os/src/server/nic_bridge/component.h +++ b/repos/os/src/server/nic_bridge/component.h @@ -211,14 +211,30 @@ class Net::Root : public Genode::Root_component memset(ip_addr, 0, MAX_IP_ADDR_LENGTH); Session_label label; - try { + Mac_address mac; + try { label = label_from_args(args); Session_policy policy(label, _config); - policy.attribute("ip_addr").value(ip_addr, sizeof(ip_addr)); - } catch (Xml_node::Nonexistent_attribute) { - Genode::log("Missing \"ip_addr\" attribute in policy definition"); - } catch (Session_policy::No_policy_defined) { } + /* determine session MAC address */ + mac = policy.attribute_value("mac", Mac_address()); + if (mac == Mac_address()) { + mac = _mac_alloc.alloc(); } + else if (_mac_alloc.mac_managed_by_allocator(mac)) { + Genode::warning("Bad MAC address in policy"); + throw Service_denied(); + } + + policy.attribute("ip_addr").value(ip_addr, sizeof(ip_addr)); + } + catch (Xml_node::Nonexistent_attribute) { + Genode::log("Missing \"ip_addr\" attribute in policy definition"); + } + catch (Session_policy::No_policy_defined) { } + catch (Mac_allocator::Alloc_failed) { + Genode::warning("Mac address allocation failed!"); + throw Service_denied(); + } size_t ram_quota = Arg_string::find_arg(args, "ram_quota" ).ulong_value(0); size_t tx_buf_size = @@ -230,12 +246,7 @@ class Net::Root : public Genode::Root_component return new (md_alloc()) Session_component(_env.ram(), _env.rm(), _env.ep(), ram_quota, tx_buf_size, rx_buf_size, - _mac_alloc.alloc(), _nic, _verbose, - label, ip_addr); - } - catch (Mac_allocator::Alloc_failed) { - Genode::warning("Mac address allocation failed!"); - throw Service_denied(); + mac, _nic, _verbose, label, ip_addr); } catch (Out_of_ram) { Genode::warning("insufficient 'ram_quota'"); diff --git a/repos/os/src/server/nic_bridge/config.xsd b/repos/os/src/server/nic_bridge/config.xsd index df2dbd2511..e4c84fc295 100644 --- a/repos/os/src/server/nic_bridge/config.xsd +++ b/repos/os/src/server/nic_bridge/config.xsd @@ -19,6 +19,7 @@ + diff --git a/repos/os/src/server/nic_bridge/mac_allocator.h b/repos/os/src/server/nic_bridge/mac_allocator.h index 69892b399c..d34179e644 100644 --- a/repos/os/src/server/nic_bridge/mac_allocator.h +++ b/repos/os/src/server/nic_bridge/mac_allocator.h @@ -52,6 +52,15 @@ class Net::Mac_allocator } void free(Mac_address mac) { _free[mac.addr[5]] = true; } + + bool mac_managed_by_allocator(Mac_address &mac) + { + return _base.addr[0] == mac.addr[0] && + _base.addr[1] == mac.addr[1] && + _base.addr[2] == mac.addr[2] && + _base.addr[3] == mac.addr[3] && + _base.addr[4] == mac.addr[4]; + } }; #endif /* _MAC_ALLOCATOR_H_ */ diff --git a/repos/os/xsd/net_types.xsd b/repos/os/xsd/net_types.xsd index 7d88cdc28f..901c2888a4 100644 --- a/repos/os/xsd/net_types.xsd +++ b/repos/os/xsd/net_types.xsd @@ -3,7 +3,7 @@ - +