|
1
2
3
4
5
6
|
struct softnet_data{ struct sk_buff_head
input_pkt_queue; //旧接口的输入队列 struct list_head
poll_list; //有需要处理报文的NAPI设备 struct napi_struct
backlog;//虚拟的NAPI设备
backlog}; |
|
1
|
DECLARE_PER_CPU(struct softnet_data,softnet_data); |
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
static int __init
net_dev_init(void){ int i,
rc = -ENOMEM; /* *
Initialise the packet receive queues. */ for_each_possible_cpu(i) { struct softnet_data
*queue; queue
= &per_cpu(softnet_data, i); /*初始化输入队列*/ skb_queue_head_init(&queue->input_pkt_queue); queue->completion_queue
= NULL; /*初始化pool
链表头*/ INIT_LIST_HEAD(&queue->poll_list); /*把backlog的轮询函数初始化为
process_backlog 该函数来处理传统接口使用的输入队列的报文*/ queue->backlog.poll
= process_backlog; /*backlog
轮询函数一次可以处理的报文上限个数*/ queue->backlog.weight
= weight_p; queue->backlog.gro_list
= NULL; queue->backlog.gro_count
= 0; }} |
|
1
2
3
4
5
6
7
8
9
10
|
struct napi_struct{ struct list_head
poll_list;//挂到softnet_data的pool_list上 unsigned long state;//NAPI的调度状态 int weight;//一次轮询的最大处理报文数 int (*poll)(struct napi_struct
*, int);//轮询函数 struct net_device
*dev;//指向关联的网络设备 struct list_head
dev_list;//对应的网络设备上关联的NAPI链表节点 /*其他字段是gso功能用,这里先不讨论*/}; |
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
void netif_napi_add(struct net_device
*dev, struct napi_struct
*napi, int (*poll)(struct napi_struct
*, int), int weight){ INIT_LIST_HEAD(&napi->poll_list); napi->poll
= poll; napi->weight
= weight; /*把NAPI加入到网络设备相关联的NAPI链表上去。*/ list_add(&napi->dev_list,
&dev->napi_list); napi->dev
= dev; /*绑定时设置NAPI是已调度状态,禁用该NAPI,以后手动的来清除该标识来使 能NAPI.*/ set_bit(NAPI_STATE_SCHED,
&napi->state);} |
|
1
2
3
4
5
6
7
8
9
10
11
12
|
static inline void napi_disable(struct napi_struct
*n){ /*先设置NAPI状态为DISABLE*/ set_bit(NAPI_STATE_DISABLE,
&n->state); /*循环的等待NAPI被调度完成,变成可用的,设置成SCHED状态*/ while (test_and_set_bit(NAPI_STATE_SCHED,
&n->state)) msleep(1); /*清除DISABLE状态*/ clear_bit(NAPI_STATE_DISABLE,
&n->state);} |
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
void __napi_schedule(struct napi_struct
*n){ unsigned long flags; /*链表操作必须在关闭本地中断的情况下操作,防止硬中断抢占*/ local_irq_save(flags); /*把NAPI加入到本地CPU的softnet_data
的pool_list 链表上*/ list_add_tail(&n->poll_list, &__get_cpu_var(softnet_data).poll_list); /*调度收包软中断*/ __raise_softirq_irqoff(NET_RX_SOFTIRQ); local_irq_restore(flags);} |
|
1
2
3
4
5
6
7
8
9
10
11
12
|
void __napi_complete(struct napi_struct
*n){ BUG_ON(!test_bit(NAPI_STATE_SCHED,
&n->state)); BUG_ON(n->gro_list); /*把NAPI从softnet_data的pool_list上摘除下来*/ list_del(&n->poll_list); /*使能NAPI,允许它下次可以被再次调度*/ smp_mb__before_clear_bit(); clear_bit(NAPI_STATE_SCHED,
&n->state);} |
277

被折叠的 条评论
为什么被折叠?



