linux/tools/testing/selftests/bpf/progs/netif_receive_skb.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/* Copyright (c) 2020, Oracle and/or its affiliates. */
   3
   4#include "btf_ptr.h"
   5#include <bpf/bpf_helpers.h>
   6#include <bpf/bpf_tracing.h>
   7#include <bpf/bpf_core_read.h>
   8
   9#include <errno.h>
  10
  11long ret = 0;
  12int num_subtests = 0;
  13int ran_subtests = 0;
  14bool skip = false;
  15
  16#define STRSIZE                 2048
  17#define EXPECTED_STRSIZE        256
  18
  19#if defined(bpf_target_s390)
  20/* NULL points to a readable struct lowcore on s390, so take the last page */
  21#define BADPTR                  ((void *)0xFFFFFFFFFFFFF000ULL)
  22#else
  23#define BADPTR                  0
  24#endif
  25
  26#ifndef ARRAY_SIZE
  27#define ARRAY_SIZE(x)   (sizeof(x) / sizeof((x)[0]))
  28#endif
  29
  30struct {
  31        __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
  32        __uint(max_entries, 1);
  33        __type(key, __u32);
  34        __type(value, char[STRSIZE]);
  35} strdata SEC(".maps");
  36
  37static int __strncmp(const void *m1, const void *m2, size_t len)
  38{
  39        const unsigned char *s1 = m1;
  40        const unsigned char *s2 = m2;
  41        int i, delta = 0;
  42
  43        for (i = 0; i < len; i++) {
  44                delta = s1[i] - s2[i];
  45                if (delta || s1[i] == 0 || s2[i] == 0)
  46                        break;
  47        }
  48        return delta;
  49}
  50
  51#if __has_builtin(__builtin_btf_type_id)
  52#define TEST_BTF(_str, _type, _flags, _expected, ...)                   \
  53        do {                                                            \
  54                static const char _expectedval[EXPECTED_STRSIZE] =      \
  55                                                        _expected;      \
  56                static const char _ptrtype[64] = #_type;                \
  57                __u64 _hflags = _flags | BTF_F_COMPACT;                 \
  58                static _type _ptrdata = __VA_ARGS__;                    \
  59                static struct btf_ptr _ptr = { };                       \
  60                int _cmp;                                               \
  61                                                                        \
  62                ++num_subtests;                                         \
  63                if (ret < 0)                                            \
  64                        break;                                          \
  65                ++ran_subtests;                                         \
  66                _ptr.ptr = &_ptrdata;                                   \
  67                _ptr.type_id = bpf_core_type_id_kernel(_type);          \
  68                if (_ptr.type_id <= 0) {                                \
  69                        ret = -EINVAL;                                  \
  70                        break;                                          \
  71                }                                                       \
  72                ret = bpf_snprintf_btf(_str, STRSIZE,                   \
  73                                       &_ptr, sizeof(_ptr), _hflags);   \
  74                if (ret)                                                \
  75                        break;                                          \
  76                _cmp = __strncmp(_str, _expectedval, EXPECTED_STRSIZE); \
  77                if (_cmp != 0) {                                        \
  78                        bpf_printk("(%d) got %s", _cmp, _str);          \
  79                        bpf_printk("(%d) expected %s", _cmp,            \
  80                                   _expectedval);                       \
  81                        ret = -EBADMSG;                                 \
  82                        break;                                          \
  83                }                                                       \
  84        } while (0)
  85#endif
  86
  87/* Use where expected data string matches its stringified declaration */
  88#define TEST_BTF_C(_str, _type, _flags, ...)                            \
  89        TEST_BTF(_str, _type, _flags, "(" #_type ")" #__VA_ARGS__,      \
  90                 __VA_ARGS__)
  91
  92/* TRACE_EVENT(netif_receive_skb,
  93 *      TP_PROTO(struct sk_buff *skb),
  94 */
  95SEC("tp_btf/netif_receive_skb")
  96int BPF_PROG(trace_netif_receive_skb, struct sk_buff *skb)
  97{
  98        static __u64 flags[] = { 0, BTF_F_COMPACT, BTF_F_ZERO, BTF_F_PTR_RAW,
  99                                 BTF_F_NONAME, BTF_F_COMPACT | BTF_F_ZERO |
 100                                 BTF_F_PTR_RAW | BTF_F_NONAME };
 101        static struct btf_ptr p = { };
 102        __u32 key = 0;
 103        int i, __ret;
 104        char *str;
 105
 106#if __has_builtin(__builtin_btf_type_id)
 107        str = bpf_map_lookup_elem(&strdata, &key);
 108        if (!str)
 109                return 0;
 110
 111        /* Ensure we can write skb string representation */
 112        p.type_id = bpf_core_type_id_kernel(struct sk_buff);
 113        p.ptr = skb;
 114        for (i = 0; i < ARRAY_SIZE(flags); i++) {
 115                ++num_subtests;
 116                ret = bpf_snprintf_btf(str, STRSIZE, &p, sizeof(p), 0);
 117                if (ret < 0)
 118                        bpf_printk("returned %d when writing skb", ret);
 119                ++ran_subtests;
 120        }
 121
 122        /* Check invalid ptr value */
 123        p.ptr = BADPTR;
 124        __ret = bpf_snprintf_btf(str, STRSIZE, &p, sizeof(p), 0);
 125        if (__ret >= 0) {
 126                bpf_printk("printing %llx should generate error, got (%d)",
 127                           (unsigned long long)BADPTR, __ret);
 128                ret = -ERANGE;
 129        }
 130
 131        /* Verify type display for various types. */
 132
 133        /* simple int */
 134        TEST_BTF_C(str, int, 0, 1234);
 135        TEST_BTF(str, int, BTF_F_NONAME, "1234", 1234);
 136        /* zero value should be printed at toplevel */
 137        TEST_BTF(str, int, 0, "(int)0", 0);
 138        TEST_BTF(str, int, BTF_F_NONAME, "0", 0);
 139        TEST_BTF(str, int, BTF_F_ZERO, "(int)0", 0);
 140        TEST_BTF(str, int, BTF_F_NONAME | BTF_F_ZERO, "0", 0);
 141        TEST_BTF_C(str, int, 0, -4567);
 142        TEST_BTF(str, int, BTF_F_NONAME, "-4567", -4567);
 143
 144        /* simple char */
 145        TEST_BTF_C(str, char, 0, 100);
 146        TEST_BTF(str, char, BTF_F_NONAME, "100", 100);
 147        /* zero value should be printed at toplevel */
 148        TEST_BTF(str, char, 0, "(char)0", 0);
 149        TEST_BTF(str, char, BTF_F_NONAME, "0", 0);
 150        TEST_BTF(str, char, BTF_F_ZERO, "(char)0", 0);
 151        TEST_BTF(str, char, BTF_F_NONAME | BTF_F_ZERO, "0", 0);
 152
 153        /* simple typedef */
 154        TEST_BTF_C(str, uint64_t, 0, 100);
 155        TEST_BTF(str, u64, BTF_F_NONAME, "1", 1);
 156        /* zero value should be printed at toplevel */
 157        TEST_BTF(str, u64, 0, "(u64)0", 0);
 158        TEST_BTF(str, u64, BTF_F_NONAME, "0", 0);
 159        TEST_BTF(str, u64, BTF_F_ZERO, "(u64)0", 0);
 160        TEST_BTF(str, u64, BTF_F_NONAME|BTF_F_ZERO, "0", 0);
 161
 162        /* typedef struct */
 163        TEST_BTF_C(str, atomic_t, 0, {.counter = (int)1,});
 164        TEST_BTF(str, atomic_t, BTF_F_NONAME, "{1,}", {.counter = 1,});
 165        /* typedef with 0 value should be printed at toplevel */
 166        TEST_BTF(str, atomic_t, 0, "(atomic_t){}", {.counter = 0,});
 167        TEST_BTF(str, atomic_t, BTF_F_NONAME, "{}", {.counter = 0,});
 168        TEST_BTF(str, atomic_t, BTF_F_ZERO, "(atomic_t){.counter = (int)0,}",
 169                 {.counter = 0,});
 170        TEST_BTF(str, atomic_t, BTF_F_NONAME|BTF_F_ZERO,
 171                 "{0,}", {.counter = 0,});
 172
 173        /* enum where enum value does (and does not) exist */
 174        TEST_BTF_C(str, enum bpf_cmd, 0, BPF_MAP_CREATE);
 175        TEST_BTF(str, enum bpf_cmd, 0, "(enum bpf_cmd)BPF_MAP_CREATE", 0);
 176        TEST_BTF(str, enum bpf_cmd, BTF_F_NONAME, "BPF_MAP_CREATE",
 177                 BPF_MAP_CREATE);
 178        TEST_BTF(str, enum bpf_cmd, BTF_F_NONAME|BTF_F_ZERO,
 179                 "BPF_MAP_CREATE", 0);
 180
 181        TEST_BTF(str, enum bpf_cmd, BTF_F_ZERO, "(enum bpf_cmd)BPF_MAP_CREATE",
 182                 BPF_MAP_CREATE);
 183        TEST_BTF(str, enum bpf_cmd, BTF_F_NONAME|BTF_F_ZERO,
 184                 "BPF_MAP_CREATE", BPF_MAP_CREATE);
 185        TEST_BTF_C(str, enum bpf_cmd, 0, 2000);
 186        TEST_BTF(str, enum bpf_cmd, BTF_F_NONAME, "2000", 2000);
 187
 188        /* simple struct */
 189        TEST_BTF_C(str, struct btf_enum, 0,
 190                   {.name_off = (__u32)3,.val = (__s32)-1,});
 191        TEST_BTF(str, struct btf_enum, BTF_F_NONAME, "{3,-1,}",
 192                 { .name_off = 3, .val = -1,});
 193        TEST_BTF(str, struct btf_enum, BTF_F_NONAME, "{-1,}",
 194                 { .name_off = 0, .val = -1,});
 195        TEST_BTF(str, struct btf_enum, BTF_F_NONAME|BTF_F_ZERO, "{0,-1,}",
 196                 { .name_off = 0, .val = -1,});
 197        /* empty struct should be printed */
 198        TEST_BTF(str, struct btf_enum, 0, "(struct btf_enum){}",
 199                 { .name_off = 0, .val = 0,});
 200        TEST_BTF(str, struct btf_enum, BTF_F_NONAME, "{}",
 201                 { .name_off = 0, .val = 0,});
 202        TEST_BTF(str, struct btf_enum, BTF_F_ZERO,
 203                 "(struct btf_enum){.name_off = (__u32)0,.val = (__s32)0,}",
 204                 { .name_off = 0, .val = 0,});
 205
 206        /* struct with pointers */
 207        TEST_BTF(str, struct list_head, BTF_F_PTR_RAW,
 208                 "(struct list_head){.next = (struct list_head *)0x0000000000000001,}",
 209                 { .next = (struct list_head *)1 });
 210        /* NULL pointer should not be displayed */
 211        TEST_BTF(str, struct list_head, BTF_F_PTR_RAW,
 212                 "(struct list_head){}",
 213                 { .next = (struct list_head *)0 });
 214
 215        /* struct with char array */
 216        TEST_BTF(str, struct bpf_prog_info, 0,
 217                 "(struct bpf_prog_info){.name = (char[])['f','o','o',],}",
 218                 { .name = "foo",});
 219        TEST_BTF(str, struct bpf_prog_info, BTF_F_NONAME,
 220                 "{['f','o','o',],}",
 221                 {.name = "foo",});
 222        /* leading null char means do not display string */
 223        TEST_BTF(str, struct bpf_prog_info, 0,
 224                 "(struct bpf_prog_info){}",
 225                 {.name = {'\0', 'f', 'o', 'o'}});
 226        /* handle non-printable characters */
 227        TEST_BTF(str, struct bpf_prog_info, 0,
 228                 "(struct bpf_prog_info){.name = (char[])[1,2,3,],}",
 229                 { .name = {1, 2, 3, 0}});
 230
 231        /* struct with non-char array */
 232        TEST_BTF(str, struct __sk_buff, 0,
 233                 "(struct __sk_buff){.cb = (__u32[])[1,2,3,4,5,],}",
 234                 { .cb = {1, 2, 3, 4, 5,},});
 235        TEST_BTF(str, struct __sk_buff, BTF_F_NONAME,
 236                 "{[1,2,3,4,5,],}",
 237                 { .cb = { 1, 2, 3, 4, 5},});
 238        /* For non-char, arrays, show non-zero values only */
 239        TEST_BTF(str, struct __sk_buff, 0,
 240                 "(struct __sk_buff){.cb = (__u32[])[1,],}",
 241                 { .cb = { 0, 0, 1, 0, 0},});
 242
 243        /* struct with bitfields */
 244        TEST_BTF_C(str, struct bpf_insn, 0,
 245                   {.code = (__u8)1,.dst_reg = (__u8)0x2,.src_reg = (__u8)0x3,.off = (__s16)4,.imm = (__s32)5,});
 246        TEST_BTF(str, struct bpf_insn, BTF_F_NONAME, "{1,0x2,0x3,4,5,}",
 247                 {.code = 1, .dst_reg = 0x2, .src_reg = 0x3, .off = 4,
 248                  .imm = 5,});
 249#else
 250        skip = true;
 251#endif
 252
 253        return 0;
 254}
 255
 256char _license[] SEC("license") = "GPL";
 257