Xilinx/AMD Solarflare Onload

repository·master·Indexed 21 days ago

https://github.com/xilinx-cns/onload

Components for Xilinx/AMD Solarflare Onload, including OpenOnload utilities, Debian packaging tools, and the ef_vi zero-copy API. Provides documentation on building from source, creating distribution tarballs, generating container images, and configuring kernel-level logging and control plane servers.

Tokens
5.8K
Snippets
13
Records
28
Agent score
71%

What's inside xilinx-cns-onload

  1. Create an Onload distribution tarball

    master

    Use the scripts/onload_mkdist script to create a tarball containing production code. The resulting tarball will be placed at the base of the repository.

    • Non-release tarballs: Versioned with the current commit hash (intended for testing).
    • Release tarballs: Versioned with the current date only (intended for wider distribution). Use the --release flag to produce these.

    To install from the resulting tarball, follow the README included inside it. You can install with the --debug flag to enable additional logging and error-checking.

    ./scripts/onload_mkdist --release
  2. Run Onload unit tests

    master

    Unit tests for the user build tree are located in tests/onload/cplane_unit and tests/onload/oof. They are written in C. While you can run make inside the user tree to compile and run individual tests, the easiest way to run the full suite is using the provided script.

    ./scripts/run_unit_tests.sh
  3. Build OpenOnload directly from the repository

    master

    For active development or running tests, you can build directly from the repository. This process involves two parts: Driver code (kernel modules) and User code (libraries).

    Build Steps:

    1. Construct the build tree using mmakebuildtree.
    2. Compile the driver and user components using make.

    Note: Building from the repository enables debugging mode (extra logging) by default. To disable it, pass NDEBUG=1 to the make command.

    export PATH="$PWD/scripts:$PATH"
    
    mmakebuildtree --driver
    mmakebuildtree --user
    
    make -C "$(mmaketool --toppath)/build/$(mmaketool --driverbuild)"
    make -C "$(mmaketool --toppath)/build/$(mmaketool --userbuild)"
  4. Install and load Onload from a repository build

    master

    After building from the repository, you must load the drivers into the kernel and then load the libraries for your applications.

    1. Load Kernel Drivers: Use the load.sh script located in the driver build directory.

    2. Run Applications with Onload: You can use either LD_PRELOAD or the onload wrapper script.

    Methods:

    • Using onload script (Recommended): scripts/onload <app>
    • Using LD_PRELOAD: LD_PRELOAD="$(mmaketool --toppath)/build/$(mmaketool --userbuild)/lib/transport/unix/libcitransport0.so" <app>
    # Load drivers
    "$(mmaketool --toppath)/build/$(mmaketool --driverbuild)/driver/linux/load.sh" onload
    
    # Run application
    scripts/onload <app>
  5. Create an Onload container image

    master

    You can create container images containing compiled userland components from a mkdist tarball using scripts/onload_mkcontainer.

    Note: Kernel modules and the control plane must be installed separately.

    Usage Patterns:

    • Create userland image: ./scripts/onload_mkcontainer --user onload-user:latest *.tgz
    • Create image from existing mkdist contents: ./scripts/onload_mkcontainer --source onload-source:latest *.tgz
    • Create both source and user images: Specify both --source and --user flags.

    Configuration via Environment Variables:

    • Set custom UBI base images: USER_DOCKER_EXTRA_ARGS="--build-arg BUILDER_UBI_BASE=... --build-arg USER_BASE=..."
    • Build a debug version: USER_DOCKER_EXTRA_ARGS="--build-arg ONLOAD_BUILD_PARAMS=--debug"

    These images are designed for reuse in compatible libc environments (e.g., via COPY --from=) rather than being used as base images (FROM onload-user).

    ./scripts/onload_mkdist
    ./scripts/onload_mkcontainer --user onload-user:latest *.tgz
  6. Build requirements for OpenOnload

    master

    To build OpenOnload, you need the following dependencies (noted for Redhat-based distributions; names may vary on other distros):

    • binutils
    • gawk
    • gcc / gcc-c++ or g++ (preferably gcc-11 for C11 features)
    • sed
    • make
    • bash
    • which
    • kmod
    • tar
    • gzip
    • glibc-common
    • libcap-devel
    • libmnl-devel
    • perl-Test-Harness
    • git (required for automatic versioning via onload_mkdist)

    Crucial: You must also install the kernel and its development headers (kernel and kernel-devel) for the specific kernel version you wish to build against.

  7. What is ef_vi and when to use it

    master

    ef_vi is a zero-copy API that provides applications with direct access to the network adapter's datapath. It allows for sending and receiving raw Ethernet frames directly from user-level, bypassing the kernel network stack to achieve minimal CPU overhead and maximum performance.

    Use ef_vi when your application requires:

    • Very high throughput.
    • High-performance packet filtering.
    • High-performance data forwarding.

    Important Considerations:

    • Protocol Implementation: Because ef_vi operates at the Ethernet layer, you must implement your own upper-layer protocols (e.g., IP, UDP, TCP). It is relatively straightforward for UDP, but implementing TCP from scratch is highly complex.
    • Coexistence: ef_vi can be used alongside OpenOnload. A common pattern is using ef_vi for performance-critical UDP traffic while using OpenOnload sockets for TCP traffic.
    • Zero-Copy: The interface provides direct access to hardware memory buffers, avoiding the copies typically incurred by higher-level socket interfaces.
  8. Core components of an ef_vi Virtual Interface (VI)

    master

    To use ef_vi, you must first allocate a Virtual Interface (VI), represented by the type ef_vi. A VI consists of three primary components:

    1. Receive Descriptor Ring: Used for receiving incoming packets.
    2. Transmit Descriptor Ring: Used for sending outgoing packets.
    3. Event Queue: A communication channel from the NIC to your software. It notifies you when:
      • Packets arrive from the network.
      • Transmits complete (allowing you to free or reuse buffers).
      • You can retrieve these events by calling ef_eventq_poll().

    Memory Requirements:

    • Buffers: Packet data buffers must be pinned (to prevent paging) and registered for DMA using an ef_memreg.
    • Addressing: The NIC uses ef_addr (a special address space) to identify locations in registered memory.
    • Protection Domains (ef_pd): These provide an address space for registered memory. All VIs allocated against the same protection domain can access any memory registered within that domain.
  9. Onload Cplane Server Networking and Privilege Model

    master

    The Onload Cplane Server manages network state (ARP, routes, interfaces, etc.) for Onload-accelerated applications. It operates with the following key behaviors:

    Network Namespace Management

    If a network namespace file is provided via the command line, the server switches into that namespace before initializing its state. In certain build configurations (CP_SYSUNIT), it may also interact with a 'shim' to manage state across namespaces.

    Privilege Dropping

    To enhance security, the server can drop privileges after initialization.

    • It can drop to a specific UID and GID using --uid and --gid.
    • Even when dropping privileges, the server retains CAP_NET_ADMIN to allow for network management tasks like teaming.
    • If --track-xdp is enabled, the server also retains CAP_SYS_ADMIN to track XDP programs.

    Memory Management

    The server uses mmap with MAP_SHARED to create a continuous chunk of memory for the Management Information Base (MIB) tables. This memory is shared between the kernel, the cplane process, and Onloaded user processes, ensuring a consistent view of network state.

  10. Install Onload Debian packages

    master

    The Debian source package for Onload provides several distinct packages depending on your requirements:

    • #TYPE#-user: Provides the 32-bit and 64-bit userspace libraries.
    • #TYPE#-source: Provides the source code required to build the kernel modules.
    • #TYPE#-dev: Provides the header files necessary for developing applications that use Onload.
    • #TYPE#-examples: Provides sample applications for onload and ef_vi.
  11. Use the Onload Extensions API in Java

    master

    The Onload extensions API is accessed via the OnloadExt class, which mimics the documented C interface. All extension methods are static.

    Library Loading

    When running your Java application, the libOnloadExt.so file must be in your library path. If it is not found, you will encounter a failed to load the jni shared library exception.

    You can add the library directory to LD_LIBRARY_PATH or use LD_BIND_NOW to ensure correct location:

    export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ONLOAD_LIB
    export LD_BIND_NOW=y

    Best Practices and Constraints

    • File Descriptors: The wrapper works most effectively when provided with native file descriptors. While some overloads exist for common Java socket classes, you may need to implement your own for custom types.
    • Availability Checks: Most calls will throw an exception if the application is not running under Onload. To avoid this, check availability first using:
      • OnloadExt.IsPresent()
      • OnloadZeroCopy.IsZeroCopyEnabled()
    • Constants: The API uses public static final int instead of Java enums to maintain compatibility with older Java versions.
    • ZeroCopy: The OnloadZeroCopy library requires you to implement a class that provides a Callback function. Note that JNI overhead may reduce the performance gains of ZeroCopy.
    export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ONLOAD_LIB
    export LD_BIND_NOW=y