1 // SPDX-License-Identifier: GPL-2.0
5 #include <linux/perf_event.h>
10 #include <sys/sysinfo.h>
11 #include <sys/ioctl.h>
17 #include "trace_helpers.h"
20 static int pmu_fds
[MAX_CPUS
], if_idx
;
21 static struct perf_event_mmap_page
*headers
[MAX_CPUS
];
24 static int do_attach(int idx
, int fd
, const char *name
)
28 err
= bpf_set_link_xdp_fd(idx
, fd
, 0);
30 printf("ERROR: failed to attach program to %s\n", name
);
35 static int do_detach(int idx
, const char *name
)
39 err
= bpf_set_link_xdp_fd(idx
, -1, 0);
41 printf("ERROR: failed to detach program from %s\n", name
);
46 #define SAMPLE_SIZE 64
48 static int print_bpf_output(void *data
, int size
)
53 __u8 pkt_data
[SAMPLE_SIZE
];
57 if (e
->cookie
!= 0xdead) {
58 printf("BUG cookie %x sized %d\n",
60 return LIBBPF_PERF_EVENT_ERROR
;
63 printf("Pkt len: %-5d bytes. Ethernet hdr: ", e
->pkt_len
);
64 for (i
= 0; i
< 14 && i
< e
->pkt_len
; i
++)
65 printf("%02x ", e
->pkt_data
[i
]);
68 return LIBBPF_PERF_EVENT_CONT
;
71 static void test_bpf_perf_event(int map_fd
, int num
)
73 struct perf_event_attr attr
= {
74 .sample_type
= PERF_SAMPLE_RAW
,
75 .type
= PERF_TYPE_SOFTWARE
,
76 .config
= PERF_COUNT_SW_BPF_OUTPUT
,
77 .wakeup_events
= 1, /* get an fd notification for every event */
81 for (i
= 0; i
< num
; i
++) {
84 pmu_fds
[i
] = sys_perf_event_open(&attr
, -1/*pid*/, i
/*cpu*/,
87 assert(pmu_fds
[i
] >= 0);
88 assert(bpf_map_update_elem(map_fd
, &key
,
89 &pmu_fds
[i
], BPF_ANY
) == 0);
90 ioctl(pmu_fds
[i
], PERF_EVENT_IOC_ENABLE
, 0);
94 static void sig_handler(int signo
)
96 do_detach(if_idx
, if_name
);
100 int main(int argc
, char **argv
)
102 struct bpf_prog_load_attr prog_load_attr
= {
103 .prog_type
= BPF_PROG_TYPE_XDP
,
105 struct bpf_object
*obj
;
113 printf("Usage: %s <ifname>\n", argv
[0]);
117 numcpus
= get_nprocs();
118 if (numcpus
> MAX_CPUS
)
121 snprintf(filename
, sizeof(filename
), "%s_kern.o", argv
[0]);
122 prog_load_attr
.file
= filename
;
124 if (bpf_prog_load_xattr(&prog_load_attr
, &obj
, &prog_fd
))
128 printf("load_bpf_file: %s\n", strerror(errno
));
132 map
= bpf_map__next(NULL
, obj
);
134 printf("finding a map in obj file failed\n");
137 map_fd
= bpf_map__fd(map
);
139 if_idx
= if_nametoindex(argv
[1]);
141 if_idx
= strtoul(argv
[1], NULL
, 0);
144 fprintf(stderr
, "Invalid ifname\n");
148 err
= do_attach(if_idx
, prog_fd
, argv
[1]);
152 if (signal(SIGINT
, sig_handler
) ||
153 signal(SIGHUP
, sig_handler
) ||
154 signal(SIGTERM
, sig_handler
)) {
159 test_bpf_perf_event(map_fd
, numcpus
);
161 for (i
= 0; i
< numcpus
; i
++)
162 if (perf_event_mmap_header(pmu_fds
[i
], &headers
[i
]) < 0)
165 ret
= perf_event_poller_multi(pmu_fds
, headers
, numcpus
,