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

bpf: Add more stats to HBM

Adds more stats to HBM, including average cwnd and rtt of all TCP
flows, percents of packets that are ecn ce marked and distribution
of return values.

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

authored by

brakmo and committed by
Alexei Starovoitov
d58c6f72 ffd81558

+117 -10
+33
samples/bpf/hbm.c
··· 316 316 double percent_pkts, percent_bytes; 317 317 char fname[100]; 318 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 319 327 320 328 // Future support of ingress 321 329 // if (!outFlag) ··· 358 350 (qstats.bytes_total + 1); 359 351 fprintf(fout, "pkts_dropped_percent:%6.2f\n", percent_pkts); 360 352 fprintf(fout, "bytes_dropped_percent:%6.2f\n", percent_bytes); 353 + 354 + // ECN CE markings 355 + percent_pkts = (qstats.pkts_ecn_ce * 100.0) / 356 + (qstats.pkts_total + 1); 357 + fprintf(fout, "pkts_ecn_ce:%6.2f (%d)\n", percent_pkts, 358 + (int)qstats.pkts_ecn_ce); 359 + 360 + // Average cwnd 361 + fprintf(fout, "avg cwnd:%d\n", 362 + (int)(qstats.sum_cwnd / (qstats.sum_cwnd_cnt + 1))); 363 + // Average rtt 364 + fprintf(fout, "avg rtt:%d\n", 365 + (int)(qstats.sum_rtt / (qstats.pkts_total + 1))); 366 + // Average credit 367 + fprintf(fout, "avg credit:%d\n", 368 + (int)(qstats.sum_credit / 369 + (1500 * ((int)qstats.pkts_total) + 1))); 370 + 371 + // Return values stats 372 + for (k = 0; k < RET_VAL_COUNT; k++) { 373 + percent_pkts = (qstats.returnValCount[k] * 100.0) / 374 + (qstats.pkts_total + 1); 375 + fprintf(fout, "%s:%6.2f (%d)\n", returnValNames[k], 376 + percent_pkts, (int)qstats.returnValCount[k]); 377 + } 361 378 fclose(fout); 362 379 } 363 380
+6
samples/bpf/hbm.h
··· 29 29 unsigned long long bytes_total; 30 30 unsigned long long firstPacketTime; 31 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; 32 38 };
+64 -2
samples/bpf/hbm_kern.h
··· 65 65 BPF_ANNOTATE_KV_PAIR(queue_stats, int, struct hbm_queue_stats); 66 66 67 67 struct hbm_pkt_info { 68 + int cwnd; 69 + int rtt; 68 70 bool is_ip; 69 71 bool is_tcp; 70 72 short ecn; 71 73 }; 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 + } 72 96 73 97 static __always_inline void hbm_get_pkt_info(struct __sk_buff *skb, 74 98 struct hbm_pkt_info *pkti) ··· 100 76 struct iphdr iph; 101 77 struct ipv6hdr *ip6h; 102 78 79 + pkti->cwnd = 0; 80 + pkti->rtt = 0; 103 81 bpf_skb_load_bytes(skb, 0, &iph, 12); 104 82 if (iph.version == 6) { 105 83 ip6h = (struct ipv6hdr *)&iph; ··· 117 91 pkti->is_tcp = false; 118 92 pkti->ecn = 0; 119 93 } 94 + if (pkti->is_tcp) 95 + get_tcp_info(skb, pkti); 120 96 } 121 97 122 98 static __always_inline void hbm_init_vqueue(struct hbm_vqueue *qdp, int rate) ··· 133 105 int len, 134 106 unsigned long long curtime, 135 107 bool congestion_flag, 136 - bool drop_flag) 108 + bool drop_flag, 109 + bool cwr_flag, 110 + bool ecn_ce_flag, 111 + struct hbm_pkt_info *pkti, 112 + int credit) 137 113 { 114 + int rv = ALLOW_PKT; 115 + 138 116 if (qsp != NULL) { 139 117 // Following is needed for work conserving 140 118 __sync_add_and_fetch(&(qsp->bytes_total), len); ··· 150 116 qsp->firstPacketTime = curtime; 151 117 qsp->lastPacketTime = curtime; 152 118 __sync_add_and_fetch(&(qsp->pkts_total), 1); 153 - if (congestion_flag || drop_flag) { 119 + if (congestion_flag) { 154 120 __sync_add_and_fetch(&(qsp->pkts_marked), 1); 155 121 __sync_add_and_fetch(&(qsp->bytes_marked), len); 156 122 } ··· 159 125 __sync_add_and_fetch(&(qsp->bytes_dropped), 160 126 len); 161 127 } 128 + if (ecn_ce_flag) 129 + __sync_add_and_fetch(&(qsp->pkts_ecn_ce), 1); 130 + if (pkti->cwnd) { 131 + __sync_add_and_fetch(&(qsp->sum_cwnd), 132 + pkti->cwnd); 133 + __sync_add_and_fetch(&(qsp->sum_cwnd_cnt), 1); 134 + } 135 + if (pkti->rtt) 136 + __sync_add_and_fetch(&(qsp->sum_rtt), 137 + pkti->rtt); 138 + __sync_add_and_fetch(&(qsp->sum_credit), credit); 139 + 140 + if (drop_flag) 141 + rv = DROP_PKT; 142 + if (cwr_flag) 143 + rv |= 2; 144 + if (rv == DROP_PKT) 145 + __sync_add_and_fetch(&(qsp->returnValCount[0]), 146 + 1); 147 + else if (rv == ALLOW_PKT) 148 + __sync_add_and_fetch(&(qsp->returnValCount[1]), 149 + 1); 150 + else if (rv == 2) 151 + __sync_add_and_fetch(&(qsp->returnValCount[2]), 152 + 1); 153 + else if (rv == 3) 154 + __sync_add_and_fetch(&(qsp->returnValCount[3]), 155 + 1); 162 156 } 163 157 } 164 158 }
+14 -8
samples/bpf/hbm_out_kern.c
··· 62 62 unsigned int queue_index = 0; 63 63 unsigned long long curtime; 64 64 int credit; 65 - signed long long delta = 0, zero = 0; 65 + signed long long delta = 0, new_credit; 66 66 int max_credit = MAX_CREDIT; 67 67 bool congestion_flag = false; 68 68 bool drop_flag = false; 69 69 bool cwr_flag = false; 70 + bool ecn_ce_flag = false; 70 71 struct hbm_vqueue *qdp; 71 72 struct hbm_queue_stats *qsp = NULL; 72 73 int rv = ALLOW_PKT; ··· 100 99 */ 101 100 if (delta > 0) { 102 101 qdp->lasttime = curtime; 103 - credit += CREDIT_PER_NS(delta, qdp->rate); 104 - if (credit > MAX_CREDIT) 102 + new_credit = credit + CREDIT_PER_NS(delta, qdp->rate); 103 + if (new_credit > MAX_CREDIT) 105 104 credit = MAX_CREDIT; 105 + else 106 + credit = new_credit; 106 107 } 107 108 credit -= len; 108 109 qdp->credit = credit; ··· 142 139 } 143 140 144 141 if (congestion_flag) { 145 - if (!bpf_skb_ecn_set_ce(skb)) { 142 + if (bpf_skb_ecn_set_ce(skb)) { 143 + ecn_ce_flag = true; 144 + } else { 146 145 if (pkti.is_tcp) { 147 146 unsigned int rand = bpf_get_prandom_u32(); 148 147 ··· 160 155 } 161 156 } 162 157 163 - if (drop_flag) 164 - rv = DROP_PKT; 165 158 if (qsp != NULL) 166 159 if (qsp->no_cn) 167 160 cwr_flag = false; 168 161 169 - hbm_update_stats(qsp, len, curtime, congestion_flag, drop_flag); 162 + hbm_update_stats(qsp, len, curtime, congestion_flag, drop_flag, 163 + cwr_flag, ecn_ce_flag, &pkti, credit); 170 164 171 - if (rv == DROP_PKT) 165 + if (drop_flag) { 172 166 __sync_add_and_fetch(&(qdp->credit), len); 167 + rv = DROP_PKT; 168 + } 173 169 174 170 if (cwr_flag) 175 171 rv |= 2;