mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-18 18:56:29 +00:00
nic_router: find nat rules w/o exceptions
Replaces the former implementation of the 'find_by_domain' method at the data structure for NAT rules. This method used to return a reference to the found object and threw an exception if no matching object was found. The new implementation doesn't return anything and doesn't throw exceptions. It takes two lambda arguments instead. One for handling the case that a match was found with a reference to the matching object as argument and another for handling the case that no object matches. This way, expensive exception handling can be avoided and object references stay in a local scope. Ref #4536
This commit is contained in:
parent
65955601f0
commit
6294167eff
@ -589,16 +589,19 @@ void Interface::_nat_link_and_pass(Ethernet_frame ð,
|
||||
{
|
||||
try {
|
||||
Pointer<Port_allocator_guard> remote_port_alloc;
|
||||
try {
|
||||
Nat_rule &nat = remote_domain.nat_rules().find_by_domain(local_domain);
|
||||
if(_config().verbose()) {
|
||||
log("[", local_domain, "] using NAT rule: ", nat); }
|
||||
remote_domain.nat_rules().find_by_domain(
|
||||
local_domain,
|
||||
[&] /* handle_match */ (Nat_rule &nat)
|
||||
{
|
||||
if(_config().verbose()) {
|
||||
log("[", local_domain, "] using NAT rule: ", nat); }
|
||||
|
||||
_src_port(prot, prot_base, nat.port_alloc(prot).alloc());
|
||||
ip.src(remote_domain.ip_config().interface().address);
|
||||
remote_port_alloc = nat.port_alloc(prot);
|
||||
}
|
||||
catch (Nat_rule_tree::No_match) { }
|
||||
_src_port(prot, prot_base, nat.port_alloc(prot).alloc());
|
||||
ip.src(remote_domain.ip_config().interface().address);
|
||||
remote_port_alloc = nat.port_alloc(prot);
|
||||
},
|
||||
[&] /* no_match */ () { }
|
||||
);
|
||||
Link_side_id const remote_id = { ip.dst(), _dst_port(prot, prot_base),
|
||||
ip.src(), _src_port(prot, prot_base) };
|
||||
_new_link(prot, local_id, remote_port_alloc, remote_domain, remote_id);
|
||||
@ -1869,14 +1872,28 @@ void Interface::_update_link_check_nat(Link &link,
|
||||
_dismiss_link_log(link, "NAT IP");
|
||||
throw Dismiss_link();
|
||||
}
|
||||
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 = remote_port_alloc;
|
||||
link.handle_config(cln_dom, new_srv_dom, remote_port_alloc_ptr, _config());
|
||||
return;
|
||||
bool done { false };
|
||||
new_srv_dom.nat_rules().find_by_domain(
|
||||
cln_dom,
|
||||
[&] /* handle_match */ (Nat_rule &nat)
|
||||
{
|
||||
Port_allocator_guard &remote_port_alloc = nat.port_alloc(prot);
|
||||
remote_port_alloc.alloc(link.server().dst_port());
|
||||
remote_port_alloc_ptr = remote_port_alloc;
|
||||
link.handle_config(
|
||||
cln_dom, new_srv_dom, remote_port_alloc_ptr, _config());
|
||||
|
||||
done = true;
|
||||
},
|
||||
[&] /* handle_no_match */ ()
|
||||
{
|
||||
_dismiss_link_log(link, "no NAT rule");
|
||||
}
|
||||
);
|
||||
if (done) {
|
||||
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();
|
||||
|
@ -57,30 +57,6 @@ Nat_rule::Nat_rule(Domain_tree &domains,
|
||||
{ }
|
||||
|
||||
|
||||
Nat_rule &Nat_rule::find_by_domain(Domain &domain)
|
||||
{
|
||||
if (&domain == &_domain) {
|
||||
return *this; }
|
||||
|
||||
bool const side = (addr_t)&domain > (addr_t)&_domain;
|
||||
Nat_rule *const rule = Avl_node<Nat_rule>::child(side);
|
||||
if (!rule) {
|
||||
throw Nat_rule_tree::No_match(); }
|
||||
|
||||
return rule->find_by_domain(domain);
|
||||
}
|
||||
|
||||
|
||||
Nat_rule &Nat_rule_tree::find_by_domain(Domain &domain)
|
||||
{
|
||||
Nat_rule *const rule = first();
|
||||
if (!rule) {
|
||||
throw No_match(); }
|
||||
|
||||
return rule->find_by_domain(domain);
|
||||
}
|
||||
|
||||
|
||||
void Nat_rule::print(Output &output) const
|
||||
{
|
||||
Genode::print(output, "domain ", _domain,
|
||||
|
@ -59,6 +59,35 @@ class Net::Nat_rule : public Genode::Avl_node<Nat_rule>
|
||||
|
||||
Nat_rule &find_by_domain(Domain &domain);
|
||||
|
||||
template <typename HANDLE_MATCH_FN,
|
||||
typename HANDLE_NO_MATCH_FN>
|
||||
|
||||
void find_by_domain(Domain &domain,
|
||||
HANDLE_MATCH_FN && handle_match,
|
||||
HANDLE_NO_MATCH_FN && handle_no_match)
|
||||
{
|
||||
if (&domain != &_domain) {
|
||||
|
||||
Nat_rule *const rule_ptr {
|
||||
Avl_node<Nat_rule>::child(
|
||||
(Genode::addr_t)&domain > (Genode::addr_t)&_domain) };
|
||||
|
||||
if (rule_ptr != nullptr) {
|
||||
|
||||
rule_ptr->find_by_domain(
|
||||
domain, handle_match, handle_no_match);
|
||||
|
||||
} else {
|
||||
|
||||
handle_no_match();
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
handle_match(*this);
|
||||
}
|
||||
}
|
||||
|
||||
Port_allocator_guard &port_alloc(L3_protocol const prot);
|
||||
|
||||
|
||||
@ -89,9 +118,22 @@ class Net::Nat_rule : public Genode::Avl_node<Nat_rule>
|
||||
|
||||
struct Net::Nat_rule_tree : Avl_tree<Nat_rule>
|
||||
{
|
||||
struct No_match : Genode::Exception { };
|
||||
template <typename HANDLE_MATCH_FN,
|
||||
typename HANDLE_NO_MATCH_FN>
|
||||
|
||||
Nat_rule &find_by_domain(Domain &domain);
|
||||
void find_by_domain(Domain &domain,
|
||||
HANDLE_MATCH_FN && handle_match,
|
||||
HANDLE_NO_MATCH_FN && handle_no_match)
|
||||
{
|
||||
if (first() != nullptr) {
|
||||
|
||||
first()->find_by_domain(domain, handle_match, handle_no_match);
|
||||
|
||||
} else {
|
||||
|
||||
handle_no_match();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _NAT_RULE_H_ */
|
||||
|
Loading…
Reference in New Issue
Block a user