数据包流量在下半部分

Has*_*ell 4 cpu-architecture interrupt-handling

我正在阅读从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;
}
Run Code Online (Sandbox Code Playgroud)

所以在netif_rx(skb)之后直到skb保持在下半部分的哪一点?

谢谢.

Joe*_*ato 5

编辑:我写了一篇博客文章,概述了提供大量详细信息的整个linux网络堆栈(接收路径),看一看.

答案很复杂,但是netfilter代码在softirq上下文中运行.

流程的工作方式如下:

  1. 数据包到达,启用NAPI.
  2. 在软irq上下文(NET_RX_SOFTIRQin /proc/softirqs)中运行的NAPI内核线程从内存中收集数据包(NIC DMA'd数据).
  3. softirq只能消耗其budget数据包或数据包处理的时间限制.你可以在这里找到这个代码.
  4. 这可以防止softirq占用整个CPU.
  5. 最终,该函数__netif_receive_skb_core被调用.此函数的确切路径取决于驱动程序,但e1000e路径为:
    1. NAPI softirq电话 e1000e_poll
    2. e1000e_poll 电话 e1000_clean_rx_irq
    3. e1000_clean_rx_irq 电话 e1000_receive_skb
    4. e1000_receive_skb 电话 napi_gro_receive
    5. napi_gro_receive 电话 napi_skb_finish
    6. napi_skb_finish 电话 netif_receive_skb
    7. netif_receive_skb 电话 netif_receive_skb
    8. netif_receive_skb 电话 __netif_receive_skb_core
  6. 根据您是否使用接收数据包转向,这里的代码路径稍有不同.
  7. 在这两种情况下,最终包被传递到协议层这里.
  8. 如果我们将IP视为我们选择的协议,则会传递数据包ip_rcv,也会检查netfilter.
  9. 数据包继续通过每个协议栈,直到它通过调用排队到套接字的接收缓冲区sock_queue_rcv_skb.例如,UDP在这里从一个名为的函数执行此操作__udp_queue_rcv_skb.
  10. 该函数sock_queue_rcv_skb将数据排队到套接字接收缓冲区.你可以在这里找到这个代码.

一些说明:

  • 您可以budget通过更改sysctl 来调整for NAPI net.core.netdev_budget.预算越高,将排队到进程的接收队列的数据包越多,但CPU将有更少的时间来运行用户进程.
  • 如果您的NIC支持多个RX队列,则可以在多个CPU之间分配传入的数据包处理负载.
  • 如果您的NIC不支持多个RX队列,则可以使用接收数据包控制将数据包处理负载分配到多个CPU.

如果您对此流程有任何其他疑问,请与我联系.