From 468057638bf1379d0c96f04c9dbbdf1b909bbe5c Mon Sep 17 00:00:00 2001 From: Martin Stein Date: Sat, 12 Feb 2022 17:51:02 +0100 Subject: [PATCH] black_hole: provide Nic service Ref #4419 --- repos/os/recipes/pkg/black_hole/runtime | 2 + repos/os/recipes/pkg/test-black_hole/runtime | 3 + repos/os/recipes/src/black_hole/used_apis | 1 + .../os/recipes/src/test-black_hole/used_apis | 1 + repos/os/src/server/black_hole/README | 2 + repos/os/src/server/black_hole/config.xsd | 1 + repos/os/src/server/black_hole/main.cc | 7 ++ repos/os/src/server/black_hole/nic.h | 116 ++++++++++++++++++ repos/os/src/test/black_hole/main.cc | 88 ++++++++++++- 9 files changed, 218 insertions(+), 3 deletions(-) create mode 100644 repos/os/src/server/black_hole/nic.h diff --git a/repos/os/recipes/pkg/black_hole/runtime b/repos/os/recipes/pkg/black_hole/runtime index f9ea659189..5b2ab031bb 100644 --- a/repos/os/recipes/pkg/black_hole/runtime +++ b/repos/os/recipes/pkg/black_hole/runtime @@ -5,6 +5,7 @@ + @@ -12,6 +13,7 @@ + diff --git a/repos/os/recipes/pkg/test-black_hole/runtime b/repos/os/recipes/pkg/test-black_hole/runtime index 32a896e218..597e59ac8e 100644 --- a/repos/os/recipes/pkg/test-black_hole/runtime +++ b/repos/os/recipes/pkg/test-black_hole/runtime @@ -30,12 +30,14 @@ + + @@ -53,6 +55,7 @@ + diff --git a/repos/os/recipes/src/black_hole/used_apis b/repos/os/recipes/src/black_hole/used_apis index 74942fb292..a40b53f092 100644 --- a/repos/os/recipes/src/black_hole/used_apis +++ b/repos/os/recipes/src/black_hole/used_apis @@ -3,4 +3,5 @@ audio_in_session audio_out_session capture_session event_session +nic_session os diff --git a/repos/os/recipes/src/test-black_hole/used_apis b/repos/os/recipes/src/test-black_hole/used_apis index 6c271c2f7a..1474ce00c2 100644 --- a/repos/os/recipes/src/test-black_hole/used_apis +++ b/repos/os/recipes/src/test-black_hole/used_apis @@ -5,3 +5,4 @@ audio_in_session audio_out_session event_session capture_session +nic_session diff --git a/repos/os/src/server/black_hole/README b/repos/os/src/server/black_hole/README index fe17834729..66f07dd720 100644 --- a/repos/os/src/server/black_hole/README +++ b/repos/os/src/server/black_hole/README @@ -8,10 +8,12 @@ in the configuration of the component: * Audio_out * Capture * Event +* Nic + diff --git a/repos/os/src/server/black_hole/config.xsd b/repos/os/src/server/black_hole/config.xsd index ef050a6dfa..3919c4653e 100644 --- a/repos/os/src/server/black_hole/config.xsd +++ b/repos/os/src/server/black_hole/config.xsd @@ -4,6 +4,7 @@ + diff --git a/repos/os/src/server/black_hole/main.cc b/repos/os/src/server/black_hole/main.cc index 56991d459c..c1f78bbb05 100644 --- a/repos/os/src/server/black_hole/main.cc +++ b/repos/os/src/server/black_hole/main.cc @@ -25,6 +25,7 @@ #include "audio_out.h" #include "capture.h" #include "event.h" +#include "nic.h" /*************** @@ -43,6 +44,7 @@ struct Black_hole::Main Genode::Constructible audio_out_root { }; Genode::Constructible capture_root { }; Genode::Constructible event_root { }; + Genode::Constructible nic_root { }; Main(Genode::Env &env) : env(env) { @@ -66,6 +68,11 @@ struct Black_hole::Main event_root.construct(env, heap); env.parent().announce(env.ep().manage(*event_root)); } + + if (_config_rom.xml().has_sub_node("nic")) { + nic_root.construct(env, heap); + env.parent().announce(env.ep().manage(*nic_root)); + } } }; diff --git a/repos/os/src/server/black_hole/nic.h b/repos/os/src/server/black_hole/nic.h new file mode 100644 index 0000000000..4b5e5b104b --- /dev/null +++ b/repos/os/src/server/black_hole/nic.h @@ -0,0 +1,116 @@ +/* + * \brief Nic session component and root + * \author Martin Stein + * \date 2022-02-12 + */ + +/* + * Copyright (C) 2022 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_H_ +#define _NIC_H_ + +/* base includes */ +#include +#include + +/* os includes */ +#include + +namespace Black_hole { + + using namespace Genode; + + class Nic_session; + class Nic_root; +} + + +class Black_hole::Nic_session : public Nic::Session_component +{ + public: + + Nic_session(size_t const tx_buf_size, + size_t const rx_buf_size, + Allocator &rx_block_md_alloc, + Env &env) + : + Nic::Session_component(tx_buf_size, rx_buf_size, CACHED, + rx_block_md_alloc, env) + { } + + Nic::Mac_address mac_address() override + { + char buf[] = { 2, 3, 4, 5, 6, 7 }; + Nic::Mac_address result((void*)buf); + return result; + } + + bool link_state() override { return true; } + + void _handle_packet_stream() override + { + while (_tx.sink()->packet_avail()) { + + if (!_tx.sink()->ready_to_ack()) { + return; + } + Packet_descriptor const pkt { _tx.sink()->get_packet() }; + if (!pkt.size() || !_tx.sink()->packet_valid(pkt)) { + continue; + } + _tx.sink()->acknowledge_packet(pkt); + } + } +}; + + +class Black_hole::Nic_root : public Root_component +{ + private: + + Env &_env; + + protected: + + Nic_session *_create_session(char const *args) override + { + size_t ram_quota = Arg_string::find_arg(args, "ram_quota" ).ulong_value(0); + size_t tx_buf_size = Arg_string::find_arg(args, "tx_buf_size").ulong_value(0); + size_t rx_buf_size = Arg_string::find_arg(args, "rx_buf_size").ulong_value(0); + + /* deplete ram quota by the memory needed for the session structure */ + size_t session_size = max(4096UL, (size_t)sizeof(Nic_session)); + if (ram_quota < session_size) + throw Insufficient_ram_quota(); + + /* + * Check if donated ram quota suffices for both communication + * buffers and check for overflow + */ + if (tx_buf_size + rx_buf_size < tx_buf_size || + tx_buf_size + rx_buf_size > ram_quota - session_size) { + error("insufficient 'ram_quota', got ", ram_quota, ", " + "need ", tx_buf_size + rx_buf_size + session_size); + throw Insufficient_ram_quota(); + } + + return new (md_alloc()) Nic_session(tx_buf_size, rx_buf_size, + *md_alloc(), _env); + } + + public: + + Nic_root(Env &env, + Allocator &md_alloc) + : + Root_component(&env.ep().rpc_ep(), &md_alloc), + _env(env) + { } +}; + +#endif /* _NIC_H_ */ diff --git a/repos/os/src/test/black_hole/main.cc b/repos/os/src/test/black_hole/main.cc index c78815df8e..0e73b4c0a9 100644 --- a/repos/os/src/test/black_hole/main.cc +++ b/repos/os/src/test/black_hole/main.cc @@ -13,13 +13,16 @@ /* base includes */ #include +#include /* os includes */ #include #include #include #include - +#include +#include +#include #include using namespace Genode; @@ -34,7 +37,13 @@ class Test::Main { private: + enum { + NIC_BUF_SIZE = Nic::Packet_allocator::DEFAULT_PACKET_SIZE * 128, + NIC_PKT_SIZE = 100, + }; + Env &_env; + Heap _heap { _env.ram(), _env.rm() }; Event::Connection _event { _env }; Capture::Connection _capture { _env }; Capture::Area _capture_screen_size { 1, 1 }; @@ -43,20 +52,93 @@ class Test::Main Capture::Connection::Screen _capture_screen { _capture, _env.rm(), _capture_screen_size }; Audio_in::Connection _audio_in { _env, "left" }; Audio_out::Connection _audio_out { _env, "left" }; + Allocator_avl _nic_tx_blk_alloc { &_heap }; + Nic::Connection _nic { _env, &_nic_tx_blk_alloc, NIC_BUF_SIZE, NIC_BUF_SIZE }; + Signal_handler
_nic_handler { _env.ep(), *this, &Main::_handle_nic }; + unsigned long _nic_pkt_count { 0 }; + + void _check_if_test_has_finished() + { + if (_nic_pkt_count > 100) { + log("Finished"); + } + } + + void _handle_nic() + { + if (_nic.rx()->packet_avail()) { + class Nic_rx_packet_avail { }; + throw Nic_rx_packet_avail { }; + } + if (!_nic.rx()->ack_slots_free()) { + class Nic_no_rx_ack_slots_free { }; + throw Nic_no_rx_ack_slots_free { }; + } + while (_nic.tx()->ack_avail()) { + + Packet_descriptor const pkt { _nic.tx()->get_acked_packet() }; + if (pkt.size() != NIC_PKT_SIZE) { + class Nic_packet_size_unexpected { }; + throw Nic_packet_size_unexpected { }; + } + _nic.tx()->release_packet(pkt); + _nic_pkt_count++; + } + _submit_nic_pkts(); + _check_if_test_has_finished(); + } + + void _submit_nic_pkts() + { + for (unsigned idx { 0 }; idx < 40; idx++) { + + if (!_nic.tx()->ready_to_submit()) { + class Nic_submit_queue_full { }; + throw Nic_submit_queue_full { }; + } + Packet_descriptor pkt; + try { pkt = _nic.tx()->alloc_packet(NIC_PKT_SIZE); } + catch (...) { + class Nic_packet_alloc_failed { }; + throw Nic_packet_alloc_failed { }; + } + _nic.tx()->submit_packet(pkt); + } + } public: Main(Env &env) : _env { env } { + /* test-drive nic connection */ + _nic.tx_channel()->sigh_ready_to_submit(_nic_handler); + _nic.tx_channel()->sigh_ack_avail(_nic_handler); + _nic.rx_channel()->sigh_ready_to_ack(_nic_handler); + _nic.rx_channel()->sigh_packet_avail(_nic_handler); + if (!_nic.link_state()) { + class Nic_link_down { }; + throw Nic_link_down { }; + } + if (_nic.mac_address() == Net::Mac_address { }) { + class Nic_mac_invalid { }; + throw Nic_mac_invalid { }; + } + _submit_nic_pkts(); + + /* test-drive event connection */ _event.with_batch([&] (Event::Session_client::Batch &batch) { batch.submit(Input::Press {Input::KEY_1 }); batch.submit(Input::Release {Input::KEY_2 }); batch.submit(Input::Relative_motion { 3, 4 }); }); - + /* test-drive capture connection */ _capture_screen.apply_to_surface(_capture_surface); - log("Finished"); + /* + * FIXME + * + * Test-driving audio_in and audio_out connection is yet missing. + */ } };