nic_router: encapsulate IPv4 peer config in class

An IPv4 config (for a domain/interface of the router) consists of
an IPv4 address, a subnet prefix specifier, an optional gateway
IPv4 address, and some flags that declare whether these fields and
the config as a whole are valid. To make the handling of those
tightly connected values easier and less error prone, we encapsulate
them in a new class.

Ref #2534
This commit is contained in:
Martin Stein 2017-10-13 16:22:05 +02:00 committed by Christian Helmuth
parent 0ca248551a
commit 3560555acc
7 changed files with 93 additions and 22 deletions

View File

@ -160,19 +160,17 @@ Domain::Domain(Configuration &config, Xml_node const node, Allocator &alloc)
:
Domain_base(node), _avl_member(_name, *this), _config(config),
_node(node), _alloc(alloc),
_interface_attr(node.attribute_value("interface", Ipv4_address_prefix())),
_gateway(node.attribute_value("gateway", Ipv4_address())),
_gateway_valid(_gateway.valid())
_ip_config(_node.attribute_value("interface", Ipv4_address_prefix()),
_node.attribute_value("gateway", Ipv4_address()))
{
if (_name == Domain_name() || !_interface_attr.valid() ||
(_gateway_valid && !_interface_attr.prefix_matches(_gateway)))
{
if (_name == Domain_name() || !_ip_config.interface_valid) {
throw Invalid();
}
/* try to find configuration for DHCP server role */
try {
_dhcp_server.set(*new (alloc)
Dhcp_server(node.sub_node("dhcp-server"), alloc, _interface_attr));
Dhcp_server(node.sub_node("dhcp-server"), alloc,
_ip_config.interface));
if (_config.verbose()) {
log(" DHCP server: ", _dhcp_server.deref()); }
@ -221,8 +219,8 @@ void Domain::create_rules(Domain_tree &domains)
Ipv4_address const &Domain::next_hop(Ipv4_address const &ip) const
{
if (_interface_attr.prefix_matches(ip)) { return ip; }
if (_gateway_valid) { return _gateway; }
if (_ip_config.interface.prefix_matches(ip)) { return ip; }
if (_ip_config.gateway_valid) { return _ip_config.gateway; }
throw No_next_hop();
}

View File

@ -22,6 +22,7 @@
#include <port_allocator.h>
#include <pointer.h>
#include <bit_allocator_dynamic.h>
#include <ipv4_config.h>
/* Genode includes */
#include <util/avl_string.h>
@ -128,9 +129,6 @@ class Net::Domain : public Domain_base
Configuration &_config;
Genode::Xml_node _node;
Genode::Allocator &_alloc;
Ipv4_address_prefix _interface_attr;
Ipv4_address const _gateway;
bool const _gateway_valid;
Ip_rule_list _ip_rules;
Forward_rule_tree _tcp_forward_rules;
Forward_rule_tree _udp_forward_rules;
@ -141,6 +139,7 @@ class Net::Domain : public Domain_base
Nat_rule_tree _nat_rules;
Pointer<Interface> _interface;
Pointer<Dhcp_server> _dhcp_server;
Ipv4_config _ip_config;
void _read_forward_rules(Genode::Cstring const &protocol,
Domain_tree &domains,
@ -181,15 +180,14 @@ class Net::Domain : public Domain_base
** Accessors **
***************/
bool gateway_valid() const { return _gateway_valid; }
Domain_name const &name() { return _name; }
Ipv4_config const &ip_config() const { return _ip_config; }
Domain_name const &name() { 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; }
Ipv4_address_prefix &interface_attr() { return _interface_attr; }
Pointer<Interface> &interface() { return _interface; }
Configuration &config() const { return _config; }
Domain_avl_member &avl_member() { return _avl_member; }

View File

@ -399,11 +399,11 @@ void Interface::_send_dhcp_reply(Dhcp_server const &dhcp_srv,
reply_dhcp_opts.append_option<Dhcp_packet::Message_type_option>(msg_type);
reply_dhcp_opts.append_option<Dhcp_packet::Server_ipv4>(_router_ip());
reply_dhcp_opts.append_option<Dhcp_packet::Ip_lease_time>(dhcp_srv.ip_lease_time().value / 1000 / 1000);
reply_dhcp_opts.append_option<Dhcp_packet::Subnet_mask>(_domain.interface_attr().subnet_mask());
reply_dhcp_opts.append_option<Dhcp_packet::Subnet_mask>(_ip_config().interface.subnet_mask());
reply_dhcp_opts.append_option<Dhcp_packet::Router_ipv4>(_router_ip());
if (dhcp_srv.dns_server().valid()) {
reply_dhcp_opts.append_option<Dhcp_packet::Dns_server_ipv4>(dhcp_srv.dns_server()); }
reply_dhcp_opts.append_option<Dhcp_packet::Broadcast_addr>(_domain.interface_attr().broadcast_address());
reply_dhcp_opts.append_option<Dhcp_packet::Broadcast_addr>(_ip_config().interface.broadcast_address());
reply_dhcp_opts.append_option<Dhcp_packet::Options_end>();
/* fill in header values that need the packet to be complete already */
@ -723,7 +723,7 @@ void Interface::_handle_arp_reply(Arp_packet &arp)
Ipv4_address const &Interface::_router_ip() const
{
return _domain.interface_attr().address;
return _ip_config().interface.address;
}
@ -739,8 +739,8 @@ void Interface::_handle_arp_request(Ethernet_frame &eth,
* attribute.
*/
if (arp.dst_ip() != _router_ip() &&
(_domain.gateway_valid() ||
_domain.interface_attr().prefix_matches(arp.dst_ip())))
(_ip_config().gateway_valid ||
_ip_config().interface.prefix_matches(arp.dst_ip())))
{
if (_config().verbose()) {
log("Ignore ARP request"); }
@ -913,7 +913,7 @@ Interface::Interface(Entrypoint &ep,
log("Interface connected ", *this);
log(" MAC ", _mac);
log(" Router identity: MAC ", _router_mac, " IP ",
_router_ip(), "/", _domain.interface_attr().prefix);
_router_ip(), "/", _ip_config().interface.prefix);
}
_domain.interface().set(*this);
}
@ -967,6 +967,9 @@ Interface::~Interface()
Configuration &Interface::_config() const { return _domain.config(); }
Ipv4_config const &Interface::_ip_config() const { return _domain.ip_config(); }
void Interface::print(Output &output) const
{
Genode::print(output, "\"", _domain.name(), "\"");

View File

@ -29,6 +29,7 @@ namespace Net {
using Packet_descriptor = ::Nic::Packet_descriptor;
using Packet_stream_sink = ::Nic::Packet_stream_sink< ::Nic::Session::Policy>;
using Packet_stream_source = ::Nic::Packet_stream_source< ::Nic::Session::Policy>;
class Ipv4_config;
class Forward_rule_tree;
class Transport_rule_list;
class Ethernet_frame;
@ -210,6 +211,8 @@ class Net::Interface
Configuration &_config() const;
Ipv4_config const &_ip_config() const;
Ipv4_address const &_router_ip() const;
void _handle_eth(void *const eth_base,

View File

@ -0,0 +1,31 @@
/*
* \brief IPv4 peer configuration
* \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.
*/
/* Genode includes */
#include <base/log.h>
/* local includes */
#include <ipv4_config.h>
using namespace Genode;
using namespace Net;
Ipv4_config::Ipv4_config(Ipv4_address_prefix interface,
Ipv4_address gateway)
:
interface(interface), gateway(gateway)
{
if (!valid && (interface_valid || gateway_valid)) {
error("Bad IP configuration");
}
}

View File

@ -0,0 +1,38 @@
/*
* \brief IPv4 peer configuration
* \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 _IPV4_CONFIG_H_
#define _IPV4_CONFIG_H_
/* local includes */
#include <ipv4_address_prefix.h>
namespace Net { class Ipv4_config; }
struct Net::Ipv4_config
{
Ipv4_address_prefix const interface;
bool const interface_valid { interface.valid() };
Ipv4_address const gateway;
bool const gateway_valid { gateway.valid() };
bool const valid { interface_valid &&
(!gateway_valid ||
interface.prefix_matches(gateway)) };
Ipv4_config(Ipv4_address_prefix interface,
Ipv4_address gateway);
Ipv4_config() { }
};
#endif /* _IPV4_CONFIG_H_ */

View File

@ -4,7 +4,7 @@ LIBS += base net
SRC_CC += arp_waiter.cc ip_rule.cc ipv4_address_prefix.cc
SRC_CC += component.cc port_allocator.cc forward_rule.cc
SRC_CC += nat_rule.cc mac_allocator.cc main.cc
SRC_CC += nat_rule.cc mac_allocator.cc main.cc ipv4_config.cc
SRC_CC += uplink.cc interface.cc arp_cache.cc configuration.cc
SRC_CC += domain.cc l3_protocol.cc direct_rule.cc link.cc
SRC_CC += transport_rule.cc leaf_rule.cc permit_rule.cc