mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-18 18:56:29 +00:00
nic_router: handle configuration changes
The router reacts as follows to a configuration change: 1) Construct new internal configuration representation (the old one stays in place to be able to do comparisons in the following steps) 2) Iterate through all user-dependent objects (interfaces, link states, ARP information, DHCP information) and re-check which remain valid with the new configuration and which must be dismissed. 3) Adapt the objects that remain valid to the new configuration (re-write references) and remove or detach the dismissed objects. 4) Do a link state DOWN at each interface and a link state UP at each interface that remains attached to a domain. 5) Replace the old internal configuration representation with the new one This way, the router keeps as much user dependent states as possible while going through a configuration change. Thus, overwriting the old configuration with an exact copy of itself is (almost) transparent to clients of the router. Almost, because there are things the router must do on every configuration handling, like re-scheduling the expiration timeouts of links. Ref #2670
This commit is contained in:
parent
4e8453b7bf
commit
92a30e0953
@ -29,12 +29,26 @@ Arp_waiter::Arp_waiter(Interface &src,
|
||||
_packet(packet)
|
||||
{
|
||||
_src.own_arp_waiters().insert(&_src_le);
|
||||
_dst.foreign_arp_waiters().insert(&_dst_le);
|
||||
_dst().foreign_arp_waiters().insert(&_dst_le);
|
||||
}
|
||||
|
||||
|
||||
Arp_waiter::~Arp_waiter()
|
||||
{
|
||||
_src.own_arp_waiters().remove(&_src_le);
|
||||
_dst.foreign_arp_waiters().remove(&_dst_le);
|
||||
_dst().foreign_arp_waiters().remove(&_dst_le);
|
||||
}
|
||||
|
||||
|
||||
void Arp_waiter::handle_config(Domain &dst)
|
||||
{
|
||||
_dst().foreign_arp_waiters().remove(&_dst_le);
|
||||
_dst = dst;
|
||||
_dst().foreign_arp_waiters().insert(&_dst_le);
|
||||
}
|
||||
|
||||
|
||||
void Arp_waiter::print(Output &output) const
|
||||
{
|
||||
Genode::print(output, "IP ", _ip, " DST ", _dst());
|
||||
}
|
||||
|
@ -14,6 +14,10 @@
|
||||
#ifndef _ARP_WAITER_H_
|
||||
#define _ARP_WAITER_H_
|
||||
|
||||
/* local includes */
|
||||
#include <list.h>
|
||||
#include <reference.h>
|
||||
|
||||
/* Genode includes */
|
||||
#include <net/ipv4.h>
|
||||
#include <util/list.h>
|
||||
@ -24,9 +28,10 @@ namespace Net {
|
||||
using Packet_descriptor = ::Nic::Packet_descriptor;
|
||||
class Interface;
|
||||
class Domain;
|
||||
class Configuration;
|
||||
class Arp_waiter;
|
||||
using Arp_waiter_list_element = Genode::List_element<Arp_waiter>;
|
||||
using Arp_waiter_list = Genode::List<Arp_waiter_list_element >;
|
||||
using Arp_waiter_list = List<Arp_waiter_list_element>;
|
||||
}
|
||||
|
||||
|
||||
@ -37,7 +42,7 @@ class Net::Arp_waiter
|
||||
Arp_waiter_list_element _src_le;
|
||||
Interface &_src;
|
||||
Arp_waiter_list_element _dst_le;
|
||||
Domain &_dst;
|
||||
Reference<Domain> _dst;
|
||||
Ipv4_address const _ip;
|
||||
Packet_descriptor const _packet;
|
||||
|
||||
@ -50,6 +55,15 @@ class Net::Arp_waiter
|
||||
|
||||
~Arp_waiter();
|
||||
|
||||
void handle_config(Domain &dst);
|
||||
|
||||
|
||||
/*********
|
||||
** Log **
|
||||
*********/
|
||||
|
||||
void print(Genode::Output &output) const;
|
||||
|
||||
|
||||
/***************
|
||||
** Accessors **
|
||||
@ -58,6 +72,7 @@ class Net::Arp_waiter
|
||||
Interface &src() const { return _src; }
|
||||
Ipv4_address const &ip() const { return _ip; }
|
||||
Packet_descriptor const &packet() const { return _packet; }
|
||||
Domain &dst() { return _dst(); }
|
||||
};
|
||||
|
||||
#endif /* _ARP_WAITER_H_ */
|
||||
|
@ -59,7 +59,7 @@ Session_component_base(Allocator &guarded_alloc_backing,
|
||||
Net::Session_component_base::
|
||||
Interface_policy::Interface_policy(Genode::Session_label const &label,
|
||||
Configuration const &config)
|
||||
: label(label), config(config) { }
|
||||
: _label(label), _config(config) { }
|
||||
|
||||
|
||||
Domain_name
|
||||
@ -67,11 +67,11 @@ Net::Session_component_base::Interface_policy::determine_domain_name() const
|
||||
{
|
||||
Domain_name domain_name;
|
||||
try {
|
||||
Session_policy policy(label, config.node());
|
||||
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 matching policy"); } }
|
||||
catch (Xml_node::Nonexistent_attribute) { if (config.verbose()) { log("No domain attribute in policy"); } }
|
||||
catch (Session_policy::No_policy_defined) { if (_config().verbose()) { log("No matching policy"); } }
|
||||
catch (Xml_node::Nonexistent_attribute) { if (_config().verbose()) { log("No domain attribute in policy"); } }
|
||||
return domain_name;
|
||||
}
|
||||
|
||||
@ -91,12 +91,15 @@ Net::Session_component::Session_component(Allocator &alloc,
|
||||
Entrypoint &ep,
|
||||
Mac_address const &router_mac,
|
||||
Session_label const &label,
|
||||
Interface_list &interfaces,
|
||||
Configuration &config)
|
||||
:
|
||||
Session_component_base(alloc, amount, buf_ram, tx_buf_size, rx_buf_size,
|
||||
config, label),
|
||||
Session_rpc_object(region_map, _tx_buf, _rx_buf, &_range_alloc, ep.rpc_ep()),
|
||||
Interface(ep, timer, router_mac, _guarded_alloc, mac, config, _intf_policy)
|
||||
Session_rpc_object(region_map, _tx_buf, _rx_buf, &_range_alloc,
|
||||
ep.rpc_ep()),
|
||||
Interface(ep, timer, router_mac, _guarded_alloc, mac, config, interfaces,
|
||||
_intf_policy)
|
||||
{
|
||||
_tx.sigh_ready_to_ack(_sink_ack);
|
||||
_tx.sigh_packet_avail(_sink_submit);
|
||||
@ -115,11 +118,12 @@ Net::Root::Root(Entrypoint &ep,
|
||||
Mac_address const &router_mac,
|
||||
Configuration &config,
|
||||
Ram_session &buf_ram,
|
||||
Interface_list &interfaces,
|
||||
Region_map ®ion_map)
|
||||
:
|
||||
Root_component<Session_component>(&ep.rpc_ep(), &alloc), _timer(timer),
|
||||
_ep(ep), _router_mac(router_mac), _config(config), _buf_ram(buf_ram),
|
||||
_region_map(region_map)
|
||||
_region_map(region_map), _interfaces(interfaces)
|
||||
{ }
|
||||
|
||||
|
||||
@ -153,7 +157,7 @@ Session_component *Net::Root::_create_session(char const *args)
|
||||
Session_component(*md_alloc(), _timer, ram_quota - session_size,
|
||||
_buf_ram, tx_buf_size, rx_buf_size, _region_map,
|
||||
_mac_alloc.alloc(), _ep, _router_mac, label,
|
||||
_config);
|
||||
_interfaces, _config());
|
||||
}
|
||||
catch (Mac_allocator::Alloc_failed) {
|
||||
error("failed to allocate MAC address");
|
||||
|
@ -23,6 +23,7 @@
|
||||
|
||||
/* local includes */
|
||||
#include <interface.h>
|
||||
#include <reference.h>
|
||||
|
||||
namespace Net {
|
||||
|
||||
@ -54,18 +55,23 @@ class Net::Session_component_base
|
||||
|
||||
struct Interface_policy : Net::Interface_policy
|
||||
{
|
||||
Genode::Session_label const label;
|
||||
Configuration const &config;
|
||||
private:
|
||||
|
||||
Interface_policy(Genode::Session_label const &label,
|
||||
Configuration const &config);
|
||||
Genode::Session_label const _label;
|
||||
Const_reference<Configuration> _config;
|
||||
|
||||
public:
|
||||
|
||||
Interface_policy(Genode::Session_label const &label,
|
||||
Configuration const &config);
|
||||
|
||||
|
||||
/***************************
|
||||
** Net::Interface_policy **
|
||||
***************************/
|
||||
/***************************
|
||||
** Net::Interface_policy **
|
||||
***************************/
|
||||
|
||||
Domain_name determine_domain_name() const override;
|
||||
Domain_name determine_domain_name() const override;
|
||||
void handle_config(Configuration const &config) override { _config = config; }
|
||||
};
|
||||
|
||||
Genode::Allocator_guard _guarded_alloc;
|
||||
@ -112,6 +118,7 @@ class Net::Session_component : private Session_component_base,
|
||||
Genode::Entrypoint &ep,
|
||||
Mac_address const &router_mac,
|
||||
Genode::Session_label const &label,
|
||||
Interface_list &interfaces,
|
||||
Configuration &config);
|
||||
|
||||
|
||||
@ -120,8 +127,8 @@ class Net::Session_component : private Session_component_base,
|
||||
******************/
|
||||
|
||||
Mac_address mac_address() { return _mac; }
|
||||
bool link_state() { return true; }
|
||||
void link_state_sigh(Genode::Signal_context_capability) { }
|
||||
bool link_state() { return Interface::link_state(); }
|
||||
void link_state_sigh(Genode::Signal_context_capability sigh) { Interface::link_state_sigh(sigh); }
|
||||
};
|
||||
|
||||
|
||||
@ -129,13 +136,14 @@ class Net::Root : public Genode::Root_component<Session_component>
|
||||
{
|
||||
private:
|
||||
|
||||
Timer::Connection &_timer;
|
||||
Mac_allocator _mac_alloc { };
|
||||
Genode::Entrypoint &_ep;
|
||||
Mac_address const _router_mac;
|
||||
Configuration &_config;
|
||||
Genode::Ram_session &_buf_ram;
|
||||
Genode::Region_map &_region_map;
|
||||
Timer::Connection &_timer;
|
||||
Mac_allocator _mac_alloc { };
|
||||
Genode::Entrypoint &_ep;
|
||||
Mac_address const _router_mac;
|
||||
Reference<Configuration> _config;
|
||||
Genode::Ram_session &_buf_ram;
|
||||
Genode::Region_map &_region_map;
|
||||
Interface_list &_interfaces;
|
||||
|
||||
|
||||
/********************
|
||||
@ -152,7 +160,10 @@ class Net::Root : public Genode::Root_component<Session_component>
|
||||
Mac_address const &router_mac,
|
||||
Configuration &config,
|
||||
Genode::Ram_session &buf_ram,
|
||||
Interface_list &interfaces,
|
||||
Genode::Region_map ®ion_map);
|
||||
|
||||
void handle_config(Configuration &config) { _config = Reference<Configuration>(config); }
|
||||
};
|
||||
|
||||
#endif /* _COMPONENT_H_ */
|
||||
|
@ -27,10 +27,19 @@ using namespace Genode;
|
||||
** Configuration **
|
||||
*******************/
|
||||
|
||||
Configuration::Configuration(Xml_node const node,
|
||||
Allocator &alloc)
|
||||
:
|
||||
_alloc(alloc),
|
||||
_node(node)
|
||||
{ }
|
||||
|
||||
|
||||
Configuration::Configuration(Env &env,
|
||||
Xml_node const node,
|
||||
Allocator &alloc,
|
||||
Timer::Connection &timer)
|
||||
Timer::Connection &timer,
|
||||
Configuration &legacy)
|
||||
:
|
||||
_alloc(alloc),
|
||||
_verbose (node.attribute_value("verbose", false)),
|
||||
@ -44,7 +53,6 @@ Configuration::Configuration(Env &env,
|
||||
_tcp_max_segm_lifetime(read_sec_attr(node, "tcp_max_segm_lifetime_sec", DEFAULT_TCP_MAX_SEGM_LIFETIME_SEC)),
|
||||
_node(node)
|
||||
{
|
||||
|
||||
/* read domains */
|
||||
node.for_each_sub_node("domain", [&] (Xml_node const node) {
|
||||
try { _domains.insert(*new (_alloc) Domain(*this, node, _alloc)); }
|
||||
@ -57,9 +65,37 @@ Configuration::Configuration(Env &env,
|
||||
|
||||
domain.create_rules(_domains);
|
||||
});
|
||||
/* if configured, create a report generator */
|
||||
try {
|
||||
_report.set(*new (_alloc) Report(env, node.sub_node("report"), timer,
|
||||
_domains));
|
||||
} catch (Genode::Xml_node::Nonexistent_sub_node) { }
|
||||
/* check whether we shall create a report generator */
|
||||
Xml_node const report_node = node.sub_node("report");
|
||||
try {
|
||||
/* try to re-use existing reporter */
|
||||
_reporter.set(legacy._reporter.deref());
|
||||
legacy._reporter.unset();
|
||||
}
|
||||
catch (Pointer<Reporter>::Invalid) {
|
||||
|
||||
/* there is no reporter by now, create a new one */
|
||||
_reporter.set(*new (_alloc) Reporter(env, "state"));
|
||||
}
|
||||
/* create report generator */
|
||||
_report.set(*new (_alloc)
|
||||
Report(report_node, timer, _domains, _reporter.deref()));
|
||||
}
|
||||
catch (Genode::Xml_node::Nonexistent_sub_node) { }
|
||||
}
|
||||
|
||||
|
||||
Configuration::~Configuration()
|
||||
{
|
||||
/* destroy reporter */
|
||||
try { destroy(_alloc, &_reporter.deref()); }
|
||||
catch (Pointer<Reporter>::Invalid) { }
|
||||
|
||||
/* destroy report generator */
|
||||
try { destroy(_alloc, &_report.deref()); }
|
||||
catch (Pointer<Report>::Invalid) { }
|
||||
|
||||
/* destroy domains */
|
||||
_domains.destroy_each(_alloc);
|
||||
}
|
||||
|
@ -31,18 +31,18 @@ class Net::Configuration
|
||||
private:
|
||||
|
||||
Genode::Allocator &_alloc;
|
||||
bool const _verbose;
|
||||
bool const _verbose_packets;
|
||||
bool const _verbose_domain_state;
|
||||
Genode::Microseconds const _dhcp_discover_timeout;
|
||||
Genode::Microseconds const _dhcp_request_timeout;
|
||||
Genode::Microseconds const _dhcp_offer_timeout;
|
||||
Genode::Microseconds const _udp_idle_timeout;
|
||||
Genode::Microseconds const _tcp_idle_timeout;
|
||||
Genode::Microseconds const _tcp_max_segm_lifetime;
|
||||
Pointer<Report> _report { };
|
||||
Domain_tree _domains { };
|
||||
List<Interface> _detached_interfaces { };
|
||||
bool const _verbose { false };
|
||||
bool const _verbose_packets { false };
|
||||
bool const _verbose_domain_state { false };
|
||||
Genode::Microseconds const _dhcp_discover_timeout { DEFAULT_DHCP_DISCOVER_TIMEOUT_SEC };
|
||||
Genode::Microseconds const _dhcp_request_timeout { DEFAULT_DHCP_REQUEST_TIMEOUT_SEC };
|
||||
Genode::Microseconds const _dhcp_offer_timeout { DEFAULT_DHCP_OFFER_TIMEOUT_SEC };
|
||||
Genode::Microseconds const _udp_idle_timeout { DEFAULT_UDP_IDLE_TIMEOUT_SEC };
|
||||
Genode::Microseconds const _tcp_idle_timeout { DEFAULT_TCP_IDLE_TIMEOUT_SEC };
|
||||
Genode::Microseconds const _tcp_max_segm_lifetime { DEFAULT_TCP_MAX_SEGM_LIFETIME_SEC };
|
||||
Pointer<Report> _report { };
|
||||
Pointer<Genode::Reporter> _reporter { };
|
||||
Domain_tree _domains { };
|
||||
Genode::Xml_node const _node;
|
||||
|
||||
public:
|
||||
@ -55,10 +55,16 @@ class Net::Configuration
|
||||
enum { DEFAULT_TCP_IDLE_TIMEOUT_SEC = 600 };
|
||||
enum { DEFAULT_TCP_MAX_SEGM_LIFETIME_SEC = 30 };
|
||||
|
||||
Configuration(Genode::Xml_node const node,
|
||||
Genode::Allocator &alloc);
|
||||
|
||||
Configuration(Genode::Env &env,
|
||||
Genode::Xml_node const node,
|
||||
Genode::Allocator &alloc,
|
||||
Timer::Connection &timer);
|
||||
Timer::Connection &timer,
|
||||
Configuration &legacy);
|
||||
|
||||
~Configuration();
|
||||
|
||||
|
||||
/***************
|
||||
@ -75,7 +81,6 @@ class Net::Configuration
|
||||
Genode::Microseconds tcp_idle_timeout() const { return _tcp_idle_timeout; }
|
||||
Genode::Microseconds tcp_max_segm_lifetime() const { return _tcp_max_segm_lifetime; }
|
||||
Domain_tree &domains() { return _domains; }
|
||||
List<Interface> &detached_interfaces() { return _detached_interfaces; }
|
||||
Report &report() { return _report.deref(); }
|
||||
Genode::Xml_node node() const { return _node; }
|
||||
};
|
||||
|
@ -36,11 +36,11 @@ class Net::Dhcp_client
|
||||
INIT = 0, SELECT = 1, REQUEST = 2, BOUND = 3, RENEW = 4, REBIND = 5
|
||||
};
|
||||
|
||||
Genode::Allocator &_alloc;
|
||||
Interface &_interface;
|
||||
State _state { State::INIT };
|
||||
Timer::One_shot_timeout<Dhcp_client> _timeout;
|
||||
unsigned long _lease_time_sec = 0;
|
||||
Genode::Allocator &_alloc;
|
||||
Interface &_interface;
|
||||
State _state { State::INIT };
|
||||
Timer::One_shot_timeout<Dhcp_client> _timeout;
|
||||
unsigned long _lease_time_sec = 0;
|
||||
|
||||
void _handle_dhcp_reply(Dhcp_packet &dhcp);
|
||||
|
||||
|
@ -80,6 +80,14 @@ Ipv4_address Dhcp_server::alloc_ip()
|
||||
}
|
||||
|
||||
|
||||
void Dhcp_server::alloc_ip(Ipv4_address const &ip)
|
||||
{
|
||||
try { _ip_alloc.alloc_addr(ip.to_uint32_little_endian() - _ip_first_raw); }
|
||||
catch (Bit_allocator_dynamic::Range_conflict) { throw Alloc_ip_failed(); }
|
||||
catch (Bit_array_dynamic::Invalid_index_access) { throw Alloc_ip_failed(); }
|
||||
}
|
||||
|
||||
|
||||
void Dhcp_server::free_ip(Ipv4_address const &ip)
|
||||
{
|
||||
_ip_alloc.free(ip.to_uint32_little_endian() - _ip_first_raw);
|
||||
@ -147,8 +155,8 @@ void Dhcp_allocation::_handle_timeout(Duration)
|
||||
Dhcp_allocation &
|
||||
Dhcp_allocation_tree::find_by_mac(Mac_address const &mac) const
|
||||
{
|
||||
if (!first()) {
|
||||
if (!_tree.first()) {
|
||||
throw No_match(); }
|
||||
|
||||
return first()->find_by_mac(mac);
|
||||
return _tree.first()->find_by_mac(mac);
|
||||
}
|
||||
|
@ -17,6 +17,7 @@
|
||||
/* local includes */
|
||||
#include <ipv4_address_prefix.h>
|
||||
#include <bit_allocator_dynamic.h>
|
||||
#include <list.h>
|
||||
|
||||
/* Genode includes */
|
||||
#include <net/mac_address.h>
|
||||
@ -30,7 +31,7 @@ namespace Net {
|
||||
class Dhcp_allocation;
|
||||
class Dhcp_allocation;
|
||||
class Dhcp_allocation_tree;
|
||||
using Dhcp_allocation_list = Genode::List<Dhcp_allocation>;
|
||||
using Dhcp_allocation_list = List<Dhcp_allocation>;
|
||||
|
||||
/* forward declarations */
|
||||
class Interface;
|
||||
@ -64,6 +65,8 @@ class Net::Dhcp_server : private Genode::Noncopyable
|
||||
|
||||
Ipv4_address alloc_ip();
|
||||
|
||||
void alloc_ip(Ipv4_address const &ip);
|
||||
|
||||
void free_ip(Ipv4_address const &ip);
|
||||
|
||||
|
||||
@ -83,14 +86,6 @@ class Net::Dhcp_server : private Genode::Noncopyable
|
||||
};
|
||||
|
||||
|
||||
struct Net::Dhcp_allocation_tree : public Genode::Avl_tree<Dhcp_allocation>
|
||||
{
|
||||
struct No_match : Genode::Exception { };
|
||||
|
||||
Dhcp_allocation &find_by_mac(Mac_address const &mac) const;
|
||||
};
|
||||
|
||||
|
||||
class Net::Dhcp_allocation : public Genode::Avl_node<Dhcp_allocation>,
|
||||
public Dhcp_allocation_list::Element
|
||||
{
|
||||
@ -143,4 +138,45 @@ class Net::Dhcp_allocation : public Genode::Avl_node<Dhcp_allocation>,
|
||||
void set_bound() { _bound = true; }
|
||||
};
|
||||
|
||||
|
||||
struct Net::Dhcp_allocation_tree
|
||||
{
|
||||
private:
|
||||
|
||||
Genode::Avl_tree<Dhcp_allocation> _tree { };
|
||||
Dhcp_allocation_list _list { };
|
||||
|
||||
public:
|
||||
|
||||
struct No_match : Genode::Exception { };
|
||||
|
||||
Dhcp_allocation &find_by_mac(Mac_address const &mac) const;
|
||||
|
||||
void insert(Dhcp_allocation &dhcp_alloc)
|
||||
{
|
||||
_tree.insert(&dhcp_alloc);
|
||||
_list.insert(&dhcp_alloc);
|
||||
}
|
||||
|
||||
void remove(Dhcp_allocation &dhcp_alloc)
|
||||
{
|
||||
_tree.remove(&dhcp_alloc);
|
||||
_list.remove(&dhcp_alloc);
|
||||
}
|
||||
|
||||
Dhcp_allocation *first() { return _tree.first(); }
|
||||
|
||||
template <typename FUNC>
|
||||
void for_each(FUNC && functor)
|
||||
{
|
||||
using List_item = Dhcp_allocation_list::Element;
|
||||
for (Dhcp_allocation *item = _list.first(); item; )
|
||||
{
|
||||
Dhcp_allocation *const next_item = item->List_item::next();
|
||||
functor(*item);
|
||||
item = next_item;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _DHCP_SERVER_H_ */
|
||||
|
@ -17,6 +17,7 @@
|
||||
/* local includes */
|
||||
#include <ipv4_address_prefix.h>
|
||||
#include <rule.h>
|
||||
#include <list.h>
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/list.h>
|
||||
@ -67,16 +68,16 @@ struct Net::Direct_rule : Direct_rule_base,
|
||||
|
||||
|
||||
template <typename T>
|
||||
struct Net::Direct_rule_list : Genode::List<T>
|
||||
struct Net::Direct_rule_list : List<T>
|
||||
{
|
||||
using List = Genode::List<T>;
|
||||
using Base = List<T>;
|
||||
|
||||
struct No_match : Genode::Exception { };
|
||||
|
||||
T const &longest_prefix_match(Ipv4_address const &ip) const
|
||||
{
|
||||
/* first match is sufficient as the list is prefix-size-sorted */
|
||||
for (T const *curr = List::first(); curr; curr = curr->next()) {
|
||||
for (T const *curr = Base::first(); curr; curr = curr->next()) {
|
||||
if (curr->dst().prefix_matches(ip)) {
|
||||
return *curr; }
|
||||
}
|
||||
@ -87,13 +88,13 @@ struct Net::Direct_rule_list : Genode::List<T>
|
||||
{
|
||||
/* ensure that the list stays prefix-size-sorted (descending) */
|
||||
T *behind = nullptr;
|
||||
for (T *curr = List::first(); curr; curr = curr->next()) {
|
||||
for (T *curr = Base::first(); curr; curr = curr->next()) {
|
||||
if (rule.dst().prefix >= curr->dst().prefix) {
|
||||
break; }
|
||||
|
||||
behind = curr;
|
||||
}
|
||||
List::insert(&rule, behind);
|
||||
Base::insert(&rule, behind);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -140,6 +140,9 @@ Link_side_tree &Domain::links(L3_protocol const protocol)
|
||||
|
||||
void Domain::_ip_config_changed()
|
||||
{
|
||||
_interfaces.for_each([&] (Interface &interface) {
|
||||
interface.detach_from_ip_config();
|
||||
});
|
||||
if (!ip_config().valid) {
|
||||
|
||||
if (_config.verbose_domain_state()) {
|
||||
@ -168,15 +171,29 @@ void Domain::_ip_config_changed()
|
||||
|
||||
|
||||
Domain::~Domain()
|
||||
{
|
||||
/* destroy rules */
|
||||
_ip_rules.destroy_each(_alloc);
|
||||
_nat_rules.destroy_each(_alloc);
|
||||
_udp_rules.destroy_each(_alloc);
|
||||
_tcp_rules.destroy_each(_alloc);
|
||||
_udp_forward_rules.destroy_each(_alloc);
|
||||
_tcp_forward_rules.destroy_each(_alloc);
|
||||
|
||||
/* destroy DHCP server and IP config */
|
||||
try { destroy(_alloc, &_dhcp_server.deref()); }
|
||||
catch (Pointer<Dhcp_server>::Invalid) { }
|
||||
_ip_config.destruct();
|
||||
}
|
||||
|
||||
|
||||
void Domain::__FIXME__dissolve_foreign_arp_waiters()
|
||||
{
|
||||
/* let other interfaces destroy their ARP waiters that wait for us */
|
||||
while (_foreign_arp_waiters.first()) {
|
||||
Arp_waiter &waiter = *_foreign_arp_waiters.first()->object();
|
||||
waiter.src().cancel_arp_waiting(waiter);
|
||||
}
|
||||
/* destroy DHCP server */
|
||||
try { destroy(_alloc, &_dhcp_server.deref()); }
|
||||
catch (Pointer<Dhcp_server>::Invalid) { }
|
||||
}
|
||||
|
||||
|
||||
|
@ -94,7 +94,7 @@ class Net::Domain : public Domain_base
|
||||
Port_allocator _tcp_port_alloc { };
|
||||
Port_allocator _udp_port_alloc { };
|
||||
Nat_rule_tree _nat_rules { };
|
||||
List<Interface> _interfaces { };
|
||||
Interface_list _interfaces { };
|
||||
unsigned long _interface_cnt { 0 };
|
||||
Pointer<Dhcp_server> _dhcp_server { };
|
||||
Genode::Reconstructible<Ipv4_config> _ip_config;
|
||||
@ -120,6 +120,8 @@ class Net::Domain : public Domain_base
|
||||
|
||||
void _ip_config_changed();
|
||||
|
||||
void __FIXME__dissolve_foreign_arp_waiters();
|
||||
|
||||
public:
|
||||
|
||||
struct Invalid : Genode::Exception { };
|
||||
@ -167,14 +169,14 @@ class Net::Domain : public Domain_base
|
||||
|
||||
bool verbose_packets() const { return _verbose_packets; }
|
||||
Ipv4_config const &ip_config() const { return *_ip_config; }
|
||||
Domain_name const &name() { return _name; }
|
||||
Domain_name const &name() const { return _name; }
|
||||
Ip_rule_list &ip_rules() { return _ip_rules; }
|
||||
Forward_rule_tree &tcp_forward_rules() { return _tcp_forward_rules; }
|
||||
Forward_rule_tree &udp_forward_rules() { return _udp_forward_rules; }
|
||||
Transport_rule_list &tcp_rules() { return _tcp_rules; }
|
||||
Transport_rule_list &udp_rules() { return _udp_rules; }
|
||||
Nat_rule_tree &nat_rules() { return _nat_rules; }
|
||||
List<Interface> &interfaces() { return _interfaces; }
|
||||
Interface_list &interfaces() { return _interfaces; }
|
||||
Configuration &config() const { return _config; }
|
||||
Domain_avl_member &avl_member() { return _avl_member; }
|
||||
Dhcp_server &dhcp_server() { return _dhcp_server.deref(); }
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
/* local includes */
|
||||
#include <leaf_rule.h>
|
||||
#include <avl_tree.h>
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/avl_tree.h>
|
||||
@ -69,7 +70,7 @@ class Net::Forward_rule : public Leaf_rule,
|
||||
};
|
||||
|
||||
|
||||
struct Net::Forward_rule_tree : Genode::Avl_tree<Forward_rule>
|
||||
struct Net::Forward_rule_tree : Avl_tree<Forward_rule>
|
||||
{
|
||||
struct No_match : Genode::Exception { };
|
||||
|
||||
|
@ -29,6 +29,8 @@ using Genode::uint32_t;
|
||||
using Genode::log;
|
||||
using Genode::error;
|
||||
using Genode::warning;
|
||||
using Genode::Signal_context_capability;
|
||||
using Genode::Signal_transmitter;
|
||||
|
||||
|
||||
/***************
|
||||
@ -46,6 +48,17 @@ static void _destroy_dissolved_links(Link_list &dissolved_links,
|
||||
}
|
||||
|
||||
|
||||
template <typename LINK_TYPE>
|
||||
static void _destroy_link(Link &link,
|
||||
Link_list &links,
|
||||
Deallocator &dealloc)
|
||||
{
|
||||
link.dissolve();
|
||||
links.remove(&link);
|
||||
destroy(dealloc, static_cast<LINK_TYPE *>(&link));
|
||||
}
|
||||
|
||||
|
||||
template <typename LINK_TYPE>
|
||||
static void _destroy_links(Link_list &links,
|
||||
Link_list &dissolved_links,
|
||||
@ -53,10 +66,7 @@ static void _destroy_links(Link_list &links,
|
||||
{
|
||||
_destroy_dissolved_links<LINK_TYPE>(dissolved_links, dealloc);
|
||||
while (Link *link = links.first()) {
|
||||
link->dissolve();
|
||||
links.remove(link);
|
||||
destroy(dealloc, static_cast<LINK_TYPE *>(link));
|
||||
}
|
||||
_destroy_link<LINK_TYPE>(*link, links, dealloc); }
|
||||
}
|
||||
|
||||
|
||||
@ -153,6 +163,16 @@ static void *_prot_base(L3_protocol const prot,
|
||||
** Interface **
|
||||
***************/
|
||||
|
||||
void Interface::_destroy_link(Link &link)
|
||||
{
|
||||
L3_protocol const prot = link.protocol();
|
||||
switch (prot) {
|
||||
case L3_protocol::TCP: ::_destroy_link<Tcp_link>(link, links(prot), _alloc); break;
|
||||
case L3_protocol::UDP: ::_destroy_link<Udp_link>(link, links(prot), _alloc); break;
|
||||
default: throw Bad_transport_protocol(); }
|
||||
}
|
||||
|
||||
|
||||
void Interface::_pass_prot(Ethernet_frame ð,
|
||||
size_t const eth_size,
|
||||
Ipv4_packet &ip,
|
||||
@ -194,38 +214,127 @@ Interface::_transport_rules(Domain &local_domain, L3_protocol const prot) const
|
||||
}
|
||||
|
||||
|
||||
void Interface::attach_to_domain(Domain &domain)
|
||||
void Interface::_attach_to_domain_raw(Domain_name const &domain_name)
|
||||
{
|
||||
_domain_ptr.set(domain);
|
||||
Domain &domain = _config().domains().find_by_name(domain_name);
|
||||
_domain = domain;
|
||||
Signal_transmitter(_link_state_sigh).submit();
|
||||
_interfaces.remove(this);
|
||||
domain.attach_interface(*this);
|
||||
if (!domain.ip_config().valid) {
|
||||
}
|
||||
|
||||
|
||||
void Interface::_detach_from_domain_raw()
|
||||
{
|
||||
Domain &domain = _domain.deref();
|
||||
domain.detach_interface(*this);
|
||||
_interfaces.insert(this);
|
||||
_domain = Pointer<Domain>();
|
||||
Signal_transmitter(_link_state_sigh).submit();
|
||||
}
|
||||
|
||||
|
||||
void Interface::_attach_to_domain(Domain_name const &domain_name,
|
||||
bool apply_foreign_arp)
|
||||
{
|
||||
_attach_to_domain_raw(domain_name);
|
||||
|
||||
/* ensure that DHCP requests are sent on each interface of the domain */
|
||||
if (!domain().ip_config().valid) {
|
||||
_dhcp_client.discover();
|
||||
}
|
||||
/* ensure that DHCP requests are sent on each interface of the domain */
|
||||
if ( apply_foreign_arp) { _apply_foreign_arp(); }
|
||||
else { _apply_foreign_arp_pending = true; }
|
||||
}
|
||||
|
||||
|
||||
void Interface::_apply_foreign_arp()
|
||||
{
|
||||
/* sent ARP request for each foreign ARP waiter */
|
||||
Domain &domain_ = domain();
|
||||
domain_.foreign_arp_waiters().for_each([&] (Arp_waiter_list_element &le) {
|
||||
_broadcast_arp_request(domain_.ip_config().interface.address,
|
||||
le.object()->ip());
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
bool Interface::link_state()
|
||||
{
|
||||
try {
|
||||
_domain.deref();
|
||||
return true;
|
||||
}
|
||||
catch (Pointer<Domain>::Invalid) { }
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void Interface::link_state_sigh(Signal_context_capability sigh)
|
||||
{
|
||||
_link_state_sigh = sigh;
|
||||
}
|
||||
|
||||
|
||||
void Interface::handle_config_aftermath()
|
||||
{
|
||||
/* ensure that ARP requests are sent on each interface of the domain */
|
||||
if (_apply_foreign_arp_pending) {
|
||||
_apply_foreign_arp();
|
||||
_apply_foreign_arp_pending = false;
|
||||
}
|
||||
}
|
||||
|
||||
struct Detach_from_domain_not_implemented : Genode::Exception { };
|
||||
void Interface::detach_from_domain()
|
||||
|
||||
void Interface::detach_from_ip_config()
|
||||
{
|
||||
_domain_ptr.unset();
|
||||
throw Detach_from_domain_not_implemented();
|
||||
/* destroy our own ARP waiters */
|
||||
Domain &domain = _domain.deref();
|
||||
while (_own_arp_waiters.first()) {
|
||||
cancel_arp_waiting(*_own_arp_waiters.first()->object());
|
||||
}
|
||||
/* destroy links */
|
||||
_destroy_links<Tcp_link>(_tcp_links, _dissolved_tcp_links, _alloc);
|
||||
_destroy_links<Udp_link>(_udp_links, _dissolved_udp_links, _alloc);
|
||||
|
||||
/* destroy DHCP allocations */
|
||||
_destroy_released_dhcp_allocations(domain);
|
||||
while (Dhcp_allocation *allocation = _dhcp_allocations.first()) {
|
||||
_dhcp_allocations.remove(*allocation);
|
||||
_destroy_dhcp_allocation(*allocation, domain);
|
||||
}
|
||||
/* dissolve ARP cache entries with the MAC address of this interface */
|
||||
domain.arp_cache().destroy_entries_with_mac(_mac);
|
||||
}
|
||||
|
||||
|
||||
void Interface::_detach_from_domain()
|
||||
{
|
||||
try {
|
||||
detach_from_ip_config();
|
||||
_detach_from_domain_raw();
|
||||
_apply_foreign_arp_pending = false;
|
||||
}
|
||||
catch (Pointer<Domain>::Invalid) { }
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Interface::_new_link(L3_protocol const protocol,
|
||||
Link_side_id const &local,
|
||||
Pointer<Port_allocator_guard> const remote_port_alloc,
|
||||
Domain &remote_domain,
|
||||
Link_side_id const &remote)
|
||||
Interface::_new_link(L3_protocol const protocol,
|
||||
Link_side_id const &local,
|
||||
Pointer<Port_allocator_guard> remote_port_alloc,
|
||||
Domain &remote_domain,
|
||||
Link_side_id const &remote)
|
||||
{
|
||||
switch (protocol) {
|
||||
case L3_protocol::TCP:
|
||||
new (_alloc) Tcp_link(*this, local, remote_port_alloc, remote_domain,
|
||||
remote, _timer, _config, protocol);
|
||||
remote, _timer, _config(), protocol);
|
||||
break;
|
||||
case L3_protocol::UDP:
|
||||
new (_alloc) Udp_link(*this, local, remote_port_alloc, remote_domain,
|
||||
remote, _timer, _config, protocol);
|
||||
remote, _timer, _config(), protocol);
|
||||
break;
|
||||
default: throw Bad_transport_protocol(); }
|
||||
}
|
||||
@ -233,7 +342,7 @@ Interface::_new_link(L3_protocol const protocol,
|
||||
|
||||
void Interface::dhcp_allocation_expired(Dhcp_allocation &allocation)
|
||||
{
|
||||
_release_dhcp_allocation(allocation, _domain_ptr.deref());
|
||||
_release_dhcp_allocation(allocation, _domain.deref());
|
||||
_released_dhcp_allocations.insert(&allocation);
|
||||
}
|
||||
|
||||
@ -292,7 +401,7 @@ void Interface::_nat_link_and_pass(Ethernet_frame ð,
|
||||
Pointer<Port_allocator_guard> remote_port_alloc;
|
||||
try {
|
||||
Nat_rule &nat = remote_domain.nat_rules().find_by_domain(local_domain);
|
||||
if(_config.verbose()) {
|
||||
if(_config().verbose()) {
|
||||
log("Using NAT rule: ", nat); }
|
||||
|
||||
_src_port(prot, prot_base, nat.port_alloc(prot).alloc());
|
||||
@ -394,11 +503,11 @@ void Interface::_send_dhcp_reply(Dhcp_server const &dhcp_srv,
|
||||
void Interface::_release_dhcp_allocation(Dhcp_allocation &allocation,
|
||||
Domain &local_domain)
|
||||
{
|
||||
if (_config.verbose()) {
|
||||
if (_config().verbose()) {
|
||||
log("Release DHCP allocation: ", allocation,
|
||||
" at ", local_domain);
|
||||
}
|
||||
_dhcp_allocations.remove(&allocation);
|
||||
_dhcp_allocations.remove(allocation);
|
||||
}
|
||||
|
||||
|
||||
@ -410,10 +519,10 @@ void Interface::_new_dhcp_allocation(Ethernet_frame ð,
|
||||
Dhcp_allocation &allocation = *new (_alloc)
|
||||
Dhcp_allocation(*this, dhcp_srv.alloc_ip(),
|
||||
dhcp.client_mac(), _timer,
|
||||
_config.dhcp_offer_timeout());
|
||||
_config().dhcp_offer_timeout());
|
||||
|
||||
_dhcp_allocations.insert(&allocation);
|
||||
if (_config.verbose()) {
|
||||
_dhcp_allocations.insert(allocation);
|
||||
if (_config().verbose()) {
|
||||
log("Offer DHCP allocation: ", allocation,
|
||||
" at ", local_domain);
|
||||
}
|
||||
@ -457,7 +566,7 @@ void Interface::_handle_dhcp_request(Ethernet_frame ð, size_t ,
|
||||
return;
|
||||
|
||||
} else {
|
||||
allocation.lifetime(_config.dhcp_offer_timeout());
|
||||
allocation.lifetime(_config().dhcp_offer_timeout());
|
||||
_send_dhcp_reply(dhcp_srv, eth.src(),
|
||||
allocation.ip(),
|
||||
Dhcp_packet::Message_type::OFFER,
|
||||
@ -482,7 +591,7 @@ void Interface::_handle_dhcp_request(Ethernet_frame ð, size_t ,
|
||||
{
|
||||
allocation.set_bound();
|
||||
allocation.lifetime(dhcp_srv.ip_lease_time());
|
||||
if (_config.verbose()) {
|
||||
if (_config().verbose()) {
|
||||
log("Bind DHCP allocation: ", allocation,
|
||||
" at ", local_domain);
|
||||
}
|
||||
@ -618,7 +727,7 @@ void Interface::_handle_ip(Ethernet_frame ð,
|
||||
bool const client = local_side.is_client();
|
||||
Link_side &remote_side = client ? link.server() : link.client();
|
||||
Domain &remote_domain = remote_side.domain();
|
||||
if (_config.verbose()) {
|
||||
if (_config().verbose()) {
|
||||
log("Using ", l3_protocol_name(prot), " link: ", link); }
|
||||
|
||||
_adapt_eth(eth, remote_side.src_ip(), pkt, remote_domain);
|
||||
@ -641,7 +750,7 @@ void Interface::_handle_ip(Ethernet_frame ð,
|
||||
Forward_rule const &rule =
|
||||
_forward_rules(local_domain, prot).find_by_port(local_id.dst_port);
|
||||
|
||||
if(_config.verbose()) {
|
||||
if(_config().verbose()) {
|
||||
log("Using forward rule: ", l3_protocol_name(prot), " ", rule); }
|
||||
|
||||
Domain &remote_domain = rule.domain();
|
||||
@ -661,7 +770,7 @@ void Interface::_handle_ip(Ethernet_frame ð,
|
||||
Permit_rule const &permit_rule =
|
||||
transport_rule.permit_rule(local_id.dst_port);
|
||||
|
||||
if(_config.verbose()) {
|
||||
if(_config().verbose()) {
|
||||
log("Using ", l3_protocol_name(prot), " rule: ", transport_rule,
|
||||
" ", permit_rule); }
|
||||
|
||||
@ -681,7 +790,7 @@ void Interface::_handle_ip(Ethernet_frame ð,
|
||||
Ip_rule const &rule =
|
||||
local_domain.ip_rules().longest_prefix_match(ip.dst());
|
||||
|
||||
if(_config.verbose()) {
|
||||
if(_config().verbose()) {
|
||||
log("Using IP rule: ", rule); }
|
||||
|
||||
Domain &remote_domain = rule.domain();
|
||||
@ -695,7 +804,7 @@ void Interface::_handle_ip(Ethernet_frame ð,
|
||||
catch (Ip_rule_list::No_match) { }
|
||||
|
||||
/* give up and drop packet */
|
||||
if (_config.verbose()) {
|
||||
if (_config().verbose()) {
|
||||
log("Unroutable packet"); }
|
||||
}
|
||||
|
||||
@ -742,7 +851,7 @@ void Interface::_handle_arp_reply(Ethernet_frame ð,
|
||||
try {
|
||||
/* check wether a matching ARP cache entry already exists */
|
||||
local_domain.arp_cache().find_by_ip(arp.src_ip());
|
||||
if (_config.verbose()) {
|
||||
if (_config().verbose()) {
|
||||
log("ARP entry already exists"); }
|
||||
}
|
||||
catch (Arp_cache::No_match) {
|
||||
@ -905,7 +1014,7 @@ void Interface::_handle_eth(void *const eth_base,
|
||||
Packet_descriptor const &pkt)
|
||||
{
|
||||
try {
|
||||
Domain &local_domain = _domain_ptr.deref();
|
||||
Domain &local_domain = _domain.deref();
|
||||
try {
|
||||
local_domain.raise_rx_bytes(eth_size);
|
||||
|
||||
@ -938,12 +1047,12 @@ void Interface::_handle_eth(void *const eth_base,
|
||||
catch (Udp_packet::Bad_data_type) { warning("malformed UDP packet" ); }
|
||||
|
||||
catch (Bad_network_protocol) {
|
||||
if (_config.verbose()) {
|
||||
if (_config().verbose()) {
|
||||
log("unknown network layer protocol");
|
||||
}
|
||||
}
|
||||
catch (Drop_packet_inform exception) {
|
||||
if (_config.verbose()) {
|
||||
if (_config().verbose()) {
|
||||
log("(", local_domain, ") Drop packet: ", exception.msg);
|
||||
}
|
||||
}
|
||||
@ -966,7 +1075,7 @@ void Interface::_handle_eth(void *const eth_base,
|
||||
error("failed to allocate IP for DHCP client"); }
|
||||
}
|
||||
catch (Pointer<Domain>::Invalid) {
|
||||
if (_config.verbose()) {
|
||||
if (_config().verbose()) {
|
||||
log("(?) Drop packet: no domain");
|
||||
}
|
||||
}
|
||||
@ -994,7 +1103,7 @@ void Interface::_send_submit_pkt(Packet_descriptor &pkt,
|
||||
void * &pkt_base,
|
||||
size_t pkt_size)
|
||||
{
|
||||
Domain &local_domain = _domain_ptr.deref();
|
||||
Domain &local_domain = _domain.deref();
|
||||
_source().submit_packet(pkt);
|
||||
local_domain.raise_tx_bytes(pkt_size);
|
||||
if (local_domain.verbose_packets()) {
|
||||
@ -1010,23 +1119,240 @@ Interface::Interface(Genode::Entrypoint &ep,
|
||||
Genode::Allocator &alloc,
|
||||
Mac_address const mac,
|
||||
Configuration &config,
|
||||
Interface_policy const &policy)
|
||||
Interface_list &interfaces,
|
||||
Interface_policy &policy)
|
||||
:
|
||||
_sink_ack(ep, *this, &Interface::_ack_avail),
|
||||
_sink_submit(ep, *this, &Interface::_ready_to_submit),
|
||||
_source_ack(ep, *this, &Interface::_ready_to_ack),
|
||||
_source_submit(ep, *this, &Interface::_packet_avail),
|
||||
_router_mac(router_mac), _mac(mac), _config(config),
|
||||
_policy(policy), _timer(timer), _alloc(alloc)
|
||||
_policy(policy), _timer(timer), _alloc(alloc),
|
||||
_interfaces(interfaces)
|
||||
{
|
||||
/* try to find matching domain and attach interface to it */
|
||||
Domain_name const domain_name = _policy.determine_domain_name();
|
||||
try { attach_to_domain(config.domains().find_by_name(domain_name)); }
|
||||
catch (Domain_tree::No_match) {
|
||||
if (config.verbose()) {
|
||||
log("No matching domain");
|
||||
_interfaces.insert(this);
|
||||
try { _attach_to_domain(_policy.determine_domain_name(), true); }
|
||||
catch (Domain_tree::No_match) { }
|
||||
}
|
||||
|
||||
|
||||
void Interface::_dismiss_link_log(Link &link,
|
||||
char const *reason)
|
||||
{
|
||||
if (!_config().verbose()) {
|
||||
return;
|
||||
}
|
||||
log("[", link.client().domain(), "] dismiss link client: ", link.client(), " (", reason, ")");
|
||||
log("[", link.server().domain(), "] dismiss link server: ", link.server(), " (", reason, ")");
|
||||
}
|
||||
|
||||
|
||||
void Interface::_update_link_check_nat(Link &link,
|
||||
Domain &new_srv_dom,
|
||||
L3_protocol prot,
|
||||
Domain &cln_dom)
|
||||
{
|
||||
/* if server domain or its IP config changed, dismiss link */
|
||||
Domain &old_srv_dom = link.server().domain();
|
||||
if (old_srv_dom.name() != new_srv_dom.name() ||
|
||||
old_srv_dom.ip_config() != new_srv_dom.ip_config())
|
||||
{
|
||||
_dismiss_link_log(link, "rule targets other domain");
|
||||
throw Dismiss_link();
|
||||
}
|
||||
Pointer<Port_allocator_guard> remote_port_alloc_ptr;
|
||||
if (link.client().src_ip() == link.server().dst_ip()) {
|
||||
link.handle_config(cln_dom, new_srv_dom, remote_port_alloc_ptr, _config());
|
||||
return;
|
||||
}
|
||||
try {
|
||||
if (link.server().dst_ip() != new_srv_dom.ip_config().interface.address) {
|
||||
_dismiss_link_log(link, "NAT IP");
|
||||
throw Dismiss_link();
|
||||
}
|
||||
_config.detached_interfaces().insert(this);
|
||||
Nat_rule &nat = new_srv_dom.nat_rules().find_by_domain(cln_dom);
|
||||
Port_allocator_guard &remote_port_alloc = nat.port_alloc(prot);
|
||||
remote_port_alloc.alloc(link.server().dst_port());
|
||||
remote_port_alloc_ptr.set(remote_port_alloc);
|
||||
link.handle_config(cln_dom, new_srv_dom, remote_port_alloc_ptr, _config());
|
||||
return;
|
||||
}
|
||||
catch (Nat_rule_tree::No_match) { _dismiss_link_log(link, "no NAT rule"); }
|
||||
catch (Port_allocator::Allocation_conflict) { _dismiss_link_log(link, "no NAT-port"); }
|
||||
catch (Port_allocator_guard::Out_of_indices) { _dismiss_link_log(link, "no NAT-port quota"); }
|
||||
throw Dismiss_link();
|
||||
}
|
||||
|
||||
|
||||
void Interface::_update_links(L3_protocol prot,
|
||||
Domain &cln_dom)
|
||||
{
|
||||
links(prot).for_each([&] (Link &link) {
|
||||
try {
|
||||
/* try to find forward rule that matches the server port */
|
||||
Forward_rule const &rule =
|
||||
_forward_rules(cln_dom, prot).
|
||||
find_by_port(link.client().dst_port());
|
||||
|
||||
/* if destination IP of forwarding changed, dismiss link */
|
||||
if (rule.to() != link.server().src_ip()) {
|
||||
_dismiss_link_log(link, "other forward-rule to");
|
||||
throw Dismiss_link();
|
||||
}
|
||||
_update_link_check_nat(link, rule.domain(), prot, cln_dom);
|
||||
return;
|
||||
}
|
||||
catch (Forward_rule_tree::No_match) {
|
||||
try {
|
||||
/* try to find transport rule that matches the server IP */
|
||||
Transport_rule const &transport_rule =
|
||||
_transport_rules(cln_dom, prot).
|
||||
longest_prefix_match(link.client().dst_ip());
|
||||
|
||||
/* try to find permit rule that matches the server port */
|
||||
Permit_rule const &permit_rule =
|
||||
transport_rule.permit_rule(link.client().dst_port());
|
||||
|
||||
_update_link_check_nat(link, permit_rule.domain(), prot, cln_dom);
|
||||
return;
|
||||
}
|
||||
catch (Transport_rule_list::No_match) { _dismiss_link_log(link, "no transport/forward rule"); }
|
||||
catch (Permit_single_rule_tree::No_match) { _dismiss_link_log(link, "no permit rule"); }
|
||||
catch (Dismiss_link) { }
|
||||
}
|
||||
catch (Dismiss_link) { }
|
||||
_destroy_link(link);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
void Interface::_update_dhcp_allocations(Domain &old_domain,
|
||||
Domain &new_domain)
|
||||
{
|
||||
try {
|
||||
Dhcp_server &old_dhcp_srv = old_domain.dhcp_server();
|
||||
Dhcp_server &new_dhcp_srv = new_domain.dhcp_server();
|
||||
if (old_dhcp_srv.dns_server() != new_dhcp_srv.dns_server()) {
|
||||
throw Pointer<Dhcp_server>::Invalid();
|
||||
}
|
||||
if (old_dhcp_srv.ip_lease_time().value !=
|
||||
new_dhcp_srv.ip_lease_time().value)
|
||||
{
|
||||
throw Pointer<Dhcp_server>::Invalid();
|
||||
}
|
||||
_dhcp_allocations.for_each([&] (Dhcp_allocation &allocation) {
|
||||
try {
|
||||
new_dhcp_srv.alloc_ip(allocation.ip());
|
||||
|
||||
/* keep DHCP allocation */
|
||||
if (_config().verbose()) {
|
||||
log("[", new_domain, "] update DHCP allocation: ",
|
||||
allocation);
|
||||
}
|
||||
return;
|
||||
}
|
||||
catch (Dhcp_server::Alloc_ip_failed) {
|
||||
if (_config().verbose()) {
|
||||
log("[", new_domain, "] dismiss DHCP allocation: ",
|
||||
allocation, " (no IP)");
|
||||
}
|
||||
}
|
||||
/* dismiss DHCP allocation */
|
||||
_dhcp_allocations.remove(allocation);
|
||||
_destroy_dhcp_allocation(allocation, old_domain);
|
||||
});
|
||||
}
|
||||
catch (Pointer<Dhcp_server>::Invalid) {
|
||||
|
||||
/* dismiss all DHCP allocations */
|
||||
while (Dhcp_allocation *allocation = _dhcp_allocations.first()) {
|
||||
if (_config().verbose()) {
|
||||
log("[", new_domain, "] dismiss DHCP allocation: ",
|
||||
*allocation, " (other/no DHCP server)");
|
||||
}
|
||||
_dhcp_allocations.remove(*allocation);
|
||||
_destroy_dhcp_allocation(*allocation, old_domain);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Interface::_update_own_arp_waiters(Domain &domain)
|
||||
{
|
||||
_own_arp_waiters.for_each([&] (Arp_waiter_list_element &le) {
|
||||
Arp_waiter &arp_waiter = *le.object();
|
||||
try {
|
||||
Domain &dst = _config().domains().find_by_name(arp_waiter.dst().name());
|
||||
if (dst.ip_config() != arp_waiter.dst().ip_config()) {
|
||||
throw Dismiss_arp_waiter(); }
|
||||
|
||||
/* keep ARP waiter */
|
||||
arp_waiter.handle_config(dst);
|
||||
if (_config().verbose()) {
|
||||
log("[", domain, "] update ARP waiter: ", arp_waiter);
|
||||
}
|
||||
return;
|
||||
}
|
||||
catch (Domain_tree::No_match) { }
|
||||
catch (Dismiss_arp_waiter) { }
|
||||
|
||||
/* dismiss ARP waiter */
|
||||
if (_config().verbose()) {
|
||||
log("[", domain, "] dismiss ARP waiter: ", arp_waiter, " (no domain)");
|
||||
}
|
||||
cancel_arp_waiting(*_own_arp_waiters.first()->object());
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
void Interface::handle_config(Configuration &config)
|
||||
{
|
||||
/* deteremine the name of the new domain */
|
||||
_config = config;
|
||||
_policy.handle_config(config);
|
||||
Domain_name const &new_domain_name = _policy.determine_domain_name();
|
||||
try {
|
||||
/* destroy state objects that are not needed anymore */
|
||||
Domain &old_domain = domain();
|
||||
_destroy_dissolved_links<Udp_link>(_dissolved_udp_links, _alloc);
|
||||
_destroy_dissolved_links<Tcp_link>(_dissolved_tcp_links, _alloc);
|
||||
_destroy_released_dhcp_allocations(old_domain);
|
||||
|
||||
/* if the domains differ, detach completely from the domain */
|
||||
if (old_domain.name() != new_domain_name) {
|
||||
_detach_from_domain();
|
||||
_attach_to_domain(new_domain_name, false);
|
||||
return;
|
||||
}
|
||||
/* move to new domain object without considering any state objects */
|
||||
_detach_from_domain_raw();
|
||||
_attach_to_domain_raw(new_domain_name);
|
||||
Domain &new_domain = domain();
|
||||
|
||||
/* if the IP configs differ, detach completely from the IP config */
|
||||
if (old_domain.ip_config() != new_domain.ip_config()) {
|
||||
detach_from_ip_config();
|
||||
return;
|
||||
}
|
||||
/* if there was/is no IP config, there is nothing more to update */
|
||||
if (!new_domain.ip_config().valid) {
|
||||
return;
|
||||
}
|
||||
/* update state objects */
|
||||
_update_links(L3_protocol::TCP, new_domain);
|
||||
_update_links(L3_protocol::UDP, new_domain);
|
||||
_update_dhcp_allocations(old_domain, new_domain);
|
||||
_update_own_arp_waiters(new_domain);
|
||||
}
|
||||
catch (Domain_tree::No_match) {
|
||||
|
||||
/* the interface no longer has a domain */
|
||||
_detach_from_domain();
|
||||
}
|
||||
catch (Pointer<Domain>::Invalid) {
|
||||
|
||||
/* the interface had no domain but now it gets one */
|
||||
_attach_to_domain(new_domain_name, false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1051,31 +1377,6 @@ void Interface::cancel_arp_waiting(Arp_waiter &waiter)
|
||||
|
||||
Interface::~Interface()
|
||||
{
|
||||
try {
|
||||
/* try to detach from domain */
|
||||
Domain &local_domain = _domain_ptr.deref();
|
||||
local_domain.detach_interface(*this);
|
||||
|
||||
/* destroy our own ARP waiters */
|
||||
while (_own_arp_waiters.first()) {
|
||||
cancel_arp_waiting(*_own_arp_waiters.first()->object());
|
||||
}
|
||||
/* destroy links */
|
||||
_destroy_links<Tcp_link>(_tcp_links, _dissolved_tcp_links, _alloc);
|
||||
_destroy_links<Udp_link>(_udp_links, _dissolved_udp_links, _alloc);
|
||||
|
||||
/* destroy DHCP allocations */
|
||||
_destroy_released_dhcp_allocations(local_domain);
|
||||
while (Dhcp_allocation *allocation = _dhcp_allocations.first()) {
|
||||
_dhcp_allocations.remove(allocation);
|
||||
_destroy_dhcp_allocation(*allocation, local_domain);
|
||||
}
|
||||
/* dissolve ARP cache entries with the MAC address of this interface */
|
||||
local_domain.arp_cache().destroy_entries_with_mac(_mac);
|
||||
}
|
||||
catch (Pointer<Domain>::Invalid) {
|
||||
|
||||
/* if not attached to a domain the interface is in a global list */
|
||||
_config.detached_interfaces().remove(this);
|
||||
}
|
||||
_detach_from_domain();
|
||||
_interfaces.remove(this);
|
||||
}
|
||||
|
@ -32,6 +32,7 @@ namespace Net {
|
||||
using Packet_stream_sink = ::Nic::Packet_stream_sink< ::Nic::Session::Policy>;
|
||||
using Packet_stream_source = ::Nic::Packet_stream_source< ::Nic::Session::Policy>;
|
||||
using Domain_name = Genode::String<160>;
|
||||
class Leaf_rule;
|
||||
class Ipv4_config;
|
||||
class Forward_rule_tree;
|
||||
class Transport_rule_list;
|
||||
@ -39,6 +40,7 @@ namespace Net {
|
||||
class Arp_packet;
|
||||
class Interface_policy;
|
||||
class Interface;
|
||||
using Interface_list = List<Interface>;
|
||||
class Dhcp_server;
|
||||
class Configuration;
|
||||
class Domain;
|
||||
@ -49,16 +51,18 @@ struct Net::Interface_policy
|
||||
{
|
||||
virtual Domain_name determine_domain_name() const = 0;
|
||||
|
||||
virtual void handle_config(Configuration const &config) = 0;
|
||||
|
||||
virtual ~Interface_policy() { }
|
||||
};
|
||||
|
||||
|
||||
class Net::Interface : private Genode::List<Interface>::Element
|
||||
class Net::Interface : private Interface_list::Element
|
||||
{
|
||||
protected:
|
||||
friend class List<Interface>;
|
||||
friend class Genode::List<Interface>;
|
||||
|
||||
friend class Genode::List<Interface>;
|
||||
friend class Net::List<Interface>;
|
||||
protected:
|
||||
|
||||
using Signal_handler = Genode::Signal_handler<Interface>;
|
||||
|
||||
@ -71,25 +75,31 @@ class Net::Interface : private Genode::List<Interface>::Element
|
||||
|
||||
private:
|
||||
|
||||
Configuration &_config;
|
||||
Interface_policy const &_policy;
|
||||
Timer::Connection &_timer;
|
||||
Genode::Allocator &_alloc;
|
||||
Pointer<Domain> _domain_ptr { };
|
||||
Arp_waiter_list _own_arp_waiters { };
|
||||
Link_list _tcp_links { };
|
||||
Link_list _udp_links { };
|
||||
Link_list _dissolved_tcp_links { };
|
||||
Link_list _dissolved_udp_links { };
|
||||
Dhcp_allocation_tree _dhcp_allocations { };
|
||||
Dhcp_allocation_list _released_dhcp_allocations { };
|
||||
Dhcp_client _dhcp_client { _alloc, _timer, *this };
|
||||
struct Dismiss_link : Genode::Exception { };
|
||||
struct Dismiss_arp_waiter : Genode::Exception { };
|
||||
|
||||
void _new_link(L3_protocol const protocol,
|
||||
Link_side_id const &local_id,
|
||||
Pointer<Port_allocator_guard> const remote_port_alloc,
|
||||
Domain &remote_domain,
|
||||
Link_side_id const &remote_id);
|
||||
Reference<Configuration> _config;
|
||||
Interface_policy &_policy;
|
||||
Timer::Connection &_timer;
|
||||
Genode::Allocator &_alloc;
|
||||
Pointer<Domain> _domain { };
|
||||
Arp_waiter_list _own_arp_waiters { };
|
||||
Link_list _tcp_links { };
|
||||
Link_list _udp_links { };
|
||||
Link_list _dissolved_tcp_links { };
|
||||
Link_list _dissolved_udp_links { };
|
||||
Dhcp_allocation_tree _dhcp_allocations { };
|
||||
Dhcp_allocation_list _released_dhcp_allocations { };
|
||||
Dhcp_client _dhcp_client { _alloc, _timer, *this };
|
||||
Interface_list &_interfaces;
|
||||
bool _apply_foreign_arp_pending { false };
|
||||
Genode::Signal_context_capability _link_state_sigh { };
|
||||
|
||||
void _new_link(L3_protocol const protocol,
|
||||
Link_side_id const &local_id,
|
||||
Pointer<Port_allocator_guard> remote_port_alloc,
|
||||
Domain &remote_domain,
|
||||
Link_side_id const &remote_id);
|
||||
|
||||
void _destroy_released_dhcp_allocations(Domain &local_domain);
|
||||
|
||||
@ -200,6 +210,36 @@ class Net::Interface : private Genode::List<Interface>::Element
|
||||
void * &pkt_base,
|
||||
Genode::size_t pkt_size);
|
||||
|
||||
void _update_dhcp_allocations(Domain &old_domain,
|
||||
Domain &new_domain);
|
||||
|
||||
void _update_own_arp_waiters(Domain &domain);
|
||||
|
||||
void _update_links(L3_protocol prot,
|
||||
Domain &cln_dom);
|
||||
|
||||
void _update_link_check_nat(Link &link,
|
||||
Domain &new_srv_dom,
|
||||
L3_protocol prot,
|
||||
Domain &cln_dom);
|
||||
|
||||
void _dismiss_link_log(Link &link,
|
||||
char const *reason);
|
||||
|
||||
void _destroy_link(Link &link);
|
||||
|
||||
void _detach_from_domain_raw();
|
||||
|
||||
void _attach_to_domain_raw(Domain_name const &domain_name);
|
||||
|
||||
void _detach_from_domain();
|
||||
|
||||
void _attach_to_domain(Domain_name const &domain_name,
|
||||
bool apply_foreign_arp);
|
||||
|
||||
void _apply_foreign_arp();
|
||||
|
||||
|
||||
|
||||
/***********************************
|
||||
** Packet-stream signal handlers **
|
||||
@ -241,7 +281,8 @@ class Net::Interface : private Genode::List<Interface>::Element
|
||||
Genode::Allocator &alloc,
|
||||
Mac_address const mac,
|
||||
Configuration &config,
|
||||
Interface_policy const &policy);
|
||||
Interface_list &interfaces,
|
||||
Interface_policy &policy);
|
||||
|
||||
virtual ~Interface();
|
||||
|
||||
@ -271,16 +312,22 @@ class Net::Interface : private Genode::List<Interface>::Element
|
||||
|
||||
void cancel_arp_waiting(Arp_waiter &waiter);
|
||||
|
||||
void attach_to_domain(Domain &domain);
|
||||
void handle_config(Configuration &new_config);
|
||||
|
||||
void detach_from_domain();
|
||||
void handle_config_aftermath();
|
||||
|
||||
void detach_from_ip_config();
|
||||
|
||||
bool link_state();
|
||||
|
||||
void link_state_sigh(Genode::Signal_context_capability sigh);
|
||||
|
||||
|
||||
/***************
|
||||
** Accessors **
|
||||
***************/
|
||||
|
||||
Domain &domain() { return _domain_ptr.deref(); }
|
||||
Domain &domain() { return _domain.deref(); }
|
||||
Mac_address router_mac() const { return _router_mac; }
|
||||
Arp_waiter_list &own_arp_waiters() { return _own_arp_waiters; }
|
||||
};
|
||||
|
@ -113,15 +113,15 @@ void Link::print(Output &output) const
|
||||
}
|
||||
|
||||
|
||||
Link::Link(Interface &cln_interface,
|
||||
Link_side_id const &cln_id,
|
||||
Pointer<Port_allocator_guard> const srv_port_alloc,
|
||||
Domain &srv_domain,
|
||||
Link_side_id const &srv_id,
|
||||
Timer::Connection &timer,
|
||||
Configuration &config,
|
||||
L3_protocol const protocol,
|
||||
Microseconds const dissolve_timeout)
|
||||
Link::Link(Interface &cln_interface,
|
||||
Link_side_id const &cln_id,
|
||||
Pointer<Port_allocator_guard> srv_port_alloc,
|
||||
Domain &srv_domain,
|
||||
Link_side_id const &srv_id,
|
||||
Timer::Connection &timer,
|
||||
Configuration &config,
|
||||
L3_protocol const protocol,
|
||||
Microseconds const dissolve_timeout)
|
||||
:
|
||||
_config(config),
|
||||
_client_interface(cln_interface),
|
||||
@ -151,12 +151,12 @@ void Link::dissolve()
|
||||
{
|
||||
_client.domain().links(_protocol).remove(&_client);
|
||||
_server.domain().links(_protocol).remove(&_server);
|
||||
if (_config.verbose()) {
|
||||
if (_config().verbose()) {
|
||||
log("Dissolve ", l3_protocol_name(_protocol), " link: ", *this); }
|
||||
|
||||
try {
|
||||
_server_port_alloc.deref().free(_server.dst_port());
|
||||
if (_config.verbose()) {
|
||||
if (_config().verbose()) {
|
||||
log("Free ", l3_protocol_name(_protocol),
|
||||
" port ", _server.dst_port(),
|
||||
" at ", _server.domain(),
|
||||
@ -167,18 +167,49 @@ void Link::dissolve()
|
||||
}
|
||||
|
||||
|
||||
void Link::handle_config(Domain &cln_domain,
|
||||
Domain &srv_domain,
|
||||
Pointer<Port_allocator_guard> srv_port_alloc,
|
||||
Configuration &config)
|
||||
{
|
||||
Microseconds dissolve_timeout_us(0);
|
||||
switch (_protocol) {
|
||||
case L3_protocol::TCP: dissolve_timeout_us = config.tcp_idle_timeout(); break;
|
||||
case L3_protocol::UDP: dissolve_timeout_us = config.tcp_idle_timeout(); break;
|
||||
}
|
||||
_dissolve_timeout_us = dissolve_timeout_us;
|
||||
_dissolve_timeout.schedule(_dissolve_timeout_us);
|
||||
|
||||
_client.domain().links(_protocol).remove(&_client);
|
||||
_server.domain().links(_protocol).remove(&_server);
|
||||
|
||||
_config = config;
|
||||
_client._domain = cln_domain;
|
||||
_server._domain = srv_domain;
|
||||
_server_port_alloc = srv_port_alloc;
|
||||
|
||||
cln_domain.links(_protocol).insert(&_client);
|
||||
srv_domain.links(_protocol).insert(&_server);
|
||||
|
||||
if (config.verbose()) {
|
||||
log("[", cln_domain, "] update link client: ", _client);
|
||||
log("[", srv_domain, "] update link server: ", _server);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**************
|
||||
** Tcp_link **
|
||||
**************/
|
||||
|
||||
Tcp_link::Tcp_link(Interface &cln_interface,
|
||||
Link_side_id const &cln_id,
|
||||
Pointer<Port_allocator_guard> const srv_port_alloc,
|
||||
Domain &srv_domain,
|
||||
Link_side_id const &srv_id,
|
||||
Timer::Connection &timer,
|
||||
Configuration &config,
|
||||
L3_protocol const protocol)
|
||||
Tcp_link::Tcp_link(Interface &cln_interface,
|
||||
Link_side_id const &cln_id,
|
||||
Pointer<Port_allocator_guard> srv_port_alloc,
|
||||
Domain &srv_domain,
|
||||
Link_side_id const &srv_id,
|
||||
Timer::Connection &timer,
|
||||
Configuration &config,
|
||||
L3_protocol const protocol)
|
||||
:
|
||||
Link(cln_interface, cln_id, srv_port_alloc, srv_domain, srv_id, timer,
|
||||
config, protocol, config.tcp_idle_timeout())
|
||||
@ -188,7 +219,7 @@ Tcp_link::Tcp_link(Interface &cln_interface,
|
||||
void Tcp_link::_fin_acked()
|
||||
{
|
||||
if (_server_fin_acked && _client_fin_acked) {
|
||||
_dissolve_timeout.schedule(Microseconds(config().tcp_max_segm_lifetime().value << 1));
|
||||
_dissolve_timeout.schedule(Microseconds(_config().tcp_max_segm_lifetime().value << 1));
|
||||
_closed = true;
|
||||
}
|
||||
}
|
||||
@ -232,14 +263,14 @@ void Tcp_link::client_packet(Tcp_packet &tcp)
|
||||
** Udp_link **
|
||||
**************/
|
||||
|
||||
Udp_link::Udp_link(Interface &cln_interface,
|
||||
Link_side_id const &cln_id,
|
||||
Pointer<Port_allocator_guard> const srv_port_alloc,
|
||||
Domain &srv_domain,
|
||||
Link_side_id const &srv_id,
|
||||
Timer::Connection &timer,
|
||||
Configuration &config,
|
||||
L3_protocol const protocol)
|
||||
Udp_link::Udp_link(Interface &cln_interface,
|
||||
Link_side_id const &cln_id,
|
||||
Pointer<Port_allocator_guard> srv_port_alloc,
|
||||
Domain &srv_domain,
|
||||
Link_side_id const &srv_id,
|
||||
Timer::Connection &timer,
|
||||
Configuration &config,
|
||||
L3_protocol const protocol)
|
||||
:
|
||||
Link(cln_interface, cln_id, srv_port_alloc, srv_domain, srv_id, timer,
|
||||
config, protocol, config.udp_idle_timeout())
|
||||
|
@ -38,6 +38,8 @@
|
||||
#include <net/port.h>
|
||||
|
||||
/* local includes */
|
||||
#include <list.h>
|
||||
#include <reference.h>
|
||||
#include <pointer.h>
|
||||
#include <l3_protocol.h>
|
||||
|
||||
@ -52,7 +54,7 @@ namespace Net {
|
||||
class Link_side;
|
||||
class Link_side_tree;
|
||||
class Link;
|
||||
struct Link_list : Genode::List<Link> { };
|
||||
struct Link_list : List<Link> { };
|
||||
class Tcp_link;
|
||||
class Udp_link;
|
||||
}
|
||||
@ -87,7 +89,7 @@ class Net::Link_side : public Genode::Avl_node<Link_side>
|
||||
|
||||
private:
|
||||
|
||||
Domain &_domain;
|
||||
Reference<Domain> _domain;
|
||||
Link_side_id const _id;
|
||||
Link &_link;
|
||||
|
||||
@ -120,7 +122,7 @@ class Net::Link_side : public Genode::Avl_node<Link_side>
|
||||
** Accessors **
|
||||
***************/
|
||||
|
||||
Domain &domain() const { return _domain; }
|
||||
Domain &domain() const { return _domain(); }
|
||||
Link &link() const { return _link; }
|
||||
Ipv4_address const &src_ip() const { return _id.src_ip; }
|
||||
Ipv4_address const &dst_ip() const { return _id.dst_ip; }
|
||||
@ -141,14 +143,14 @@ class Net::Link : public Link_list::Element
|
||||
{
|
||||
protected:
|
||||
|
||||
Configuration &_config;
|
||||
Interface &_client_interface;
|
||||
Pointer<Port_allocator_guard> const _server_port_alloc;
|
||||
Timer::One_shot_timeout<Link> _dissolve_timeout;
|
||||
Genode::Microseconds const _dissolve_timeout_us;
|
||||
L3_protocol const _protocol;
|
||||
Link_side _client;
|
||||
Link_side _server;
|
||||
Reference<Configuration> _config;
|
||||
Interface &_client_interface;
|
||||
Pointer<Port_allocator_guard> _server_port_alloc;
|
||||
Timer::One_shot_timeout<Link> _dissolve_timeout;
|
||||
Genode::Microseconds _dissolve_timeout_us;
|
||||
L3_protocol const _protocol;
|
||||
Link_side _client;
|
||||
Link_side _server;
|
||||
|
||||
void _handle_dissolve_timeout(Genode::Duration);
|
||||
|
||||
@ -160,7 +162,7 @@ class Net::Link : public Link_list::Element
|
||||
|
||||
Link(Interface &cln_interface,
|
||||
Link_side_id const &cln_id,
|
||||
Pointer<Port_allocator_guard> const srv_port_alloc,
|
||||
Pointer<Port_allocator_guard> srv_port_alloc,
|
||||
Domain &srv_domain,
|
||||
Link_side_id const &srv_id,
|
||||
Timer::Connection &timer,
|
||||
@ -170,6 +172,10 @@ class Net::Link : public Link_list::Element
|
||||
|
||||
void dissolve();
|
||||
|
||||
void handle_config(Domain &cln_domain,
|
||||
Domain &srv_domain,
|
||||
Pointer<Port_allocator_guard> srv_port_alloc,
|
||||
Configuration &config);
|
||||
|
||||
/*********
|
||||
** Log **
|
||||
@ -184,7 +190,7 @@ class Net::Link : public Link_list::Element
|
||||
|
||||
Link_side &client() { return _client; }
|
||||
Link_side &server() { return _server; }
|
||||
Configuration &config() { return _config; }
|
||||
Configuration &config() { return _config(); }
|
||||
L3_protocol protocol() const { return _protocol; }
|
||||
};
|
||||
|
||||
@ -203,14 +209,14 @@ class Net::Tcp_link : public Link
|
||||
|
||||
public:
|
||||
|
||||
Tcp_link(Interface &cln_interface,
|
||||
Link_side_id const &cln_id,
|
||||
Pointer<Port_allocator_guard> const srv_port_alloc,
|
||||
Domain &srv_domain,
|
||||
Link_side_id const &srv_id,
|
||||
Timer::Connection &timer,
|
||||
Configuration &config,
|
||||
L3_protocol const protocol);
|
||||
Tcp_link(Interface &cln_interface,
|
||||
Link_side_id const &cln_id,
|
||||
Pointer<Port_allocator_guard> srv_port_alloc,
|
||||
Domain &srv_domain,
|
||||
Link_side_id const &srv_id,
|
||||
Timer::Connection &timer,
|
||||
Configuration &config,
|
||||
L3_protocol const protocol);
|
||||
|
||||
void client_packet(Tcp_packet &tcp);
|
||||
|
||||
@ -220,14 +226,14 @@ class Net::Tcp_link : public Link
|
||||
|
||||
struct Net::Udp_link : Link
|
||||
{
|
||||
Udp_link(Interface &cln_interface,
|
||||
Link_side_id const &cln_id,
|
||||
Pointer<Port_allocator_guard> const srv_port_alloc,
|
||||
Domain &srv_domain,
|
||||
Link_side_id const &srv_id,
|
||||
Timer::Connection &timer,
|
||||
Configuration &config,
|
||||
L3_protocol const protocol);
|
||||
Udp_link(Interface &cln_interface,
|
||||
Link_side_id const &cln_id,
|
||||
Pointer<Port_allocator_guard> srv_port_alloc,
|
||||
Domain &srv_domain,
|
||||
Link_side_id const &srv_id,
|
||||
Timer::Connection &timer,
|
||||
Configuration &config,
|
||||
L3_protocol const protocol);
|
||||
|
||||
void packet() { _packet(); }
|
||||
};
|
||||
|
@ -26,17 +26,39 @@
|
||||
using namespace Net;
|
||||
using namespace Genode;
|
||||
|
||||
namespace Net { class Main; }
|
||||
|
||||
class Main
|
||||
|
||||
class Net::Main
|
||||
{
|
||||
private:
|
||||
|
||||
Timer::Connection _timer;
|
||||
Genode::Heap _heap;
|
||||
Genode::Attached_rom_dataspace _config_rom;
|
||||
Configuration _config;
|
||||
Uplink _uplink;
|
||||
Net::Root _root;
|
||||
Genode::Env &_env;
|
||||
Interface_list _interfaces { };
|
||||
Timer::Connection _timer { _env };
|
||||
Genode::Heap _heap { &_env.ram(), &_env.rm() };
|
||||
Genode::Attached_rom_dataspace _config_rom { _env, "config" };
|
||||
Reference<Configuration> _config { _init_config() };
|
||||
Signal_handler<Main> _config_handler { _env.ep(), *this, &Main::_handle_config };
|
||||
Uplink _uplink { _env, _timer, _heap, _interfaces, _config() };
|
||||
Root _root { _env.ep(), _timer, _heap, _uplink.router_mac(), _config(), _env.ram(), _interfaces, _env.rm()};
|
||||
|
||||
void _handle_config();
|
||||
|
||||
Configuration &_init_config();
|
||||
|
||||
template <typename FUNC>
|
||||
void _for_each_interface(FUNC && functor)
|
||||
{
|
||||
_interfaces.for_each([&] (Interface &interface) {
|
||||
functor(interface);
|
||||
});
|
||||
_config().domains().for_each([&] (Domain &domain) {
|
||||
domain.interfaces().for_each([&] (Interface &interface) {
|
||||
functor(interface);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
@ -44,24 +66,47 @@ class Main
|
||||
};
|
||||
|
||||
|
||||
Main::Main(Env &env)
|
||||
:
|
||||
_timer(env), _heap(&env.ram(), &env.rm()), _config_rom(env, "config"),
|
||||
_config(env, _config_rom.xml(), _heap, _timer),
|
||||
_uplink(env, _timer, _heap, _config),
|
||||
_root(env.ep(), _timer, _heap, _uplink.router_mac(), _config,
|
||||
env.ram(), env.rm())
|
||||
Configuration &Net::Main::_init_config()
|
||||
{
|
||||
Configuration &config_legacy = *new (_heap)
|
||||
Configuration(_config_rom.xml(), _heap);
|
||||
|
||||
Configuration &config = *new (_heap)
|
||||
Configuration(_env, _config_rom.xml(), _heap, _timer, config_legacy);
|
||||
|
||||
destroy(_heap, &config_legacy);
|
||||
return config;
|
||||
}
|
||||
|
||||
|
||||
Net::Main::Main(Env &env) : _env(env)
|
||||
{
|
||||
_config_rom.sigh(_config_handler);
|
||||
env.parent().announce(env.ep().manage(_root));
|
||||
}
|
||||
|
||||
|
||||
void Net::Main::_handle_config()
|
||||
{
|
||||
_config_rom.update();
|
||||
Configuration &config = *new (_heap)
|
||||
Configuration(_env, _config_rom.xml(), _heap, _timer, _config());
|
||||
|
||||
_root.handle_config(config);
|
||||
_for_each_interface([&] (Interface &intf) { intf.handle_config(config); });
|
||||
_for_each_interface([&] (Interface &intf) { intf.handle_config_aftermath(); });
|
||||
|
||||
destroy(_heap, &_config());
|
||||
_config = Reference<Configuration>(config);
|
||||
}
|
||||
|
||||
|
||||
void Component::construct(Env &env)
|
||||
{
|
||||
/* XXX execute constructors of global statics */
|
||||
env.exec_static_constructors();
|
||||
|
||||
try { static Main main(env); }
|
||||
try { static Net::Main main(env); }
|
||||
|
||||
catch (Net::Domain_tree::No_match) {
|
||||
error("failed to find configuration for domain 'uplink'");
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <port_allocator.h>
|
||||
#include <leaf_rule.h>
|
||||
#include <l3_protocol.h>
|
||||
#include <avl_tree.h>
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/avl_string.h>
|
||||
@ -74,7 +75,7 @@ class Net::Nat_rule : public Leaf_rule,
|
||||
};
|
||||
|
||||
|
||||
struct Net::Nat_rule_tree : Genode::Avl_tree<Nat_rule>
|
||||
struct Net::Nat_rule_tree : Avl_tree<Nat_rule>
|
||||
{
|
||||
struct No_match : Genode::Exception { };
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
/* local includes */
|
||||
#include <leaf_rule.h>
|
||||
#include <avl_tree.h>
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/avl_tree.h>
|
||||
@ -25,6 +26,8 @@ namespace Genode { class Output; }
|
||||
|
||||
namespace Net {
|
||||
|
||||
class Interface;
|
||||
|
||||
class Permit_rule;
|
||||
class Permit_any_rule;
|
||||
class Permit_single_rule;
|
||||
@ -34,6 +37,8 @@ namespace Net {
|
||||
|
||||
struct Net::Permit_rule : private Leaf_rule, public Genode::Interface
|
||||
{
|
||||
friend class Interface;
|
||||
|
||||
Permit_rule(Domain_tree &domains, Genode::Xml_node const node);
|
||||
|
||||
using Leaf_rule::domain;
|
||||
@ -64,11 +69,12 @@ struct Net::Permit_any_rule : Permit_rule
|
||||
class Net::Permit_single_rule : public Permit_rule,
|
||||
private Genode::Avl_node<Permit_single_rule>
|
||||
{
|
||||
private:
|
||||
friend class Genode::Avl_node<Permit_single_rule>;
|
||||
friend class Genode::Avl_tree<Permit_single_rule>;
|
||||
friend class Avl_tree<Permit_single_rule>;
|
||||
friend class Net::Permit_single_rule_tree;
|
||||
|
||||
friend class Genode::Avl_node<Permit_single_rule>;
|
||||
friend class Genode::Avl_tree<Permit_single_rule>;
|
||||
friend class Net::Permit_single_rule_tree;
|
||||
private:
|
||||
|
||||
Port const _port;
|
||||
|
||||
@ -102,8 +108,10 @@ class Net::Permit_single_rule : public Permit_rule,
|
||||
};
|
||||
|
||||
|
||||
struct Net::Permit_single_rule_tree : private Genode::Avl_tree<Permit_single_rule>
|
||||
struct Net::Permit_single_rule_tree : private Avl_tree<Permit_single_rule>
|
||||
{
|
||||
friend class Transport_rule;
|
||||
|
||||
struct No_match : Genode::Exception { };
|
||||
|
||||
void insert(Permit_single_rule *rule)
|
||||
|
@ -20,14 +20,14 @@ using namespace Net;
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
Net::Report::Report(Env &env,
|
||||
Xml_node const node,
|
||||
Net::Report::Report(Xml_node const node,
|
||||
Timer::Connection &timer,
|
||||
Domain_tree &domains)
|
||||
Domain_tree &domains,
|
||||
Reporter &reporter)
|
||||
:
|
||||
_config(node.attribute_value("config", true)),
|
||||
_bytes (node.attribute_value("bytes", true)),
|
||||
_reporter(env, "state"),
|
||||
_reporter(reporter),
|
||||
_domains(domains),
|
||||
_timeout(timer, *this, &Report::_handle_report_timeout,
|
||||
read_sec_attr(node, "interval_sec", 5))
|
||||
@ -36,7 +36,6 @@ Net::Report::Report(Env &env,
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Net::Report::_handle_report_timeout(Duration)
|
||||
{
|
||||
try {
|
||||
|
@ -37,7 +37,7 @@ class Net::Report
|
||||
|
||||
bool const _config;
|
||||
bool const _bytes;
|
||||
Genode::Reporter _reporter;
|
||||
Genode::Reporter &_reporter;
|
||||
Domain_tree &_domains;
|
||||
Timer::Periodic_timeout<Report> _timeout;
|
||||
|
||||
@ -45,10 +45,10 @@ class Net::Report
|
||||
|
||||
public:
|
||||
|
||||
Report(Genode::Env &env,
|
||||
Genode::Xml_node const node,
|
||||
Report(Genode::Xml_node const node,
|
||||
Timer::Connection &timer,
|
||||
Domain_tree &domains);
|
||||
Domain_tree &domains,
|
||||
Genode::Reporter &reporter);
|
||||
|
||||
|
||||
/***************
|
||||
|
@ -24,17 +24,19 @@ using namespace Net;
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
Permit_any_rule *Transport_rule::_read_permit_any(Domain_tree &domains,
|
||||
Xml_node const node,
|
||||
Allocator &alloc)
|
||||
Pointer<Permit_any_rule>
|
||||
Transport_rule::_read_permit_any_rule(Domain_tree &domains,
|
||||
Xml_node const node,
|
||||
Allocator &alloc)
|
||||
{
|
||||
try {
|
||||
Xml_node sub_node = node.sub_node("permit-any");
|
||||
return new (alloc) Permit_any_rule(domains, sub_node);
|
||||
return Pointer<Permit_any_rule>(*new (alloc)
|
||||
Permit_any_rule(domains, sub_node));
|
||||
}
|
||||
catch (Xml_node::Nonexistent_sub_node) { }
|
||||
catch (Rule::Invalid) { warning("invalid permit-any rule"); }
|
||||
return nullptr;
|
||||
return Pointer<Permit_any_rule>();
|
||||
}
|
||||
|
||||
|
||||
@ -44,15 +46,18 @@ Transport_rule::Transport_rule(Domain_tree &domains,
|
||||
Cstring const &protocol,
|
||||
Configuration &config)
|
||||
:
|
||||
Direct_rule(node), _permit_any(_read_permit_any(domains, node, alloc))
|
||||
Direct_rule(node),
|
||||
_alloc(alloc),
|
||||
_permit_any_rule(_read_permit_any_rule(domains, node, alloc))
|
||||
{
|
||||
/* skip specific permit rules if all ports are permitted anyway */
|
||||
if (_permit_any) {
|
||||
try {
|
||||
Permit_any_rule &permit_any_rule = _permit_any_rule.deref();
|
||||
if (config.verbose()) {
|
||||
log(" ", protocol, " rule: ", _dst, " ", *_permit_any); }
|
||||
log(" ", protocol, " rule: ", _dst, " ", permit_any_rule); }
|
||||
|
||||
return;
|
||||
}
|
||||
} catch (Pointer<Permit_any_rule>::Invalid) { }
|
||||
|
||||
/* read specific permit rules */
|
||||
node.for_each_sub_node("permit", [&] (Xml_node const node) {
|
||||
@ -72,8 +77,17 @@ Transport_rule::Transport_rule(Domain_tree &domains,
|
||||
}
|
||||
|
||||
|
||||
Transport_rule::~Transport_rule()
|
||||
{
|
||||
_permit_single_rules.destroy_each(_alloc);
|
||||
try { destroy(_alloc, &_permit_any_rule.deref()); }
|
||||
catch (Pointer<Permit_any_rule>::Invalid) { }
|
||||
}
|
||||
|
||||
|
||||
Permit_rule const &Transport_rule::permit_rule(Port const port) const
|
||||
{
|
||||
if (_permit_any) { return *_permit_any; }
|
||||
try { return _permit_any_rule.deref(); }
|
||||
catch (Pointer<Permit_any_rule>::Invalid) { }
|
||||
return _permit_single_rules.find_by_port(port);
|
||||
}
|
||||
|
@ -17,6 +17,7 @@
|
||||
/* local includes */
|
||||
#include <direct_rule.h>
|
||||
#include <permit_rule.h>
|
||||
#include <pointer.h>
|
||||
|
||||
namespace Genode { class Allocator; }
|
||||
|
||||
@ -32,19 +33,14 @@ class Net::Transport_rule : public Direct_rule<Transport_rule>
|
||||
{
|
||||
private:
|
||||
|
||||
/*
|
||||
* Noncopyable
|
||||
*/
|
||||
Transport_rule(Transport_rule const &);
|
||||
Transport_rule &operator = (Transport_rule const &);
|
||||
Genode::Allocator &_alloc;
|
||||
Pointer<Permit_any_rule> const _permit_any_rule;
|
||||
Permit_single_rule_tree _permit_single_rules { };
|
||||
|
||||
Permit_any_rule *const _permit_any;
|
||||
Permit_single_rule_tree _permit_single_rules { };
|
||||
|
||||
static Permit_any_rule *
|
||||
_read_permit_any(Domain_tree &domains,
|
||||
Genode::Xml_node const node,
|
||||
Genode::Allocator &alloc);
|
||||
static Pointer<Permit_any_rule>
|
||||
_read_permit_any_rule(Domain_tree &domains,
|
||||
Genode::Xml_node const node,
|
||||
Genode::Allocator &alloc);
|
||||
|
||||
public:
|
||||
|
||||
@ -54,6 +50,8 @@ class Net::Transport_rule : public Direct_rule<Transport_rule>
|
||||
Genode::Cstring const &protocol,
|
||||
Configuration &config);
|
||||
|
||||
~Transport_rule();
|
||||
|
||||
Permit_rule const &permit_rule(Port const port) const;
|
||||
};
|
||||
|
||||
|
@ -26,12 +26,13 @@ using namespace Genode;
|
||||
Net::Uplink::Uplink(Env &env,
|
||||
Timer::Connection &timer,
|
||||
Genode::Allocator &alloc,
|
||||
Interface_list &interfaces,
|
||||
Configuration &config)
|
||||
:
|
||||
Nic::Packet_allocator(&alloc),
|
||||
Nic::Connection(env, this, BUF_SIZE, BUF_SIZE),
|
||||
Net::Interface(env.ep(), timer, mac_address(), alloc, Mac_address(),
|
||||
config, _intf_policy)
|
||||
config, interfaces, _intf_policy)
|
||||
{
|
||||
rx_channel()->sigh_ready_to_ack(_sink_ack);
|
||||
rx_channel()->sigh_packet_avail(_sink_submit);
|
||||
|
@ -41,6 +41,7 @@ class Net::Uplink_base
|
||||
***************************/
|
||||
|
||||
Domain_name determine_domain_name() const override { return Genode::Cstring("uplink"); };
|
||||
void handle_config(Configuration const &) override { }
|
||||
};
|
||||
|
||||
Interface_policy _intf_policy { };
|
||||
@ -76,6 +77,7 @@ class Net::Uplink : public Uplink_base,
|
||||
Uplink(Genode::Env &env,
|
||||
Timer::Connection &timer,
|
||||
Genode::Allocator &alloc,
|
||||
Interface_list &interfaces,
|
||||
Configuration &config);
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user