Blame view

samples/bpf/xdpsock_user.c 38.3 KB
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1
  // SPDX-License-Identifier: GPL-2.0
dac09149d   Björn Töpel   xsk: clean up SPD...
2
  /* Copyright(c) 2017 - 2018 Intel Corporation. */
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
3

248c7f9c0   Magnus Karlsson   samples/bpf: conv...
4
  #include <asm/barrier.h>
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
5
6
7
8
  #include <errno.h>
  #include <getopt.h>
  #include <libgen.h>
  #include <linux/bpf.h>
248c7f9c0   Magnus Karlsson   samples/bpf: conv...
9
  #include <linux/compiler.h>
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
10
11
12
  #include <linux/if_link.h>
  #include <linux/if_xdp.h>
  #include <linux/if_ether.h>
4a3c23ae3   Jay Jayatheerthan   samples/bpf: xdps...
13
  #include <linux/ip.h>
67ed37553   Ciara Loftus   samples: bpf: Dri...
14
  #include <linux/limits.h>
4a3c23ae3   Jay Jayatheerthan   samples/bpf: xdps...
15
16
  #include <linux/udp.h>
  #include <arpa/inet.h>
248c7f9c0   Magnus Karlsson   samples/bpf: conv...
17
18
  #include <locale.h>
  #include <net/ethernet.h>
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
19
  #include <net/if.h>
248c7f9c0   Magnus Karlsson   samples/bpf: conv...
20
21
  #include <poll.h>
  #include <pthread.h>
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
22
23
24
25
26
  #include <signal.h>
  #include <stdbool.h>
  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>
248c7f9c0   Magnus Karlsson   samples/bpf: conv...
27
  #include <sys/mman.h>
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
28
29
  #include <sys/resource.h>
  #include <sys/socket.h>
248c7f9c0   Magnus Karlsson   samples/bpf: conv...
30
  #include <sys/types.h>
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
31
32
  #include <time.h>
  #include <unistd.h>
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
33

7cf245a37   Toke Høiland-Jørgensen   samples/bpf: Use ...
34
35
  #include <bpf/libbpf.h>
  #include <bpf/xsk.h>
2bf3e2ef4   Jakub Kicinski   samples: bpf: inc...
36
  #include <bpf/bpf.h>
7cf245a37   Toke Høiland-Jørgensen   samples/bpf: Use ...
37
  #include "xdpsock.h"
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
38

b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
39
40
41
42
43
44
45
46
47
48
49
  #ifndef SOL_XDP
  #define SOL_XDP 283
  #endif
  
  #ifndef AF_XDP
  #define AF_XDP 44
  #endif
  
  #ifndef PF_XDP
  #define PF_XDP AF_XDP
  #endif
248c7f9c0   Magnus Karlsson   samples/bpf: conv...
50
  #define NUM_FRAMES (4 * 1024)
4a3c23ae3   Jay Jayatheerthan   samples/bpf: xdps...
51
  #define MIN_PKT_SIZE 64
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
52
53
  
  #define DEBUG_HEXDUMP 0
a412ef54f   Björn Töpel   samples/bpf: adap...
54
  typedef __u64 u64;
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
55
  typedef __u32 u32;
4a3c23ae3   Jay Jayatheerthan   samples/bpf: xdps...
56
57
  typedef __u16 u16;
  typedef __u8  u8;
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
58
59
60
61
62
63
64
65
66
67
  
  static unsigned long prev_time;
  
  enum benchmark_type {
  	BENCH_RXDROP = 0,
  	BENCH_TXONLY = 1,
  	BENCH_L2FWD = 2,
  };
  
  static enum benchmark_type opt_bench = BENCH_RXDROP;
743e568c1   Maciej Fijalkowski   samples/bpf: Add ...
68
  static u32 opt_xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
69
70
71
  static const char *opt_if = "";
  static int opt_ifindex;
  static int opt_queue;
d3f11b018   Jay Jayatheerthan   samples/bpf: xdps...
72
73
74
  static unsigned long opt_duration;
  static unsigned long start_time;
  static bool benchmark_done;
cd9e72b6f   Jay Jayatheerthan   samples/bpf: xdps...
75
  static u32 opt_batch_size = 64;
ece6e9694   Jay Jayatheerthan   samples/bpf: xdps...
76
  static int opt_pkt_count;
4a3c23ae3   Jay Jayatheerthan   samples/bpf: xdps...
77
  static u16 opt_pkt_size = MIN_PKT_SIZE;
46e3268ea   Jay Jayatheerthan   samples/bpf: xdps...
78
  static u32 opt_pkt_fill_pattern = 0x12345678;
b36c3206f   Ciara Loftus   samples: bpf: Add...
79
  static bool opt_extra_stats;
74e00676d   Magnus Karlsson   samples/bpf: Add ...
80
  static bool opt_quiet;
60dc609db   Ciara Loftus   samples: bpf: Cou...
81
  static bool opt_app_stats;
67ed37553   Ciara Loftus   samples: bpf: Dri...
82
83
84
  static const char *opt_irq_str = "";
  static u32 irq_no;
  static int irqs_at_init = -1;
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
85
  static int opt_poll;
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
86
  static int opt_interval = 1;
46738f73e   Magnus Karlsson   samples/bpf: add ...
87
  static u32 opt_xdp_bind_flags = XDP_USE_NEED_WAKEUP;
c543f5469   Kevin Laatz   samples/bpf: add ...
88
89
  static u32 opt_umem_flags;
  static int opt_unaligned_chunks;
3945b37a9   Kevin Laatz   samples/bpf: use ...
90
  static int opt_mmap_flags;
123e8da1d   Maxim Mikityanskiy   xsk: Change the d...
91
  static int opt_xsk_frame_size = XSK_UMEM__DEFAULT_FRAME_SIZE;
46738f73e   Magnus Karlsson   samples/bpf: add ...
92
93
  static int opt_timeout = 1000;
  static bool opt_need_wakeup = true;
2e5d72c15   Magnus Karlsson   samples/bpf: Add ...
94
95
  static u32 opt_num_xsks = 1;
  static u32 prog_id;
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
96

2e8806f03   Ciara Loftus   samples: bpf: Spl...
97
  struct xsk_ring_stats {
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
98
99
  	unsigned long rx_npkts;
  	unsigned long tx_npkts;
b36c3206f   Ciara Loftus   samples: bpf: Add...
100
101
102
103
104
105
  	unsigned long rx_dropped_npkts;
  	unsigned long rx_invalid_npkts;
  	unsigned long tx_invalid_npkts;
  	unsigned long rx_full_npkts;
  	unsigned long rx_fill_empty_npkts;
  	unsigned long tx_empty_npkts;
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
106
107
  	unsigned long prev_rx_npkts;
  	unsigned long prev_tx_npkts;
b36c3206f   Ciara Loftus   samples: bpf: Add...
108
109
110
111
112
113
  	unsigned long prev_rx_dropped_npkts;
  	unsigned long prev_rx_invalid_npkts;
  	unsigned long prev_tx_invalid_npkts;
  	unsigned long prev_rx_full_npkts;
  	unsigned long prev_rx_fill_empty_npkts;
  	unsigned long prev_tx_empty_npkts;
2e8806f03   Ciara Loftus   samples: bpf: Spl...
114
  };
67ed37553   Ciara Loftus   samples: bpf: Dri...
115
116
117
118
  struct xsk_driver_stats {
  	unsigned long intrs;
  	unsigned long prev_intrs;
  };
60dc609db   Ciara Loftus   samples: bpf: Cou...
119
120
121
122
123
124
125
126
127
128
129
130
  struct xsk_app_stats {
  	unsigned long rx_empty_polls;
  	unsigned long fill_fail_polls;
  	unsigned long copy_tx_sendtos;
  	unsigned long tx_wakeup_sendtos;
  	unsigned long opt_polls;
  	unsigned long prev_rx_empty_polls;
  	unsigned long prev_fill_fail_polls;
  	unsigned long prev_copy_tx_sendtos;
  	unsigned long prev_tx_wakeup_sendtos;
  	unsigned long prev_opt_polls;
  };
2e8806f03   Ciara Loftus   samples: bpf: Spl...
131
132
133
134
135
136
137
138
139
140
141
142
143
  struct xsk_umem_info {
  	struct xsk_ring_prod fq;
  	struct xsk_ring_cons cq;
  	struct xsk_umem *umem;
  	void *buffer;
  };
  
  struct xsk_socket_info {
  	struct xsk_ring_cons rx;
  	struct xsk_ring_prod tx;
  	struct xsk_umem_info *umem;
  	struct xsk_socket *xsk;
  	struct xsk_ring_stats ring_stats;
60dc609db   Ciara Loftus   samples: bpf: Cou...
144
  	struct xsk_app_stats app_stats;
67ed37553   Ciara Loftus   samples: bpf: Dri...
145
  	struct xsk_driver_stats drv_stats;
248c7f9c0   Magnus Karlsson   samples/bpf: conv...
146
  	u32 outstanding_tx;
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
147
  };
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
148
  static int num_socks;
248c7f9c0   Magnus Karlsson   samples/bpf: conv...
149
  struct xsk_socket_info *xsks[MAX_SOCKS];
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
150
151
152
153
154
155
156
157
  
  static unsigned long get_nsecs(void)
  {
  	struct timespec ts;
  
  	clock_gettime(CLOCK_MONOTONIC, &ts);
  	return ts.tv_sec * 1000000000UL + ts.tv_nsec;
  }
248c7f9c0   Magnus Karlsson   samples/bpf: conv...
158
  static void print_benchmark(bool running)
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
159
  {
248c7f9c0   Magnus Karlsson   samples/bpf: conv...
160
  	const char *bench_str = "INVALID";
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
161

248c7f9c0   Magnus Karlsson   samples/bpf: conv...
162
163
164
165
166
167
  	if (opt_bench == BENCH_RXDROP)
  		bench_str = "rxdrop";
  	else if (opt_bench == BENCH_TXONLY)
  		bench_str = "txonly";
  	else if (opt_bench == BENCH_L2FWD)
  		bench_str = "l2fwd";
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
168

248c7f9c0   Magnus Karlsson   samples/bpf: conv...
169
170
171
172
173
174
175
  	printf("%s:%d %s ", opt_if, opt_queue, bench_str);
  	if (opt_xdp_flags & XDP_FLAGS_SKB_MODE)
  		printf("xdp-skb ");
  	else if (opt_xdp_flags & XDP_FLAGS_DRV_MODE)
  		printf("xdp-drv ");
  	else
  		printf("	");
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
176

248c7f9c0   Magnus Karlsson   samples/bpf: conv...
177
178
  	if (opt_poll)
  		printf("poll() ");
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
179

248c7f9c0   Magnus Karlsson   samples/bpf: conv...
180
181
182
  	if (running) {
  		printf("running...");
  		fflush(stdout);
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
183
  	}
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
184
  }
b36c3206f   Ciara Loftus   samples: bpf: Add...
185
186
187
188
189
190
191
192
193
194
195
196
  static int xsk_get_xdp_stats(int fd, struct xsk_socket_info *xsk)
  {
  	struct xdp_statistics stats;
  	socklen_t optlen;
  	int err;
  
  	optlen = sizeof(stats);
  	err = getsockopt(fd, SOL_XDP, XDP_STATISTICS, &stats, &optlen);
  	if (err)
  		return err;
  
  	if (optlen == sizeof(struct xdp_statistics)) {
2e8806f03   Ciara Loftus   samples: bpf: Spl...
197
198
199
200
201
202
  		xsk->ring_stats.rx_dropped_npkts = stats.rx_dropped;
  		xsk->ring_stats.rx_invalid_npkts = stats.rx_invalid_descs;
  		xsk->ring_stats.tx_invalid_npkts = stats.tx_invalid_descs;
  		xsk->ring_stats.rx_full_npkts = stats.rx_ring_full;
  		xsk->ring_stats.rx_fill_empty_npkts = stats.rx_fill_ring_empty_descs;
  		xsk->ring_stats.tx_empty_npkts = stats.tx_ring_empty_descs;
b36c3206f   Ciara Loftus   samples: bpf: Add...
203
204
205
206
207
  		return 0;
  	}
  
  	return -EINVAL;
  }
60dc609db   Ciara Loftus   samples: bpf: Cou...
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
  static void dump_app_stats(long dt)
  {
  	int i;
  
  	for (i = 0; i < num_socks && xsks[i]; i++) {
  		char *fmt = "%-18s %'-14.0f %'-14lu
  ";
  		double rx_empty_polls_ps, fill_fail_polls_ps, copy_tx_sendtos_ps,
  				tx_wakeup_sendtos_ps, opt_polls_ps;
  
  		rx_empty_polls_ps = (xsks[i]->app_stats.rx_empty_polls -
  					xsks[i]->app_stats.prev_rx_empty_polls) * 1000000000. / dt;
  		fill_fail_polls_ps = (xsks[i]->app_stats.fill_fail_polls -
  					xsks[i]->app_stats.prev_fill_fail_polls) * 1000000000. / dt;
  		copy_tx_sendtos_ps = (xsks[i]->app_stats.copy_tx_sendtos -
  					xsks[i]->app_stats.prev_copy_tx_sendtos) * 1000000000. / dt;
  		tx_wakeup_sendtos_ps = (xsks[i]->app_stats.tx_wakeup_sendtos -
  					xsks[i]->app_stats.prev_tx_wakeup_sendtos)
  										* 1000000000. / dt;
  		opt_polls_ps = (xsks[i]->app_stats.opt_polls -
  					xsks[i]->app_stats.prev_opt_polls) * 1000000000. / dt;
  
  		printf("
  %-18s %-14s %-14s
  ", "", "calls/s", "count");
  		printf(fmt, "rx empty polls", rx_empty_polls_ps, xsks[i]->app_stats.rx_empty_polls);
  		printf(fmt, "fill fail polls", fill_fail_polls_ps,
  							xsks[i]->app_stats.fill_fail_polls);
  		printf(fmt, "copy tx sendtos", copy_tx_sendtos_ps,
  							xsks[i]->app_stats.copy_tx_sendtos);
  		printf(fmt, "tx wakeup sendtos", tx_wakeup_sendtos_ps,
  							xsks[i]->app_stats.tx_wakeup_sendtos);
  		printf(fmt, "opt polls", opt_polls_ps, xsks[i]->app_stats.opt_polls);
  
  		xsks[i]->app_stats.prev_rx_empty_polls = xsks[i]->app_stats.rx_empty_polls;
  		xsks[i]->app_stats.prev_fill_fail_polls = xsks[i]->app_stats.fill_fail_polls;
  		xsks[i]->app_stats.prev_copy_tx_sendtos = xsks[i]->app_stats.copy_tx_sendtos;
  		xsks[i]->app_stats.prev_tx_wakeup_sendtos = xsks[i]->app_stats.tx_wakeup_sendtos;
  		xsks[i]->app_stats.prev_opt_polls = xsks[i]->app_stats.opt_polls;
  	}
  }
67ed37553   Ciara Loftus   samples: bpf: Dri...
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
  static bool get_interrupt_number(void)
  {
  	FILE *f_int_proc;
  	char line[4096];
  	bool found = false;
  
  	f_int_proc = fopen("/proc/interrupts", "r");
  	if (f_int_proc == NULL) {
  		printf("Failed to open /proc/interrupts.
  ");
  		return found;
  	}
  
  	while (!feof(f_int_proc) && !found) {
  		/* Make sure to read a full line at a time */
  		if (fgets(line, sizeof(line), f_int_proc) == NULL ||
  				line[strlen(line) - 1] != '
  ') {
  			printf("Error reading from interrupts file
  ");
  			break;
  		}
  
  		/* Extract interrupt number from line */
  		if (strstr(line, opt_irq_str) != NULL) {
  			irq_no = atoi(line);
  			found = true;
  			break;
  		}
  	}
  
  	fclose(f_int_proc);
  
  	return found;
  }
  
  static int get_irqs(void)
  {
  	char count_path[PATH_MAX];
  	int total_intrs = -1;
  	FILE *f_count_proc;
  	char line[4096];
  
  	snprintf(count_path, sizeof(count_path),
  		"/sys/kernel/irq/%i/per_cpu_count", irq_no);
  	f_count_proc = fopen(count_path, "r");
  	if (f_count_proc == NULL) {
  		printf("Failed to open %s
  ", count_path);
  		return total_intrs;
  	}
  
  	if (fgets(line, sizeof(line), f_count_proc) == NULL ||
  			line[strlen(line) - 1] != '
  ') {
  		printf("Error reading from %s
  ", count_path);
  	} else {
  		static const char com[2] = ",";
  		char *token;
  
  		total_intrs = 0;
  		token = strtok(line, com);
  		while (token != NULL) {
  			/* sum up interrupts across all cores */
  			total_intrs += atoi(token);
  			token = strtok(NULL, com);
  		}
  	}
  
  	fclose(f_count_proc);
  
  	return total_intrs;
  }
  
  static void dump_driver_stats(long dt)
  {
  	int i;
  
  	for (i = 0; i < num_socks && xsks[i]; i++) {
  		char *fmt = "%-18s %'-14.0f %'-14lu
  ";
  		double intrs_ps;
  		int n_ints = get_irqs();
  
  		if (n_ints < 0) {
  			printf("error getting intr info for intr %i
  ", irq_no);
  			return;
  		}
  		xsks[i]->drv_stats.intrs = n_ints - irqs_at_init;
  
  		intrs_ps = (xsks[i]->drv_stats.intrs - xsks[i]->drv_stats.prev_intrs) *
  			 1000000000. / dt;
  
  		printf("
  %-18s %-14s %-14s
  ", "", "intrs/s", "count");
  		printf(fmt, "irqs", intrs_ps, xsks[i]->drv_stats.intrs);
  
  		xsks[i]->drv_stats.prev_intrs = xsks[i]->drv_stats.intrs;
  	}
  }
248c7f9c0   Magnus Karlsson   samples/bpf: conv...
352
  static void dump_stats(void)
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
353
  {
248c7f9c0   Magnus Karlsson   samples/bpf: conv...
354
355
356
  	unsigned long now = get_nsecs();
  	long dt = now - prev_time;
  	int i;
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
357

248c7f9c0   Magnus Karlsson   samples/bpf: conv...
358
  	prev_time = now;
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
359

248c7f9c0   Magnus Karlsson   samples/bpf: conv...
360
  	for (i = 0; i < num_socks && xsks[i]; i++) {
60dc609db   Ciara Loftus   samples: bpf: Cou...
361
362
  		char *fmt = "%-18s %'-14.0f %'-14lu
  ";
b36c3206f   Ciara Loftus   samples: bpf: Add...
363
364
  		double rx_pps, tx_pps, dropped_pps, rx_invalid_pps, full_pps, fill_empty_pps,
  			tx_invalid_pps, tx_empty_pps;
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
365

2e8806f03   Ciara Loftus   samples: bpf: Spl...
366
  		rx_pps = (xsks[i]->ring_stats.rx_npkts - xsks[i]->ring_stats.prev_rx_npkts) *
248c7f9c0   Magnus Karlsson   samples/bpf: conv...
367
  			 1000000000. / dt;
2e8806f03   Ciara Loftus   samples: bpf: Spl...
368
  		tx_pps = (xsks[i]->ring_stats.tx_npkts - xsks[i]->ring_stats.prev_tx_npkts) *
248c7f9c0   Magnus Karlsson   samples/bpf: conv...
369
  			 1000000000. / dt;
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
370

248c7f9c0   Magnus Karlsson   samples/bpf: conv...
371
372
373
374
375
  		printf("
   sock%d@", i);
  		print_benchmark(false);
  		printf("
  ");
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
376

60dc609db   Ciara Loftus   samples: bpf: Cou...
377
378
  		printf("%-18s %-14s %-14s %-14.2f
  ", "", "pps", "pkts",
248c7f9c0   Magnus Karlsson   samples/bpf: conv...
379
  		       dt / 1000000000.);
2e8806f03   Ciara Loftus   samples: bpf: Spl...
380
381
  		printf(fmt, "rx", rx_pps, xsks[i]->ring_stats.rx_npkts);
  		printf(fmt, "tx", tx_pps, xsks[i]->ring_stats.tx_npkts);
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
382

2e8806f03   Ciara Loftus   samples: bpf: Spl...
383
384
  		xsks[i]->ring_stats.prev_rx_npkts = xsks[i]->ring_stats.rx_npkts;
  		xsks[i]->ring_stats.prev_tx_npkts = xsks[i]->ring_stats.tx_npkts;
b36c3206f   Ciara Loftus   samples: bpf: Add...
385
386
387
  
  		if (opt_extra_stats) {
  			if (!xsk_get_xdp_stats(xsk_socket__fd(xsks[i]->xsk), xsks[i])) {
2e8806f03   Ciara Loftus   samples: bpf: Spl...
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
  				dropped_pps = (xsks[i]->ring_stats.rx_dropped_npkts -
  						xsks[i]->ring_stats.prev_rx_dropped_npkts) *
  							1000000000. / dt;
  				rx_invalid_pps = (xsks[i]->ring_stats.rx_invalid_npkts -
  						xsks[i]->ring_stats.prev_rx_invalid_npkts) *
  							1000000000. / dt;
  				tx_invalid_pps = (xsks[i]->ring_stats.tx_invalid_npkts -
  						xsks[i]->ring_stats.prev_tx_invalid_npkts) *
  							1000000000. / dt;
  				full_pps = (xsks[i]->ring_stats.rx_full_npkts -
  						xsks[i]->ring_stats.prev_rx_full_npkts) *
  							1000000000. / dt;
  				fill_empty_pps = (xsks[i]->ring_stats.rx_fill_empty_npkts -
  						xsks[i]->ring_stats.prev_rx_fill_empty_npkts) *
  							1000000000. / dt;
  				tx_empty_pps = (xsks[i]->ring_stats.tx_empty_npkts -
  						xsks[i]->ring_stats.prev_tx_empty_npkts) *
  							1000000000. / dt;
b36c3206f   Ciara Loftus   samples: bpf: Add...
406
407
  
  				printf(fmt, "rx dropped", dropped_pps,
2e8806f03   Ciara Loftus   samples: bpf: Spl...
408
  				       xsks[i]->ring_stats.rx_dropped_npkts);
b36c3206f   Ciara Loftus   samples: bpf: Add...
409
  				printf(fmt, "rx invalid", rx_invalid_pps,
2e8806f03   Ciara Loftus   samples: bpf: Spl...
410
  				       xsks[i]->ring_stats.rx_invalid_npkts);
b36c3206f   Ciara Loftus   samples: bpf: Add...
411
  				printf(fmt, "tx invalid", tx_invalid_pps,
2e8806f03   Ciara Loftus   samples: bpf: Spl...
412
  				       xsks[i]->ring_stats.tx_invalid_npkts);
b36c3206f   Ciara Loftus   samples: bpf: Add...
413
  				printf(fmt, "rx queue full", full_pps,
2e8806f03   Ciara Loftus   samples: bpf: Spl...
414
  				       xsks[i]->ring_stats.rx_full_npkts);
b36c3206f   Ciara Loftus   samples: bpf: Add...
415
  				printf(fmt, "fill ring empty", fill_empty_pps,
2e8806f03   Ciara Loftus   samples: bpf: Spl...
416
  				       xsks[i]->ring_stats.rx_fill_empty_npkts);
b36c3206f   Ciara Loftus   samples: bpf: Add...
417
  				printf(fmt, "tx ring empty", tx_empty_pps,
2e8806f03   Ciara Loftus   samples: bpf: Spl...
418
419
420
421
422
423
424
425
426
427
428
429
430
431
  				       xsks[i]->ring_stats.tx_empty_npkts);
  
  				xsks[i]->ring_stats.prev_rx_dropped_npkts =
  					xsks[i]->ring_stats.rx_dropped_npkts;
  				xsks[i]->ring_stats.prev_rx_invalid_npkts =
  					xsks[i]->ring_stats.rx_invalid_npkts;
  				xsks[i]->ring_stats.prev_tx_invalid_npkts =
  					xsks[i]->ring_stats.tx_invalid_npkts;
  				xsks[i]->ring_stats.prev_rx_full_npkts =
  					xsks[i]->ring_stats.rx_full_npkts;
  				xsks[i]->ring_stats.prev_rx_fill_empty_npkts =
  					xsks[i]->ring_stats.rx_fill_empty_npkts;
  				xsks[i]->ring_stats.prev_tx_empty_npkts =
  					xsks[i]->ring_stats.tx_empty_npkts;
b36c3206f   Ciara Loftus   samples: bpf: Add...
432
433
434
435
436
  			} else {
  				printf("%-15s
  ", "Error retrieving extra stats");
  			}
  		}
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
437
  	}
60dc609db   Ciara Loftus   samples: bpf: Cou...
438
439
440
  
  	if (opt_app_stats)
  		dump_app_stats(dt);
67ed37553   Ciara Loftus   samples: bpf: Dri...
441
442
  	if (irq_no)
  		dump_driver_stats(dt);
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
443
  }
d3f11b018   Jay Jayatheerthan   samples/bpf: xdps...
444
445
446
447
448
449
450
451
452
453
  static bool is_benchmark_done(void)
  {
  	if (opt_duration > 0) {
  		unsigned long dt = (get_nsecs() - start_time);
  
  		if (dt >= opt_duration)
  			benchmark_done = true;
  	}
  	return benchmark_done;
  }
248c7f9c0   Magnus Karlsson   samples/bpf: conv...
454
  static void *poller(void *arg)
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
455
  {
248c7f9c0   Magnus Karlsson   samples/bpf: conv...
456
  	(void)arg;
d3f11b018   Jay Jayatheerthan   samples/bpf: xdps...
457
  	while (!is_benchmark_done()) {
248c7f9c0   Magnus Karlsson   samples/bpf: conv...
458
459
  		sleep(opt_interval);
  		dump_stats();
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
460
  	}
248c7f9c0   Magnus Karlsson   samples/bpf: conv...
461
  	return NULL;
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
462
  }
248c7f9c0   Magnus Karlsson   samples/bpf: conv...
463
  static void remove_xdp_program(void)
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
464
  {
2e5d72c15   Magnus Karlsson   samples/bpf: Add ...
465
  	u32 curr_prog_id = 0;
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
466

248c7f9c0   Magnus Karlsson   samples/bpf: conv...
467
468
469
470
  	if (bpf_get_link_xdp_id(opt_ifindex, &curr_prog_id, opt_xdp_flags)) {
  		printf("bpf_get_link_xdp_id failed
  ");
  		exit(EXIT_FAILURE);
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
471
  	}
248c7f9c0   Magnus Karlsson   samples/bpf: conv...
472
473
474
475
476
477
478
479
  	if (prog_id == curr_prog_id)
  		bpf_set_link_xdp_fd(opt_ifindex, -1, opt_xdp_flags);
  	else if (!curr_prog_id)
  		printf("couldn't find a prog id on a given interface
  ");
  	else
  		printf("program on interface changed, not removing
  ");
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
480
  }
248c7f9c0   Magnus Karlsson   samples/bpf: conv...
481
  static void int_exit(int sig)
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
482
  {
695255882   Jay Jayatheerthan   samples/bpf: xdps...
483
484
485
486
487
  	benchmark_done = true;
  }
  
  static void xdpsock_cleanup(void)
  {
248c7f9c0   Magnus Karlsson   samples/bpf: conv...
488
  	struct xsk_umem *umem = xsks[0]->umem->umem;
2e5d72c15   Magnus Karlsson   samples/bpf: Add ...
489
  	int i;
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
490

248c7f9c0   Magnus Karlsson   samples/bpf: conv...
491
  	dump_stats();
2e5d72c15   Magnus Karlsson   samples/bpf: Add ...
492
493
  	for (i = 0; i < num_socks; i++)
  		xsk_socket__delete(xsks[i]->xsk);
248c7f9c0   Magnus Karlsson   samples/bpf: conv...
494
495
  	(void)xsk_umem__delete(umem);
  	remove_xdp_program();
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
496
  }
248c7f9c0   Magnus Karlsson   samples/bpf: conv...
497
498
  static void __exit_with_error(int error, const char *file, const char *func,
  			      int line)
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
499
  {
248c7f9c0   Magnus Karlsson   samples/bpf: conv...
500
501
502
503
504
505
  	fprintf(stderr, "%s:%s:%i: errno: %d/\"%s\"
  ", file, func,
  		line, error, strerror(error));
  	dump_stats();
  	remove_xdp_program();
  	exit(EXIT_FAILURE);
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
506
  }
248c7f9c0   Magnus Karlsson   samples/bpf: conv...
507
508
  #define exit_with_error(error) __exit_with_error(error, __FILE__, __func__, \
  						 __LINE__)
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
509
510
511
512
513
514
515
516
517
518
519
  static void swap_mac_addresses(void *data)
  {
  	struct ether_header *eth = (struct ether_header *)data;
  	struct ether_addr *src_addr = (struct ether_addr *)&eth->ether_shost;
  	struct ether_addr *dst_addr = (struct ether_addr *)&eth->ether_dhost;
  	struct ether_addr tmp;
  
  	tmp = *src_addr;
  	*src_addr = *dst_addr;
  	*dst_addr = tmp;
  }
a412ef54f   Björn Töpel   samples/bpf: adap...
520
  static void hex_dump(void *pkt, size_t length, u64 addr)
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
521
  {
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
522
523
524
525
  	const unsigned char *address = (unsigned char *)pkt;
  	const unsigned char *line = address;
  	size_t line_size = 32;
  	unsigned char c;
a412ef54f   Björn Töpel   samples/bpf: adap...
526
527
  	char buf[32];
  	int i = 0;
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
528

a412ef54f   Björn Töpel   samples/bpf: adap...
529
530
531
532
  	if (!DEBUG_HEXDUMP)
  		return;
  
  	sprintf(buf, "addr=%llu", addr);
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
533
534
  	printf("length = %zu
  ", length);
a412ef54f   Björn Töpel   samples/bpf: adap...
535
  	printf("%s | ", buf);
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
  	while (length-- > 0) {
  		printf("%02X ", *address++);
  		if (!(++i % line_size) || (length == 0 && i % line_size)) {
  			if (length == 0) {
  				while (i++ % line_size)
  					printf("__ ");
  			}
  			printf(" | ");	/* right close */
  			while (line < address) {
  				c = *line++;
  				printf("%c", (c < 33 || c == 255) ? 0x2E : c);
  			}
  			printf("
  ");
  			if (length > 0)
a412ef54f   Björn Töpel   samples/bpf: adap...
551
  				printf("%s | ", buf);
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
552
553
554
555
556
  		}
  	}
  	printf("
  ");
  }
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
557

4a3c23ae3   Jay Jayatheerthan   samples/bpf: xdps...
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
  static void *memset32_htonl(void *dest, u32 val, u32 size)
  {
  	u32 *ptr = (u32 *)dest;
  	int i;
  
  	val = htonl(val);
  
  	for (i = 0; i < (size & (~0x3)); i += 4)
  		ptr[i >> 2] = val;
  
  	for (; i < size; i++)
  		((char *)dest)[i] = ((char *)&val)[i & 3];
  
  	return dest;
  }
  
  /*
   * This function code has been taken from
   * Linux kernel lib/checksum.c
   */
  static inline unsigned short from32to16(unsigned int x)
  {
  	/* add up 16-bit and 16-bit for 16+c bit */
  	x = (x & 0xffff) + (x >> 16);
  	/* add up carry.. */
  	x = (x & 0xffff) + (x >> 16);
  	return x;
  }
  
  /*
   * This function code has been taken from
   * Linux kernel lib/checksum.c
   */
  static unsigned int do_csum(const unsigned char *buff, int len)
  {
  	unsigned int result = 0;
  	int odd;
  
  	if (len <= 0)
  		goto out;
  	odd = 1 & (unsigned long)buff;
  	if (odd) {
  #ifdef __LITTLE_ENDIAN
  		result += (*buff << 8);
  #else
  		result = *buff;
  #endif
  		len--;
  		buff++;
  	}
  	if (len >= 2) {
  		if (2 & (unsigned long)buff) {
  			result += *(unsigned short *)buff;
  			len -= 2;
  			buff += 2;
  		}
  		if (len >= 4) {
  			const unsigned char *end = buff +
  						   ((unsigned int)len & ~3);
  			unsigned int carry = 0;
  
  			do {
  				unsigned int w = *(unsigned int *)buff;
  
  				buff += 4;
  				result += carry;
  				result += w;
  				carry = (w > result);
  			} while (buff < end);
  			result += carry;
  			result = (result & 0xffff) + (result >> 16);
  		}
  		if (len & 2) {
  			result += *(unsigned short *)buff;
  			buff += 2;
  		}
  	}
  	if (len & 1)
  #ifdef __LITTLE_ENDIAN
  		result += *buff;
  #else
  		result += (*buff << 8);
  #endif
  	result = from32to16(result);
  	if (odd)
  		result = ((result >> 8) & 0xff) | ((result & 0xff) << 8);
  out:
  	return result;
  }
  
  __sum16 ip_fast_csum(const void *iph, unsigned int ihl);
  
  /*
   *	This is a version of ip_compute_csum() optimized for IP headers,
   *	which always checksum on 4 octet boundaries.
   *	This function code has been taken from
   *	Linux kernel lib/checksum.c
   */
  __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
  {
  	return (__force __sum16)~do_csum(iph, ihl * 4);
  }
  
  /*
   * Fold a partial checksum
   * This function code has been taken from
   * Linux kernel include/asm-generic/checksum.h
   */
  static inline __sum16 csum_fold(__wsum csum)
  {
  	u32 sum = (__force u32)csum;
  
  	sum = (sum & 0xffff) + (sum >> 16);
  	sum = (sum & 0xffff) + (sum >> 16);
  	return (__force __sum16)~sum;
  }
  
  /*
   * This function code has been taken from
   * Linux kernel lib/checksum.c
   */
  static inline u32 from64to32(u64 x)
  {
  	/* add up 32-bit and 32-bit for 32+c bit */
  	x = (x & 0xffffffff) + (x >> 32);
  	/* add up carry.. */
  	x = (x & 0xffffffff) + (x >> 32);
  	return (u32)x;
  }
  
  __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
  			  __u32 len, __u8 proto, __wsum sum);
  
  /*
   * This function code has been taken from
   * Linux kernel lib/checksum.c
   */
  __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
  			  __u32 len, __u8 proto, __wsum sum)
  {
  	unsigned long long s = (__force u32)sum;
  
  	s += (__force u32)saddr;
  	s += (__force u32)daddr;
  #ifdef __BIG_ENDIAN__
  	s += proto + len;
  #else
  	s += (proto + len) << 8;
  #endif
  	return (__force __wsum)from64to32(s);
  }
  
  /*
   * This function has been taken from
   * Linux kernel include/asm-generic/checksum.h
   */
  static inline __sum16
  csum_tcpudp_magic(__be32 saddr, __be32 daddr, __u32 len,
  		  __u8 proto, __wsum sum)
  {
  	return csum_fold(csum_tcpudp_nofold(saddr, daddr, len, proto, sum));
  }
  
  static inline u16 udp_csum(u32 saddr, u32 daddr, u32 len,
  			   u8 proto, u16 *udp_pkt)
  {
  	u32 csum = 0;
  	u32 cnt = 0;
  
  	/* udp hdr and data */
  	for (; cnt < len; cnt += 2)
  		csum += udp_pkt[cnt >> 1];
  
  	return csum_tcpudp_magic(saddr, daddr, len, proto, csum);
  }
  
  #define ETH_FCS_SIZE 4
  
  #define PKT_HDR_SIZE (sizeof(struct ethhdr) + sizeof(struct iphdr) + \
  		      sizeof(struct udphdr))
  
  #define PKT_SIZE		(opt_pkt_size - ETH_FCS_SIZE)
  #define IP_PKT_SIZE		(PKT_SIZE - sizeof(struct ethhdr))
  #define UDP_PKT_SIZE		(IP_PKT_SIZE - sizeof(struct iphdr))
  #define UDP_PKT_DATA_SIZE	(UDP_PKT_SIZE - sizeof(struct udphdr))
  
  static u8 pkt_data[XSK_UMEM__DEFAULT_FRAME_SIZE];
  
  static void gen_eth_hdr_data(void)
  {
  	struct udphdr *udp_hdr = (struct udphdr *)(pkt_data +
  						   sizeof(struct ethhdr) +
  						   sizeof(struct iphdr));
  	struct iphdr *ip_hdr = (struct iphdr *)(pkt_data +
  						sizeof(struct ethhdr));
  	struct ethhdr *eth_hdr = (struct ethhdr *)pkt_data;
  
  	/* ethernet header */
  	memcpy(eth_hdr->h_dest, "\x3c\xfd\xfe\x9e\x7f\x71", ETH_ALEN);
  	memcpy(eth_hdr->h_source, "\xec\xb1\xd7\x98\x3a\xc0", ETH_ALEN);
  	eth_hdr->h_proto = htons(ETH_P_IP);
  
  	/* IP header */
  	ip_hdr->version = IPVERSION;
  	ip_hdr->ihl = 0x5; /* 20 byte header */
  	ip_hdr->tos = 0x0;
  	ip_hdr->tot_len = htons(IP_PKT_SIZE);
  	ip_hdr->id = 0;
  	ip_hdr->frag_off = 0;
  	ip_hdr->ttl = IPDEFTTL;
  	ip_hdr->protocol = IPPROTO_UDP;
  	ip_hdr->saddr = htonl(0x0a0a0a10);
  	ip_hdr->daddr = htonl(0x0a0a0a20);
  
  	/* IP header checksum */
  	ip_hdr->check = 0;
  	ip_hdr->check = ip_fast_csum((const void *)ip_hdr, ip_hdr->ihl);
  
  	/* UDP header */
  	udp_hdr->source = htons(0x1000);
  	udp_hdr->dest = htons(0x1000);
  	udp_hdr->len = htons(UDP_PKT_SIZE);
  
  	/* UDP data */
46e3268ea   Jay Jayatheerthan   samples/bpf: xdps...
782
  	memset32_htonl(pkt_data + PKT_HDR_SIZE, opt_pkt_fill_pattern,
4a3c23ae3   Jay Jayatheerthan   samples/bpf: xdps...
783
784
785
786
787
788
789
  		       UDP_PKT_DATA_SIZE);
  
  	/* UDP header checksum */
  	udp_hdr->check = 0;
  	udp_hdr->check = udp_csum(ip_hdr->saddr, ip_hdr->daddr, UDP_PKT_SIZE,
  				  IPPROTO_UDP, (u16 *)udp_hdr);
  }
cd9e72b6f   Jay Jayatheerthan   samples/bpf: xdps...
790
  static void gen_eth_frame(struct xsk_umem_info *umem, u64 addr)
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
791
  {
248c7f9c0   Magnus Karlsson   samples/bpf: conv...
792
  	memcpy(xsk_umem__get_data(umem->buffer, addr), pkt_data,
4a3c23ae3   Jay Jayatheerthan   samples/bpf: xdps...
793
  	       PKT_SIZE);
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
794
  }
248c7f9c0   Magnus Karlsson   samples/bpf: conv...
795
  static struct xsk_umem_info *xsk_configure_umem(void *buffer, u64 size)
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
796
  {
248c7f9c0   Magnus Karlsson   samples/bpf: conv...
797
  	struct xsk_umem_info *umem;
123e8da1d   Maxim Mikityanskiy   xsk: Change the d...
798
  	struct xsk_umem_config cfg = {
c8a039a47   Magnus Karlsson   samples/bpf: Opti...
799
800
801
802
803
804
805
806
807
808
  		/* We recommend that you set the fill ring size >= HW RX ring size +
  		 * AF_XDP RX ring size. Make sure you fill up the fill ring
  		 * with buffers at regular intervals, and you will with this setting
  		 * avoid allocation failures in the driver. These are usually quite
  		 * expensive since drivers have not been written to assume that
  		 * allocation failures are common. For regular sockets, kernel
  		 * allocated memory is used that only runs out in OOM situations
  		 * that should be rare.
  		 */
  		.fill_size = XSK_RING_PROD__DEFAULT_NUM_DESCS * 2,
123e8da1d   Maxim Mikityanskiy   xsk: Change the d...
809
810
811
  		.comp_size = XSK_RING_CONS__DEFAULT_NUM_DESCS,
  		.frame_size = opt_xsk_frame_size,
  		.frame_headroom = XSK_UMEM__DEFAULT_FRAME_HEADROOM,
c543f5469   Kevin Laatz   samples/bpf: add ...
812
  		.flags = opt_umem_flags
123e8da1d   Maxim Mikityanskiy   xsk: Change the d...
813
  	};
661842c46   Magnus Karlsson   samples/bpf: Use ...
814
  	int ret;
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
815
816
  
  	umem = calloc(1, sizeof(*umem));
248c7f9c0   Magnus Karlsson   samples/bpf: conv...
817
818
  	if (!umem)
  		exit_with_error(errno);
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
819

248c7f9c0   Magnus Karlsson   samples/bpf: conv...
820
  	ret = xsk_umem__create(&umem->umem, buffer, size, &umem->fq, &umem->cq,
123e8da1d   Maxim Mikityanskiy   xsk: Change the d...
821
  			       &cfg);
248c7f9c0   Magnus Karlsson   samples/bpf: conv...
822
823
  	if (ret)
  		exit_with_error(-ret);
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
824

661842c46   Magnus Karlsson   samples/bpf: Use ...
825
826
827
828
829
830
831
832
  	umem->buffer = buffer;
  	return umem;
  }
  
  static void xsk_populate_fill_ring(struct xsk_umem_info *umem)
  {
  	int ret, i;
  	u32 idx;
2e5d72c15   Magnus Karlsson   samples/bpf: Add ...
833
  	ret = xsk_ring_prod__reserve(&umem->fq,
c8a039a47   Magnus Karlsson   samples/bpf: Opti...
834
835
  				     XSK_RING_PROD__DEFAULT_NUM_DESCS * 2, &idx);
  	if (ret != XSK_RING_PROD__DEFAULT_NUM_DESCS * 2)
2e5d72c15   Magnus Karlsson   samples/bpf: Add ...
836
  		exit_with_error(-ret);
c8a039a47   Magnus Karlsson   samples/bpf: Opti...
837
  	for (i = 0; i < XSK_RING_PROD__DEFAULT_NUM_DESCS * 2; i++)
2e5d72c15   Magnus Karlsson   samples/bpf: Add ...
838
839
  		*xsk_ring_prod__fill_addr(&umem->fq, idx++) =
  			i * opt_xsk_frame_size;
c8a039a47   Magnus Karlsson   samples/bpf: Opti...
840
  	xsk_ring_prod__submit(&umem->fq, XSK_RING_PROD__DEFAULT_NUM_DESCS * 2);
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
841
  }
661842c46   Magnus Karlsson   samples/bpf: Use ...
842
843
  static struct xsk_socket_info *xsk_configure_socket(struct xsk_umem_info *umem,
  						    bool rx, bool tx)
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
844
  {
248c7f9c0   Magnus Karlsson   samples/bpf: conv...
845
846
  	struct xsk_socket_config cfg;
  	struct xsk_socket_info *xsk;
661842c46   Magnus Karlsson   samples/bpf: Use ...
847
848
  	struct xsk_ring_cons *rxr;
  	struct xsk_ring_prod *txr;
248c7f9c0   Magnus Karlsson   samples/bpf: conv...
849
  	int ret;
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
850
851
  
  	xsk = calloc(1, sizeof(*xsk));
248c7f9c0   Magnus Karlsson   samples/bpf: conv...
852
853
854
855
856
857
  	if (!xsk)
  		exit_with_error(errno);
  
  	xsk->umem = umem;
  	cfg.rx_size = XSK_RING_CONS__DEFAULT_NUM_DESCS;
  	cfg.tx_size = XSK_RING_PROD__DEFAULT_NUM_DESCS;
2e5d72c15   Magnus Karlsson   samples/bpf: Add ...
858
859
860
861
  	if (opt_num_xsks > 1)
  		cfg.libbpf_flags = XSK_LIBBPF_FLAGS__INHIBIT_PROG_LOAD;
  	else
  		cfg.libbpf_flags = 0;
248c7f9c0   Magnus Karlsson   samples/bpf: conv...
862
863
  	cfg.xdp_flags = opt_xdp_flags;
  	cfg.bind_flags = opt_xdp_bind_flags;
2e5d72c15   Magnus Karlsson   samples/bpf: Add ...
864

661842c46   Magnus Karlsson   samples/bpf: Use ...
865
866
867
868
  	rxr = rx ? &xsk->rx : NULL;
  	txr = tx ? &xsk->tx : NULL;
  	ret = xsk_socket__create(&xsk->xsk, opt_if, opt_queue, umem->umem,
  				 rxr, txr, &cfg);
248c7f9c0   Magnus Karlsson   samples/bpf: conv...
869
870
871
872
873
874
  	if (ret)
  		exit_with_error(-ret);
  
  	ret = bpf_get_link_xdp_id(opt_ifindex, &prog_id, opt_xdp_flags);
  	if (ret)
  		exit_with_error(-ret);
60dc609db   Ciara Loftus   samples: bpf: Cou...
875
876
877
878
879
880
881
882
883
884
  	xsk->app_stats.rx_empty_polls = 0;
  	xsk->app_stats.fill_fail_polls = 0;
  	xsk->app_stats.copy_tx_sendtos = 0;
  	xsk->app_stats.tx_wakeup_sendtos = 0;
  	xsk->app_stats.opt_polls = 0;
  	xsk->app_stats.prev_rx_empty_polls = 0;
  	xsk->app_stats.prev_fill_fail_polls = 0;
  	xsk->app_stats.prev_copy_tx_sendtos = 0;
  	xsk->app_stats.prev_tx_wakeup_sendtos = 0;
  	xsk->app_stats.prev_opt_polls = 0;
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
885
886
  	return xsk;
  }
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
887
888
889
890
891
892
893
  static struct option long_options[] = {
  	{"rxdrop", no_argument, 0, 'r'},
  	{"txonly", no_argument, 0, 't'},
  	{"l2fwd", no_argument, 0, 'l'},
  	{"interface", required_argument, 0, 'i'},
  	{"queue", required_argument, 0, 'q'},
  	{"poll", no_argument, 0, 'p'},
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
894
895
896
  	{"xdp-skb", no_argument, 0, 'S'},
  	{"xdp-native", no_argument, 0, 'N'},
  	{"interval", required_argument, 0, 'n'},
58c50ae4a   Björn Töpel   samples/bpf: add ...
897
898
  	{"zero-copy", no_argument, 0, 'z'},
  	{"copy", no_argument, 0, 'c'},
123e8da1d   Maxim Mikityanskiy   xsk: Change the d...
899
  	{"frame-size", required_argument, 0, 'f'},
46738f73e   Magnus Karlsson   samples/bpf: add ...
900
  	{"no-need-wakeup", no_argument, 0, 'm'},
c543f5469   Kevin Laatz   samples/bpf: add ...
901
  	{"unaligned", no_argument, 0, 'u'},
2e5d72c15   Magnus Karlsson   samples/bpf: Add ...
902
  	{"shared-umem", no_argument, 0, 'M'},
b31333298   Andre Guedes   samples/bpf: Add ...
903
  	{"force", no_argument, 0, 'F'},
d3f11b018   Jay Jayatheerthan   samples/bpf: xdps...
904
  	{"duration", required_argument, 0, 'd'},
cd9e72b6f   Jay Jayatheerthan   samples/bpf: xdps...
905
  	{"batch-size", required_argument, 0, 'b'},
ece6e9694   Jay Jayatheerthan   samples/bpf: xdps...
906
  	{"tx-pkt-count", required_argument, 0, 'C'},
4a3c23ae3   Jay Jayatheerthan   samples/bpf: xdps...
907
  	{"tx-pkt-size", required_argument, 0, 's'},
46e3268ea   Jay Jayatheerthan   samples/bpf: xdps...
908
  	{"tx-pkt-pattern", required_argument, 0, 'P'},
b36c3206f   Ciara Loftus   samples: bpf: Add...
909
  	{"extra-stats", no_argument, 0, 'x'},
74e00676d   Magnus Karlsson   samples/bpf: Add ...
910
  	{"quiet", no_argument, 0, 'Q'},
60dc609db   Ciara Loftus   samples: bpf: Cou...
911
  	{"app-stats", no_argument, 0, 'a'},
67ed37553   Ciara Loftus   samples: bpf: Dri...
912
  	{"irq-string", no_argument, 0, 'I'},
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
  	{0, 0, 0, 0}
  };
  
  static void usage(const char *prog)
  {
  	const char *str =
  		"  Usage: %s [OPTIONS]
  "
  		"  Options:
  "
  		"  -r, --rxdrop		Discard all incoming packets (default)
  "
  		"  -t, --txonly		Only send packets
  "
  		"  -l, --l2fwd		MAC swap L2 forwarding
  "
  		"  -i, --interface=n	Run on interface n
  "
  		"  -q, --queue=n	Use queue n (default 0)
  "
  		"  -p, --poll		Use poll syscall
  "
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
935
936
  		"  -S, --xdp-skb=n	Use XDP skb-mod
  "
4564a8bb5   Anton Ivanov   samples/bpf: Triv...
937
938
  		"  -N, --xdp-native=n	Enforce XDP native mode
  "
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
939
940
  		"  -n, --interval=n	Specify statistics update interval (default 1 sec).
  "
58c50ae4a   Björn Töpel   samples/bpf: add ...
941
942
943
944
  		"  -z, --zero-copy      Force zero-copy mode.
  "
  		"  -c, --copy           Force copy mode.
  "
46738f73e   Magnus Karlsson   samples/bpf: add ...
945
946
  		"  -m, --no-need-wakeup Turn off use of driver need wakeup flag.
  "
c543f5469   Kevin Laatz   samples/bpf: add ...
947
948
949
950
  		"  -f, --frame-size=n   Set the frame size (must be a power of two in aligned mode, default is %d).
  "
  		"  -u, --unaligned	Enable unaligned chunk placement
  "
2e5d72c15   Magnus Karlsson   samples/bpf: Add ...
951
952
  		"  -M, --shared-umem	Enable XDP_SHARED_UMEM
  "
b31333298   Andre Guedes   samples/bpf: Add ...
953
954
  		"  -F, --force		Force loading the XDP prog
  "
d3f11b018   Jay Jayatheerthan   samples/bpf: xdps...
955
956
957
958
  		"  -d, --duration=n	Duration in secs to run command.
  "
  		"			Default: forever.
  "
cd9e72b6f   Jay Jayatheerthan   samples/bpf: xdps...
959
960
961
962
  		"  -b, --batch-size=n	Batch size for sending or receiving
  "
  		"			packets. Default: %d
  "
ece6e9694   Jay Jayatheerthan   samples/bpf: xdps...
963
964
965
966
  		"  -C, --tx-pkt-count=n	Number of packets to send.
  "
  		"			Default: Continuous packets.
  "
4a3c23ae3   Jay Jayatheerthan   samples/bpf: xdps...
967
968
969
970
971
972
  		"  -s, --tx-pkt-size=n	Transmit packet size.
  "
  		"			(Default: %d bytes)
  "
  		"			Min size: %d, Max size %d.
  "
46e3268ea   Jay Jayatheerthan   samples/bpf: xdps...
973
974
  		"  -P, --tx-pkt-pattern=nPacket fill pattern. Default: 0x%x
  "
b36c3206f   Ciara Loftus   samples: bpf: Add...
975
976
  		"  -x, --extra-stats	Display extra statistics.
  "
74e00676d   Magnus Karlsson   samples/bpf: Add ...
977
978
  		"  -Q, --quiet          Do not display any stats.
  "
60dc609db   Ciara Loftus   samples: bpf: Cou...
979
980
  		"  -a, --app-stats	Display application (syscall) statistics.
  "
67ed37553   Ciara Loftus   samples: bpf: Dri...
981
982
  		"  -I, --irq-string	Display driver interrupt statistics for interface associated with irq-string.
  "
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
983
984
  		"
  ";
cd9e72b6f   Jay Jayatheerthan   samples/bpf: xdps...
985
  	fprintf(stderr, str, prog, XSK_UMEM__DEFAULT_FRAME_SIZE,
4a3c23ae3   Jay Jayatheerthan   samples/bpf: xdps...
986
  		opt_batch_size, MIN_PKT_SIZE, MIN_PKT_SIZE,
46e3268ea   Jay Jayatheerthan   samples/bpf: xdps...
987
  		XSK_UMEM__DEFAULT_FRAME_SIZE, opt_pkt_fill_pattern);
4a3c23ae3   Jay Jayatheerthan   samples/bpf: xdps...
988

b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
989
990
991
992
993
994
995
996
997
998
  	exit(EXIT_FAILURE);
  }
  
  static void parse_command_line(int argc, char **argv)
  {
  	int option_index, c;
  
  	opterr = 0;
  
  	for (;;) {
67ed37553   Ciara Loftus   samples: bpf: Dri...
999
  		c = getopt_long(argc, argv, "Frtli:q:pSNn:czf:muMd:b:C:s:P:xQaI:",
46738f73e   Magnus Karlsson   samples/bpf: add ...
1000
  				long_options, &option_index);
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
  		if (c == -1)
  			break;
  
  		switch (c) {
  		case 'r':
  			opt_bench = BENCH_RXDROP;
  			break;
  		case 't':
  			opt_bench = BENCH_TXONLY;
  			break;
  		case 'l':
  			opt_bench = BENCH_L2FWD;
  			break;
  		case 'i':
  			opt_if = optarg;
  			break;
  		case 'q':
  			opt_queue = atoi(optarg);
  			break;
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1020
1021
1022
1023
1024
  		case 'p':
  			opt_poll = 1;
  			break;
  		case 'S':
  			opt_xdp_flags |= XDP_FLAGS_SKB_MODE;
9f5232cc7   Björn Töpel   samples/bpf: xdps...
1025
  			opt_xdp_bind_flags |= XDP_COPY;
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1026
1027
  			break;
  		case 'N':
d50ecc46d   Toke Høiland-Jørgensen   samples/bpf: Atta...
1028
  			/* default, set below */
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1029
1030
1031
1032
  			break;
  		case 'n':
  			opt_interval = atoi(optarg);
  			break;
58c50ae4a   Björn Töpel   samples/bpf: add ...
1033
1034
1035
1036
1037
1038
  		case 'z':
  			opt_xdp_bind_flags |= XDP_ZEROCOPY;
  			break;
  		case 'c':
  			opt_xdp_bind_flags |= XDP_COPY;
  			break;
c543f5469   Kevin Laatz   samples/bpf: add ...
1039
1040
1041
  		case 'u':
  			opt_umem_flags |= XDP_UMEM_UNALIGNED_CHUNK_FLAG;
  			opt_unaligned_chunks = 1;
3945b37a9   Kevin Laatz   samples/bpf: use ...
1042
  			opt_mmap_flags = MAP_HUGETLB;
c543f5469   Kevin Laatz   samples/bpf: add ...
1043
  			break;
743e568c1   Maciej Fijalkowski   samples/bpf: Add ...
1044
1045
1046
  		case 'F':
  			opt_xdp_flags &= ~XDP_FLAGS_UPDATE_IF_NOEXIST;
  			break;
123e8da1d   Maxim Mikityanskiy   xsk: Change the d...
1047
1048
  		case 'f':
  			opt_xsk_frame_size = atoi(optarg);
2e5d72c15   Magnus Karlsson   samples/bpf: Add ...
1049
  			break;
46738f73e   Magnus Karlsson   samples/bpf: add ...
1050
1051
1052
  		case 'm':
  			opt_need_wakeup = false;
  			opt_xdp_bind_flags &= ~XDP_USE_NEED_WAKEUP;
123e8da1d   Maxim Mikityanskiy   xsk: Change the d...
1053
  			break;
2e5d72c15   Magnus Karlsson   samples/bpf: Add ...
1054
1055
1056
  		case 'M':
  			opt_num_xsks = MAX_SOCKS;
  			break;
d3f11b018   Jay Jayatheerthan   samples/bpf: xdps...
1057
1058
1059
1060
  		case 'd':
  			opt_duration = atoi(optarg);
  			opt_duration *= 1000000000;
  			break;
cd9e72b6f   Jay Jayatheerthan   samples/bpf: xdps...
1061
1062
1063
  		case 'b':
  			opt_batch_size = atoi(optarg);
  			break;
ece6e9694   Jay Jayatheerthan   samples/bpf: xdps...
1064
1065
1066
  		case 'C':
  			opt_pkt_count = atoi(optarg);
  			break;
4a3c23ae3   Jay Jayatheerthan   samples/bpf: xdps...
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
  		case 's':
  			opt_pkt_size = atoi(optarg);
  			if (opt_pkt_size > (XSK_UMEM__DEFAULT_FRAME_SIZE) ||
  			    opt_pkt_size < MIN_PKT_SIZE) {
  				fprintf(stderr,
  					"ERROR: Invalid frame size %d
  ",
  					opt_pkt_size);
  				usage(basename(argv[0]));
  			}
  			break;
46e3268ea   Jay Jayatheerthan   samples/bpf: xdps...
1078
1079
1080
  		case 'P':
  			opt_pkt_fill_pattern = strtol(optarg, NULL, 16);
  			break;
b36c3206f   Ciara Loftus   samples: bpf: Add...
1081
1082
1083
  		case 'x':
  			opt_extra_stats = 1;
  			break;
74e00676d   Magnus Karlsson   samples/bpf: Add ...
1084
1085
1086
  		case 'Q':
  			opt_quiet = 1;
  			break;
60dc609db   Ciara Loftus   samples: bpf: Cou...
1087
1088
1089
  		case 'a':
  			opt_app_stats = 1;
  			break;
67ed37553   Ciara Loftus   samples: bpf: Dri...
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
  		case 'I':
  			opt_irq_str = optarg;
  			if (get_interrupt_number())
  				irqs_at_init = get_irqs();
  			if (irqs_at_init < 0) {
  				fprintf(stderr, "ERROR: Failed to get irqs for %s
  ", opt_irq_str);
  				usage(basename(argv[0]));
  			}
  
  			break;
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1101
1102
1103
1104
  		default:
  			usage(basename(argv[0]));
  		}
  	}
d50ecc46d   Toke Høiland-Jørgensen   samples/bpf: Atta...
1105
1106
  	if (!(opt_xdp_flags & XDP_FLAGS_SKB_MODE))
  		opt_xdp_flags |= XDP_FLAGS_DRV_MODE;
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1107
1108
1109
1110
1111
1112
1113
  	opt_ifindex = if_nametoindex(opt_if);
  	if (!opt_ifindex) {
  		fprintf(stderr, "ERROR: interface \"%s\" does not exist
  ",
  			opt_if);
  		usage(basename(argv[0]));
  	}
248c7f9c0   Magnus Karlsson   samples/bpf: conv...
1114

c543f5469   Kevin Laatz   samples/bpf: add ...
1115
1116
  	if ((opt_xsk_frame_size & (opt_xsk_frame_size - 1)) &&
  	    !opt_unaligned_chunks) {
123e8da1d   Maxim Mikityanskiy   xsk: Change the d...
1117
1118
1119
1120
1121
  		fprintf(stderr, "--frame-size=%d is not a power of two
  ",
  			opt_xsk_frame_size);
  		usage(basename(argv[0]));
  	}
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1122
  }
248c7f9c0   Magnus Karlsson   samples/bpf: conv...
1123
  static void kick_tx(struct xsk_socket_info *xsk)
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1124
1125
  {
  	int ret;
248c7f9c0   Magnus Karlsson   samples/bpf: conv...
1126
  	ret = sendto(xsk_socket__fd(xsk->xsk), NULL, 0, MSG_DONTWAIT, NULL, 0);
8ed47e140   Maciej Fijalkowski   samples: bpf: All...
1127
1128
  	if (ret >= 0 || errno == ENOBUFS || errno == EAGAIN ||
  	    errno == EBUSY || errno == ENETDOWN)
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1129
  		return;
248c7f9c0   Magnus Karlsson   samples/bpf: conv...
1130
  	exit_with_error(errno);
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1131
  }
46738f73e   Magnus Karlsson   samples/bpf: add ...
1132
1133
  static inline void complete_tx_l2fwd(struct xsk_socket_info *xsk,
  				     struct pollfd *fds)
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1134
  {
03895e63f   Kevin Laatz   samples/bpf: add ...
1135
  	struct xsk_umem_info *umem = xsk->umem;
b74e21ab7   Yonghong Song   samples/bpf: sile...
1136
  	u32 idx_cq = 0, idx_fq = 0;
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1137
1138
1139
1140
1141
  	unsigned int rcvd;
  	size_t ndescs;
  
  	if (!xsk->outstanding_tx)
  		return;
3131cf66d   Magnus Karlsson   samples/bpf: Fix ...
1142
1143
1144
1145
1146
  	/* In copy mode, Tx is driven by a syscall so we need to use e.g. sendto() to
  	 * really send the packets. In zero-copy mode we do not have to do this, since Tx
  	 * is driven by the NAPI loop. So as an optimization, we do not have to call
  	 * sendto() all the time in zero-copy mode for l2fwd.
  	 */
60dc609db   Ciara Loftus   samples: bpf: Cou...
1147
1148
  	if (opt_xdp_bind_flags & XDP_COPY) {
  		xsk->app_stats.copy_tx_sendtos++;
3131cf66d   Magnus Karlsson   samples/bpf: Fix ...
1149
  		kick_tx(xsk);
60dc609db   Ciara Loftus   samples: bpf: Cou...
1150
  	}
3131cf66d   Magnus Karlsson   samples/bpf: Fix ...
1151

cd9e72b6f   Jay Jayatheerthan   samples/bpf: xdps...
1152
  	ndescs = (xsk->outstanding_tx > opt_batch_size) ? opt_batch_size :
248c7f9c0   Magnus Karlsson   samples/bpf: conv...
1153
  		xsk->outstanding_tx;
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1154
1155
  
  	/* re-add completed Tx buffers */
03895e63f   Kevin Laatz   samples/bpf: add ...
1156
  	rcvd = xsk_ring_cons__peek(&umem->cq, ndescs, &idx_cq);
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1157
  	if (rcvd > 0) {
248c7f9c0   Magnus Karlsson   samples/bpf: conv...
1158
1159
  		unsigned int i;
  		int ret;
03895e63f   Kevin Laatz   samples/bpf: add ...
1160
  		ret = xsk_ring_prod__reserve(&umem->fq, rcvd, &idx_fq);
248c7f9c0   Magnus Karlsson   samples/bpf: conv...
1161
1162
1163
  		while (ret != rcvd) {
  			if (ret < 0)
  				exit_with_error(-ret);
60dc609db   Ciara Loftus   samples: bpf: Cou...
1164
1165
  			if (xsk_ring_prod__needs_wakeup(&umem->fq)) {
  				xsk->app_stats.fill_fail_polls++;
46738f73e   Magnus Karlsson   samples/bpf: add ...
1166
  				ret = poll(fds, num_socks, opt_timeout);
60dc609db   Ciara Loftus   samples: bpf: Cou...
1167
  			}
03895e63f   Kevin Laatz   samples/bpf: add ...
1168
  			ret = xsk_ring_prod__reserve(&umem->fq, rcvd, &idx_fq);
248c7f9c0   Magnus Karlsson   samples/bpf: conv...
1169
  		}
03895e63f   Kevin Laatz   samples/bpf: add ...
1170

248c7f9c0   Magnus Karlsson   samples/bpf: conv...
1171
  		for (i = 0; i < rcvd; i++)
03895e63f   Kevin Laatz   samples/bpf: add ...
1172
1173
  			*xsk_ring_prod__fill_addr(&umem->fq, idx_fq++) =
  				*xsk_ring_cons__comp_addr(&umem->cq, idx_cq++);
248c7f9c0   Magnus Karlsson   samples/bpf: conv...
1174
1175
1176
  
  		xsk_ring_prod__submit(&xsk->umem->fq, rcvd);
  		xsk_ring_cons__release(&xsk->umem->cq, rcvd);
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1177
  		xsk->outstanding_tx -= rcvd;
2e8806f03   Ciara Loftus   samples: bpf: Spl...
1178
  		xsk->ring_stats.tx_npkts += rcvd;
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1179
1180
  	}
  }
ece6e9694   Jay Jayatheerthan   samples/bpf: xdps...
1181
1182
  static inline void complete_tx_only(struct xsk_socket_info *xsk,
  				    int batch_size)
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1183
  {
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1184
  	unsigned int rcvd;
248c7f9c0   Magnus Karlsson   samples/bpf: conv...
1185
  	u32 idx;
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1186
1187
1188
  
  	if (!xsk->outstanding_tx)
  		return;
60dc609db   Ciara Loftus   samples: bpf: Cou...
1189
1190
  	if (!opt_need_wakeup || xsk_ring_prod__needs_wakeup(&xsk->tx)) {
  		xsk->app_stats.tx_wakeup_sendtos++;
46738f73e   Magnus Karlsson   samples/bpf: add ...
1191
  		kick_tx(xsk);
60dc609db   Ciara Loftus   samples: bpf: Cou...
1192
  	}
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1193

ece6e9694   Jay Jayatheerthan   samples/bpf: xdps...
1194
  	rcvd = xsk_ring_cons__peek(&xsk->umem->cq, batch_size, &idx);
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1195
  	if (rcvd > 0) {
248c7f9c0   Magnus Karlsson   samples/bpf: conv...
1196
  		xsk_ring_cons__release(&xsk->umem->cq, rcvd);
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1197
  		xsk->outstanding_tx -= rcvd;
2e8806f03   Ciara Loftus   samples: bpf: Spl...
1198
  		xsk->ring_stats.tx_npkts += rcvd;
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1199
1200
  	}
  }
46738f73e   Magnus Karlsson   samples/bpf: add ...
1201
  static void rx_drop(struct xsk_socket_info *xsk, struct pollfd *fds)
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1202
  {
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1203
  	unsigned int rcvd, i;
b74e21ab7   Yonghong Song   samples/bpf: sile...
1204
  	u32 idx_rx = 0, idx_fq = 0;
248c7f9c0   Magnus Karlsson   samples/bpf: conv...
1205
  	int ret;
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1206

cd9e72b6f   Jay Jayatheerthan   samples/bpf: xdps...
1207
  	rcvd = xsk_ring_cons__peek(&xsk->rx, opt_batch_size, &idx_rx);
46738f73e   Magnus Karlsson   samples/bpf: add ...
1208
  	if (!rcvd) {
60dc609db   Ciara Loftus   samples: bpf: Cou...
1209
1210
  		if (xsk_ring_prod__needs_wakeup(&xsk->umem->fq)) {
  			xsk->app_stats.rx_empty_polls++;
46738f73e   Magnus Karlsson   samples/bpf: add ...
1211
  			ret = poll(fds, num_socks, opt_timeout);
60dc609db   Ciara Loftus   samples: bpf: Cou...
1212
  		}
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1213
  		return;
46738f73e   Magnus Karlsson   samples/bpf: add ...
1214
  	}
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1215

248c7f9c0   Magnus Karlsson   samples/bpf: conv...
1216
1217
1218
1219
  	ret = xsk_ring_prod__reserve(&xsk->umem->fq, rcvd, &idx_fq);
  	while (ret != rcvd) {
  		if (ret < 0)
  			exit_with_error(-ret);
60dc609db   Ciara Loftus   samples: bpf: Cou...
1220
1221
  		if (xsk_ring_prod__needs_wakeup(&xsk->umem->fq)) {
  			xsk->app_stats.fill_fail_polls++;
46738f73e   Magnus Karlsson   samples/bpf: add ...
1222
  			ret = poll(fds, num_socks, opt_timeout);
60dc609db   Ciara Loftus   samples: bpf: Cou...
1223
  		}
248c7f9c0   Magnus Karlsson   samples/bpf: conv...
1224
1225
  		ret = xsk_ring_prod__reserve(&xsk->umem->fq, rcvd, &idx_fq);
  	}
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1226
  	for (i = 0; i < rcvd; i++) {
248c7f9c0   Magnus Karlsson   samples/bpf: conv...
1227
1228
  		u64 addr = xsk_ring_cons__rx_desc(&xsk->rx, idx_rx)->addr;
  		u32 len = xsk_ring_cons__rx_desc(&xsk->rx, idx_rx++)->len;
03895e63f   Kevin Laatz   samples/bpf: add ...
1229
1230
1231
  		u64 orig = xsk_umem__extract_addr(addr);
  
  		addr = xsk_umem__add_offset_to_addr(addr);
248c7f9c0   Magnus Karlsson   samples/bpf: conv...
1232
  		char *pkt = xsk_umem__get_data(xsk->umem->buffer, addr);
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1233

248c7f9c0   Magnus Karlsson   samples/bpf: conv...
1234
  		hex_dump(pkt, len, addr);
03895e63f   Kevin Laatz   samples/bpf: add ...
1235
  		*xsk_ring_prod__fill_addr(&xsk->umem->fq, idx_fq++) = orig;
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1236
  	}
248c7f9c0   Magnus Karlsson   samples/bpf: conv...
1237
1238
  	xsk_ring_prod__submit(&xsk->umem->fq, rcvd);
  	xsk_ring_cons__release(&xsk->rx, rcvd);
2e8806f03   Ciara Loftus   samples: bpf: Spl...
1239
  	xsk->ring_stats.rx_npkts += rcvd;
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1240
1241
1242
1243
  }
  
  static void rx_drop_all(void)
  {
2e5d72c15   Magnus Karlsson   samples/bpf: Add ...
1244
  	struct pollfd fds[MAX_SOCKS] = {};
46738f73e   Magnus Karlsson   samples/bpf: add ...
1245
  	int i, ret;
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1246

b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1247
  	for (i = 0; i < num_socks; i++) {
248c7f9c0   Magnus Karlsson   samples/bpf: conv...
1248
  		fds[i].fd = xsk_socket__fd(xsks[i]->xsk);
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1249
  		fds[i].events = POLLIN;
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1250
1251
1252
1253
  	}
  
  	for (;;) {
  		if (opt_poll) {
60dc609db   Ciara Loftus   samples: bpf: Cou...
1254
1255
  			for (i = 0; i < num_socks; i++)
  				xsks[i]->app_stats.opt_polls++;
46738f73e   Magnus Karlsson   samples/bpf: add ...
1256
  			ret = poll(fds, num_socks, opt_timeout);
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1257
1258
1259
1260
1261
  			if (ret <= 0)
  				continue;
  		}
  
  		for (i = 0; i < num_socks; i++)
46738f73e   Magnus Karlsson   samples/bpf: add ...
1262
  			rx_drop(xsks[i], fds);
d3f11b018   Jay Jayatheerthan   samples/bpf: xdps...
1263
1264
1265
  
  		if (benchmark_done)
  			break;
46738f73e   Magnus Karlsson   samples/bpf: add ...
1266
1267
  	}
  }
b69e56cf7   Weqaar Janjua   samples/bpf: Fix ...
1268
  static void tx_only(struct xsk_socket_info *xsk, u32 *frame_nb, int batch_size)
46738f73e   Magnus Karlsson   samples/bpf: add ...
1269
1270
  {
  	u32 idx;
cd9e72b6f   Jay Jayatheerthan   samples/bpf: xdps...
1271
  	unsigned int i;
46738f73e   Magnus Karlsson   samples/bpf: add ...
1272

ece6e9694   Jay Jayatheerthan   samples/bpf: xdps...
1273
1274
1275
  	while (xsk_ring_prod__reserve(&xsk->tx, batch_size, &idx) <
  				      batch_size) {
  		complete_tx_only(xsk, batch_size);
81ef603e8   Magnus Karlsson   samples/bpf: Fix ...
1276
1277
  		if (benchmark_done)
  			return;
cd9e72b6f   Jay Jayatheerthan   samples/bpf: xdps...
1278
  	}
46738f73e   Magnus Karlsson   samples/bpf: add ...
1279

ece6e9694   Jay Jayatheerthan   samples/bpf: xdps...
1280
  	for (i = 0; i < batch_size; i++) {
cd9e72b6f   Jay Jayatheerthan   samples/bpf: xdps...
1281
1282
  		struct xdp_desc *tx_desc = xsk_ring_prod__tx_desc(&xsk->tx,
  								  idx + i);
b69e56cf7   Weqaar Janjua   samples/bpf: Fix ...
1283
  		tx_desc->addr = (*frame_nb + i) << XSK_UMEM__DEFAULT_FRAME_SHIFT;
4a3c23ae3   Jay Jayatheerthan   samples/bpf: xdps...
1284
  		tx_desc->len = PKT_SIZE;
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1285
  	}
46738f73e   Magnus Karlsson   samples/bpf: add ...
1286

ece6e9694   Jay Jayatheerthan   samples/bpf: xdps...
1287
1288
  	xsk_ring_prod__submit(&xsk->tx, batch_size);
  	xsk->outstanding_tx += batch_size;
b69e56cf7   Weqaar Janjua   samples/bpf: Fix ...
1289
1290
  	*frame_nb += batch_size;
  	*frame_nb %= NUM_FRAMES;
ece6e9694   Jay Jayatheerthan   samples/bpf: xdps...
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
  	complete_tx_only(xsk, batch_size);
  }
  
  static inline int get_batch_size(int pkt_cnt)
  {
  	if (!opt_pkt_count)
  		return opt_batch_size;
  
  	if (pkt_cnt + opt_batch_size <= opt_pkt_count)
  		return opt_batch_size;
  
  	return opt_pkt_count - pkt_cnt;
  }
  
  static void complete_tx_only_all(void)
  {
  	bool pending;
  	int i;
  
  	do {
  		pending = false;
  		for (i = 0; i < num_socks; i++) {
  			if (xsks[i]->outstanding_tx) {
  				complete_tx_only(xsks[i], opt_batch_size);
  				pending = !!xsks[i]->outstanding_tx;
  			}
  		}
  	} while (pending);
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1319
  }
46738f73e   Magnus Karlsson   samples/bpf: add ...
1320
  static void tx_only_all(void)
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1321
  {
2e5d72c15   Magnus Karlsson   samples/bpf: Add ...
1322
  	struct pollfd fds[MAX_SOCKS] = {};
46738f73e   Magnus Karlsson   samples/bpf: add ...
1323
  	u32 frame_nb[MAX_SOCKS] = {};
ece6e9694   Jay Jayatheerthan   samples/bpf: xdps...
1324
  	int pkt_cnt = 0;
46738f73e   Magnus Karlsson   samples/bpf: add ...
1325
  	int i, ret;
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1326

46738f73e   Magnus Karlsson   samples/bpf: add ...
1327
1328
1329
1330
  	for (i = 0; i < num_socks; i++) {
  		fds[0].fd = xsk_socket__fd(xsks[i]->xsk);
  		fds[0].events = POLLOUT;
  	}
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1331

ece6e9694   Jay Jayatheerthan   samples/bpf: xdps...
1332
1333
  	while ((opt_pkt_count && pkt_cnt < opt_pkt_count) || !opt_pkt_count) {
  		int batch_size = get_batch_size(pkt_cnt);
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1334
  		if (opt_poll) {
60dc609db   Ciara Loftus   samples: bpf: Cou...
1335
1336
  			for (i = 0; i < num_socks; i++)
  				xsks[i]->app_stats.opt_polls++;
46738f73e   Magnus Karlsson   samples/bpf: add ...
1337
  			ret = poll(fds, num_socks, opt_timeout);
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1338
1339
  			if (ret <= 0)
  				continue;
248c7f9c0   Magnus Karlsson   samples/bpf: conv...
1340
  			if (!(fds[0].revents & POLLOUT))
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1341
1342
  				continue;
  		}
46738f73e   Magnus Karlsson   samples/bpf: add ...
1343
  		for (i = 0; i < num_socks; i++)
b69e56cf7   Weqaar Janjua   samples/bpf: Fix ...
1344
  			tx_only(xsks[i], &frame_nb[i], batch_size);
ece6e9694   Jay Jayatheerthan   samples/bpf: xdps...
1345
1346
  
  		pkt_cnt += batch_size;
d3f11b018   Jay Jayatheerthan   samples/bpf: xdps...
1347
1348
1349
  
  		if (benchmark_done)
  			break;
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1350
  	}
ece6e9694   Jay Jayatheerthan   samples/bpf: xdps...
1351
1352
1353
  
  	if (opt_pkt_count)
  		complete_tx_only_all();
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1354
  }
46738f73e   Magnus Karlsson   samples/bpf: add ...
1355
  static void l2fwd(struct xsk_socket_info *xsk, struct pollfd *fds)
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1356
  {
46738f73e   Magnus Karlsson   samples/bpf: add ...
1357
1358
1359
  	unsigned int rcvd, i;
  	u32 idx_rx = 0, idx_tx = 0;
  	int ret;
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1360

46738f73e   Magnus Karlsson   samples/bpf: add ...
1361
  	complete_tx_l2fwd(xsk, fds);
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1362

cd9e72b6f   Jay Jayatheerthan   samples/bpf: xdps...
1363
  	rcvd = xsk_ring_cons__peek(&xsk->rx, opt_batch_size, &idx_rx);
46738f73e   Magnus Karlsson   samples/bpf: add ...
1364
  	if (!rcvd) {
60dc609db   Ciara Loftus   samples: bpf: Cou...
1365
1366
  		if (xsk_ring_prod__needs_wakeup(&xsk->umem->fq)) {
  			xsk->app_stats.rx_empty_polls++;
46738f73e   Magnus Karlsson   samples/bpf: add ...
1367
  			ret = poll(fds, num_socks, opt_timeout);
60dc609db   Ciara Loftus   samples: bpf: Cou...
1368
  		}
46738f73e   Magnus Karlsson   samples/bpf: add ...
1369
1370
  		return;
  	}
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1371

46738f73e   Magnus Karlsson   samples/bpf: add ...
1372
1373
1374
1375
  	ret = xsk_ring_prod__reserve(&xsk->tx, rcvd, &idx_tx);
  	while (ret != rcvd) {
  		if (ret < 0)
  			exit_with_error(-ret);
5a2a0dd88   Magnus Karlsson   samples/bpf: Fix ...
1376
  		complete_tx_l2fwd(xsk, fds);
60dc609db   Ciara Loftus   samples: bpf: Cou...
1377
1378
  		if (xsk_ring_prod__needs_wakeup(&xsk->tx)) {
  			xsk->app_stats.tx_wakeup_sendtos++;
46738f73e   Magnus Karlsson   samples/bpf: add ...
1379
  			kick_tx(xsk);
60dc609db   Ciara Loftus   samples: bpf: Cou...
1380
  		}
248c7f9c0   Magnus Karlsson   samples/bpf: conv...
1381
  		ret = xsk_ring_prod__reserve(&xsk->tx, rcvd, &idx_tx);
46738f73e   Magnus Karlsson   samples/bpf: add ...
1382
1383
1384
1385
1386
  	}
  
  	for (i = 0; i < rcvd; i++) {
  		u64 addr = xsk_ring_cons__rx_desc(&xsk->rx, idx_rx)->addr;
  		u32 len = xsk_ring_cons__rx_desc(&xsk->rx, idx_rx++)->len;
5a712e136   Ciara Loftus   samples/bpf: fix ...
1387
  		u64 orig = addr;
03895e63f   Kevin Laatz   samples/bpf: add ...
1388
1389
  
  		addr = xsk_umem__add_offset_to_addr(addr);
46738f73e   Magnus Karlsson   samples/bpf: add ...
1390
1391
1392
  		char *pkt = xsk_umem__get_data(xsk->umem->buffer, addr);
  
  		swap_mac_addresses(pkt);
248c7f9c0   Magnus Karlsson   samples/bpf: conv...
1393

46738f73e   Magnus Karlsson   samples/bpf: add ...
1394
  		hex_dump(pkt, len, addr);
03895e63f   Kevin Laatz   samples/bpf: add ...
1395
  		xsk_ring_prod__tx_desc(&xsk->tx, idx_tx)->addr = orig;
46738f73e   Magnus Karlsson   samples/bpf: add ...
1396
1397
  		xsk_ring_prod__tx_desc(&xsk->tx, idx_tx++)->len = len;
  	}
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1398

46738f73e   Magnus Karlsson   samples/bpf: add ...
1399
1400
  	xsk_ring_prod__submit(&xsk->tx, rcvd);
  	xsk_ring_cons__release(&xsk->rx, rcvd);
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1401

2e8806f03   Ciara Loftus   samples: bpf: Spl...
1402
  	xsk->ring_stats.rx_npkts += rcvd;
46738f73e   Magnus Karlsson   samples/bpf: add ...
1403
1404
1405
1406
1407
  	xsk->outstanding_tx += rcvd;
  }
  
  static void l2fwd_all(void)
  {
2e5d72c15   Magnus Karlsson   samples/bpf: Add ...
1408
  	struct pollfd fds[MAX_SOCKS] = {};
46738f73e   Magnus Karlsson   samples/bpf: add ...
1409
  	int i, ret;
46738f73e   Magnus Karlsson   samples/bpf: add ...
1410
1411
1412
1413
  	for (i = 0; i < num_socks; i++) {
  		fds[i].fd = xsk_socket__fd(xsks[i]->xsk);
  		fds[i].events = POLLOUT | POLLIN;
  	}
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1414

46738f73e   Magnus Karlsson   samples/bpf: add ...
1415
1416
  	for (;;) {
  		if (opt_poll) {
60dc609db   Ciara Loftus   samples: bpf: Cou...
1417
1418
  			for (i = 0; i < num_socks; i++)
  				xsks[i]->app_stats.opt_polls++;
46738f73e   Magnus Karlsson   samples/bpf: add ...
1419
1420
1421
1422
  			ret = poll(fds, num_socks, opt_timeout);
  			if (ret <= 0)
  				continue;
  		}
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1423

46738f73e   Magnus Karlsson   samples/bpf: add ...
1424
1425
  		for (i = 0; i < num_socks; i++)
  			l2fwd(xsks[i], fds);
d3f11b018   Jay Jayatheerthan   samples/bpf: xdps...
1426
1427
1428
  
  		if (benchmark_done)
  			break;
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1429
1430
  	}
  }
2e5d72c15   Magnus Karlsson   samples/bpf: Add ...
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
  static void load_xdp_program(char **argv, struct bpf_object **obj)
  {
  	struct bpf_prog_load_attr prog_load_attr = {
  		.prog_type      = BPF_PROG_TYPE_XDP,
  	};
  	char xdp_filename[256];
  	int prog_fd;
  
  	snprintf(xdp_filename, sizeof(xdp_filename), "%s_kern.o", argv[0]);
  	prog_load_attr.file = xdp_filename;
  
  	if (bpf_prog_load_xattr(&prog_load_attr, obj, &prog_fd))
  		exit(EXIT_FAILURE);
  	if (prog_fd < 0) {
  		fprintf(stderr, "ERROR: no program found: %s
  ",
  			strerror(prog_fd));
  		exit(EXIT_FAILURE);
  	}
  
  	if (bpf_set_link_xdp_fd(opt_ifindex, prog_fd, opt_xdp_flags) < 0) {
  		fprintf(stderr, "ERROR: link set xdp fd failed
  ");
  		exit(EXIT_FAILURE);
  	}
  }
  
  static void enter_xsks_into_map(struct bpf_object *obj)
  {
  	struct bpf_map *map;
  	int i, xsks_map;
  
  	map = bpf_object__find_map_by_name(obj, "xsks_map");
  	xsks_map = bpf_map__fd(map);
  	if (xsks_map < 0) {
  		fprintf(stderr, "ERROR: no xsks map found: %s
  ",
  			strerror(xsks_map));
  			exit(EXIT_FAILURE);
  	}
  
  	for (i = 0; i < num_socks; i++) {
  		int fd = xsk_socket__fd(xsks[i]->xsk);
  		int key, ret;
  
  		key = i;
  		ret = bpf_map_update_elem(xsks_map, &key, &fd, 0);
  		if (ret) {
  			fprintf(stderr, "ERROR: bpf_map_update_elem %d
  ", i);
  			exit(EXIT_FAILURE);
  		}
  	}
  }
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1485
1486
1487
  int main(int argc, char **argv)
  {
  	struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
661842c46   Magnus Karlsson   samples/bpf: Use ...
1488
  	bool rx = false, tx = false;
248c7f9c0   Magnus Karlsson   samples/bpf: conv...
1489
  	struct xsk_umem_info *umem;
2e5d72c15   Magnus Karlsson   samples/bpf: Add ...
1490
  	struct bpf_object *obj;
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1491
  	pthread_t pt;
2e5d72c15   Magnus Karlsson   samples/bpf: Add ...
1492
  	int i, ret;
248c7f9c0   Magnus Karlsson   samples/bpf: conv...
1493
  	void *bufs;
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1494
1495
1496
1497
1498
1499
1500
1501
1502
  
  	parse_command_line(argc, argv);
  
  	if (setrlimit(RLIMIT_MEMLOCK, &r)) {
  		fprintf(stderr, "ERROR: setrlimit(RLIMIT_MEMLOCK) \"%s\"
  ",
  			strerror(errno));
  		exit(EXIT_FAILURE);
  	}
2e5d72c15   Magnus Karlsson   samples/bpf: Add ...
1503
1504
  	if (opt_num_xsks > 1)
  		load_xdp_program(argv, &obj);
3945b37a9   Kevin Laatz   samples/bpf: use ...
1505
1506
1507
1508
1509
1510
1511
1512
1513
  	/* Reserve memory for the umem. Use hugepages if unaligned chunk mode */
  	bufs = mmap(NULL, NUM_FRAMES * opt_xsk_frame_size,
  		    PROT_READ | PROT_WRITE,
  		    MAP_PRIVATE | MAP_ANONYMOUS | opt_mmap_flags, -1, 0);
  	if (bufs == MAP_FAILED) {
  		printf("ERROR: mmap failed
  ");
  		exit(EXIT_FAILURE);
  	}
2e5d72c15   Magnus Karlsson   samples/bpf: Add ...
1514
1515
  
  	/* Create sockets... */
123e8da1d   Maxim Mikityanskiy   xsk: Change the d...
1516
  	umem = xsk_configure_umem(bufs, NUM_FRAMES * opt_xsk_frame_size);
661842c46   Magnus Karlsson   samples/bpf: Use ...
1517
1518
1519
1520
1521
1522
  	if (opt_bench == BENCH_RXDROP || opt_bench == BENCH_L2FWD) {
  		rx = true;
  		xsk_populate_fill_ring(umem);
  	}
  	if (opt_bench == BENCH_L2FWD || opt_bench == BENCH_TXONLY)
  		tx = true;
2e5d72c15   Magnus Karlsson   samples/bpf: Add ...
1523
  	for (i = 0; i < opt_num_xsks; i++)
661842c46   Magnus Karlsson   samples/bpf: Use ...
1524
  		xsks[num_socks++] = xsk_configure_socket(umem, rx, tx);
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1525

4a3c23ae3   Jay Jayatheerthan   samples/bpf: xdps...
1526
1527
  	if (opt_bench == BENCH_TXONLY) {
  		gen_eth_hdr_data();
661842c46   Magnus Karlsson   samples/bpf: Use ...
1528
1529
  		for (i = 0; i < NUM_FRAMES; i++)
  			gen_eth_frame(umem, i * opt_xsk_frame_size);
4a3c23ae3   Jay Jayatheerthan   samples/bpf: xdps...
1530
  	}
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1531

2e5d72c15   Magnus Karlsson   samples/bpf: Add ...
1532
1533
  	if (opt_num_xsks > 1 && opt_bench != BENCH_TXONLY)
  		enter_xsks_into_map(obj);
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1534
1535
1536
1537
1538
1539
  
  	signal(SIGINT, int_exit);
  	signal(SIGTERM, int_exit);
  	signal(SIGABRT, int_exit);
  
  	setlocale(LC_ALL, "");
74e00676d   Magnus Karlsson   samples/bpf: Add ...
1540
1541
1542
1543
1544
  	if (!opt_quiet) {
  		ret = pthread_create(&pt, NULL, poller, NULL);
  		if (ret)
  			exit_with_error(ret);
  	}
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1545
1546
  
  	prev_time = get_nsecs();
d3f11b018   Jay Jayatheerthan   samples/bpf: xdps...
1547
  	start_time = prev_time;
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1548
1549
1550
1551
  
  	if (opt_bench == BENCH_RXDROP)
  		rx_drop_all();
  	else if (opt_bench == BENCH_TXONLY)
46738f73e   Magnus Karlsson   samples/bpf: add ...
1552
  		tx_only_all();
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1553
  	else
46738f73e   Magnus Karlsson   samples/bpf: add ...
1554
  		l2fwd_all();
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1555

ece6e9694   Jay Jayatheerthan   samples/bpf: xdps...
1556
  	benchmark_done = true;
74e00676d   Magnus Karlsson   samples/bpf: Add ...
1557
1558
  	if (!opt_quiet)
  		pthread_join(pt, NULL);
d3f11b018   Jay Jayatheerthan   samples/bpf: xdps...
1559

695255882   Jay Jayatheerthan   samples/bpf: xdps...
1560
  	xdpsock_cleanup();
b4b8faa1d   Magnus Karlsson   samples/bpf: samp...
1561
1562
  	return 0;
  }