bpf: Add more stats to HBM
authorbrakmo <brakmo@fb.com>
Tue, 28 May 2019 23:59:40 +0000 (16:59 -0700)
committerAlexei Starovoitov <ast@kernel.org>
Fri, 31 May 2019 23:41:29 +0000 (16:41 -0700)
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>
samples/bpf/hbm.c
samples/bpf/hbm.h
samples/bpf/hbm_kern.h
samples/bpf/hbm_out_kern.c

index c5629bae67ab6221d3ea1570ed2ae548a2005755..480b7ad6a1f20787023717f2e6c7ba1ec34bfd74 100644 (file)
@@ -316,6 +316,14 @@ static int run_bpf_prog(char *prog, int cg_id)
                double percent_pkts, percent_bytes;
                char fname[100];
                FILE *fout;
+               int k;
+               static const char *returnValNames[] = {
+                       "DROP_PKT",
+                       "ALLOW_PKT",
+                       "DROP_PKT_CWR",
+                       "ALLOW_PKT_CWR"
+               };
+#define RET_VAL_COUNT 4
 
 // Future support of ingress
 //             if (!outFlag)
@@ -350,6 +358,31 @@ static int run_bpf_prog(char *prog, int cg_id)
                        (qstats.bytes_total + 1);
                fprintf(fout, "pkts_dropped_percent:%6.2f\n", percent_pkts);
                fprintf(fout, "bytes_dropped_percent:%6.2f\n", percent_bytes);
+
+               // ECN CE markings
+               percent_pkts = (qstats.pkts_ecn_ce * 100.0) /
+                       (qstats.pkts_total + 1);
+               fprintf(fout, "pkts_ecn_ce:%6.2f (%d)\n", percent_pkts,
+                       (int)qstats.pkts_ecn_ce);
+
+               // Average cwnd
+               fprintf(fout, "avg cwnd:%d\n",
+                       (int)(qstats.sum_cwnd / (qstats.sum_cwnd_cnt + 1)));
+               // Average rtt
+               fprintf(fout, "avg rtt:%d\n",
+                       (int)(qstats.sum_rtt / (qstats.pkts_total + 1)));
+               // Average credit
+               fprintf(fout, "avg credit:%d\n",
+                       (int)(qstats.sum_credit /
+                             (1500 * ((int)qstats.pkts_total) + 1)));
+
+               // Return values stats
+               for (k = 0; k < RET_VAL_COUNT; k++) {
+                       percent_pkts = (qstats.returnValCount[k] * 100.0) /
+                               (qstats.pkts_total + 1);
+                       fprintf(fout, "%s:%6.2f (%d)\n", returnValNames[k],
+                               percent_pkts, (int)qstats.returnValCount[k]);
+               }
                fclose(fout);
        }
 
index c08247cec2a702f3d9b9817b40e6d03f649f3fce..f0963ed6a5620dbb8d29a66105294b17c5f264d5 100644 (file)
@@ -29,4 +29,10 @@ struct hbm_queue_stats {
        unsigned long long bytes_total;
        unsigned long long firstPacketTime;
        unsigned long long lastPacketTime;
+       unsigned long long pkts_ecn_ce;
+       unsigned long long returnValCount[4];
+       unsigned long long sum_cwnd;
+       unsigned long long sum_rtt;
+       unsigned long long sum_cwnd_cnt;
+       long long sum_credit;
 };
index 41384be233b9b84d247e0f8c1a119b4513a73303..be19cf1d5cd5c70577f3ec2e63cf48913e72c8e0 100644 (file)
@@ -65,17 +65,43 @@ struct bpf_map_def SEC("maps") queue_stats = {
 BPF_ANNOTATE_KV_PAIR(queue_stats, int, struct hbm_queue_stats);
 
 struct hbm_pkt_info {
+       int     cwnd;
+       int     rtt;
        bool    is_ip;
        bool    is_tcp;
        short   ecn;
 };
 
+static int get_tcp_info(struct __sk_buff *skb, struct hbm_pkt_info *pkti)
+{
+       struct bpf_sock *sk;
+       struct bpf_tcp_sock *tp;
+
+       sk = skb->sk;
+       if (sk) {
+               sk = bpf_sk_fullsock(sk);
+               if (sk) {
+                       if (sk->protocol == IPPROTO_TCP) {
+                               tp = bpf_tcp_sock(sk);
+                               if (tp) {
+                                       pkti->cwnd = tp->snd_cwnd;
+                                       pkti->rtt = tp->srtt_us >> 3;
+                                       return 0;
+                               }
+                       }
+               }
+       }
+       return 1;
+}
+
 static __always_inline void hbm_get_pkt_info(struct __sk_buff *skb,
                                             struct hbm_pkt_info *pkti)
 {
        struct iphdr iph;
        struct ipv6hdr *ip6h;
 
+       pkti->cwnd = 0;
+       pkti->rtt = 0;
        bpf_skb_load_bytes(skb, 0, &iph, 12);
        if (iph.version == 6) {
                ip6h = (struct ipv6hdr *)&iph;
@@ -91,6 +117,8 @@ static __always_inline void hbm_get_pkt_info(struct __sk_buff *skb,
                pkti->is_tcp = false;
                pkti->ecn = 0;
        }
+       if (pkti->is_tcp)
+               get_tcp_info(skb, pkti);
 }
 
 static __always_inline void hbm_init_vqueue(struct hbm_vqueue *qdp, int rate)
@@ -105,8 +133,14 @@ static __always_inline void hbm_update_stats(struct hbm_queue_stats *qsp,
                                             int len,
                                             unsigned long long curtime,
                                             bool congestion_flag,
-                                            bool drop_flag)
+                                            bool drop_flag,
+                                            bool cwr_flag,
+                                            bool ecn_ce_flag,
+                                            struct hbm_pkt_info *pkti,
+                                            int credit)
 {
+       int rv = ALLOW_PKT;
+
        if (qsp != NULL) {
                // Following is needed for work conserving
                __sync_add_and_fetch(&(qsp->bytes_total), len);
@@ -116,7 +150,7 @@ static __always_inline void hbm_update_stats(struct hbm_queue_stats *qsp,
                                qsp->firstPacketTime = curtime;
                        qsp->lastPacketTime = curtime;
                        __sync_add_and_fetch(&(qsp->pkts_total), 1);
-                       if (congestion_flag || drop_flag) {
+                       if (congestion_flag) {
                                __sync_add_and_fetch(&(qsp->pkts_marked), 1);
                                __sync_add_and_fetch(&(qsp->bytes_marked), len);
                        }
@@ -125,6 +159,34 @@ static __always_inline void hbm_update_stats(struct hbm_queue_stats *qsp,
                                __sync_add_and_fetch(&(qsp->bytes_dropped),
                                                     len);
                        }
+                       if (ecn_ce_flag)
+                               __sync_add_and_fetch(&(qsp->pkts_ecn_ce), 1);
+                       if (pkti->cwnd) {
+                               __sync_add_and_fetch(&(qsp->sum_cwnd),
+                                                    pkti->cwnd);
+                               __sync_add_and_fetch(&(qsp->sum_cwnd_cnt), 1);
+                       }
+                       if (pkti->rtt)
+                               __sync_add_and_fetch(&(qsp->sum_rtt),
+                                                    pkti->rtt);
+                       __sync_add_and_fetch(&(qsp->sum_credit), credit);
+
+                       if (drop_flag)
+                               rv = DROP_PKT;
+                       if (cwr_flag)
+                               rv |= 2;
+                       if (rv == DROP_PKT)
+                               __sync_add_and_fetch(&(qsp->returnValCount[0]),
+                                                    1);
+                       else if (rv == ALLOW_PKT)
+                               __sync_add_and_fetch(&(qsp->returnValCount[1]),
+                                                    1);
+                       else if (rv == 2)
+                               __sync_add_and_fetch(&(qsp->returnValCount[2]),
+                                                    1);
+                       else if (rv == 3)
+                               __sync_add_and_fetch(&(qsp->returnValCount[3]),
+                                                    1);
                }
        }
 }
index fa3ea92e1564ae80a853bb6089945ff213e11bb9..829934bd43cbe8da0c65570ad7fe51343ab6544a 100644 (file)
@@ -62,11 +62,12 @@ int _hbm_out_cg(struct __sk_buff *skb)
        unsigned int queue_index = 0;
        unsigned long long curtime;
        int credit;
-       signed long long delta = 0, zero = 0;
+       signed long long delta = 0, new_credit;
        int max_credit = MAX_CREDIT;
        bool congestion_flag = false;
        bool drop_flag = false;
        bool cwr_flag = false;
+       bool ecn_ce_flag = false;
        struct hbm_vqueue *qdp;
        struct hbm_queue_stats *qsp = NULL;
        int rv = ALLOW_PKT;
@@ -99,9 +100,11 @@ int _hbm_out_cg(struct __sk_buff *skb)
         */
        if (delta > 0) {
                qdp->lasttime = curtime;
-               credit += CREDIT_PER_NS(delta, qdp->rate);
-               if (credit > MAX_CREDIT)
+               new_credit = credit + CREDIT_PER_NS(delta, qdp->rate);
+               if (new_credit > MAX_CREDIT)
                        credit = MAX_CREDIT;
+               else
+                       credit = new_credit;
        }
        credit -= len;
        qdp->credit = credit;
@@ -139,7 +142,9 @@ int _hbm_out_cg(struct __sk_buff *skb)
        }
 
        if (congestion_flag) {
-               if (!bpf_skb_ecn_set_ce(skb)) {
+               if (bpf_skb_ecn_set_ce(skb)) {
+                       ecn_ce_flag = true;
+               } else {
                        if (pkti.is_tcp) {
                                unsigned int rand = bpf_get_prandom_u32();
 
@@ -155,16 +160,17 @@ int _hbm_out_cg(struct __sk_buff *skb)
                }
        }
 
-       if (drop_flag)
-               rv = DROP_PKT;
        if (qsp != NULL)
                if (qsp->no_cn)
                        cwr_flag = false;
 
-       hbm_update_stats(qsp, len, curtime, congestion_flag, drop_flag);
+       hbm_update_stats(qsp, len, curtime, congestion_flag, drop_flag,
+                        cwr_flag, ecn_ce_flag, &pkti, credit);
 
-       if (rv == DROP_PKT)
+       if (drop_flag) {
                __sync_add_and_fetch(&(qdp->credit), len);
+               rv = DROP_PKT;
+       }
 
        if (cwr_flag)
                rv |= 2;