================================= Component for routing NIC packets ================================= Brief ##### The nic_router component can be used to individually route IPv4 packets between multiple NIC sessions. Thereby, it can translate between different IP subnets. The component supports port forwarding, as well as the partitioning of the TCP and UDP port spaces. Basic routing ############# The nic_router component provides multiple sessions of the 'NIC' service (downlinks) while requesting one 'NIC' session (the uplink) itself. Through common Genode session routing, the uplink can be connected to any other NIC server. Inside the component, uplink and downlinks are treated the same. Its routing algorithm is ultimately controlled through the configuration. For each NIC session there must be a policy: ! ! The 'label' attribute must match the session label respectively 'uplink' for the uplink session. The 'src' attribute contains a static IPv4 identity that represents the nic_router with respect to that session. This identity is used when doing Network-Address-Translation to the session. Moreover, a policy tag may contain multiple 'ip' sub-tags: ! ! Each 'ip' tag defines a routing rule for IPv4 packets that are sent by the session of the surrounding policy. Such a rule needs at least a 'dst' attribute that contains an IPv4 address prefix. When the nic_router receives an IPv4 packet, it goes top-down through all the rules of the session, checking whether the packet destination matches the 'dst' attribute. The first rule that matches is inspected deeper. The next thing to be read is the 'label' attribute that names the target session of the rule. If the label points to a valid session, the packet could now be routed via this rule. But the IP rule is only remembered as fallback yet because it may contain sub-tags for preferred UDP and TCP routing: ! ! Those tags work pretty similar to the IP rules. The 'dst' attribute defines the port that a packet must be addressed to for a match. The 'label' attribute again points to the target session. If no matching UDP or TCP rule with a valid target session is found inside the matching IP rule, the nic_router falls back to the IP rule. If the target session of the matching IP rule isn't valid, it continues with the next matching IP rule, and so on. Modify destination and gateway ############################## All three, the 'ip', 'udp', and 'tcp' tag may have further attributes 'to' and/or 'via'. Both attributes define an IPv4 address. The address in the 'to' attribute replaces the IPv4 destination of an affected packet. The address in the 'via' attribute is the gateway for that rule. This means, when searching for the next Ethernet destination of an affected packet, the nic_router uses the 'via' address as criterion. If not set, the 'via' address is always the IPv4 destination of the packet. Hence, if only the 'to' attribute is set for a rule, the value is also used as 'via' address. ! ! ! Network address translation ########################### The nic_router component can translate between different IPv4 subnets of clients, and "uplink". When enabled within the policy of a client: ! the source address of all IPv4 packets of that client is replaced by the 'src' value of the applied target session. And the TCP/UDP source port is replaced by a dynamically allocated source port of the applied target session. There is an exception from the latter. If the source port of the packet matches a TCP/UDP rule of the applied target session, the packet is assumed to be a reply to a port-forwarded request from the counterside. In this case, the source port remains unchanged to enable the receiver to correlate the packet correctly. For partitioning the TCP/UDP port space, e.g., the source ports regarding the 'uplink' session between different client sessions, one can configure how many ports may be used concurrently per client session: ! ! ! The ports attribute contains the maximum number of ports that the nic_router assigns to the given session. This is necessary to avoid that a NIC session can run Denial-of-Service attacks against the nic_router by occupying all of its ports. For both, UDP and TCP activities, the nic_router holds link states. The link states enable the nic_router to re-direct related packets from the counterside correctly without the need for additional routing rules. Such link state rules are the most preferred way of routing. Before the nic_router starts looking for IP, UDP, or TCP rules for a packet, it tries to find a matching rule amongst the link states. As link state rules are created on demand and are bound to an active connection between two peers, it is desirable to clear them away as soon as they are not needed anymore. A precise algorithm for that enables the NIC sessions to get the maximum out of their resources (ports, RAM). A TCP state rule corresponding is held until the nic_router observes the four-way termination handshake of TCP and two times the estimated round-trip time has passed. The nic_router currently doesn't estimate any round-trip times by itself. Instead it expects an attribute 'rtt_sec' in its 'config' tag: ! ... This would set the round-trip time to three seconds which means that link state rules wait six seconds after a termination handshake before they close themselves. As UDP has no notion of connections, UDP state rules are simply held for a duration of two times the round-trip time after the last packet. This way, the peers can keep alive a UDP pseudo-connection by frequently sending empty packets. Examples ######## This paragraph will list and explain some interesting configuration snippets. A comprehensive example of how to use the nic_router can be found in the test script 'libports/run/nic_router.run' . Accessing a private server network ================================== In this example, we assume that there is a HTTP server "behind" the nic_router (downlink) listening at port 80. Through the uplink session, several clients may ask the nic_router for HTTP. The nic_router has the following configuration: ! ! ! ! ! ! ! ! ! The uplink IP rule matches only packets that directly address the nic_router's uplink identity. Amongst those packets, the ones to TCP port 80 also match the TCP sub-rule. The TCP sub-rule is rated higher than the surrounding IP rule and thus gets applied. Consequently, the nic_router replaces the IPv4 destination of the packets with the 'to' value (which is the local server address), then looks up and installs the next Ethernet destination for the given server address, and finally sends the packet on the servers NIC session. All other packets from the uplink are dropped. Even those that address the nic_router directly but with another port. This is because, although the IP rule still matches, it specifies no target session. If the server sends back reply packets to the client, they address the clients public IP because the IPv4 source of the previous request wasn't modified. Thus, these packets match the IP rule in the server policy and get forwarded to the uplink. But furthermore, the nic_router is configured do NAT for the server (with 30 simultaneous TCP connections allowed). Hence, the nic_router replaces the IPv4 source in the server replies by its uplink identity '10.0.2.55'. The source port, at the other hand, is not replaced because it matches a TCP rule in the uplink policy. This way, the client is able to associate the replies to its TCP connection with the server. Using public servers from a private network =========================================== Let's assume we have a UDP client "behind" the nic_router and like to talk to an "outside" server. An example configuration for that would be: ! ! ! ! ! UDP packets from the client to the public network match the clients IP rule and therefore are forwarded to the uplink. Because of the NAT attributes, the packets are modified to have '10.0.2.55' as IPv4 source and a free UDP port of the uplink session as source port. The client is allowed to open a maximum of two such connections at a time. The uplink doesn't need any rules to forward the replies for the UDP client correctly as long as the server replies in time. This is because the nic_router still holds the link state of the initial UDP packet from the client and can use it to map back IP address and port. Limitations ########### Currently, different client sessions should not share the same subnet to be able to communicate with each other, because forwarding broadcast packets (e.g., ARP packets) between different clients of the same subnet is not supported yet.