diff options
author | Chenbo Feng | 2017-04-05 21:00:56 -0500 |
---|---|---|
committer | David S. Miller | 2017-04-08 10:07:01 -0500 |
commit | 00f660eaf37808aa0a537c288c9e2dee73bd4316 (patch) | |
tree | 566ff6609ee3fc6ff216b9c18d3118dc50b3bf30 /samples | |
parent | 5daab9db7b65df87da26fd8cfa695fb9546a1ddb (diff) | |
download | kernel-00f660eaf37808aa0a537c288c9e2dee73bd4316.tar.gz kernel-00f660eaf37808aa0a537c288c9e2dee73bd4316.tar.xz kernel-00f660eaf37808aa0a537c288c9e2dee73bd4316.zip |
Sample program using SO_COOKIE
Added a per socket traffic monitoring option to illustrate the usage
of new getsockopt SO_COOKIE. The program is based on the socket traffic
monitoring program using xt_eBPF and in the new option the data entry
can be directly accessed using socket cookie. The cookie retrieved
allow us to lookup an element in the eBPF for a specific socket.
Signed-off-by: Chenbo Feng <fengc@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'samples')
-rw-r--r-- | samples/bpf/cookie_uid_helper_example.c | 146 | ||||
-rwxr-xr-x[-rw-r--r--] | samples/bpf/run_cookie_uid_helper_example.sh | 4 |
2 files changed, 127 insertions, 23 deletions
diff --git a/samples/bpf/cookie_uid_helper_example.c b/samples/bpf/cookie_uid_helper_example.c index f6e5e58931c5..ad5afedf2e70 100644 --- a/samples/bpf/cookie_uid_helper_example.c +++ b/samples/bpf/cookie_uid_helper_example.c | |||
@@ -4,10 +4,11 @@ | |||
4 | * program into the xt_bpf match. | 4 | * program into the xt_bpf match. |
5 | * | 5 | * |
6 | * TEST: | 6 | * TEST: |
7 | * ./run_cookie_uid_helper_example.sh | 7 | * ./run_cookie_uid_helper_example.sh -option |
8 | * Then generate some traffic in variate ways. ping 0 -c 10 would work | 8 | * option: |
9 | * but the cookie and uid in this case could both be 0. A sample output | 9 | * -t: do traffic monitoring test, the program will continuously |
10 | * with some traffic generated by web browser is shown below: | 10 | * print out network traffic happens after program started A sample |
11 | * output is shown below: | ||
11 | * | 12 | * |
12 | * cookie: 877, uid: 0x3e8, Pakcet Count: 20, Bytes Count: 11058 | 13 | * cookie: 877, uid: 0x3e8, Pakcet Count: 20, Bytes Count: 11058 |
13 | * cookie: 132, uid: 0x0, Pakcet Count: 2, Bytes Count: 286 | 14 | * cookie: 132, uid: 0x0, Pakcet Count: 2, Bytes Count: 286 |
@@ -18,6 +19,10 @@ | |||
18 | * cookie: 0, uid: 0x0, Pakcet Count: 6, Bytes Count: 712 | 19 | * cookie: 0, uid: 0x0, Pakcet Count: 6, Bytes Count: 712 |
19 | * cookie: 880, uid: 0xfffe, Pakcet Count: 1, Bytes Count: 70 | 20 | * cookie: 880, uid: 0xfffe, Pakcet Count: 1, Bytes Count: 70 |
20 | * | 21 | * |
22 | * -s: do getsockopt SO_COOKIE test, the program will set up a pair of | ||
23 | * UDP sockets and send packets between them. And read out the traffic data | ||
24 | * directly from the ebpf map based on the socket cookie. | ||
25 | * | ||
21 | * Clean up: if using shell script, the script file will delete the iptables | 26 | * Clean up: if using shell script, the script file will delete the iptables |
22 | * rule and unmount the bpf program when exit. Else the iptables rule need | 27 | * rule and unmount the bpf program when exit. Else the iptables rule need |
23 | * to be deleted by hand, see run_cookie_uid_helper_example.sh for detail. | 28 | * to be deleted by hand, see run_cookie_uid_helper_example.sh for detail. |
@@ -34,6 +39,8 @@ | |||
34 | #include <limits.h> | 39 | #include <limits.h> |
35 | #include <linux/bpf.h> | 40 | #include <linux/bpf.h> |
36 | #include <linux/if_ether.h> | 41 | #include <linux/if_ether.h> |
42 | #include <net/if.h> | ||
43 | #include <signal.h> | ||
37 | #include <stdbool.h> | 44 | #include <stdbool.h> |
38 | #include <stdint.h> | 45 | #include <stdint.h> |
39 | #include <stdio.h> | 46 | #include <stdio.h> |
@@ -46,6 +53,8 @@ | |||
46 | #include <bpf/bpf.h> | 53 | #include <bpf/bpf.h> |
47 | #include "libbpf.h" | 54 | #include "libbpf.h" |
48 | 55 | ||
56 | #define PORT 8888 | ||
57 | |||
49 | struct stats { | 58 | struct stats { |
50 | uint32_t uid; | 59 | uint32_t uid; |
51 | uint64_t packets; | 60 | uint64_t packets; |
@@ -54,6 +63,8 @@ struct stats { | |||
54 | 63 | ||
55 | static int map_fd, prog_fd; | 64 | static int map_fd, prog_fd; |
56 | 65 | ||
66 | static bool test_finish; | ||
67 | |||
57 | static void maps_create(void) | 68 | static void maps_create(void) |
58 | { | 69 | { |
59 | map_fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(uint32_t), | 70 | map_fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(uint32_t), |
@@ -164,7 +175,7 @@ static void prog_attach_iptables(char *file) | |||
164 | printf("file path too long: %s\n", file); | 175 | printf("file path too long: %s\n", file); |
165 | exit(1); | 176 | exit(1); |
166 | } | 177 | } |
167 | sprintf(rules, "iptables -A INPUT -m bpf --object-pinned %s -j ACCEPT", | 178 | sprintf(rules, "iptables -A OUTPUT -m bpf --object-pinned %s -j ACCEPT", |
168 | file); | 179 | file); |
169 | ret = system(rules); | 180 | ret = system(rules); |
170 | if (ret < 0) { | 181 | if (ret < 0) { |
@@ -177,7 +188,8 @@ static void print_table(void) | |||
177 | { | 188 | { |
178 | struct stats curEntry; | 189 | struct stats curEntry; |
179 | uint32_t curN = UINT32_MAX; | 190 | uint32_t curN = UINT32_MAX; |
180 | uint32_t nextN, res; | 191 | uint32_t nextN; |
192 | int res; | ||
181 | 193 | ||
182 | while (bpf_map_get_next_key(map_fd, &curN, &nextN) > -1) { | 194 | while (bpf_map_get_next_key(map_fd, &curN, &nextN) > -1) { |
183 | curN = nextN; | 195 | curN = nextN; |
@@ -193,25 +205,117 @@ static void print_table(void) | |||
193 | } | 205 | } |
194 | } | 206 | } |
195 | 207 | ||
196 | int main(int argc, char *argv[]) | 208 | static void udp_client(void) |
197 | { | 209 | { |
198 | if (argc > 2) { | 210 | struct sockaddr_in si_other = {0}; |
199 | printf("Too many argument provided\n"); | 211 | struct sockaddr_in si_me = {0}; |
200 | return 1; | 212 | struct stats dataEntry; |
201 | } else if (argc < 2) { | 213 | int s_rcv, s_send, i, recv_len; |
202 | printf("Usage: %s bpfObjName\n", argv[0]); | 214 | char message = 'a'; |
203 | return 1; | 215 | char buf; |
216 | uint64_t cookie; | ||
217 | int res; | ||
218 | socklen_t cookie_len = sizeof(cookie); | ||
219 | socklen_t slen = sizeof(si_other); | ||
220 | |||
221 | s_rcv = socket(PF_INET, SOCK_DGRAM, 0); | ||
222 | if (s_rcv < 0) | ||
223 | error(1, errno, "rcv socket creat failed!\n"); | ||
224 | si_other.sin_family = AF_INET; | ||
225 | si_other.sin_port = htons(PORT); | ||
226 | if (inet_aton("127.0.0.1", &si_other.sin_addr) == 0) | ||
227 | error(1, errno, "inet_aton\n"); | ||
228 | if (bind(s_rcv, (struct sockaddr *)&si_other, sizeof(si_other)) == -1) | ||
229 | error(1, errno, "bind\n"); | ||
230 | s_send = socket(PF_INET, SOCK_DGRAM, 0); | ||
231 | if (s_send < 0) | ||
232 | error(1, errno, "send socket creat failed!\n"); | ||
233 | res = getsockopt(s_send, SOL_SOCKET, SO_COOKIE, &cookie, &cookie_len); | ||
234 | if (res < 0) | ||
235 | printf("get cookie failed: %s\n", strerror(errno)); | ||
236 | res = bpf_map_lookup_elem(map_fd, &cookie, &dataEntry); | ||
237 | if (res != -1) | ||
238 | error(1, errno, "socket stat found while flow not active\n"); | ||
239 | for (i = 0; i < 10; i++) { | ||
240 | res = sendto(s_send, &message, sizeof(message), 0, | ||
241 | (struct sockaddr *)&si_other, slen); | ||
242 | if (res == -1) | ||
243 | error(1, errno, "send\n"); | ||
244 | if (res != sizeof(message)) | ||
245 | error(1, 0, "%uB != %luB\n", res, sizeof(message)); | ||
246 | recv_len = recvfrom(s_rcv, &buf, sizeof(buf), 0, | ||
247 | (struct sockaddr *)&si_me, &slen); | ||
248 | if (recv_len < 0) | ||
249 | error(1, errno, "revieve\n"); | ||
250 | res = memcmp(&(si_other.sin_addr), &(si_me.sin_addr), | ||
251 | sizeof(si_me.sin_addr)); | ||
252 | if (res != 0) | ||
253 | error(1, EFAULT, "sender addr error: %d\n", res); | ||
254 | printf("Message received: %c\n", buf); | ||
255 | res = bpf_map_lookup_elem(map_fd, &cookie, &dataEntry); | ||
256 | if (res < 0) | ||
257 | error(1, errno, "lookup sk stat failed, cookie: %lu\n", | ||
258 | cookie); | ||
259 | printf("cookie: %lu, uid: 0x%x, Packet Count: %lu," | ||
260 | " Bytes Count: %lu\n\n", cookie, dataEntry.uid, | ||
261 | dataEntry.packets, dataEntry.bytes); | ||
204 | } | 262 | } |
263 | close(s_send); | ||
264 | close(s_rcv); | ||
265 | } | ||
205 | 266 | ||
206 | maps_create(); | 267 | static int usage(void) |
207 | prog_load(); | 268 | { |
208 | prog_attach_iptables(argv[1]); | 269 | printf("Usage: ./run_cookie_uid_helper_example.sh" |
270 | " bpfObjName -option\n" | ||
271 | " -t traffic monitor test\n" | ||
272 | " -s getsockopt cookie test\n"); | ||
273 | return 1; | ||
274 | } | ||
209 | 275 | ||
210 | while (true) { | 276 | void finish(int ret) |
211 | print_table(); | 277 | { |
212 | printf("\n"); | 278 | test_finish = true; |
213 | sleep(1); | 279 | } |
214 | }; | 280 | |
281 | int main(int argc, char *argv[]) | ||
282 | { | ||
283 | int opt; | ||
284 | bool cfg_test_traffic = false; | ||
285 | bool cfg_test_cookie = false; | ||
286 | |||
287 | if (argc != 3) | ||
288 | return usage(); | ||
289 | while ((opt = getopt(argc, argv, "ts")) != -1) { | ||
290 | switch (opt) { | ||
291 | case 't': | ||
292 | cfg_test_traffic = true; | ||
293 | break; | ||
294 | case 's': | ||
295 | cfg_test_cookie = true; | ||
296 | break; | ||
215 | 297 | ||
298 | default: | ||
299 | printf("unknown option %c\n", opt); | ||
300 | usage(); | ||
301 | return -1; | ||
302 | } | ||
303 | } | ||
304 | maps_create(); | ||
305 | prog_load(); | ||
306 | prog_attach_iptables(argv[2]); | ||
307 | if (cfg_test_traffic) { | ||
308 | if (signal(SIGINT, finish) == SIG_ERR) | ||
309 | error(1, errno, "register handler failed"); | ||
310 | while (!test_finish) { | ||
311 | print_table(); | ||
312 | printf("\n"); | ||
313 | sleep(1); | ||
314 | }; | ||
315 | } else if (cfg_test_cookie) { | ||
316 | udp_client(); | ||
317 | } | ||
318 | close(prog_fd); | ||
319 | close(map_fd); | ||
216 | return 0; | 320 | return 0; |
217 | } | 321 | } |
diff --git a/samples/bpf/run_cookie_uid_helper_example.sh b/samples/bpf/run_cookie_uid_helper_example.sh index 40da8aa75c44..f898cfa2b1aa 100644..100755 --- a/samples/bpf/run_cookie_uid_helper_example.sh +++ b/samples/bpf/run_cookie_uid_helper_example.sh | |||
@@ -4,11 +4,11 @@ root_dir=$local_dir/../.. | |||
4 | mnt_dir=$(mktemp -d --tmp) | 4 | mnt_dir=$(mktemp -d --tmp) |
5 | 5 | ||
6 | on_exit() { | 6 | on_exit() { |
7 | iptables -D INPUT -m bpf --object-pinned ${mnt_dir}/bpf_prog -j ACCEPT | 7 | iptables -D OUTPUT -m bpf --object-pinned ${mnt_dir}/bpf_prog -j ACCEPT |
8 | umount ${mnt_dir} | 8 | umount ${mnt_dir} |
9 | rm -r ${mnt_dir} | 9 | rm -r ${mnt_dir} |
10 | } | 10 | } |
11 | 11 | ||
12 | trap on_exit EXIT | 12 | trap on_exit EXIT |
13 | mount -t bpf bpf ${mnt_dir} | 13 | mount -t bpf bpf ${mnt_dir} |
14 | ./per_socket_stats_example ${mnt_dir}/bpf_prog | 14 | ./per_socket_stats_example ${mnt_dir}/bpf_prog $1 |