linux 网络收包NAPI理解

网卡驱动:

1.初始化DMA中断函数

2.驱动提供 int (*poll)(struct napi_struct *, int)回调函数用于接收数据帧

3.驱动分配结构A,A中包括一个struct napi_struct结构体B

4.驱动调用netif_napi_add()函数,此函数关键:

4.1  B->poll = poll  (poll为驱动接收数据帧回调函数),即2中的函数

4.2  B->weight = weight 接收权重,默认由驱动设置为64,表示一个poll可以最多接收64个帧

4.3 list_add(&napi->dev_list, &dev->napi_list); 将B->dev_list加入此网卡设备的napi_list链表

将驱动提供的帧接收回调函数加入struct net_device结构体(每个网络设备都会使用struct net_device来描述)的dev->napi_list链表中。

4.4 set_bit(NAPI_STATE_SCHED, &napi->state); 设置napi的状态

NAPI收包:

1.驱动打开NAPI功能,默认处于未工作状态(没有收包)

2.数据包到达,网卡通过DMA写到内存

3.网卡触发一个硬件中断,中断处理函数做的事情:

napi_schedule(&B)

        __napi_schedule(n)

                ____napi_schedule(this_cpu_ptr(&softnet_data), n);

                        __raise_softirq_irqoff(NET_RX_SOFTIRQ);

3.1 将B->poll_list加入到softnet_net->poll_list中

3.2 使能NET_RX_SOFTIRQ(其实就是将软中断表示位置为1,在进程退出内核态前夕时,会去检测此标志,一般在entry.S汇编中,所以软中断优先级高于应用程序,可以理解为抢占应用程序)。

net_rx_action

此函数为软中断调用的收包函数

1.将softnet_net->poll_list中的所有元素,添加到临时链表list

2.遍历list链表,调用驱动中注册的poll函数收包

2.1 收包需满足weight不能超过配置的64,时间不能超过2ms

2.2 如果收包低于64,并且时间不超过2ms就没有包的,将list加入到struct softnet_data->list队尾

2.3  如果收包大于等于64或者超过2ms,则关闭NAPI,等下一次硬件中断触发。

2.4 收割的数据完数据(接收的包大于等于weight时),调用napi_complete()把数据上协议栈。

注意,在本次没有接收完成时,还会设置软中断标志位,为什么呢?虽然本次没有接收完所有的数据包,但是释放了此次软中断抢占的进程,下一次软中断可能就不会在本次的进程上下文中了。可以降低进程的延迟。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

byd yes

你的鼓励是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值