]> asedeno.scripts.mit.edu Git - linux.git/blob - samples/bpf/xdp_adjust_tail_user.c
bpf: add bpf_xdp_adjust_tail sample prog
[linux.git] / samples / bpf / xdp_adjust_tail_user.c
1 /* SPDX-License-Identifier: GPL-2.0
2  * Copyright (c) 2018 Facebook
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of version 2 of the GNU General Public
6  * License as published by the Free Software Foundation.
7  */
8 #include <linux/bpf.h>
9 #include <linux/if_link.h>
10 #include <assert.h>
11 #include <errno.h>
12 #include <signal.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <sys/resource.h>
17 #include <arpa/inet.h>
18 #include <netinet/ether.h>
19 #include <unistd.h>
20 #include <time.h>
21 #include "bpf_load.h"
22 #include "libbpf.h"
23 #include "bpf_util.h"
24
25 #define STATS_INTERVAL_S 2U
26
27 static int ifindex = -1;
28 static __u32 xdp_flags;
29
30 static void int_exit(int sig)
31 {
32         if (ifindex > -1)
33                 bpf_set_link_xdp_fd(ifindex, -1, xdp_flags);
34         exit(0);
35 }
36
37 /* simple "icmp packet too big sent" counter
38  */
39 static void poll_stats(unsigned int kill_after_s)
40 {
41         time_t started_at = time(NULL);
42         __u64 value = 0;
43         int key = 0;
44
45
46         while (!kill_after_s || time(NULL) - started_at <= kill_after_s) {
47                 sleep(STATS_INTERVAL_S);
48
49                 assert(bpf_map_lookup_elem(map_fd[0], &key, &value) == 0);
50
51                 printf("icmp \"packet too big\" sent: %10llu pkts\n", value);
52         }
53 }
54
55 static void usage(const char *cmd)
56 {
57         printf("Start a XDP prog which send ICMP \"packet too big\" \n"
58                 "messages if ingress packet is bigger then MAX_SIZE bytes\n");
59         printf("Usage: %s [...]\n", cmd);
60         printf("    -i <ifindex> Interface Index\n");
61         printf("    -T <stop-after-X-seconds> Default: 0 (forever)\n");
62         printf("    -S use skb-mode\n");
63         printf("    -N enforce native mode\n");
64         printf("    -h Display this help\n");
65 }
66
67 int main(int argc, char **argv)
68 {
69         unsigned char opt_flags[256] = {};
70         unsigned int kill_after_s = 0;
71         const char *optstr = "i:T:SNh";
72         struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
73         char filename[256];
74         int opt;
75         int i;
76
77
78         for (i = 0; i < strlen(optstr); i++)
79                 if (optstr[i] != 'h' && 'a' <= optstr[i] && optstr[i] <= 'z')
80                         opt_flags[(unsigned char)optstr[i]] = 1;
81
82         while ((opt = getopt(argc, argv, optstr)) != -1) {
83
84                 switch (opt) {
85                 case 'i':
86                         ifindex = atoi(optarg);
87                         break;
88                 case 'T':
89                         kill_after_s = atoi(optarg);
90                         break;
91                 case 'S':
92                         xdp_flags |= XDP_FLAGS_SKB_MODE;
93                         break;
94                 case 'N':
95                         xdp_flags |= XDP_FLAGS_DRV_MODE;
96                         break;
97                 default:
98                         usage(argv[0]);
99                         return 1;
100                 }
101                 opt_flags[opt] = 0;
102         }
103
104         for (i = 0; i < strlen(optstr); i++) {
105                 if (opt_flags[(unsigned int)optstr[i]]) {
106                         fprintf(stderr, "Missing argument -%c\n", optstr[i]);
107                         usage(argv[0]);
108                         return 1;
109                 }
110         }
111
112         if (setrlimit(RLIMIT_MEMLOCK, &r)) {
113                 perror("setrlimit(RLIMIT_MEMLOCK, RLIM_INFINITY)");
114                 return 1;
115         }
116
117         snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
118
119         if (load_bpf_file(filename)) {
120                 printf("%s", bpf_log_buf);
121                 return 1;
122         }
123
124         if (!prog_fd[0]) {
125                 printf("load_bpf_file: %s\n", strerror(errno));
126                 return 1;
127         }
128
129         signal(SIGINT, int_exit);
130         signal(SIGTERM, int_exit);
131
132         if (bpf_set_link_xdp_fd(ifindex, prog_fd[0], xdp_flags) < 0) {
133                 printf("link set xdp fd failed\n");
134                 return 1;
135         }
136
137         poll_stats(kill_after_s);
138
139         bpf_set_link_xdp_fd(ifindex, -1, xdp_flags);
140
141         return 0;
142 }