aboutsummaryrefslogtreecommitdiffstats
path: root/samples/bpf
diff options
context:
space:
mode:
Diffstat (limited to 'samples/bpf')
-rw-r--r--samples/bpf/.gitignore1
-rw-r--r--samples/bpf/Makefile2
-rw-r--r--samples/bpf/bpf_load.c8
-rwxr-xr-xsamples/bpf/do_hbm_test.sh10
-rw-r--r--samples/bpf/hbm.c51
-rw-r--r--samples/bpf/hbm.h9
-rw-r--r--samples/bpf/hbm_kern.h77
-rw-r--r--samples/bpf/hbm_out_kern.c48
-rw-r--r--samples/bpf/tcp_basertt_kern.c7
-rw-r--r--samples/bpf/tcp_bufs_kern.c7
-rw-r--r--samples/bpf/tcp_clamp_kern.c7
-rw-r--r--samples/bpf/tcp_cong_kern.c7
-rw-r--r--samples/bpf/tcp_iw_kern.c7
-rw-r--r--samples/bpf/tcp_rwnd_kern.c7
-rw-r--r--samples/bpf/tcp_synrto_kern.c7
-rw-r--r--samples/bpf/tcp_tos_reflect_kern.c7
-rw-r--r--samples/bpf/test_cgrp2_attach2.c459
-rw-r--r--samples/bpf/xdp_sample_pkts_kern.c7
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 @@
1cpustat 1cpustat
2fds_example 2fds_example
3hbm 3hbm
4ibumad
4lathist 5lathist
5lwt_len_hist 6lwt_len_hist
6map_perf_test 7map_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
26hostprogs-y += test_overhead 26hostprogs-y += test_overhead
27hostprogs-y += test_cgrp2_array_pin 27hostprogs-y += test_cgrp2_array_pin
28hostprogs-y += test_cgrp2_attach 28hostprogs-y += test_cgrp2_attach
29hostprogs-y += test_cgrp2_attach2
30hostprogs-y += test_cgrp2_sock 29hostprogs-y += test_cgrp2_sock
31hostprogs-y += test_cgrp2_sock2 30hostprogs-y += test_cgrp2_sock2
32hostprogs-y += xdp1 31hostprogs-y += xdp1
@@ -81,7 +80,6 @@ map_perf_test-objs := bpf_load.o map_perf_test_user.o
81test_overhead-objs := bpf_load.o test_overhead_user.o 80test_overhead-objs := bpf_load.o test_overhead_user.o
82test_cgrp2_array_pin-objs := test_cgrp2_array_pin.o 81test_cgrp2_array_pin-objs := test_cgrp2_array_pin.o
83test_cgrp2_attach-objs := test_cgrp2_attach.o 82test_cgrp2_attach-objs := test_cgrp2_attach.o
84test_cgrp2_attach2-objs := test_cgrp2_attach2.o $(CGROUP_HELPERS)
85test_cgrp2_sock-objs := test_cgrp2_sock.o 83test_cgrp2_sock-objs := test_cgrp2_sock.o
86test_cgrp2_sock2-objs := bpf_load.o test_cgrp2_sock2.o 84test_cgrp2_sock2-objs := bpf_load.o test_cgrp2_sock2.o
87xdp1-objs := xdp1_user.o 85xdp1-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;
40int prog_array_fd = -1; 40int prog_array_fd = -1;
41 41
42struct bpf_map_data map_data[MAX_MAPS]; 42struct bpf_map_data map_data[MAX_MAPS];
43int map_data_count = 0; 43int map_data_count;
44 44
45static int populate_prog_array(const char *event, int prog_fd) 45static 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;
59bool loopback_flag; 61bool loopback_flag;
60bool debugFlag; 62bool debugFlag;
61bool work_conserving_flag; 63bool work_conserving_flag;
64bool no_cn_flag;
62 65
63static void Usage(void); 66static void Usage(void);
64static void read_trace_pipe2(void); 67static 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 {
19struct hbm_queue_stats { 19struct 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 = {
72BPF_ANNOTATE_KV_PAIR(queue_stats, int, struct hbm_queue_stats); 65BPF_ANNOTATE_KV_PAIR(queue_stats, int, struct hbm_queue_stats);
73 66
74struct hbm_pkt_info { 67struct 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
75static 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
80static __always_inline void hbm_get_pkt_info(struct __sk_buff *skb, 97static __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
103static __always_inline void hbm_init_vqueue(struct hbm_vqueue *qdp, int rate) 124static __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}
157char _license[] SEC("license") = "GPL"; 179char _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
31SEC("sockops") 24SEC("sockops")
32int bpf_basertt(struct bpf_sock_ops *skops) 25int 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
32SEC("sockops") 25SEC("sockops")
33int bpf_bufs(struct bpf_sock_ops *skops) 26int 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
32SEC("sockops") 25SEC("sockops")
33int bpf_clamp(struct bpf_sock_ops *skops) 26int 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
31SEC("sockops") 24SEC("sockops")
32int bpf_cong(struct bpf_sock_ops *skops) 25int 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
32SEC("sockops") 25SEC("sockops")
33int bpf_iw(struct bpf_sock_ops *skops) 26int 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
31SEC("sockops") 24SEC("sockops")
32int bpf_rwnd(struct bpf_sock_ops *skops) 25int 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
31SEC("sockops") 24SEC("sockops")
32int bpf_synrto(struct bpf_sock_ops *skops) 25int 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
30SEC("sockops") 23SEC("sockops")
31int bpf_basertt(struct bpf_sock_ops *skops) 24int 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
40char bpf_log_buf[BPF_LOG_BUF_SIZE];
41
42static 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
63static 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
194err:
195 rc = 1;
196
197out:
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
208static int map_fd = -1;
209
210static 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
280static 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;
430err:
431 rc = 1;
432
433out:
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
450int 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
17struct bpf_map_def SEC("maps") my_map = { 10struct 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),