xref: /aosp_15_r20/external/bcc/tools/netqtop.c (revision 387f9dfdfa2baef462e92476d413c7bc2470293e)
1*387f9dfdSAndroid Build Coastguard Worker 
2*387f9dfdSAndroid Build Coastguard Worker #include <linux/netdevice.h>
3*387f9dfdSAndroid Build Coastguard Worker #include <linux/ethtool.h>
4*387f9dfdSAndroid Build Coastguard Worker #if IFNAMSIZ != 16
5*387f9dfdSAndroid Build Coastguard Worker #error "IFNAMSIZ != 16 is not supported"
6*387f9dfdSAndroid Build Coastguard Worker #endif
7*387f9dfdSAndroid Build Coastguard Worker #define MAX_QUEUE_NUM 1024
8*387f9dfdSAndroid Build Coastguard Worker 
9*387f9dfdSAndroid Build Coastguard Worker /**
10*387f9dfdSAndroid Build Coastguard Worker * This union is use to store name of the specified interface
11*387f9dfdSAndroid Build Coastguard Worker * and read it as two different data types
12*387f9dfdSAndroid Build Coastguard Worker */
13*387f9dfdSAndroid Build Coastguard Worker union name_buf{
14*387f9dfdSAndroid Build Coastguard Worker     char name[IFNAMSIZ];
15*387f9dfdSAndroid Build Coastguard Worker     struct {
16*387f9dfdSAndroid Build Coastguard Worker         u64 hi;
17*387f9dfdSAndroid Build Coastguard Worker         u64 lo;
18*387f9dfdSAndroid Build Coastguard Worker     }name_int;
19*387f9dfdSAndroid Build Coastguard Worker };
20*387f9dfdSAndroid Build Coastguard Worker 
21*387f9dfdSAndroid Build Coastguard Worker /* data retrieved in tracepoints */
22*387f9dfdSAndroid Build Coastguard Worker struct queue_data{
23*387f9dfdSAndroid Build Coastguard Worker     u64 total_pkt_len;
24*387f9dfdSAndroid Build Coastguard Worker     u32 num_pkt;
25*387f9dfdSAndroid Build Coastguard Worker     u32 size_64B;
26*387f9dfdSAndroid Build Coastguard Worker     u32 size_512B;
27*387f9dfdSAndroid Build Coastguard Worker     u32 size_2K;
28*387f9dfdSAndroid Build Coastguard Worker     u32 size_16K;
29*387f9dfdSAndroid Build Coastguard Worker     u32 size_64K;
30*387f9dfdSAndroid Build Coastguard Worker };
31*387f9dfdSAndroid Build Coastguard Worker 
32*387f9dfdSAndroid Build Coastguard Worker /* array of length 1 for device name */
33*387f9dfdSAndroid Build Coastguard Worker BPF_ARRAY(name_map, union name_buf, 1);
34*387f9dfdSAndroid Build Coastguard Worker /* table for transmit & receive packets */
35*387f9dfdSAndroid Build Coastguard Worker BPF_HASH(tx_q, u16, struct queue_data, MAX_QUEUE_NUM);
36*387f9dfdSAndroid Build Coastguard Worker BPF_HASH(rx_q, u16, struct queue_data, MAX_QUEUE_NUM);
37*387f9dfdSAndroid Build Coastguard Worker 
name_filter(struct sk_buff * skb)38*387f9dfdSAndroid Build Coastguard Worker static inline int name_filter(struct sk_buff* skb){
39*387f9dfdSAndroid Build Coastguard Worker     /* get device name from skb */
40*387f9dfdSAndroid Build Coastguard Worker     union name_buf real_devname;
41*387f9dfdSAndroid Build Coastguard Worker     struct net_device *dev;
42*387f9dfdSAndroid Build Coastguard Worker     bpf_probe_read(&dev, sizeof(skb->dev), ((char *)skb + offsetof(struct sk_buff, dev)));
43*387f9dfdSAndroid Build Coastguard Worker     bpf_probe_read(&real_devname, IFNAMSIZ, dev->name);
44*387f9dfdSAndroid Build Coastguard Worker 
45*387f9dfdSAndroid Build Coastguard Worker     int key=0;
46*387f9dfdSAndroid Build Coastguard Worker     union name_buf *leaf = name_map.lookup(&key);
47*387f9dfdSAndroid Build Coastguard Worker     if(!leaf){
48*387f9dfdSAndroid Build Coastguard Worker         return 0;
49*387f9dfdSAndroid Build Coastguard Worker     }
50*387f9dfdSAndroid Build Coastguard Worker     if((leaf->name_int).hi != real_devname.name_int.hi || (leaf->name_int).lo != real_devname.name_int.lo){
51*387f9dfdSAndroid Build Coastguard Worker         return 0;
52*387f9dfdSAndroid Build Coastguard Worker     }
53*387f9dfdSAndroid Build Coastguard Worker 
54*387f9dfdSAndroid Build Coastguard Worker     return 1;
55*387f9dfdSAndroid Build Coastguard Worker }
56*387f9dfdSAndroid Build Coastguard Worker 
updata_data(struct queue_data * data,u64 len)57*387f9dfdSAndroid Build Coastguard Worker static void updata_data(struct queue_data *data, u64 len){
58*387f9dfdSAndroid Build Coastguard Worker     data->total_pkt_len += len;
59*387f9dfdSAndroid Build Coastguard Worker     data->num_pkt ++;
60*387f9dfdSAndroid Build Coastguard Worker     if(len / 64 == 0){
61*387f9dfdSAndroid Build Coastguard Worker         data->size_64B ++;
62*387f9dfdSAndroid Build Coastguard Worker     }
63*387f9dfdSAndroid Build Coastguard Worker     else if(len / 512 == 0){
64*387f9dfdSAndroid Build Coastguard Worker         data->size_512B ++;
65*387f9dfdSAndroid Build Coastguard Worker     }
66*387f9dfdSAndroid Build Coastguard Worker     else if(len / 2048 == 0){
67*387f9dfdSAndroid Build Coastguard Worker         data->size_2K ++;
68*387f9dfdSAndroid Build Coastguard Worker     }
69*387f9dfdSAndroid Build Coastguard Worker     else if(len / 16384 == 0){
70*387f9dfdSAndroid Build Coastguard Worker         data->size_16K ++;
71*387f9dfdSAndroid Build Coastguard Worker     }
72*387f9dfdSAndroid Build Coastguard Worker     else if(len / 65536 == 0){
73*387f9dfdSAndroid Build Coastguard Worker         data->size_64K ++;
74*387f9dfdSAndroid Build Coastguard Worker     }
75*387f9dfdSAndroid Build Coastguard Worker }
76*387f9dfdSAndroid Build Coastguard Worker 
TRACEPOINT_PROBE(net,net_dev_start_xmit)77*387f9dfdSAndroid Build Coastguard Worker TRACEPOINT_PROBE(net, net_dev_start_xmit){
78*387f9dfdSAndroid Build Coastguard Worker     /* read device name */
79*387f9dfdSAndroid Build Coastguard Worker     struct sk_buff* skb = (struct sk_buff*)args->skbaddr;
80*387f9dfdSAndroid Build Coastguard Worker     if(!name_filter(skb)){
81*387f9dfdSAndroid Build Coastguard Worker         return 0;
82*387f9dfdSAndroid Build Coastguard Worker     }
83*387f9dfdSAndroid Build Coastguard Worker 
84*387f9dfdSAndroid Build Coastguard Worker     /* update table */
85*387f9dfdSAndroid Build Coastguard Worker     u16 qid = skb->queue_mapping;
86*387f9dfdSAndroid Build Coastguard Worker     struct queue_data newdata;
87*387f9dfdSAndroid Build Coastguard Worker     __builtin_memset(&newdata, 0, sizeof(newdata));
88*387f9dfdSAndroid Build Coastguard Worker     struct queue_data *data = tx_q.lookup_or_try_init(&qid, &newdata);
89*387f9dfdSAndroid Build Coastguard Worker     if(!data){
90*387f9dfdSAndroid Build Coastguard Worker         return 0;
91*387f9dfdSAndroid Build Coastguard Worker     }
92*387f9dfdSAndroid Build Coastguard Worker     updata_data(data, skb->len);
93*387f9dfdSAndroid Build Coastguard Worker 
94*387f9dfdSAndroid Build Coastguard Worker     return 0;
95*387f9dfdSAndroid Build Coastguard Worker }
96*387f9dfdSAndroid Build Coastguard Worker 
TRACEPOINT_PROBE(net,netif_receive_skb)97*387f9dfdSAndroid Build Coastguard Worker TRACEPOINT_PROBE(net, netif_receive_skb){
98*387f9dfdSAndroid Build Coastguard Worker     struct sk_buff skb;
99*387f9dfdSAndroid Build Coastguard Worker 
100*387f9dfdSAndroid Build Coastguard Worker     bpf_probe_read(&skb, sizeof(skb), args->skbaddr);
101*387f9dfdSAndroid Build Coastguard Worker     if(!name_filter(&skb)){
102*387f9dfdSAndroid Build Coastguard Worker         return 0;
103*387f9dfdSAndroid Build Coastguard Worker     }
104*387f9dfdSAndroid Build Coastguard Worker 
105*387f9dfdSAndroid Build Coastguard Worker     /* case 1: if the NIC does not support multi-queue feature, there is only
106*387f9dfdSAndroid Build Coastguard Worker      *         one queue(qid is always 0).
107*387f9dfdSAndroid Build Coastguard Worker      * case 2: if the NIC supports multi-queue feature, there are several queues
108*387f9dfdSAndroid Build Coastguard Worker      *         with different qid(from 0 to n-1).
109*387f9dfdSAndroid Build Coastguard Worker      * The net device driver should mark queue id by API 'skb_record_rx_queue'
110*387f9dfdSAndroid Build Coastguard Worker      * for a recieved skb, otherwise it should be a BUG(all of the packets are
111*387f9dfdSAndroid Build Coastguard Worker      * reported as queue 0). For example, virtio net driver is fixed for linux:
112*387f9dfdSAndroid Build Coastguard Worker      * commit: 133bbb18ab1a2("virtio-net: per-queue RPS config")
113*387f9dfdSAndroid Build Coastguard Worker      */
114*387f9dfdSAndroid Build Coastguard Worker     u16 qid = 0;
115*387f9dfdSAndroid Build Coastguard Worker     if (skb_rx_queue_recorded(&skb))
116*387f9dfdSAndroid Build Coastguard Worker         qid = skb_get_rx_queue(&skb);
117*387f9dfdSAndroid Build Coastguard Worker 
118*387f9dfdSAndroid Build Coastguard Worker     struct queue_data newdata;
119*387f9dfdSAndroid Build Coastguard Worker     __builtin_memset(&newdata, 0, sizeof(newdata));
120*387f9dfdSAndroid Build Coastguard Worker     struct queue_data *data = rx_q.lookup_or_try_init(&qid, &newdata);
121*387f9dfdSAndroid Build Coastguard Worker     if(!data){
122*387f9dfdSAndroid Build Coastguard Worker         return 0;
123*387f9dfdSAndroid Build Coastguard Worker     }
124*387f9dfdSAndroid Build Coastguard Worker     updata_data(data, skb.len);
125*387f9dfdSAndroid Build Coastguard Worker 
126*387f9dfdSAndroid Build Coastguard Worker     return 0;
127*387f9dfdSAndroid Build Coastguard Worker }
128