在虚拟化场景,中断的开销更大,所以要尽可能的少用中断,我们从中断处理函数开始看。
skb_recv_done函数
static void skb_recv_done(struct virtqueue *rvq)
{
struct virtnet_info *vi = rvq->vdev->priv;
struct receive_queue *rq = &vi->rq[vq2rxq(rvq)];
/* Schedule NAPI, Suppress further interrupts if successful. */
if (napi_schedule_prep(&rq->napi)) {
virtqueue_disable_cb(rvq); //关闭中断,vhost不会通知前端
__napi_schedule(&rq->napi); //注册napi,触发软中断
}
}
触发软中断前,关闭vhost中断通知,此时通过poll机制收包。 收包软中断最终会调用napi定义的poll函数,virtio_net定义的是virtnet_poll函数。
virtnet_poll函数
static int virtnet_poll(struct napi_struct *napi, int budget)
{
struct receive_queue *rq =
container_of(napi, struct receive_queue, napi);
unsigned int r, received;
received = virtnet_receive(rq, budget); //接收报文,并上送协议栈
/* Out of packets