From 1d2649b49a202bdca82c83def81a9e7b64caaa4d Mon Sep 17 00:00:00 2001 From: Martin Stein Date: Mon, 7 Dec 2020 16:46:15 +0100 Subject: [PATCH] nic_router: act as "Uplink" server Let the NIC router provide an Uplink service besides the Nic service that it already provided. Requests for an Uplink session towards the NIC router are assigned to Domains using the same configuration tags that are used in order to assign Nic session requests. The MAC addresses of Uplink session components are _NOT_ considered during the allocation of MAC addresses for NIC session components at the same Domain. The task of avoiding MAC address clashes between Uplink session components and Nic session components is therefore left to the integrator. Apart from that, Uplink session components are treated by the NIC router like any other interface. Ref #3961 --- repos/dde_linux/run/nic_router_uplinks.run | 5 +- .../gems/recipes/src/sculpt_manager/used_apis | 1 + .../app/sculpt_manager/runtime/nic_router.cc | 13 +- .../pkg/test-libc_connect_lwip/runtime | 5 +- .../pkg/test-libc_connect_lxip/runtime | 5 +- .../test-libc_connect_vfs_server_lwip/runtime | 5 +- .../test-libc_connect_vfs_server_lxip/runtime | 5 +- repos/libports/run/nic_router.run | 10 +- repos/libports/run/nic_router_dyn_config.run | 5 +- repos/os/recipes/src/nic_router/used_apis | 1 + repos/os/run/nic_dump.run | 10 +- repos/os/run/nic_router_dhcp.inc | 10 +- repos/os/run/nic_router_disable_arp.run | 5 +- repos/os/run/nic_router_flood.run | 5 +- repos/os/run/nic_stress.inc | 10 +- repos/os/run/ping_nic_router.run | 10 +- .../server/nic_router/communication_buffer.cc | 26 ++ .../server/nic_router/communication_buffer.h | 46 ++ repos/os/src/server/nic_router/component.h | 397 ------------------ repos/os/src/server/nic_router/main.cc | 26 +- .../{component.cc => nic_session_root.cc} | 147 +++---- .../src/server/nic_router/nic_session_root.h | 201 +++++++++ repos/os/src/server/nic_router/session_env.h | 196 +++++++++ repos/os/src/server/nic_router/target.mk | 35 +- .../server/nic_router/uplink_session_root.cc | 256 +++++++++++ .../server/nic_router/uplink_session_root.h | 153 +++++++ repos/ports/run/netperf.inc | 5 +- 27 files changed, 1079 insertions(+), 514 deletions(-) create mode 100644 repos/os/src/server/nic_router/communication_buffer.cc create mode 100644 repos/os/src/server/nic_router/communication_buffer.h delete mode 100644 repos/os/src/server/nic_router/component.h rename repos/os/src/server/nic_router/{component.cc => nic_session_root.cc} (67%) create mode 100644 repos/os/src/server/nic_router/nic_session_root.h create mode 100644 repos/os/src/server/nic_router/session_env.h create mode 100644 repos/os/src/server/nic_router/uplink_session_root.cc create mode 100644 repos/os/src/server/nic_router/uplink_session_root.h diff --git a/repos/dde_linux/run/nic_router_uplinks.run b/repos/dde_linux/run/nic_router_uplinks.run index 5ef4bd97d5..95c7f5c071 100644 --- a/repos/dde_linux/run/nic_router_uplinks.run +++ b/repos/dde_linux/run/nic_router_uplinks.run @@ -317,7 +317,10 @@ append config { - + + + + diff --git a/repos/gems/recipes/src/sculpt_manager/used_apis b/repos/gems/recipes/src/sculpt_manager/used_apis index 685de8b9d4..c7b53ffe6d 100644 --- a/repos/gems/recipes/src/sculpt_manager/used_apis +++ b/repos/gems/recipes/src/sculpt_manager/used_apis @@ -3,6 +3,7 @@ os report_session file_system_session nic_session +uplink_session timer_session block_session usb_session diff --git a/repos/gems/src/app/sculpt_manager/runtime/nic_router.cc b/repos/gems/src/app/sculpt_manager/runtime/nic_router.cc index 3677b1e9c4..cec8f54fed 100644 --- a/repos/gems/src/app/sculpt_manager/runtime/nic_router.cc +++ b/repos/gems/src/app/sculpt_manager/runtime/nic_router.cc @@ -11,6 +11,10 @@ * under the terms of the GNU Affero General Public License version 3. */ +/* Genode includes */ +#include + +/* local includes */ #include @@ -22,7 +26,14 @@ void Sculpt::gen_nic_router_start_content(Xml_generator &xml, gen_common_start_content(xml, "nic_router", Cap_quota{300}, Ram_quota{10*1024*1024}); - gen_provides(xml); + xml.node("provides", [&] () { + xml.node("service", [&] () { + xml.attribute("name", Nic::Session::service_name()); + }); + xml.node("service", [&] () { + xml.attribute("name", Uplink::Session::service_name()); + }); + }); xml.node("route", [&] () { diff --git a/repos/libports/recipes/pkg/test-libc_connect_lwip/runtime b/repos/libports/recipes/pkg/test-libc_connect_lwip/runtime index b73c4e5e8d..baca0f5ba8 100644 --- a/repos/libports/recipes/pkg/test-libc_connect_lwip/runtime +++ b/repos/libports/recipes/pkg/test-libc_connect_lwip/runtime @@ -39,7 +39,10 @@ - + + + + diff --git a/repos/libports/recipes/pkg/test-libc_connect_lxip/runtime b/repos/libports/recipes/pkg/test-libc_connect_lxip/runtime index 42b76f9178..324fcda299 100644 --- a/repos/libports/recipes/pkg/test-libc_connect_lxip/runtime +++ b/repos/libports/recipes/pkg/test-libc_connect_lxip/runtime @@ -40,7 +40,10 @@ - + + + + diff --git a/repos/libports/recipes/pkg/test-libc_connect_vfs_server_lwip/runtime b/repos/libports/recipes/pkg/test-libc_connect_vfs_server_lwip/runtime index 9ff91065f3..f362befcf6 100644 --- a/repos/libports/recipes/pkg/test-libc_connect_vfs_server_lwip/runtime +++ b/repos/libports/recipes/pkg/test-libc_connect_vfs_server_lwip/runtime @@ -40,7 +40,10 @@ - + + + + diff --git a/repos/libports/recipes/pkg/test-libc_connect_vfs_server_lxip/runtime b/repos/libports/recipes/pkg/test-libc_connect_vfs_server_lxip/runtime index 204df8f627..de72666540 100644 --- a/repos/libports/recipes/pkg/test-libc_connect_vfs_server_lxip/runtime +++ b/repos/libports/recipes/pkg/test-libc_connect_vfs_server_lxip/runtime @@ -41,7 +41,10 @@ - + + + + diff --git a/repos/libports/run/nic_router.run b/repos/libports/run/nic_router.run index 1c64259c4c..11a83d2962 100644 --- a/repos/libports/run/nic_router.run +++ b/repos/libports/run/nic_router.run @@ -188,7 +188,10 @@ proc test_7_config { } { - + + + + @@ -286,7 +289,10 @@ append config { - + + + + - + + + + diff --git a/repos/os/recipes/src/nic_router/used_apis b/repos/os/recipes/src/nic_router/used_apis index 64e9a07739..1988ee0b01 100644 --- a/repos/os/recipes/src/nic_router/used_apis +++ b/repos/os/recipes/src/nic_router/used_apis @@ -1,5 +1,6 @@ base os nic_session +uplink_session timer_session report_session diff --git a/repos/os/run/nic_dump.run b/repos/os/run/nic_dump.run index 25199aeb03..5b15cbfba4 100644 --- a/repos/os/run/nic_dump.run +++ b/repos/os/run/nic_dump.run @@ -81,7 +81,10 @@ append config { - + + + + - + + + + diff --git a/repos/os/run/nic_router_dhcp.inc b/repos/os/run/nic_router_dhcp.inc index e24786dbac..7d62956a12 100644 --- a/repos/os/run/nic_router_dhcp.inc +++ b/repos/os/run/nic_router_dhcp.inc @@ -142,7 +142,10 @@ append config { - + + + + @@ -154,7 +157,10 @@ append config { - } + + + + } append_if [expr ![nic_router_2_managed]] config { diff --git a/repos/os/run/nic_router_disable_arp.run b/repos/os/run/nic_router_disable_arp.run index e71365752e..b6df26d6a1 100644 --- a/repos/os/run/nic_router_disable_arp.run +++ b/repos/os/run/nic_router_disable_arp.run @@ -51,7 +51,10 @@ append config { - + + + + diff --git a/repos/os/run/nic_router_flood.run b/repos/os/run/nic_router_flood.run index 21d921802c..0cfb8f459b 100644 --- a/repos/os/run/nic_router_flood.run +++ b/repos/os/run/nic_router_flood.run @@ -142,7 +142,10 @@ install_config { - + + + + diff --git a/repos/os/run/nic_stress.inc b/repos/os/run/nic_stress.inc index 5ab1c0eda5..50833753bc 100644 --- a/repos/os/run/nic_stress.inc +++ b/repos/os/run/nic_stress.inc @@ -83,7 +83,10 @@ append_if [string equal $type "nic_router"] config { - + + + + @@ -97,7 +100,10 @@ append_if [string equal $type "nic_bridge"] config { - + + + + diff --git a/repos/os/run/ping_nic_router.run b/repos/os/run/ping_nic_router.run index f231909473..d8eb2ecdb5 100644 --- a/repos/os/run/ping_nic_router.run +++ b/repos/os/run/ping_nic_router.run @@ -61,7 +61,10 @@ append config { - + + + + - + + + + diff --git a/repos/os/src/server/nic_router/communication_buffer.cc b/repos/os/src/server/nic_router/communication_buffer.cc new file mode 100644 index 0000000000..ac231ed9ab --- /dev/null +++ b/repos/os/src/server/nic_router/communication_buffer.cc @@ -0,0 +1,26 @@ +/* + * \brief Buffer for network communication + * \author Martin Stein + * \date 2020-11-30 + */ + +/* + * Copyright (C) 2020 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +/* local includes */ +#include + +using namespace Net; +using namespace Genode; + + +Communication_buffer::Communication_buffer(Ram_allocator &ram_alloc, + size_t const size) +: + _ram_alloc { ram_alloc }, + _ram_ds { ram_alloc.alloc(size) } +{ } diff --git a/repos/os/src/server/nic_router/communication_buffer.h b/repos/os/src/server/nic_router/communication_buffer.h new file mode 100644 index 0000000000..91be70a1ff --- /dev/null +++ b/repos/os/src/server/nic_router/communication_buffer.h @@ -0,0 +1,46 @@ +/* + * \brief Buffer for network communication + * \author Martin Stein + * \date 2020-11-30 + */ + +/* + * Copyright (C) 2020 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _COMMUNICATION_BUFFER_H_ +#define _COMMUNICATION_BUFFER_H_ + +/* Genode includes */ +#include +#include + +namespace Net { class Communication_buffer; } + + +class Net::Communication_buffer +{ + private: + + Genode::Ram_allocator &_ram_alloc; + Genode::Ram_dataspace_capability _ram_ds; + + public: + + Communication_buffer(Genode::Ram_allocator &ram_alloc, + Genode::size_t const size); + + ~Communication_buffer() { _ram_alloc.free(_ram_ds); } + + + /*************** + ** Accessors ** + ***************/ + + Genode::Dataspace_capability ds() const { return _ram_ds; } +}; + +#endif /* _COMMUNICATION_BUFFER_H_ */ diff --git a/repos/os/src/server/nic_router/component.h b/repos/os/src/server/nic_router/component.h deleted file mode 100644 index 812dfca53c..0000000000 --- a/repos/os/src/server/nic_router/component.h +++ /dev/null @@ -1,397 +0,0 @@ -/* - * \brief Downlink interface in form of a NIC session component - * \author Martin Stein - * \date 2016-08-23 - */ - -/* - * Copyright (C) 2016-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _COMPONENT_H_ -#define _COMPONENT_H_ - -/* Genode includes */ -#include -#include -#include -#include - -/* local includes */ -#include -#include -#include -#include - -namespace Genode { class Session_env; } - -namespace Net { - - class Communication_buffer; - class Session_component_base; - class Session_component; - class Root; -} - - -class Genode::Session_env : public Ram_allocator, - public Region_map -{ - private: - - Env &_env; - Net::Quota &_shared_quota; - Ram_quota_guard _ram_guard; - Cap_quota_guard _cap_guard; - - template - void _consume(size_t own_ram, - size_t max_shared_ram, - size_t own_cap, - size_t max_shared_cap, - FUNC && functor) - { - size_t const max_ram_consumpt { own_ram + max_shared_ram }; - size_t const max_cap_consumpt { own_cap + max_shared_cap }; - size_t ram_consumpt { _env.pd().used_ram().value }; - size_t cap_consumpt { _env.pd().used_caps().value }; - { - Ram_quota_guard::Reservation ram_reserv { _ram_guard, Ram_quota { max_ram_consumpt } }; - Cap_quota_guard::Reservation cap_reserv { _cap_guard, Cap_quota { max_cap_consumpt } }; - - functor(); - - ram_reserv.acknowledge(); - cap_reserv.acknowledge(); - } - ram_consumpt = _env.pd().used_ram().value - ram_consumpt; - cap_consumpt = _env.pd().used_caps().value - cap_consumpt; - - if (ram_consumpt > max_ram_consumpt) { - error("Session_env: more RAM quota consumed than expected"); } - if (cap_consumpt > max_cap_consumpt) { - error("Session_env: more CAP quota consumed than expected"); } - if (ram_consumpt < own_ram) { - error("Session_env: less RAM quota consumed than expected"); } - if (cap_consumpt < own_cap) { - error("Session_env: less CAP quota consumed than expected"); } - - _shared_quota.ram += ram_consumpt - own_ram; - _shared_quota.cap += cap_consumpt - own_cap; - - _ram_guard.replenish( Ram_quota { max_shared_ram } ); - _cap_guard.replenish( Cap_quota { max_shared_cap } ); - } - - template - void _replenish(size_t accounted_ram, - size_t accounted_cap, - FUNC && functor) - { - size_t ram_replenish { _env.pd().used_ram().value }; - size_t cap_replenish { _env.pd().used_caps().value }; - functor(); - ram_replenish = ram_replenish - _env.pd().used_ram().value; - cap_replenish = cap_replenish - _env.pd().used_caps().value; - - if (ram_replenish < accounted_ram) { - error("Session_env: less RAM quota replenished than expected"); } - if (cap_replenish < accounted_cap) { - error("Session_env: less CAP quota replenished than expected"); } - - _shared_quota.ram -= ram_replenish - accounted_ram; - _shared_quota.cap -= cap_replenish - accounted_cap; - - _ram_guard.replenish( Ram_quota { accounted_ram } ); - _cap_guard.replenish( Cap_quota { accounted_cap } ); - - } - - public: - - Session_env(Env &env, - Net::Quota &shared_quota, - Ram_quota const &ram_quota, - Cap_quota const &cap_quota) - : - _env { env }, - _shared_quota { shared_quota }, - _ram_guard { ram_quota }, - _cap_guard { cap_quota } - { } - - Entrypoint &ep() { return _env.ep(); } - - - /******************* - ** Ram_allocator ** - *******************/ - - Ram_dataspace_capability alloc(size_t size, Cache_attribute cached) override - { - enum { MAX_SHARED_CAP = 1 }; - enum { MAX_SHARED_RAM = 4096 }; - enum { DS_SIZE_GRANULARITY_LOG2 = 12 }; - - size_t const ds_size = align_addr(size, DS_SIZE_GRANULARITY_LOG2); - Ram_dataspace_capability ds; - _consume(ds_size, MAX_SHARED_RAM, 1, MAX_SHARED_CAP, [&] () { - ds = _env.pd().alloc(ds_size, cached); - }); - return ds; - } - - - void free(Ram_dataspace_capability ds) override - { - _replenish(_env.pd().dataspace_size(ds), 1, [&] () { - _env.pd().free(ds); - }); - } - - size_t dataspace_size(Ram_dataspace_capability ds) const override { return _env.pd().dataspace_size(ds); } - - - /**************** - ** Region_map ** - ****************/ - - Local_addr attach(Dataspace_capability ds, - size_t size = 0, - off_t offset = 0, - bool use_local_addr = false, - Local_addr local_addr = (void *)0, - bool executable = false, - bool writeable = true) override - { - enum { MAX_SHARED_CAP = 2 }; - enum { MAX_SHARED_RAM = 4 * 4096 }; - - void *ptr; - _consume(0, MAX_SHARED_RAM, 0, MAX_SHARED_CAP, [&] () { - ptr = _env.rm().attach(ds, size, offset, use_local_addr, - local_addr, executable, writeable); - }); - return ptr; - }; - - void report(Genode::Xml_generator &xml) const - { - xml.node("ram-quota", [&] () { - xml.attribute("used", _ram_guard.used().value); - xml.attribute("limit", _ram_guard.limit().value); - xml.attribute("avail", _ram_guard.avail().value); - }); - xml.node("cap-quota", [&] () { - xml.attribute("used", _cap_guard.used().value); - xml.attribute("limit", _cap_guard.limit().value); - xml.attribute("avail", _cap_guard.avail().value); - }); - } - - void detach(Local_addr local_addr) override - { - _replenish(0, 0, [&] () { _env.rm().detach(local_addr); }); - } - - void fault_handler(Signal_context_capability handler) override { _env.rm().fault_handler(handler); } - State state() override { return _env.rm().state(); } - Dataspace_capability dataspace() override { return _env.rm().dataspace(); } - - - /*************** - ** Accessors ** - ***************/ - - Ram_quota_guard const &ram_guard() const { return _ram_guard; }; - Cap_quota_guard const &cap_guard() const { return _cap_guard; }; -}; - - -class Net::Communication_buffer -{ - private: - - Genode::Ram_allocator &_ram_alloc; - Genode::Ram_dataspace_capability _ram_ds; - - public: - - Communication_buffer(Genode::Ram_allocator &ram_alloc, - Genode::size_t const size); - - ~Communication_buffer() { _ram_alloc.free(_ram_ds); } - - - /*************** - ** Accessors ** - ***************/ - - Genode::Dataspace_capability ds() const { return _ram_ds; } -}; - - -class Net::Session_component_base -{ - protected: - - Genode::Session_env &_session_env; - Genode::Heap _alloc; - Nic::Packet_allocator _packet_alloc; - Communication_buffer _tx_buf; - Communication_buffer _rx_buf; - - public: - - Session_component_base(Genode::Session_env &session_env, - Genode::size_t const tx_buf_size, - Genode::size_t const rx_buf_size); -}; - - -class Net::Session_component : private Session_component_base, - public ::Nic::Session_rpc_object -{ - private: - - class Interface_policy : public Net::Interface_policy - { - private: - - using Signal_context_capability = - Genode::Signal_context_capability; - - /* - * The transient link state is a combination of session and - * interface link state. The first word in the value name - * denotes the link state of the session. If the session - * link state has already been read by the client and - * can therefore be altered directly, it is marked as - * 'ACKNOWLEDGED'. Otherwise, the denoted session state - * has to stay fixed until the client has read it. In this - * case, the session link state in the value name may be - * followed by the pending link state edges. Consequently, - * the last 'UP' or 'DOWN' in each value name denotes the - * router-internal interface link-state. - */ - enum Transient_link_state - { - DOWN_ACKNOWLEDGED, - DOWN, - DOWN_UP, - DOWN_UP_DOWN, - UP_ACKNOWLEDGED, - UP, - UP_DOWN, - UP_DOWN_UP - }; - - Genode::Session_label const _label; - Const_reference _config; - Genode::Session_env const &_session_env; - Transient_link_state _transient_link_state { DOWN_ACKNOWLEDGED }; - Signal_context_capability _session_link_state_sigh { }; - - void _session_link_state_transition(Transient_link_state tls); - - public: - - Interface_policy(Genode::Session_label const &label, - Genode::Session_env const &session_env, - Configuration const &config); - - bool read_and_ack_session_link_state(); - - void session_link_state_sigh(Genode::Signal_context_capability sigh); - - - /*************************** - ** Net::Interface_policy ** - ***************************/ - - Domain_name determine_domain_name() const override; - void handle_config(Configuration const &config) override { _config = config; } - Genode::Session_label const &label() const override { return _label; } - void report(Genode::Xml_generator &xml) const override { _session_env.report(xml); }; - void interface_unready() override; - void interface_ready() override; - bool interface_link_state() const override; - }; - - Interface_policy _interface_policy; - Interface _interface; - Genode::Ram_dataspace_capability const _ram_ds; - - public: - - Session_component(Genode::Session_env &session_env, - Genode::size_t const tx_buf_size, - Genode::size_t const rx_buf_size, - Timer::Connection &timer, - Mac_address const mac, - Mac_address const &router_mac, - Genode::Session_label const &label, - Interface_list &interfaces, - Configuration &config, - Genode::Ram_dataspace_capability const ram_ds); - - - /****************** - ** Nic::Session ** - ******************/ - - Mac_address mac_address() override { return _interface.mac(); } - bool link_state() override; - void link_state_sigh(Genode::Signal_context_capability sigh) override; - - - /*************** - ** Accessors ** - ***************/ - - Interface_policy const &interface_policy() const { return _interface_policy; } - Genode::Ram_dataspace_capability ram_ds() const { return _ram_ds; }; - Genode::Session_env const &session_env() const { return _session_env; }; -}; - - -class Net::Root : public Genode::Root_component -{ - private: - - enum { MAC_ALLOC_BASE = 0x02 }; - - Genode::Env &_env; - Timer::Connection &_timer; - Mac_allocator _mac_alloc; - Mac_address const _router_mac; - Reference _config; - Quota &_shared_quota; - Interface_list &_interfaces; - - void _invalid_downlink(char const *reason); - - - /******************** - ** Root_component ** - ********************/ - - Session_component *_create_session(char const *args) override; - void _destroy_session(Session_component *session) override; - - public: - - Root(Genode::Env &env, - Timer::Connection &timer, - Genode::Allocator &alloc, - Configuration &config, - Quota &shared_quota, - Interface_list &interfaces); - - void handle_config(Configuration &config) { _config = Reference(config); } -}; - -#endif /* _COMPONENT_H_ */ diff --git a/repos/os/src/server/nic_router/main.cc b/repos/os/src/server/nic_router/main.cc index 86993d8e01..2a6fcef2f2 100644 --- a/repos/os/src/server/nic_router/main.cc +++ b/repos/os/src/server/nic_router/main.cc @@ -18,7 +18,8 @@ #include /* local includes */ -#include +#include +#include #include #include @@ -33,14 +34,15 @@ class Net::Main private: Genode::Env &_env; - Quota _shared_quota { }; - Interface_list _interfaces { }; - Timer::Connection _timer { _env }; - Genode::Heap _heap { &_env.ram(), &_env.rm() }; - Genode::Attached_rom_dataspace _config_rom { _env, "config" }; - Reference _config { *new (_heap) Configuration { _config_rom.xml(), _heap } }; - Signal_handler
_config_handler { _env.ep(), *this, &Main::_handle_config }; - Root _root { _env, _timer, _heap, _config(), _shared_quota, _interfaces }; + Quota _shared_quota { }; + Interface_list _interfaces { }; + Timer::Connection _timer { _env }; + Genode::Heap _heap { &_env.ram(), &_env.rm() }; + Genode::Attached_rom_dataspace _config_rom { _env, "config" }; + Reference _config { *new (_heap) Configuration { _config_rom.xml(), _heap } }; + Signal_handler
_config_handler { _env.ep(), *this, &Main::_handle_config }; + Nic_session_root _nic_session_root { _env, _timer, _heap, _config(), _shared_quota, _interfaces }; + Uplink_session_root _uplink_session_root { _env, _timer, _heap, _config(), _shared_quota, _interfaces }; void _handle_config(); @@ -67,7 +69,8 @@ Net::Main::Main(Env &env) : _env(env) { _config_rom.sigh(_config_handler); _handle_config(); - env.parent().announce(env.ep().manage(_root)); + env.parent().announce(env.ep().manage(_nic_session_root)); + env.parent().announce(env.ep().manage(_uplink_session_root)); } @@ -81,7 +84,8 @@ void Net::Main::_handle_config() Configuration(_env, _config_rom.xml(), _heap, _timer, old_config, _shared_quota, _interfaces); - _root.handle_config(new_config); + _nic_session_root.handle_config(new_config); + _uplink_session_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(); }); _config = Reference(new_config); diff --git a/repos/os/src/server/nic_router/component.cc b/repos/os/src/server/nic_router/nic_session_root.cc similarity index 67% rename from repos/os/src/server/nic_router/component.cc rename to repos/os/src/server/nic_router/nic_session_root.cc index f7c91dbd5f..2acb38549e 100644 --- a/repos/os/src/server/nic_router/component.cc +++ b/repos/os/src/server/nic_router/nic_session_root.cc @@ -1,5 +1,5 @@ /* - * \brief Downlink interface in form of a NIC session component + * \brief NIC session server role of the NIC router * \author Martin Stein * \date 2016-08-23 */ @@ -15,33 +15,21 @@ #include /* local includes */ -#include +#include #include using namespace Net; using namespace Genode; -/************************** - ** Communication_buffer ** - **************************/ +/******************************** + ** Nic_session_component_base ** + ********************************/ -Communication_buffer::Communication_buffer(Ram_allocator &ram_alloc, - size_t const size) -: - _ram_alloc { ram_alloc }, - _ram_ds { ram_alloc.alloc(size) } -{ } - - -/**************************** - ** Session_component_base ** - ****************************/ - -Session_component_base:: -Session_component_base(Session_env &session_env, - size_t const tx_buf_size, - size_t const rx_buf_size) +Nic_session_component_base:: +Nic_session_component_base(Session_env &session_env, + size_t const tx_buf_size, + size_t const rx_buf_size) : _session_env { session_env }, _alloc { _session_env, _session_env }, @@ -51,11 +39,11 @@ Session_component_base(Session_env &session_env, { } -/***************************************** - ** Session_component::Interface_policy ** - *****************************************/ +/********************************************* + ** Nic_session_component::Interface_policy ** + *********************************************/ -Net::Session_component:: +Net::Nic_session_component:: Interface_policy::Interface_policy(Genode::Session_label const &label, Session_env const &session_env, Configuration const &config) @@ -69,7 +57,7 @@ Interface_policy::Interface_policy(Genode::Session_label const &label, Domain_name -Net::Session_component::Interface_policy::determine_domain_name() const +Net::Nic_session_component::Interface_policy::determine_domain_name() const { Domain_name domain_name; try { @@ -90,7 +78,7 @@ Net::Session_component::Interface_policy::determine_domain_name() const } -void Net::Session_component:: +void Net::Nic_session_component:: Interface_policy::_session_link_state_transition(Transient_link_state tls) { _transient_link_state = tls; @@ -98,7 +86,7 @@ Interface_policy::_session_link_state_transition(Transient_link_state tls) } -void Net::Session_component::Interface_policy::interface_unready() +void Net::Nic_session_component::Interface_policy::interface_unready() { switch (_transient_link_state) { case UP_ACKNOWLEDGED: @@ -132,7 +120,7 @@ void Net::Session_component::Interface_policy::interface_unready() } -void Net::Session_component::Interface_policy::interface_ready() +void Net::Nic_session_component::Interface_policy::interface_ready() { switch (_transient_link_state) { case DOWN_ACKNOWLEDGED: @@ -166,7 +154,7 @@ void Net::Session_component::Interface_policy::interface_ready() } bool -Net::Session_component::Interface_policy::interface_link_state() const +Net::Nic_session_component::Interface_policy::interface_link_state() const { switch (_transient_link_state) { case DOWN_ACKNOWLEDGED: return false; @@ -184,7 +172,7 @@ Net::Session_component::Interface_policy::interface_link_state() const bool -Net::Session_component::Interface_policy::read_and_ack_session_link_state() +Net::Nic_session_component::Interface_policy::read_and_ack_session_link_state() { switch (_transient_link_state) { case DOWN_ACKNOWLEDGED: @@ -230,36 +218,38 @@ Net::Session_component::Interface_policy::read_and_ack_session_link_state() } -void Net::Session_component::Interface_policy:: +void Net::Nic_session_component::Interface_policy:: session_link_state_sigh(Signal_context_capability sigh) { _session_link_state_sigh = sigh; } -/*********************** - ** Session_component ** - ***********************/ +/*************************** + ** Nic_session_component ** + ***************************/ -Net::Session_component::Session_component(Session_env &session_env, - size_t const tx_buf_size, - size_t const rx_buf_size, - Timer::Connection &timer, - Mac_address const mac, - Mac_address const &router_mac, - Session_label const &label, - Interface_list &interfaces, - Configuration &config, - Ram_dataspace_capability const ram_ds) +Net:: +Nic_session_component:: +Nic_session_component(Session_env &session_env, + size_t const tx_buf_size, + size_t const rx_buf_size, + Timer::Connection &timer, + Mac_address const mac, + Mac_address const &router_mac, + Session_label const &label, + Interface_list &interfaces, + Configuration &config, + Ram_dataspace_capability const ram_ds) : - Session_component_base { session_env, tx_buf_size,rx_buf_size }, - Session_rpc_object { _session_env, _tx_buf.ds(), _rx_buf.ds(), - &_packet_alloc, _session_env.ep().rpc_ep() }, - _interface_policy { label, _session_env, config }, - _interface { _session_env.ep(), timer, router_mac, _alloc, - mac, config, interfaces, *_tx.sink(), - *_rx.source(), _interface_policy }, - _ram_ds { ram_ds } + Nic_session_component_base { session_env, tx_buf_size,rx_buf_size }, + Session_rpc_object { _session_env, _tx_buf.ds(), _rx_buf.ds(), + &_packet_alloc, _session_env.ep().rpc_ep() }, + _interface_policy { label, _session_env, config }, + _interface { _session_env.ep(), timer, router_mac, _alloc, + mac, config, interfaces, *_tx.sink(), + *_rx.source(), _interface_policy }, + _ram_ds { ram_ds } { _interface.attach_to_domain(); @@ -270,42 +260,42 @@ Net::Session_component::Session_component(Session_env &sessio } -bool Net::Session_component::link_state() +bool Net::Nic_session_component::link_state() { return _interface_policy.read_and_ack_session_link_state(); } void Net:: -Session_component::link_state_sigh(Signal_context_capability sigh) +Nic_session_component::link_state_sigh(Signal_context_capability sigh) { _interface_policy.session_link_state_sigh(sigh); } -/********** - ** Root ** - **********/ +/********************** + ** Nic_session_root ** + **********************/ -Net::Root::Root(Env &env, - Timer::Connection &timer, - Allocator &alloc, - Configuration &config, - Quota &shared_quota, - Interface_list &interfaces) +Net::Nic_session_root::Nic_session_root(Env &env, + Timer::Connection &timer, + Allocator &alloc, + Configuration &config, + Quota &shared_quota, + Interface_list &interfaces) : - Root_component { &env.ep().rpc_ep(), &alloc }, - _env { env }, - _timer { timer }, - _mac_alloc { MAC_ALLOC_BASE }, - _router_mac { _mac_alloc.alloc() }, - _config { config }, - _shared_quota { shared_quota }, - _interfaces { interfaces } + Root_component { &env.ep().rpc_ep(), &alloc }, + _env { env }, + _timer { timer }, + _mac_alloc { MAC_ALLOC_BASE }, + _router_mac { _mac_alloc.alloc() }, + _config { config }, + _shared_quota { shared_quota }, + _interfaces { interfaces } { } -Session_component *Net::Root::_create_session(char const *args) +Nic_session_component *Net::Nic_session_root::_create_session(char const *args) { try { /* create session environment temporarily on the stack */ @@ -316,7 +306,7 @@ Session_component *Net::Root::_create_session(char const *args) /* alloc/attach RAM block and move session env to base of the block */ Ram_dataspace_capability ram_ds { session_env_stack.alloc(sizeof(Session_env) + - sizeof(Session_component), CACHED) }; + sizeof(Nic_session_component), CACHED) }; try { void * const ram_ptr { session_env_stack.attach(ram_ds) }; Session_env &session_env { @@ -327,14 +317,13 @@ Session_component *Net::Root::_create_session(char const *args) Session_label const label { label_from_args(args) }; Mac_address const mac { _mac_alloc.alloc() }; try { - Session_component *x = construct_at( + return construct_at( (void*)((addr_t)ram_ptr + sizeof(Session_env)), session_env, Arg_string::find_arg(args, "tx_buf_size").ulong_value(0), Arg_string::find_arg(args, "rx_buf_size").ulong_value(0), _timer, mac, _router_mac, label, _interfaces, _config(), ram_ds); - return x; } catch (Out_of_ram) { _mac_alloc.free(mac); @@ -392,7 +381,7 @@ Session_component *Net::Root::_create_session(char const *args) } } -void Net::Root::_destroy_session(Session_component *session) +void Net::Nic_session_root::_destroy_session(Nic_session_component *session) { Mac_address const mac = session->mac_address(); @@ -400,7 +389,7 @@ void Net::Root::_destroy_session(Session_component *session) Ram_dataspace_capability ram_ds { session->ram_ds() }; Session_env const &session_env { session->session_env() }; Session_label const session_label { session->interface_policy().label() }; - session->~Session_component(); + session->~Nic_session_component(); /* copy session env to stack and detach/free all session data */ Session_env session_env_stack { session_env }; @@ -420,7 +409,7 @@ void Net::Root::_destroy_session(Session_component *session) } -void Net::Root::_invalid_downlink(char const *reason) +void Net::Nic_session_root::_invalid_downlink(char const *reason) { if (_config().verbose()) { log("[?] invalid downlink (", reason, ")"); } diff --git a/repos/os/src/server/nic_router/nic_session_root.h b/repos/os/src/server/nic_router/nic_session_root.h new file mode 100644 index 0000000000..54116a1775 --- /dev/null +++ b/repos/os/src/server/nic_router/nic_session_root.h @@ -0,0 +1,201 @@ +/* + * \brief NIC session server role of the NIC router + * \author Martin Stein + * \date 2016-08-23 + */ + +/* + * Copyright (C) 2016-2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _NIC_SESSION_ROOT_H_ +#define _NIC_SESSION_ROOT_H_ + +/* Genode includes */ +#include +#include +#include +#include + +/* local includes */ +#include +#include +#include +#include +#include +#include + +namespace Net { + + class Nic_session_component_base; + class Nic_session_component; + class Nic_session_root; +} + + +class Net::Nic_session_component_base +{ + protected: + + Genode::Session_env &_session_env; + Genode::Heap _alloc; + Nic::Packet_allocator _packet_alloc; + Communication_buffer _tx_buf; + Communication_buffer _rx_buf; + + public: + + Nic_session_component_base(Genode::Session_env &session_env, + Genode::size_t const tx_buf_size, + Genode::size_t const rx_buf_size); +}; + + +class Net::Nic_session_component : private Nic_session_component_base, + public ::Nic::Session_rpc_object +{ + private: + + class Interface_policy : public Net::Interface_policy + { + private: + + using Signal_context_capability = + Genode::Signal_context_capability; + + /* + * The transient link state is a combination of session and + * interface link state. The first word in the value name + * denotes the link state of the session. If the session + * link state has already been read by the client and + * can therefore be altered directly, it is marked as + * 'ACKNOWLEDGED'. Otherwise, the denoted session state + * has to stay fixed until the client has read it. In this + * case, the session link state in the value name may be + * followed by the pending link state edges. Consequently, + * the last 'UP' or 'DOWN' in each value name denotes the + * router-internal interface link-state. + */ + enum Transient_link_state + { + DOWN_ACKNOWLEDGED, + DOWN, + DOWN_UP, + DOWN_UP_DOWN, + UP_ACKNOWLEDGED, + UP, + UP_DOWN, + UP_DOWN_UP + }; + + Genode::Session_label const _label; + Const_reference _config; + Genode::Session_env const &_session_env; + Transient_link_state _transient_link_state { DOWN_ACKNOWLEDGED }; + Signal_context_capability _session_link_state_sigh { }; + + void _session_link_state_transition(Transient_link_state tls); + + public: + + Interface_policy(Genode::Session_label const &label, + Genode::Session_env const &session_env, + Configuration const &config); + + bool read_and_ack_session_link_state(); + + void session_link_state_sigh(Genode::Signal_context_capability sigh); + + + /*************************** + ** Net::Interface_policy ** + ***************************/ + + Domain_name determine_domain_name() const override; + void handle_config(Configuration const &config) override { _config = config; } + Genode::Session_label const &label() const override { return _label; } + void report(Genode::Xml_generator &xml) const override { _session_env.report(xml); }; + void interface_unready() override; + void interface_ready() override; + bool interface_link_state() const override; + }; + + Interface_policy _interface_policy; + Interface _interface; + Genode::Ram_dataspace_capability const _ram_ds; + + public: + + Nic_session_component(Genode::Session_env &session_env, + Genode::size_t const tx_buf_size, + Genode::size_t const rx_buf_size, + Timer::Connection &timer, + Mac_address const mac, + Mac_address const &router_mac, + Genode::Session_label const &label, + Interface_list &interfaces, + Configuration &config, + Genode::Ram_dataspace_capability const ram_ds); + + + /****************** + ** Nic::Session ** + ******************/ + + Mac_address mac_address() override { return _interface.mac(); } + bool link_state() override; + void link_state_sigh(Genode::Signal_context_capability sigh) override; + + + /*************** + ** Accessors ** + ***************/ + + Interface_policy const &interface_policy() const { return _interface_policy; } + Genode::Ram_dataspace_capability ram_ds() const { return _ram_ds; }; + Genode::Session_env const &session_env() const { return _session_env; }; +}; + + +class Net::Nic_session_root +: + public Genode::Root_component +{ + private: + + enum { MAC_ALLOC_BASE = 0x02 }; + + Genode::Env &_env; + Timer::Connection &_timer; + Mac_allocator _mac_alloc; + Mac_address const _router_mac; + Reference _config; + Quota &_shared_quota; + Interface_list &_interfaces; + + void _invalid_downlink(char const *reason); + + + /******************** + ** Root_component ** + ********************/ + + Nic_session_component *_create_session(char const *args) override; + void _destroy_session(Nic_session_component *session) override; + + public: + + Nic_session_root(Genode::Env &env, + Timer::Connection &timer, + Genode::Allocator &alloc, + Configuration &config, + Quota &shared_quota, + Interface_list &interfaces); + + void handle_config(Configuration &config) { _config = Reference(config); } +}; + +#endif /* _NIC_SESSION_ROOT_H_ */ diff --git a/repos/os/src/server/nic_router/session_env.h b/repos/os/src/server/nic_router/session_env.h new file mode 100644 index 0000000000..f399494b60 --- /dev/null +++ b/repos/os/src/server/nic_router/session_env.h @@ -0,0 +1,196 @@ +/* + * \brief Guarded Genode environment for session components + * \author Martin Stein + * \date 2020-11-30 + */ + +/* + * Copyright (C) 2020 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _SESSION_ENV_H_ +#define _SESSION_ENV_H_ + +/* Genode includes */ +#include + +namespace Genode { class Session_env; } + + +class Genode::Session_env : public Ram_allocator, + public Region_map +{ + private: + + Env &_env; + Net::Quota &_shared_quota; + Ram_quota_guard _ram_guard; + Cap_quota_guard _cap_guard; + + template + void _consume(size_t own_ram, + size_t max_shared_ram, + size_t own_cap, + size_t max_shared_cap, + FUNC && functor) + { + size_t const max_ram_consumpt { own_ram + max_shared_ram }; + size_t const max_cap_consumpt { own_cap + max_shared_cap }; + size_t ram_consumpt { _env.pd().used_ram().value }; + size_t cap_consumpt { _env.pd().used_caps().value }; + { + Ram_quota_guard::Reservation ram_reserv { _ram_guard, Ram_quota { max_ram_consumpt } }; + Cap_quota_guard::Reservation cap_reserv { _cap_guard, Cap_quota { max_cap_consumpt } }; + + functor(); + + ram_reserv.acknowledge(); + cap_reserv.acknowledge(); + } + ram_consumpt = _env.pd().used_ram().value - ram_consumpt; + cap_consumpt = _env.pd().used_caps().value - cap_consumpt; + + if (ram_consumpt > max_ram_consumpt) { + error("Session_env: more RAM quota consumed than expected"); } + if (cap_consumpt > max_cap_consumpt) { + error("Session_env: more CAP quota consumed than expected"); } + if (ram_consumpt < own_ram) { + error("Session_env: less RAM quota consumed than expected"); } + if (cap_consumpt < own_cap) { + error("Session_env: less CAP quota consumed than expected"); } + + _shared_quota.ram += ram_consumpt - own_ram; + _shared_quota.cap += cap_consumpt - own_cap; + + _ram_guard.replenish( Ram_quota { max_shared_ram } ); + _cap_guard.replenish( Cap_quota { max_shared_cap } ); + } + + template + void _replenish(size_t accounted_ram, + size_t accounted_cap, + FUNC && functor) + { + size_t ram_replenish { _env.pd().used_ram().value }; + size_t cap_replenish { _env.pd().used_caps().value }; + functor(); + ram_replenish = ram_replenish - _env.pd().used_ram().value; + cap_replenish = cap_replenish - _env.pd().used_caps().value; + + if (ram_replenish < accounted_ram) { + error("Session_env: less RAM quota replenished than expected"); } + if (cap_replenish < accounted_cap) { + error("Session_env: less CAP quota replenished than expected"); } + + _shared_quota.ram -= ram_replenish - accounted_ram; + _shared_quota.cap -= cap_replenish - accounted_cap; + + _ram_guard.replenish( Ram_quota { accounted_ram } ); + _cap_guard.replenish( Cap_quota { accounted_cap } ); + + } + + public: + + Session_env(Env &env, + Net::Quota &shared_quota, + Ram_quota const &ram_quota, + Cap_quota const &cap_quota) + : + _env { env }, + _shared_quota { shared_quota }, + _ram_guard { ram_quota }, + _cap_guard { cap_quota } + { } + + Entrypoint &ep() { return _env.ep(); } + + + /******************* + ** Ram_allocator ** + *******************/ + + Ram_dataspace_capability alloc(size_t size, Cache_attribute cached) override + { + enum { MAX_SHARED_CAP = 1 }; + enum { MAX_SHARED_RAM = 4096 }; + enum { DS_SIZE_GRANULARITY_LOG2 = 12 }; + + size_t const ds_size = align_addr(size, DS_SIZE_GRANULARITY_LOG2); + Ram_dataspace_capability ds; + _consume(ds_size, MAX_SHARED_RAM, 1, MAX_SHARED_CAP, [&] () { + ds = _env.pd().alloc(ds_size, cached); + }); + return ds; + } + + + void free(Ram_dataspace_capability ds) override + { + _replenish(_env.pd().dataspace_size(ds), 1, [&] () { + _env.pd().free(ds); + }); + } + + size_t dataspace_size(Ram_dataspace_capability ds) const override { return _env.pd().dataspace_size(ds); } + + + /**************** + ** Region_map ** + ****************/ + + Local_addr attach(Dataspace_capability ds, + size_t size = 0, + off_t offset = 0, + bool use_local_addr = false, + Local_addr local_addr = (void *)0, + bool executable = false, + bool writeable = true) override + { + enum { MAX_SHARED_CAP = 2 }; + enum { MAX_SHARED_RAM = 4 * 4096 }; + + void *ptr; + _consume(0, MAX_SHARED_RAM, 0, MAX_SHARED_CAP, [&] () { + ptr = _env.rm().attach(ds, size, offset, use_local_addr, + local_addr, executable, writeable); + }); + return ptr; + }; + + void report(Genode::Xml_generator &xml) const + { + xml.node("ram-quota", [&] () { + xml.attribute("used", _ram_guard.used().value); + xml.attribute("limit", _ram_guard.limit().value); + xml.attribute("avail", _ram_guard.avail().value); + }); + xml.node("cap-quota", [&] () { + xml.attribute("used", _cap_guard.used().value); + xml.attribute("limit", _cap_guard.limit().value); + xml.attribute("avail", _cap_guard.avail().value); + }); + } + + void detach(Local_addr local_addr) override + { + _replenish(0, 0, [&] () { _env.rm().detach(local_addr); }); + } + + void fault_handler(Signal_context_capability handler) override { _env.rm().fault_handler(handler); } + State state() override { return _env.rm().state(); } + Dataspace_capability dataspace() override { return _env.rm().dataspace(); } + + + /*************** + ** Accessors ** + ***************/ + + Ram_quota_guard const &ram_guard() const { return _ram_guard; }; + Cap_quota_guard const &cap_guard() const { return _cap_guard; }; +}; + +#endif /* _SESSION_ENV_H_ */ diff --git a/repos/os/src/server/nic_router/target.mk b/repos/os/src/server/nic_router/target.mk index 011e8cba8b..66a6b20bfb 100644 --- a/repos/os/src/server/nic_router/target.mk +++ b/repos/os/src/server/nic_router/target.mk @@ -2,13 +2,34 @@ TARGET = nic_router LIBS += base net -SRC_CC += arp_waiter.cc ip_rule.cc ipv4_address_prefix.cc -SRC_CC += component.cc port_allocator.cc forward_rule.cc -SRC_CC += nat_rule.cc main.cc ipv4_config.cc -SRC_CC += uplink.cc interface.cc arp_cache.cc configuration.cc -SRC_CC += domain.cc l3_protocol.cc direct_rule.cc link.cc -SRC_CC += transport_rule.cc permit_rule.cc dns_server.cc -SRC_CC += dhcp_client.cc dhcp_server.cc report.cc xml_node.cc +SRC_CC += \ + arp_waiter.cc \ + ip_rule.cc \ + ipv4_address_prefix.cc \ + nic_session_root.cc \ + port_allocator.cc \ + forward_rule.cc \ + nat_rule.cc \ + main.cc \ + ipv4_config.cc \ + uplink.cc \ + interface.cc \ + arp_cache.cc \ + configuration.cc \ + domain.cc \ + l3_protocol.cc \ + direct_rule.cc \ + link.cc \ + transport_rule.cc \ + permit_rule.cc \ + dns_server.cc \ + dhcp_client.cc \ + dhcp_server.cc \ + report.cc \ + xml_node.cc \ + uplink_session_root.cc \ + communication_buffer.cc \ + INC_DIR += $(PRG_DIR) diff --git a/repos/os/src/server/nic_router/uplink_session_root.cc b/repos/os/src/server/nic_router/uplink_session_root.cc new file mode 100644 index 0000000000..50f16028ec --- /dev/null +++ b/repos/os/src/server/nic_router/uplink_session_root.cc @@ -0,0 +1,256 @@ +/* + * \brief Downlink interface in form of an Uplink session component + * \author Martin Stein + * \date 2016-08-23 + */ + +/* + * Copyright (C) 2016-2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +/* Genode includes */ +#include + +/* local includes */ +#include +#include + +using namespace Net; +using namespace Genode; + + +/*********************************** + ** Uplink_session_component_base ** + ***********************************/ + +Uplink_session_component_base:: +Uplink_session_component_base(Session_env &session_env, + size_t const tx_buf_size, + size_t const rx_buf_size) +: + _session_env { session_env }, + _alloc { _session_env, _session_env }, + _packet_alloc { &_alloc }, + _tx_buf { _session_env, tx_buf_size }, + _rx_buf { _session_env, rx_buf_size } +{ } + + +/************************************************ + ** Uplink_session_component::Interface_policy ** + ************************************************/ + +Net::Uplink_session_component:: +Interface_policy::Interface_policy(Genode::Session_label const &label, + Session_env const &session_env, + Configuration const &config) +: + _label { label }, + _config { config }, + _session_env { session_env } +{ } + + +Domain_name +Net::Uplink_session_component::Interface_policy::determine_domain_name() const +{ + Domain_name domain_name; + try { + Session_policy policy(_label, _config().node()); + domain_name = policy.attribute_value("domain", Domain_name()); + } + catch (Session_policy::No_policy_defined) { + if (_config().verbose()) { + log("[?] no policy for downlink label \"", _label, "\""); } + } + catch (Xml_node::Nonexistent_attribute) { + if (_config().verbose()) { + log("[?] no domain attribute in policy for downlink label \"", + _label, "\""); + } + } + return domain_name; +} + + +/****************************** + ** Uplink_session_component ** + ******************************/ + +Net::Uplink_session_component::Uplink_session_component(Session_env &session_env, + size_t const tx_buf_size, + size_t const rx_buf_size, + Timer::Connection &timer, + Mac_address const mac, + Session_label const &label, + Interface_list &interfaces, + Configuration &config, + Ram_dataspace_capability const ram_ds) +: + Uplink_session_component_base { session_env, tx_buf_size,rx_buf_size }, + Session_rpc_object { _session_env, _tx_buf.ds(), _rx_buf.ds(), + &_packet_alloc, _session_env.ep().rpc_ep() }, + _interface_policy { label, _session_env, config }, + _interface { _session_env.ep(), timer, mac, _alloc, + Mac_address(), config, interfaces, *_tx.sink(), + *_rx.source(), _interface_policy }, + _ram_ds { ram_ds } +{ + _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()); + _rx.sigh_ready_to_submit(_interface.source_submit()); +} + + +/************************* + ** Uplink_session_root ** + *************************/ + +Net::Uplink_session_root::Uplink_session_root(Env &env, + Timer::Connection &timer, + Allocator &alloc, + Configuration &config, + Quota &shared_quota, + Interface_list &interfaces) +: + Root_component { &env.ep().rpc_ep(), &alloc }, + _env { env }, + _timer { timer }, + _config { config }, + _shared_quota { shared_quota }, + _interfaces { interfaces } +{ } + + +Uplink_session_component * +Net::Uplink_session_root::_create_session(char const *args) +{ + try { + /* create session environment temporarily on the stack */ + Session_env session_env_stack { _env, _shared_quota, + Ram_quota { Arg_string::find_arg(args, "ram_quota").ulong_value(0) }, + Cap_quota { Arg_string::find_arg(args, "cap_quota").ulong_value(0) } }; + + /* alloc/attach RAM block and move session env to base of the block */ + Ram_dataspace_capability ram_ds { + session_env_stack.alloc(sizeof(Session_env) + + sizeof(Uplink_session_component), CACHED) }; + try { + void * const ram_ptr { session_env_stack.attach(ram_ds) }; + Session_env &session_env { + *construct_at(ram_ptr, session_env_stack) }; + + Session_label const label { label_from_args(args) }; + + enum { MAC_STR_LENGTH = 19 }; + char mac_str [MAC_STR_LENGTH]; + Arg mac_arg { Arg_string::find_arg(args, "mac_address") }; + + if (!mac_arg.valid()) { + Session_env session_env_stack { session_env }; + session_env_stack.detach(ram_ptr); + session_env_stack.free(ram_ds); + _invalid_downlink("failed to find 'mac_address' arg"); + throw Service_denied(); + } + mac_arg.string(mac_str, MAC_STR_LENGTH, ""); + Mac_address mac { }; + ascii_to(mac_str, mac); + if (mac == Mac_address { }) { + Session_env session_env_stack { session_env }; + session_env_stack.detach(ram_ptr); + session_env_stack.free(ram_ds); + _invalid_downlink("malformed 'mac_address' arg"); + throw Service_denied(); + } + /* create new session object behind session env in the RAM block */ + try { + return construct_at( + (void*)((addr_t)ram_ptr + sizeof(Session_env)), + session_env, + Arg_string::find_arg(args, "tx_buf_size").ulong_value(0), + Arg_string::find_arg(args, "rx_buf_size").ulong_value(0), + _timer, mac, label, _interfaces, _config(), ram_ds); + } + catch (Out_of_ram) { + Session_env session_env_stack { session_env }; + session_env_stack.detach(ram_ptr); + session_env_stack.free(ram_ds); + _invalid_downlink("Uplink session RAM quota"); + throw Insufficient_ram_quota(); + } + catch (Out_of_caps) { + Session_env session_env_stack { session_env }; + session_env_stack.detach(ram_ptr); + session_env_stack.free(ram_ds); + _invalid_downlink("Uplink session CAP quota"); + throw Insufficient_cap_quota(); + } + } + catch (Region_map::Invalid_dataspace) { + session_env_stack.free(ram_ds); + _invalid_downlink("Failed to attach RAM"); + throw Service_denied(); + } + catch (Region_map::Region_conflict) { + session_env_stack.free(ram_ds); + _invalid_downlink("Failed to attach RAM"); + throw Service_denied(); + } + catch (Out_of_ram) { + session_env_stack.free(ram_ds); + _invalid_downlink("Uplink session RAM quota"); + throw Insufficient_ram_quota(); + } + catch (Out_of_caps) { + session_env_stack.free(ram_ds); + _invalid_downlink("Uplink session CAP quota"); + throw Insufficient_cap_quota(); + } + } + catch (Out_of_ram) { + _invalid_downlink("Uplink session RAM quota"); + throw Insufficient_ram_quota(); + } + catch (Out_of_caps) { + _invalid_downlink("Uplink session CAP quota"); + throw Insufficient_cap_quota(); + } +} + +void +Net::Uplink_session_root::_destroy_session(Uplink_session_component *session) +{ + /* read out initial dataspace and session env and destruct session */ + Ram_dataspace_capability ram_ds { session->ram_ds() }; + Session_env const &session_env { session->session_env() }; + Session_label const session_label { session->interface_policy().label() }; + session->~Uplink_session_component(); + + /* copy session env to stack and detach/free all session data */ + Session_env session_env_stack { session_env }; + session_env_stack.detach(session); + session_env_stack.detach(&session_env); + session_env_stack.free(ram_ds); + + /* check for leaked quota */ + if (session_env_stack.ram_guard().used().value) { + error("Uplink session component \"", session_label, "\" leaks RAM quota of ", + session_env_stack.ram_guard().used().value, " byte(s)"); }; + if (session_env_stack.cap_guard().used().value) { + error("Uplink session component \"", session_label, "\" leaks CAP quota of ", + session_env_stack.cap_guard().used().value, " cap(s)"); }; +} + + +void Net::Uplink_session_root::_invalid_downlink(char const *reason) +{ + if (_config().verbose()) { + log("[?] invalid downlink (", reason, ")"); } +} diff --git a/repos/os/src/server/nic_router/uplink_session_root.h b/repos/os/src/server/nic_router/uplink_session_root.h new file mode 100644 index 0000000000..d85c67f1de --- /dev/null +++ b/repos/os/src/server/nic_router/uplink_session_root.h @@ -0,0 +1,153 @@ +/* + * \brief Downlink interface in form of an Uplink session component + * \author Martin Stein + * \date 2016-08-23 + */ + +/* + * Copyright (C) 2016-2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _UPLINK_SESSION_ROOT_H_ +#define _UPLINK_SESSION_ROOT_H_ + +/* Genode includes */ +#include +#include +#include +#include + +/* local includes */ +#include +#include +#include +#include +#include +#include + +namespace Net { + + class Uplink_session_component_base; + class Uplink_session_component; + class Uplink_session_root; +} + + +class Net::Uplink_session_component_base +{ + protected: + + Genode::Session_env &_session_env; + Genode::Heap _alloc; + Nic::Packet_allocator _packet_alloc; + Communication_buffer _tx_buf; + Communication_buffer _rx_buf; + + public: + + Uplink_session_component_base(Genode::Session_env &session_env, + Genode::size_t const tx_buf_size, + Genode::size_t const rx_buf_size); +}; + + +class Net::Uplink_session_component : private Uplink_session_component_base, + public ::Uplink::Session_rpc_object +{ + private: + + class Interface_policy : public Net::Interface_policy + { + private: + + Genode::Session_label const _label; + Const_reference _config; + Genode::Session_env const &_session_env; + + public: + + Interface_policy(Genode::Session_label const &label, + Genode::Session_env const &session_env, + Configuration const &config); + + + /*************************** + ** Net::Interface_policy ** + ***************************/ + + Domain_name determine_domain_name() const override; + void handle_config(Configuration const &config) override { _config = config; } + Genode::Session_label const &label() const override { return _label; } + void report(Genode::Xml_generator &xml) const override { _session_env.report(xml); }; + void interface_unready() override { } + void interface_ready() override { } + bool interface_link_state() const override { return true; } + }; + + Interface_policy _interface_policy; + Interface _interface; + Genode::Ram_dataspace_capability const _ram_ds; + + public: + + Uplink_session_component(Genode::Session_env &session_env, + Genode::size_t const tx_buf_size, + Genode::size_t const rx_buf_size, + Timer::Connection &timer, + Mac_address const mac, + Genode::Session_label const &label, + Interface_list &interfaces, + Configuration &config, + Genode::Ram_dataspace_capability const ram_ds); + + + /*************** + ** Accessors ** + ***************/ + + Interface_policy const &interface_policy() const { return _interface_policy; } + Genode::Ram_dataspace_capability ram_ds() const { return _ram_ds; }; + Genode::Session_env const &session_env() const { return _session_env; }; +}; + + +class Net::Uplink_session_root +: + public Genode::Root_component +{ + private: + + enum { MAC_ALLOC_BASE = 0x02 }; + + Genode::Env &_env; + Timer::Connection &_timer; + Reference _config; + Quota &_shared_quota; + Interface_list &_interfaces; + + void _invalid_downlink(char const *reason); + + + /******************** + ** Root_component ** + ********************/ + + Uplink_session_component *_create_session(char const *args) override; + void _destroy_session(Uplink_session_component *session) override; + + public: + + Uplink_session_root(Genode::Env &env, + Timer::Connection &timer, + Genode::Allocator &alloc, + Configuration &config, + Quota &shared_quota, + Interface_list &interfaces); + + void handle_config(Configuration &config) { _config = Reference(config); } +}; + +#endif /* _UPLINK_SESSION_ROOT_H_ */ diff --git a/repos/ports/run/netperf.inc b/repos/ports/run/netperf.inc index be873c3460..da04b75ff8 100644 --- a/repos/ports/run/netperf.inc +++ b/repos/ports/run/netperf.inc @@ -221,7 +221,10 @@ append config { append_if $use_nic_router config { - + + + +