~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/samples/bpf/trace_output_user.c

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /samples/bpf/trace_output_user.c (Version linux-6.12-rc7) and /samples/bpf/trace_output_user.c (Version linux-4.14.336)


  1 // SPDX-License-Identifier: GPL-2.0-only       !!   1 /* This program is free software; you can redistribute it and/or
                                                   >>   2  * modify it under the terms of version 2 of the GNU General Public
                                                   >>   3  * License as published by the Free Software Foundation.
                                                   >>   4  */
  2 #include <stdio.h>                                  5 #include <stdio.h>
                                                   >>   6 #include <unistd.h>
                                                   >>   7 #include <stdlib.h>
                                                   >>   8 #include <stdbool.h>
                                                   >>   9 #include <string.h>
  3 #include <fcntl.h>                                 10 #include <fcntl.h>
  4 #include <poll.h>                                  11 #include <poll.h>
                                                   >>  12 #include <linux/perf_event.h>
                                                   >>  13 #include <linux/bpf.h>
                                                   >>  14 #include <errno.h>
                                                   >>  15 #include <assert.h>
                                                   >>  16 #include <sys/syscall.h>
                                                   >>  17 #include <sys/ioctl.h>
                                                   >>  18 #include <sys/mman.h>
  5 #include <time.h>                                  19 #include <time.h>
  6 #include <signal.h>                                20 #include <signal.h>
  7 #include <bpf/libbpf.h>                        !!  21 #include "libbpf.h"
                                                   >>  22 #include "bpf_load.h"
                                                   >>  23 #include "perf-sys.h"
                                                   >>  24 
                                                   >>  25 static int pmu_fd;
                                                   >>  26 
                                                   >>  27 int page_size;
                                                   >>  28 int page_cnt = 8;
                                                   >>  29 volatile struct perf_event_mmap_page *header;
                                                   >>  30 
                                                   >>  31 typedef void (*print_fn)(void *data, int size);
                                                   >>  32 
                                                   >>  33 static int perf_event_mmap(int fd)
                                                   >>  34 {
                                                   >>  35         void *base;
                                                   >>  36         int mmap_size;
                                                   >>  37 
                                                   >>  38         page_size = getpagesize();
                                                   >>  39         mmap_size = page_size * (page_cnt + 1);
                                                   >>  40 
                                                   >>  41         base = mmap(NULL, mmap_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
                                                   >>  42         if (base == MAP_FAILED) {
                                                   >>  43                 printf("mmap err\n");
                                                   >>  44                 return -1;
                                                   >>  45         }
                                                   >>  46 
                                                   >>  47         header = base;
                                                   >>  48         return 0;
                                                   >>  49 }
                                                   >>  50 
                                                   >>  51 static int perf_event_poll(int fd)
                                                   >>  52 {
                                                   >>  53         struct pollfd pfd = { .fd = fd, .events = POLLIN };
                                                   >>  54 
                                                   >>  55         return poll(&pfd, 1, 1000);
                                                   >>  56 }
                                                   >>  57 
                                                   >>  58 struct perf_event_sample {
                                                   >>  59         struct perf_event_header header;
                                                   >>  60         __u32 size;
                                                   >>  61         char data[];
                                                   >>  62 };
                                                   >>  63 
                                                   >>  64 static void perf_event_read(print_fn fn)
                                                   >>  65 {
                                                   >>  66         __u64 data_tail = header->data_tail;
                                                   >>  67         __u64 data_head = header->data_head;
                                                   >>  68         __u64 buffer_size = page_cnt * page_size;
                                                   >>  69         void *base, *begin, *end;
                                                   >>  70         char buf[256];
                                                   >>  71 
                                                   >>  72         asm volatile("" ::: "memory"); /* in real code it should be smp_rmb() */
                                                   >>  73         if (data_head == data_tail)
                                                   >>  74                 return;
                                                   >>  75 
                                                   >>  76         base = ((char *)header) + page_size;
                                                   >>  77 
                                                   >>  78         begin = base + data_tail % buffer_size;
                                                   >>  79         end = base + data_head % buffer_size;
                                                   >>  80 
                                                   >>  81         while (begin != end) {
                                                   >>  82                 struct perf_event_sample *e;
                                                   >>  83 
                                                   >>  84                 e = begin;
                                                   >>  85                 if (begin + e->header.size > base + buffer_size) {
                                                   >>  86                         long len = base + buffer_size - begin;
                                                   >>  87 
                                                   >>  88                         assert(len < e->header.size);
                                                   >>  89                         memcpy(buf, begin, len);
                                                   >>  90                         memcpy(buf + len, base, e->header.size - len);
                                                   >>  91                         e = (void *) buf;
                                                   >>  92                         begin = base + e->header.size - len;
                                                   >>  93                 } else if (begin + e->header.size == base + buffer_size) {
                                                   >>  94                         begin = base;
                                                   >>  95                 } else {
                                                   >>  96                         begin += e->header.size;
                                                   >>  97                 }
                                                   >>  98 
                                                   >>  99                 if (e->header.type == PERF_RECORD_SAMPLE) {
                                                   >> 100                         fn(e->data, e->size);
                                                   >> 101                 } else if (e->header.type == PERF_RECORD_LOST) {
                                                   >> 102                         struct {
                                                   >> 103                                 struct perf_event_header header;
                                                   >> 104                                 __u64 id;
                                                   >> 105                                 __u64 lost;
                                                   >> 106                         } *lost = (void *) e;
                                                   >> 107                         printf("lost %lld events\n", lost->lost);
                                                   >> 108                 } else {
                                                   >> 109                         printf("unknown event type=%d size=%d\n",
                                                   >> 110                                e->header.type, e->header.size);
                                                   >> 111                 }
                                                   >> 112         }
                                                   >> 113 
                                                   >> 114         __sync_synchronize(); /* smp_mb() */
                                                   >> 115         header->data_tail = data_head;
                                                   >> 116 }
  8                                                   117 
  9 static __u64 time_get_ns(void)                    118 static __u64 time_get_ns(void)
 10 {                                                 119 {
 11         struct timespec ts;                       120         struct timespec ts;
 12                                                   121 
 13         clock_gettime(CLOCK_MONOTONIC, &ts);      122         clock_gettime(CLOCK_MONOTONIC, &ts);
 14         return ts.tv_sec * 1000000000ull + ts.    123         return ts.tv_sec * 1000000000ull + ts.tv_nsec;
 15 }                                                 124 }
 16                                                   125 
 17 static __u64 start_time;                          126 static __u64 start_time;
 18 static __u64 cnt;                              << 
 19                                                   127 
 20 #define MAX_CNT 100000ll                          128 #define MAX_CNT 100000ll
 21                                                   129 
 22 static void print_bpf_output(void *ctx, int cp !! 130 static void print_bpf_output(void *data, int size)
 23 {                                                 131 {
                                                   >> 132         static __u64 cnt;
 24         struct {                                  133         struct {
 25                 __u64 pid;                        134                 __u64 pid;
 26                 __u64 cookie;                     135                 __u64 cookie;
 27         } *e = data;                              136         } *e = data;
 28                                                   137 
 29         if (e->cookie != 0x12345678) {            138         if (e->cookie != 0x12345678) {
 30                 printf("BUG pid %llx cookie %l    139                 printf("BUG pid %llx cookie %llx sized %d\n",
 31                        e->pid, e->cookie, size    140                        e->pid, e->cookie, size);
 32                 return;                        !! 141                 kill(0, SIGINT);
 33         }                                         142         }
 34                                                   143 
 35         cnt++;                                    144         cnt++;
 36                                                   145 
 37         if (cnt == MAX_CNT) {                     146         if (cnt == MAX_CNT) {
 38                 printf("recv %lld events per s    147                 printf("recv %lld events per sec\n",
 39                        MAX_CNT * 1000000000ll     148                        MAX_CNT * 1000000000ll / (time_get_ns() - start_time));
 40                 return;                        !! 149                 kill(0, SIGINT);
 41         }                                         150         }
 42 }                                                 151 }
 43                                                   152 
                                                   >> 153 static void test_bpf_perf_event(void)
                                                   >> 154 {
                                                   >> 155         struct perf_event_attr attr = {
                                                   >> 156                 .sample_type = PERF_SAMPLE_RAW,
                                                   >> 157                 .type = PERF_TYPE_SOFTWARE,
                                                   >> 158                 .config = PERF_COUNT_SW_BPF_OUTPUT,
                                                   >> 159         };
                                                   >> 160         int key = 0;
                                                   >> 161 
                                                   >> 162         pmu_fd = sys_perf_event_open(&attr, -1/*pid*/, 0/*cpu*/, -1/*group_fd*/, 0);
                                                   >> 163 
                                                   >> 164         assert(pmu_fd >= 0);
                                                   >> 165         assert(bpf_map_update_elem(map_fd[0], &key, &pmu_fd, BPF_ANY) == 0);
                                                   >> 166         ioctl(pmu_fd, PERF_EVENT_IOC_ENABLE, 0);
                                                   >> 167 }
                                                   >> 168 
 44 int main(int argc, char **argv)                   169 int main(int argc, char **argv)
 45 {                                                 170 {
 46         struct bpf_link *link = NULL;          << 
 47         struct bpf_program *prog;              << 
 48         struct perf_buffer *pb;                << 
 49         struct bpf_object *obj;                << 
 50         int map_fd, ret = 0;                   << 
 51         char filename[256];                       171         char filename[256];
 52         FILE *f;                                  172         FILE *f;
 53                                                   173 
 54         snprintf(filename, sizeof(filename), " !! 174         snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
 55         obj = bpf_object__open_file(filename,  << 
 56         if (libbpf_get_error(obj)) {           << 
 57                 fprintf(stderr, "ERROR: openin << 
 58                 return 0;                      << 
 59         }                                      << 
 60                                                   175 
 61         /* load BPF program */                 !! 176         if (load_bpf_file(filename)) {
 62         if (bpf_object__load(obj)) {           !! 177                 printf("%s", bpf_log_buf);
 63                 fprintf(stderr, "ERROR: loadin !! 178                 return 1;
 64                 goto cleanup;                  << 
 65         }                                      << 
 66                                                << 
 67         map_fd = bpf_object__find_map_fd_by_na << 
 68         if (map_fd < 0) {                      << 
 69                 fprintf(stderr, "ERROR: findin << 
 70                 goto cleanup;                  << 
 71         }                                      << 
 72                                                << 
 73         prog = bpf_object__find_program_by_nam << 
 74         if (libbpf_get_error(prog)) {          << 
 75                 fprintf(stderr, "ERROR: findin << 
 76                 goto cleanup;                  << 
 77         }                                         179         }
 78                                                   180 
 79         link = bpf_program__attach(prog);      !! 181         test_bpf_perf_event();
 80         if (libbpf_get_error(link)) {          << 
 81                 fprintf(stderr, "ERROR: bpf_pr << 
 82                 link = NULL;                   << 
 83                 goto cleanup;                  << 
 84         }                                      << 
 85                                                   182 
 86         pb = perf_buffer__new(map_fd, 8, print !! 183         if (perf_event_mmap(pmu_fd) < 0)
 87         ret = libbpf_get_error(pb);            << 
 88         if (ret) {                             << 
 89                 printf("failed to setup perf_b << 
 90                 return 1;                         184                 return 1;
 91         }                                      << 
 92                                                   185 
 93         f = popen("taskset 1 dd if=/dev/zero o    186         f = popen("taskset 1 dd if=/dev/zero of=/dev/null", "r");
 94         (void) f;                                 187         (void) f;
 95                                                   188 
 96         start_time = time_get_ns();               189         start_time = time_get_ns();
 97         while ((ret = perf_buffer__poll(pb, 10 !! 190         for (;;) {
                                                   >> 191                 perf_event_poll(pmu_fd);
                                                   >> 192                 perf_event_read(print_bpf_output);
 98         }                                         193         }
 99         kill(0, SIGINT);                       << 
100                                                   194 
101 cleanup:                                       !! 195         return 0;
102         bpf_link__destroy(link);               << 
103         bpf_object__close(obj);                << 
104         return ret;                            << 
105 }                                                 196 }
106                                                   197 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php