kernel:linux-2.6.18
net_rx
接收处理函数触发软中断,负责“下半部”处理的软中断函数net_rx_action函数将会被执行。
-
static int __init net_dev_init(void)
-
{
-
….
-
open_softirq(NET_TX_SOFTIRQ, net_tx_action, NULL);
-
open_softirq(NET_RX_SOFTIRQ, net_rx_action, NULL);
-
….
-
}
net_rx_action负责从当前CPU中获取softnet_data,处理poll_list上的dev,调用dev->poll()对网络数据进行真正处理。
-
# define jiffies raid6_jiffies()
-
-
static inline uint32_t raid6_jiffies(void)
-
{
-
struct timeval tv;
-
gettimeofday(&tv, NULL);
-
return tv.tv_sec*1000 + tv.tv_usec/1000;
-
}
-
-
static void net_rx_action(struct softirq_action *h)
-
{
-
struct softnet_data *queue = &__get_cpu_var(softnet_data);
-
unsigned long start_time = jiffies;
-
int budget = netdev_budget;
-
void *have;
-
-
-
local_irq_disable();
-
-
-
/*
-
* __netif_rx_schedule函数中进行的挂链操作
-
* list_add_tail(&dev->poll_list, &__get_cpu_var(softnet_data).poll_list);
-
*/
-
while (!list_empty(&queue->poll_list)) {
-
struct net_device *dev;
-
-
/*
-
(jiffies - start_time>1)保证执行当前的 POLL 过程的时间不超过一个时间片,
-
不被软中断占用太多的时间,这样在一次调度的时间内执行完毕当前的 POLL 过程。
-
budget 表示一个时间片内最大数据传输的"块数",
-
块的意思为每个 POLL 所完成sk_buff数量,
-
每块中间的 sk_buff 数量为 dev->quota 决定,
-
在 8139CP 驱动中,budget 为 300,
-
而 quota 为 16 表示每给时间片最多可以接收到 4.8K 的 sk_buff 数量
-
*/
-
if (budget <= 0 || jiffies - start_time > 1)
-
goto softnet_break;
-
-
-
local_irq_enable();
-
-
-
/*
-
* 取出设备
-
* 比如在netif_rx_schedule(&queue->backlog_dev)中,dev就是backlog_dev,
-
*/
-
dev = list_entry(queue->poll_list.next,
-
struct net_device, poll_list);
-
have = netpoll_poll_lock(dev);
-
/*
-
* 调用dev->poll()进行数据真正处理
-
* poll 指针在net_dev_init默认指向process_backlog()
-
*
-
*/
-
if (dev->quota <= 0 || dev->poll(dev, &budget)){
-
netpoll_poll_unlock(have);
-
local_irq_disable();
-
list_move_tail(&dev->poll_list, &queue->poll_list);
-
/*完成一次POLL过程的数据的接收,重新定义设备接收数据的"配额"(事实上就是sk_buff缓冲区的数量,每次调用POLL方法的时候可以创建并且最多可以向上层提交的sk_buff缓冲区数目,这个参数很重要在高速处理的时候有需要慎重优化这个数值,在有大量数据接收的情况下,需要增加该数值)*/
-
if (dev->quota < 0)
-
dev->quota += dev->weight;
-
else
-
dev->quota = dev->weight;
-
} else {
-
netpoll_poll_unlock(have);
-
dev_put(dev);
-
local_irq_disable();
-
}
-
}
-
out:
-
local_irq_enable();
-
return;
-
-
-
softnet_break:
-
__get_cpu_var(netdev_rx_stat).time_squeeze++;
-
__raise_softirq_irqoff(NET_RX_SOFTIRQ);
-
goto out;
-
}
参考文档:
http://www.ibm.com/developerworks/cn/linux/l-napi/index.html?ca=dwcn-newsletter-linux
阅读(4868) | 评论(0) | 转发(2) |