Linux 6.18 NAPI 문서 · 일반적인 NIC 수신 예

네트워크 수신은 패킷마다 interrupt 한 번일까요?

NIC의 DMA ring, interrupt, NAPI poll, socket 수신을 다른 단계로 나눕니다.

장치 완료와 사용자 recv는 멀리 떨어져 있습니다

일반적인 NIC의 수신 처리 경로
  1. NIC의 receive queue

    장치가 준비된 RAM buffer에 수신 데이터를 씁니다.

    완료 상태와 interrupt 등을 제공합니다.

  2. driver의 NAPI 처리

    완료된 descriptor와 buffer를 처리하고 상위 stack에 전달합니다.

    protocol stack이 packet을 해석합니다.

  3. 네트워크 stack

    주소·protocol·연결 상태와 정책에 따라 처리합니다.

    해당 socket의 수신 데이터와 대기 상태를 갱신합니다.

  4. 사용자 프로그램

    recv 등으로 준비된 데이터를 읽습니다.

화살표는 처리 계층의 흐름입니다. packet 하나가 interrupt 하나, recv 한 번과 반드시 대응한다는 뜻은 아닙니다.

TCP는 byte stream이므로 driver가 받은 Ethernet frame 경계가 애플리케이션 메시지 경계로 그대로 전달되지 않습니다. 이 글은 NIC에서 커널 처리까지를 다루며, 메시지 길이와 backpressure는 기존 TCP 글에서 이어서 보실 수 있습니다. NAPI의 기본 동작 TCP byte stream

NAPI의 budget은 이번 poll의 Rx 처리량을 제한합니다

상황poll의 의미
처리할 Rx가 있고 budget이 남습니다.budget 안에서 수신 작업을 진행합니다.
budget을 다 썼고 일이 남습니다.계속 처리할 수 있도록 해당 규칙에 맞는 work 수를 반환합니다.
일을 끝냈습니다.napi_complete_done 등의 완료 규칙을 따르고 필요한 경우 IRQ를 다시 허용합니다.
budget이 0입니다.Rx·XDP 처리를 하지 않는 특별한 호출 조건을 확인해야 합니다. 이때 napi_complete_done을 호출하지 않습니다.

Tx completion 처리와 Rx budget은 같은 제한이 아닙니다. 또한 정확히 budget만큼 처리한 순간 queue가 비었을 때는 “일이 남음”과 “모두 끝남”의 표현을 조심해야 합니다. 일을 정확히 budget만큼 하고 모두 끝냈다면, 완료 처리 없이 budget을 반환해 다음 poll에서 종료하거나, 완료 처리 후 budget - 1을 반환하는 방식을 사용할 수 있습니다. budget이 0인 경우에는 이 완료 처리 방식을 적용하지 않습니다.

NAPI 중 IRQ masking은 race를 고려해야 합니다

장치가 새 이벤트마다 interrupt를 계속 발생시키는 동안 같은 queue를 poll하면 불필요한 interrupt가 늘 수 있습니다. driver는 장치가 자동으로 mask하는지, 자신이 mask해야 하는지에 맞춰 schedule·mask·complete·unmask 순서를 설계합니다. 무조건 interrupt를 영구히 꺼 버리는 최적화가 아닙니다.

NAPI는 보통 softirq에서 처리하지만 threaded NAPI와 busy polling 같은 구성도 있습니다. 따라서 “NAPI는 반드시 interrupt 직후 같은 CPU에서만 실행된다”는 식으로 범위를 줄이지 않습니다. NAPI instance·queue pair·IRQ의 관계도 장치별로 확인합니다. queue와 CPU의 관계

손실과 지연을 어느 queue에서 발생했는지 나눕니다

ip -s link show dev eth0
ethtool -S eth0
cat /proc/interrupts
cat /proc/softirqs

eth0는 예시 이름입니다. 실제 interface 이름과 driver가 지원하는 통계를 사용해야 합니다. 서로 다른 장치의 ethtool 통계 이름은 같지 않을 수 있습니다.

관찰함께 볼 것
NIC drop·miss가 증가합니다.ring 고갈·buffer 공급·처리 CPU의 부하·장치 error를 확인합니다.
interrupt가 적은데 throughput이 높습니다.coalescing·batch 처리·polling 여부를 확인합니다. interrupt 수만으로 packet 수를 계산하지 않습니다.
packet은 도착하지만 앱이 느립니다.socket buffer·scheduler·애플리케이션 소비 속도와 protocol 처리를 함께 확인합니다.
종료 중 crash가 납니다.NAPI ownership 해제와 poll 함수의 실제 반환 시점, buffer·netdev 수명을 구분합니다.

device driver의 queue·통계·종료 규칙도 함께 확인해야 합니다. 네트워크 driver의 수명 규칙 특히 napi_disable은 NAPI ownership이 해제되기를 기다리는 규칙을 갖습니다. napi_complete_done 뒤에 해제될 수 있는 자료 구조를 계속 만지는 코드는 별도로 점검해야 합니다.