1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > Linux网络子系统中旧的报文接收接口netif_rx

Linux网络子系统中旧的报文接收接口netif_rx

时间:2023-06-27 20:30:26

相关推荐

Linux网络子系统中旧的报文接收接口netif_rx

linux旧的收包方式提供给驱动的接口netif_rx()

intnetif_rx(struct sk_buff *skb)

{

struct softnet_data *queue;

unsigned long flags;

/*如果接收skb的时间戳没设定,设定接收时间戳*/

if (!skb->tstamp.tv64)

{

net_timestamp(skb);

}

/*禁止本地cpu的中断*/

local_irq_save(flags);

/*取得本地cpu的softnet_data*/

queue = &__get_cpu_var(softnet_data);

/*每个CPU都有一个统计数据,增加统计数据*/

__get_cpu_var(netdev_rx_stat).total++;

/*如果本地CPU的输入队列中的skb 个数小于允许的最多的个数*/

if (queue->input_pkt_queue.qlen <= netdev_max_backlog)

{

/*如果本地cpu的输入队列长度不为0,表示输入队列已经有skb了,

并且特殊的napi backlog 已经挂入了softnet_data 的

pool_list上了*/

if (queue->input_pkt_queue.qlen)

{

enqueue:

/*把skb 放入CPU的输入队列 input_pkt_queue*/

__skb_queue_tail(&queue->input_pkt_queue, skb);

/*使能中断 并 返回*/

local_irq_restore(flags);

return NET_RX_SUCCESS;

}

/*如果输入队列为空,则把 特殊的napi backlog 挂到softnet_data

的 pool_list 上 并返回把skb放入输入队列并返回*/

napi_schedule(&queue->backlog);

goto enqueue;

}

/*如果本地cpu的输入队列已经满了,则丢弃报文,

并增加丢包计数并返回*/

__get_cpu_var(netdev_rx_stat).dropped++;

local_irq_restore(flags);

kfree_skb(skb);

return NET_RX_DROP;

}

上篇博文里我们已经分析过,Linux网络子系统中管理的收包队列由一个虚拟的NAPI backlog来进行处理。

驱动调用netif_rx把报文放入队列,把虚拟的NAPI backlog加入到pool链表上,调度收包软中断。收包软中断会调用backlog的轮询

函数对队列中的报文进行处理。

该虚拟的NAPI backlog的轮询函数在函数net_dev_init中被初始化为process_backlog

我们看一下NAPI backlog的轮询函数process_backlog的实现

参数:

napi: 本地cpu上softnet_data 的backlog .

quota: 一次轮询可以处理的最多报文数。

函数详解:

static intprocess_backlog(struct napi_struct *napi, int quota)

{

int work = 0;

/*取得本地CPU上的softnet_data 数据*/

struct softnet_data *queue = &__get_cpu_var(softnet_data);

/*开始计时,一旦允许时间到,就退出轮询*/

unsigned long start_time = jiffies;

napi->weight = weight_p;

/*循环从softnet_data 的输入队列取报文并处理,直到队列中没有报文了,

或处理的报文数大于了允许的上限值了,

或轮询函数执行时间大于一个jiffies 了

*/

do

{

struct sk_buff *skb;

/*禁用本地中断,要存队列中取skb,防止抢占*/

local_irq_disable();

/*从softnet_data 的输入队列中取得一个skb*/

skb = __skb_dequeue(&queue->input_pkt_queue);

/*如果队列中没有skb,则使能中断并退出轮询*/

if (!skb)

{

/*把napi 从 softnet_data 的 pool_list 链表上摘除*/

__napi_complete(napi);

/*使能本地CPU的中断*/

local_irq_enable();

break;

}

/*skb 已经摘下来了,使能中断*/

local_irq_enable();

/*把skb送到协议栈相关协议模块进行处理,详细处理见后续章节*/

netif_receive_skb(skb);

} while (++work < quota && jiffies == start_time);

/*返回处理报文个数*/

return work;

}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。