monitor: Plot RX information with -a/--analyze
authorLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
Mon, 7 Aug 2023 21:45:34 +0000 (14:45 -0700)
committerAyush Garg <ayush.garg@samsung.com>
Fri, 5 Jan 2024 13:34:03 +0000 (19:04 +0530)
This attempts to plot the RX information just as TX:

  Found BR-ACL connection with handle 256
        Address: XX:XX:XX:XX:XX:XX
        RX packets: 60/60
        RX Latency: 0-39040 msec (~20294 msec)
        RX size: 6-344 octets (~34 octets)
        RX speed: ~0 Kb/s

  100 +-+------------------------------------------------------------------+
       +|                                                                  |
       +|                                                       RX +-----+ |
       +|                                                                  |
       +|                                                                  |
       +|                                                                  |
        |                                                                  |
        |                                                                  |
   10 +-|                                                                  |
       +|                                                                  |
       +|                                                                  |
       +|                                                                  |
       +|                                                                  |
       +|                                                                  |
        |                                                                  |
        |                                                                  |
    1 +-|  + +                                                           + |
       +|  | |                                                           | |
       ++------------------------------------------------------------------+
        +       +        +       +        +       +       +        +       +
        0      5000    10000   15000    20000   25000   30000    35000   40000
                                   Latency (ms)

        TX packets: 22548/22547
        TX Latency: 3-73 msec (~11 msec)
        TX size: 6-850 octets (~847 octets)
        TX speed: ~568 Kb/s

monitor/analyze.c

index 213405d..7d0d6dd 100755 (executable)
@@ -61,23 +61,27 @@ struct hci_dev {
 #define CONN_LE_ACL    0x04
 #define CONN_LE_ISO    0x05
 
+struct hci_stats {
+       size_t bytes;
+       size_t num;
+       size_t num_comp;
+       struct packet_latency latency;
+       struct queue *plot;
+       uint16_t min;
+       uint16_t max;
+};
+
 struct hci_conn {
        uint16_t handle;
        uint8_t type;
        uint8_t bdaddr[6];
        bool setup_seen;
        bool terminated;
-       unsigned long rx_num;
-       unsigned long tx_num;
-       unsigned long tx_num_comp;
-       size_t tx_bytes;
        struct queue *tx_queue;
-       struct packet_latency tx_l;
-       struct queue *plot;
-       uint16_t tx_pkt_min;
-       uint16_t tx_pkt_max;
-       uint16_t tx_pkt_med;
+       struct timeval last_rx;
        struct queue *chan_list;
+       struct hci_stats rx;
+       struct hci_stats tx;
 };
 
 struct hci_conn_tx {
@@ -94,12 +98,9 @@ struct l2cap_chan {
        uint16_t cid;
        uint16_t psm;
        bool out;
-       unsigned long num;
-       size_t tx_bytes;
-       struct packet_latency tx_l;
-       struct queue *plot;
-       uint16_t tx_pkt_min;
-       uint16_t tx_pkt_max;
+       struct timeval last_rx;
+       struct hci_stats rx;
+       struct hci_stats tx;
 };
 
 static struct queue *dev_list;
@@ -112,7 +113,7 @@ static void tmp_write(void *data, void *user_data)
        fprintf(tmp, "%lld %zu\n", plot->x_msec, plot->y_count);
 }
 
-static void plot_draw(struct queue *queue)
+static void plot_draw(struct queue *queue, const char *tittle)
 {
        FILE *gplot;
 
@@ -132,37 +133,48 @@ static void plot_draw(struct queue *queue)
        fprintf(gplot, "set tics out nomirror\n");
        fprintf(gplot, "set log y\n");
        fprintf(gplot, "set yrange [0.5:*]\n");
-       fprintf(gplot, "plot $data using 1:2 t 'Packets' w impulses\n");
+       fprintf(gplot, "plot $data using 1:2 t '%s' w impulses\n", tittle);
        fflush(gplot);
 
        pclose(gplot);
 }
 
+static void print_stats(struct hci_stats *stats, const char *label)
+{
+       if (!stats->num)
+               return;
+
+       print_field("%s packets: %zu/%zu", label, stats->num, stats->num_comp);
+       print_field("%s Latency: %lld-%lld msec (~%lld msec)", label,
+                       TV_MSEC(stats->latency.min),
+                       TV_MSEC(stats->latency.max),
+                       TV_MSEC(stats->latency.med));
+       print_field("%s size: %u-%u octets (~%zd octets)", label,
+                       stats->min, stats->max, stats->bytes / stats->num);
+
+       if (TV_MSEC(stats->latency.total))
+               print_field("%s speed: ~%lld Kb/s", label,
+                       stats->bytes * 8 / TV_MSEC(stats->latency.total));
+
+       plot_draw(stats->plot, label);
+}
+
 static void chan_destroy(void *data)
 {
        struct l2cap_chan *chan = data;
 
+       if (!chan->rx.num && !chan->tx.num)
+               goto done;
+
        printf("  Found %s L2CAP channel with CID %u\n",
                                        chan->out ? "TX" : "RX", chan->cid);
        if (chan->psm)
                print_field("PSM %u", chan->psm);
 
-       print_field("%lu packets", chan->num);
-
-       if (!queue_isempty(chan->plot)) {
-               print_field("%lld-%lld msec (~%lld msec) TX Latency",
-                       TV_MSEC(chan->tx_l.min), TV_MSEC(chan->tx_l.max),
-                       TV_MSEC(chan->tx_l.med));
-               print_field("%u-%u octets TX packet size",
-                               chan->tx_pkt_min, chan->tx_pkt_max);
-       }
-
-       if (TV_MSEC(chan->tx_l.total))
-               print_field("~%lld Kb/s TX transfer speed",
-                               chan->tx_bytes * 8 / TV_MSEC(chan->tx_l.total));
-
-       plot_draw(chan->plot);
+       print_stats(&chan->rx, "RX");
+       print_stats(&chan->tx, "TX");
 
+done:
        free(chan);
 }
 
@@ -175,7 +187,8 @@ static struct l2cap_chan *chan_alloc(struct hci_conn *conn, uint16_t cid,
 
        chan->cid = cid;
        chan->out = out;
-       chan->plot = queue_new();
+       chan->rx.plot = queue_new();
+       chan->tx.plot = queue_new();
 
        return chan;
 }
@@ -231,30 +244,16 @@ static void conn_destroy(void *data)
                break;
        }
 
-       if (conn->tx_num > 0)
-               conn->tx_pkt_med = conn->tx_bytes / conn->tx_num;
-
        printf("  Found %s connection with handle %u\n", str, conn->handle);
        /* TODO: Store address type */
        packet_print_addr("Address", conn->bdaddr, 0x00);
        if (!conn->setup_seen)
                print_field("Connection setup missing");
-       print_field("%lu RX packets", conn->rx_num);
-       print_field("%lu TX packets", conn->tx_num);
-       print_field("%lu TX completed packets", conn->tx_num_comp);
-       print_field("%lld-%lld msec (~%lld msec) TX Latency",
-                       TV_MSEC(conn->tx_l.min), TV_MSEC(conn->tx_l.max),
-                       TV_MSEC(conn->tx_l.med));
-       print_field("%u-%u octets (~%u octets) TX packet size",
-                       conn->tx_pkt_min, conn->tx_pkt_max, conn->tx_pkt_med);
-
-       if (TV_MSEC(conn->tx_l.total))
-               print_field("~%lld Kb/s TX transfer speed",
-                       conn->tx_bytes * 8 / TV_MSEC(conn->tx_l.total));
-
-       plot_draw(conn->plot);
-
-       queue_destroy(conn->plot, free);
+       print_stats(&conn->rx, "RX");
+       print_stats(&conn->tx, "TX");
+
+       queue_destroy(conn->rx.plot, free);
+       queue_destroy(conn->tx.plot, free);
        queue_destroy(conn->chan_list, chan_destroy);
 
        queue_destroy(conn->tx_queue, free);
@@ -271,7 +270,8 @@ static struct hci_conn *conn_alloc(struct hci_dev *dev, uint16_t handle,
        conn->handle = handle;
        conn->type = type;
        conn->tx_queue = queue_new();
-       conn->plot = queue_new();
+       conn->tx.plot = queue_new();
+       conn->rx.plot = queue_new();
 
        conn->chan_list = queue_new();
 
@@ -568,7 +568,7 @@ static void evt_num_completed_packets(struct hci_dev *dev, struct timeval *tv,
                if (!conn)
                        continue;
 
-               conn->tx_num_comp += count;
+               conn->tx.num_comp += count;
 
                for (j = 0; j < count; j++) {
                        last_tx = queue_pop_head(conn->tx_queue);
@@ -577,12 +577,14 @@ static void evt_num_completed_packets(struct hci_dev *dev, struct timeval *tv,
 
                                timersub(tv, &last_tx->tv, &res);
 
-                               packet_latency_add(&conn->tx_l, &res);
-                               plot_add(conn->plot, &res, 1);
+                               packet_latency_add(&conn->tx.latency, &res);
+                               plot_add(conn->tx.plot, &res, 1);
 
                                if (chan) {
-                                       packet_latency_add(&chan->tx_l, &res);
-                                       plot_add(chan->plot, &res, 1);
+                                       chan->tx.num_comp += count;
+                                       packet_latency_add(&chan->tx.latency,
+                                                                       &res);
+                                       plot_add(chan->tx.plot, &res, 1);
                                }
 
                                free(last_tx);
@@ -735,31 +737,60 @@ static void event_pkt(struct timeval *tv, uint16_t index,
        }
 }
 
+static void stats_add(struct hci_stats *stats, uint16_t size)
+{
+       stats->num++;
+       stats->bytes += size;
+
+       if (!stats->min || size < stats->min)
+               stats->min = size;
+       if (!stats->max || size > stats->max)
+               stats->max = size;
+}
+
 static void conn_pkt_tx(struct hci_conn *conn, struct timeval *tv,
                                uint16_t size, struct l2cap_chan *chan)
 {
        struct hci_conn_tx *last_tx;
 
-       conn->tx_num++;
-
        last_tx = new0(struct hci_conn_tx, 1);
        memcpy(last_tx, tv, sizeof(*tv));
        last_tx->chan = chan;
        queue_push_tail(conn->tx_queue, last_tx);
-       conn->tx_bytes += size;
 
-       if (!conn->tx_pkt_min || size < conn->tx_pkt_min)
-               conn->tx_pkt_min = size;
-       if (!conn->tx_pkt_max || size > conn->tx_pkt_max)
-               conn->tx_pkt_max = size;
+       stats_add(&conn->tx, size);
+
+       if (chan)
+               stats_add(&chan->tx, size);
+}
+
+static void conn_pkt_rx(struct hci_conn *conn, struct timeval *tv,
+                               uint16_t size, struct l2cap_chan *chan)
+{
+       struct timeval res;
+
+       if (timerisset(&conn->last_rx)) {
+               timersub(tv, &conn->last_rx, &res);
+               packet_latency_add(&conn->rx.latency, &res);
+               plot_add(conn->rx.plot, &res, 1);
+       }
+
+       conn->last_rx = *tv;
+
+       stats_add(&conn->rx, size);
+       conn->rx.num_comp++;
 
        if (chan) {
-               chan->tx_bytes += size;
+               if (timerisset(&chan->last_rx)) {
+                       timersub(tv, &chan->last_rx, &res);
+                       packet_latency_add(&chan->rx.latency, &res);
+                       plot_add(chan->rx.plot, &res, 1);
+               }
 
-               if (!chan->tx_pkt_min || size < chan->tx_pkt_min)
-                       chan->tx_pkt_min = size;
-               if (!chan->tx_pkt_max || size > chan->tx_pkt_max)
-                       chan->tx_pkt_max = size;
+               chan->last_rx = *tv;
+
+               stats_add(&chan->rx, size);
+               chan->rx.num_comp++;
        }
 }
 
@@ -792,8 +823,6 @@ static void acl_pkt(struct timeval *tv, uint16_t index, bool out,
        case 0x02:
                cid = get_le16(data + 2);
                chan = chan_lookup(conn, cid, out);
-               if (chan)
-                       chan->num++;
                if (cid == 1)
                        l2cap_sig(conn, out, data + 4, size - 4);
                break;
@@ -802,7 +831,7 @@ static void acl_pkt(struct timeval *tv, uint16_t index, bool out,
        if (out) {
                conn_pkt_tx(conn, tv, size, chan);
        } else {
-               conn->rx_num++;
+               conn_pkt_rx(conn, tv, size, chan);
        }
 }
 
@@ -828,7 +857,7 @@ static void sco_pkt(struct timeval *tv, uint16_t index, bool out,
        if (out) {
                conn_pkt_tx(conn, tv, size - sizeof(*hdr), NULL);
        } else {
-               conn->rx_num++;
+               conn_pkt_rx(conn, tv, size - sizeof(*hdr), NULL);
        }
 }
 
@@ -915,7 +944,7 @@ static void iso_pkt(struct timeval *tv, uint16_t index, bool out,
        if (out) {
                conn_pkt_tx(conn, tv, size - sizeof(*hdr), NULL);
        } else {
-               conn->rx_num++;
+               conn_pkt_rx(conn, tv, size - sizeof(*hdr), NULL);
        }
 }