networking - NIC 内存管理和 RSS 队列
问题描述
我想了解 NIC 如何管理环形缓冲区的内存。
假设我有 Q 个大小为 N 的 RSS 队列。驱动程序将在内核空间中分配大小为 N 个数据包的 Q 个环形缓冲区:
我的问题是,如果操作系统无法为特定队列拉取数据包或缓慢拉取数据包,并且 NIC 端有 N 个数据包等待拉取,那么硬件端会发生什么。我可以想象两种情况:
- 队列的数据包将“吃掉”网卡的所有内存,从而迫使网卡丢弃其他队列的数据包
- NIC会在到达N个数据包时停止接收队列的数据包,因此其余队列不受影响?
谢谢
解决方案
当前的网络堆栈(以及一般的商用操作系统)是从基于简单 NIC 的模型发展而来的,这些 NIC 以增量方式为单核 CPU 供电。当多核机器变得普遍并且软件堆栈的可扩展性成为一个严重的问题时,人们做出了巨大的努力来调整这些模型以利用多核
与 NIC 硬件中的任何其他规则硬编码一样,RSS 的主要缺点是操作系统对队列如何分配给流几乎没有影响。
RSS 的缺点可以通过使用更灵活的 NIC 过滤器或尝试使用系统操作员中烘焙的软件智能地将队列分配给流来克服。
以下 ASCII 艺术图像描述了在硬件接收到两个数据包并向操作系统传递中断后,环的外观:
+--------------+ <----- OS Pointer
| Descriptor 0 |
+--------------+
| Descriptor 1 |
+--------------+ <----- Hardware Pointer
| Descriptor 2 |
+--------------+
| ... |
+--------------+
| Descriptor n |
+--------------+
当操作系统接收到中断时,它会读取硬件指针的位置并在其指针和硬件之间处理这些数据包。一旦完成,它就不必做任何事情,直到它用新的缓冲区准备这些描述符。一旦完成,它将通过写入硬件来更新其指针。例如,如果操作系统已经处理了前两个描述符,然后更新了硬件,那么环将如下所示:
+--------------+
| Descriptor 0 |
+--------------+
| Descriptor 1 |
+--------------+ <----- Hardware Pointer, OS Pointer
| Descriptor 2 |
+--------------+
| ... |
+--------------+
| Descriptor n |
+--------------+
当你发送数据包时,它是相似的。操作系统填写描述符,然后通知硬件。一旦硬件通过线路将它们发送出去,它就会注入一个中断并指示它写入网络的描述符,从而允许操作系统释放相关的内存。
推荐阅读
- go - 插入整数时处理空值
- javascript - index.html 在 Chrome DevTools 中引发错误
- c++ - 通过给出一个单词从c ++文件中删除一行
- c# - 还有另一种方法可以使物体上下移动吗?
- c++ - 为什么 C++ 中的“整数”数据类型能够保存“真”或“假”;布尔值
- .net-core - 在 Blazor 客户端应用程序中登录主页顶部后显示 Hello + 一个很长的哈希码而不是用户名
- python - 在循环的每次通过时显示子图
- java - publish/publishLocal 和 compile/package 访问修饰符处理的区别
- c - 更改函数中的指针引用变量
- reactjs - 无法从函数组件调用函数/访问变量