我正在阅读从NIC中断处理程序到用户空间的接收路径中的数据包流。
我想知道新分配的skbuff在下半部分中保留到哪一点。
从LDD获取snull_rx()代码:
void snull_rx(struct net_device *dev, struct snull_packet *pkt)
{
struct sk_buff *skb;
struct snull_priv *priv = netdev_priv(dev);
/*
* The packet has been retrieved from the transmission
* medium. Build an skb around it, so upper layers can handle it
*/
skb = dev_alloc_skb(pkt->datalen + 2);
if (!skb) {
if (printk_ratelimit( ))
printk(KERN_NOTICE "snull rx: low on mem - packet dropped\n");
priv->stats.rx_dropped++;
goto out;
}
memcpy(skb_put(skb, pkt->datalen), pkt->data, pkt->datalen);
/* Write metadata, and then pass to the receive level */
skb->dev = dev;
skb->protocol = eth_type_trans(skb, dev);
skb->ip_summed = CHECKSUM_UNNECESSARY; /* don't check it */
priv->stats.rx_packets++;
priv->stats.rx_bytes += pkt->datalen;
netif_rx(skb);
out:
return;
}
所以在netif_rx(skb)之后直到skb保持在下半部分的哪一点?。
感谢。
答案 0 :(得分:5)
编辑:我写了一篇博客文章,概述了提供大量详细信息的整个linux网络堆栈(接收路径),take a look。
答案很复杂,但是netfilter代码在softirq上下文中运行。
流程的工作方式如下:
NET_RX_SOFTIRQ
中的/proc/softirqs
)从内存中收集数据包(NIC DMA'数据)。budget
个数据包或数据包处理的时间限制。你可以找到这段代码here。__netif_receive_skb_core
。此函数的确切路径取决于驱动程序,但对于e1000e
,路径为:
e1000e_poll
e1000e_poll
来电e1000_clean_rx_irq
e1000_clean_rx_irq
来电e1000_receive_skb
e1000_receive_skb
来电napi_gro_receive
napi_gro_receive
来电napi_skb_finish
napi_skb_finish
来电netif_receive_skb
netif_receive_skb
来电netif_receive_skb
netif_receive_skb
来电__netif_receive_skb_core
ip_rcv
,这也将check netfilter。sock_queue_rcv_skb
排队到套接字的接收缓冲区。例如,UDP从名为__udp_queue_rcv_skb
的函数中执行此here。sock_queue_rcv_skb
将数据排入套接字接收缓冲区。您可以找到此代码here。一些注意事项:
budget
来调整NAPI的net.core.netdev_budget
。预算越高,排队到流程的数据包就越多。接收队列,但CPU将有更少的时间来运行用户进程。如果您对此流程有任何其他疑问,请与我联系。
答案 1 :(得分:0)
上面的代码在硬件中断上下文上运行 netif_rx对数据包进行排队并通知内核在SOFTIRQ上下文(NET_RX)上继续