Network manager (io-pkt*)
The io-pkt* component is the active executable within the network subsystem. Acting as a kind of packet redirector/multiplexer, io-pkt* is responsible for loading protocol and driver modules based on the configuration given to it on its command line (or via the mount command after it's started).
Employing a zero-copy architecture, the io-pkt* executable efficiently loads multiple networking protocols or drivers on the fly— these modules are shared objects that install into io-pkt*.
The io-pkt stack is very similar in architecture to other component subsystems inside of the Neutrino operating system. At the bottom layer, are drivers that provide the mechanism for passing data to and receiving data from the hardware. The drivers hook into a multi-threaded layer-2 component (that also provides fast forwarding and bridging capability) that ties them together and provides a unified interface for directing packets into the protocol-processing components of the stack. This includes, for example, handling individual IP and upper-layer protocols such as TCP and UDP.
In Neutrino, a resource manager forms a layer on top of the stack. The resource manager acts as the message-passing intermediary between the stack and user applications. It provides a standardized type of interface involving open(), read(), write(), and ioctl() that uses a message stream to communicate with networking applications. Networking applications written by the user link with the socket library. The socket library converts the message-passing interface exposed by the stack into a standard BSD-style socket layer API, which is the standard for most networking code today.
At the driver layer, there are interfaces for Ethernet traffic (used by all Ethernet drivers), and an interface into the stack for 802.11 management frames from wireless drivers. The hc variants of the stack also include a separate hardware crypto API that allows the stack to use a crypto offload engine when it's encrypting or decrypting data for secure links. You can load drivers (built as DLLs for dynamic linking and prefixed with devnp- for new-style drivers, and devn- for legacy drivers) into the stack using the -d option to io-pkt.
APIs providing connection into the data flow at either the Ethernet or IP layer allow protocols to coexist within the stack process. Protocols (such as Qnet) are also built as DLLs. A protocol links directly into either the IP or Ethernet layer and runs within the stack context. They're prefixed with lsm (loadable shared module) and you load them into the stack using the -p option. The tcpip protocol (-ptcpip) is a special option that the stack recognizes, but doesn't link a protocol module for (since the IP stack is already built in). You still use the -ptcpip option to pass additional parameters to the stack that apply to the IP protocol layer (e.g. -ptcpip prefix=/alt to get the IP stack to register /alt/dev/socket as the name of its resource manager).
A protocol requiring interaction from an application sitting outside of the stack process may include its own resource manager infrastructure (this is what Qnet does) to allow communication and configuration to occur.
In addition to drivers and protocols, the stack also includes hooks for packet filtering. The main interfaces supported for filtering are:
- Berkeley Packet Filter (BPF) interface
- A socket-level interface that lets you read and write, but not modify or block, packets, and that you access by using a socket interface at the application layer (see http://en.wikipedia.org/wiki/Berkeley_Packet_Filter ). This is the interface of choice for basic, raw packet interception and transmission and gives applications outside of the stack process domain access to raw data streams.
- Packet Filter (PF) interface
- A read/write/modify/block interface that gives complete control over which packets are received by or transmitted from the upper layers and is more closely related to the io-net filter API.