首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >包流在下半部分

包流在下半部分
EN

Stack Overflow用户
提问于 2016-03-12 14:53:22
回答 2查看 1.4K关注 0票数 4

我读到了从NIC中断处理程序到用户空间的接收路径中的数据包流。

我想知道,直到哪一点,新分配的skbuff仍然处于下半部分的上下文。

从LDD获取snull_rx()代码:

代码语言:javascript
运行
复制
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将保持在下半部分的哪一点?

谢谢。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-04-06 08:29:17

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

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

流程的工作方式如下:

  1. 一个数据包到达,这就启用了纳比
  2. 在软irq上下文(NET_RX_SOFTIRQ in /proc/softirqs)中运行的NAPI内核线程从内存( NIC获取数据)中获取数据包。
  3. softirq只能消耗最多其数据包的budget或数据包处理的时间限制。您可以找到这段代码这里
  4. 这将防止软CPU消耗整个CPU。
  5. 最后,调用函数__netif_receive_skb_core。这个函数的确切路径取决于驱动程序,但是对于e1000e,路径是:
    1. NAPI调用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

  1. 取决于您是否使用接收包引导,这里的代码路径会稍微偏离一些。
  2. 在任何一种情况下,包最终都会被传送到协议层这里
  3. 如果我们将IP作为我们选择的协议,分组将被传递给ip_rcv,后者也将检查网络过滤器
  4. 该数据包通过每个协议栈继续进行,直到通过调用sock_queue_rcv_skb将其排队到套接字的接收缓冲区。例如,UDP从一个名为这里的函数执行此__udp_queue_rcv_skb
  5. 函数sock_queue_rcv_skb将数据排队到套接字接收缓冲区。您可以找到这段代码这里

一些注意事项:

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

如果你对这个过程有什么其他问题我可以回答,请告诉我。

票数 5
EN

Stack Overflow用户

发布于 2016-03-22 13:50:43

上面的代码运行在硬件中断上下文、netif_rx队列、数据包和信号内核继续SOFTIRQ上下文(NET_RX)上。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35959155

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档