mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-21 22:47:50 +00:00
parent
bade0a85e7
commit
3e460211c8
@ -6,6 +6,7 @@
|
|||||||
<capture/>
|
<capture/>
|
||||||
<event/>
|
<event/>
|
||||||
<nic/>
|
<nic/>
|
||||||
|
<uplink/>
|
||||||
</provides>
|
</provides>
|
||||||
|
|
||||||
<config>
|
<config>
|
||||||
@ -14,6 +15,7 @@
|
|||||||
<capture/>
|
<capture/>
|
||||||
<event/>
|
<event/>
|
||||||
<nic/>
|
<nic/>
|
||||||
|
<uplink/>
|
||||||
</config>
|
</config>
|
||||||
|
|
||||||
<content>
|
<content>
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
<start name="black_hole" caps="100">
|
<start name="black_hole" caps="100">
|
||||||
<resource name="RAM" quantum="1M"/>
|
<resource name="RAM" quantum="1M"/>
|
||||||
<provides>
|
<provides>
|
||||||
|
<service name="Uplink"/>
|
||||||
<service name="Nic"/>
|
<service name="Nic"/>
|
||||||
<service name="Event"/>
|
<service name="Event"/>
|
||||||
<service name="Capture"/>
|
<service name="Capture"/>
|
||||||
@ -37,6 +38,7 @@
|
|||||||
<service name="Audio_out"/>
|
<service name="Audio_out"/>
|
||||||
</provides>
|
</provides>
|
||||||
<config>
|
<config>
|
||||||
|
<uplink/>
|
||||||
<nic/>
|
<nic/>
|
||||||
<event/>
|
<event/>
|
||||||
<capture/>
|
<capture/>
|
||||||
@ -55,6 +57,7 @@
|
|||||||
<start name="test-black_hole" caps="100">
|
<start name="test-black_hole" caps="100">
|
||||||
<resource name="RAM" quantum="10M"/>
|
<resource name="RAM" quantum="10M"/>
|
||||||
<route>
|
<route>
|
||||||
|
<service name="Uplink"> <child name="black_hole"/> </service>
|
||||||
<service name="Nic"> <child name="black_hole"/> </service>
|
<service name="Nic"> <child name="black_hole"/> </service>
|
||||||
<service name="Event"> <child name="black_hole"/> </service>
|
<service name="Event"> <child name="black_hole"/> </service>
|
||||||
<service name="Capture"> <child name="black_hole"/> </service>
|
<service name="Capture"> <child name="black_hole"/> </service>
|
||||||
|
@ -4,4 +4,5 @@ audio_out_session
|
|||||||
capture_session
|
capture_session
|
||||||
event_session
|
event_session
|
||||||
nic_session
|
nic_session
|
||||||
|
uplink_session
|
||||||
os
|
os
|
||||||
|
@ -6,3 +6,4 @@ audio_out_session
|
|||||||
event_session
|
event_session
|
||||||
capture_session
|
capture_session
|
||||||
nic_session
|
nic_session
|
||||||
|
uplink_session
|
||||||
|
@ -9,6 +9,7 @@ in the configuration of the component:
|
|||||||
* Capture
|
* Capture
|
||||||
* Event
|
* Event
|
||||||
* Nic
|
* Nic
|
||||||
|
* Uplink
|
||||||
|
|
||||||
<config>
|
<config>
|
||||||
<audio_in/>
|
<audio_in/>
|
||||||
@ -16,4 +17,5 @@ in the configuration of the component:
|
|||||||
<capture/>
|
<capture/>
|
||||||
<event/>
|
<event/>
|
||||||
<nic/>
|
<nic/>
|
||||||
|
<uplink/>
|
||||||
</config>
|
</config>
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
<xs:element name="config">
|
<xs:element name="config">
|
||||||
<xs:complexType>
|
<xs:complexType>
|
||||||
<xs:choice minOccurs="0" maxOccurs="unbounded">
|
<xs:choice minOccurs="0" maxOccurs="unbounded">
|
||||||
|
<xs:element name="uplink"/>
|
||||||
<xs:element name="nic"/>
|
<xs:element name="nic"/>
|
||||||
<xs:element name="event"/>
|
<xs:element name="event"/>
|
||||||
<xs:element name="capture"/>
|
<xs:element name="capture"/>
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include "capture.h"
|
#include "capture.h"
|
||||||
#include "event.h"
|
#include "event.h"
|
||||||
#include "nic.h"
|
#include "nic.h"
|
||||||
|
#include "uplink.h"
|
||||||
|
|
||||||
|
|
||||||
/***************
|
/***************
|
||||||
@ -45,6 +46,7 @@ struct Black_hole::Main
|
|||||||
Genode::Constructible<Capture::Root> capture_root { };
|
Genode::Constructible<Capture::Root> capture_root { };
|
||||||
Genode::Constructible<Event_root> event_root { };
|
Genode::Constructible<Event_root> event_root { };
|
||||||
Genode::Constructible<Nic_root> nic_root { };
|
Genode::Constructible<Nic_root> nic_root { };
|
||||||
|
Genode::Constructible<Uplink_root> uplink_root { };
|
||||||
|
|
||||||
Main(Genode::Env &env) : env(env)
|
Main(Genode::Env &env) : env(env)
|
||||||
{
|
{
|
||||||
@ -73,6 +75,11 @@ struct Black_hole::Main
|
|||||||
nic_root.construct(env, heap);
|
nic_root.construct(env, heap);
|
||||||
env.parent().announce(env.ep().manage(*nic_root));
|
env.parent().announce(env.ep().manage(*nic_root));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_config_rom.xml().has_sub_node("uplink")) {
|
||||||
|
uplink_root.construct(env, heap);
|
||||||
|
env.parent().announce(env.ep().manage(*uplink_root));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
171
repos/os/src/server/black_hole/uplink.h
Normal file
171
repos/os/src/server/black_hole/uplink.h
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
/*
|
||||||
|
* \brief Uplink 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 _UPLINK_H_
|
||||||
|
#define _UPLINK_H_
|
||||||
|
|
||||||
|
/* base includes */
|
||||||
|
#include <base/ram_allocator.h>
|
||||||
|
#include <root/component.h>
|
||||||
|
|
||||||
|
/* os includes */
|
||||||
|
#include <nic/packet_allocator.h>
|
||||||
|
#include <uplink_session/rpc_object.h>
|
||||||
|
|
||||||
|
namespace Black_hole {
|
||||||
|
|
||||||
|
using namespace Genode;
|
||||||
|
|
||||||
|
class Uplink_session_base;
|
||||||
|
class Uplink_session;
|
||||||
|
class Uplink_root;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class Black_hole::Uplink_session_base
|
||||||
|
{
|
||||||
|
friend class Uplink_session;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
class Buffer
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
Ram_allocator &_ram_alloc;
|
||||||
|
Ram_dataspace_capability _ram_ds;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Buffer(Ram_allocator &ram_alloc,
|
||||||
|
size_t const size)
|
||||||
|
:
|
||||||
|
_ram_alloc { ram_alloc },
|
||||||
|
_ram_ds { ram_alloc.alloc(size) }
|
||||||
|
{ }
|
||||||
|
|
||||||
|
~Buffer() { _ram_alloc.free(_ram_ds); }
|
||||||
|
|
||||||
|
Dataspace_capability ds() const { return _ram_ds; }
|
||||||
|
};
|
||||||
|
|
||||||
|
Env &_env;
|
||||||
|
Allocator &_alloc;
|
||||||
|
Nic::Packet_allocator _packet_alloc;
|
||||||
|
Buffer _tx_buf;
|
||||||
|
Buffer _rx_buf;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Uplink_session_base(Env &env,
|
||||||
|
size_t tx_buf_size,
|
||||||
|
size_t rx_buf_size,
|
||||||
|
Allocator &alloc)
|
||||||
|
:
|
||||||
|
_env { env },
|
||||||
|
_alloc { alloc },
|
||||||
|
_packet_alloc { &_alloc },
|
||||||
|
_tx_buf { _env.ram(), tx_buf_size },
|
||||||
|
_rx_buf { _env.ram(), rx_buf_size }
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Black_hole::Uplink_session : private Uplink_session_base,
|
||||||
|
public Uplink::Session_rpc_object
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
Signal_handler<Uplink_session> _packet_stream_handler;
|
||||||
|
|
||||||
|
void _handle_packet_stream()
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Uplink_session(Env &env,
|
||||||
|
size_t tx_buf_size,
|
||||||
|
size_t rx_buf_size,
|
||||||
|
Allocator &alloc)
|
||||||
|
:
|
||||||
|
Uplink_session_base { env, tx_buf_size,rx_buf_size, alloc },
|
||||||
|
Session_rpc_object {
|
||||||
|
_env.rm(), _tx_buf.ds(), _rx_buf.ds() ,&_packet_alloc,
|
||||||
|
_env.ep().rpc_ep() },
|
||||||
|
|
||||||
|
_packet_stream_handler {
|
||||||
|
env.ep(), *this, &Uplink_session::_handle_packet_stream }
|
||||||
|
{
|
||||||
|
_tx.sigh_ready_to_ack (_packet_stream_handler);
|
||||||
|
_tx.sigh_packet_avail (_packet_stream_handler);
|
||||||
|
_rx.sigh_ack_avail (_packet_stream_handler);
|
||||||
|
_rx.sigh_ready_to_submit(_packet_stream_handler);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Black_hole::Uplink_root : public Root_component<Uplink_session>
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
Env &_env;
|
||||||
|
|
||||||
|
Uplink_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(Uplink_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())
|
||||||
|
Uplink_session(_env, tx_buf_size, rx_buf_size, *md_alloc());
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Uplink_root(Env &env,
|
||||||
|
Allocator &alloc)
|
||||||
|
:
|
||||||
|
Root_component<Uplink_session> { &env.ep().rpc_ep(), &alloc },
|
||||||
|
_env { env }
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* _UPLINK_H_ */
|
@ -14,12 +14,14 @@
|
|||||||
/* base includes */
|
/* base includes */
|
||||||
#include <base/component.h>
|
#include <base/component.h>
|
||||||
#include <base/heap.h>
|
#include <base/heap.h>
|
||||||
|
#include <util/reconstructible.h>
|
||||||
|
|
||||||
/* os includes */
|
/* os includes */
|
||||||
#include <event_session/connection.h>
|
#include <event_session/connection.h>
|
||||||
#include <capture_session/connection.h>
|
#include <capture_session/connection.h>
|
||||||
#include <audio_in_session/connection.h>
|
#include <audio_in_session/connection.h>
|
||||||
#include <audio_out_session/connection.h>
|
#include <audio_out_session/connection.h>
|
||||||
|
#include <uplink_session/connection.h>
|
||||||
#include <nic_session/connection.h>
|
#include <nic_session/connection.h>
|
||||||
#include <nic/packet_allocator.h>
|
#include <nic/packet_allocator.h>
|
||||||
#include <base/allocator_avl.h>
|
#include <base/allocator_avl.h>
|
||||||
@ -40,30 +42,99 @@ class Test::Main
|
|||||||
enum {
|
enum {
|
||||||
NIC_BUF_SIZE = Nic::Packet_allocator::DEFAULT_PACKET_SIZE * 128,
|
NIC_BUF_SIZE = Nic::Packet_allocator::DEFAULT_PACKET_SIZE * 128,
|
||||||
NIC_PKT_SIZE = 100,
|
NIC_PKT_SIZE = 100,
|
||||||
|
UPLINK_BUF_SIZE = Nic::Packet_allocator::DEFAULT_PACKET_SIZE * 128,
|
||||||
|
UPLINK_PKT_SIZE = 100,
|
||||||
};
|
};
|
||||||
|
|
||||||
Env &_env;
|
Env &_env;
|
||||||
Heap _heap { _env.ram(), _env.rm() };
|
Heap _heap { _env.ram(), _env.rm() };
|
||||||
Event::Connection _event { _env };
|
Event::Connection _event { _env };
|
||||||
Capture::Connection _capture { _env };
|
Capture::Connection _capture { _env };
|
||||||
Capture::Area _capture_screen_size { 1, 1 };
|
Capture::Area _capture_screen_size { 1, 1 };
|
||||||
Capture::Pixel _capture_pixels[1];
|
Capture::Pixel _capture_pixels[1];
|
||||||
Surface<Capture::Pixel> _capture_surface { _capture_pixels, _capture_screen_size };
|
Surface<Capture::Pixel> _capture_surface { _capture_pixels, _capture_screen_size };
|
||||||
Capture::Connection::Screen _capture_screen { _capture, _env.rm(), _capture_screen_size };
|
Capture::Connection::Screen _capture_screen { _capture, _env.rm(), _capture_screen_size };
|
||||||
Audio_in::Connection _audio_in { _env, "left" };
|
Audio_in::Connection _audio_in { _env, "left" };
|
||||||
Audio_out::Connection _audio_out { _env, "left" };
|
Audio_out::Connection _audio_out { _env, "left" };
|
||||||
Allocator_avl _nic_tx_blk_alloc { &_heap };
|
Allocator_avl _nic_tx_blk_alloc { &_heap };
|
||||||
Nic::Connection _nic { _env, &_nic_tx_blk_alloc, NIC_BUF_SIZE, NIC_BUF_SIZE };
|
Nic::Connection _nic { _env, &_nic_tx_blk_alloc, NIC_BUF_SIZE, NIC_BUF_SIZE };
|
||||||
Signal_handler<Main> _nic_handler { _env.ep(), *this, &Main::_handle_nic };
|
Signal_handler<Main> _nic_handler { _env.ep(), *this, &Main::_handle_nic };
|
||||||
unsigned long _nic_pkt_count { 0 };
|
unsigned long _nic_pkt_count { 0 };
|
||||||
|
Allocator_avl _uplink_tx_blk_alloc { &_heap };
|
||||||
|
Constructible<Uplink::Connection> _uplink { };
|
||||||
|
Signal_handler<Main> _uplink_handler { _env.ep(), *this, &Main::_handle_uplink };
|
||||||
|
unsigned long _uplink_pkt_count { 0 };
|
||||||
|
|
||||||
void _check_if_test_has_finished()
|
void _check_if_test_has_finished()
|
||||||
{
|
{
|
||||||
if (_nic_pkt_count > 100) {
|
if (_nic_pkt_count > 100 &&
|
||||||
|
_uplink_pkt_count > 100) {
|
||||||
|
|
||||||
log("Finished");
|
log("Finished");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _reconstruct_uplink()
|
||||||
|
{
|
||||||
|
_uplink.destruct();
|
||||||
|
_uplink.construct(
|
||||||
|
_env, &_uplink_tx_blk_alloc, UPLINK_BUF_SIZE,
|
||||||
|
UPLINK_BUF_SIZE, Net::Mac_address { 2 });
|
||||||
|
|
||||||
|
_uplink->tx_channel()->sigh_ready_to_submit(_uplink_handler);
|
||||||
|
_uplink->tx_channel()->sigh_ack_avail(_uplink_handler);
|
||||||
|
_uplink->rx_channel()->sigh_ready_to_ack(_uplink_handler);
|
||||||
|
_uplink->rx_channel()->sigh_packet_avail(_uplink_handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _handle_uplink()
|
||||||
|
{
|
||||||
|
if (!_uplink.constructed()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (_uplink->rx()->packet_avail()) {
|
||||||
|
class Uplink_rx_packet_avail { };
|
||||||
|
throw Uplink_rx_packet_avail { };
|
||||||
|
}
|
||||||
|
if (!_uplink->rx()->ack_slots_free()) {
|
||||||
|
class Uplink_no_rx_ack_slots_free { };
|
||||||
|
throw Uplink_no_rx_ack_slots_free { };
|
||||||
|
}
|
||||||
|
while (_uplink->tx()->ack_avail()) {
|
||||||
|
|
||||||
|
Packet_descriptor const pkt { _uplink->tx()->get_acked_packet() };
|
||||||
|
if (pkt.size() != UPLINK_PKT_SIZE) {
|
||||||
|
class Uplink_packet_size_unexpected { };
|
||||||
|
throw Uplink_packet_size_unexpected { };
|
||||||
|
}
|
||||||
|
_uplink->tx()->release_packet(pkt);
|
||||||
|
_uplink_pkt_count++;
|
||||||
|
}
|
||||||
|
_submit_uplink_pkts();
|
||||||
|
_check_if_test_has_finished();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _submit_uplink_pkts()
|
||||||
|
{
|
||||||
|
for (unsigned idx { 0 }; idx < 40; idx++) {
|
||||||
|
|
||||||
|
if (idx == 10) {
|
||||||
|
_reconstruct_uplink();
|
||||||
|
}
|
||||||
|
if (!_uplink->tx()->ready_to_submit()) {
|
||||||
|
class Uplink_submit_queue_full { };
|
||||||
|
throw Uplink_submit_queue_full { };
|
||||||
|
}
|
||||||
|
Packet_descriptor pkt;
|
||||||
|
try { pkt = _uplink->tx()->alloc_packet(UPLINK_PKT_SIZE); }
|
||||||
|
catch (...) {
|
||||||
|
class Uplink_packet_alloc_failed { };
|
||||||
|
throw Uplink_packet_alloc_failed { };
|
||||||
|
}
|
||||||
|
_uplink->tx()->submit_packet(pkt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void _handle_nic()
|
void _handle_nic()
|
||||||
{
|
{
|
||||||
if (_nic.rx()->packet_avail()) {
|
if (_nic.rx()->packet_avail()) {
|
||||||
@ -110,6 +181,10 @@ class Test::Main
|
|||||||
|
|
||||||
Main(Env &env) : _env { env }
|
Main(Env &env) : _env { env }
|
||||||
{
|
{
|
||||||
|
/* test-drive uplink connection */
|
||||||
|
_reconstruct_uplink();
|
||||||
|
_submit_uplink_pkts();
|
||||||
|
|
||||||
/* test-drive nic connection */
|
/* test-drive nic connection */
|
||||||
_nic.tx_channel()->sigh_ready_to_submit(_nic_handler);
|
_nic.tx_channel()->sigh_ready_to_submit(_nic_handler);
|
||||||
_nic.tx_channel()->sigh_ack_avail(_nic_handler);
|
_nic.tx_channel()->sigh_ack_avail(_nic_handler);
|
||||||
|
Loading…
Reference in New Issue
Block a user