2016-08-25 17:48:53 +02:00
|
|
|
/*
|
|
|
|
* \brief Downlink interface in form of a NIC session component
|
|
|
|
* \author Martin Stein
|
|
|
|
* \date 2016-08-23
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
2017-01-13 19:38:23 +01:00
|
|
|
* Copyright (C) 2016-2017 Genode Labs GmbH
|
2016-08-25 17:48:53 +02:00
|
|
|
*
|
|
|
|
* This file is part of the Genode OS framework, which is distributed
|
2017-02-20 13:23:52 +01:00
|
|
|
* under the terms of the GNU Affero General Public License version 3.
|
2016-08-25 17:48:53 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef _COMPONENT_H_
|
|
|
|
#define _COMPONENT_H_
|
|
|
|
|
|
|
|
/* Genode includes */
|
2018-09-16 14:21:38 +02:00
|
|
|
#include <base/heap.h>
|
2016-09-12 12:55:12 +02:00
|
|
|
#include <base/allocator_guard.h>
|
2016-08-25 17:48:53 +02:00
|
|
|
#include <root/component.h>
|
|
|
|
#include <nic/packet_allocator.h>
|
|
|
|
#include <nic_session/rpc_object.h>
|
|
|
|
|
|
|
|
/* local includes */
|
2019-10-03 20:30:26 +02:00
|
|
|
#include "mac_allocator.h"
|
|
|
|
#include "interface.h"
|
|
|
|
#include "reference.h"
|
|
|
|
#include "report.h"
|
2018-09-16 14:21:38 +02:00
|
|
|
|
|
|
|
namespace Genode { class Session_env; }
|
2016-08-25 17:48:53 +02:00
|
|
|
|
|
|
|
namespace Net {
|
|
|
|
|
|
|
|
class Communication_buffer;
|
2016-09-12 12:55:12 +02:00
|
|
|
class Session_component_base;
|
2016-08-25 17:48:53 +02:00
|
|
|
class Session_component;
|
|
|
|
class Root;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-09-16 14:21:38 +02:00
|
|
|
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 <typename FUNC>
|
|
|
|
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 <typename FUNC>
|
|
|
|
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
|
2016-08-25 17:48:53 +02:00
|
|
|
{
|
|
|
|
private:
|
|
|
|
|
2018-09-16 14:21:38 +02:00
|
|
|
Genode::Ram_allocator &_ram_alloc;
|
|
|
|
Genode::Ram_dataspace_capability _ram_ds;
|
2016-08-25 17:48:53 +02:00
|
|
|
|
|
|
|
public:
|
|
|
|
|
2018-09-16 14:21:38 +02:00
|
|
|
Communication_buffer(Genode::Ram_allocator &ram_alloc,
|
|
|
|
Genode::size_t const size);
|
|
|
|
|
|
|
|
~Communication_buffer() { _ram_alloc.free(_ram_ds); }
|
2016-08-25 17:48:53 +02:00
|
|
|
|
2018-09-16 14:21:38 +02:00
|
|
|
|
|
|
|
/***************
|
|
|
|
** Accessors **
|
|
|
|
***************/
|
|
|
|
|
|
|
|
Genode::Dataspace_capability ds() const { return _ram_ds; }
|
2016-08-25 17:48:53 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2016-09-12 12:55:12 +02:00
|
|
|
class Net::Session_component_base
|
2016-08-25 17:48:53 +02:00
|
|
|
{
|
2016-09-12 12:55:12 +02:00
|
|
|
protected:
|
2016-08-25 17:48:53 +02:00
|
|
|
|
2018-09-16 14:21:38 +02:00
|
|
|
Genode::Session_env &_session_env;
|
|
|
|
Genode::Heap _alloc;
|
|
|
|
Nic::Packet_allocator _packet_alloc;
|
|
|
|
Communication_buffer _tx_buf;
|
|
|
|
Communication_buffer _rx_buf;
|
2018-06-07 16:17:08 +02:00
|
|
|
|
|
|
|
public:
|
|
|
|
|
2018-09-16 14:21:38 +02:00
|
|
|
Session_component_base(Genode::Session_env &session_env,
|
|
|
|
Genode::size_t const tx_buf_size,
|
|
|
|
Genode::size_t const rx_buf_size);
|
2018-06-07 16:17:08 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class Net::Session_component : private Session_component_base,
|
|
|
|
public ::Nic::Session_rpc_object
|
|
|
|
{
|
|
|
|
private:
|
|
|
|
|
2018-02-07 18:38:49 +01:00
|
|
|
struct Interface_policy : Net::Interface_policy
|
|
|
|
{
|
2018-03-19 19:16:17 +01:00
|
|
|
private:
|
2018-02-07 18:38:49 +01:00
|
|
|
|
2018-09-16 14:21:38 +02:00
|
|
|
Genode::Session_label const _label;
|
|
|
|
Const_reference<Configuration> _config;
|
|
|
|
Genode::Session_env const &_session_env;
|
2018-02-07 18:38:49 +01:00
|
|
|
|
2018-03-19 19:16:17 +01:00
|
|
|
public:
|
2018-02-07 18:38:49 +01:00
|
|
|
|
2018-03-19 19:16:17 +01:00
|
|
|
Interface_policy(Genode::Session_label const &label,
|
2018-09-16 14:21:38 +02:00
|
|
|
Genode::Session_env const &session_env,
|
2018-03-19 19:16:17 +01:00
|
|
|
Configuration const &config);
|
2018-02-07 18:38:49 +01:00
|
|
|
|
2018-03-19 19:16:17 +01:00
|
|
|
|
|
|
|
/***************************
|
|
|
|
** Net::Interface_policy **
|
|
|
|
***************************/
|
|
|
|
|
|
|
|
Domain_name determine_domain_name() const override;
|
|
|
|
void handle_config(Configuration const &config) override { _config = config; }
|
2018-09-16 14:21:38 +02:00
|
|
|
Genode::Session_label const &label() const override { return _label; }
|
|
|
|
void report(Genode::Xml_generator &xml) const override { _session_env.report(xml); };
|
2018-02-07 18:38:49 +01:00
|
|
|
};
|
|
|
|
|
2018-09-16 14:21:38 +02:00
|
|
|
bool _link_state { true };
|
|
|
|
Interface_policy _interface_policy;
|
|
|
|
Interface _interface;
|
|
|
|
Genode::Ram_dataspace_capability const _ram_ds;
|
2016-08-25 17:48:53 +02:00
|
|
|
|
|
|
|
public:
|
|
|
|
|
2018-09-16 14:21:38 +02:00
|
|
|
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);
|
2016-08-25 17:48:53 +02:00
|
|
|
|
|
|
|
|
|
|
|
/******************
|
|
|
|
** Nic::Session **
|
|
|
|
******************/
|
|
|
|
|
2018-06-07 16:17:08 +02:00
|
|
|
Mac_address mac_address() override { return _interface.mac(); }
|
|
|
|
bool link_state() override { return _interface.link_state(); }
|
|
|
|
void link_state_sigh(Genode::Signal_context_capability sigh) override {
|
|
|
|
_interface.session_link_state_sigh(sigh); }
|
2018-09-16 14:21:38 +02:00
|
|
|
|
|
|
|
|
|
|
|
/***************
|
|
|
|
** 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; };
|
2016-08-25 17:48:53 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class Net::Root : public Genode::Root_component<Session_component>
|
|
|
|
{
|
|
|
|
private:
|
|
|
|
|
2018-04-27 14:00:07 +02:00
|
|
|
enum { MAC_ALLOC_BASE = 0x02 };
|
|
|
|
|
2018-09-16 14:21:38 +02:00
|
|
|
Genode::Env &_env;
|
2018-03-19 19:16:17 +01:00
|
|
|
Timer::Connection &_timer;
|
2018-04-27 13:38:49 +02:00
|
|
|
Mac_allocator _mac_alloc;
|
2018-09-16 14:21:38 +02:00
|
|
|
Mac_address const _router_mac;
|
2018-03-19 19:16:17 +01:00
|
|
|
Reference<Configuration> _config;
|
2018-09-16 14:21:38 +02:00
|
|
|
Quota &_shared_quota;
|
2018-03-19 19:16:17 +01:00
|
|
|
Interface_list &_interfaces;
|
2016-08-25 17:48:53 +02:00
|
|
|
|
2018-06-13 13:28:22 +02:00
|
|
|
void _invalid_downlink(char const *reason);
|
|
|
|
|
2016-08-25 17:48:53 +02:00
|
|
|
|
|
|
|
/********************
|
|
|
|
** Root_component **
|
|
|
|
********************/
|
|
|
|
|
2018-03-22 19:06:36 +01:00
|
|
|
Session_component *_create_session(char const *args) override;
|
2018-09-16 14:21:38 +02:00
|
|
|
void _destroy_session(Session_component *session) override;
|
2016-08-25 17:48:53 +02:00
|
|
|
|
|
|
|
public:
|
|
|
|
|
2018-09-16 14:21:38 +02:00
|
|
|
Root(Genode::Env &env,
|
|
|
|
Timer::Connection &timer,
|
|
|
|
Genode::Allocator &alloc,
|
|
|
|
Configuration &config,
|
|
|
|
Quota &shared_quota,
|
|
|
|
Interface_list &interfaces);
|
2018-03-19 19:16:17 +01:00
|
|
|
|
|
|
|
void handle_config(Configuration &config) { _config = Reference<Configuration>(config); }
|
2016-08-25 17:48:53 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
#endif /* _COMPONENT_H_ */
|