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