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
