genode/repos/os/src/server/nic_router/link.h

284 lines
7.4 KiB
C++

/*
* \brief State tracking for ICMP/UDP//TCP connections
* \author Martin Stein
* \date 2016-08-19
*
* A link is in the UDP/ICMP case the state tracking of a pseudo UDP/ICMP
* connection (UDP/ICMP hole punching) and in the TCP case the state tracking
* of a TCP connection. Beside the layer-3 connection state, a link also
* contains information about the routing and the NAT translation that
* correspond to the connection. Link objects have three different functions:
*
* 1) Link objects allow the router to manage the lifetime of resources
* related to a layer-3 connection.
*
* 2) Link objects allow the router to route the back-channel packets of a
* connection without additional routing rules.
*
* 3) Link objects reduce the routing overhead for successive packets of a
* connection as they gather the required information in one place and as
* preprocessed as possible.
*/
/*
* 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 _LINK_H_
#define _LINK_H_
/* Genode includes */
#include <timer_session/connection.h>
#include <util/avl_tree.h>
#include <util/list.h>
#include <net/ipv4.h>
#include <net/port.h>
/* local includes */
#include "list.h"
#include "reference.h"
#include "pointer.h"
#include "l3_protocol.h"
namespace Net {
class Interface_link_stats;
class Configuration;
class Port_allocator_guard;
class Tcp_packet;
class Domain;
class Interface;
class Link_side_id;
class Link_side;
class Link_side_tree;
class Link;
struct Link_list : List<Link> { };
class Tcp_link;
class Udp_link;
class Icmp_link;
}
struct Net::Link_side_id
{
Ipv4_address const src_ip;
Port const src_port;
Ipv4_address const dst_ip;
Port const dst_port;
static constexpr Genode::size_t data_size();
void *data_base() const { return (void *)&src_ip; }
/************************
** Standard operators **
************************/
bool operator == (Link_side_id const &id) const;
bool operator > (Link_side_id const &id) const;
}
__attribute__((__packed__));
class Net::Link_side : public Genode::Avl_node<Link_side>
{
friend class Link;
private:
Reference<Domain> _domain;
Link_side_id const _id;
Link &_link;
public:
Link_side(Domain &domain,
Link_side_id const &id,
Link &link);
Link_side const &find_by_id(Link_side_id const &id) const;
bool is_client() const;
/**************
** Avl_node **
**************/
bool higher(Link_side *side) { return side->_id > _id; }
/*********
** Log **
*********/
void print(Genode::Output &output) const;
/***************
** Accessors **
***************/
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; }
Port src_port() const { return _id.src_port; }
Port dst_port() const { return _id.dst_port; }
};
struct Net::Link_side_tree : Genode::Avl_tree<Link_side>
{
struct No_match : Genode::Exception { };
Link_side const &find_by_id(Link_side_id const &id) const;
};
class Net::Link : public Link_list::Element
{
protected:
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;
bool _opening { true };
Interface_link_stats &_stats;
Reference<Genode::size_t> _stats_curr;
void _handle_dissolve_timeout(Genode::Duration);
void _packet() { _dissolve_timeout.schedule(_dissolve_timeout_us); }
public:
struct No_port_allocator : Genode::Exception { };
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,
Genode::Microseconds const dissolve_timeout,
Interface_link_stats &stats);
~Link();
void dissolve(bool timeout);
void handle_config(Domain &cln_domain,
Domain &srv_domain,
Pointer<Port_allocator_guard> srv_port_alloc,
Configuration &config);
/*********
** Log **
*********/
void print(Genode::Output &output) const;
/***************
** Accessors **
***************/
Link_side &client() { return _client; }
Link_side &server() { return _server; }
Configuration &config() { return _config(); }
L3_protocol protocol() const { return _protocol; }
};
class Net::Tcp_link : public Link
{
private:
enum class State : Genode::uint8_t { OPEN, CLOSING, CLOSED, };
struct Peer
{
bool fin { false };
bool fin_acked { false };
};
State _state { State::OPEN };
Peer _client { };
Peer _server { };
void _tcp_packet(Tcp_packet &tcp,
Peer &sender,
Peer &receiver);
void _closing();
void _closed();
public:
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,
Interface_link_stats &stats);
void client_packet(Tcp_packet &tcp) { _tcp_packet(tcp, _client, _server); }
void server_packet(Tcp_packet &tcp);
};
struct Net::Udp_link : 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,
Interface_link_stats &stats);
void client_packet() { _packet(); }
void server_packet();
};
struct Net::Icmp_link : Link
{
Icmp_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,
Interface_link_stats &stats);
void client_packet() { _packet(); }
void server_packet();
};
#endif /* _LINK_H_ */