Blame view
samples/bpf/xdp_adjust_tail_user.c
4.7 KB
c6ffd1ff7 bpf: add bpf_xdp_... |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
/* SPDX-License-Identifier: GPL-2.0 * Copyright (c) 2018 Facebook * * This program is free software; you can redistribute it and/or * modify it under the terms of version 2 of the GNU General Public * License as published by the Free Software Foundation. */ #include <linux/bpf.h> #include <linux/if_link.h> #include <assert.h> #include <errno.h> #include <signal.h> #include <stdio.h> #include <stdlib.h> #include <string.h> |
9e859e8f1 samples: bpf: mak... |
16 |
#include <net/if.h> |
c6ffd1ff7 bpf: add bpf_xdp_... |
17 18 19 20 21 |
#include <sys/resource.h> #include <arpa/inet.h> #include <netinet/ether.h> #include <unistd.h> #include <time.h> |
7cf245a37 samples/bpf: Use ... |
22 23 |
#include <bpf/bpf.h> #include <bpf/libbpf.h> |
c6ffd1ff7 bpf: add bpf_xdp_... |
24 25 |
#define STATS_INTERVAL_S 2U |
8fdf5b780 samples: bpf: Add... |
26 |
#define MAX_PCKT_SIZE 600 |
c6ffd1ff7 bpf: add bpf_xdp_... |
27 28 |
static int ifindex = -1; |
743e568c1 samples/bpf: Add ... |
29 |
static __u32 xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST; |
3b7a8ec2d samples/bpf: Chec... |
30 |
static __u32 prog_id; |
c6ffd1ff7 bpf: add bpf_xdp_... |
31 32 33 |
static void int_exit(int sig) { |
3b7a8ec2d samples/bpf: Chec... |
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
__u32 curr_prog_id = 0; if (ifindex > -1) { if (bpf_get_link_xdp_id(ifindex, &curr_prog_id, xdp_flags)) { printf("bpf_get_link_xdp_id failed "); exit(1); } if (prog_id == curr_prog_id) bpf_set_link_xdp_fd(ifindex, -1, xdp_flags); else if (!curr_prog_id) printf("couldn't find a prog id on a given iface "); else printf("program on interface changed, not removing "); } |
c6ffd1ff7 bpf: add bpf_xdp_... |
51 52 53 54 55 |
exit(0); } /* simple "icmp packet too big sent" counter */ |
be5bca44a samples: bpf: con... |
56 |
static void poll_stats(unsigned int map_fd, unsigned int kill_after_s) |
c6ffd1ff7 bpf: add bpf_xdp_... |
57 58 59 60 61 62 63 64 |
{ time_t started_at = time(NULL); __u64 value = 0; int key = 0; while (!kill_after_s || time(NULL) - started_at <= kill_after_s) { sleep(STATS_INTERVAL_S); |
be5bca44a samples: bpf: con... |
65 |
assert(bpf_map_lookup_elem(map_fd, &key, &value) == 0); |
c6ffd1ff7 bpf: add bpf_xdp_... |
66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
printf("icmp \"packet too big\" sent: %10llu pkts ", value); } } static void usage(const char *cmd) { printf("Start a XDP prog which send ICMP \"packet too big\" " "messages if ingress packet is bigger then MAX_SIZE bytes "); printf("Usage: %s [...] ", cmd); |
9e859e8f1 samples: bpf: mak... |
80 81 |
printf(" -i <ifname|ifindex> Interface "); |
c6ffd1ff7 bpf: add bpf_xdp_... |
82 83 |
printf(" -T <stop-after-X-seconds> Default: 0 (forever) "); |
8fdf5b780 samples: bpf: Add... |
84 85 |
printf(" -P <MAX_PCKT_SIZE> Default: %u ", MAX_PCKT_SIZE); |
c6ffd1ff7 bpf: add bpf_xdp_... |
86 87 88 89 |
printf(" -S use skb-mode "); printf(" -N enforce native mode "); |
743e568c1 samples/bpf: Add ... |
90 91 |
printf(" -F force loading prog "); |
c6ffd1ff7 bpf: add bpf_xdp_... |
92 93 94 95 96 97 |
printf(" -h Display this help "); } int main(int argc, char **argv) { |
be5bca44a samples: bpf: con... |
98 99 100 101 |
struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY}; struct bpf_prog_load_attr prog_load_attr = { .prog_type = BPF_PROG_TYPE_XDP, }; |
c6ffd1ff7 bpf: add bpf_xdp_... |
102 |
unsigned char opt_flags[256] = {}; |
8fdf5b780 samples: bpf: Add... |
103 |
const char *optstr = "i:T:P:SNFh"; |
3b7a8ec2d samples/bpf: Chec... |
104 105 |
struct bpf_prog_info info = {}; __u32 info_len = sizeof(info); |
c6ffd1ff7 bpf: add bpf_xdp_... |
106 |
unsigned int kill_after_s = 0; |
be5bca44a samples: bpf: con... |
107 108 |
int i, prog_fd, map_fd, opt; struct bpf_object *obj; |
8fdf5b780 samples: bpf: Add... |
109 110 |
__u32 max_pckt_size = 0; __u32 key = 0; |
c6ffd1ff7 bpf: add bpf_xdp_... |
111 |
char filename[256]; |
3b7a8ec2d samples/bpf: Chec... |
112 |
int err; |
c6ffd1ff7 bpf: add bpf_xdp_... |
113 114 115 116 117 118 119 120 121 |
for (i = 0; i < strlen(optstr); i++) if (optstr[i] != 'h' && 'a' <= optstr[i] && optstr[i] <= 'z') opt_flags[(unsigned char)optstr[i]] = 1; while ((opt = getopt(argc, argv, optstr)) != -1) { switch (opt) { case 'i': |
9e859e8f1 samples: bpf: mak... |
122 123 124 |
ifindex = if_nametoindex(optarg); if (!ifindex) ifindex = atoi(optarg); |
c6ffd1ff7 bpf: add bpf_xdp_... |
125 126 127 128 |
break; case 'T': kill_after_s = atoi(optarg); break; |
8fdf5b780 samples: bpf: Add... |
129 130 131 |
case 'P': max_pckt_size = atoi(optarg); break; |
c6ffd1ff7 bpf: add bpf_xdp_... |
132 133 134 135 |
case 'S': xdp_flags |= XDP_FLAGS_SKB_MODE; break; case 'N': |
d50ecc46d samples/bpf: Atta... |
136 |
/* default, set below */ |
c6ffd1ff7 bpf: add bpf_xdp_... |
137 |
break; |
743e568c1 samples/bpf: Add ... |
138 139 140 |
case 'F': xdp_flags &= ~XDP_FLAGS_UPDATE_IF_NOEXIST; break; |
c6ffd1ff7 bpf: add bpf_xdp_... |
141 142 143 144 145 146 |
default: usage(argv[0]); return 1; } opt_flags[opt] = 0; } |
d50ecc46d samples/bpf: Atta... |
147 148 |
if (!(xdp_flags & XDP_FLAGS_SKB_MODE)) xdp_flags |= XDP_FLAGS_DRV_MODE; |
c6ffd1ff7 bpf: add bpf_xdp_... |
149 150 151 152 153 154 155 156 157 158 159 160 161 |
for (i = 0; i < strlen(optstr); i++) { if (opt_flags[(unsigned int)optstr[i]]) { fprintf(stderr, "Missing argument -%c ", optstr[i]); usage(argv[0]); return 1; } } if (setrlimit(RLIMIT_MEMLOCK, &r)) { perror("setrlimit(RLIMIT_MEMLOCK, RLIM_INFINITY)"); return 1; } |
9e859e8f1 samples: bpf: mak... |
162 163 164 165 166 |
if (!ifindex) { fprintf(stderr, "Invalid ifname "); return 1; } |
c6ffd1ff7 bpf: add bpf_xdp_... |
167 |
snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); |
be5bca44a samples: bpf: con... |
168 169 170 171 |
prog_load_attr.file = filename; if (bpf_prog_load_xattr(&prog_load_attr, &obj, &prog_fd)) return 1; |
c6ffd1ff7 bpf: add bpf_xdp_... |
172 |
|
8fdf5b780 samples: bpf: Add... |
173 174 175 176 177 178 179 180 181 |
/* static global var 'max_pcktsz' is accessible from .data section */ if (max_pckt_size) { map_fd = bpf_object__find_map_fd_by_name(obj, "xdp_adju.data"); if (map_fd < 0) { printf("finding a max_pcktsz map in obj file failed "); return 1; } bpf_map_update_elem(map_fd, &key, &max_pckt_size, BPF_ANY); |
c6ffd1ff7 bpf: add bpf_xdp_... |
182 |
} |
8fdf5b780 samples: bpf: Add... |
183 184 185 186 187 |
/* fetch icmpcnt map */ map_fd = bpf_object__find_map_fd_by_name(obj, "icmpcnt"); if (map_fd < 0) { printf("finding a icmpcnt map in obj file failed "); |
c6ffd1ff7 bpf: add bpf_xdp_... |
188 189 190 191 192 |
return 1; } signal(SIGINT, int_exit); signal(SIGTERM, int_exit); |
be5bca44a samples: bpf: con... |
193 |
if (bpf_set_link_xdp_fd(ifindex, prog_fd, xdp_flags) < 0) { |
c6ffd1ff7 bpf: add bpf_xdp_... |
194 195 196 197 |
printf("link set xdp fd failed "); return 1; } |
3b7a8ec2d samples/bpf: Chec... |
198 199 200 201 202 203 204 |
err = bpf_obj_get_info_by_fd(prog_fd, &info, &info_len); if (err) { printf("can't get prog info - %s ", strerror(errno)); return 1; } prog_id = info.id; |
c6ffd1ff7 bpf: add bpf_xdp_... |
205 |
|
3b7a8ec2d samples/bpf: Chec... |
206 207 |
poll_stats(map_fd, kill_after_s); int_exit(0); |
c6ffd1ff7 bpf: add bpf_xdp_... |
208 209 210 |
return 0; } |