mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-19 05:37:54 +00:00
nic_router: multiple uplinks
Introduce the uplink tag: ! <config> ! <uplink label="wifi" domain="uplink"> ! <uplink label="wired" domain="wired_bridge"> ! <uplink domain="wired_bridge"> ! <config/> For each uplink tag, the NIC router requests a NIC session with the corresponding label or an empty label if there is no label attribute. These NIC sessions get attached to the domain that is set in their uplink tag as soon as the domain appears. This means their lifetime is not bound to the domain. Uplink NIC sessions can be safely moved from one domain to another without being closed by reconfiguring the corresponding domain attribute. Attention: This may render previously valid NIC router configurations useless. A domain named "uplink" doesn't automatically request a NIC session anymore. To fix these configurations, just add ! <uplink domain="uplink"/> or ! <uplink label="[LABEL]" domain="uplink"/> as direct subtag of the <config> tag. Issue #2840
This commit is contained in:
parent
d4f08b5a71
commit
49a3a0e0d0
@ -125,8 +125,9 @@ append config {
|
||||
<inline>
|
||||
|
||||
<config dhcp_discover_timeout_sec="1">
|
||||
<default-policy domain="downlink"/>
|
||||
<domain name="uplink" label="nic">
|
||||
<default-policy domain="downlink"/>
|
||||
<uplink label="nic" domain="uplink" />
|
||||
<domain name="uplink">
|
||||
<nat domain="downlink" icmp-ids="999"/>
|
||||
</domain>
|
||||
<domain name="downlink" interface="10.0.1.79/24">
|
||||
@ -140,8 +141,9 @@ append config {
|
||||
<inline>
|
||||
|
||||
<config dhcp_discover_timeout_sec="1">
|
||||
<default-policy domain="downlink"/>
|
||||
<domain name="uplink" label="wifi">
|
||||
<default-policy domain="downlink"/>
|
||||
<uplink label="wifi" domain="uplink" />
|
||||
<domain name="uplink">
|
||||
<nat domain="downlink" icmp-ids="999"/>
|
||||
</domain>
|
||||
<domain name="downlink" interface="10.0.1.79/24">
|
||||
@ -167,8 +169,9 @@ append config {
|
||||
<inline>
|
||||
|
||||
<config dhcp_discover_timeout_sec="1">
|
||||
<default-policy domain="downlink"/>
|
||||
<domain name="uplink" label="nic">
|
||||
<default-policy domain="downlink"/>
|
||||
<uplink label="nic" domain="uplink" />
|
||||
<domain name="uplink">
|
||||
<nat domain="downlink" icmp-ids="999"/>
|
||||
</domain>
|
||||
<domain name="downlink" interface="10.0.1.79/24">
|
||||
@ -182,8 +185,9 @@ append config {
|
||||
<inline>
|
||||
|
||||
<config dhcp_discover_timeout_sec="1">
|
||||
<default-policy domain="downlink"/>
|
||||
<domain name="uplink" label="nic">
|
||||
<default-policy domain="downlink"/>
|
||||
<uplink label="nic" domain="uplink" />
|
||||
<domain name="uplink">
|
||||
<nat domain="downlink" icmp-ids="999"/>
|
||||
</domain>
|
||||
<domain name="downlink" interface="10.0.1.79/24">
|
||||
@ -209,8 +213,9 @@ append config {
|
||||
<inline>
|
||||
|
||||
<config dhcp_discover_timeout_sec="1">
|
||||
<default-policy domain="downlink"/>
|
||||
<domain name="uplink" label="wifi">
|
||||
<default-policy domain="downlink"/>
|
||||
<uplink label="wifi" domain="uplink" />
|
||||
<domain name="uplink">
|
||||
<nat domain="downlink" icmp-ids="999"/>
|
||||
</domain>
|
||||
<domain name="downlink" interface="10.0.1.79/24">
|
||||
@ -224,8 +229,9 @@ append config {
|
||||
<inline>
|
||||
|
||||
<config dhcp_discover_timeout_sec="1">
|
||||
<default-policy domain="downlink"/>
|
||||
<domain name="uplink" label="nic">
|
||||
<default-policy domain="downlink"/>
|
||||
<uplink label="nic" domain="uplink" />
|
||||
<domain name="uplink">
|
||||
<nat domain="downlink" icmp-ids="999"/>
|
||||
</domain>
|
||||
<domain name="downlink" interface="10.0.1.79/24">
|
||||
|
@ -15,6 +15,24 @@
|
||||
#include <network.h>
|
||||
|
||||
|
||||
void Sculpt::Network::_generate_nic_router_uplink(Xml_generator &xml,
|
||||
char const *label)
|
||||
{
|
||||
xml.node("uplink", [&] () {
|
||||
xml.attribute("label", label);
|
||||
xml.attribute("domain", "uplink");
|
||||
});
|
||||
gen_named_node(xml, "domain", "uplink", [&] () {
|
||||
xml.node("nat", [&] () {
|
||||
xml.attribute("domain", "default");
|
||||
xml.attribute("tcp-ports", "1000");
|
||||
xml.attribute("udp-ports", "1000");
|
||||
xml.attribute("icmp-ids", "1000");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
void Sculpt::Network::handle_key_press(Codepoint code)
|
||||
{
|
||||
enum { BACKSPACE = 8, ENTER = 10 };
|
||||
@ -70,22 +88,12 @@ void Sculpt::Network::_generate_nic_router_config()
|
||||
xml.node("default-policy", [&] () {
|
||||
xml.attribute("domain", "default"); });
|
||||
|
||||
if (_nic_target.type() != Nic_target::LOCAL) {
|
||||
gen_named_node(xml, "domain", "uplink", [&] () {
|
||||
switch (_nic_target.type()) {
|
||||
case Nic_target::WIRED: xml.attribute("label", "wired"); break;
|
||||
case Nic_target::WIFI: xml.attribute("label", "wifi"); break;
|
||||
default: break;
|
||||
}
|
||||
xml.node("nat", [&] () {
|
||||
xml.attribute("domain", "default");
|
||||
xml.attribute("tcp-ports", "1000");
|
||||
xml.attribute("udp-ports", "1000");
|
||||
xml.attribute("icmp-ids", "1000");
|
||||
});
|
||||
});
|
||||
bool uplink_exists = true;
|
||||
switch (_nic_target.type()) {
|
||||
case Nic_target::WIRED: _generate_nic_router_uplink(xml, "wired"); break;
|
||||
case Nic_target::WIFI: _generate_nic_router_uplink(xml, "wifi"); break;
|
||||
default: uplink_exists = false;
|
||||
}
|
||||
|
||||
gen_named_node(xml, "domain", "default", [&] () {
|
||||
xml.attribute("interface", "10.0.1.1/24");
|
||||
|
||||
@ -96,7 +104,7 @@ void Sculpt::Network::_generate_nic_router_config()
|
||||
xml.attribute("dns_server_from", "uplink"); }
|
||||
});
|
||||
|
||||
if (_nic_target.type() != Nic_target::LOCAL) {
|
||||
if (uplink_exists) {
|
||||
xml.node("tcp", [&] () {
|
||||
xml.attribute("dst", "0.0.0.0/0");
|
||||
xml.node("permit-any", [&] () {
|
||||
@ -171,19 +179,31 @@ void Sculpt::Network::_handle_nic_router_config(Xml_node config)
|
||||
if (!config.has_sub_node("domain"))
|
||||
target = Nic_target::OFF;
|
||||
|
||||
config.for_each_sub_node("domain", [&] (Xml_node domain) {
|
||||
struct Break : Exception { };
|
||||
try {
|
||||
config.for_each_sub_node("domain", [&] (Xml_node domain) {
|
||||
|
||||
/* skip non-uplink domains */
|
||||
if (domain.attribute_value("name", String<16>()) != "uplink")
|
||||
return;
|
||||
/* skip domains that are not called "uplink" */
|
||||
if (domain.attribute_value("name", String<16>()) != "uplink")
|
||||
return;
|
||||
|
||||
if (domain.attribute_value("label", String<16>()) == "wired")
|
||||
target = Nic_target::WIRED;
|
||||
config.for_each_sub_node("uplink", [&] (Xml_node uplink) {
|
||||
|
||||
if (domain.attribute_value("label", String<16>()) == "wifi")
|
||||
target = Nic_target::WIFI;
|
||||
});
|
||||
/* skip uplinks not assigned to a domain called "uplink" */
|
||||
if (uplink.attribute_value("domain", String<16>()) != "uplink")
|
||||
return;
|
||||
|
||||
if (uplink.attribute_value("label", String<16>()) == "wired") {
|
||||
target = Nic_target::WIRED;
|
||||
throw Break();
|
||||
}
|
||||
if (uplink.attribute_value("label", String<16>()) == "wifi") {
|
||||
target = Nic_target::WIFI;
|
||||
throw Break();
|
||||
}
|
||||
});
|
||||
});
|
||||
} catch (Break) { }
|
||||
_nic_target.manual_type = target;
|
||||
}
|
||||
|
||||
|
@ -63,6 +63,9 @@ struct Sculpt::Network : Network_dialog::Action
|
||||
|
||||
void _generate_nic_router_config();
|
||||
|
||||
void _generate_nic_router_uplink(Xml_generator &xml,
|
||||
char const *label);
|
||||
|
||||
Access_points _access_points { };
|
||||
|
||||
Wifi_connection _wifi_connection = Wifi_connection::disconnected_wifi_connection();
|
||||
|
@ -88,6 +88,7 @@ append config {
|
||||
<policy label_prefix="http_server_2" domain="http_server_2" />
|
||||
<policy label_prefix="udp_server_1" domain="udp_server_1" />
|
||||
<policy label_prefix="udp_server_2" domain="udp_server_2" />
|
||||
<uplink domain="uplink" />
|
||||
|
||||
<domain name="uplink" interface="10.0.2.55/24" gateway="10.0.2.1">
|
||||
<tcp-forward port="80" domain="http_server_1" to="192.168.1.18" />
|
||||
|
@ -158,6 +158,7 @@ proc test_7_config { } {
|
||||
<config>
|
||||
|
||||
<policy label_prefix="lan_2" domain="downlink" />
|
||||
<uplink domain="uplink" />
|
||||
|
||||
<domain name="uplink">
|
||||
<nat domain="downlink" tcp-ports="6" />
|
||||
@ -260,6 +261,8 @@ append config {
|
||||
|
||||
<report bytes="yes" config="yes" interval_sec="60" />
|
||||
|
||||
<uplink domain="uplink"/>
|
||||
|
||||
<domain name="uplink"
|
||||
interface="10.0.2.55/24"
|
||||
gateway="10.0.2.1"
|
||||
|
@ -230,6 +230,8 @@ append config {
|
||||
|
||||
<report/>
|
||||
|
||||
<uplink domain="uplink"/>
|
||||
|
||||
<domain name="uplink"
|
||||
interface="10.0.2.55/24"
|
||||
gateway="10.0.2.1"
|
||||
@ -266,6 +268,8 @@ append config {
|
||||
tcp_idle_timeout_sec="30"
|
||||
tcp_max_segm_lifetime_sec="15">
|
||||
|
||||
<uplink domain="uplink"/>
|
||||
|
||||
<domain name="uplink"
|
||||
interface="10.0.2.55/24"
|
||||
gateway="10.0.2.1"
|
||||
@ -306,6 +310,8 @@ append config {
|
||||
|
||||
<report interval_sec="2" bytes="yes" config="no" />
|
||||
|
||||
<uplink domain="uplink"/>
|
||||
|
||||
<domain name="uplink"
|
||||
interface="10.0.2.55/24"
|
||||
gateway="10.0.2.1"
|
||||
@ -338,6 +344,8 @@ append config {
|
||||
|
||||
<report interval_sec="2" bytes="yes" config="no" />
|
||||
|
||||
<uplink domain="uplink"/>
|
||||
|
||||
<domain name="uplink"
|
||||
interface="10.0.2.55/24"
|
||||
gateway="10.0.2.1"
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
<config verbose_domain_state="yes">
|
||||
<default-policy domain="default" />
|
||||
<uplink domain="uplink" />
|
||||
<domain name="uplink">
|
||||
<nat domain="default"
|
||||
tcp-ports="1000"
|
||||
|
@ -93,6 +93,7 @@ append config {
|
||||
|
||||
<policy label_prefix="flood_links" domain="flood_links"/>
|
||||
<policy label_prefix="ping" domain="flood_links"/>
|
||||
<uplink domain="uplink"/>
|
||||
|
||||
<domain name="uplink" verbose_packets="no">
|
||||
<nat domain="flood_links" udp-ports="16384"
|
||||
|
@ -98,6 +98,7 @@ append config {
|
||||
|
||||
<policy label_prefix="ping_1" domain="ping_1"/>
|
||||
<policy label_prefix="ping_2" domain="ping_2"/>
|
||||
<uplink domain="uplink"/>
|
||||
|
||||
<domain name="uplink">
|
||||
<nat domain="ping_1" icmp-ids="100"/>
|
||||
@ -131,6 +132,7 @@ append config {
|
||||
icmp_idle_timeout_sec="10">
|
||||
|
||||
<policy label_prefix="ping_2" domain="ping_2"/>
|
||||
<uplink domain="uplink"/>
|
||||
|
||||
<domain name="uplink" interface="10.0.4.2/24" gateway="10.0.4.1">
|
||||
<nat domain="ping_2" icmp-ids="100" udp-ports="100"/>
|
||||
|
@ -19,22 +19,35 @@ these domains. This is a brief overview of the features thereby provided:
|
||||
Basics
|
||||
~~~~~~
|
||||
|
||||
The 'nic_router' component provides multiple sessions of the 'NIC' service
|
||||
(downlinks) while requesting one 'NIC' session (the uplink) itself. Through
|
||||
common Genode session routing, the uplink can be connected to any other NIC
|
||||
server. Inside the component, uplink and downlinks are treated the same. Its
|
||||
routing algorithm is ultimately controlled through the configuration. NIC
|
||||
The NIC router can act as server of multiple NIC session clients (downlinks)
|
||||
and at the same time as client of multiple NIC session servers (uplinks).
|
||||
Besides the decision which side initiates the NIC session and provides MAC
|
||||
address respectively link state, uplinks and downlinks are equal to the NIC
|
||||
router.
|
||||
|
||||
The routing algorithm is ultimately controlled through the configuration. NIC
|
||||
sessions are assigned to domains. Each domain represents one subnet and a
|
||||
corresponding routing configuration. Currently, each domain can contain
|
||||
only one NIC session at a time. The assignment of sessions to domains is
|
||||
controlled through the the common Genode session-policy tag:
|
||||
corresponding routing configuration. The assignment of downlink NIC sessions
|
||||
to domains is controlled through the policy tag that is also known from other
|
||||
Genode components:
|
||||
|
||||
! <policy label_prefix="http_server" domain="http_servers" />
|
||||
! <policy label_prefix="imap_server" domain="imap_servers" />
|
||||
! <policy label_prefix="vlan_" domain="vlan" />
|
||||
! <policy label_suffix="_server" domain="servers" />
|
||||
! <policy label="nic_bridge_1" domain="wired_bridge" />
|
||||
! <policy label="nic_bridge_2" domain="wired_bridge" />
|
||||
|
||||
The domain name can be freely choosen but must be unique. There is no need
|
||||
to have a policy for the uplink. It is automatically assigned to the domain
|
||||
named "uplink". For each domain there must be a domain tag:
|
||||
The domain name can be freely choosen but must be unique.
|
||||
The uplink tag instructs the NIC router to create an uplink NIC session that
|
||||
is assigned to the give domain:
|
||||
|
||||
! <uplink domain="wired_bridge" />
|
||||
! <uplink label="wired" domain="wired_bridge" />
|
||||
! <uplink label="wifi" domain="wifi_uplink" />
|
||||
|
||||
The label is the session label that is used when requesting the uplink NIC
|
||||
session. The label attribute is optional. It is perfectly fine to have a
|
||||
domain with uplinks and downlinks assigned to at the same time. For each
|
||||
domain there must be a domain tag:
|
||||
|
||||
! <domain name="uplink" interface="10.0.2.55/24" />
|
||||
! <domain name="http_servers" interface="192.168.1.18/24" />
|
||||
@ -411,27 +424,6 @@ router:
|
||||
! dhcp_request_timeout_sec="6">
|
||||
|
||||
|
||||
The uplink domain
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
The uplink domain is treated like every other domain wherever possible.
|
||||
However, there are still some differences that are visible to the user:
|
||||
|
||||
* 'policy' tags that target the uplink domain have no effect at all
|
||||
* The domain tag of the uplink is the only domain tag in which the
|
||||
'label' attribute has an effect
|
||||
* The uplink domain, as long as existant, has exactly one NIC session in which
|
||||
the NIC router is the session client
|
||||
* When the uplink 'domain' tag appears, the uplink NIC session is requested by
|
||||
the NIC router using the label denoted in the 'label' attribute of the
|
||||
uplink 'domain' tag (default label "")
|
||||
* When the 'label' attribute of the uplink 'domain' tag changes, the NIC
|
||||
router closes the uplink NIC session and requests it again with the new
|
||||
label
|
||||
* When the uplink 'domain' tag disappears, the NIC router closes the uplink
|
||||
NIC session
|
||||
|
||||
|
||||
Configuring reporting functionality
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@ -511,6 +503,7 @@ following configuration:
|
||||
|
||||
! <policy label_prefix="virtnet_a" domain="virtnet_a" />
|
||||
! <policy label_prefix="virtnet_b" domain="virtnet_b" />
|
||||
! <uplink domain="uplink" />
|
||||
!
|
||||
! <domain name="uplink" interface="10.0.2.55/24" gateway="10.0.2.1/24">
|
||||
! <ip dst="192.168.1.0/24" domain="virtnet_a"/>
|
||||
@ -550,6 +543,7 @@ internet. The router would have the following configuration:
|
||||
|
||||
! <policy label_prefix="virtnet_a" domain="virtnet_a" />
|
||||
! <policy label_prefix="virtnet_b" domain="virtnet_b" />
|
||||
! <uplink domain="uplink" />
|
||||
!
|
||||
! <domain name="uplink" interface="10.0.2.55/24" gateway="10.0.2.1/24">
|
||||
! <nat domain="virtnet_a" tcp_ports="1000" udp_ports="1000">
|
||||
@ -588,6 +582,7 @@ following configuration:
|
||||
|
||||
! <policy label_prefix="virtnet_a" domain="virtnet_a" />
|
||||
! <policy label_prefix="virtnet_b" domain="virtnet_b" />
|
||||
! <uplink domain="uplink" />
|
||||
!
|
||||
! <domain name="uplink" interface="10.0.2.55/24" gateway="10.0.2.1">
|
||||
! <tcp-forward port="80" domain="virtnet_a" to="192.168.1.2" />
|
||||
|
@ -101,6 +101,8 @@ Net::Session_component::Session_component(Allocator &alloc,
|
||||
config, interfaces, *_tx.sink(), *_rx.source(),
|
||||
_link_state, _interface_policy }
|
||||
{
|
||||
_interface.attach_to_domain();
|
||||
|
||||
_tx.sigh_ready_to_ack (_interface.sink_ack());
|
||||
_tx.sigh_packet_avail (_interface.sink_submit());
|
||||
_rx.sigh_ack_avail (_interface.source_ack());
|
||||
|
@ -112,6 +112,13 @@
|
||||
</xs:complexType>
|
||||
</xs:element><!-- policy -->
|
||||
|
||||
<xs:element name="uplink">
|
||||
<xs:complexType>
|
||||
<xs:attribute name="label" type="Session_label" />
|
||||
<xs:attribute name="domain" type="Domain_name" />
|
||||
</xs:complexType>
|
||||
</xs:element><!-- uplink -->
|
||||
|
||||
<xs:element name="domain">
|
||||
<xs:complexType>
|
||||
<xs:choice minOccurs="0" maxOccurs="unbounded">
|
||||
|
@ -35,6 +35,17 @@ Configuration::Configuration(Xml_node const node,
|
||||
{ }
|
||||
|
||||
|
||||
void Configuration::_invalid_uplink(Uplink &uplink,
|
||||
char const *reason)
|
||||
{
|
||||
if (_verbose) {
|
||||
log("[", uplink.domain(), "] invalid uplink: ", uplink, " (", reason, ")"); }
|
||||
|
||||
_uplinks.remove(uplink);
|
||||
destroy(_alloc, &uplink);
|
||||
}
|
||||
|
||||
|
||||
void Configuration::_invalid_domain(Domain &domain,
|
||||
char const *reason)
|
||||
{
|
||||
@ -50,7 +61,8 @@ Configuration::Configuration(Env &env,
|
||||
Xml_node const node,
|
||||
Allocator &alloc,
|
||||
Timer::Connection &timer,
|
||||
Configuration &old_config)
|
||||
Configuration &old_config,
|
||||
Interface_list &interfaces)
|
||||
:
|
||||
_alloc(alloc),
|
||||
_verbose (node.attribute_value("verbose", false)),
|
||||
@ -129,11 +141,35 @@ Configuration::Configuration(Env &env,
|
||||
Report(report_node, timer, _domains, _reporter());
|
||||
}
|
||||
catch (Genode::Xml_node::Nonexistent_sub_node) { }
|
||||
|
||||
/* initialize uplinks */
|
||||
_node.for_each_sub_node("uplink", [&] (Xml_node const node) {
|
||||
try {
|
||||
Uplink &uplink = *new (_alloc)
|
||||
Uplink { node, alloc, old_config._uplinks, env, timer,
|
||||
interfaces, *this };
|
||||
|
||||
try { _uplinks.insert(uplink); }
|
||||
catch (Uplink_tree::Name_not_unique exception) {
|
||||
_invalid_uplink(uplink, "label not unique");
|
||||
_invalid_uplink(exception.object, "label not unique");
|
||||
}
|
||||
}
|
||||
catch (Uplink::Invalid) { }
|
||||
});
|
||||
/*
|
||||
* Destroy old uplinks to ensure that uplink interfaces that were not
|
||||
* re-used are not re-attached to the new domains.
|
||||
*/
|
||||
old_config._uplinks.destroy_each(_alloc);
|
||||
}
|
||||
|
||||
|
||||
Configuration::~Configuration()
|
||||
{
|
||||
/* destroy uplinks */
|
||||
_uplinks.destroy_each(_alloc);
|
||||
|
||||
/* destroy reporter */
|
||||
try { destroy(_alloc, &_reporter()); }
|
||||
catch (Pointer<Reporter>::Invalid) { }
|
||||
|
@ -17,6 +17,7 @@
|
||||
/* local includes */
|
||||
#include <domain.h>
|
||||
#include <report.h>
|
||||
#include <uplink.h>
|
||||
|
||||
/* Genode includes */
|
||||
#include <os/duration.h>
|
||||
@ -46,8 +47,12 @@ class Net::Configuration
|
||||
Pointer<Report> _report { };
|
||||
Pointer<Genode::Reporter> _reporter { };
|
||||
Domain_tree _domains { };
|
||||
Uplink_tree _uplinks { };
|
||||
Genode::Xml_node const _node;
|
||||
|
||||
void _invalid_uplink(Uplink &uplink,
|
||||
char const *reason);
|
||||
|
||||
void _invalid_domain(Domain &domain,
|
||||
char const *reason);
|
||||
|
||||
@ -69,7 +74,8 @@ class Net::Configuration
|
||||
Genode::Xml_node const node,
|
||||
Genode::Allocator &alloc,
|
||||
Timer::Connection &timer,
|
||||
Configuration &old_config);
|
||||
Configuration &old_config,
|
||||
Interface_list &interfaces);
|
||||
|
||||
~Configuration();
|
||||
|
||||
|
@ -30,6 +30,7 @@ using Genode::uint32_t;
|
||||
using Genode::log;
|
||||
using Genode::error;
|
||||
using Genode::warning;
|
||||
using Genode::Exception;
|
||||
using Genode::construct_at;
|
||||
using Genode::Quota_guard;
|
||||
using Genode::Ram_quota;
|
||||
@ -256,15 +257,23 @@ void Interface::_detach_from_domain_raw()
|
||||
}
|
||||
|
||||
|
||||
void Interface::_attach_to_domain(Domain_name const &domain_name)
|
||||
void Interface::attach_to_domain()
|
||||
{
|
||||
_attach_to_domain_raw(_config().domains().find_by_name(domain_name));
|
||||
attach_to_domain_finish();
|
||||
try {
|
||||
_attach_to_domain_raw(_config().domains().find_by_name(
|
||||
_policy.determine_domain_name()));
|
||||
|
||||
attach_to_domain_finish();
|
||||
}
|
||||
catch (Domain_tree::No_match) { }
|
||||
}
|
||||
|
||||
|
||||
void Interface::attach_to_domain_finish()
|
||||
{
|
||||
if (!link_state()) {
|
||||
return; }
|
||||
|
||||
/* if domain has yet no IP config, participate in requesting one */
|
||||
Domain &domain = _domain();
|
||||
Ipv4_config const &ip_config = domain.ip_config();
|
||||
@ -764,6 +773,27 @@ bool Interface::link_state() const
|
||||
}
|
||||
|
||||
|
||||
void Interface::handle_link_state()
|
||||
{
|
||||
struct Keep_ip_config : Exception { };
|
||||
try {
|
||||
attach_to_domain_finish();
|
||||
|
||||
/* if the wholde domain became down, discard IP config */
|
||||
Domain &domain_ = domain();
|
||||
if (!link_state() && domain_.ip_config().valid) {
|
||||
domain_.interfaces().for_each([&] (Interface &interface) {
|
||||
if (interface.link_state()) {
|
||||
throw Keep_ip_config(); }
|
||||
});
|
||||
domain_.discard_ip_config();
|
||||
}
|
||||
}
|
||||
catch (Domain::Ip_config_static) { }
|
||||
catch (Keep_ip_config) { }
|
||||
}
|
||||
|
||||
|
||||
void Interface::_handle_icmp_query(Ethernet_frame ð,
|
||||
Size_guard &size_guard,
|
||||
Ipv4_packet &ip,
|
||||
@ -1383,8 +1413,6 @@ Interface::Interface(Genode::Entrypoint &ep,
|
||||
_interfaces { interfaces }
|
||||
{
|
||||
_interfaces.insert(this);
|
||||
try { _attach_to_domain(_policy.determine_domain_name()); }
|
||||
catch (Domain_tree::No_match) { }
|
||||
}
|
||||
|
||||
|
||||
|
@ -274,8 +274,6 @@ class Net::Interface : private Interface_list::Element
|
||||
|
||||
void _detach_from_domain();
|
||||
|
||||
void _attach_to_domain(Domain_name const &domain_name);
|
||||
|
||||
void _attach_to_domain_raw(Domain &domain);
|
||||
|
||||
void _apply_foreign_arp();
|
||||
@ -375,6 +373,8 @@ class Net::Interface : private Interface_list::Element
|
||||
|
||||
void handle_config_3();
|
||||
|
||||
void attach_to_domain();
|
||||
|
||||
void detach_from_ip_config();
|
||||
|
||||
void attach_to_ip_config(Domain &domain,
|
||||
@ -388,6 +388,8 @@ class Net::Interface : private Interface_list::Element
|
||||
|
||||
bool link_state() const;
|
||||
|
||||
void handle_link_state();
|
||||
|
||||
|
||||
/***************
|
||||
** Accessors **
|
||||
|
@ -38,22 +38,12 @@ class Net::Main
|
||||
Timer::Connection _timer { _env };
|
||||
Genode::Heap _heap { &_env.ram(), &_env.rm() };
|
||||
Genode::Attached_rom_dataspace _config_rom { _env, "config" };
|
||||
Reference<Configuration> _config { _init_config() };
|
||||
Reference<Configuration> _config { *new (_heap) Configuration { _config_rom.xml(), _heap } };
|
||||
Signal_handler<Main> _config_handler { _env.ep(), *this, &Main::_handle_config };
|
||||
Pointer<Uplink> _uplink { };
|
||||
Root _root { _env.ep(), _timer, _heap, _config(), _env.ram(), _interfaces, _env.rm()};
|
||||
|
||||
void _handle_config();
|
||||
|
||||
Configuration &_init_config();
|
||||
|
||||
void _deinit_uplink(Configuration &config);
|
||||
|
||||
void _init_uplink(Configuration &config,
|
||||
Session_label const &label);
|
||||
|
||||
void _uplink_handle_config(Configuration &config);
|
||||
|
||||
template <typename FUNC>
|
||||
void _for_each_interface(FUNC && functor)
|
||||
{
|
||||
@ -73,80 +63,22 @@ class Net::Main
|
||||
};
|
||||
|
||||
|
||||
Configuration &Net::Main::_init_config()
|
||||
{
|
||||
Configuration &dummy_config = *new (_heap)
|
||||
Configuration(_config_rom.xml(), _heap);
|
||||
|
||||
Configuration &config = *new (_heap)
|
||||
Configuration(_env, _config_rom.xml(), _heap, _timer, dummy_config);
|
||||
|
||||
destroy(_heap, &dummy_config);
|
||||
return config;
|
||||
}
|
||||
|
||||
|
||||
Net::Main::Main(Env &env) : _env(env)
|
||||
{
|
||||
_uplink_handle_config(_config());
|
||||
_config_rom.sigh(_config_handler);
|
||||
_handle_config();
|
||||
env.parent().announce(env.ep().manage(_root));
|
||||
}
|
||||
|
||||
|
||||
void Net::Main::_init_uplink(Configuration &config,
|
||||
Session_label const &label)
|
||||
{
|
||||
if (config.verbose()) {
|
||||
log("[uplink] request NIC session \"", label, "\""); }
|
||||
|
||||
Uplink &uplink = *new (_heap) Uplink(_env, _timer, _heap, _interfaces,
|
||||
config, label);
|
||||
_uplink = Pointer<Uplink>(uplink);
|
||||
}
|
||||
|
||||
|
||||
void Net::Main::_deinit_uplink(Configuration &config)
|
||||
{
|
||||
try {
|
||||
Uplink &uplink = _uplink();
|
||||
if (config.verbose()) {
|
||||
log("[uplink] close NIC session \"", uplink.label(), "\""); }
|
||||
|
||||
destroy(_heap, &uplink);
|
||||
_uplink = Pointer<Uplink>();
|
||||
}
|
||||
catch (Pointer<Uplink>::Invalid) { }
|
||||
}
|
||||
|
||||
|
||||
void Net::Main::_uplink_handle_config(Configuration &config)
|
||||
{
|
||||
try {
|
||||
Session_label const &label =
|
||||
config.domains().find_by_name("uplink").label();
|
||||
|
||||
try {
|
||||
if (label == _uplink().label()) {
|
||||
return;
|
||||
}
|
||||
_deinit_uplink(config);
|
||||
_init_uplink(config, label);
|
||||
}
|
||||
catch (Pointer<Uplink>::Invalid) { _init_uplink(config, label); }
|
||||
}
|
||||
catch (Domain_tree::No_match) { _deinit_uplink(config); }
|
||||
}
|
||||
|
||||
|
||||
void Net::Main::_handle_config()
|
||||
{
|
||||
_config_rom.update();
|
||||
Configuration &old_config = _config();
|
||||
Configuration &new_config = *new (_heap)
|
||||
Configuration(_env, _config_rom.xml(), _heap, _timer, old_config);
|
||||
Configuration(_env, _config_rom.xml(), _heap, _timer, old_config,
|
||||
_interfaces);
|
||||
|
||||
_uplink_handle_config(new_config);
|
||||
_root.handle_config(new_config);
|
||||
_for_each_interface([&] (Interface &intf) { intf.handle_config_1(new_config); });
|
||||
_for_each_interface([&] (Interface &intf) { intf.handle_config_2(); });
|
||||
@ -157,12 +89,4 @@ void Net::Main::_handle_config()
|
||||
}
|
||||
|
||||
|
||||
void Component::construct(Env &env)
|
||||
{
|
||||
try { static Net::Main main(env); }
|
||||
|
||||
catch (Net::Domain_tree::No_match) {
|
||||
error("failed to find configuration for domain 'uplink'");
|
||||
env.parent().exit(-1);
|
||||
}
|
||||
}
|
||||
void Component::construct(Env &env) { static Net::Main main(env); }
|
||||
|
@ -13,7 +13,6 @@
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/env.h>
|
||||
#include <net/ethernet.h>
|
||||
|
||||
/* local includes */
|
||||
#include <uplink.h>
|
||||
@ -23,20 +22,111 @@ using namespace Net;
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
Net::Uplink::Uplink(Env &env,
|
||||
Timer::Connection &timer,
|
||||
Genode::Allocator &alloc,
|
||||
Interface_list &interfaces,
|
||||
Configuration &config,
|
||||
Session_label const &label)
|
||||
/*****************
|
||||
** Uplink_base **
|
||||
*****************/
|
||||
|
||||
Net::Uplink_base::Uplink_base(Xml_node const &node)
|
||||
:
|
||||
_label { node.attribute_value("label", Session_label::String()) },
|
||||
_domain { node.attribute_value("domain", Domain_name()) }
|
||||
{ }
|
||||
|
||||
|
||||
/************
|
||||
** Uplink **
|
||||
************/
|
||||
|
||||
void Uplink::_invalid(char const *reason) const
|
||||
{
|
||||
if (_config.verbose()) {
|
||||
log("[", domain(), "] invalid uplink: ", *this, " (", reason, ")"); }
|
||||
|
||||
throw Invalid();
|
||||
}
|
||||
|
||||
|
||||
Net::Uplink::Uplink(Xml_node const &node,
|
||||
Allocator &alloc,
|
||||
Uplink_tree &old_uplinks,
|
||||
Env &env,
|
||||
Timer::Connection &timer,
|
||||
Interface_list &interfaces,
|
||||
Configuration &config)
|
||||
:
|
||||
Uplink_base { node },
|
||||
Avl_string_base { label().string() },
|
||||
_alloc { alloc },
|
||||
_config { config }
|
||||
{
|
||||
/* if an interface with this label already exists, reuse it */
|
||||
try {
|
||||
Uplink &old_uplink = old_uplinks.find_by_name(label());
|
||||
Uplink_interface &interface = old_uplink._interface();
|
||||
old_uplink._interface = Pointer<Uplink_interface>();
|
||||
interface.domain_name(domain());
|
||||
_interface = interface;
|
||||
}
|
||||
/* if not, create a new one */
|
||||
catch (Uplink_tree::No_match) {
|
||||
if (config.verbose()) {
|
||||
log("[", domain(), "] request uplink NIC session: ", *this); }
|
||||
|
||||
try {
|
||||
_interface = *new (_alloc)
|
||||
Uplink_interface { env, timer, alloc, interfaces, config,
|
||||
domain(), label() };
|
||||
}
|
||||
catch (Insufficient_ram_quota) { _invalid("NIC session RAM quota"); }
|
||||
catch (Insufficient_cap_quota) { _invalid("NIC session CAP quota"); }
|
||||
catch (Service_denied) { _invalid("NIC session denied"); }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Net::Uplink::~Uplink()
|
||||
{
|
||||
/* if the interface was yet not reused by another uplink, destroy it */
|
||||
try {
|
||||
Uplink_interface &interface = _interface();
|
||||
if (_config.verbose()) {
|
||||
log("[", domain(), "] close uplink NIC session: ", *this); }
|
||||
|
||||
destroy(_alloc, &interface);
|
||||
}
|
||||
catch (Pointer<Uplink_interface>::Invalid) { }
|
||||
}
|
||||
|
||||
|
||||
void Net::Uplink::print(Output &output) const
|
||||
{
|
||||
if (label() == Session_label()) {
|
||||
Genode::print(output, "<unlabeled>"); }
|
||||
else {
|
||||
Genode::print(output, label()); }
|
||||
}
|
||||
|
||||
|
||||
/**********************
|
||||
** Uplink_interface **
|
||||
**********************/
|
||||
|
||||
Net::Uplink_interface::Uplink_interface(Env &env,
|
||||
Timer::Connection &timer,
|
||||
Genode::Allocator &alloc,
|
||||
Interface_list &interfaces,
|
||||
Configuration &config,
|
||||
Domain_name const &domain_name,
|
||||
Session_label const &label)
|
||||
:
|
||||
Uplink_interface_base { domain_name },
|
||||
Nic::Packet_allocator { &alloc },
|
||||
Nic::Connection { env, this, BUF_SIZE, BUF_SIZE, label.string() },
|
||||
_label { label },
|
||||
_link_state_handler { env.ep(), *this, &Uplink::_handle_link_state },
|
||||
_link_state_handler { env.ep(), *this,
|
||||
&Uplink_interface::_handle_link_state },
|
||||
_interface { env.ep(), timer, mac_address(), alloc,
|
||||
Mac_address(), config, interfaces, *rx(), *tx(),
|
||||
_link_state, _intf_policy }
|
||||
_link_state, *this }
|
||||
{
|
||||
/* install packet stream signal handlers */
|
||||
rx_channel()->sigh_ready_to_ack (_interface.sink_ack());
|
||||
@ -50,9 +140,8 @@ Net::Uplink::Uplink(Env &env,
|
||||
}
|
||||
|
||||
|
||||
void Net::Uplink::_handle_link_state()
|
||||
void Net::Uplink_interface::_handle_link_state()
|
||||
{
|
||||
_link_state = link_state();
|
||||
try { _interface.domain().discard_ip_config(); }
|
||||
catch (Domain::Ip_config_static) { }
|
||||
_interface.handle_link_state();
|
||||
}
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <nic/packet_allocator.h>
|
||||
|
||||
/* local includes */
|
||||
#include <avl_string_tree.h>
|
||||
#include <interface.h>
|
||||
#include <ipv4_address_prefix.h>
|
||||
|
||||
@ -27,32 +28,110 @@ namespace Net {
|
||||
using Domain_name = Genode::String<160>;
|
||||
class Uplink_base;
|
||||
class Uplink;
|
||||
class Uplink_tree;
|
||||
class Uplink_interface_base;
|
||||
class Uplink_interface;
|
||||
}
|
||||
|
||||
|
||||
class Net::Uplink_tree
|
||||
:
|
||||
public Avl_string_tree<Uplink, Genode::Session_label>
|
||||
{ };
|
||||
|
||||
|
||||
class Net::Uplink_base
|
||||
{
|
||||
protected:
|
||||
private:
|
||||
|
||||
struct Interface_policy : Net::Interface_policy
|
||||
{
|
||||
/***************************
|
||||
** Net::Interface_policy **
|
||||
***************************/
|
||||
Genode::Session_label const _label;
|
||||
Domain_name const _domain;
|
||||
|
||||
Domain_name determine_domain_name() const override { return Genode::Cstring("uplink"); };
|
||||
void handle_config(Configuration const &) override { }
|
||||
};
|
||||
public:
|
||||
|
||||
Interface_policy _intf_policy { };
|
||||
Uplink_base(Genode::Xml_node const &node);
|
||||
|
||||
virtual ~Uplink_base() { }
|
||||
|
||||
|
||||
/**************
|
||||
** Acessors **
|
||||
**************/
|
||||
|
||||
Genode::Session_label const &label() const { return _label; }
|
||||
Domain_name const &domain() const { return _domain; }
|
||||
};
|
||||
|
||||
|
||||
class Net::Uplink : public Uplink_base,
|
||||
public Nic::Packet_allocator,
|
||||
public Nic::Connection
|
||||
struct Net::Uplink : public Uplink_base,
|
||||
private Genode::Avl_string_base
|
||||
{
|
||||
friend class Avl_string_tree<Uplink, Genode::Session_label>;
|
||||
friend class Genode::List<Uplink>;
|
||||
|
||||
private:
|
||||
|
||||
Genode::Allocator &_alloc;
|
||||
Configuration const &_config;
|
||||
Pointer<Uplink_interface> _interface { };
|
||||
|
||||
void _invalid(char const *reason) const;
|
||||
|
||||
public:
|
||||
|
||||
struct Invalid : Genode::Exception { };
|
||||
|
||||
Uplink(Genode::Xml_node const &node,
|
||||
Genode::Allocator &alloc,
|
||||
Uplink_tree &old_uplinks,
|
||||
Genode::Env &env,
|
||||
Timer::Connection &timer,
|
||||
Interface_list &interfaces,
|
||||
Configuration &config);
|
||||
|
||||
~Uplink();
|
||||
|
||||
|
||||
/*********
|
||||
** log **
|
||||
*********/
|
||||
|
||||
void print(Genode::Output &output) const;
|
||||
};
|
||||
|
||||
|
||||
class Net::Uplink_interface_base : public Interface_policy
|
||||
{
|
||||
private:
|
||||
|
||||
Const_reference<Domain_name> _domain_name;
|
||||
|
||||
|
||||
/***************************
|
||||
** Net::Interface_policy **
|
||||
***************************/
|
||||
|
||||
Domain_name determine_domain_name() const override { return _domain_name(); };
|
||||
void handle_config(Configuration const &) override { }
|
||||
|
||||
public:
|
||||
|
||||
Uplink_interface_base(Domain_name const &domain_name) : _domain_name(domain_name) { }
|
||||
|
||||
virtual ~Uplink_interface_base() { }
|
||||
|
||||
|
||||
/***************
|
||||
** Accessors **
|
||||
***************/
|
||||
|
||||
void domain_name(Domain_name const &v) { _domain_name = v; }
|
||||
};
|
||||
|
||||
|
||||
class Net::Uplink_interface : public Uplink_interface_base,
|
||||
public Nic::Packet_allocator,
|
||||
public Nic::Connection
|
||||
{
|
||||
private:
|
||||
|
||||
@ -61,10 +140,9 @@ class Net::Uplink : public Uplink_base,
|
||||
BUF_SIZE = Nic::Session::QUEUE_SIZE * PKT_SIZE,
|
||||
};
|
||||
|
||||
Genode::Session_label const &_label;
|
||||
bool _link_state { false };
|
||||
Genode::Signal_handler<Uplink> _link_state_handler;
|
||||
Net::Interface _interface;
|
||||
bool _link_state { false };
|
||||
Genode::Signal_handler<Uplink_interface> _link_state_handler;
|
||||
Net::Interface _interface;
|
||||
|
||||
Ipv4_address_prefix _read_interface();
|
||||
|
||||
@ -72,20 +150,20 @@ class Net::Uplink : public Uplink_base,
|
||||
|
||||
public:
|
||||
|
||||
Uplink(Genode::Env &env,
|
||||
Timer::Connection &timer,
|
||||
Genode::Allocator &alloc,
|
||||
Interface_list &interfaces,
|
||||
Configuration &config,
|
||||
Genode::Session_label const &label);
|
||||
Uplink_interface(Genode::Env &env,
|
||||
Timer::Connection &timer,
|
||||
Genode::Allocator &alloc,
|
||||
Interface_list &interfaces,
|
||||
Configuration &config,
|
||||
Domain_name const &domain_name,
|
||||
Genode::Session_label const &label);
|
||||
|
||||
|
||||
/***************
|
||||
** Accessors **
|
||||
***************/
|
||||
|
||||
Mac_address const &router_mac() const { return _interface.router_mac(); }
|
||||
Genode::Session_label const &label() const { return _label; }
|
||||
Mac_address const &router_mac() const { return _interface.router_mac(); }
|
||||
};
|
||||
|
||||
#endif /* _UPLINK_H_ */
|
||||
|
@ -23,6 +23,7 @@
|
||||
<provides> <service name="Nic"/> </provides>
|
||||
<config verbose_domain_state="yes">
|
||||
<default-policy domain="default" />
|
||||
<uplink domain="uplink" />
|
||||
<domain name="uplink">
|
||||
<nat domain="default" tcp-ports="1000" udp-ports="1000"/>
|
||||
</domain>
|
||||
|
@ -149,6 +149,7 @@ append_if $use_nic_router config {
|
||||
<config verbose_domain_state="yes">
|
||||
|
||||
<policy label_prefix="netserver_genode" domain="server"/>
|
||||
<uplink domain="uplink"/>
|
||||
|
||||
<domain name="uplink"}
|
||||
append_if [expr $use_nic_router && [have_spec linux]] config "
|
||||
|
@ -64,8 +64,10 @@ append config {
|
||||
<resource name="RAM" quantum="10M"/>
|
||||
<provides><service name="Nic"/></provides>
|
||||
<config verbose="no">
|
||||
<policy label_prefix="vfs" domain="default" />
|
||||
<policy label_prefix="stubby" domain="dns"/>
|
||||
<policy label_prefix="vfs" domain="default" />
|
||||
<policy label_prefix="stubby" domain="dns" />
|
||||
<uplink domain="uplink" />
|
||||
|
||||
<domain name="uplink">
|
||||
<nat domain="dns" tcp-ports="64" udp-ports="64"/>
|
||||
</domain>
|
||||
|
@ -159,6 +159,7 @@ append config {
|
||||
dhcp_discover_timeout_sec="1">
|
||||
|
||||
<policy label_prefix="vbox" domain="downlink"/>
|
||||
<uplink domain="uplink" />
|
||||
|
||||
<domain name="uplink" label="wifi">
|
||||
<nat domain="downlink"
|
||||
|
Loading…
Reference in New Issue
Block a user