From: Tang Longjun <[email protected]>

track the status upon receiving host notifications by using the kprobe
functions skb_xmit_done and skb_recv_done.

Signed-off-by: Tang Longjun <[email protected]>
---
 tools/virtio/virtnet_mon/virtnet_mon.c | 82 +++++++++++++++++++++++++-
 1 file changed, 81 insertions(+), 1 deletion(-)

diff --git a/tools/virtio/virtnet_mon/virtnet_mon.c 
b/tools/virtio/virtnet_mon/virtnet_mon.c
index 69b4afcbeb56..09f566d3443f 100644
--- a/tools/virtio/virtnet_mon/virtnet_mon.c
+++ b/tools/virtio/virtnet_mon/virtnet_mon.c
@@ -442,6 +442,10 @@ enum event_type {
        GRO_RECEIVE_SKB_POST_EVENT = 4,
        IP_LOCAL_DELIVER_PRE_EVENT = 5,
        IP_LOCAL_DELIVER_POST_EVENT = 6,
+       SKB_XMIT_DONE_PRE_EVENT = 7,
+       SKB_XMIT_DONE_POST_EVENT = 8,
+       SKB_RECV_DONE_PRE_EVENT = 9,
+       SKB_RECV_DONE_POST_EVENT = 10,
 };
 
 struct iph_info {
@@ -485,6 +489,8 @@ static char read_buf[READ_SIZE];
 static struct kprobe start_xmit_kp;
 static struct kprobe gro_receive_skb_kp;
 static struct kprobe ip_local_deliver_kp;
+static struct kprobe skb_xmit_done_kp;
+static struct kprobe skb_recv_done_kp;
 
 /* convert pkt_dir to string */
 static const char *pkt_dir_to_str(enum pkt_dir dir)
@@ -530,6 +536,14 @@ static const char *event_type_to_str(enum event_type 
event_type)
                return "IP_LOCAL_DELIVER_PRE_EVENT";
        case IP_LOCAL_DELIVER_POST_EVENT:
                return "IP_LOCAL_DELIVER_POST_EVENT";
+       case SKB_XMIT_DONE_PRE_EVENT:
+               return "SKB_XMIT_DONE_PRE_EVENT";
+       case SKB_XMIT_DONE_POST_EVENT:
+               return "SKB_XMIT_DONE_POST_EVENT";
+       case SKB_RECV_DONE_PRE_EVENT:
+               return "SKB_RECV_DONE_PRE_EVENT";
+       case SKB_RECV_DONE_POST_EVENT:
+               return "SKB_RECV_DONE_POST_EVENT";
        default:
                return "Unknown";
        }
@@ -784,6 +798,46 @@ static int ip_local_deliver_pre_handler(struct kprobe *p, 
struct pt_regs *regs)
        return 0;
 }
 
+/* Kprobe pre-handler for skb_xmit_done */
+static int skb_xmit_done_pre_handler(struct kprobe *p, struct pt_regs *regs)
+{
+       struct virtqueue *vq;
+       struct virtnet_mon_pkt_info info;
+
+       /* Get vq parameter (first parameter) */
+       vq = (struct virtqueue *)KP_GET_ARG(regs, 0);
+
+       memset(&info, 0, sizeof(struct virtnet_mon_pkt_info));
+       get_common_info(PKT_DIR_TX, SKB_XMIT_DONE_PRE_EVENT, &info);
+       if (get_queue_info(vq, &info.rx_tx_queue_info) != 0)
+               return 0;
+
+       kfifo_in(&virtnet_mon_kfifo, &info, 1);
+       wake_up_interruptible(&virtnet_mon_wq);
+
+       return 0;
+}
+
+/* Kprobe pre-handler for skb_recv_done */
+static int skb_recv_done_pre_handler(struct kprobe *p, struct pt_regs *regs)
+{
+       struct virtqueue *vq;
+       struct virtnet_mon_pkt_info info;
+
+       /* Get vq parameter (first parameter) */
+       vq = (struct virtqueue *)KP_GET_ARG(regs, 0);
+
+       memset(&info, 0, sizeof(struct virtnet_mon_pkt_info));
+       get_common_info(PKT_DIR_RX, SKB_RECV_DONE_PRE_EVENT, &info);
+       if (get_queue_info(vq, &info.rx_tx_queue_info) != 0)
+               return 0;
+
+       kfifo_in(&virtnet_mon_kfifo, &info, 1);
+       wake_up_interruptible(&virtnet_mon_wq);
+
+       return 0;
+}
+
 // open device
 static int virtnet_mon_open(struct inode *inode, struct file *file)
 {
@@ -943,6 +997,30 @@ static int __init virtnet_mon_init(void)
        }
        pr_info("virtnet_mon: Registered kprobe for ip_local_deliver\n");
 
+       /* Setup kprobe for skb_xmit_done */
+       skb_xmit_done_kp.pre_handler = skb_xmit_done_pre_handler;
+       skb_xmit_done_kp.symbol_name = "skb_xmit_done";
+
+       ret = register_kprobe(&skb_xmit_done_kp);
+       if (ret < 0) {
+               pr_info("virtnet_mon: Failed to register kprobe for 
skb_xmit_done: %d\n", ret);
+               unregister_kprobe(&skb_xmit_done_kp);
+               return ret;
+       }
+       pr_info("virtnet_mon: Registered kprobe for skb_xmit_done\n");
+
+       /* Setup kprobe for skb_recv_done */
+       skb_recv_done_kp.pre_handler = skb_recv_done_pre_handler;
+       skb_recv_done_kp.symbol_name = "skb_recv_done";
+
+       ret = register_kprobe(&skb_recv_done_kp);
+       if (ret < 0) {
+               pr_info("virtnet_mon: Failed to register kprobe for 
skb_recv_done: %d\n", ret);
+               unregister_kprobe(&skb_recv_done_kp);
+               return ret;
+       }
+       pr_info("virtnet_mon: Registered kprobe for skb_recv_done\n");
+
        return 0;
 }
 
@@ -956,6 +1034,8 @@ static void __exit virtnet_mon_exit(void)
        unregister_kprobe(&start_xmit_kp);
        unregister_kprobe(&gro_receive_skb_kp);
        unregister_kprobe(&ip_local_deliver_kp);
+       unregister_kprobe(&skb_xmit_done_kp);
+       unregister_kprobe(&skb_recv_done_kp);
        pr_info("virtnet_mon: Unloading module\n");
 }
 
@@ -965,4 +1045,4 @@ module_exit(virtnet_mon_exit);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Tang Longjun");
 MODULE_DESCRIPTION("Monitor virtio_net driver packet transmission and 
reception");
-MODULE_VERSION("0.2");
+MODULE_VERSION("0.3");
-- 
2.43.0


Reply via email to