数据包被捕获后会发生什么?

我一直在阅读网卡捕获数据后发生的事情,而我越读越多,我就感到困惑。

首先,我已经阅读了传统的网卡捕获数据包之后,它被复制到内核空间的一块内存,然后到用户空间的任何应用程序,然后在数据包的数据。 然后我读了关于DMA的信息,NIC直接将数据包复制到内存中,绕过CPU。 那么是网卡 – >内核内存 – >用户空间内存stream量仍然有效? 另外,大多数NIC(如Myricom)是否使用DMA来提高数据包捕获率?

其次,RSS(接收端缩放)在Windows和Linux系统中的工作是否类似? 我只能在MSDN文章中find有关RSS如何工作的详细解释,其中讨论了RSS(和MSI-X)如何在Windows Server 2008上工作。但RSS和MSI-X的相同概念仍然适用于Linux系统, ?

谢谢。

问候,Rayne

这个过程如何发挥主要取决于驱动程序作者和硬件,但是对于我所看过或写过的驱动程序以及我所使用的硬件,通常是这样的:

  1. 在驱动程序初始化时,它将分配一定数量的缓冲区并将它们提供给NIC。
  2. 当数据包被NIC接收到时,它将下一个地址从缓冲区列表中提取出来,直接将DMA数据写入其中,并通过中断通知驱动程序。
  3. 驱动程序获取中断,可以将缓冲区转到内核,或者分配一个新的内核缓冲区并复制数据。 “零复制网络”是前者,显然需要操作系统的支持。 (更多在这下面)
  4. 驱动程序需要分配一个新的缓冲区(在零拷贝情况下),否则它将重新使用缓冲区。 无论哪种情况,都会将缓冲区返回给NIC以备将来的数据包使用。

内核中的零拷贝网络并不是那么糟糕。 零拷贝一直到userland是非常困难的。 Userland获取数据,但是网络数据包由头和数据组成。 至少,真正的零拷贝一直到userland需要你的NIC的支持,以便它可以把DMA包分成不同的头/数据缓冲区。 一旦内核将数据包路由到其目的地并且验证校验和(对于TCP,如果NIC支持的话,在硬件中,或者在软件中,如果不是),那么头部被回收;注意,如果内核必须自己计算校验和,也可以复制数据:查看数据导致缓存未命中并将其复制到其他地方可以通过调整代码免费)。

即使假设所有星星都对齐,当系统接收到数据时,数据并不在您的用户缓冲区中。 在应用程序询问数据之前,内核不知道它会在哪里结束。 考虑像Apache这样的多进程守护进程的情况。 有很多子进程,都在同一个socket上监听。 你也可以建立一个连接fork() ,并且两个进程都能够recv()传入的数据。

互联网上的TCP数据包通常是1460字节的有效负载(1500的MTU = 20字节的IP报头+ 20字节的TCP报头+ 1460字节的数据)。 1460不是2的幂,并且不会匹配任何系统上的页面大小。 这给重组数据流带来了问题。 请记住,TCP是面向流的。 在发送方写入之间没有区别,并且在接收到的两个1000字节的写入操作将被完全消耗在2000字节的读取中。

进一步考虑用户缓冲区。 这些由应用程序分配。 为了一直使用零拷贝,缓冲区需要页面对齐,而不是与其他任何内容共享该页面。 在recv()时候,内核理论上可以重新映射包含数据的旧页面,并将其“翻转”到位,但是由于连续的数据包将位于不同的页面上,因此上面的重新组装问题会变得复杂。 内核可以将数据交给每个数据包的有效载荷,但是这意味着会有很多额外的系统调用,页面重新映射以及可能的整体吞吐量下降。

我真的只是在这个话题上表面上摸不着头脑。 在二十一世纪初,我曾在几家公司工作,试图将零拷贝概念扩展到用户空间。 我们甚至在用户空间中实现了一个TCP协议栈,完全绕过了使用协议栈的应用程序,但是这带来了一系列的问题,而且从来没有生产质量。 这是一个很难解决的问题。