net_rx() --> netif_rx()
netif_rx() -- 将sk_buff插入到softnet_data->input_pkt_queue链表中
netif_rx() completes the interrupt handling. First, the current
time is set in skb->time, and the socket buffer is placed in the
input queue. As compared with earlier versions of the Linux kernel,
there is now not only one single queue having the name "backlog";
instead, each CPU stores "its" incoming packets in the structure
softnet_data[cpu].input_pkt_queue. This means that the processor that
handles the interrupt always stores the packet in its queue. This
mechanism was introduced to avoid kernel-wide locks of a single input
queue.
Once the packet was placed in the queue, the interrupt handling
is complete. The handling routine of a hardware interrupt should run
only the operations absolutely required to ensure that other activities
of the computer (software interrupts, tasklets, processes) won't be
unnecessarily interrupted.
/usr/src/linux-2.6.19/net/core/dev.c
int netif_rx(struct sk_buff *skb)
{
struct softnet_data *queue;
unsigned long flags;
if (netpoll_rx(skb))
return NET_RX_DROP;
if (!skb->tstamp.off_sec)
net_timestamp(skb);
local_irq_save(flags);
queue = &__get_cpu_var(softnet_data);
__get_cpu_var(netdev_rx_stat).total++;
if (queue->input_pkt_queue.qlen <= netdev_max_backlog) {
if (queue->input_pkt_queue.qlen) {
enqueue:
dev_hold(skb->dev);
__skb_queue_tail(&queue->input_pkt_queue, skb);
local_irq_restore(flags);
return NET_RX_SUCCESS;
}
netif_rx_schedule(&queue->backlog_dev);
goto enqueue;
}
__get_cpu_var(netdev_rx_stat).dropped++;
local_irq_restore(flags);
kfree_skb(skb);
return NET_RX_DROP;
}
netif_rx_schedule()触发网络软中断
--------------------------------------
netif_rx_schedule()-->
__netif_rx_schedule()-->
__raise_softirq_irqoff(NET_RX_SOFTIRQ)
/usr/src/linux-2.6.19/net/core/dev.c
int netdev_max_backlog = 1000;
阅读(1592) | 评论(0) | 转发(0) |