github.com/cilium/cilium@v1.16.2/Documentation/contributing/testing/bpf.rst (about) 1 .. only:: not (epub or latex or html) 2 3 WARNING: You are looking at unreleased Cilium documentation. 4 Please use the official rendered version released here: 5 https://docs.cilium.io 6 7 .. _bpf_testing: 8 9 ******************************** 10 BPF Unit and Integration Testing 11 ******************************** 12 13 Our BPF datapath has its own test framework, which allows us to write unit and integration tests that 14 verify that our BPF code works as intended, independently from the other Cilium components. The 15 framework uses the ``BPF_PROG_RUN`` feature to run eBPF programs in the kernel without attaching 16 them to actual hooks. 17 18 The framework is designed to allow datapath developers to quickly write tests 19 for the code they are working on. The tests themselves are fully written in C to minimize context 20 switching. Tests pass results back to the framework which will outputs the results in Go test output, 21 for optimal integration with CI and other tools. 22 23 Running tests 24 ============= 25 26 To run the tests in your local environment, execute the following command from the project root: 27 28 .. code-block:: shell-session 29 30 $ make run_bpf_tests 31 32 .. note:: 33 34 Running BPF tests requires Docker and is only expected to work on Linux. 35 36 To run a single test, specify its name without extension. For example: 37 38 $ make run_bpf_tests BPF_TEST_FILE="xdp_nodeport_lb4_nat_lb" 39 40 Writing tests 41 ============= 42 43 All BPF tests live in the ``bpf/tests`` directory. All ``.c`` files in this directory are assumed to 44 contain BPF test programs which can be independently compiled, loaded, and executed using 45 ``BPF_PROG_RUN``. All files in this directory are automatically picked up, so all you have to do is 46 create a new ``.c`` file and start writing. All other files like ``.h`` files are ignored and can be 47 used for sharing code for example. 48 49 Each ``.c`` file must at least have one ``CHECK`` program. The ``CHECK`` macro replaces the ``SEC`` which is 50 typically used in BPF programs. The ``CHECK`` macro takes two arguments, the first being the program 51 type (for example ``xdp`` or ``tc``. See `the list of recognized types in the Go library 52 <https://github.com/cilium/ebpf/blob/v0.13.2/elf_sections.go#L9>`__), 53 the second being the name of the test which will appear in the output. All macros are defined in 54 ``bpf/tests/common.h``, so all programs should start by including this file: ``#include "common.h"``. 55 56 Each ``CHECK`` program should start with ``test_init()`` and end with ``test_finish()``, ``CHECK`` programs 57 will return implicitly with the result of the test, a user doesn't need to add ``return`` statements 58 to the code manually. A test will PASS if it reaches ``test_finish()``, unless it is marked as 59 failed(``test_fail()``, ``test_fail_now()``, ``test_fatal()``) or skipped(``test_skip()``, ``test_skip_now()``). 60 61 The name of the function has no significance for the tests themselves. The function names are still 62 used as indicators in the kernel (at least the first 15 chars), used to populate tail call maps, 63 and should be unique for the purposes of compilation. 64 65 .. code-block:: c 66 67 #include "common.h" 68 69 CHECK("xdp", "nodeport-lb4") 70 int nodeportLB4(struct __ctx_buff *ctx) 71 { 72 test_init(); 73 74 /* ensure preconditions are met */ 75 /* call the functions you would like to test */ 76 /* check that everything works as expected */ 77 78 test_finish(); 79 } 80 81 Sub-tests 82 --------- 83 84 Each ``CHECK`` program may contain sub-tests, each of which has its own test status. A sub-test is 85 created with the ``TEST`` macro like so: 86 87 .. code-block:: c 88 89 #include "common.h" 90 91 #include <bpf/ctx/xdp.h> 92 #include <lib/jhash.h> 93 #include "bpf/section.h" 94 95 CHECK("xdp", "jhash") 96 int bpf_test(__maybe_unused struct xdp_md *ctx) 97 { 98 test_init(); 99 100 TEST("Non-zero", { 101 unsigned int hash = jhash_3words(123, 234, 345, 456); 102 103 if (hash != 2698615579) 104 test_fatal("expected '2698615579' got '%lu'", hash); 105 }); 106 107 TEST("Zero", { 108 unsigned int hash = jhash_3words(0, 0, 0, 0); 109 110 if (hash != 459859287) 111 test_fatal("expected '459859287' got '%lu'", hash); 112 }); 113 114 test_finish(); 115 } 116 117 Since all sub-tests are part of the same BPF program they are executed consecutively in one 118 ``BPF_PROG_RUN`` invocation and can share setup code which can improve run speed and reduce code duplication. 119 The name passed to the ``TEST`` macro for each sub-test serves to self-document the steps and makes it easier to spot what part of a test fails. 120 121 Integration tests 122 ----------------- 123 124 Writing tests for a single function or small group of functions should be fairly straightforward, 125 only requiring a ``CHECK`` program. Testing functionality across tail calls requires an additional step: 126 given that the program does not return to the ``CHECK`` function after making a tail call, we can't check whether it was successful. 127 128 The workaround is to use ``PKTGEN`` and ``SETUP`` programs in addition to a ``CHECK`` program. 129 These programs will run before the ``CHECK`` program with the same name. 130 Intended usage is that the ``PKGTEN`` program builds a BPF context (for example fill a ``struct __sk_buff`` for TC programs), and passes it on 131 to the ``SETUP`` program, which performs further setup steps (for example fill a BPF map). The two-stage pattern is needed so that ``BPF_PROG_RUN`` gets 132 invoked with the actual packet content (and for example fills ``skb->protocol``). 133 134 The BPF context is then passed to the ``CHECK`` program, which can inspect the result. By executing the test setup and executing the tail 135 call in ``SETUP`` we can execute complete programs. The return code of the ``SETUP`` program is prepended as a ``u32`` to the start of the 136 packet data passed to ``CHECK``, meaning that the ``CHECK`` program will find the actual packet data at ``(void *)data + 4``. 137 138 This is an abbreviated example showing the key components: 139 140 .. code-block:: c 141 142 #include "common.h" 143 144 #include "bpf/ctx/xdp.h" 145 #include "bpf_xdp.c" 146 147 struct { 148 __uint(type, BPF_MAP_TYPE_PROG_ARRAY); 149 __uint(key_size, sizeof(__u32)); 150 __uint(max_entries, 2); 151 __array(values, int()); 152 } entry_call_map __section(".maps") = { 153 .values = { 154 [0] = &cil_xdp_entry, 155 }, 156 }; 157 158 PKTGEN("xdp", "l2_example") 159 int test1_pktgen(struct __ctx_buff *ctx) 160 { 161 /* Create room for our packet to be crafted */ 162 unsigned int data_len = ctx->data_end - ctx->data; 163 int offset = offset = sizeof(struct ethhdr) - data_len; 164 bpf_xdp_adjust_tail(ctx, offset); 165 166 void *data = (void *)(long)ctx->data; 167 void *data_end = (void *)(long)ctx->data_end; 168 169 if (data + sizeof(struct ethhdr) > data_end) 170 return TEST_ERROR; 171 172 /* Writing just the L2 header for brevity */ 173 struct ethhdr l2 = { 174 .h_source = {0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF}, 175 .h_dest = {0x12, 0x23, 0x34, 0x45, 0x56, 0x67}, 176 .h_proto = bpf_htons(ETH_P_IP) 177 }; 178 memcpy(data, &l2, sizeof(struct ethhdr)); 179 180 return 0; 181 } 182 183 SETUP("xdp", "l2_example") 184 int test1_setup(struct __ctx_buff *ctx) 185 { 186 /* OMITTED setting up map state */ 187 188 /* Jump into the entrypoint */ 189 tail_call_static(ctx, entry_call_map, 0); 190 /* Fail if we didn't jump */ 191 return TEST_ERROR; 192 } 193 194 CHECK("xdp", "l2_example") 195 int test1_check(__maybe_unused const struct __ctx_buff *ctx) 196 { 197 test_init(); 198 199 void *data = (void *)(long)ctx->data; 200 void *data_end = (void *)(long)ctx->data_end; 201 202 if (data + sizeof(__u32) > data_end) 203 test_fatal("status code out of bounds"); 204 205 __u32 *status_code = data; 206 207 if (*status_code != XDP_TX) 208 test_fatal("status code != XDP_TX"); 209 210 data += sizeof(__u32); 211 212 if (data + sizeof(struct ethhdr) > data_end) 213 test_fatal("ctx doesn't fit ethhdr"); 214 215 struct ethhdr *l2 = data; 216 217 data += sizeof(struct ethhdr); 218 219 if (memcmp(l2->h_source, fib_smac, sizeof(fib_smac))) 220 test_fatal("l2->h_source != fib_smac"); 221 222 if (memcmp(l2->h_dest, fib_dmac, sizeof(fib_dmac))) 223 test_fatal("l2->h_dest != fib_dmac"); 224 225 if (data + sizeof(struct iphdr) > data_end) 226 test_fatal("ctx doesn't fit iphdr"); 227 228 test_finish(); 229 } 230 231 Function reference 232 ------------------ 233 234 * ``test_log(fmt, args...)`` - writes a log message. The conversion specifiers supported by *fmt* are the same as for 235 ``bpf_trace_printk()``. They are **%d**, **%i**, **%u**, **%x**, **%ld**, **%li**, **%lu**, **%lx**, **%lld**, **%lli**, 236 **%llu**, **%llx**. No modifier (size of field, padding with zeroes, etc.) is available. 237 238 * ``test_fail()`` - marks the current test or sub-test as failed but will continue execution. 239 240 * ``test_fail_now()`` - marks the current test or sub-test as failed and will stop execution of the 241 test or sub-test (If called in a sub-test, the other sub-tests will still run). 242 243 * ``test_fatal(fmt, args...)`` - writes a log and then calls ``test_fail_now()`` 244 245 * ``assert(stmt)`` - asserts that the statement within is true and call ``test_fail_now()`` otherwise. 246 ``assert`` will log the file and line number of the assert statement. 247 248 * ``test_skip()`` - marks the current test or sub-test as skipped but will continue execution. 249 250 * ``test_skip_now()`` - marks the current test or sub-test as skipped and will stop execution of the 251 test or sub-test (If called in a sub-test, the other sub-tests will still run). 252 253 * ``test_init()`` - initializes the internal state for the test and must be called before any of the 254 functions above can be called. 255 256 * ``test_finish()`` - submits the results and returns from the current function. 257 258 .. warning:: 259 Functions that halt the execution (``test_fail_now()``, ``test_fatal()``, ``test_skip_now()``) can't be 260 used within both a sub-test (``TEST``) and ``for``, ``while``, or ``switch/case`` blocks since they use the ``break`` keyword to stop a 261 sub-test. These functions can still be used from within ``for``, ``while`` and ``switch/case`` blocks if no 262 sub-tests are used, because in that case the flow interruption happens via ``return``. 263 264 Function mocking 265 ---------------- 266 267 Being able to mock out a function is a great tool to have when creating tests for a number of 268 reasons. You might for example want to test what happens if a specific function returns an error 269 to see if it is handled gracefully. You might want to proxy function calls to record if the function 270 under test actually called specific dependencies. Or you might want to test code that uses helpers 271 which rely on a state we can't set in BPF, like the routing table. 272 273 Mocking is easy with this framework: 274 275 1. Create a function with a unique name and the same signature as the function it is replacing. 276 277 2. Create a macro with the exact same name as the function we want to replace and point it to the 278 function created in step 1. For example ``#define original_function our_mocked_function``` 279 280 3. Include the file which contains the definition we are replacing. 281 282 The following example mocks out the fib_lookup helper call and replaces it with our 283 mocked version, since we don't actually have routes for the IPs we want to test: 284 285 .. code-block:: c 286 287 #include "common.h" 288 289 #include "bpf/ctx/xdp.h" 290 291 #define fib_lookup mock_fib_lookup 292 293 static const char fib_smac[6] = {0xDE, 0xAD, 0xBE, 0xEF, 0x01, 0x02}; 294 static const char fib_dmac[6] = {0x13, 0x37, 0x13, 0x37, 0x13, 0x37}; 295 296 long mock_fib_lookup(__maybe_unused void *ctx, struct bpf_fib_lookup *params, 297 __maybe_unused int plen, __maybe_unused __u32 flags) 298 { 299 memcpy(params->smac, fib_smac, sizeof(fib_smac)); 300 memcpy(params->dmac, fib_dmac, sizeof(fib_dmac)); 301 return 0; 302 } 303 304 #include "bpf_xdp.c" 305 #include "lib/nodeport.h" 306 307 Limitations 308 ----------- 309 310 For all its benefits there are some limitations to this way of testing: 311 312 * Code must pass the verifier, so our setup and test code has to obey the same rules as other BPF 313 programs. A side effect is that it automatically guarantees that all code that passes will also 314 load. The biggest concern is the complexity limit on older kernels, this can be somewhat mitigated 315 by separating heavy setup work into its own ``SETUP`` program and optionally tail calling into the 316 code to be tested, to ensure the testing harness doesn't push us over the complexity limit. 317 318 * Test functions like ``test_log()``, ``test_fail()``, ``test_skip()`` can only be executed within the 319 scope of the main program or a ``TEST``. These functions rely on local variables set by ``test_init()`` 320 and will produce errors when used in other functions. 321 322 * Functions that halt the execution (``test_fail_now()``, ``test_fatal()``, ``test_skip_now()``) can't be 323 used within both a sub-test (``TEST``) and ``for``, ``while``, or ``switch/case`` blocks since they use the ``break`` keyword to stop a 324 sub-test. These functions can still be used from within ``for``, ``while`` and ``switch/case`` blocks if no 325 sub-tests are used, because in that case the flow interruption happens via ``return``. 326 327 * Sub-test names can't use more than 127 characters. 328 329 * Log messages can't use more than 127 characters and have no more than 12 arguments.