Blame view

samples/bpf/xdp_adjust_tail_user.c 4.7 KB
c6ffd1ff7   Nikita V. Shirokov   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   Daniel T. Lee   samples: bpf: mak...
16
  #include <net/if.h>
c6ffd1ff7   Nikita V. Shirokov   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   Toke Høiland-Jørgensen   samples/bpf: Use ...
22
23
  #include <bpf/bpf.h>
  #include <bpf/libbpf.h>
c6ffd1ff7   Nikita V. Shirokov   bpf: add bpf_xdp_...
24
25
  
  #define STATS_INTERVAL_S 2U
8fdf5b780   Daniel T. Lee   samples: bpf: Add...
26
  #define MAX_PCKT_SIZE 600
c6ffd1ff7   Nikita V. Shirokov   bpf: add bpf_xdp_...
27
28
  
  static int ifindex = -1;
743e568c1   Maciej Fijalkowski   samples/bpf: Add ...
29
  static __u32 xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
3b7a8ec2d   Maciej Fijalkowski   samples/bpf: Chec...
30
  static __u32 prog_id;
c6ffd1ff7   Nikita V. Shirokov   bpf: add bpf_xdp_...
31
32
33
  
  static void int_exit(int sig)
  {
3b7a8ec2d   Maciej Fijalkowski   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   Nikita V. Shirokov   bpf: add bpf_xdp_...
51
52
53
54
55
  	exit(0);
  }
  
  /* simple "icmp packet too big sent" counter
   */
be5bca44a   Jakub Kicinski   samples: bpf: con...
56
  static void poll_stats(unsigned int map_fd, unsigned int kill_after_s)
c6ffd1ff7   Nikita V. Shirokov   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   Jakub Kicinski   samples: bpf: con...
65
  		assert(bpf_map_lookup_elem(map_fd, &key, &value) == 0);
c6ffd1ff7   Nikita V. Shirokov   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   Daniel T. Lee   samples: bpf: mak...
80
81
  	printf("    -i <ifname|ifindex> Interface
  ");
c6ffd1ff7   Nikita V. Shirokov   bpf: add bpf_xdp_...
82
83
  	printf("    -T <stop-after-X-seconds> Default: 0 (forever)
  ");
8fdf5b780   Daniel T. Lee   samples: bpf: Add...
84
85
  	printf("    -P <MAX_PCKT_SIZE> Default: %u
  ", MAX_PCKT_SIZE);
c6ffd1ff7   Nikita V. Shirokov   bpf: add bpf_xdp_...
86
87
88
89
  	printf("    -S use skb-mode
  ");
  	printf("    -N enforce native mode
  ");
743e568c1   Maciej Fijalkowski   samples/bpf: Add ...
90
91
  	printf("    -F force loading prog
  ");
c6ffd1ff7   Nikita V. Shirokov   bpf: add bpf_xdp_...
92
93
94
95
96
97
  	printf("    -h Display this help
  ");
  }
  
  int main(int argc, char **argv)
  {
be5bca44a   Jakub Kicinski   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   Nikita V. Shirokov   bpf: add bpf_xdp_...
102
  	unsigned char opt_flags[256] = {};
8fdf5b780   Daniel T. Lee   samples: bpf: Add...
103
  	const char *optstr = "i:T:P:SNFh";
3b7a8ec2d   Maciej Fijalkowski   samples/bpf: Chec...
104
105
  	struct bpf_prog_info info = {};
  	__u32 info_len = sizeof(info);
c6ffd1ff7   Nikita V. Shirokov   bpf: add bpf_xdp_...
106
  	unsigned int kill_after_s = 0;
be5bca44a   Jakub Kicinski   samples: bpf: con...
107
108
  	int i, prog_fd, map_fd, opt;
  	struct bpf_object *obj;
8fdf5b780   Daniel T. Lee   samples: bpf: Add...
109
110
  	__u32 max_pckt_size = 0;
  	__u32 key = 0;
c6ffd1ff7   Nikita V. Shirokov   bpf: add bpf_xdp_...
111
  	char filename[256];
3b7a8ec2d   Maciej Fijalkowski   samples/bpf: Chec...
112
  	int err;
c6ffd1ff7   Nikita V. Shirokov   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   Daniel T. Lee   samples: bpf: mak...
122
123
124
  			ifindex = if_nametoindex(optarg);
  			if (!ifindex)
  				ifindex = atoi(optarg);
c6ffd1ff7   Nikita V. Shirokov   bpf: add bpf_xdp_...
125
126
127
128
  			break;
  		case 'T':
  			kill_after_s = atoi(optarg);
  			break;
8fdf5b780   Daniel T. Lee   samples: bpf: Add...
129
130
131
  		case 'P':
  			max_pckt_size = atoi(optarg);
  			break;
c6ffd1ff7   Nikita V. Shirokov   bpf: add bpf_xdp_...
132
133
134
135
  		case 'S':
  			xdp_flags |= XDP_FLAGS_SKB_MODE;
  			break;
  		case 'N':
d50ecc46d   Toke Høiland-Jørgensen   samples/bpf: Atta...
136
  			/* default, set below */
c6ffd1ff7   Nikita V. Shirokov   bpf: add bpf_xdp_...
137
  			break;
743e568c1   Maciej Fijalkowski   samples/bpf: Add ...
138
139
140
  		case 'F':
  			xdp_flags &= ~XDP_FLAGS_UPDATE_IF_NOEXIST;
  			break;
c6ffd1ff7   Nikita V. Shirokov   bpf: add bpf_xdp_...
141
142
143
144
145
146
  		default:
  			usage(argv[0]);
  			return 1;
  		}
  		opt_flags[opt] = 0;
  	}
d50ecc46d   Toke Høiland-Jørgensen   samples/bpf: Atta...
147
148
  	if (!(xdp_flags & XDP_FLAGS_SKB_MODE))
  		xdp_flags |= XDP_FLAGS_DRV_MODE;
c6ffd1ff7   Nikita V. Shirokov   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   Daniel T. Lee   samples: bpf: mak...
162
163
164
165
166
  	if (!ifindex) {
  		fprintf(stderr, "Invalid ifname
  ");
  		return 1;
  	}
c6ffd1ff7   Nikita V. Shirokov   bpf: add bpf_xdp_...
167
  	snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
be5bca44a   Jakub Kicinski   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   Nikita V. Shirokov   bpf: add bpf_xdp_...
172

8fdf5b780   Daniel T. Lee   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   Nikita V. Shirokov   bpf: add bpf_xdp_...
182
  	}
8fdf5b780   Daniel T. Lee   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   Nikita V. Shirokov   bpf: add bpf_xdp_...
188
189
190
191
192
  		return 1;
  	}
  
  	signal(SIGINT, int_exit);
  	signal(SIGTERM, int_exit);
be5bca44a   Jakub Kicinski   samples: bpf: con...
193
  	if (bpf_set_link_xdp_fd(ifindex, prog_fd, xdp_flags) < 0) {
c6ffd1ff7   Nikita V. Shirokov   bpf: add bpf_xdp_...
194
195
196
197
  		printf("link set xdp fd failed
  ");
  		return 1;
  	}
3b7a8ec2d   Maciej Fijalkowski   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   Nikita V. Shirokov   bpf: add bpf_xdp_...
205

3b7a8ec2d   Maciej Fijalkowski   samples/bpf: Chec...
206
207
  	poll_stats(map_fd, kill_after_s);
  	int_exit(0);
c6ffd1ff7   Nikita V. Shirokov   bpf: add bpf_xdp_...
208
209
210
  
  	return 0;
  }