我正在阅读从 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 将保持在下半部分到什么时候?
谢谢。
最佳答案
编辑 :我写了一篇博客文章,概述了提供大量详细信息的整个 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 会这样做 here来自一个名为 __udp_queue_rcv_skb
的函数. sock_queue_rcv_skb
将数据排队到套接字接收缓冲区。您可以找到此代码 here . 一些注意事项:
budget
对于 NAPI,通过更改 sysctl net.core.netdev_budget
.预算越高,进入进程接收队列的数据包就越多,但 CPU 运行用户进程的时间就会减少。 如果您对此过程有任何其他我可以回答的问题,请告诉我。
关于cpu-architecture - 下半部分的数据包流,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35959155/