Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v5.13-rc3 196 lines 4.1 kB view raw
1// SPDX-License-Identifier: GPL-2.0 2#include <stdio.h> 3#include <stdlib.h> 4#include <string.h> 5#include <linux/perf_event.h> 6#include <linux/bpf.h> 7#include <net/if.h> 8#include <errno.h> 9#include <assert.h> 10#include <sys/sysinfo.h> 11#include <sys/ioctl.h> 12#include <signal.h> 13#include <bpf/libbpf.h> 14#include <bpf/bpf.h> 15#include <sys/resource.h> 16#include <libgen.h> 17#include <linux/if_link.h> 18 19#include "perf-sys.h" 20 21static int if_idx; 22static char *if_name; 23static __u32 xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST; 24static __u32 prog_id; 25static struct perf_buffer *pb = NULL; 26 27static int do_attach(int idx, int fd, const char *name) 28{ 29 struct bpf_prog_info info = {}; 30 __u32 info_len = sizeof(info); 31 int err; 32 33 err = bpf_set_link_xdp_fd(idx, fd, xdp_flags); 34 if (err < 0) { 35 printf("ERROR: failed to attach program to %s\n", name); 36 return err; 37 } 38 39 err = bpf_obj_get_info_by_fd(fd, &info, &info_len); 40 if (err) { 41 printf("can't get prog info - %s\n", strerror(errno)); 42 return err; 43 } 44 prog_id = info.id; 45 46 return err; 47} 48 49static int do_detach(int idx, const char *name) 50{ 51 __u32 curr_prog_id = 0; 52 int err = 0; 53 54 err = bpf_get_link_xdp_id(idx, &curr_prog_id, xdp_flags); 55 if (err) { 56 printf("bpf_get_link_xdp_id failed\n"); 57 return err; 58 } 59 if (prog_id == curr_prog_id) { 60 err = bpf_set_link_xdp_fd(idx, -1, xdp_flags); 61 if (err < 0) 62 printf("ERROR: failed to detach prog from %s\n", name); 63 } else if (!curr_prog_id) { 64 printf("couldn't find a prog id on a %s\n", name); 65 } else { 66 printf("program on interface changed, not removing\n"); 67 } 68 69 return err; 70} 71 72#define SAMPLE_SIZE 64 73 74static void print_bpf_output(void *ctx, int cpu, void *data, __u32 size) 75{ 76 struct { 77 __u16 cookie; 78 __u16 pkt_len; 79 __u8 pkt_data[SAMPLE_SIZE]; 80 } __packed *e = data; 81 int i; 82 83 if (e->cookie != 0xdead) { 84 printf("BUG cookie %x sized %d\n", e->cookie, size); 85 return; 86 } 87 88 printf("Pkt len: %-5d bytes. Ethernet hdr: ", e->pkt_len); 89 for (i = 0; i < 14 && i < e->pkt_len; i++) 90 printf("%02x ", e->pkt_data[i]); 91 printf("\n"); 92} 93 94static void sig_handler(int signo) 95{ 96 do_detach(if_idx, if_name); 97 perf_buffer__free(pb); 98 exit(0); 99} 100 101static void usage(const char *prog) 102{ 103 fprintf(stderr, 104 "%s: %s [OPTS] <ifname|ifindex>\n\n" 105 "OPTS:\n" 106 " -F force loading prog\n", 107 __func__, prog); 108} 109 110int main(int argc, char **argv) 111{ 112 struct bpf_prog_load_attr prog_load_attr = { 113 .prog_type = BPF_PROG_TYPE_XDP, 114 }; 115 struct perf_buffer_opts pb_opts = {}; 116 const char *optstr = "FS"; 117 int prog_fd, map_fd, opt; 118 struct bpf_object *obj; 119 struct bpf_map *map; 120 char filename[256]; 121 int ret, err; 122 123 while ((opt = getopt(argc, argv, optstr)) != -1) { 124 switch (opt) { 125 case 'F': 126 xdp_flags &= ~XDP_FLAGS_UPDATE_IF_NOEXIST; 127 break; 128 case 'S': 129 xdp_flags |= XDP_FLAGS_SKB_MODE; 130 break; 131 default: 132 usage(basename(argv[0])); 133 return 1; 134 } 135 } 136 137 if (!(xdp_flags & XDP_FLAGS_SKB_MODE)) 138 xdp_flags |= XDP_FLAGS_DRV_MODE; 139 140 if (optind == argc) { 141 usage(basename(argv[0])); 142 return 1; 143 } 144 145 snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); 146 prog_load_attr.file = filename; 147 148 if (bpf_prog_load_xattr(&prog_load_attr, &obj, &prog_fd)) 149 return 1; 150 151 if (!prog_fd) { 152 printf("bpf_prog_load_xattr: %s\n", strerror(errno)); 153 return 1; 154 } 155 156 map = bpf_map__next(NULL, obj); 157 if (!map) { 158 printf("finding a map in obj file failed\n"); 159 return 1; 160 } 161 map_fd = bpf_map__fd(map); 162 163 if_idx = if_nametoindex(argv[optind]); 164 if (!if_idx) 165 if_idx = strtoul(argv[optind], NULL, 0); 166 167 if (!if_idx) { 168 fprintf(stderr, "Invalid ifname\n"); 169 return 1; 170 } 171 if_name = argv[optind]; 172 err = do_attach(if_idx, prog_fd, if_name); 173 if (err) 174 return err; 175 176 if (signal(SIGINT, sig_handler) || 177 signal(SIGHUP, sig_handler) || 178 signal(SIGTERM, sig_handler)) { 179 perror("signal"); 180 return 1; 181 } 182 183 pb_opts.sample_cb = print_bpf_output; 184 pb = perf_buffer__new(map_fd, 8, &pb_opts); 185 err = libbpf_get_error(pb); 186 if (err) { 187 perror("perf_buffer setup failed"); 188 return 1; 189 } 190 191 while ((ret = perf_buffer__poll(pb, 1000)) >= 0) { 192 } 193 194 kill(0, SIGINT); 195 return ret; 196}