This code base provides an infrastructure and application test and analysis framework. Discrete modules provide functionality with the assistance of a common core. Each module also defines a REST API via a Swagger specification to allow users to access and control its functionality.
The first set of modules for OpenPerf provides a user-mode stack. This stack is an amalgam of lwip for TCP/IP protocol support and DPDK for network connectivity. Configuration and management of network ports and interfaces is defined in this REST API.
OpenPerf is written in modern C/C++, e.g. C11 and C++17. The build process is
handled via make
and uses clang by default. OpenPerf
also depends on some 3rd party components:
- DPDK - used for network drivers and packet buffers
- expected - a std::expected implementation
- immer - a library of persistent and immutable data structures written in C++.
- json - a modern JSON library for C++
- libpcap - a packet capture library
- lwip - a lightweight IP stack
- pistache - a C++ REST framework with Swagger support
- sljit - a platform independent JIT compiler used to compile BPF programs to machine code
- yaml-cpp - a YAML parser and emitter in C++ matching the YAML 1.2 spec.
- ZeroMQ - a distributed messaging library
Unit tests are written with catch2, a modern C++ unit testing framework. Additionally, build acceptance tests are run with mamba, a Python based test runner.
OpenPerf is inherently multi-threaded. In order to maximize per thread performance, OpenPerf uses lockless and non-blocking techniques instead of traditional thread synchronization methods.
One motivation for using ZeroMQ is to allow message passing between components. For example, logging is handled internally by a thread whose sole job is to listen for incoming logging messages on a ZeroMQ socket and write them to the console. This design ensures serialization of log messages while allowing asynchronous logging from client threads.
In cases where message passing is not applicable, components use lockless data structures to communicate between threads. The framework contains both a lockless list and hash-table implementation.
OpenPerf is composed of a core framework and three primary code modules:
-
API
: The API module runs a web service that provides access to OpenPerf internals via a REST interface. -
PacketIO
: The packetio module contains the stack and packet forwarding logic necessary to pass packets between the physical ports and the user created interfaces. -
Socket
: The socket module provides a BSD sockets compatible API to the stack in the packetio module. It creates the shared memory and UNIX domain socket required by the libopenperf-shim.so library for access to stack functions.
The core framework provides support for common functionality across all modules, such as logging, option handling, data structures, event loops, etc.
Client access to the stack is provided via a shim library, libopenperf-shim.so
, that can be
used with any program via the LD_PRELOAD environment variable. Consult the
getting started guide for example usage.
Additionally, users can create their own modules to link directly into the OpenPerf binary to allow direct access to the packetio and socket module. For more information, refer to the developer guide.