diff options
Diffstat (limited to 'samples/bpf')
-rw-r--r-- | samples/bpf/.gitignore | 1 | ||||
-rw-r--r-- | samples/bpf/Makefile | 2 | ||||
-rw-r--r-- | samples/bpf/bpf_load.c | 8 | ||||
-rwxr-xr-x | samples/bpf/do_hbm_test.sh | 10 | ||||
-rw-r--r-- | samples/bpf/hbm.c | 51 | ||||
-rw-r--r-- | samples/bpf/hbm.h | 9 | ||||
-rw-r--r-- | samples/bpf/hbm_kern.h | 77 | ||||
-rw-r--r-- | samples/bpf/hbm_out_kern.c | 48 | ||||
-rw-r--r-- | samples/bpf/tcp_basertt_kern.c | 7 | ||||
-rw-r--r-- | samples/bpf/tcp_bufs_kern.c | 7 | ||||
-rw-r--r-- | samples/bpf/tcp_clamp_kern.c | 7 | ||||
-rw-r--r-- | samples/bpf/tcp_cong_kern.c | 7 | ||||
-rw-r--r-- | samples/bpf/tcp_iw_kern.c | 7 | ||||
-rw-r--r-- | samples/bpf/tcp_rwnd_kern.c | 7 | ||||
-rw-r--r-- | samples/bpf/tcp_synrto_kern.c | 7 | ||||
-rw-r--r-- | samples/bpf/tcp_tos_reflect_kern.c | 7 | ||||
-rw-r--r-- | samples/bpf/test_cgrp2_attach2.c | 459 | ||||
-rw-r--r-- | samples/bpf/xdp_sample_pkts_kern.c | 7 |
18 files changed, 169 insertions, 559 deletions
diff --git a/samples/bpf/.gitignore b/samples/bpf/.gitignore index c7498457595a..74d31fd3c99c 100644 --- a/samples/bpf/.gitignore +++ b/samples/bpf/.gitignore | |||
@@ -1,6 +1,7 @@ | |||
1 | cpustat | 1 | cpustat |
2 | fds_example | 2 | fds_example |
3 | hbm | 3 | hbm |
4 | ibumad | ||
4 | lathist | 5 | lathist |
5 | lwt_len_hist | 6 | lwt_len_hist |
6 | map_perf_test | 7 | map_perf_test |
diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile index 4f0a1cdbfe7c..253e5a2856be 100644 --- a/samples/bpf/Makefile +++ b/samples/bpf/Makefile | |||
@@ -26,7 +26,6 @@ hostprogs-y += map_perf_test | |||
26 | hostprogs-y += test_overhead | 26 | hostprogs-y += test_overhead |
27 | hostprogs-y += test_cgrp2_array_pin | 27 | hostprogs-y += test_cgrp2_array_pin |
28 | hostprogs-y += test_cgrp2_attach | 28 | hostprogs-y += test_cgrp2_attach |
29 | hostprogs-y += test_cgrp2_attach2 | ||
30 | hostprogs-y += test_cgrp2_sock | 29 | hostprogs-y += test_cgrp2_sock |
31 | hostprogs-y += test_cgrp2_sock2 | 30 | hostprogs-y += test_cgrp2_sock2 |
32 | hostprogs-y += xdp1 | 31 | hostprogs-y += xdp1 |
@@ -81,7 +80,6 @@ map_perf_test-objs := bpf_load.o map_perf_test_user.o | |||
81 | test_overhead-objs := bpf_load.o test_overhead_user.o | 80 | test_overhead-objs := bpf_load.o test_overhead_user.o |
82 | test_cgrp2_array_pin-objs := test_cgrp2_array_pin.o | 81 | test_cgrp2_array_pin-objs := test_cgrp2_array_pin.o |
83 | test_cgrp2_attach-objs := test_cgrp2_attach.o | 82 | test_cgrp2_attach-objs := test_cgrp2_attach.o |
84 | test_cgrp2_attach2-objs := test_cgrp2_attach2.o $(CGROUP_HELPERS) | ||
85 | test_cgrp2_sock-objs := test_cgrp2_sock.o | 83 | test_cgrp2_sock-objs := test_cgrp2_sock.o |
86 | test_cgrp2_sock2-objs := bpf_load.o test_cgrp2_sock2.o | 84 | test_cgrp2_sock2-objs := bpf_load.o test_cgrp2_sock2.o |
87 | xdp1-objs := xdp1_user.o | 85 | xdp1-objs := xdp1_user.o |
diff --git a/samples/bpf/bpf_load.c b/samples/bpf/bpf_load.c index eae7b635343d..1734ade04f7f 100644 --- a/samples/bpf/bpf_load.c +++ b/samples/bpf/bpf_load.c | |||
@@ -40,7 +40,7 @@ int prog_cnt; | |||
40 | int prog_array_fd = -1; | 40 | int prog_array_fd = -1; |
41 | 41 | ||
42 | struct bpf_map_data map_data[MAX_MAPS]; | 42 | struct bpf_map_data map_data[MAX_MAPS]; |
43 | int map_data_count = 0; | 43 | int map_data_count; |
44 | 44 | ||
45 | static int populate_prog_array(const char *event, int prog_fd) | 45 | static int populate_prog_array(const char *event, int prog_fd) |
46 | { | 46 | { |
@@ -65,7 +65,7 @@ static int write_kprobe_events(const char *val) | |||
65 | else | 65 | else |
66 | flags = O_WRONLY | O_APPEND; | 66 | flags = O_WRONLY | O_APPEND; |
67 | 67 | ||
68 | fd = open("/sys/kernel/debug/tracing/kprobe_events", flags); | 68 | fd = open(DEBUGFS "kprobe_events", flags); |
69 | 69 | ||
70 | ret = write(fd, val, strlen(val)); | 70 | ret = write(fd, val, strlen(val)); |
71 | close(fd); | 71 | close(fd); |
@@ -490,8 +490,8 @@ static int load_elf_maps_section(struct bpf_map_data *maps, int maps_shndx, | |||
490 | 490 | ||
491 | /* Verify no newer features were requested */ | 491 | /* Verify no newer features were requested */ |
492 | if (validate_zero) { | 492 | if (validate_zero) { |
493 | addr = (unsigned char*) def + map_sz_copy; | 493 | addr = (unsigned char *) def + map_sz_copy; |
494 | end = (unsigned char*) def + map_sz_elf; | 494 | end = (unsigned char *) def + map_sz_elf; |
495 | for (; addr < end; addr++) { | 495 | for (; addr < end; addr++) { |
496 | if (*addr != 0) { | 496 | if (*addr != 0) { |
497 | free(sym); | 497 | free(sym); |
diff --git a/samples/bpf/do_hbm_test.sh b/samples/bpf/do_hbm_test.sh index 56c8b4115c95..e48b047d4646 100755 --- a/samples/bpf/do_hbm_test.sh +++ b/samples/bpf/do_hbm_test.sh | |||
@@ -13,10 +13,10 @@ Usage() { | |||
13 | echo "egress or ingress bandwidht. It then uses iperf3 or netperf to create" | 13 | echo "egress or ingress bandwidht. It then uses iperf3 or netperf to create" |
14 | echo "loads. The output is the goodput in Mbps (unless -D was used)." | 14 | echo "loads. The output is the goodput in Mbps (unless -D was used)." |
15 | echo "" | 15 | echo "" |
16 | echo "USAGE: $name [out] [-b=<prog>|--bpf=<prog>] [-c=<cc>|--cc=<cc>] [-D]" | 16 | echo "USAGE: $name [out] [-b=<prog>|--bpf=<prog>] [-c=<cc>|--cc=<cc>]" |
17 | echo " [-d=<delay>|--delay=<delay>] [--debug] [-E]" | 17 | echo " [-D] [-d=<delay>|--delay=<delay>] [--debug] [-E]" |
18 | echo " [-f=<#flows>|--flows=<#flows>] [-h] [-i=<id>|--id=<id >]" | 18 | echo " [-f=<#flows>|--flows=<#flows>] [-h] [-i=<id>|--id=<id >]" |
19 | echo " [-l] [-N] [-p=<port>|--port=<port>] [-P]" | 19 | echo " [-l] [-N] [--no_cn] [-p=<port>|--port=<port>] [-P]" |
20 | echo " [-q=<qdisc>] [-R] [-s=<server>|--server=<server]" | 20 | echo " [-q=<qdisc>] [-R] [-s=<server>|--server=<server]" |
21 | echo " [-S|--stats] -t=<time>|--time=<time>] [-w] [cubic|dctcp]" | 21 | echo " [-S|--stats] -t=<time>|--time=<time>] [-w] [cubic|dctcp]" |
22 | echo " Where:" | 22 | echo " Where:" |
@@ -33,6 +33,7 @@ Usage() { | |||
33 | echo " -f or --flows number of concurrent flows (default=1)" | 33 | echo " -f or --flows number of concurrent flows (default=1)" |
34 | echo " -i or --id cgroup id (an integer, default is 1)" | 34 | echo " -i or --id cgroup id (an integer, default is 1)" |
35 | echo " -N use netperf instead of iperf3" | 35 | echo " -N use netperf instead of iperf3" |
36 | echo " --no_cn Do not return CN notifications" | ||
36 | echo " -l do not limit flows using loopback" | 37 | echo " -l do not limit flows using loopback" |
37 | echo " -h Help" | 38 | echo " -h Help" |
38 | echo " -p or --port iperf3 port (default is 5201)" | 39 | echo " -p or --port iperf3 port (default is 5201)" |
@@ -115,6 +116,9 @@ processArgs () { | |||
115 | -c=*|--cc=*) | 116 | -c=*|--cc=*) |
116 | cc="${i#*=}" | 117 | cc="${i#*=}" |
117 | ;; | 118 | ;; |
119 | --no_cn) | ||
120 | flags="$flags --no_cn" | ||
121 | ;; | ||
118 | --debug) | 122 | --debug) |
119 | flags="$flags -d" | 123 | flags="$flags -d" |
120 | debug_flag=1 | 124 | debug_flag=1 |
diff --git a/samples/bpf/hbm.c b/samples/bpf/hbm.c index a79828ab273f..480b7ad6a1f2 100644 --- a/samples/bpf/hbm.c +++ b/samples/bpf/hbm.c | |||
@@ -16,6 +16,7 @@ | |||
16 | * -l Also limit flows doing loopback | 16 | * -l Also limit flows doing loopback |
17 | * -n <#> To create cgroup \"/hbm#\" and attach prog | 17 | * -n <#> To create cgroup \"/hbm#\" and attach prog |
18 | * Default is /hbm1 | 18 | * Default is /hbm1 |
19 | * --no_cn Do not return cn notifications | ||
19 | * -r <rate> Rate limit in Mbps | 20 | * -r <rate> Rate limit in Mbps |
20 | * -s Get HBM stats (marked, dropped, etc.) | 21 | * -s Get HBM stats (marked, dropped, etc.) |
21 | * -t <time> Exit after specified seconds (default is 0) | 22 | * -t <time> Exit after specified seconds (default is 0) |
@@ -42,6 +43,7 @@ | |||
42 | 43 | ||
43 | #include <linux/bpf.h> | 44 | #include <linux/bpf.h> |
44 | #include <bpf/bpf.h> | 45 | #include <bpf/bpf.h> |
46 | #include <getopt.h> | ||
45 | 47 | ||
46 | #include "bpf_load.h" | 48 | #include "bpf_load.h" |
47 | #include "bpf_rlimit.h" | 49 | #include "bpf_rlimit.h" |
@@ -59,6 +61,7 @@ bool stats_flag; | |||
59 | bool loopback_flag; | 61 | bool loopback_flag; |
60 | bool debugFlag; | 62 | bool debugFlag; |
61 | bool work_conserving_flag; | 63 | bool work_conserving_flag; |
64 | bool no_cn_flag; | ||
62 | 65 | ||
63 | static void Usage(void); | 66 | static void Usage(void); |
64 | static void read_trace_pipe2(void); | 67 | static void read_trace_pipe2(void); |
@@ -185,6 +188,7 @@ static int run_bpf_prog(char *prog, int cg_id) | |||
185 | qstats.rate = rate; | 188 | qstats.rate = rate; |
186 | qstats.stats = stats_flag ? 1 : 0; | 189 | qstats.stats = stats_flag ? 1 : 0; |
187 | qstats.loopback = loopback_flag ? 1 : 0; | 190 | qstats.loopback = loopback_flag ? 1 : 0; |
191 | qstats.no_cn = no_cn_flag ? 1 : 0; | ||
188 | if (bpf_map_update_elem(map_fd, &key, &qstats, BPF_ANY)) { | 192 | if (bpf_map_update_elem(map_fd, &key, &qstats, BPF_ANY)) { |
189 | printf("ERROR: Could not update map element\n"); | 193 | printf("ERROR: Could not update map element\n"); |
190 | goto err; | 194 | goto err; |
@@ -312,6 +316,14 @@ static int run_bpf_prog(char *prog, int cg_id) | |||
312 | double percent_pkts, percent_bytes; | 316 | double percent_pkts, percent_bytes; |
313 | char fname[100]; | 317 | char fname[100]; |
314 | FILE *fout; | 318 | FILE *fout; |
319 | int k; | ||
320 | static const char *returnValNames[] = { | ||
321 | "DROP_PKT", | ||
322 | "ALLOW_PKT", | ||
323 | "DROP_PKT_CWR", | ||
324 | "ALLOW_PKT_CWR" | ||
325 | }; | ||
326 | #define RET_VAL_COUNT 4 | ||
315 | 327 | ||
316 | // Future support of ingress | 328 | // Future support of ingress |
317 | // if (!outFlag) | 329 | // if (!outFlag) |
@@ -346,6 +358,31 @@ static int run_bpf_prog(char *prog, int cg_id) | |||
346 | (qstats.bytes_total + 1); | 358 | (qstats.bytes_total + 1); |
347 | fprintf(fout, "pkts_dropped_percent:%6.2f\n", percent_pkts); | 359 | fprintf(fout, "pkts_dropped_percent:%6.2f\n", percent_pkts); |
348 | fprintf(fout, "bytes_dropped_percent:%6.2f\n", percent_bytes); | 360 | fprintf(fout, "bytes_dropped_percent:%6.2f\n", percent_bytes); |
361 | |||
362 | // ECN CE markings | ||
363 | percent_pkts = (qstats.pkts_ecn_ce * 100.0) / | ||
364 | (qstats.pkts_total + 1); | ||
365 | fprintf(fout, "pkts_ecn_ce:%6.2f (%d)\n", percent_pkts, | ||
366 | (int)qstats.pkts_ecn_ce); | ||
367 | |||
368 | // Average cwnd | ||
369 | fprintf(fout, "avg cwnd:%d\n", | ||
370 | (int)(qstats.sum_cwnd / (qstats.sum_cwnd_cnt + 1))); | ||
371 | // Average rtt | ||
372 | fprintf(fout, "avg rtt:%d\n", | ||
373 | (int)(qstats.sum_rtt / (qstats.pkts_total + 1))); | ||
374 | // Average credit | ||
375 | fprintf(fout, "avg credit:%d\n", | ||
376 | (int)(qstats.sum_credit / | ||
377 | (1500 * ((int)qstats.pkts_total) + 1))); | ||
378 | |||
379 | // Return values stats | ||
380 | for (k = 0; k < RET_VAL_COUNT; k++) { | ||
381 | percent_pkts = (qstats.returnValCount[k] * 100.0) / | ||
382 | (qstats.pkts_total + 1); | ||
383 | fprintf(fout, "%s:%6.2f (%d)\n", returnValNames[k], | ||
384 | percent_pkts, (int)qstats.returnValCount[k]); | ||
385 | } | ||
349 | fclose(fout); | 386 | fclose(fout); |
350 | } | 387 | } |
351 | 388 | ||
@@ -366,14 +403,15 @@ static void Usage(void) | |||
366 | { | 403 | { |
367 | printf("This program loads a cgroup skb BPF program to enforce\n" | 404 | printf("This program loads a cgroup skb BPF program to enforce\n" |
368 | "cgroup output (egress) bandwidth limits.\n\n" | 405 | "cgroup output (egress) bandwidth limits.\n\n" |
369 | "USAGE: hbm [-o] [-d] [-l] [-n <id>] [-r <rate>] [-s]\n" | 406 | "USAGE: hbm [-o] [-d] [-l] [-n <id>] [--no_cn] [-r <rate>]\n" |
370 | " [-t <secs>] [-w] [-h] [prog]\n" | 407 | " [-s] [-t <secs>] [-w] [-h] [prog]\n" |
371 | " Where:\n" | 408 | " Where:\n" |
372 | " -o indicates egress direction (default)\n" | 409 | " -o indicates egress direction (default)\n" |
373 | " -d print BPF trace debug buffer\n" | 410 | " -d print BPF trace debug buffer\n" |
374 | " -l also limit flows using loopback\n" | 411 | " -l also limit flows using loopback\n" |
375 | " -n <#> to create cgroup \"/hbm#\" and attach prog\n" | 412 | " -n <#> to create cgroup \"/hbm#\" and attach prog\n" |
376 | " Default is /hbm1\n" | 413 | " Default is /hbm1\n" |
414 | " --no_cn disable CN notifcations\n" | ||
377 | " -r <rate> Rate in Mbps\n" | 415 | " -r <rate> Rate in Mbps\n" |
378 | " -s Update HBM stats\n" | 416 | " -s Update HBM stats\n" |
379 | " -t <time> Exit after specified seconds (default is 0)\n" | 417 | " -t <time> Exit after specified seconds (default is 0)\n" |
@@ -393,9 +431,16 @@ int main(int argc, char **argv) | |||
393 | int k; | 431 | int k; |
394 | int cg_id = 1; | 432 | int cg_id = 1; |
395 | char *optstring = "iodln:r:st:wh"; | 433 | char *optstring = "iodln:r:st:wh"; |
434 | struct option loptions[] = { | ||
435 | {"no_cn", 0, NULL, 1}, | ||
436 | {NULL, 0, NULL, 0} | ||
437 | }; | ||
396 | 438 | ||
397 | while ((k = getopt(argc, argv, optstring)) != -1) { | 439 | while ((k = getopt_long(argc, argv, optstring, loptions, NULL)) != -1) { |
398 | switch (k) { | 440 | switch (k) { |
441 | case 1: | ||
442 | no_cn_flag = true; | ||
443 | break; | ||
399 | case'o': | 444 | case'o': |
400 | break; | 445 | break; |
401 | case 'd': | 446 | case 'd': |
diff --git a/samples/bpf/hbm.h b/samples/bpf/hbm.h index 518e8147d084..f0963ed6a562 100644 --- a/samples/bpf/hbm.h +++ b/samples/bpf/hbm.h | |||
@@ -19,7 +19,8 @@ struct hbm_vqueue { | |||
19 | struct hbm_queue_stats { | 19 | struct hbm_queue_stats { |
20 | unsigned long rate; /* in Mbps*/ | 20 | unsigned long rate; /* in Mbps*/ |
21 | unsigned long stats:1, /* get HBM stats (marked, dropped,..) */ | 21 | unsigned long stats:1, /* get HBM stats (marked, dropped,..) */ |
22 | loopback:1; /* also limit flows using loopback */ | 22 | loopback:1, /* also limit flows using loopback */ |
23 | no_cn:1; /* do not use cn flags */ | ||
23 | unsigned long long pkts_marked; | 24 | unsigned long long pkts_marked; |
24 | unsigned long long bytes_marked; | 25 | unsigned long long bytes_marked; |
25 | unsigned long long pkts_dropped; | 26 | unsigned long long pkts_dropped; |
@@ -28,4 +29,10 @@ struct hbm_queue_stats { | |||
28 | unsigned long long bytes_total; | 29 | unsigned long long bytes_total; |
29 | unsigned long long firstPacketTime; | 30 | unsigned long long firstPacketTime; |
30 | unsigned long long lastPacketTime; | 31 | unsigned long long lastPacketTime; |
32 | unsigned long long pkts_ecn_ce; | ||
33 | unsigned long long returnValCount[4]; | ||
34 | unsigned long long sum_cwnd; | ||
35 | unsigned long long sum_rtt; | ||
36 | unsigned long long sum_cwnd_cnt; | ||
37 | long long sum_credit; | ||
31 | }; | 38 | }; |
diff --git a/samples/bpf/hbm_kern.h b/samples/bpf/hbm_kern.h index c5635d924193..be19cf1d5cd5 100644 --- a/samples/bpf/hbm_kern.h +++ b/samples/bpf/hbm_kern.h | |||
@@ -30,15 +30,8 @@ | |||
30 | #define ALLOW_PKT 1 | 30 | #define ALLOW_PKT 1 |
31 | #define TCP_ECN_OK 1 | 31 | #define TCP_ECN_OK 1 |
32 | 32 | ||
33 | #define HBM_DEBUG 0 // Set to 1 to enable debugging | 33 | #ifndef HBM_DEBUG // Define HBM_DEBUG to enable debugging |
34 | #if HBM_DEBUG | 34 | #undef bpf_printk |
35 | #define bpf_printk(fmt, ...) \ | ||
36 | ({ \ | ||
37 | char ____fmt[] = fmt; \ | ||
38 | bpf_trace_printk(____fmt, sizeof(____fmt), \ | ||
39 | ##__VA_ARGS__); \ | ||
40 | }) | ||
41 | #else | ||
42 | #define bpf_printk(fmt, ...) | 35 | #define bpf_printk(fmt, ...) |
43 | #endif | 36 | #endif |
44 | 37 | ||
@@ -72,17 +65,43 @@ struct bpf_map_def SEC("maps") queue_stats = { | |||
72 | BPF_ANNOTATE_KV_PAIR(queue_stats, int, struct hbm_queue_stats); | 65 | BPF_ANNOTATE_KV_PAIR(queue_stats, int, struct hbm_queue_stats); |
73 | 66 | ||
74 | struct hbm_pkt_info { | 67 | struct hbm_pkt_info { |
68 | int cwnd; | ||
69 | int rtt; | ||
75 | bool is_ip; | 70 | bool is_ip; |
76 | bool is_tcp; | 71 | bool is_tcp; |
77 | short ecn; | 72 | short ecn; |
78 | }; | 73 | }; |
79 | 74 | ||
75 | static int get_tcp_info(struct __sk_buff *skb, struct hbm_pkt_info *pkti) | ||
76 | { | ||
77 | struct bpf_sock *sk; | ||
78 | struct bpf_tcp_sock *tp; | ||
79 | |||
80 | sk = skb->sk; | ||
81 | if (sk) { | ||
82 | sk = bpf_sk_fullsock(sk); | ||
83 | if (sk) { | ||
84 | if (sk->protocol == IPPROTO_TCP) { | ||
85 | tp = bpf_tcp_sock(sk); | ||
86 | if (tp) { | ||
87 | pkti->cwnd = tp->snd_cwnd; | ||
88 | pkti->rtt = tp->srtt_us >> 3; | ||
89 | return 0; | ||
90 | } | ||
91 | } | ||
92 | } | ||
93 | } | ||
94 | return 1; | ||
95 | } | ||
96 | |||
80 | static __always_inline void hbm_get_pkt_info(struct __sk_buff *skb, | 97 | static __always_inline void hbm_get_pkt_info(struct __sk_buff *skb, |
81 | struct hbm_pkt_info *pkti) | 98 | struct hbm_pkt_info *pkti) |
82 | { | 99 | { |
83 | struct iphdr iph; | 100 | struct iphdr iph; |
84 | struct ipv6hdr *ip6h; | 101 | struct ipv6hdr *ip6h; |
85 | 102 | ||
103 | pkti->cwnd = 0; | ||
104 | pkti->rtt = 0; | ||
86 | bpf_skb_load_bytes(skb, 0, &iph, 12); | 105 | bpf_skb_load_bytes(skb, 0, &iph, 12); |
87 | if (iph.version == 6) { | 106 | if (iph.version == 6) { |
88 | ip6h = (struct ipv6hdr *)&iph; | 107 | ip6h = (struct ipv6hdr *)&iph; |
@@ -98,6 +117,8 @@ static __always_inline void hbm_get_pkt_info(struct __sk_buff *skb, | |||
98 | pkti->is_tcp = false; | 117 | pkti->is_tcp = false; |
99 | pkti->ecn = 0; | 118 | pkti->ecn = 0; |
100 | } | 119 | } |
120 | if (pkti->is_tcp) | ||
121 | get_tcp_info(skb, pkti); | ||
101 | } | 122 | } |
102 | 123 | ||
103 | static __always_inline void hbm_init_vqueue(struct hbm_vqueue *qdp, int rate) | 124 | static __always_inline void hbm_init_vqueue(struct hbm_vqueue *qdp, int rate) |
@@ -112,8 +133,14 @@ static __always_inline void hbm_update_stats(struct hbm_queue_stats *qsp, | |||
112 | int len, | 133 | int len, |
113 | unsigned long long curtime, | 134 | unsigned long long curtime, |
114 | bool congestion_flag, | 135 | bool congestion_flag, |
115 | bool drop_flag) | 136 | bool drop_flag, |
137 | bool cwr_flag, | ||
138 | bool ecn_ce_flag, | ||
139 | struct hbm_pkt_info *pkti, | ||
140 | int credit) | ||
116 | { | 141 | { |
142 | int rv = ALLOW_PKT; | ||
143 | |||
117 | if (qsp != NULL) { | 144 | if (qsp != NULL) { |
118 | // Following is needed for work conserving | 145 | // Following is needed for work conserving |
119 | __sync_add_and_fetch(&(qsp->bytes_total), len); | 146 | __sync_add_and_fetch(&(qsp->bytes_total), len); |
@@ -123,7 +150,7 @@ static __always_inline void hbm_update_stats(struct hbm_queue_stats *qsp, | |||
123 | qsp->firstPacketTime = curtime; | 150 | qsp->firstPacketTime = curtime; |
124 | qsp->lastPacketTime = curtime; | 151 | qsp->lastPacketTime = curtime; |
125 | __sync_add_and_fetch(&(qsp->pkts_total), 1); | 152 | __sync_add_and_fetch(&(qsp->pkts_total), 1); |
126 | if (congestion_flag || drop_flag) { | 153 | if (congestion_flag) { |
127 | __sync_add_and_fetch(&(qsp->pkts_marked), 1); | 154 | __sync_add_and_fetch(&(qsp->pkts_marked), 1); |
128 | __sync_add_and_fetch(&(qsp->bytes_marked), len); | 155 | __sync_add_and_fetch(&(qsp->bytes_marked), len); |
129 | } | 156 | } |
@@ -132,6 +159,34 @@ static __always_inline void hbm_update_stats(struct hbm_queue_stats *qsp, | |||
132 | __sync_add_and_fetch(&(qsp->bytes_dropped), | 159 | __sync_add_and_fetch(&(qsp->bytes_dropped), |
133 | len); | 160 | len); |
134 | } | 161 | } |
162 | if (ecn_ce_flag) | ||
163 | __sync_add_and_fetch(&(qsp->pkts_ecn_ce), 1); | ||
164 | if (pkti->cwnd) { | ||
165 | __sync_add_and_fetch(&(qsp->sum_cwnd), | ||
166 | pkti->cwnd); | ||
167 | __sync_add_and_fetch(&(qsp->sum_cwnd_cnt), 1); | ||
168 | } | ||
169 | if (pkti->rtt) | ||
170 | __sync_add_and_fetch(&(qsp->sum_rtt), | ||
171 | pkti->rtt); | ||
172 | __sync_add_and_fetch(&(qsp->sum_credit), credit); | ||
173 | |||
174 | if (drop_flag) | ||
175 | rv = DROP_PKT; | ||
176 | if (cwr_flag) | ||
177 | rv |= 2; | ||
178 | if (rv == DROP_PKT) | ||
179 | __sync_add_and_fetch(&(qsp->returnValCount[0]), | ||
180 | 1); | ||
181 | else if (rv == ALLOW_PKT) | ||
182 | __sync_add_and_fetch(&(qsp->returnValCount[1]), | ||
183 | 1); | ||
184 | else if (rv == 2) | ||
185 | __sync_add_and_fetch(&(qsp->returnValCount[2]), | ||
186 | 1); | ||
187 | else if (rv == 3) | ||
188 | __sync_add_and_fetch(&(qsp->returnValCount[3]), | ||
189 | 1); | ||
135 | } | 190 | } |
136 | } | 191 | } |
137 | } | 192 | } |
diff --git a/samples/bpf/hbm_out_kern.c b/samples/bpf/hbm_out_kern.c index f806863d0b79..829934bd43cb 100644 --- a/samples/bpf/hbm_out_kern.c +++ b/samples/bpf/hbm_out_kern.c | |||
@@ -62,11 +62,12 @@ int _hbm_out_cg(struct __sk_buff *skb) | |||
62 | unsigned int queue_index = 0; | 62 | unsigned int queue_index = 0; |
63 | unsigned long long curtime; | 63 | unsigned long long curtime; |
64 | int credit; | 64 | int credit; |
65 | signed long long delta = 0, zero = 0; | 65 | signed long long delta = 0, new_credit; |
66 | int max_credit = MAX_CREDIT; | 66 | int max_credit = MAX_CREDIT; |
67 | bool congestion_flag = false; | 67 | bool congestion_flag = false; |
68 | bool drop_flag = false; | 68 | bool drop_flag = false; |
69 | bool cwr_flag = false; | 69 | bool cwr_flag = false; |
70 | bool ecn_ce_flag = false; | ||
70 | struct hbm_vqueue *qdp; | 71 | struct hbm_vqueue *qdp; |
71 | struct hbm_queue_stats *qsp = NULL; | 72 | struct hbm_queue_stats *qsp = NULL; |
72 | int rv = ALLOW_PKT; | 73 | int rv = ALLOW_PKT; |
@@ -99,9 +100,11 @@ int _hbm_out_cg(struct __sk_buff *skb) | |||
99 | */ | 100 | */ |
100 | if (delta > 0) { | 101 | if (delta > 0) { |
101 | qdp->lasttime = curtime; | 102 | qdp->lasttime = curtime; |
102 | credit += CREDIT_PER_NS(delta, qdp->rate); | 103 | new_credit = credit + CREDIT_PER_NS(delta, qdp->rate); |
103 | if (credit > MAX_CREDIT) | 104 | if (new_credit > MAX_CREDIT) |
104 | credit = MAX_CREDIT; | 105 | credit = MAX_CREDIT; |
106 | else | ||
107 | credit = new_credit; | ||
105 | } | 108 | } |
106 | credit -= len; | 109 | credit -= len; |
107 | qdp->credit = credit; | 110 | qdp->credit = credit; |
@@ -119,13 +122,16 @@ int _hbm_out_cg(struct __sk_buff *skb) | |||
119 | // Set flags (drop, congestion, cwr) | 122 | // Set flags (drop, congestion, cwr) |
120 | // Dropping => we are congested, so ignore congestion flag | 123 | // Dropping => we are congested, so ignore congestion flag |
121 | if (credit < -DROP_THRESH || | 124 | if (credit < -DROP_THRESH || |
122 | (len > LARGE_PKT_THRESH && | 125 | (len > LARGE_PKT_THRESH && credit < -LARGE_PKT_DROP_THRESH)) { |
123 | credit < -LARGE_PKT_DROP_THRESH)) { | 126 | // Very congested, set drop packet |
124 | // Very congested, set drop flag | ||
125 | drop_flag = true; | 127 | drop_flag = true; |
128 | if (pkti.ecn) | ||
129 | congestion_flag = true; | ||
130 | else if (pkti.is_tcp) | ||
131 | cwr_flag = true; | ||
126 | } else if (credit < 0) { | 132 | } else if (credit < 0) { |
127 | // Congested, set congestion flag | 133 | // Congested, set congestion flag |
128 | if (pkti.ecn) { | 134 | if (pkti.ecn || pkti.is_tcp) { |
129 | if (credit < -MARK_THRESH) | 135 | if (credit < -MARK_THRESH) |
130 | congestion_flag = true; | 136 | congestion_flag = true; |
131 | else | 137 | else |
@@ -136,22 +142,38 @@ int _hbm_out_cg(struct __sk_buff *skb) | |||
136 | } | 142 | } |
137 | 143 | ||
138 | if (congestion_flag) { | 144 | if (congestion_flag) { |
139 | if (!bpf_skb_ecn_set_ce(skb)) { | 145 | if (bpf_skb_ecn_set_ce(skb)) { |
140 | if (len > LARGE_PKT_THRESH) { | 146 | ecn_ce_flag = true; |
147 | } else { | ||
148 | if (pkti.is_tcp) { | ||
149 | unsigned int rand = bpf_get_prandom_u32(); | ||
150 | |||
151 | if (-credit >= MARK_THRESH + | ||
152 | (rand % MARK_REGION_SIZE)) { | ||
153 | // Do congestion control | ||
154 | cwr_flag = true; | ||
155 | } | ||
156 | } else if (len > LARGE_PKT_THRESH) { | ||
141 | // Problem if too many small packets? | 157 | // Problem if too many small packets? |
142 | drop_flag = true; | 158 | drop_flag = true; |
143 | } | 159 | } |
144 | } | 160 | } |
145 | } | 161 | } |
146 | 162 | ||
147 | if (drop_flag) | 163 | if (qsp != NULL) |
148 | rv = DROP_PKT; | 164 | if (qsp->no_cn) |
165 | cwr_flag = false; | ||
149 | 166 | ||
150 | hbm_update_stats(qsp, len, curtime, congestion_flag, drop_flag); | 167 | hbm_update_stats(qsp, len, curtime, congestion_flag, drop_flag, |
168 | cwr_flag, ecn_ce_flag, &pkti, credit); | ||
151 | 169 | ||
152 | if (rv == DROP_PKT) | 170 | if (drop_flag) { |
153 | __sync_add_and_fetch(&(qdp->credit), len); | 171 | __sync_add_and_fetch(&(qdp->credit), len); |
172 | rv = DROP_PKT; | ||
173 | } | ||
154 | 174 | ||
175 | if (cwr_flag) | ||
176 | rv |= 2; | ||
155 | return rv; | 177 | return rv; |
156 | } | 178 | } |
157 | char _license[] SEC("license") = "GPL"; | 179 | char _license[] SEC("license") = "GPL"; |
diff --git a/samples/bpf/tcp_basertt_kern.c b/samples/bpf/tcp_basertt_kern.c index 6ef1625e8b2c..9dba48c2b920 100644 --- a/samples/bpf/tcp_basertt_kern.c +++ b/samples/bpf/tcp_basertt_kern.c | |||
@@ -21,13 +21,6 @@ | |||
21 | 21 | ||
22 | #define DEBUG 1 | 22 | #define DEBUG 1 |
23 | 23 | ||
24 | #define bpf_printk(fmt, ...) \ | ||
25 | ({ \ | ||
26 | char ____fmt[] = fmt; \ | ||
27 | bpf_trace_printk(____fmt, sizeof(____fmt), \ | ||
28 | ##__VA_ARGS__); \ | ||
29 | }) | ||
30 | |||
31 | SEC("sockops") | 24 | SEC("sockops") |
32 | int bpf_basertt(struct bpf_sock_ops *skops) | 25 | int bpf_basertt(struct bpf_sock_ops *skops) |
33 | { | 26 | { |
diff --git a/samples/bpf/tcp_bufs_kern.c b/samples/bpf/tcp_bufs_kern.c index e03e204739fa..af8486f33771 100644 --- a/samples/bpf/tcp_bufs_kern.c +++ b/samples/bpf/tcp_bufs_kern.c | |||
@@ -22,13 +22,6 @@ | |||
22 | 22 | ||
23 | #define DEBUG 1 | 23 | #define DEBUG 1 |
24 | 24 | ||
25 | #define bpf_printk(fmt, ...) \ | ||
26 | ({ \ | ||
27 | char ____fmt[] = fmt; \ | ||
28 | bpf_trace_printk(____fmt, sizeof(____fmt), \ | ||
29 | ##__VA_ARGS__); \ | ||
30 | }) | ||
31 | |||
32 | SEC("sockops") | 25 | SEC("sockops") |
33 | int bpf_bufs(struct bpf_sock_ops *skops) | 26 | int bpf_bufs(struct bpf_sock_ops *skops) |
34 | { | 27 | { |
diff --git a/samples/bpf/tcp_clamp_kern.c b/samples/bpf/tcp_clamp_kern.c index a0dc2d254aca..26c0fd091f3c 100644 --- a/samples/bpf/tcp_clamp_kern.c +++ b/samples/bpf/tcp_clamp_kern.c | |||
@@ -22,13 +22,6 @@ | |||
22 | 22 | ||
23 | #define DEBUG 1 | 23 | #define DEBUG 1 |
24 | 24 | ||
25 | #define bpf_printk(fmt, ...) \ | ||
26 | ({ \ | ||
27 | char ____fmt[] = fmt; \ | ||
28 | bpf_trace_printk(____fmt, sizeof(____fmt), \ | ||
29 | ##__VA_ARGS__); \ | ||
30 | }) | ||
31 | |||
32 | SEC("sockops") | 25 | SEC("sockops") |
33 | int bpf_clamp(struct bpf_sock_ops *skops) | 26 | int bpf_clamp(struct bpf_sock_ops *skops) |
34 | { | 27 | { |
diff --git a/samples/bpf/tcp_cong_kern.c b/samples/bpf/tcp_cong_kern.c index 4fd3ca979a06..6d4dc4c7dd1e 100644 --- a/samples/bpf/tcp_cong_kern.c +++ b/samples/bpf/tcp_cong_kern.c | |||
@@ -21,13 +21,6 @@ | |||
21 | 21 | ||
22 | #define DEBUG 1 | 22 | #define DEBUG 1 |
23 | 23 | ||
24 | #define bpf_printk(fmt, ...) \ | ||
25 | ({ \ | ||
26 | char ____fmt[] = fmt; \ | ||
27 | bpf_trace_printk(____fmt, sizeof(____fmt), \ | ||
28 | ##__VA_ARGS__); \ | ||
29 | }) | ||
30 | |||
31 | SEC("sockops") | 24 | SEC("sockops") |
32 | int bpf_cong(struct bpf_sock_ops *skops) | 25 | int bpf_cong(struct bpf_sock_ops *skops) |
33 | { | 26 | { |
diff --git a/samples/bpf/tcp_iw_kern.c b/samples/bpf/tcp_iw_kern.c index 9b139ec69560..da61d53378b3 100644 --- a/samples/bpf/tcp_iw_kern.c +++ b/samples/bpf/tcp_iw_kern.c | |||
@@ -22,13 +22,6 @@ | |||
22 | 22 | ||
23 | #define DEBUG 1 | 23 | #define DEBUG 1 |
24 | 24 | ||
25 | #define bpf_printk(fmt, ...) \ | ||
26 | ({ \ | ||
27 | char ____fmt[] = fmt; \ | ||
28 | bpf_trace_printk(____fmt, sizeof(____fmt), \ | ||
29 | ##__VA_ARGS__); \ | ||
30 | }) | ||
31 | |||
32 | SEC("sockops") | 25 | SEC("sockops") |
33 | int bpf_iw(struct bpf_sock_ops *skops) | 26 | int bpf_iw(struct bpf_sock_ops *skops) |
34 | { | 27 | { |
diff --git a/samples/bpf/tcp_rwnd_kern.c b/samples/bpf/tcp_rwnd_kern.c index cc71ee96e044..d011e38b80d2 100644 --- a/samples/bpf/tcp_rwnd_kern.c +++ b/samples/bpf/tcp_rwnd_kern.c | |||
@@ -21,13 +21,6 @@ | |||
21 | 21 | ||
22 | #define DEBUG 1 | 22 | #define DEBUG 1 |
23 | 23 | ||
24 | #define bpf_printk(fmt, ...) \ | ||
25 | ({ \ | ||
26 | char ____fmt[] = fmt; \ | ||
27 | bpf_trace_printk(____fmt, sizeof(____fmt), \ | ||
28 | ##__VA_ARGS__); \ | ||
29 | }) | ||
30 | |||
31 | SEC("sockops") | 24 | SEC("sockops") |
32 | int bpf_rwnd(struct bpf_sock_ops *skops) | 25 | int bpf_rwnd(struct bpf_sock_ops *skops) |
33 | { | 26 | { |
diff --git a/samples/bpf/tcp_synrto_kern.c b/samples/bpf/tcp_synrto_kern.c index ca87ed34f896..720d1950322d 100644 --- a/samples/bpf/tcp_synrto_kern.c +++ b/samples/bpf/tcp_synrto_kern.c | |||
@@ -21,13 +21,6 @@ | |||
21 | 21 | ||
22 | #define DEBUG 1 | 22 | #define DEBUG 1 |
23 | 23 | ||
24 | #define bpf_printk(fmt, ...) \ | ||
25 | ({ \ | ||
26 | char ____fmt[] = fmt; \ | ||
27 | bpf_trace_printk(____fmt, sizeof(____fmt), \ | ||
28 | ##__VA_ARGS__); \ | ||
29 | }) | ||
30 | |||
31 | SEC("sockops") | 24 | SEC("sockops") |
32 | int bpf_synrto(struct bpf_sock_ops *skops) | 25 | int bpf_synrto(struct bpf_sock_ops *skops) |
33 | { | 26 | { |
diff --git a/samples/bpf/tcp_tos_reflect_kern.c b/samples/bpf/tcp_tos_reflect_kern.c index de788be6f862..369faca70a15 100644 --- a/samples/bpf/tcp_tos_reflect_kern.c +++ b/samples/bpf/tcp_tos_reflect_kern.c | |||
@@ -20,13 +20,6 @@ | |||
20 | 20 | ||
21 | #define DEBUG 1 | 21 | #define DEBUG 1 |
22 | 22 | ||
23 | #define bpf_printk(fmt, ...) \ | ||
24 | ({ \ | ||
25 | char ____fmt[] = fmt; \ | ||
26 | bpf_trace_printk(____fmt, sizeof(____fmt), \ | ||
27 | ##__VA_ARGS__); \ | ||
28 | }) | ||
29 | |||
30 | SEC("sockops") | 23 | SEC("sockops") |
31 | int bpf_basertt(struct bpf_sock_ops *skops) | 24 | int bpf_basertt(struct bpf_sock_ops *skops) |
32 | { | 25 | { |
diff --git a/samples/bpf/test_cgrp2_attach2.c b/samples/bpf/test_cgrp2_attach2.c deleted file mode 100644 index 0bb6507256b7..000000000000 --- a/samples/bpf/test_cgrp2_attach2.c +++ /dev/null | |||
@@ -1,459 +0,0 @@ | |||
1 | /* eBPF example program: | ||
2 | * | ||
3 | * - Creates arraymap in kernel with 4 bytes keys and 8 byte values | ||
4 | * | ||
5 | * - Loads eBPF program | ||
6 | * | ||
7 | * The eBPF program accesses the map passed in to store two pieces of | ||
8 | * information. The number of invocations of the program, which maps | ||
9 | * to the number of packets received, is stored to key 0. Key 1 is | ||
10 | * incremented on each iteration by the number of bytes stored in | ||
11 | * the skb. The program also stores the number of received bytes | ||
12 | * in the cgroup storage. | ||
13 | * | ||
14 | * - Attaches the new program to a cgroup using BPF_PROG_ATTACH | ||
15 | * | ||
16 | * - Every second, reads map[0] and map[1] to see how many bytes and | ||
17 | * packets were seen on any socket of tasks in the given cgroup. | ||
18 | */ | ||
19 | |||
20 | #define _GNU_SOURCE | ||
21 | |||
22 | #include <stdio.h> | ||
23 | #include <stdlib.h> | ||
24 | #include <assert.h> | ||
25 | #include <sys/resource.h> | ||
26 | #include <sys/time.h> | ||
27 | #include <unistd.h> | ||
28 | |||
29 | #include <linux/bpf.h> | ||
30 | #include <bpf/bpf.h> | ||
31 | |||
32 | #include "bpf_insn.h" | ||
33 | #include "bpf_rlimit.h" | ||
34 | #include "cgroup_helpers.h" | ||
35 | |||
36 | #define FOO "/foo" | ||
37 | #define BAR "/foo/bar/" | ||
38 | #define PING_CMD "ping -c1 -w1 127.0.0.1 > /dev/null" | ||
39 | |||
40 | char bpf_log_buf[BPF_LOG_BUF_SIZE]; | ||
41 | |||
42 | static int prog_load(int verdict) | ||
43 | { | ||
44 | int ret; | ||
45 | struct bpf_insn prog[] = { | ||
46 | BPF_MOV64_IMM(BPF_REG_0, verdict), /* r0 = verdict */ | ||
47 | BPF_EXIT_INSN(), | ||
48 | }; | ||
49 | size_t insns_cnt = sizeof(prog) / sizeof(struct bpf_insn); | ||
50 | |||
51 | ret = bpf_load_program(BPF_PROG_TYPE_CGROUP_SKB, | ||
52 | prog, insns_cnt, "GPL", 0, | ||
53 | bpf_log_buf, BPF_LOG_BUF_SIZE); | ||
54 | |||
55 | if (ret < 0) { | ||
56 | log_err("Loading program"); | ||
57 | printf("Output from verifier:\n%s\n-------\n", bpf_log_buf); | ||
58 | return 0; | ||
59 | } | ||
60 | return ret; | ||
61 | } | ||
62 | |||
63 | static int test_foo_bar(void) | ||
64 | { | ||
65 | int drop_prog, allow_prog, foo = 0, bar = 0, rc = 0; | ||
66 | |||
67 | allow_prog = prog_load(1); | ||
68 | if (!allow_prog) | ||
69 | goto err; | ||
70 | |||
71 | drop_prog = prog_load(0); | ||
72 | if (!drop_prog) | ||
73 | goto err; | ||
74 | |||
75 | if (setup_cgroup_environment()) | ||
76 | goto err; | ||
77 | |||
78 | /* Create cgroup /foo, get fd, and join it */ | ||
79 | foo = create_and_get_cgroup(FOO); | ||
80 | if (foo < 0) | ||
81 | goto err; | ||
82 | |||
83 | if (join_cgroup(FOO)) | ||
84 | goto err; | ||
85 | |||
86 | if (bpf_prog_attach(drop_prog, foo, BPF_CGROUP_INET_EGRESS, | ||
87 | BPF_F_ALLOW_OVERRIDE)) { | ||
88 | log_err("Attaching prog to /foo"); | ||
89 | goto err; | ||
90 | } | ||
91 | |||
92 | printf("Attached DROP prog. This ping in cgroup /foo should fail...\n"); | ||
93 | assert(system(PING_CMD) != 0); | ||
94 | |||
95 | /* Create cgroup /foo/bar, get fd, and join it */ | ||
96 | bar = create_and_get_cgroup(BAR); | ||
97 | if (bar < 0) | ||
98 | goto err; | ||
99 | |||
100 | if (join_cgroup(BAR)) | ||
101 | goto err; | ||
102 | |||
103 | printf("Attached DROP prog. This ping in cgroup /foo/bar should fail...\n"); | ||
104 | assert(system(PING_CMD) != 0); | ||
105 | |||
106 | if (bpf_prog_attach(allow_prog, bar, BPF_CGROUP_INET_EGRESS, | ||
107 | BPF_F_ALLOW_OVERRIDE)) { | ||
108 | log_err("Attaching prog to /foo/bar"); | ||
109 | goto err; | ||
110 | } | ||
111 | |||
112 | printf("Attached PASS prog. This ping in cgroup /foo/bar should pass...\n"); | ||
113 | assert(system(PING_CMD) == 0); | ||
114 | |||
115 | if (bpf_prog_detach(bar, BPF_CGROUP_INET_EGRESS)) { | ||
116 | log_err("Detaching program from /foo/bar"); | ||
117 | goto err; | ||
118 | } | ||
119 | |||
120 | printf("Detached PASS from /foo/bar while DROP is attached to /foo.\n" | ||
121 | "This ping in cgroup /foo/bar should fail...\n"); | ||
122 | assert(system(PING_CMD) != 0); | ||
123 | |||
124 | if (bpf_prog_attach(allow_prog, bar, BPF_CGROUP_INET_EGRESS, | ||
125 | BPF_F_ALLOW_OVERRIDE)) { | ||
126 | log_err("Attaching prog to /foo/bar"); | ||
127 | goto err; | ||
128 | } | ||
129 | |||
130 | if (bpf_prog_detach(foo, BPF_CGROUP_INET_EGRESS)) { | ||
131 | log_err("Detaching program from /foo"); | ||
132 | goto err; | ||
133 | } | ||
134 | |||
135 | printf("Attached PASS from /foo/bar and detached DROP from /foo.\n" | ||
136 | "This ping in cgroup /foo/bar should pass...\n"); | ||
137 | assert(system(PING_CMD) == 0); | ||
138 | |||
139 | if (bpf_prog_attach(allow_prog, bar, BPF_CGROUP_INET_EGRESS, | ||
140 | BPF_F_ALLOW_OVERRIDE)) { | ||
141 | log_err("Attaching prog to /foo/bar"); | ||
142 | goto err; | ||
143 | } | ||
144 | |||
145 | if (!bpf_prog_attach(allow_prog, bar, BPF_CGROUP_INET_EGRESS, 0)) { | ||
146 | errno = 0; | ||
147 | log_err("Unexpected success attaching prog to /foo/bar"); | ||
148 | goto err; | ||
149 | } | ||
150 | |||
151 | if (bpf_prog_detach(bar, BPF_CGROUP_INET_EGRESS)) { | ||
152 | log_err("Detaching program from /foo/bar"); | ||
153 | goto err; | ||
154 | } | ||
155 | |||
156 | if (!bpf_prog_detach(foo, BPF_CGROUP_INET_EGRESS)) { | ||
157 | errno = 0; | ||
158 | log_err("Unexpected success in double detach from /foo"); | ||
159 | goto err; | ||
160 | } | ||
161 | |||
162 | if (bpf_prog_attach(allow_prog, foo, BPF_CGROUP_INET_EGRESS, 0)) { | ||
163 | log_err("Attaching non-overridable prog to /foo"); | ||
164 | goto err; | ||
165 | } | ||
166 | |||
167 | if (!bpf_prog_attach(allow_prog, bar, BPF_CGROUP_INET_EGRESS, 0)) { | ||
168 | errno = 0; | ||
169 | log_err("Unexpected success attaching non-overridable prog to /foo/bar"); | ||
170 | goto err; | ||
171 | } | ||
172 | |||
173 | if (!bpf_prog_attach(allow_prog, bar, BPF_CGROUP_INET_EGRESS, | ||
174 | BPF_F_ALLOW_OVERRIDE)) { | ||
175 | errno = 0; | ||
176 | log_err("Unexpected success attaching overridable prog to /foo/bar"); | ||
177 | goto err; | ||
178 | } | ||
179 | |||
180 | if (!bpf_prog_attach(allow_prog, foo, BPF_CGROUP_INET_EGRESS, | ||
181 | BPF_F_ALLOW_OVERRIDE)) { | ||
182 | errno = 0; | ||
183 | log_err("Unexpected success attaching overridable prog to /foo"); | ||
184 | goto err; | ||
185 | } | ||
186 | |||
187 | if (bpf_prog_attach(drop_prog, foo, BPF_CGROUP_INET_EGRESS, 0)) { | ||
188 | log_err("Attaching different non-overridable prog to /foo"); | ||
189 | goto err; | ||
190 | } | ||
191 | |||
192 | goto out; | ||
193 | |||
194 | err: | ||
195 | rc = 1; | ||
196 | |||
197 | out: | ||
198 | close(foo); | ||
199 | close(bar); | ||
200 | cleanup_cgroup_environment(); | ||
201 | if (!rc) | ||
202 | printf("### override:PASS\n"); | ||
203 | else | ||
204 | printf("### override:FAIL\n"); | ||
205 | return rc; | ||
206 | } | ||
207 | |||
208 | static int map_fd = -1; | ||
209 | |||
210 | static int prog_load_cnt(int verdict, int val) | ||
211 | { | ||
212 | int cgroup_storage_fd, percpu_cgroup_storage_fd; | ||
213 | |||
214 | if (map_fd < 0) | ||
215 | map_fd = bpf_create_map(BPF_MAP_TYPE_ARRAY, 4, 8, 1, 0); | ||
216 | if (map_fd < 0) { | ||
217 | printf("failed to create map '%s'\n", strerror(errno)); | ||
218 | return -1; | ||
219 | } | ||
220 | |||
221 | cgroup_storage_fd = bpf_create_map(BPF_MAP_TYPE_CGROUP_STORAGE, | ||
222 | sizeof(struct bpf_cgroup_storage_key), 8, 0, 0); | ||
223 | if (cgroup_storage_fd < 0) { | ||
224 | printf("failed to create map '%s'\n", strerror(errno)); | ||
225 | return -1; | ||
226 | } | ||
227 | |||
228 | percpu_cgroup_storage_fd = bpf_create_map( | ||
229 | BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE, | ||
230 | sizeof(struct bpf_cgroup_storage_key), 8, 0, 0); | ||
231 | if (percpu_cgroup_storage_fd < 0) { | ||
232 | printf("failed to create map '%s'\n", strerror(errno)); | ||
233 | return -1; | ||
234 | } | ||
235 | |||
236 | struct bpf_insn prog[] = { | ||
237 | BPF_MOV32_IMM(BPF_REG_0, 0), | ||
238 | BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_0, -4), /* *(u32 *)(fp - 4) = r0 */ | ||
239 | BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), | ||
240 | BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -4), /* r2 = fp - 4 */ | ||
241 | BPF_LD_MAP_FD(BPF_REG_1, map_fd), | ||
242 | BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), | ||
243 | BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2), | ||
244 | BPF_MOV64_IMM(BPF_REG_1, val), /* r1 = 1 */ | ||
245 | BPF_RAW_INSN(BPF_STX | BPF_XADD | BPF_DW, BPF_REG_0, BPF_REG_1, 0, 0), /* xadd r0 += r1 */ | ||
246 | |||
247 | BPF_LD_MAP_FD(BPF_REG_1, cgroup_storage_fd), | ||
248 | BPF_MOV64_IMM(BPF_REG_2, 0), | ||
249 | BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_local_storage), | ||
250 | BPF_MOV64_IMM(BPF_REG_1, val), | ||
251 | BPF_RAW_INSN(BPF_STX | BPF_XADD | BPF_W, BPF_REG_0, BPF_REG_1, 0, 0), | ||
252 | |||
253 | BPF_LD_MAP_FD(BPF_REG_1, percpu_cgroup_storage_fd), | ||
254 | BPF_MOV64_IMM(BPF_REG_2, 0), | ||
255 | BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_local_storage), | ||
256 | BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_0, 0), | ||
257 | BPF_ALU64_IMM(BPF_ADD, BPF_REG_3, 0x1), | ||
258 | BPF_STX_MEM(BPF_W, BPF_REG_0, BPF_REG_3, 0), | ||
259 | |||
260 | BPF_MOV64_IMM(BPF_REG_0, verdict), /* r0 = verdict */ | ||
261 | BPF_EXIT_INSN(), | ||
262 | }; | ||
263 | size_t insns_cnt = sizeof(prog) / sizeof(struct bpf_insn); | ||
264 | int ret; | ||
265 | |||
266 | ret = bpf_load_program(BPF_PROG_TYPE_CGROUP_SKB, | ||
267 | prog, insns_cnt, "GPL", 0, | ||
268 | bpf_log_buf, BPF_LOG_BUF_SIZE); | ||
269 | |||
270 | if (ret < 0) { | ||
271 | log_err("Loading program"); | ||
272 | printf("Output from verifier:\n%s\n-------\n", bpf_log_buf); | ||
273 | return 0; | ||
274 | } | ||
275 | close(cgroup_storage_fd); | ||
276 | return ret; | ||
277 | } | ||
278 | |||
279 | |||
280 | static int test_multiprog(void) | ||
281 | { | ||
282 | __u32 prog_ids[4], prog_cnt = 0, attach_flags, saved_prog_id; | ||
283 | int cg1 = 0, cg2 = 0, cg3 = 0, cg4 = 0, cg5 = 0, key = 0; | ||
284 | int drop_prog, allow_prog[6] = {}, rc = 0; | ||
285 | unsigned long long value; | ||
286 | int i = 0; | ||
287 | |||
288 | for (i = 0; i < 6; i++) { | ||
289 | allow_prog[i] = prog_load_cnt(1, 1 << i); | ||
290 | if (!allow_prog[i]) | ||
291 | goto err; | ||
292 | } | ||
293 | drop_prog = prog_load_cnt(0, 1); | ||
294 | if (!drop_prog) | ||
295 | goto err; | ||
296 | |||
297 | if (setup_cgroup_environment()) | ||
298 | goto err; | ||
299 | |||
300 | cg1 = create_and_get_cgroup("/cg1"); | ||
301 | if (cg1 < 0) | ||
302 | goto err; | ||
303 | cg2 = create_and_get_cgroup("/cg1/cg2"); | ||
304 | if (cg2 < 0) | ||
305 | goto err; | ||
306 | cg3 = create_and_get_cgroup("/cg1/cg2/cg3"); | ||
307 | if (cg3 < 0) | ||
308 | goto err; | ||
309 | cg4 = create_and_get_cgroup("/cg1/cg2/cg3/cg4"); | ||
310 | if (cg4 < 0) | ||
311 | goto err; | ||
312 | cg5 = create_and_get_cgroup("/cg1/cg2/cg3/cg4/cg5"); | ||
313 | if (cg5 < 0) | ||
314 | goto err; | ||
315 | |||
316 | if (join_cgroup("/cg1/cg2/cg3/cg4/cg5")) | ||
317 | goto err; | ||
318 | |||
319 | if (bpf_prog_attach(allow_prog[0], cg1, BPF_CGROUP_INET_EGRESS, | ||
320 | BPF_F_ALLOW_MULTI)) { | ||
321 | log_err("Attaching prog to cg1"); | ||
322 | goto err; | ||
323 | } | ||
324 | if (!bpf_prog_attach(allow_prog[0], cg1, BPF_CGROUP_INET_EGRESS, | ||
325 | BPF_F_ALLOW_MULTI)) { | ||
326 | log_err("Unexpected success attaching the same prog to cg1"); | ||
327 | goto err; | ||
328 | } | ||
329 | if (bpf_prog_attach(allow_prog[1], cg1, BPF_CGROUP_INET_EGRESS, | ||
330 | BPF_F_ALLOW_MULTI)) { | ||
331 | log_err("Attaching prog2 to cg1"); | ||
332 | goto err; | ||
333 | } | ||
334 | if (bpf_prog_attach(allow_prog[2], cg2, BPF_CGROUP_INET_EGRESS, | ||
335 | BPF_F_ALLOW_OVERRIDE)) { | ||
336 | log_err("Attaching prog to cg2"); | ||
337 | goto err; | ||
338 | } | ||
339 | if (bpf_prog_attach(allow_prog[3], cg3, BPF_CGROUP_INET_EGRESS, | ||
340 | BPF_F_ALLOW_MULTI)) { | ||
341 | log_err("Attaching prog to cg3"); | ||
342 | goto err; | ||
343 | } | ||
344 | if (bpf_prog_attach(allow_prog[4], cg4, BPF_CGROUP_INET_EGRESS, | ||
345 | BPF_F_ALLOW_OVERRIDE)) { | ||
346 | log_err("Attaching prog to cg4"); | ||
347 | goto err; | ||
348 | } | ||
349 | if (bpf_prog_attach(allow_prog[5], cg5, BPF_CGROUP_INET_EGRESS, 0)) { | ||
350 | log_err("Attaching prog to cg5"); | ||
351 | goto err; | ||
352 | } | ||
353 | assert(system(PING_CMD) == 0); | ||
354 | assert(bpf_map_lookup_elem(map_fd, &key, &value) == 0); | ||
355 | assert(value == 1 + 2 + 8 + 32); | ||
356 | |||
357 | /* query the number of effective progs in cg5 */ | ||
358 | assert(bpf_prog_query(cg5, BPF_CGROUP_INET_EGRESS, BPF_F_QUERY_EFFECTIVE, | ||
359 | NULL, NULL, &prog_cnt) == 0); | ||
360 | assert(prog_cnt == 4); | ||
361 | /* retrieve prog_ids of effective progs in cg5 */ | ||
362 | assert(bpf_prog_query(cg5, BPF_CGROUP_INET_EGRESS, BPF_F_QUERY_EFFECTIVE, | ||
363 | &attach_flags, prog_ids, &prog_cnt) == 0); | ||
364 | assert(prog_cnt == 4); | ||
365 | assert(attach_flags == 0); | ||
366 | saved_prog_id = prog_ids[0]; | ||
367 | /* check enospc handling */ | ||
368 | prog_ids[0] = 0; | ||
369 | prog_cnt = 2; | ||
370 | assert(bpf_prog_query(cg5, BPF_CGROUP_INET_EGRESS, BPF_F_QUERY_EFFECTIVE, | ||
371 | &attach_flags, prog_ids, &prog_cnt) == -1 && | ||
372 | errno == ENOSPC); | ||
373 | assert(prog_cnt == 4); | ||
374 | /* check that prog_ids are returned even when buffer is too small */ | ||
375 | assert(prog_ids[0] == saved_prog_id); | ||
376 | /* retrieve prog_id of single attached prog in cg5 */ | ||
377 | prog_ids[0] = 0; | ||
378 | assert(bpf_prog_query(cg5, BPF_CGROUP_INET_EGRESS, 0, | ||
379 | NULL, prog_ids, &prog_cnt) == 0); | ||
380 | assert(prog_cnt == 1); | ||
381 | assert(prog_ids[0] == saved_prog_id); | ||
382 | |||
383 | /* detach bottom program and ping again */ | ||
384 | if (bpf_prog_detach2(-1, cg5, BPF_CGROUP_INET_EGRESS)) { | ||
385 | log_err("Detaching prog from cg5"); | ||
386 | goto err; | ||
387 | } | ||
388 | value = 0; | ||
389 | assert(bpf_map_update_elem(map_fd, &key, &value, 0) == 0); | ||
390 | assert(system(PING_CMD) == 0); | ||
391 | assert(bpf_map_lookup_elem(map_fd, &key, &value) == 0); | ||
392 | assert(value == 1 + 2 + 8 + 16); | ||
393 | |||
394 | /* detach 3rd from bottom program and ping again */ | ||
395 | errno = 0; | ||
396 | if (!bpf_prog_detach2(0, cg3, BPF_CGROUP_INET_EGRESS)) { | ||
397 | log_err("Unexpected success on detach from cg3"); | ||
398 | goto err; | ||
399 | } | ||
400 | if (bpf_prog_detach2(allow_prog[3], cg3, BPF_CGROUP_INET_EGRESS)) { | ||
401 | log_err("Detaching from cg3"); | ||
402 | goto err; | ||
403 | } | ||
404 | value = 0; | ||
405 | assert(bpf_map_update_elem(map_fd, &key, &value, 0) == 0); | ||
406 | assert(system(PING_CMD) == 0); | ||
407 | assert(bpf_map_lookup_elem(map_fd, &key, &value) == 0); | ||
408 | assert(value == 1 + 2 + 16); | ||
409 | |||
410 | /* detach 2nd from bottom program and ping again */ | ||
411 | if (bpf_prog_detach2(-1, cg4, BPF_CGROUP_INET_EGRESS)) { | ||
412 | log_err("Detaching prog from cg4"); | ||
413 | goto err; | ||
414 | } | ||
415 | value = 0; | ||
416 | assert(bpf_map_update_elem(map_fd, &key, &value, 0) == 0); | ||
417 | assert(system(PING_CMD) == 0); | ||
418 | assert(bpf_map_lookup_elem(map_fd, &key, &value) == 0); | ||
419 | assert(value == 1 + 2 + 4); | ||
420 | |||
421 | prog_cnt = 4; | ||
422 | assert(bpf_prog_query(cg5, BPF_CGROUP_INET_EGRESS, BPF_F_QUERY_EFFECTIVE, | ||
423 | &attach_flags, prog_ids, &prog_cnt) == 0); | ||
424 | assert(prog_cnt == 3); | ||
425 | assert(attach_flags == 0); | ||
426 | assert(bpf_prog_query(cg5, BPF_CGROUP_INET_EGRESS, 0, | ||
427 | NULL, prog_ids, &prog_cnt) == 0); | ||
428 | assert(prog_cnt == 0); | ||
429 | goto out; | ||
430 | err: | ||
431 | rc = 1; | ||
432 | |||
433 | out: | ||
434 | for (i = 0; i < 6; i++) | ||
435 | if (allow_prog[i] > 0) | ||
436 | close(allow_prog[i]); | ||
437 | close(cg1); | ||
438 | close(cg2); | ||
439 | close(cg3); | ||
440 | close(cg4); | ||
441 | close(cg5); | ||
442 | cleanup_cgroup_environment(); | ||
443 | if (!rc) | ||
444 | printf("### multi:PASS\n"); | ||
445 | else | ||
446 | printf("### multi:FAIL\n"); | ||
447 | return rc; | ||
448 | } | ||
449 | |||
450 | int main(int argc, char **argv) | ||
451 | { | ||
452 | int rc = 0; | ||
453 | |||
454 | rc = test_foo_bar(); | ||
455 | if (rc) | ||
456 | return rc; | ||
457 | |||
458 | return test_multiprog(); | ||
459 | } | ||
diff --git a/samples/bpf/xdp_sample_pkts_kern.c b/samples/bpf/xdp_sample_pkts_kern.c index f7ca8b850978..6c7c7e0aaeda 100644 --- a/samples/bpf/xdp_sample_pkts_kern.c +++ b/samples/bpf/xdp_sample_pkts_kern.c | |||
@@ -7,13 +7,6 @@ | |||
7 | #define SAMPLE_SIZE 64ul | 7 | #define SAMPLE_SIZE 64ul |
8 | #define MAX_CPUS 128 | 8 | #define MAX_CPUS 128 |
9 | 9 | ||
10 | #define bpf_printk(fmt, ...) \ | ||
11 | ({ \ | ||
12 | char ____fmt[] = fmt; \ | ||
13 | bpf_trace_printk(____fmt, sizeof(____fmt), \ | ||
14 | ##__VA_ARGS__); \ | ||
15 | }) | ||
16 | |||
17 | struct bpf_map_def SEC("maps") my_map = { | 10 | struct bpf_map_def SEC("maps") my_map = { |
18 | .type = BPF_MAP_TYPE_PERF_EVENT_ARRAY, | 11 | .type = BPF_MAP_TYPE_PERF_EVENT_ARRAY, |
19 | .key_size = sizeof(int), | 12 | .key_size = sizeof(int), |