nic_router: generic Avl_string_tree

The generic helper Avl_string_tree of the NIC router is currently only
used for finding domains via their names, but in the future it can be
used for finding uplinks by their labels also. Additionally, it enables
us to throw an exception when inserting two elements with the same
identifier.

Issue #2840
This commit is contained in:
Martin Stein 2018-06-01 21:45:18 +02:00 committed by Christian Helmuth
parent 193e14a489
commit 8004d8757f
4 changed files with 90 additions and 96 deletions

View File

@ -0,0 +1,82 @@
/*
* \brief AVL tree of strings with additional functions needed by NIC router
* \author Martin Stein
* \date 2016-08-19
*/
/*
* Copyright (C) 2016-2017 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _AVL_STRING_TREE_H_
#define _AVL_STRING_TREE_H_
/* Genode includes */
#include <util/avl_string.h>
#include <base/allocator.h>
namespace Net { template <typename, typename> class Avl_string_tree; }
template <typename OBJECT,
typename NAME>
class Net::Avl_string_tree : public Genode::Avl_tree<Genode::Avl_string_base>
{
private:
using Node = Genode::Avl_string_base;
using Tree = Genode::Avl_tree<Genode::Avl_string_base>;
OBJECT &_find_by_name(char const *name)
{
if (!first()) {
throw No_match(); }
Node *node = first()->find_by_name(name);
if (!node) {
throw No_match(); }
return *static_cast<OBJECT *>(node);
}
public:
struct No_match : Genode::Exception { };
OBJECT &find_by_name(NAME const &name) { return _find_by_name(name.string()); }
template <typename FUNCTOR>
void for_each(FUNCTOR && functor) const {
Tree::for_each([&] (Node const &node) {
/*
* FIXME This constness cast sneaked in with an older
* implementation where it was done implicitely and
* therefore not that obvious. Now the router relies on
* it and we should either get rid of the dependency to
* const Avl_tree::for_each or of the the need for
* mutable objects in Avl_string_tree::for_each.
*/
functor(*const_cast<OBJECT *>(static_cast<OBJECT const *>(&node)));
});
}
void destroy_each(Genode::Deallocator &dealloc)
{
while (Node *node = first()) {
Tree::remove(node);
Genode::destroy(dealloc, static_cast<OBJECT *>(node));
}
}
void insert(OBJECT &object) { Tree::insert(&object); }
void remove(OBJECT &object) { Tree::remove(&object); }
};
#endif /* _AVL_STRING_TREE_H_ */

View File

@ -26,17 +26,6 @@ using namespace Net;
using namespace Genode;
/***********************
** Domain_avl_member **
***********************/
Domain_avl_member::Domain_avl_member(Domain_name const &name,
Domain &domain)
:
Avl_string_base(name.string()), _domain(domain)
{ }
/*****************
** Domain_base **
*****************/
@ -184,7 +173,7 @@ void Domain::print(Output &output) const
Domain::Domain(Configuration &config, Xml_node const node, Allocator &alloc)
:
Domain_base(node), _avl_member(_name, *this), _config(config),
Domain_base(node), Avl_string_base(_name.string()), _config(config),
_node(node), _alloc(alloc),
_ip_config(_node.attribute_value("interface", Ipv4_address_prefix()),
_node.attribute_value("gateway", Ipv4_address()),
@ -358,36 +347,3 @@ void Domain::report(Xml_generator &xml)
}
});
}
/*****************
** Domain_tree **
*****************/
Domain &Domain_tree::domain(Avl_string_base const &node)
{
return static_cast<Domain_avl_member const *>(&node)->domain();
}
Domain &Domain_tree::find_by_name(Domain_name name)
{
if (name == Domain_name() || !first()) {
throw No_match(); }
Avl_string_base *node = first()->find_by_name(name.string());
if (!node) {
throw No_match(); }
return domain(*node);
}
void Domain_tree::destroy_each(Deallocator &dealloc)
{
while (Avl_string_base *first_ = first()) {
Domain &domain_ = domain(*first_);
Avl_tree::remove(first_);
destroy(dealloc, &domain_);
}
}

View File

@ -25,9 +25,9 @@
#include <ipv4_config.h>
#include <dhcp_server.h>
#include <interface.h>
#include <avl_string_tree.h>
/* Genode includes */
#include <util/avl_string.h>
#include <util/reconstructible.h>
namespace Genode {
@ -40,32 +40,14 @@ namespace Net {
class Interface;
class Configuration;
class Domain_avl_member;
class Domain_base;
class Domain;
class Domain_tree;
using Domain_name = Genode::String<160>;
class Domain_tree;
}
class Net::Domain_avl_member : public Genode::Avl_string_base
{
private:
Domain &_domain;
public:
Domain_avl_member(Domain_name const &name,
Domain &domain);
/***************
** Accessors **
***************/
Domain &domain() const { return _domain; }
};
class Net::Domain_tree : public Avl_string_tree<Domain, Domain_name> { };
class Net::Domain_base
@ -79,11 +61,11 @@ class Net::Domain_base
class Net::Domain : public Domain_base,
public List<Domain>::Element
public List<Domain>::Element,
public Genode::Avl_string_base
{
private:
Domain_avl_member _avl_member;
Configuration &_config;
Genode::Xml_node _node;
Genode::Allocator &_alloc;
@ -194,7 +176,6 @@ class Net::Domain : public Domain_base,
Nat_rule_tree &nat_rules() { return _nat_rules; }
Interface_list &interfaces() { return _interfaces; }
Configuration &config() const { return _config; }
Domain_avl_member &avl_member() { return _avl_member; }
Dhcp_server &dhcp_server();
Arp_cache &arp_cache() { return _arp_cache; }
Arp_waiter_list &foreign_arp_waiters() { return _foreign_arp_waiters; }
@ -203,29 +184,4 @@ class Net::Domain : public Domain_base,
Link_side_tree &icmp_links() { return _icmp_links; }
};
struct Net::Domain_tree : Genode::Avl_tree<Genode::Avl_string_base>
{
using Avl_tree = Genode::Avl_tree<Genode::Avl_string_base>;
struct No_match : Genode::Exception { };
static Domain &domain(Genode::Avl_string_base const &node);
Domain &find_by_name(Domain_name name);
template <typename FUNC>
void for_each(FUNC && functor) const {
Avl_tree::for_each([&] (Genode::Avl_string_base const &node) {
functor(domain(node));
});
}
void insert(Domain &domain) { Avl_tree::insert(&domain.avl_member()); }
void remove(Domain &domain) { Avl_tree::remove(&domain.avl_member()); }
void destroy_each(Genode::Deallocator &dealloc);
};
#endif /* _DOMAIN_H_ */

View File

@ -31,8 +31,8 @@ Domain &Forward_rule::_find_domain(Domain_tree &domains,
Xml_node const node)
{
try {
return domains.find_by_name(
node.attribute_value("domain", Domain_name()));
Domain_name const domain_name = node.attribute_value("domain", Domain_name());
return domains.find_by_name(domain_name);
}
catch (Domain_tree::No_match) { throw Invalid(); }
}