文章目录
- 网卡
- 网卡的核心功能
- 网卡的关键技术
- 单队列网卡
- 多队列网卡
- 查看网卡信息
- ifconfig
- ethtool
- 查看网卡队列
- Linux 查看中断绑定
- 网卡中断查询
- 查看中断绑定的 cpu
- 总结
- 1. 默认情况(单队列网卡)
- 2. 多队列网卡
- 3. 如何查看和配置绑定关系?
- 4. 性能优化建议
- 结论
网卡
网卡
(Network Interface Card,NIC),又称 网络适配器
(Network Adapter)或 网络接口控制器(Network Interface Controller),是计算机或其他网络设备用于连接网络的硬件组件。
它负责在计算机和网络(如以太网、Wi-Fi、光纤网络等)之间传输数据。
网卡的核心功能
数据发送
(TX, Transmit):将计算机的数据包转换为电信号或光信号,并通过物理介质(如网线、光纤、无线电波)发送到网络。数据接收
(RX, Receive):从网络接收数据信号,并转换为计算机可处理的数字数据。MAC 地址管理
:每个网卡都有一个唯一的 MAC 地址(Media Access Control Address),用于在局域网(LAN)中标识设备。协议处理
:支持 TCP/IP、UDP、ARP 等网络协议,确保数据正确封装和传输。中断处理(IRQ)
:当数据到达或发送完成时,网卡通过 硬件中断(IRQ) 通知 CPU 处理
网卡的关键技术
- 多队列(Multi-Queue)
RSS
(Receive Side Scaling):多个 RX 队列
,让不同 CPU 核心并行处理接收流量。XPS
(Transmit Packet Steering):多个 TX 队列
,优化发送性能。
适用场景:高吞吐量服务器(如 10G/25G 网卡)。
- 硬件卸载(Offload)
LRO/GRO
:大包合并,减少 CPU 负载。TSO
(TCP Segmentation Offload):由网卡拆分 TCP 大包
,降低 CPU 开销。Checksum Offload
:由网卡计算校验和,提高效率。
- 虚拟化支持
SR-IOV
(Single Root I/O Virtualization):一张物理网卡虚拟出多个虚拟网卡(VF),供虚拟机直通使用。VXLAN/NVGRE Offload
:硬件加速虚拟网络。
单队列网卡
如果网卡只有一个 RX 队列(接收) 和一个 TX 队列(发送)
,即为单队列网卡
要注意的是,在网卡中,单独的 RX(接收) 和 TX(发送) 通常被视为 两个独立的队列,而不是一个队列。 而称之为单队列网卡(1 RX + 1 TX
)是为了与多队列网卡(n RX + m TX
)区别开来
关键点:
RX队列
:专门负责接收数据包(从网络到主机)。TX队列
:专门负责发送数据包(从主机到网络)。独立性
:它们的功能和数据处理方向完全相反,硬件和驱动通常会分开管理这两个队列。
多队列网卡
上面说到单队列网卡 1个RX + 1个TX
= 2个队列(1个接收队列 + 1个发送队列)。
那么如果是多队列网卡,则可能是 N个RX队列 + M个TX队列
(例如 8RX+8TX
)。
查看网卡信息
ifconfig
通过 ifconfig
查看网卡,例如这里是 ens192
[root@ ~]# ifconfig
...
ens192: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
...RX packets 1447137979 bytes 421584628040 (392.6 GiB)RX errors 0 dropped 23 overruns 0 frame 0TX packets 1683429823 bytes 314926856868 (293.2 GiB)TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
ethtool
通过 ethtool
查看网卡相关信息
[root@ ~]# ethtool -i ens192
driver: vmxnet3
version: 1.4.17.0-k-NAPI
firmware-version:
expansion-rom-version:
bus-info: 0000:0b:00.0
supports-statistics: yes
supports-test: no
supports-eeprom-access: no
supports-register-dump: yes
supports-priv-flags: no
查看网卡队列
可以执行下面命令查看网卡队列,可以看出有16个队列,rx 与 tx 队列各有8个
[root@ ~]# ls /sys/class/net/ens192/queues/
rx-0 rx-1 rx-2 rx-3 rx-4 rx-5 rx-6 rx-7
tx-0 tx-1 tx-2 tx-3 tx-4 tx-5 tx-6 tx-7
Linux 查看中断绑定
先上结果图展示:
网卡内部有多个队列,每一组都有 1 RX + 1 TX
2个队列,例如 rx-0 与 tx-0
,每一组队列对应一个中断,是机器启动后注册上去的,每个中断(硬中断
)都对应着一个中断函数。
后续网络数据的收发 --> 硬中断 --> 找到中断函数 --> 用绑定的cpu来处理,网卡所发出的中断是硬中断。
网卡中断查询
通过 /proc/interrupts
过滤查询对应网卡的中断
[root@ ~]# (head -n 1 /proc/interrupts && grep ens192 /proc/interrupts)CPU0 CPU1 CPU2 CPU3 CPU4 CPU5 CPU6 CPU7 57: 54323955 50498186 58073762 26180655 117508750 61323815 13512600 5579109 PCI-MSI-edge ens192-rxtx-058: 36057837 61587828 64925105 16531986 53159081 18216138 14781056 25738649 PCI-MSI-edge ens192-rxtx-159: 21230949 35197430 29174376 15012576 21111201 19745533 193447095 4072969 PCI-MSI-edge ens192-rxtx-260: 18630617 37195730 38652962 23898573 10714277 13863697 22873438 206191900 PCI-MSI-edge ens192-rxtx-361: 20170505 20338217 24230031 27035431 11011878 198439738 60856797 2458748 PCI-MSI-edge ens192-rxtx-462: 71691281 87398091 79354652 46557471 40000772 13542848 4368702 4344379 PCI-MSI-edge ens192-rxtx-563: 58123626 26376999 40864211 157759424 34608174 12835300 31843092 10343885 PCI-MSI-edge ens192-rxtx-664: 109253297 71849659 37388197 55968603 56479525 20341714 5638153 2536989 PCI-MSI-edge ens192-rxtx-765: 0 0 0 0 0 0 0 0 PCI-MSI-edge ens192-event-8
/proc/interrupts
行中 CPU 核心编号列(如 CPU0 CPU1 CPU2…),显示的是各中断在这些 CPU 上的触发次数。
上面举例说明:
# 65号中断:
#65: 0 0 0 0 0 0 0 0 PCI-MSI-edge ens192-event-8
65:表示逻辑中断号,是系统为该中断分配的唯一标识符。
0 0 0 0 0 0 0 0:这部分表示该中断在各个 CPU 核心上发生的次数。这里显示的都是 0,说明到目前为止,这个中断还没有在任何 CPU 核心上被触发过。
PCI-MSI-edge:PCI-MSI 表示中断类型为 PCI 消息信号中断(PCI Message Signaled Interrupts),edge 表示中断触发方式为边沿触发,即当信号的电压从低电平转换到高电平时,会产生一个中断信号,且该中断信号只被发送一次。
ens192-event-8:这是与该中断相关联的设备名称,表明这个中断是由网络接口ens192产生的,event-8可能是ens192网卡的某个特定事件或队列对应的中断。另外57号中断:
#57: 54323955 50498186 58073762 26180655 117508750 61323815 13512600 5579109 PCI-MSI-edge ens192-rxtx-0...(前面几个略去解释)
ens192-rxtx-0:
ens192:网络接口名称,通常由系统自动分配。
rxtx-0:rxtx:表示该队列是 接收(RX)和发送(TX)合并队列(Combined 模式),同时处理数据收发。部分网卡支持将 RX 和 TX 队列合并为一个队列以简化管理。0:队列编号,表明这是网卡的 第 0 个合并队列。现代多队列网卡(如支持 RSS/XPS 的网卡)通常会创建多个队列(如 rxtx-0、rxtx-1 等),每个队列独立处理流量以实现多核并行。
查看中断绑定的 cpu
中断与cpu 绑定
,对应的中断则由相应的cpu来处理,通过 /proc/irq/<IRQ_NUM>/smp_affinity
查询相关中断绑定的cpu情况
[root@ ~]# for irq in {57..65}; do echo -n "IRQ $irq: " && cat /proc/irq/$irq/smp_affinity; done
IRQ 57: 01 # 0000 0001, 绑定的是 cpu0
IRQ 58: 40 # 0100 0000, 绑定的是 cpu6
IRQ 59: 02 # 0000 0010, 绑定的是 cpu1
IRQ 60: 08 # 0000 1000, 绑定的是 cpu3
IRQ 61: 20 # 0010 0000, 绑定的是 cpu5
IRQ 62: 10 # 0001 0000, 绑定的是 cpu4
IRQ 63: 02 # 0000 0010, 绑定的是 cpu1
IRQ 64: 04 # 0000 0100, 绑定的是 cpu2IRQ 65: 10 # 0001 0000, 绑定的是 cpu0
可以看出,网卡发送接收相关的中断(57-64
) 对应网卡8个合并队列 ens192-rxtx-0~7
,对应着 cpu 0-6
, 服务器是8核的虚拟机,虽然 cpu7 没用在这个网卡中断上,有可能其他中断有占用,cpu1
在 59 与 63 号中断共用,也可以自己指派 cpu,使其负载均衡,修改的文件是上面的 /proc/irq/$irq/smp_affinity
这里要注意的是每个合并队列
实际上有两个独立的队列,只是为了省写方便
,例如 ens192-rxtx-0 指代 rx-0,tx-0
中断号 | rxtx合并队列 | cpu |
---|---|---|
57 | ens192-rxtx-0 | cpu0 |
58 | ens192-rxtx-1 | cpu6 |
59 | ens192-rxtx-2 | cpu1 |
60 | ens192-rxtx-3 | cpu3 |
61 | ens192-rxtx-4 | cpu5 |
62 | ens192-rxtx-5 | cpu4 |
63 | ens192-rxtx-6 | cpu1 |
64 | ens192-rxtx-7 | cpu2 |
总结
网卡的 RX(接收)队列 和 TX(发送)队列 可以由 同一个 CPU 核心处理,也可以由不同的 CPU 核心处理,具体取决于以下因素:
1. 默认情况(单队列网卡)
- 如果网卡只有
1个 RX 队列 和1个 TX 队列
(即单队列网卡),通常:- 同一个 CPU 核心 负责处理 RX 和 TX(通过中断或轮询方式)。
- 例如,Linux 默认情况下,
eth0
的接收和发送中断可能绑定到 CPU 0。
2. 多队列网卡
- 现代高性能网卡(如 Intel I350、X710、Mellanox ConnectX)支持:
多 RX 队列
(RSS, Receive Side Scaling):不同 RX 队列可以由不同 CPU 核心处理(负载均衡)。多 TX 队列
(XPS, Transmit Packet Steering):不同 TX 队列也可以绑定到不同 CPU 核心。
- RX 和 TX 可以独立绑定到不同 CPU:
- 例如:
- RX 队列 0 → CPU 0
- TX 队列 0 → CPU 1
- RX 队列 1 → CPU 2
- TX 队列 1 → CPU 3
- 例如:
3. 如何查看和配置绑定关系?
- Linux 查看中断绑定:
cat /proc/interrupts | grep ens192 # 查看网卡中断分配
- 手动调整绑定(如将 RX 队列 0 绑定到 CPU 2):
echo 4 > /proc/irq/<IRQ_NUM>/smp_affinity # 4 = CPU 2 (二进制掩码)
- XPS(TX 队列绑定):
echo 1 > /sys/class/net/ens192/queues/tx-0/xps_cpus # TX 队列 0 绑定到 CPU 0
4. 性能优化建议
RX 和 TX 分离
:避免同一个 CPU 同时处理接收和发送,减少竞争。NUMA 架构优化
:确保网卡队列绑定的 CPU 和网卡位于同一个 NUMA 节点,减少跨节点访问延迟。
结论
单队列网卡
:RX 和 TX 通常由 同一个 CPU 处理。多队列网卡
:RX 和 TX 可以 独立绑定到不同 CPU(推荐配置,提高并行性)。
作为开篇先认识网卡的一些概念,下一篇就开始探索 Linux 网络数据的收发过程了,会用到本篇网卡队列的知识,敬请期待……