Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

bpf: Add cn support to hbm_out_kern.c

Update hbm_out_kern.c to support returning cn notifications.
Also updates relevant files to allow disabling cn notifications.

Signed-off-by: Lawrence Brakmo <brakmo@fb.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

authored by

brakmo and committed by
Alexei Starovoitov
ffd81558 956fe219

+45 -12
+7 -3
samples/bpf/do_hbm_test.sh
··· 13 13 echo "egress or ingress bandwidht. It then uses iperf3 or netperf to create" 14 14 echo "loads. The output is the goodput in Mbps (unless -D was used)." 15 15 echo "" 16 - echo "USAGE: $name [out] [-b=<prog>|--bpf=<prog>] [-c=<cc>|--cc=<cc>] [-D]" 17 - echo " [-d=<delay>|--delay=<delay>] [--debug] [-E]" 16 + echo "USAGE: $name [out] [-b=<prog>|--bpf=<prog>] [-c=<cc>|--cc=<cc>]" 17 + echo " [-D] [-d=<delay>|--delay=<delay>] [--debug] [-E]" 18 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 20 echo " [-q=<qdisc>] [-R] [-s=<server>|--server=<server]" 21 21 echo " [-S|--stats] -t=<time>|--time=<time>] [-w] [cubic|dctcp]" 22 22 echo " Where:" ··· 33 33 echo " -f or --flows number of concurrent flows (default=1)" 34 34 echo " -i or --id cgroup id (an integer, default is 1)" 35 35 echo " -N use netperf instead of iperf3" 36 + echo " --no_cn Do not return CN notifications" 36 37 echo " -l do not limit flows using loopback" 37 38 echo " -h Help" 38 39 echo " -p or --port iperf3 port (default is 5201)" ··· 115 114 ;; 116 115 -c=*|--cc=*) 117 116 cc="${i#*=}" 117 + ;; 118 + --no_cn) 119 + flags="$flags --no_cn" 118 120 ;; 119 121 --debug) 120 122 flags="$flags -d"
+15 -3
samples/bpf/hbm.c
··· 16 16 * -l Also limit flows doing loopback 17 17 * -n <#> To create cgroup \"/hbm#\" and attach prog 18 18 * Default is /hbm1 19 + * --no_cn Do not return cn notifications 19 20 * -r <rate> Rate limit in Mbps 20 21 * -s Get HBM stats (marked, dropped, etc.) 21 22 * -t <time> Exit after specified seconds (default is 0) ··· 43 42 44 43 #include <linux/bpf.h> 45 44 #include <bpf/bpf.h> 45 + #include <getopt.h> 46 46 47 47 #include "bpf_load.h" 48 48 #include "bpf_rlimit.h" ··· 61 59 bool loopback_flag; 62 60 bool debugFlag; 63 61 bool work_conserving_flag; 62 + bool no_cn_flag; 64 63 65 64 static void Usage(void); 66 65 static void read_trace_pipe2(void); ··· 188 185 qstats.rate = rate; 189 186 qstats.stats = stats_flag ? 1 : 0; 190 187 qstats.loopback = loopback_flag ? 1 : 0; 188 + qstats.no_cn = no_cn_flag ? 1 : 0; 191 189 if (bpf_map_update_elem(map_fd, &key, &qstats, BPF_ANY)) { 192 190 printf("ERROR: Could not update map element\n"); 193 191 goto err; ··· 370 366 { 371 367 printf("This program loads a cgroup skb BPF program to enforce\n" 372 368 "cgroup output (egress) bandwidth limits.\n\n" 373 - "USAGE: hbm [-o] [-d] [-l] [-n <id>] [-r <rate>] [-s]\n" 374 - " [-t <secs>] [-w] [-h] [prog]\n" 369 + "USAGE: hbm [-o] [-d] [-l] [-n <id>] [--no_cn] [-r <rate>]\n" 370 + " [-s] [-t <secs>] [-w] [-h] [prog]\n" 375 371 " Where:\n" 376 372 " -o indicates egress direction (default)\n" 377 373 " -d print BPF trace debug buffer\n" 378 374 " -l also limit flows using loopback\n" 379 375 " -n <#> to create cgroup \"/hbm#\" and attach prog\n" 380 376 " Default is /hbm1\n" 377 + " --no_cn disable CN notifcations\n" 381 378 " -r <rate> Rate in Mbps\n" 382 379 " -s Update HBM stats\n" 383 380 " -t <time> Exit after specified seconds (default is 0)\n" ··· 398 393 int k; 399 394 int cg_id = 1; 400 395 char *optstring = "iodln:r:st:wh"; 396 + struct option loptions[] = { 397 + {"no_cn", 0, NULL, 1}, 398 + {NULL, 0, NULL, 0} 399 + }; 401 400 402 - while ((k = getopt(argc, argv, optstring)) != -1) { 401 + while ((k = getopt_long(argc, argv, optstring, loptions, NULL)) != -1) { 403 402 switch (k) { 403 + case 1: 404 + no_cn_flag = true; 405 + break; 404 406 case'o': 405 407 break; 406 408 case 'd':
+2 -1
samples/bpf/hbm.h
··· 19 19 struct hbm_queue_stats { 20 20 unsigned long rate; /* in Mbps*/ 21 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 24 unsigned long long pkts_marked; 24 25 unsigned long long bytes_marked; 25 26 unsigned long long pkts_dropped;
+21 -5
samples/bpf/hbm_out_kern.c
··· 119 119 // Set flags (drop, congestion, cwr) 120 120 // Dropping => we are congested, so ignore congestion flag 121 121 if (credit < -DROP_THRESH || 122 - (len > LARGE_PKT_THRESH && 123 - credit < -LARGE_PKT_DROP_THRESH)) { 124 - // Very congested, set drop flag 122 + (len > LARGE_PKT_THRESH && credit < -LARGE_PKT_DROP_THRESH)) { 123 + // Very congested, set drop packet 125 124 drop_flag = true; 125 + if (pkti.ecn) 126 + congestion_flag = true; 127 + else if (pkti.is_tcp) 128 + cwr_flag = true; 126 129 } else if (credit < 0) { 127 130 // Congested, set congestion flag 128 - if (pkti.ecn) { 131 + if (pkti.ecn || pkti.is_tcp) { 129 132 if (credit < -MARK_THRESH) 130 133 congestion_flag = true; 131 134 else ··· 140 137 141 138 if (congestion_flag) { 142 139 if (!bpf_skb_ecn_set_ce(skb)) { 143 - if (len > LARGE_PKT_THRESH) { 140 + if (pkti.is_tcp) { 141 + unsigned int rand = bpf_get_prandom_u32(); 142 + 143 + if (-credit >= MARK_THRESH + 144 + (rand % MARK_REGION_SIZE)) { 145 + // Do congestion control 146 + cwr_flag = true; 147 + } 148 + } else if (len > LARGE_PKT_THRESH) { 144 149 // Problem if too many small packets? 145 150 drop_flag = true; 146 151 } ··· 157 146 158 147 if (drop_flag) 159 148 rv = DROP_PKT; 149 + if (qsp != NULL) 150 + if (qsp->no_cn) 151 + cwr_flag = false; 160 152 161 153 hbm_update_stats(qsp, len, curtime, congestion_flag, drop_flag); 162 154 163 155 if (rv == DROP_PKT) 164 156 __sync_add_and_fetch(&(qdp->credit), len); 165 157 158 + if (cwr_flag) 159 + rv |= 2; 166 160 return rv; 167 161 } 168 162 char _license[] SEC("license") = "GPL";