nic_bridge: fixed MAC addresses

Enable configuration of a fixed MAC address for each client.

Fixes #3040
This commit is contained in:
Martin Stein 2018-11-14 19:06:10 +01:00 committed by Christian Helmuth
parent a062ba6dd2
commit e0b7fb1929
6 changed files with 98 additions and 17 deletions

View File

@ -51,23 +51,28 @@ append config {
<resource name="RAM" quantum="1M"/>
<provides><service name="Timer"/></provides>
</start>
<start name="nic_drv">
<binary name="} [nic_drv_binary] {"/>
<resource name="RAM" quantum="4M"/>
<provides><service name="Nic"/></provides>
</start>
<start name="nic_bridge" caps="200">
<resource name="RAM" quantum="24M"/>
<provides><service name="Nic"/></provides>
<config verbose="yes">
<policy label_prefix="test-lwip_httpsrv" ip_addr="10.0.2.55"/>
<config verbose="yes" mac="02:02:02:02:42:00">
<policy label_prefix="server_1" ip_addr="10.0.2.55"/>
<policy label_prefix="server_2" ip_addr="10.0.2.56" mac="02:02:02:02:23:00"/>
</config>
<route>
<service name="Nic"> <child name="nic_drv"/> </service>
<any-service> <parent/> <any-child/> </any-service>
</route>
</start>
<start name="test-lwip_httpsrv">
<start name="server_1">
<binary name="test-lwip_httpsrv"/>
<resource name="RAM" quantum="32M"/>
<route>
<service name="Nic"> <child name="nic_bridge"/> </service>
@ -83,7 +88,27 @@ append config {
<libc stdout="/dev/log" stderr="/dev/log" socket="/socket"/>
</config>
</start>
<start name="test-http_clnt" caps="120">
<start name="server_2">
<binary name="test-lwip_httpsrv"/>
<resource name="RAM" quantum="32M"/>
<route>
<service name="Nic"> <child name="nic_bridge"/> </service>
<any-service> <parent/> <any-child/> </any-service>
</route>
<config port="80">
<vfs>
<dir name="socket">
<lwip ip_addr="10.0.2.56" netmask="255.255.255.0" gateway="10.0.2.1"/>
</dir>
<dir name="dev"> <log/> </dir>
</vfs>
<libc stdout="/dev/log" stderr="/dev/log" socket="/socket"/>
</config>
</start>
<start name="client_1" caps="120">
<binary name="test-http_clnt"/>
<resource name="RAM" quantum="32M"/>
<route>
<service name="Nic"> <child name="nic_bridge"/> </service>
@ -97,6 +122,22 @@ append config {
<libc stdout="/dev/log" stderr="/dev/log" socket="/socket"/>
</config>
</start>
<start name="client_2" caps="120">
<binary name="test-http_clnt"/>
<resource name="RAM" quantum="32M"/>
<route>
<service name="Nic"> <child name="nic_bridge"/> </service>
<any-service> <parent/> <any-child/> </any-service>
</route>
<config server_ip="10.0.2.56" server_port="80">
<vfs>
<dir name="socket"> <lwip dhcp="yes"/> </dir>
<dir name="dev"> <log/> </dir>
</vfs>
<libc stdout="/dev/log" stderr="/dev/log" socket="/socket"/>
</config>
</start>
</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

View File

@ -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 '<policy>'
tag. For example:
!<start name="nic_bridge">
! ...
! <config>
! <policy label_prefix="lighttpd" mac="02:02:02:01:23:45"/>
! </config>
!</start>
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

View File

@ -211,14 +211,30 @@ class Net::Root : public Genode::Root_component<Net::Session_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<Net::Session_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'");

View File

@ -19,6 +19,7 @@
<xs:complexContent>
<xs:extension base="Session_policy">
<xs:attribute name="ip_addr" type="Ipv4_address" />
<xs:attribute name="mac" type="Mac_address" />
</xs:extension>
</xs:complexContent>
</xs:complexType>

View File

@ -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_ */

View File

@ -3,7 +3,7 @@
<xs:simpleType name="Mac_address">
<xs:restriction base="xs:string">
<xs:pattern value="[0-9a-fA-F]{2}.[0-9a-fA-F]{2}.[0-9a-fA-F]{2}.[0-9a-fA-F]{2}.[0-9a-fA-F]{2}.[0-9a-fA-F]{2}"/>
<xs:pattern value="[0-9a-fA-F]{2}:[0-9a-fA-F]{2}:[0-9a-fA-F]{2}:[0-9a-fA-F]{2}:[0-9a-fA-F]{2}:[0-9a-fA-F]{2}"/>
</xs:restriction>
</xs:simpleType><!-- Mac_address -->