NIKSS-vSwitch / nikss

Native In-Kernel P4-programmable Software Switch for Software-Defined Networking (previously PSA-eBPF)
Apache License 2.0
48 stars 4 forks source link
ebpf p4 xdp

NIKSS - Native In-Kernel P4-programmable Software Switch for Software-Defined Networking

build nikss License

NIKSS is an in-kernel implementation of a P4 software switch. It works in conjunction with the P4-eBPF compiler. The NIKSS switch uses Portable Switch Architecture (PSA) as a forwarding model and extended Berkeley Packet Filter (eBPF) as a packet processing engine. NIKSS works seamlessly with both TC-based and XDP-based flavors of the PSA model for the P4-eBPF compiler.

This repository implements a low-level C API and CLI tool (nikss-ctl) to manage P4/PSA programs for NIKSS. The PSA-eBPF compiler that is used to generate P4 programs for NIKSS sits in the p4lang/p4c repository.

Main features of NIKSS:

Refer to the ACM CoNEXT paper for more details on design and performance numbers:

Tomasz Osiński, Jan Palimąka, Mateusz Kossakowski, Frédéric Dang Tran, El-Fadel Bonfoh, and Halina Tarasiuk. 2022. "A novel programmable software datapath for Software-Defined Networking". In Proceedings of the 18th International Conference on emerging Networking EXperiments and Technologies (CoNEXT '22). Association for Computing Machinery, New York, NY, USA, 245–260. https://doi.org/10.1145/3555050.3569117

Community

To discuss the NIKSS project you can use the following communication channels:

Installation

Docker

You can build a Docker image for NIKSS by running the below command from the project's root directory:

docker build -t nikss:latest .

We also provide a stable Docker image that is built on CI. You can fetch it by:

docker pull osinstom/nikss:latest

Installing NIKSS from source

Dependencies

NIKSS depends on following libraries and utilities:

All the dependencies can be installed on Ubuntu 20.04 with the following command:

sudo apt install make cmake gcc git libgmp-dev libelf-dev zlib1g-dev libjansson-dev

Note that nikss-ctl is statically linked with shipped libbpf, so there is no need to install this library system-wide. It is a submodule for this repository.

Build from source

  1. Get the code with submodules:

    git clone --recursive https://github.com/NIKSS-vSwitch/nikss.git
    cd nikss
  2. Build libbpf:

    ./build_libbpf.sh
  3. Build the code and install binaries:

    mkdir build
    cd build
    cmake <CMAKE_OPTIONS> ..
    make -j4
    sudo make install

    Possible cmake options to customize build are listed in the table below:

    CMake option Possible values Default value Description
    -DCMAKE_BUILD_TYPE empty | Release | Debug empty Build type. Empty means Debug without debug symbols.
    -DCMAKE_INSTALL_PREFIX any path /usr/local Sets the directory where make install intall the binaries.
    -DBUILD_SHARED on | off off Build shared library. When disabled only the nikss-ctl is built.

    Note on installing shared library: remember to execute sudo ldconfig after installation. If libnikss still can't be loaded, you can do one of these things:

    • Change prefix, e.g. to /usr and reinstall.
    • Add path to LD_LIBRARY_PATH, e.g.:
      export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH
    • Add system-wide path for LD:
      echo "/usr/local/lib" > /etc/ld.so.conf.d/usr_local_lib.conf
      ldconfig
  4. (Optional) Install C/C++ headers files:

    sudo make install_headers

    This step makes sense only when shared library is built (BUILD_SHARED is set to on) because otherwise linker will fail to find references to the libnikss library.

Commands reference

See command reference for all the possible commands. Here listed only the most important ones.

Naming convention

All objects can be accessed by name created by the p4c compiler. These names follow format <pipeline>_<extern name>. For example so defined table and actions:

control ingress(/* ... */) {
    action a() {}
    action b() {}

    table example_table {
        key = { /* ... */ }
        actions = { NoAction; a1; a2; }
    }
    /* ... */
}

Table example_table can be accessed with name ingress_example_table, and action a with name ingress_a. NoAction can be accessed with name _NoAction because it is not define within pipeline. In the same way names for all other externs are created.

Description of selected commands

Load pipeline into kernel bpf subsystem:

nikss-ctl pipeline load id <ID> <FILENAME>

Unload pipeline from kernel bpf subsystem:

nikss-ctl pipeline unload id <ID>

Attach port:

nikss-ctl add-port pipe <ID> dev <INTERFACE>

Detach port:

nikss-ctl del-port pipe <ID> dev <INTERFACE>

Show pipeline information:

nikss-ctl pipeline show id <ID>

Create clone session and add member to it:

nikss-ctl clone-session create pipe <ID> id <SESSION_ID>
nikss-ctl clone-session add-member pipe <ID> id <SESSION_ID> egress-port <OUTPUT_PORT> instance <INSTANCE_ID> [cos <CLASS_OF_SERVICE>] [truncate plen_bytes <BYTES>]

Create multicast group and add member to it:

nikss-ctl multicast-group create pipe <ID> id <MULTICAST_GROUP_ID>
nikss-ctl multicast-group add-member pipe <ID> id <MULTICAST_GROUP_ID> egress-port <OUTPUT_PORT> instance <INSTANCE_ID>

Add an entry to a table without implementation:

nikss-ctl table add pipe <ID> <TABLE> action <ACTION> key <KEY> data <DATA> [priority <PRIORITY>]