nic_router: replace term "uplink" with "NIC client"

BREAKS CONFIG COMPATIBILITY:
This commit changes the configuration interface of the NIC router in a way that
may break systems that use the component without proper adjustment!

HOW TO ADJUST:
At each occurrence of the '<uplink ...>' tag in a NIC router configuration
replace the tag name 'uplink' with 'nic-client'. The rest of the tag stays the
same.

The term "uplink" for network interfaces in the router that have a NIC session
client as back end was introduced in a time when Uplink sessions didn't yet
exist. Now, they do and, although both an uplink and an Uplink session
normally describe a network session between router and network device driver,
they are based on two different service types (NIC and Uplink). This can easily
cause confusion when integrating the router (the <uplink> is not related to
Uplink sessions) or trying to understand its functioning (an 'Uplink' object
has nothing to do with the Uplink service).

Therefore, this commit introduces the more specific term "NIC client" for an
interface that is based on a NIC session requested by the router. This doesn't
imply any semantic changes at the NIC router. However, the commit also brings a
broader update of the router's README and removes the term "downlink" that was
used only in documentation to refer to interfaces backed by a NIC session
provided by the router. The term was only associated with this meaning because
it is the natural counterpart to an uplink. This isn't appropriate anymore as
the terms for interface types have moved to a more technical level.

The commit adjusts all scenarios in the basic Genode repositories properly.

Fixes #4238
This commit is contained in:
Martin Stein 2021-07-27 13:52:21 +02:00 committed by Christian Helmuth
parent fce525f122
commit f8953de7ac
21 changed files with 617 additions and 563 deletions

View File

@ -196,7 +196,7 @@ proc test_7_config { } {
<config>
<policy label_prefix="t7_d1" domain="downlink" />
<uplink domain="uplink" />
<nic-client domain="uplink" />
<domain name="uplink">
<nat domain="downlink" tcp-ports="6" />
@ -312,7 +312,7 @@ append config {
link_state_triggers="yes"
interval_sec="60" />
<uplink domain="uplink"/>
<nic-client domain="uplink"/>
<domain name="uplink"
interface="10.0.2.55/24"

View File

@ -231,7 +231,7 @@ append config {
<report/>
<uplink domain="uplink"/>
<nic-client domain="uplink"/>
<domain name="uplink"
interface="10.0.2.55/24"
@ -269,7 +269,7 @@ append config {
tcp_idle_timeout_sec="30"
tcp_max_segm_lifetime_sec="15">
<uplink domain="uplink"/>
<nic-client domain="uplink"/>
<domain name="uplink"
interface="10.0.2.55/24"
@ -311,7 +311,7 @@ append config {
<report interval_sec="2" bytes="yes" config="no" />
<uplink domain="uplink"/>
<nic-client domain="uplink"/>
<domain name="uplink"
interface="10.0.2.55/24"
@ -345,7 +345,7 @@ append config {
<report interval_sec="2" bytes="yes" config="no" />
<uplink domain="uplink"/>
<nic-client domain="uplink"/>
<domain name="uplink"
interface="10.0.2.55/24"

View File

@ -5,7 +5,7 @@
<config verbose_domain_state="yes">
<default-policy domain="default" />
<uplink domain="uplink" />
<nic-client domain="uplink" />
<domain name="uplink">
<nat domain="default"
tcp-ports="1000"

View File

@ -131,7 +131,7 @@ append config {
<policy label_prefix="ping_1" domain="ping_1"/>
<policy label_prefix="ping_2" domain="ping_2"/>
<uplink domain="uplink"/>
<nic-client domain="uplink"/>
<domain name="uplink">
<nat domain="ping_1" icmp-ids="100"/>
@ -166,7 +166,7 @@ append config {
<config>
<policy label_prefix="ping_2" domain="ping_2"/>
<uplink domain="uplink"/>
<nic-client domain="uplink"/>
<domain name="uplink" interface="10.0.4.2/24" gateway="10.0.4.1">
<nat domain="ping_2" icmp-ids="100" udp-ports="100"/>

View File

@ -186,7 +186,7 @@ append_if [expr ![nic_router_2_managed]] config {
<config verbose_packets="no">
<policy label="test_client -> " domain="downlink"/>
<uplink domain="uplink"/>
<nic-client domain="uplink"/>
<domain name="uplink"/>
<domain name="downlink" interface="10.0.3.1/24">

View File

@ -113,7 +113,7 @@ append config {
icmp_idle_timeout_sec="10">
<policy label_prefix="ping_2" domain="ping_2"/>
<uplink domain="uplink"/>
<nic-client domain="uplink"/>
<domain name="uplink">
<nat domain="ping_2" icmp-ids="100" udp-ports="100"/>

View File

@ -1,68 +1,118 @@
The 'nic_router' component can be used to achieve a controlled mediation
between multiple NIC sessions on network or transport level. NIC sessions are
assigned to domains. The rules configured by the user then mediate between
these domains. This is a brief overview of the features thereby provided:
between multiple NIC and Uplink sessions on network or transport level.
Sessions are assigned to router domains. The rules configured by the user then
mediate between these domains. This is a brief overview of the features thereby
provided:
* Acting as hub between NIC session with the same domain,
* routing of UDP and TCP according to destination IP address and port,
* routing of ICMP and IPv4 according to destination IP address,
* port forwarding for UDP and TCP,
* NAPT for UDP, TCP and ICMP "Echo",
* forwarding of ICMP "Destination Unreachable" according to the UDP, TCP or
ICMP "Echo" connection it refers to,
* acting as ICMP echo server per domain
* acting as DHCP server or client per domain,
* Acting as hub among NIC and Uplink sessions of the same domain,
* routing of IPv4-based UDP and TCP according to destination IP address & port,
* routing of ICMPv4 and IPv4 according to destination IP address,
* port forwarding for IPv4-based UDP and TCP,
* NAPT for IPv4-based UDP, TCP and ICMPv4 echo,
* forwarding of ICMPv4 "Destination Unreachable" according to the UDP, TCP or
ICMPv4 echo connection it refers to,
* acting as ICMPv4 echo server per domain
* acting as DHCPv4 server or client per domain,
* provide per-domain network statistics via a report session,
* print out header information for each packet received or sent,
* and be fully re-configurable at runtime.
Basics
~~~~~~
Functional description
======================
The NIC router can act as server of multiple NIC session clients (downlinks)
and at the same time as client of multiple NIC session servers (uplinks).
Besides the decision which side initiates the NIC session and provides MAC
address respectively link state, uplinks and downlinks are equal to the NIC
router.
The routing algorithm is ultimately controlled through the configuration. NIC
sessions are assigned to domains. Each domain represents one subnet and a
corresponding routing configuration. The assignment of downlink NIC sessions
to domains is controlled through the policy tag that is also known from other
Genode components:
Interfaces and domains
~~~~~~~~~~~~~~~~~~~~~~
! <policy label_prefix="vlan_" domain="vlan" />
The NIC router acts as server for both Genode's NIC and Uplink service. For
both services it can manage an arbitrary number of clients at a time.
Furthermore, the NIC router can itself request multiple NIC sessions and act as
client at them. Among these types of network sessions at the router, there are
some minor differences regarding the roles when initializing the session,
determining a MAC address or communicating the link state. However, each
network session at the router, regardless of its type, is an "interface" (like
a network interface in Linux-based systems) and in all regards except the
mentioned subtleties treated the same as other interfaces.
The behavior of the router regarding interfaces is ultimately controlled
through the router's configuration. An interface that uses a NIC session that
is requested by the router (subsequently called NIC client) can be created
using the '<nic-client>' tag with an optional attribute for the session label:
! <nic-client ... />
! <nic-client label="wifi" ... />
! <nic-client label="wired" ... />
An interface that uses a NIC or Uplink session provided by the NIC router
(subsequently called NIC server respectively Uplink server) is created whenever
a client requests a session of one of the two service types at the router
(given the session arguments are valid).
New interfaces, although having a network session established, remain dead ends
towards the router (all packets are dropped by the router) as long as they are
not assigned a router domain. A domain is a set of router rules that is applied
as a whole to all interfaces assigned to that domain. Domains can be created by
using the '<domain>' tag with a unique name:
! <domain name="default" ...>...<domain/>
! <domain name="servers" ...>...<domain/>
! <domain name="home_net" ...>...<domain/>
! <domain name="travel_net" ...>...<domain/>
The assignment of NIC clients to domains is controlled through the 'domain'
attribute in the '<nic-client>' tag:
! <nic-client domain="home_net" />
! <nic-client label="mobile_drv" domain="travel_net" />
! <nic-client label="nic_bridge" domain="home_net" />
The assignment of NIC and Uplink servers is controlled through the tags
'<policy>' and '<default-policy>' that are known from other Genode components:
! <default-policy domain="default" />
! <policy label_prefix="vbox_" domain="servers" />
! <policy label_suffix="_server" domain="servers" />
! <policy label="nic_bridge_1" domain="wired_bridge" />
! <policy label="nic_bridge_2" domain="wired_bridge" />
! <policy label="nic_drv -> " domain="home_net" />
! <policy label="wifi_drv -> " domain="public" />
The domain name can be freely choosen but must be unique.
The uplink tag instructs the NIC router to create an uplink NIC session that
is assigned to the give domain:
Each of these tags applies to all NIC and Uplink servers whose session label
matches. A domain can be assigned any number of interfaces and interfaces of
different types.
! <uplink domain="wired_bridge" />
! <uplink label="wired" domain="wired_bridge" />
! <uplink label="wifi" domain="wifi_uplink" />
Besides defining the router rules for assigned interfaces, domains have a
second purpose. All interfaces assigned the same domain are assumed to be in
the same IPv4 subnet. So, from the router's perspective, each domain is a
distinct IPv4 subnet. At each domain the router is represented through an
IPv4 identity local to the corresponding IPv4 subnet.
The label is the session label that is used when requesting the uplink NIC
session. The label attribute is optional. It is perfectly fine to have a
domain with uplinks and downlinks assigned to at the same time. For each
domain there must be a domain tag:
Besides being an IPv4 peer at each domain. The router is also a hub at each
domain: If a network packet must be sent at a domain, it is always sent at all
interfaces assigned that domain. If a network packet from a domain addresses a
host in the same IPv4 subnet and it's not the routers IPv4 peer in that domain,
the packet is again sent at all interfaces assigned that domain
! <domain name="uplink" interface="10.0.2.55/24" />
! <domain name="http_servers" interface="192.168.1.18/24" />
! <domain name="imap_servers" interface="192.168.2.17/24" />
A good analogy would be that interfaces assigned a single domain are like
network cables that are all plugged into the same hub device. There's an
additional cable going away from the hub device that directly leads to the
routers IPv4 peer in the subnet.
The 'interface' attribute defines two things at once. First, it tells the
router which subnet can be found behind this domain, and second, which IP
identity the router shall use in case it has to communicate as itself with
the subnet. If the 'interface' attribute is not set in a 'domain' tag, the
router acts as DHCP client (Section [Configuring DHCP client functionality]).
A domain enters an IPv4 subnet by receing an IPv4 configuration for the routers
IPv4 peer in that subnet. This configuration can be obtained statically or
dynamically using DHCP. A static configuration is applied if an 'interface'
attribute is found in the '<domain>' tag:
! <domain name="servers" interface="10.0.2.55/24" />
The attribute defines the IPv4 address of the routers peer and the address
prefix length of the corresponding subnet. If the attribute is missing the
domain automatically sends DHCP requests at all assigned interfaces in order
to obtain a dynamic IPv4 configuration (Section [Configuring DHCP client
functionality]).
Additionaly, the optional 'gateway' attribute can be set for a domain:
! <domain name="uplink" interface="10.0.2.55/24" gateway="10.0.2.1" />
! <domain name="home_lan" interface="10.0.2.55/24" gateway="10.0.2.1" />
It defines the standard gateway of the subnet behind this domain. If a packet
shall be routed to this domain and its final IP destination does not match
@ -155,9 +205,9 @@ These are examples for IP rules:
! <ip dst="10.0.2.0/24" domain="intranet" />
! <ip dst="192.168.1.18/32" domain="my_server" />
! <ip dst="0.0.0.0/0" domain="uplink" />
! <ip dst="0.0.0.0/0" domain="default" />
IP rules only apply to IPv4 packets from the session of the surrounding
IP rules only apply to IPv4 packets from interfaces of the surrounding
domain. The 'dst' attribute is compared with the IP destination of the packet.
The rule with the longest prefix match is taken. The packet is then routed to
the domain given in the rule.
@ -179,9 +229,9 @@ These are examples for ICMP rules:
! <icmp dst="10.0.2.0/24" domain="intranet" />
! <icmp dst="192.168.1.18/32" domain="my_server" />
! <icmp dst="0.0.0.0/0" domain="uplink" />
! <icmp dst="0.0.0.0/0" domain="default" />
ICMP rules only apply to ICMP "Echo" packets from sessions of the surrounding
ICMP rules only apply to ICMP "Echo" packets from interfaces of the surrounding
domain. The 'dst' attribute is compared with the IP destination of the packet.
The rule with the longest prefix match is taken. The packet is then routed to
the domain given in the rule.
@ -212,12 +262,12 @@ rules to get effective:
! <permit port="80" domain="http_servers" />
! </tcp>
! <udp dst="10.0.2.0/24">
! <permit-any domain="uplink" />
! <permit-any domain="default" />
! </udp>
TCP rules only apply to TCP packets and UDP rules only to UDP packets from the
session of the surrounding domain. The 'dst' attribute is compared with the IP
destination of the packet. The rule with the longest prefix match is taken.
TCP rules only apply to TCP packets and UDP rules only to UDP packets from
interfaces of the surrounding domain. The 'dst' attribute is compared with the
IP destination of the packet. The rule with the longest prefix match is taken.
If the rule contains a 'permit-any' subrule or a 'permit' subrule whose 'port'
attribute matches the destination port of the packet, the packet is routed to
the domain given in the subrule.
@ -242,7 +292,7 @@ These are examples for port-forwarding rules:
! <tcp-forward port="80" domain="http_servers" to="192.168.1.18" to_port="1234" />
! <udp-forward port="69" domain="tftp_servers" to="192.168.2.23" />
Port-forwarding rules only apply to packets that come from the session of the
Port-forwarding rules only apply to packets that come from interfaces of the
surrounding domain and are addressed to the router's IP identity at this domain
(Section [Basics]). Amongst those, 'tcp-forward' rules only apply to the TCP
packets and 'udp-forward' rules only to the UDP packets. The 'port' attribute
@ -273,7 +323,7 @@ Each time a packet gets routed by using a TCP, UDP, ICMP or port-forwarding
rule, the router creates a link state. From then on, all packets that belong
to the exchange this first packet initiated and come from one of the two
involved domains are routed by the link state and not by a rule. The costs for
the link state are paid by the session that sent the first packet.
the link state are paid by the interface that sent the first packet.
If a link state exists for a packet, it is unambiguously correlated either
through source IP and port plus destination IP and port or, for ICMP, through
@ -281,7 +331,7 @@ source and destination IP plus ICMP query ID. This is also the case if the
transfer includes NAT no matter of what kind or for which side.
It is desirable to discard a link state as soon as it is not needed anymore.
The more precise this is done, the more efficient can NIC sessions use their
The more precise this is done, the more efficient can interfaces use their
resources (ports, RAM), and the less is the risk for DoS attacks. Therefore,
the NIC router keeps track of the idle time of a link. Idle time means the
time passed since the last packet was routed using that link regardless of
@ -326,23 +376,23 @@ Configuring NAT
In contrast to routing rules that affect packets coming from their domain,
NAT rules affect packets that go to their domain:
! <domain name="uplink" interface="10.0.2.55/24">
! <domain name="home_lan" interface="10.0.2.55/24">
! <nat domain="http_client" tcp-ports="6" />
! </domain>
This would tell the router to apply NAT for the HTTP client when it speaks to
the uplink. This means, it affects all packets from the HTTP client that get
routed to the uplink by using a UDP, TCP, or port-forwarding rule respectively
a corresponding link state. If this is the case, the packet's source IP
address is changed to "10.0.2.55" and the source port is replaced by a free
source port of the router. When saying "free source port" this actually means
a port that the router currently doesn't use at the destination domain. So,
at each domain, the router has two complete port spaces for source NAT
the home LAN. This means, it affects all packets from the HTTP client that get
routed to the home LAN by using a UDP, TCP, or port-forwarding rule
respectively a corresponding link state. If this is the case, the packet's
source IP address is changed to "10.0.2.55" and the source port is replaced by
a free source port of the router. When saying "free source port" this actually
means a port that the router currently doesn't use at the destination domain.
So, at each domain, the router has two complete port spaces for source NAT
available. One for UDP and one for TCP. Each port space contains the IANA
dynamic port range 49152 to 65535.
As you can see, the NAT rule also has a 'tcp-ports' attribute. It restricts
how many TCP source ports of the uplink the HTTP client may use at a time. The
As you can see, the NAT rule also has a 'tcp-ports' attribute. It restricts how
many TCP source ports of the home LAN the HTTP client may use at a time. The
same goes also for UDP:
! <nat domain="tftp_client" udp-ports="13" />
@ -407,7 +457,7 @@ or like this:
! <dhcp-server ip_first="10.0.1.80"
! ip_last="10.0.1.100"
! ip_lease_time_sec="3600"
! dns_server_from="uplink" />
! dns_server_from="home_lan" />
! ...
!
! </domain>
@ -560,7 +610,7 @@ described below:
A boolean value that controls whether the attributes 'rx_bytes' and 'tx_bytes'
of the <domain> tag in the state report are generated. These attributes
provide the number of bytes that were sent respectively recieved at all
sessions/interfaces of that domain beginning with the creation of the domain.
interfaces of that domain beginning with the creation of the domain.
'stats'
@ -581,26 +631,26 @@ itself terminated the connection).
The <destroyed> subtag can occur in <*-links> subtags in both the <interface>
and the <domain> tag. It shows the number of links of the protocol type that
once existed but were already destroyed. In case of the <interface> tag, the
corresponding session/interface still exists at that domain. Once the
session/interface gets destroyed or disconnected from the domain, the number is
transferred to the <destroyed> subtag in the <*-links> subtag in the <domain>
tag. I.e. the <destroyed> subtags in <*-links> subtags in the <domain> tag
provide the number of destroyed links that can't be correlated anymore to any
session/interface of the domain.
corresponding interface still exists at that domain. Once the interface gets
destroyed or disconnected from the domain, the number is transferred to the
<destroyed> subtag in the <*-links> subtag in the <domain> tag. I.e. the
<destroyed> subtags in <*-links> subtags in the <domain> tag provide the number
of destroyed links that can't be correlated anymore to any interface of the
domain.
The same applies for the <refused_*> subtags of <*-links> tags. They show the
number of links that couldn't be established through the router because of the
lack of a certain quota. Thereby, <refused_for_ram> refers to a lack of RAM
quota at the source session/interface of the link. The <refused_for_ports>, at
the other hand, refers to a lack of UDP/TCP-NAT-ports respectively
ICMP-NAT-IDs at the target domain (see section [Configuring NAT]).
quota at the source interface of the link. The <refused_for_ports>, at the
other hand, refers to a lack of UDP/TCP-NAT-ports respectively ICMP-NAT-IDs at
the target domain (see section [Configuring NAT]).
The subtags <arp-waiters>, and <dhcp-allocations> list the number of still
active (<active> subtag) and already destroyed (<destroyed> subtag) objects
for pending ARP requests respectively DHCP-address allocations at a
session/interface when in an <interface> tag. When in a <domain> tag, they
only list the number of already destroyed objects of these types that can't
be correlated anymore to any session/interface of the domain.
active (<active> subtag) and already destroyed (<destroyed> subtag) objects for
pending ARP requests respectively DHCP-address allocations at an interface when
in an <interface> tag. When in a <domain> tag, they only list the number of
already destroyed objects of these types that can't be correlated anymore to
any interface of the domain.
'quota'
@ -609,18 +659,18 @@ A boolean value that controls whether the subtags <ram> and <cap> of the
tag are generated.
The former two show the capability quota respectively RAM quota of the router
that isn't accounted to any of the sessions/interfaces connected to the router
(i.e., the routers "own" quota). The 'quota' attribute denotes the total amount
of quota available to the router, the 'used' attribute the part of the total
that isn't accounted to any of the interfaces connected to the router (i.e.,
the routers "own" quota). The 'quota' attribute denotes the total amount of
quota available to the router, the 'used' attribute the part of the total
amount of quota that is currently spent or in use, and the 'shared' attribute
the part of the spent quota that, although it was spent for session/interface-
specific things, can't be accounted to one session/interface technical reasons.
the part of the spent quota that, although it was spent for interface-specific
things, can't be accounted to one interface for technical reasons.
The subtags <ram-quota> and <cap-quota> in the <interface> tag, however, show
the capability quota respectively RAM quota accounted to that
session/interface. The 'limit' and 'used' attributes are equal to the 'quota'
and 'used' attributes of the <ram> and <cap> subtags of the <state> tag. The
'avail' attribute contains simply the 'limit' value minus the 'used' value.
the capability quota respectively RAM quota accounted to that interface. The
'limit' and 'used' attributes are equal to the 'quota' and 'used' attributes of
the <ram> and <cap> subtags of the <state> tag. The 'avail' attribute contains
simply the 'limit' value minus the 'used' value.
'config'
@ -645,17 +695,16 @@ changes. I.e., whenever the IP configuration of any domain has changed.
A boolean value that controls whether the attribute 'link_state' of the
<interface> tag is generated. The 'link_state' attribute shows the current real
link state of the session/interface. Note, that in case of a NIC session, this
is not necessarily the same value as the one that the session client sees. For
more information about that, refer to [Behavior regarding the NIC-session link
state].
link state of the interface. Note, that in case of a NIC server, this is not
necessarily the same value as the one that the session client sees. For more
information on that, refer to [Behavior regarding the NIC-session link state].
'link_state_triggers'
A boolean value that controls whether to enforce sending a report each time the
state that is controlled through the 'link_state' attribute of the <report> tag
changes. I.e., whenever the real link state of any session/interface at the
router has changed.
changes. I.e., whenever the real link state of any interface at the router has
changed.
'interval_sec'
@ -690,8 +739,8 @@ affects all domains without a <domain> local value.
! <config verbose_domain_state="no">
Whether to log most important changes in the state of a domain (number of NIC
sessions connected, current IPv4 config).
Whether to log most important changes in the state of a domain (number of
interfaces assigned, current IPv4 config).
Other configuration attributes
@ -701,16 +750,16 @@ Other configuration attributes
Maximum number of packets handled per signal
--------------------------------------------
If possible, the NIC router normally handles multiple packets from a NIC
session per signal. However, if one NIC session has a high packet rate and a
big buffer, this can lead to starvation of the other NIC sessions. Thus, the
maximum number of packets handled per signal is limited by default. This limit
can be configured as follows (default value shown):
If possible, the NIC router normally handles multiple packets from an interface
per signal. However, if one interface has a high packet rate and a big buffer,
this can lead to starvation of the other interfaces. Thus, the maximum number
of packets handled per signal is limited by default. This limit can be
configured as follows (default value shown):
! <config max_packets_per_signal="32">
When set to zero, the limit is deactivated, meaning that the router always
handles all available packets of a NIC session.
handles all available packets of an interface.
Disable requesting address resolutions via ARP
@ -736,14 +785,14 @@ interfaces with the 'NOARP' flag set.
Behavior regarding the NIC-session link state
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
At downlinks, the NIC router applies a feedback-driven state machine for the
At NIC servers, the NIC router applies a feedback-driven state machine for the
link state in order to ensure that clients recognize state transitions. This
means that the NIC router guarantees that a new link state remains fixed until
the client has read it using the corresponding RPC at the NIC-session
interface. If, in the meantime, further "up" and "down" edges occur, they are
memorized and executed as soon as the former state has been read by the
client. Such postponed link state edges are merged in a way that they result in
two contrary edges at a max. The following diagrams demonstrate this:
memorized and executed as soon as the former state has been read by the client.
Such postponed link state edges are merged in a way that they result in two
contrary edges at a max. The following diagrams demonstrate this:
! client reads: 0 1 0 1 0 1
@ -774,13 +823,17 @@ two contrary edges at a max. The following diagrams demonstrate this:
Examples
~~~~~~~~
========
Scripted scenarios
~~~~~~~~~~~~~~~~~~
In-action examples of how to use the router are provided through the following
automated run scripts:
* libports/run/nic_router.run (basic functionality)
* dde_linux/run/nic_router_uplinks.run (dynamically switching uplinks)
* dde_linux/run/nic_router_uplinks.run (dynamically switching between wifi and wired driver)
* os/run/ping_nic_router.run (ICMP routing)
* os/run/nic_router_disable_arp.run ('use_arp' configuration flag)
* os/run/nic_router_dhcp_unmanaged.run (DHCP + link states without a manager)
@ -789,12 +842,12 @@ automated run scripts:
* os/run/nic_router_stress.run (client misbehaving on session level)
The rest of this section will list and explain some smaller configuration
snippets. The environment for these examples shall be as follows. There are
two virtual subnets 192.168.1.0/24 and 192.168.2.0/24 that connect as Virtnet A
and B to the router. The standard gateway of the virtual networks is the NIC
router with IP 192.168.*.1 . The router's uplink leads to the NIC driver that
connects the machine with your home network 10.0.2.0/24. Your home network is
connected to the internet through its standard gateway 10.0.2.1 .
snippets. The environment for these examples shall be as follows. There are two
virtual subnets 192.168.1.0/24 and 192.168.2.0/24 that connect as Virtnet A and
B to the router. The standard gateway of the virtual networks is the NIC router
with IP 192.168.*.1 . The NIC driver connects the machine with your home
network 10.0.2.0/24 and has an Uplink session to the NIC router. Your home
network is connected to the internet through its standard gateway 10.0.2.1 .
Connecting local networks
@ -807,33 +860,33 @@ following configuration:
! <policy label_prefix="virtnet_a" domain="virtnet_a" />
! <policy label_prefix="virtnet_b" domain="virtnet_b" />
! <uplink domain="uplink" />
! <policy label_prefic="nic_drv" domain="home_lan" />
!
! <domain name="uplink" interface="10.0.2.55/24" gateway="10.0.2.1/24">
! <domain name="home_lan" interface="10.0.2.55/24" gateway="10.0.2.1/24">
! <ip dst="192.168.1.0/24" domain="virtnet_a"/>
! <ip dst="192.168.2.0/24" domain="virtnet_b"/>
! </domain>
!
! <domain name="virtnet_a" interface="192.168.1.1/24">
! <ip dst="192.168.2.0/24" domain="virtnet_b"/>
! <ip dst="0.0.0.0/0" domain="uplink"/>
! <ip dst="0.0.0.0/0" domain="home_lan"/>
! </domain>
!
! <domain name="virtnet_b" interface="192.168.2.1/24">
! <ip dst="192.168.1.0/24" domain="virtnet_a"/>
! <ip dst="0.0.0.0/0" domain="uplink"/>
! <ip dst="0.0.0.0/0" domain="home_lan"/>
! </domain>
IP packets from Virtnet A and uplink that target an IP address 192.168.2.* are
routed to Virtnet B. IP packets from Virtnet B and uplink that target an IP
address 192.168.1.* are routed to Virtnet A. Packets that are addressed to
hosts in the same local network should never reach the router as they can be
transmitted directly. If there's a packet from one of the virtual networks
that doesn't target 192.168.1.* or 192.168.2.*, the IP 0.0.0.0/0 rules route
them to the uplink. If these packets target an IP 10.0.2.*, the router sends
them directly to the host in your home network. Otherwise, the router sends
them to your gateway 10.0.2.1 . Note that none of the packets is modified on
layer 2 or higher, so, no NAT is done by the router to hide the virtual
IP packets from Virtnet A and the home LAN that target an IP address
192.168.2.* are routed to Virtnet B. IP packets from Virtnet B and the home LAN
that target an IP address 192.168.1.* are routed to Virtnet A. Packets that are
addressed to hosts in the same local network should never reach the router as
they can be transmitted directly. If there's a packet from one of the virtual
networks that doesn't target 192.168.1.* or 192.168.2.*, the IP 0.0.0.0/0 rules
route them to the home LAN. If these packets target an IP 10.0.2.*, the router
sends them directly to the host in your home network. Otherwise, the router
sends them to your gateway 10.0.2.1 . Note that none of the packets is modified
on layer 2 or higher, so, no NAT is done by the router to hide the virtual
networks.
@ -847,48 +900,49 @@ internet. The router would have the following configuration:
! <policy label_prefix="virtnet_a" domain="virtnet_a" />
! <policy label_prefix="virtnet_b" domain="virtnet_b" />
! <uplink domain="uplink" />
! <policy label_prefic="nic_drv" domain="home_lan" />
!
! <domain name="uplink" interface="10.0.2.55/24" gateway="10.0.2.1/24">
! <domain name="home_lan" interface="10.0.2.55/24" gateway="10.0.2.1/24">
! <nat domain="virtnet_a" tcp_ports="1000" udp_ports="1000">
! </domain>
!
! <domain name="virtnet_a" interface="192.168.1.1/24">
! <tcp dst="10.0.2.0/24"><permit-any domain="uplink" /></tcp>
! <udp dst="10.0.2.0/24"><permit-any domain="uplink" /></udp>
! <tcp dst="10.0.2.0/24"><permit-any domain="home_lan" /></tcp>
! <udp dst="10.0.2.0/24"><permit-any domain="home_lan" /></udp>
! <tcp dst="0.0.0.0/0">
! <permit port="443" domain="uplink" />
! <permit port="993" domain="uplink" />
! <permit port="443" domain="home_lan" />
! <permit port="993" domain="home_lan" />
! </tcp>
! </domain>
From the packets that come from Virtnet A, those that target an IP 10.0.2.*
are routed to the uplink without inspecting the port. At the uplink, the
router notices that it shall apply NAT for Virtnet A. It replaces the source
IP with 10.0.2.55 and allocates one of its uplink source ports for the
exchange. On replies to Virtnet-A packets from the home network, the router
translates IP and port back using the corresponding link state. For packets
from Virtnet A that target other IPs, only the 0.0.0.0/0 rule applies and only
if the packet targets TCP port 443 or 993. Both ports route the packet to the
uplink where, again, NAT is applied and the packets are sent to the gateway
10.0.2.1 .
From the packets that come from Virtnet A, those that target an IP 10.0.2.* are
routed to the home LAN without inspecting the port. At the home LAN, the router
notices that it shall apply NAT for Virtnet A. It replaces the source IP with
10.0.2.55 and allocates a free source port of the home LAN for the exchange. On
replies to Virtnet-A packets from the home network, the router translates IP
and port back using the corresponding link state. For packets from Virtnet A
that target other IPs, only the 0.0.0.0/0 rule applies and only if the packet
targets TCP port 443 or 993. Both ports route the packet to the home LAN where,
again, NAT is applied and the packets are sent to the gateway 10.0.2.1 .
Servers in a private network
----------------------------
In this example, we assume that there are three servers in Virtnet A. An HTTP
server at port 80 with IP 192.168.1.2, a GOPHER server at port 70 with IP
192.168.1.3, and a TFTP server at port 69 with IP 192.168.1.4 . Now you want
the servers (and only them) to be reachable to the home network via the
router's IP and to the internet via your gateway. The router would have the
following configuration:
In this example, we assume that the NIC router has to request a NIC session at
a NIC bridge instance in order to reach the NIC driver (the driver serves the
NIC bridge) and gain access to the home LAN. Furthermore, there are three
servers in Virtnet A. An HTTP server at port 80 with IP 192.168.1.2, a GOPHER
server at port 70 with IP 192.168.1.3, and a TFTP server at port 69 with IP
192.168.1.4 . Now, you want the servers (and only them) to be reachable to the
home network via the router's IP and to the internet via your gateway. The
router would have the following configuration:
! <policy label_prefix="virtnet_a" domain="virtnet_a" />
! <policy label_prefix="virtnet_b" domain="virtnet_b" />
! <uplink domain="uplink" />
! <nic-client domain="home_lan" />
!
! <domain name="uplink" interface="10.0.2.55/24" gateway="10.0.2.1">
! <domain name="home_lan" interface="10.0.2.55/24" gateway="10.0.2.1">
! <tcp-forward port="80" domain="virtnet_a" to="192.168.1.2" />
! <tcp-forward port="70" domain="virtnet_a" to="192.168.1.3" />
! <udp-forward port="69" domain="virtnet_a" to="192.168.1.4" to_port="2048"/>
@ -897,7 +951,7 @@ following configuration:
! <domain name="virtnet_a" interface="192.168.1.1/24" />
! <domain name="virtnet_b" interface="192.168.1.1/24" />
Amongst the packets that come from the uplink, only those that are addressed
Amongst the packets that come from the home LAN, only those that are addressed
to 10.0.2.55 and TCP port 80, TCP port 70, or UDP port 69 are forwarded.
All these packets are forwarded to Virtnet A. But beforehand, their IP
destination is adapted. TCP-port-80 packets are redirected to 192.168.1.2,
@ -905,7 +959,7 @@ TCP-port-70 packets to 192.168.1.3, and UDP-port-69 packets to
192.168.1.4:2048.
Amongst the packets that come from Virtnet A, only those that match a link
state at the uplink are forwarded, because the Virtnet-A domain contains no
rules. Thus, Virtnet A can only talk to the uplink in the context of
state at the home LAN are forwarded, because the Virtnet-A domain contains no
rules. Thus, Virtnet A can only talk to the home LAN in the context of
TCP-connections or UDP pseudo-connections that were opened by clients behind
the uplink. The servers IP addresses never leave Virtnet A.
the home LAN. The servers IP addresses never leave Virtnet A.

View File

@ -84,12 +84,12 @@
</xs:complexType>
</xs:element><!-- policy -->
<xs:element name="uplink">
<xs:element name="nic-client">
<xs:complexType>
<xs:attribute name="label" type="Session_label" />
<xs:attribute name="domain" type="Domain_name" />
</xs:complexType>
</xs:element><!-- uplink -->
</xs:element><!-- nic-client -->
<xs:element name="domain">
<xs:complexType>

View File

@ -48,14 +48,14 @@ Configuration::Configuration(Xml_node const node,
{ }
void Configuration::_invalid_uplink(Uplink &uplink,
char const *reason)
void Configuration::_invalid_nic_client(Nic_client &nic_client,
char const *reason)
{
if (_verbose) {
log("[", uplink.domain(), "] invalid uplink: ", uplink, " (", reason, ")"); }
log("[", nic_client.domain(), "] invalid NIC client: ", nic_client, " (", reason, ")"); }
_uplinks.remove(uplink);
destroy(_alloc, &uplink);
_nic_clients.remove(nic_client);
destroy(_alloc, &nic_client);
}
@ -160,26 +160,26 @@ Configuration::Configuration(Env &env,
}
catch (Genode::Xml_node::Nonexistent_sub_node) { }
/* initialize uplinks */
_node.for_each_sub_node("uplink", [&] (Xml_node const node) {
/* initialize NIC clients */
_node.for_each_sub_node("nic-client", [&] (Xml_node const node) {
try {
Uplink &uplink = *new (_alloc)
Uplink { node, alloc, old_config._uplinks, env, timer,
interfaces, *this };
Nic_client &nic_client = *new (_alloc)
Nic_client { node, alloc, old_config._nic_clients, env, timer,
interfaces, *this };
try { _uplinks.insert(uplink); }
catch (Uplink_tree::Name_not_unique exception) {
_invalid_uplink(uplink, "label not unique");
_invalid_uplink(exception.object, "label not unique");
try { _nic_clients.insert(nic_client); }
catch (Nic_client_tree::Name_not_unique exception) {
_invalid_nic_client(nic_client, "label not unique");
_invalid_nic_client(exception.object, "label not unique");
}
}
catch (Uplink::Invalid) { }
catch (Nic_client::Invalid) { }
});
/*
* Destroy old uplinks to ensure that uplink interfaces that were not
* Destroy old NIC clients to ensure that NIC client interfaces that were not
* re-used are not re-attached to the new domains.
*/
old_config._uplinks.destroy_each(_alloc);
old_config._nic_clients.destroy_each(_alloc);
}
@ -203,8 +203,8 @@ void Configuration::start_reporting()
Configuration::~Configuration()
{
/* destroy uplinks */
_uplinks.destroy_each(_alloc);
/* destroy NIC clients */
_nic_clients.destroy_each(_alloc);
/* destroy reporter */
try { destroy(_alloc, &_reporter()); }

View File

@ -17,7 +17,7 @@
/* local includes */
#include <domain.h>
#include <report.h>
#include <uplink.h>
#include <nic_client.h>
/* Genode includes */
#include <base/duration.h>
@ -47,14 +47,14 @@ class Net::Configuration
Genode::Microseconds const _udp_idle_timeout;
Genode::Microseconds const _tcp_idle_timeout;
Genode::Microseconds const _tcp_max_segm_lifetime;
Pointer<Report> _report { };
Pointer<Genode::Reporter> _reporter { };
Domain_tree _domains { };
Uplink_tree _uplinks { };
Pointer<Report> _report { };
Pointer<Genode::Reporter> _reporter { };
Domain_tree _domains { };
Nic_client_tree _nic_clients { };
Genode::Xml_node const _node;
void _invalid_uplink(Uplink &uplink,
char const *reason);
void _invalid_nic_client(Nic_client &nic_client,
char const *reason);
void _invalid_domain(Domain &domain,
char const *reason);

View File

@ -20,7 +20,6 @@
/* local includes */
#include <nic_session_root.h>
#include <uplink_session_root.h>
#include <uplink.h>
#include <configuration.h>
using namespace Net;

View File

@ -0,0 +1,180 @@
/*
* \brief Interface back-end using a NIC session requested by the NIC router
* \author Martin Stein
* \date 2016-08-23
*/
/*
* 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/env.h>
/* local includes */
#include <nic_client.h>
#include <configuration.h>
using namespace Net;
using namespace Genode;
/*********************
** Nic_client_base **
*********************/
Net::Nic_client_base::Nic_client_base(Xml_node const &node)
:
_label { node.attribute_value("label", Session_label::String()) },
_domain { node.attribute_value("domain", Domain_name()) }
{ }
/****************
** Nic_client **
****************/
void Nic_client::_invalid(char const *reason) const
{
if (_config.verbose()) {
log("[", domain(), "] invalid NIC client: ", *this, " (", reason, ")"); }
throw Invalid();
}
Net::Nic_client::Nic_client(Xml_node const &node,
Allocator &alloc,
Nic_client_tree &old_nic_clients,
Env &env,
Timer::Connection &timer,
Interface_list &interfaces,
Configuration &config)
:
Nic_client_base { node },
Avl_string_base { label().string() },
_alloc { alloc },
_config { config }
{
/* if an interface with this label already exists, reuse it */
try {
Nic_client &old_nic_client = old_nic_clients.find_by_name(label());
Nic_client_interface &interface = old_nic_client._interface();
old_nic_client._interface = Pointer<Nic_client_interface>();
interface.domain_name(domain());
_interface = interface;
}
/* if not, create a new one */
catch (Nic_client_tree::No_match) {
if (config.verbose()) {
log("[", domain(), "] create NIC client: ", *this); }
try {
_interface = *new (_alloc)
Nic_client_interface { env, timer, alloc, interfaces, config,
domain(), label() };
}
catch (Insufficient_ram_quota) { _invalid("NIC session RAM quota"); }
catch (Insufficient_cap_quota) { _invalid("NIC session CAP quota"); }
catch (Service_denied) { _invalid("NIC session denied"); }
}
}
Net::Nic_client::~Nic_client()
{
/* if the interface was yet not reused by another NIC client, destroy it */
try {
Nic_client_interface &interface = _interface();
if (_config.verbose()) {
log("[", domain(), "] destroy NIC client: ", *this); }
destroy(_alloc, &interface);
}
catch (Pointer<Nic_client_interface>::Invalid) { }
}
void Net::Nic_client::print(Output &output) const
{
if (label() == Session_label()) {
Genode::print(output, "?"); }
else {
Genode::print(output, label()); }
}
/*******************************
** Nic_client_interface_base **
*******************************/
Net::Nic_client_interface_base::
Nic_client_interface_base(Domain_name const &domain_name,
Session_label const &label,
bool const &session_link_state)
:
_domain_name { domain_name },
_label { label },
_session_link_state { session_link_state }
{ }
void Net::Nic_client_interface_base::interface_unready()
{
_interface_ready = false;
};
void Net::Nic_client_interface_base::interface_ready()
{
_interface_ready = true;
};
bool Net::Nic_client_interface_base::interface_link_state() const
{
return _interface_ready && _session_link_state;
}
/**************************
** Nic_client_interface **
**************************/
Net::Nic_client_interface::Nic_client_interface(Env &env,
Timer::Connection &timer,
Genode::Allocator &alloc,
Interface_list &interfaces,
Configuration &config,
Domain_name const &domain_name,
Session_label const &label)
:
Nic_client_interface_base { domain_name, label, _session_link_state },
Nic::Packet_allocator { &alloc },
Nic::Connection { env, this, BUF_SIZE, BUF_SIZE, label.string() },
_session_link_state_handler { env.ep(), *this,
&Nic_client_interface::_handle_session_link_state },
_interface { env.ep(), timer, mac_address(), alloc,
Mac_address(), config, interfaces, *rx(), *tx(),
*this }
{
/* install packet stream signal handlers */
rx_channel()->sigh_ready_to_ack (_interface.sink_ack());
rx_channel()->sigh_packet_avail (_interface.sink_submit());
tx_channel()->sigh_ack_avail (_interface.source_ack());
tx_channel()->sigh_ready_to_submit(_interface.source_submit());
/* initialize link state handling */
Nic::Connection::link_state_sigh(_session_link_state_handler);
_session_link_state = Nic::Connection::link_state();
}
void Net::Nic_client_interface::_handle_session_link_state()
{
_session_link_state = Nic::Connection::link_state();
_interface.handle_interface_link_state();
}

View File

@ -0,0 +1,178 @@
/*
* \brief Interface back-end using a NIC session requested by the NIC router
* \author Martin Stein
* \date 2016-08-23
*/
/*
* 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 _NIC_CLIENT_H_
#define _NIC_CLIENT_H_
/* Genode includes */
#include <nic_session/connection.h>
#include <nic/packet_allocator.h>
/* local includes */
#include <avl_string_tree.h>
#include <interface.h>
#include <ipv4_address_prefix.h>
namespace Net {
using Domain_name = Genode::String<160>;
class Nic_client_base;
class Nic_client;
class Nic_client_tree;
class Nic_client_interface_base;
class Nic_client_interface;
}
class Net::Nic_client_tree
:
public Avl_string_tree<Nic_client, Genode::Session_label>
{ };
class Net::Nic_client_base
{
private:
Genode::Session_label const _label;
Domain_name const _domain;
public:
Nic_client_base(Genode::Xml_node const &node);
virtual ~Nic_client_base() { }
/**************
** Acessors **
**************/
Genode::Session_label const &label() const { return _label; }
Domain_name const &domain() const { return _domain; }
};
class Net::Nic_client : public Nic_client_base,
private Genode::Avl_string_base
{
friend class Avl_string_tree<Nic_client, Genode::Session_label>;
friend class Genode::List<Nic_client>;
private:
Genode::Allocator &_alloc;
Configuration const &_config;
Pointer<Nic_client_interface> _interface { };
void _invalid(char const *reason) const;
public:
struct Invalid : Genode::Exception { };
Nic_client(Genode::Xml_node const &node,
Genode::Allocator &alloc,
Nic_client_tree &old_nic_clients,
Genode::Env &env,
Timer::Connection &timer,
Interface_list &interfaces,
Configuration &config);
~Nic_client();
/*********
** log **
*********/
void print(Genode::Output &output) const;
};
class Net::Nic_client_interface_base : public Interface_policy
{
private:
Const_reference<Domain_name> _domain_name;
Genode::Session_label const _label;
bool const &_session_link_state;
bool _interface_ready { false };
/***************************
** Net::Interface_policy **
***************************/
Domain_name determine_domain_name() const override { return _domain_name(); };
void handle_config(Configuration const &) override { }
Genode::Session_label const &label() const override { return _label; }
void interface_unready() override;
void interface_ready() override;
bool interface_link_state() const override;
public:
Nic_client_interface_base(Domain_name const &domain_name,
Genode::Session_label const &label,
bool const &session_link_state);
virtual ~Nic_client_interface_base() { }
/***************
** Accessors **
***************/
void domain_name(Domain_name const &v) { _domain_name = v; }
};
class Net::Nic_client_interface : public Nic_client_interface_base,
public Nic::Packet_allocator,
public Nic::Connection
{
private:
enum {
PKT_SIZE = Nic::Packet_allocator::DEFAULT_PACKET_SIZE,
BUF_SIZE = Nic::Session::QUEUE_SIZE * PKT_SIZE,
};
bool _session_link_state { false };
Genode::Signal_handler<Nic_client_interface> _session_link_state_handler;
Net::Interface _interface;
Ipv4_address_prefix _read_interface();
void _handle_session_link_state();
public:
Nic_client_interface(Genode::Env &env,
Timer::Connection &timer,
Genode::Allocator &alloc,
Interface_list &interfaces,
Configuration &config,
Domain_name const &domain_name,
Genode::Session_label const &label);
/***************
** Accessors **
***************/
Mac_address const &router_mac() const { return _interface.router_mac(); }
};
#endif /* _NIC_CLIENT_H_ */

View File

@ -1,5 +1,5 @@
/*
* \brief NIC session server role of the NIC router
* \brief Interface back-end using NIC sessions provided by the NIC router
* \author Martin Stein
* \date 2016-08-23
*/

View File

@ -1,5 +1,5 @@
/*
* \brief NIC session server role of the NIC router
* \brief Interface back-end using NIC sessions provided by the NIC router
* \author Martin Stein
* \date 2016-08-23
*/

View File

@ -12,7 +12,7 @@ SRC_CC += \
nat_rule.cc \
main.cc \
ipv4_config.cc \
uplink.cc \
nic_client.cc \
interface.cc \
arp_cache.cc \
configuration.cc \

View File

@ -1,179 +0,0 @@
/*
* \brief Uplink interface in form of a NIC session component
* \author Martin Stein
* \date 2016-08-23
*/
/*
* 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/env.h>
/* local includes */
#include <uplink.h>
#include <configuration.h>
using namespace Net;
using namespace Genode;
/*****************
** Uplink_base **
*****************/
Net::Uplink_base::Uplink_base(Xml_node const &node)
:
_label { node.attribute_value("label", Session_label::String()) },
_domain { node.attribute_value("domain", Domain_name()) }
{ }
/************
** Uplink **
************/
void Uplink::_invalid(char const *reason) const
{
if (_config.verbose()) {
log("[", domain(), "] invalid uplink: ", *this, " (", reason, ")"); }
throw Invalid();
}
Net::Uplink::Uplink(Xml_node const &node,
Allocator &alloc,
Uplink_tree &old_uplinks,
Env &env,
Timer::Connection &timer,
Interface_list &interfaces,
Configuration &config)
:
Uplink_base { node },
Avl_string_base { label().string() },
_alloc { alloc },
_config { config }
{
/* if an interface with this label already exists, reuse it */
try {
Uplink &old_uplink = old_uplinks.find_by_name(label());
Uplink_interface &interface = old_uplink._interface();
old_uplink._interface = Pointer<Uplink_interface>();
interface.domain_name(domain());
_interface = interface;
}
/* if not, create a new one */
catch (Uplink_tree::No_match) {
if (config.verbose()) {
log("[", domain(), "] request uplink NIC session: ", *this); }
try {
_interface = *new (_alloc)
Uplink_interface { env, timer, alloc, interfaces, config,
domain(), label() };
}
catch (Insufficient_ram_quota) { _invalid("NIC session RAM quota"); }
catch (Insufficient_cap_quota) { _invalid("NIC session CAP quota"); }
catch (Service_denied) { _invalid("NIC session denied"); }
}
}
Net::Uplink::~Uplink()
{
/* if the interface was yet not reused by another uplink, destroy it */
try {
Uplink_interface &interface = _interface();
if (_config.verbose()) {
log("[", domain(), "] close uplink NIC session: ", *this); }
destroy(_alloc, &interface);
}
catch (Pointer<Uplink_interface>::Invalid) { }
}
void Net::Uplink::print(Output &output) const
{
if (label() == Session_label()) {
Genode::print(output, "?"); }
else {
Genode::print(output, label()); }
}
/***************************
** Uplink_interface_base **
***************************/
Net::Uplink_interface_base::Uplink_interface_base(Domain_name const &domain_name,
Session_label const &label,
bool const &session_link_state)
:
_domain_name { domain_name },
_label { label },
_session_link_state { session_link_state }
{ }
void Net::Uplink_interface_base::interface_unready()
{
_interface_ready = false;
};
void Net::Uplink_interface_base::interface_ready()
{
_interface_ready = true;
};
bool Net::Uplink_interface_base::interface_link_state() const
{
return _interface_ready && _session_link_state;
}
/**********************
** Uplink_interface **
**********************/
Net::Uplink_interface::Uplink_interface(Env &env,
Timer::Connection &timer,
Genode::Allocator &alloc,
Interface_list &interfaces,
Configuration &config,
Domain_name const &domain_name,
Session_label const &label)
:
Uplink_interface_base { domain_name, label, _session_link_state },
Nic::Packet_allocator { &alloc },
Nic::Connection { env, this, BUF_SIZE, BUF_SIZE, label.string() },
_session_link_state_handler { env.ep(), *this,
&Uplink_interface::_handle_session_link_state },
_interface { env.ep(), timer, mac_address(), alloc,
Mac_address(), config, interfaces, *rx(), *tx(),
*this }
{
/* install packet stream signal handlers */
rx_channel()->sigh_ready_to_ack (_interface.sink_ack());
rx_channel()->sigh_packet_avail (_interface.sink_submit());
tx_channel()->sigh_ack_avail (_interface.source_ack());
tx_channel()->sigh_ready_to_submit(_interface.source_submit());
/* initialize link state handling */
Nic::Connection::link_state_sigh(_session_link_state_handler);
_session_link_state = Nic::Connection::link_state();
}
void Net::Uplink_interface::_handle_session_link_state()
{
_session_link_state = Nic::Connection::link_state();
_interface.handle_interface_link_state();
}

View File

@ -1,178 +0,0 @@
/*
* \brief Uplink interface in form of a NIC session component
* \author Martin Stein
* \date 2016-08-23
*/
/*
* 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 _UPLINK_H_
#define _UPLINK_H_
/* Genode includes */
#include <nic_session/connection.h>
#include <nic/packet_allocator.h>
/* local includes */
#include <avl_string_tree.h>
#include <interface.h>
#include <ipv4_address_prefix.h>
namespace Net {
using Domain_name = Genode::String<160>;
class Uplink_base;
class Uplink;
class Uplink_tree;
class Uplink_interface_base;
class Uplink_interface;
}
class Net::Uplink_tree
:
public Avl_string_tree<Uplink, Genode::Session_label>
{ };
class Net::Uplink_base
{
private:
Genode::Session_label const _label;
Domain_name const _domain;
public:
Uplink_base(Genode::Xml_node const &node);
virtual ~Uplink_base() { }
/**************
** Acessors **
**************/
Genode::Session_label const &label() const { return _label; }
Domain_name const &domain() const { return _domain; }
};
struct Net::Uplink : public Uplink_base,
private Genode::Avl_string_base
{
friend class Avl_string_tree<Uplink, Genode::Session_label>;
friend class Genode::List<Uplink>;
private:
Genode::Allocator &_alloc;
Configuration const &_config;
Pointer<Uplink_interface> _interface { };
void _invalid(char const *reason) const;
public:
struct Invalid : Genode::Exception { };
Uplink(Genode::Xml_node const &node,
Genode::Allocator &alloc,
Uplink_tree &old_uplinks,
Genode::Env &env,
Timer::Connection &timer,
Interface_list &interfaces,
Configuration &config);
~Uplink();
/*********
** log **
*********/
void print(Genode::Output &output) const;
};
class Net::Uplink_interface_base : public Interface_policy
{
private:
Const_reference<Domain_name> _domain_name;
Genode::Session_label const _label;
bool const &_session_link_state;
bool _interface_ready { false };
/***************************
** Net::Interface_policy **
***************************/
Domain_name determine_domain_name() const override { return _domain_name(); };
void handle_config(Configuration const &) override { }
Genode::Session_label const &label() const override { return _label; }
void interface_unready() override;
void interface_ready() override;
bool interface_link_state() const override;
public:
Uplink_interface_base(Domain_name const &domain_name,
Genode::Session_label const &label,
bool const &session_link_state);
virtual ~Uplink_interface_base() { }
/***************
** Accessors **
***************/
void domain_name(Domain_name const &v) { _domain_name = v; }
};
class Net::Uplink_interface : public Uplink_interface_base,
public Nic::Packet_allocator,
public Nic::Connection
{
private:
enum {
PKT_SIZE = Nic::Packet_allocator::DEFAULT_PACKET_SIZE,
BUF_SIZE = Nic::Session::QUEUE_SIZE * PKT_SIZE,
};
bool _session_link_state { false };
Genode::Signal_handler<Uplink_interface> _session_link_state_handler;
Net::Interface _interface;
Ipv4_address_prefix _read_interface();
void _handle_session_link_state();
public:
Uplink_interface(Genode::Env &env,
Timer::Connection &timer,
Genode::Allocator &alloc,
Interface_list &interfaces,
Configuration &config,
Domain_name const &domain_name,
Genode::Session_label const &label);
/***************
** Accessors **
***************/
Mac_address const &router_mac() const { return _interface.router_mac(); }
};
#endif /* _UPLINK_H_ */

View File

@ -1,5 +1,5 @@
/*
* \brief Downlink interface in form of an Uplink session component
* \brief Interface back-end using Uplink sessions provided by the NIC router
* \author Martin Stein
* \date 2016-08-23
*/

View File

@ -1,5 +1,5 @@
/*
* \brief Downlink interface in form of an Uplink session component
* \brief Interface back-end using Uplink sessions provided by the NIC router
* \author Martin Stein
* \date 2016-08-23
*/

View File

@ -147,7 +147,7 @@ void Local::Main::_handle_router_state()
xml.attribute("label", "test_client -> ");
xml.attribute("domain", "downlink");
});
xml.node("uplink", [&] () {
xml.node("nic-client", [&] () {
xml.attribute("domain", "uplink");
});
xml.node("domain", [&] () {