XDP for Windows

repository·main·Indexed 19 days ago

https://github.com/microsoft/xdp-for-windows

A high-performance networking interface for Windows that allows applications to bypass the standard networking stack to achieve high packet processing rates. It provides the AF_XDP interface for user-mode applications to receive, inspect, drop, or send network traffic via XDP hook points using shared memory rings. The project includes driver-level APIs for registering XDP interfaces, managing RX/TX queues, and handling data path operations via XDP_RING, XDP_BUFFER, and XDP_FRAME structures.

Tokens
41.8K
Snippets
137
Records
202
Agent score
66%

What's inside XDP for Windows

  1. Overview of XDP for Windows

    main
    XDP for Windows is a high-performance Windows interface designed to send and receive network packets at high rates. It achieves this by bypassing most of the standard Windows OS networking stack, similar to the eXpress Data Path (XDP) concept used in Linux. Developers use this project to implement high-throughput, low-latency networking applications on Windows.
  2. eBPF Integration Guide Overview

    main
    This guide explains how to integrate XDP for Windows with the ebpf-for-windows project. XDP for Windows provides the high-performance packet processing framework, while ebpf-for-windows provides the eBPF runtime and ecosystem. Together, they allow developers to run eBPF programs on Windows to process network traffic at the XDP layer.
  3. How extension negotiation works for drivers and AF_XDP applications

    main

    The XDP platform negotiates extensions between sockets/programs and drivers using the following workflows:

    For XDP Drivers

    1. Declaration: Drivers declare supported extensions during queue initialization using XDP_EXTENSION_INFO.
    2. Enablement: The XDP platform enables the intersection of the requested extensions and the extensions supported by the driver.
    3. Retrieval: Drivers retrieve XDP_EXTENSION handles to access the enabled extensions.

    For AF_XDP Applications

    1. Implicit Enablement: All V1 extensions are implicitly enabled by the AF_XDP subsystem.
    2. Direct Access: Applications do not need to explicitly declare version information; they can directly access extension data using extension getter functions.
    3. Driver Dependency: Extension availability is ultimately dependent on whether the underlying driver supports them.
  4. Use XDP_API_VERSION_3 or later instead of XDP_API_TABLE

    main

    The XDP_API_TABLE structure is deprecated. It was used to hold function pointers from the xdpapi.dll library for older versions of the API (XDP_API_VERSION_1 and XDP_API_VERSION_2).

    Recommendation for new applications: Do not use XDP_API_TABLE. Instead, use XDP_API_VERSION_3 or later. These newer versions provide header-only API implementations, which eliminates the need to load xdpapi.dll or manage a function pointer table manually.

  5. XDP eBPF Program Type and Context

    main

    XDP registers a specific eBPF program type. When writing programs, use the following identifiers and the xdp_md_t context structure.

    Identifiers:

    • Program type GUID: f1832a85-85d5-45b0-98a0-7069d63013b0
    • Attach type GUID: 85e0d8ef-579e-4931-b072-8ee226bb2e9d
    • bpf_prog_type: BPF_PROG_TYPE_XDP
    • ELF section prefix: xdp

    Context Structure (xdp_md_t): Every program receives a pointer to this structure describing the packet:

    typedef struct xdp_md {
        void *data;               // Pointer to start of packet data (L2 frame).
        void *data_end;           // Pointer to end of packet data.
        uint64_t data_meta;       // Packet metadata (reserved).
        uint32_t ingress_ifindex; // Ingress network interface index.
        uint32_t rx_queue_index;  // RX queue index on the ingress interface.
    } xdp_md_t;
    typedef struct xdp_md {
        void *data;
        void *data_end;
        uint64_t data_meta;
        uint32_t ingress_ifindex;
        uint32_t rx_queue_index;
    } xdp_md_t;
  6. Manage XDP receive queues (RX)

    main

    XDP interfaces manage receive queues through a lifecycle of creation, activation, and deletion:

    1. Create: Call XDP_CREATE_RX_QUEUE to request a queue. The platform ensures at most one XDP queue exists per hardware queue. This returns an InterfaceRxQueue context and an InterfaceRxQueueDispatch table.
    2. Activate: Use XDP_ACTIVATE_RX_QUEUE to insert the queue into the data path. This step is required because the queue is not ready for use immediately after creation.
    3. Delete: Call XDP_DELETE_RX_QUEUE to remove the queue. After this, the interface must not access descriptor rings or XDP buffers associated with that queue.

    Note: The XDP_INTERFACE_RX_QUEUE_DISPATCH structure contains the InterfaceNotifyQueue callback used by the platform to request data path operations.

    typedef NTSTATUS XDP_CREATE_RX_QUEUE(
        _In_ XDP_INTERFACE_HANDLE InterfaceContext,
        _Inout_ XDP_RX_QUEUE_CONFIG_CREATE Config,
        _Out_ XDP_INTERFACE_HANDLE *InterfaceRxQueue,
        _Out_ const XDP_INTERFACE_RX_QUEUE_DISPATCH **InterfaceRxQueueDispatch
    );
    
    typedef NTSTATUS XDP_ACTIVATE_RX_QUEUE(
        _In_ XDP_INTERFACE_HANDLE InterfaceRxQueue,
        _In_ XDP_RX_QUEUE_HANDLE XdpRxQueue,
        _In_ XDP_RX_QUEUE_CONFIG_ACTIVATE Config
    );
    
    typedef VOID XDP_DELETE_RX_QUEUE(
        _In_ XDP_INTERFACE_HANDLE InterfaceRxQueue
    );
  7. How the User-Mode API handles Per-Type Device Fallback

    main

    The XDP API (specifically _XdpOpenObjectType() in xdp/details/xdpapi.h and xdp/details/afxdp.h) implements a fallback mechanism to ensure compatibility with older versions of XDP.

    Fallback Logic:

    1. The API attempts to open the specific per-type device (e.g., \Device\xdpapi\program).
    2. If the per-type device does not exist, the API checks the application's version requirements.
    3. If the application defines XDP_MINIMUM_MAJOR_VER and XDP_MINIMUM_MINOR_VER such that the minimum version is <= 1.3, the API falls back to the common \Device\xdp device.
    4. Applications targeting a version > 1.3 will not perform this fallback, as per-type devices were introduced after version 1.3.
  8. Understand XDP Per-Object-Type Security

    main

    XDP provides fine-grained access control by exposing separate device objects for different XDP object types. Instead of a single monolithic device, administrators can assign independent SDDL (Security Descriptor Definition Language) security descriptors to specific object types. This allows granting a user access to XDP maps without necessarily granting them access to XDP programs or interface configurations.

    Key Concepts:

    • Per-type devices: Located under the \Device\xdpapi directory.
    • Common device: The legacy \Device\xdp device allows any object type and is used for backward compatibility.
    • Security Enforcement: To effectively restrict access via per-type devices, the common device's SDDL must be configured to be at least as restrictive as the per-type SDDLs. If a user has access to the common device, they can bypass per-type restrictions by accessing objects through it.
  9. What are XDP Descriptor Extensions?

    main
    Descriptor extensions are optional, variable-sized metadata structures stored contiguously after base descriptors (frames, buffers, or TX completions) in memory. They allow the XDP data path to pass additional information—such as timestamps, checksum offload data, or memory mapping details—without modifying the base descriptor structures, ensuring backward compatibility and memory efficiency.