Now I remember why I don’t like benchmarks much. Benchmark results are often hard to interpret as I showed with the state machine measurements. Measuring one small feature or execution path out of the context of an application does not provide meaningful results. The proper way to optimize a system is to start with a solid design, build the system, instrument the system to find the bottle necks and optimize those areas. Then you measure again to determine if the optimization was effective. So I’m changing direction yet again and starting to design my TCP/IP stack using modern C++ concepts.
Designing and implementing a TCP/IP stack is a big job for one person to take on part time as I’ve noted in the past. Here are the tactics I’ll use to make this feasible:
- Use modern C++ design techniques including Generic Programming and Design patterns. One of the major goals of this exercise is to show how using modern C++ programming makes the programmer or software engineer more productive without sacrificing performance.
- Narrow the functionality. I’ll only implement the minimum that I feel is essential for providing realistic performance results: IP, ICMP, UDP and a TFTP application that stores data in RAM.
- Use Linux as both the development environment and the execution environment. Linux provides a very productive development environment that includes the C++ Standard Library, the GNU C++ compiler GCC, and the Eclipse IDE. Linux also provides tools for profiling and measuring code performance and tools for measuring network performance. Finally, I can measure my TCP/IP stack against the Linux TCP/IP stack so I can do an almost apples-to-apples performance comparison.
The socket interface in Linux provides access to raw layer 2 (Ethernet) packets. This is done by creating a packet socket:
packet_socket = socket(PF_PACKET, int socket_type, int protocol);
by specifying the protocol family to be PF_PACKET and the socket_type to be SOCK_RAW (see packet(7) - Linux man page for incomplete details). This socket option is what is used by sniffer programs to gain access to raw packets. This also allows a TCP/IP stack to be implemented as a user space application. This approach is the mainstream implementation method for research TCP/IP stacks.
I don’t plan to stop there with yet another research TCP/IP stack. I already have some plans for the release beyond Cannonball. My plan includes porting the TCP/IP stack to two or three embedded processors, ARM, PowerPC, and ColdFire. I also plan to fill out the stack in the next release by implementing TCP and some additional protocols.