Skip to content

Latest commit

 

History

History
156 lines (123 loc) · 5.39 KB

running-p4-program-and-ptf-test.md

File metadata and controls

156 lines (123 loc) · 5.39 KB

Running a P4 program and testing it using a PTF test

(Verified this section is updated and working on 2024-Feb-03)

Prerequisites:

  • You have started the container, and followed the steps described in the section Useful extra software to install in the container.
  • You have a P4 source program that compiles successfully following the steps below.
    • If you want to test these steps on your system with a known-good example P4 program and PTF test, use the files in the directory sample.
  • You have written a PTF test in Python that you want to test it with.
    • TODO: Some time write details of how such a test should be written, e.g. what ports exist?

I will use example file names sample.p4 for the P4 program, and ptf-test1.py for the Python PTF test. These steps will work even if the P4 source code is spread over many files, but it is assumed here (so far) that the Python source code for the PTF test is in a single file.

These instructions use p4c-dpdk installed in the base OS for compiling your P4 program. The reasons for this are:

  • I know how to update the p4c-dpdk version in the base OS to the latest version, compiled from source code.
  • I do not yet know how to do so for the version of p4c-dpdk that is installed in the container.

Using the p4c-dpdk in the base OS thus makes it easier for me to choose which version of source code to build p4c-dpdk that I wish.

Compiling the P4 program

You must do these steps in the base OS in every terminal you create:

export P4GUIDE="${HOME}/p4-guide"
export PYPKG_TESTLIB="${P4GUIDE}/testlib"
export IPDK_HOME="${HOME}/ipdk"
export PATH="${P4GUIDE}/ipdk/bin:${PATH}"

In base OS:

BASENAME="sample"
DIR="${P4GUIDE}/ipdk/${BASENAME}"
cd ${DIR}
compile-base-os.sh -a pna -s ${BASENAME}.p4

Copying the necessary files into the container

In base OS:

mkdir -p ~/.ipdk/volume/${BASENAME}
cp -pr ${DIR}/* ~/.ipdk/volume/${BASENAME}

If runptf.sh and the Python PTF source code files are not in directory ${DIR}, copy them into ~/ipdk/volume/${BASENAME}, too.

Running the P4 program with the PTF test

These commands only need to be run in the container once:

source $HOME/my-venv/bin/activate
export PYPKG_TESTLIB="/tmp/testlib"

In container:

BASENAME="sample"
/tmp/bin/start-infrap4d-and-load-p4-in-cont.sh ${BASENAME} ${BASENAME}
cd /tmp/${BASENAME}
./runptf.sh

Note: These steps also work for a P4 program written for the PNA architecture where the PTF test is auto-generated by the p4testgen program. See the example P4 program in the testprog2 directory, and the small bash script create-ptf-test.sh there that shows example command line parameters for p4testgen that have been tested to work for this purpose. These steps might also work for a PSA architecture P4 program, but I have not tried that myself yet.

Debugging note: The load_p4_prog.sh script contains within it a command that begins with p4rt-ctl set-pipe. I believe that a side effect of that command is to create files with these names within the directory shared between container and base OS:

  • p4.c - A C source file that is to be compiled and loaded into the DPDK software switch, generated by translating it from the .spec file output by p4c-dpdk.
  • p4.o - The object file created by compiling p4.c
  • p4.so - A shared library file created by compiling p4.c.

Debugging note: Whatever number N of ports you create, given as the parameter to the setup_tapports_in_default_ns.sh script above, the port numbers as seen by the P4 program are numbered 0 through N-1. At least in some cases I have seen, attempting to send a packet to a port larger than N-1 can cause infrap4d to crash with a SEGFAULT.

P4 DPDK limitation: Attempting to load a compiled P4 program that has 0 tables will fail with an error message like this one:

Error: P4Runtime RPC error (INTERNAL): P4Info is missing these required resources: Tables.

It is unusual for a P4 program to have 0 tables, but if you run across this, a simple workaround is to create a "dummy table", i.e. a table with 0 key fields, one action, and const default_action = my_action(params_go_here);, where you can define whatever you want for my_action (including any name you want for that action), including an action with an empty body that does nothing.

Copying output files recorded during the PTF test run back to the base OS

See these files in the directory ~/.ipdk/volume/${BASENAME}:

  • ptf.pcap
  • ptf.log

The file ptf.pcap should contain a mix of all packets on all ports, in time order. Each should have a "PPI" header, which contains fields like the ones shown below. You can see the port number that the packet was sent or received on in the first "Interface ID" field. I do not know why there are two "Aggregation Extension" and two "Interface ID" fields, but from my experience it seems that the first one is the one you should pay attention to.

PPI version 0, 24 bytes
    Version: 0
    Flags: 0x00
        .... ...0 = Alignment: Not aligned
        0000 000. = Reserved: 0x00
    Header length: 24
    DLT: 1
    Aggregation Extension
        Field type: Aggregation Extension (8)
        Field length: 4
        Interface ID: 1
    Aggregation Extension
        Field type: Aggregation Extension (8)
        Field length: 4
        Interface ID: 0