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.7-rc1 223 lines 5.5 kB view raw
1// SPDX-License-Identifier: GPL-2.0-only 2/* Copyright (c) 2016 John Fastabend <john.r.fastabend@intel.com> 3 */ 4#include <linux/bpf.h> 5#include <linux/if_link.h> 6#include <assert.h> 7#include <errno.h> 8#include <signal.h> 9#include <stdio.h> 10#include <stdlib.h> 11#include <stdbool.h> 12#include <string.h> 13#include <net/if.h> 14#include <unistd.h> 15#include <libgen.h> 16#include <sys/resource.h> 17 18#include "bpf_util.h" 19#include <bpf/bpf.h> 20#include <bpf/libbpf.h> 21 22static int ifindex_in; 23static int ifindex_out; 24static bool ifindex_out_xdp_dummy_attached = true; 25static __u32 prog_id; 26static __u32 dummy_prog_id; 27 28static __u32 xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST; 29static int rxcnt_map_fd; 30 31static void int_exit(int sig) 32{ 33 __u32 curr_prog_id = 0; 34 35 if (bpf_get_link_xdp_id(ifindex_in, &curr_prog_id, xdp_flags)) { 36 printf("bpf_get_link_xdp_id failed\n"); 37 exit(1); 38 } 39 if (prog_id == curr_prog_id) 40 bpf_set_link_xdp_fd(ifindex_in, -1, xdp_flags); 41 else if (!curr_prog_id) 42 printf("couldn't find a prog id on iface IN\n"); 43 else 44 printf("program on iface IN changed, not removing\n"); 45 46 if (ifindex_out_xdp_dummy_attached) { 47 curr_prog_id = 0; 48 if (bpf_get_link_xdp_id(ifindex_out, &curr_prog_id, 49 xdp_flags)) { 50 printf("bpf_get_link_xdp_id failed\n"); 51 exit(1); 52 } 53 if (dummy_prog_id == curr_prog_id) 54 bpf_set_link_xdp_fd(ifindex_out, -1, xdp_flags); 55 else if (!curr_prog_id) 56 printf("couldn't find a prog id on iface OUT\n"); 57 else 58 printf("program on iface OUT changed, not removing\n"); 59 } 60 exit(0); 61} 62 63static void poll_stats(int interval, int ifindex) 64{ 65 unsigned int nr_cpus = bpf_num_possible_cpus(); 66 __u64 values[nr_cpus], prev[nr_cpus]; 67 68 memset(prev, 0, sizeof(prev)); 69 70 while (1) { 71 __u64 sum = 0; 72 __u32 key = 0; 73 int i; 74 75 sleep(interval); 76 assert(bpf_map_lookup_elem(rxcnt_map_fd, &key, values) == 0); 77 for (i = 0; i < nr_cpus; i++) 78 sum += (values[i] - prev[i]); 79 if (sum) 80 printf("ifindex %i: %10llu pkt/s\n", 81 ifindex, sum / interval); 82 memcpy(prev, values, sizeof(values)); 83 } 84} 85 86static void usage(const char *prog) 87{ 88 fprintf(stderr, 89 "usage: %s [OPTS] <IFNAME|IFINDEX>_IN <IFNAME|IFINDEX>_OUT\n\n" 90 "OPTS:\n" 91 " -S use skb-mode\n" 92 " -N enforce native mode\n" 93 " -F force loading prog\n", 94 prog); 95} 96 97 98int main(int argc, char **argv) 99{ 100 struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY}; 101 struct bpf_prog_load_attr prog_load_attr = { 102 .prog_type = BPF_PROG_TYPE_XDP, 103 }; 104 struct bpf_program *prog, *dummy_prog; 105 int prog_fd, tx_port_map_fd, opt; 106 struct bpf_prog_info info = {}; 107 __u32 info_len = sizeof(info); 108 const char *optstr = "FSN"; 109 struct bpf_object *obj; 110 char filename[256]; 111 int dummy_prog_fd; 112 int ret, key = 0; 113 114 while ((opt = getopt(argc, argv, optstr)) != -1) { 115 switch (opt) { 116 case 'S': 117 xdp_flags |= XDP_FLAGS_SKB_MODE; 118 break; 119 case 'N': 120 /* default, set below */ 121 break; 122 case 'F': 123 xdp_flags &= ~XDP_FLAGS_UPDATE_IF_NOEXIST; 124 break; 125 default: 126 usage(basename(argv[0])); 127 return 1; 128 } 129 } 130 131 if (!(xdp_flags & XDP_FLAGS_SKB_MODE)) 132 xdp_flags |= XDP_FLAGS_DRV_MODE; 133 134 if (optind == argc) { 135 printf("usage: %s <IFNAME|IFINDEX>_IN <IFNAME|IFINDEX>_OUT\n", argv[0]); 136 return 1; 137 } 138 139 if (setrlimit(RLIMIT_MEMLOCK, &r)) { 140 perror("setrlimit(RLIMIT_MEMLOCK)"); 141 return 1; 142 } 143 144 ifindex_in = if_nametoindex(argv[optind]); 145 if (!ifindex_in) 146 ifindex_in = strtoul(argv[optind], NULL, 0); 147 148 ifindex_out = if_nametoindex(argv[optind + 1]); 149 if (!ifindex_out) 150 ifindex_out = strtoul(argv[optind + 1], NULL, 0); 151 152 printf("input: %d output: %d\n", ifindex_in, ifindex_out); 153 154 snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); 155 prog_load_attr.file = filename; 156 157 if (bpf_prog_load_xattr(&prog_load_attr, &obj, &prog_fd)) 158 return 1; 159 160 prog = bpf_program__next(NULL, obj); 161 dummy_prog = bpf_program__next(prog, obj); 162 if (!prog || !dummy_prog) { 163 printf("finding a prog in obj file failed\n"); 164 return 1; 165 } 166 /* bpf_prog_load_xattr gives us the pointer to first prog's fd, 167 * so we're missing only the fd for dummy prog 168 */ 169 dummy_prog_fd = bpf_program__fd(dummy_prog); 170 if (prog_fd < 0 || dummy_prog_fd < 0) { 171 printf("bpf_prog_load_xattr: %s\n", strerror(errno)); 172 return 1; 173 } 174 175 tx_port_map_fd = bpf_object__find_map_fd_by_name(obj, "tx_port"); 176 rxcnt_map_fd = bpf_object__find_map_fd_by_name(obj, "rxcnt"); 177 if (tx_port_map_fd < 0 || rxcnt_map_fd < 0) { 178 printf("bpf_object__find_map_fd_by_name failed\n"); 179 return 1; 180 } 181 182 if (bpf_set_link_xdp_fd(ifindex_in, prog_fd, xdp_flags) < 0) { 183 printf("ERROR: link set xdp fd failed on %d\n", ifindex_in); 184 return 1; 185 } 186 187 ret = bpf_obj_get_info_by_fd(prog_fd, &info, &info_len); 188 if (ret) { 189 printf("can't get prog info - %s\n", strerror(errno)); 190 return ret; 191 } 192 prog_id = info.id; 193 194 /* Loading dummy XDP prog on out-device */ 195 if (bpf_set_link_xdp_fd(ifindex_out, dummy_prog_fd, 196 (xdp_flags | XDP_FLAGS_UPDATE_IF_NOEXIST)) < 0) { 197 printf("WARN: link set xdp fd failed on %d\n", ifindex_out); 198 ifindex_out_xdp_dummy_attached = false; 199 } 200 201 memset(&info, 0, sizeof(info)); 202 ret = bpf_obj_get_info_by_fd(dummy_prog_fd, &info, &info_len); 203 if (ret) { 204 printf("can't get prog info - %s\n", strerror(errno)); 205 return ret; 206 } 207 dummy_prog_id = info.id; 208 209 signal(SIGINT, int_exit); 210 signal(SIGTERM, int_exit); 211 212 /* bpf redirect port */ 213 ret = bpf_map_update_elem(tx_port_map_fd, &key, &ifindex_out, 0); 214 if (ret) { 215 perror("bpf_update_elem"); 216 goto out; 217 } 218 219 poll_stats(2, ifindex_out); 220 221out: 222 return 0; 223}