はじめに
NICはLinux ServerとNetworkを接続するHardwareです。しかし、高速通信はNIC単体で実現するわけではありません。Device Driver、DMA、Descriptor Ring、Interrupt、NAPI、複数CPU Core、Offload機能が連携してPacketを処理します。
本記事では、NICとDevice Driverの基本的な関係から、RX / TX Ring、DMA、Interrupt、NAPI、Multi Queue、CPUへの分散、NIC Offload、確認コマンドまでを順番に解説します。PacketがNIC、Memory、CPUの間をどのように移動し、LinuxがNICの性能をどう引き出すのかを一つの記事で整理します。
NIC・Device Driver・Network Interfaceの関係
NICとは
NICはNetwork Interface CardまたはNetwork Interface Controllerの略です。Ethernet Frameの送受信、物理Link、MAC Address、DMA、Queue、ChecksumやSegmentationなどのHardware処理を担当します。
NICにはLink Speed、Duplex、Port、Firmware、Queue数、Offload機能などの能力があります。仮想Machineでは仮想NICが見える場合があり、実際の物理NICとの間にHypervisorやVirtual Switchが存在します。
NICとDevice Driverの関係
Device DriverはKernelの共通Network機能とNIC固有Hardwareの橋渡しをします。Register操作、Descriptor Ring、DMA Mapping、Interrupt、Offload設定、Link状態取得などをNICの仕様に合わせて実装します。

同じethtool Commandでも表示できる統計や設定がNICごとに異なるのは、Driverが公開する情報に違いがあるためです。Kernel、Driver、Firmwareの互換性も性能と安定性に影響します。
Network Interfaceとは
LinuxではNICに対応するNetwork Deviceが登録され、enp1s0やeth0などのInterfaceとして見えます。InterfaceはMAC Address、MTU、Queue、統計、UP / DOWN状態などを持ちます。IP AddressはこのInterfaceへ関連付けられます。
一方、lo、Bridge、Bond、VLAN、veth、Tunnelなど、物理NICへ一対一に対応しないInterfaceもあります。障害調査では、Applicationから物理NICまでにどの仮想Interfaceを通るか確認します。
NICを使う準備とPacket転送
NICの初期化
PCIe NICの例では、KernelがPCI Deviceを検出し、対応するDriverを関連付けます。DriverのProbe処理はHardware Resourceを確認し、Network Deviceを作成してKernelへ登録します。
InterfaceをUPにすると、DriverはRX Buffer、Descriptor Ring、Interrupt、NAPIなどを準備し、NICを送受信可能な状態へ進めます。

具体的な順序はDriverとHardwareによって異なります。
RX RingとTX Ring
RX / TX RingはDescriptorを循環的に管理するQueueです。RX DescriptorはNICが受信Dataを書き込むBufferを示し、TX DescriptorはNICが送信Dataを読み取るBufferと処理方法を示します。
| Ring | NICのDMA方向 | 主な処理 |
|---|---|---|
| RX Ring | NICからMemoryへWrite | 受信BufferへPacket Dataを配置 |
| TX Ring | MemoryからNICへRead | 送信BufferからPacket Dataを取得 |
Ringが小さいとBurst時に不足しやすく、大きくすると保持できるDescriptorは増えますが、Memory消費やQueueing DelayとのTrade-offがあります。変更前後はDrop、Latency、CPU負荷を測定します。
DMAの仕組み
DMAによりNICはMain Memoryと直接Dataを転送できます。CPUがPacket Dataを1ByteずつNIC RegisterへCopyする必要はありません。DriverはDMA可能なMemory領域を準備し、NICが参照できるAddressをDescriptorへ設定します。
IOMMUが有効な環境では、Deviceが利用するIO Virtual Addressと物理MemoryのMappingも関係します。NUMA ServerではNICに近いCPUとMemoryを利用できるかが性能へ影響する場合があります。
InterruptとNAPIによる受信処理
Interruptの仕組み
NICは受信や送信完了などをInterruptでCPUへ通知します。Multi Queue NICではMSI-XによってQueueごとに異なるInterrupt Vectorを割り当て、複数CPUへ分散できる場合があります。
Interrupt Coalescingは複数のEventをまとめて通知し、Interrupt回数を減らします。まとめる量を増やすとCPU効率は向上し得ますが、通知待ちによるLatencyが増える可能性があります。
NAPIとは
NAPIでは、NICからのInterruptをきっかけにPoll処理をScheduleし、複数Packetをまとめて処理します。高Traffic時にPacketごとのInterrupt処理を繰り返すことを避けることで、Interrupt Stormを抑制し、Packet当たりの処理Costを減らします。
一回のPollにはBudgetがあり、特定QueueがCPUを独占しないよう制限します。処理しきれない状態が続く場合はSoftIRQ負荷、Queue偏り、CPU Affinity、Packet Rateを確認します。
Multi QueueとCPUへのPacket分散
Multi Queue NIC
Multi Queue NICは複数のRX QueueとTX Queueを持ちます。1つのQueueとCPUだけで全Packetを処理する代わりに、Flowを複数Queueへ分けて複数CPU Coreを活用します。

Queue数が多ければ常に高速とは限りません。Traffic Flow数、CPU数、NUMA配置、Cache Locality、IRQ Affinityが関係します。単一Flowは同一Queueへ保たれることが多く、Queueを増やしても単一Connectionの帯域が比例して増えるとは限りません。
RSS・RPS・RFS・XPS
RSS・RPS・RFS・XPSは、Packet処理を複数のQueueやCPU Coreへ分散し、Network処理を効率化するための仕組みです。RSSは主にNIC側、RPS・RFS・XPSはLinux Kernel側で分散を制御します。
| 機能 | 主な役割 | 処理場所 |
|---|---|---|
| RSS | Hashに基づき受信FlowをHardware RX Queueへ分散 | NIC |
| RPS | 受信PacketのProtocol処理をSoftwareでCPUへ分散 | Kernel |
| RFS | Flowを処理するApplicationのCPUを考慮して分散 | Kernel |
| XPS | 送信CPUとTX Queueの対応を制御 | Kernel |
RSSは一般にSource / Destination Address、PortなどのHashでQueueを選びます。同じFlowを同一Queueへ割り当て、順序を保ちながら複数Flowを分散します。RPSはHardware Queueが少ない環境でもSoftwareで処理CPUを広げられます。
分散しすぎるとCPU間転送とCache Missが増える場合があります。IRQ、Application Thread、NUMA Nodeを含めて測定し、目的なくAffinityを変更しないことが重要です。
NIC Offload
Linuxでは、Checksum OffloadやTSOなどの処理をNICへOffloadしたり、GSO / GROによってKernel内でPacket処理をまとめたりすることで、CPU負荷を軽減しNetwork処理を効率化します。以下のような機能があります。
| 機能 | 主な処理場所 | 役割 |
|---|---|---|
| Checksum Offload | NIC | Checksum計算・検証の一部をHardwareへ任せる |
| TSO | NIC | 大きなTCP Dataを送信時にWire上のSegmentへ分割する |
| GSO | Kernel | Kernel内で大きな送信単位を後段まで維持する |
| GRO | Kernel | 受信した複数Packetをまとめて上位Layerへ渡す |
| LRO | NIC / Driver | 受信Packetをまとめて上位Layerへ渡す |
OffloadやPacket集約機能はCPU負荷を減らしThroughputを高めますが、Packet Captureの見え方を変える場合があります。送信Hostで大きなSegmentや不正Checksumに見えても、NICがWireへ送る前に分割・計算する予定の場合があります。
Offloadを無効化すると診断に役立つことがありますが、性能へ影響します。Production環境では変更前に影響範囲を確認し、検証と復旧手順を用意します。
LinuxでNIC / Device Driverを確認する
Linuxでは、ip、ethtool、lspci、/procなどを利用することで、NICやDevice Driverの状態を確認できます。
NICのTroubleshootingでは、InterfaceやLink状態だけでなく、Device Driver、Descriptor Ring、Multi Queue、Offload、Interruptなどを処理の仕組みと対応付けて確認することが重要です。
Interfaceの状態を確認する
ip -details link show dev <IF名>
InterfaceのUP / DOWN、MTU、MAC Address、qdiscなど、Network Interfaceの基本的な状態を確認できます。
NICのLink状態を確認する
ethtool <IF名>
NICのLink Up / Down、Speed、Duplex、Auto-negotiationなどを確認できます。
Device Driverを確認する
ethtool -i
ethtool -i <IF名>
現在使用しているDevice Driverの情報を確認できます。
主に以下の情報を確認できます。
- Device Driver名
- Driver Version
- Firmware Version
- PCI Bus情報
特定のNICがどのDevice Driverによって制御されているのかを確認する場合は、まず ethtool -i を使うと分かりやすいです。
lspci -nnk
lspci -nnk
PCI Busに接続されているDeviceと、それを制御しているKernel Driverを確認できます。
主に以下の情報を確認できます。
- PCI Device
- Vendor ID / Device ID
- Kernel driver in use:現在使用中のDriver
- Kernel modules:対応するKernel Module
NICだけでなく、Storage ControllerやGPUなど、PCI Device全体のDriverを確認したい場合に便利です。
lsmod
lsmod
現在Linux KernelにLoadされているKernel Moduleを一覧表示します。
Device DriverがKernel ModuleとしてLoadされている場合、そのModuleを確認できます。
ただし、DriverがKernelにBuilt-inされている場合は lsmod には表示されないため、特定のNICのDriverを確認する用途では ethtool -i や lspci -nnk の方が適しています。
Descriptor Ringを確認する
ethtool -g <IF名>
NICのRX / TX Ring Parameterを確認できます。最大値(Pre-set maximums)と現在の設定値(Current hardware settings)が表示されます。
ただし、ethtool -gで確認できるのはRing Sizeなどの設定値であり、TX / RX Descriptorの中身や現在の使用率を直接表示するコマンドではありません。
Multi Queueを確認する
ethtool -l <IF名>
NICが利用できるRX / TX / Combined Channel数と、現在設定されているChannel数を確認できます。
Multi Queue NICでは複数のQueueを利用してPacket処理を複数CPU Coreへ分散できるため、Network処理の並列化を確認するときに重要な情報です。
NIC Offloadを確認する
ethtool -k <IF名>
Checksum Offload、TSO、GSO、GROなど、Network処理を効率化する各種Offload機能の有効 / 無効を確認できます。
NIC / Device Driverの統計情報を確認する
ethtool -S <IF名>
NICやDevice Driverが持つ固有の統計Counterを確認できます。TX / RX Packet、Byte、Drop、Errorなど、Interface全体の統計だけでは分からない情報を確認するときに有効です。
Counter名や取得できる情報はNIC / Device Driverによって異なるため、1回の値だけではなく時間差分で増加しているCounterを確認するとTroubleshootingしやすくなります。
Hardware Interruptを確認する
cat /proc/interrupts
Hardware InterruptがCPU Coreごとに何回処理されているかを確認できます。
Multi Queue NICではQueueごとにInterrupt Vectorが割り当てられる場合があり、どのCPU CoreへInterruptが分散しているのかを確認する手掛かりになります。
SoftIRQを確認する
cat /proc/softirqs
CPU CoreごとのSoftIRQ実行回数を確認できます。Network処理では主にNET_RXやNET_TXを確認します。
特定のCPU CoreだけNET_RXなどが大きく増えている場合は、Packet処理が一部のCPUへ偏っていないかを確認する材料になります。
NIC確認コマンドまとめ
| 確認対象 | コマンド |
|---|---|
| Interface | ip -details link show dev enp1s0 |
| Link | ethtool enp1s0 |
| Device Driver | ethtool -i enp1s0 |
| PCI / Driver | lspci -nnk |
| Kernel Module | lsmod |
| Descriptor Ring | ethtool -g enp1s0 |
| Multi Queue | ethtool -l enp1s0 |
| Offload | ethtool -k enp1s0 |
| NIC / Driver統計 | ethtool -S enp1s0 |
| Hardware Interrupt | cat /proc/interrupts |
| SoftIRQ | cat /proc/softirqs |
まとめ
NICとDevice DriverはDescriptor RingとDMAを使ってPacketを転送します。InterruptとNAPIは受信通知と大量Packet処理を効率化し、Multi Queueは複数CPU Coreを活用する基盤になります。
RSS、RPS、RFS、XPSはFlow・Queue・CPUへのPacket処理の分散を制御します。また、Checksum OffloadやTSOなどのHardware Offload、GSO / GROなどのKernel機能によって、Packet処理のCPU負荷を軽減できます。ただし性能はQueue数だけで決まらず、Traffic特性、CPU、NUMA、Application配置との組み合わせで決まります。
NIC、Device Driver、Memory、CPUの関係を一つの流れとして捉えると、RX Drop、TX Queueの停滞、Interruptの偏り、SoftIRQ負荷、期待したThroughputが出ないといった問題を、HardwareからApplicationへつながる経路の中で切り分けられるようになります。
Linuxにおけるネットワークの仕組みについては、以下の書籍にまとめています。興味がありましたら、ぜひ読んでみてください。
Linuxのネットワークの仕組みを
図解で理解したい方へ
Socket・TCP・ルーティング・NIC 現場で役立つ通信処理の基礎知識など Linuxにおけるネットワークの仕組みを図解を中心にわかりやすく解説しています。
Kindleで書籍を見る →


コメント