数据包流量在下半部分

时间:2016-03-12 14:53:23

标签: 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保持在下半部分的哪一点?。

感谢。

2 个答案:

答案 0 :(得分:5)

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

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

流程的工作方式如下:

  1. 数据包到达,启用NAPI
  2. 在软irq上下文中运行的NAPI内核线程(NET_RX_SOFTIRQ中的/proc/softirqs)从内存中收集数据包(NIC DMA'数据)。
  3. softirq最多只能消耗其budget个数据包或数据包处理的时间限制。你可以找到这段代码here
  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. 在任何一种情况下,最终都会将数据包传递到协议层here
  8. 如果我们将IP视为我们选择的协议,则数据包将被传递到ip_rcv,这也将check netfilter
  9. 数据包继续通过每个协议栈,直到它通过调用sock_queue_rcv_skb排队到套接字的接收缓冲区。例如,UDP从名为__udp_queue_rcv_skb的函数中执行此here
  10. 函数sock_queue_rcv_skb将数据排入套接字接收缓冲区。您可以找到此代码here
  11. 一些注意事项:

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

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

答案 1 :(得分:0)

上面的代码在硬件中断上下文上运行 netif_rx对数据包进行排队并通知内核在SOFTIRQ上下文(NET_RX)上继续