cpu-architecture - 下半部分的数据包流

标签 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;
}

那么在 netif_rx(skb) 之后,skb 将保持在下半部分到什么时候?

谢谢。

最佳答案

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

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

流程的工作方式是这样的:

  • 一个数据包到达,这将启用 NAPI .
  • 在软 irq 上下文中运行的 NAPI 内核线程(NET_RX_SOFTIRQ 中的 /proc/softirqs)从内存(NIC 对数据进行 DMA 处理的地方)收集数据包。
  • softirq 最多只能消耗它的 budget数据包的数量或数据包处理的时间限制。你可以找到这个代码here .
  • 这可以防止 softirq 消耗整个 CPU。
  • 最终,函数 __netif_receive_skb_core叫做。此函数的确切路径取决于驱动程序,但对于 e1000e路径是:
  • NAPI 软中断调用 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
  • 根据您是否使用接收数据包转向,此处的代码路径会有所不同。
  • 在任何一种情况下,最终数据包都会被传递到协议(protocol)层 here .
  • 如果我们将 IP 视为我们选择的协议(protocol),则数据包将移交给 ip_rcv这也将check netfilter .
  • 数据包继续通过每个协议(protocol)栈,直到通过调用 sock_queue_rcv_skb 排队到套接字的接收缓冲区。 .例如,UDP 会这样做 here来自一个名为 __udp_queue_rcv_skb 的函数.
  • 函数sock_queue_rcv_skb将数据排队到套接字接收缓冲区。您可以找到此代码 here .

  • 一些注意事项:
  • 您可以调整budget对于 NAPI,通过更改 sysctl net.core.netdev_budget .预算越高,进入进程接收队列的数据包就越多,但 CPU 运行用户进程的时间就会减少。
  • 如果您的 NIC 支持多个 RX 队列,您可以在多个 CPU 之间分配传入的数据包处理负载。
  • 如果你的网卡不支持多RX队列,可以使用Receive Packet Steering在多个 CPU 之间分配数据包处理负载。

  • 如果您对此过程有任何其他我可以回答的问题,请告诉我。

    关于cpu-architecture - 下半部分的数据包流,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35959155/

    相关文章:

    performance - CUDA 可以帮助解决什么样的数据处理问题?

    linux - "book"的输出中的 'lscpu -p' 是什么意思?

    multithreading - 同时多线程是否利用交错/临时多线程?

    x86 - 各种中断的区别 : SCI, SMI、NMI、普通中断

    c - Linux中CPU如何切换到中断栈

    assembly - 当您禁用中断时会发生什么,以及如何处理您不知道如何处理的中断?

    linux - 上半部分和下半部分概念说明

    c++ - 执行 int 3 中断会停止 Linux 上的整个进程还是仅停止当前线程?

    memory - 字可寻址和字节可寻址的区别

    c++ - 计算机中的字长与 int 或 long 有何关系