CHAPTER 07
7. NAPI budget, NET_RX_SOFTIRQ와 GRO를 실행 context별로 읽는다
hard IRQ는 NAPI를 schedule하고 빠져나오며 실제 RX 처리는 softirq 또는 threaded NAPI context에서 budget 단위로 일어납니다. `work_done < budget`과 `napi_complete_done()`의 조건을 ring pending과 함께 봅니다.
budget
poll은 최대 budget packet만 처리합니다. budget을 모두 썼으면 보통 scheduled 상태를 유지해 다음 softirq round에서 계속합니다.
complete
work가 budget보다 적고 더 처리할 것이 없을 때만 complete하고 IRQ를 다시 켭니다. device-specific race check가 필요합니다.
context
hard IRQ, NET_RX_SOFTIRQ, ksoftirqd, threaded NAPI는 preemption과 latency 성격이 다릅니다.
GRO
같은 flow의 packet을 묶어 protocol 처리 비용을 줄입니다. wire packet 수와 상위 stack skb 수가 같지 않을 수 있습니다.
레지스터와 관측값을 함께 읽는 표
| 항목 | 소유 블록 | 설정 또는 의미 | 정상 증거 | 실패 해석 |
|---|---|---|---|---|
| napi state bits | net core | SCHED, DISABLE, THREADED | IRQ/poll lifecycle와 일치 | double schedule 또는 disable race |
| poll work_done | driver | 이번 round packet 수 | 0..budget 범위 | descriptor와 packet 단위 혼동 |
| ring pending | DMA/driver | CPU 소유 RX entry | complete 시 0 또는 race 재검사 | work 남았는데 IRQ unmask |
| softnet_data poll_list | net core | CPU별 scheduled NAPI | affinity와 처리 CPU 일치 | RPS/threaded 이동 |
| softirq counters | CPU | NET_RX 실행과 backlog | traffic 증가와 대응 | ksoftirqd starvation |
| GRO stats/trace | net core | merge/flush와 flow | 상위 packet 수 차이를 설명 | 오프로드를 drop으로 오인 |
증상에서 첫 실패 경계를 찾는 표
| 관측 증상 | 직전 통과 증거 | 우선 확인 | 반증 시험 | 판정 |
|---|---|---|---|---|
| IRQ 증가, poll 없음 | hard IRQ handler 실행 | napi_schedule_prep과 state | napi state/disable trace | schedule 경계 |
| poll은 돌고 ring 누적 | NAPI 실행 | budget/CPU 시간/descriptor 처리 | budget과 work_done histogram | 처리량 부족 |
| complete 후 packet 정지 | ring이 잠시 비었음 | unmask와 새 completion race | status 재검사/IRQ mask capture | lost wakeup |
| ksoftirqd CPU 100% | packet 계속 처리 | GRO/RPS/coalescing/budget | feature와 affinity를 하나씩 변경 | software 처리 병목 |
| wire count와 stack count 불일치 | MAC/DMA count 정상 | GRO merge와 XDP/drop | GRO off 및 drop reason 비교 | 의도적 aggregate인지 판정 |
| latency tail만 큼 | 평균 throughput 정상 | softirq defer와 CPU contention | irq/softirq scheduling trace | context scheduling 경계 |
실제 검증 절차
| 순서 | 실행 | 남길 증거 | 판정 목적 |
|---|---|---|---|
| 1 | IRQ, poll enter/exit, budget/work_done, complete를 trace합니다. | round별 event | NAPI 계약 확인 |
| 2 | 각 poll 종료 시 ring pending과 IRQ mask를 기록합니다. | complete 경계 snapshot | lost wakeup 검증 |
| 3 | softirq와 ksoftirqd 실행 시간을 CPU별로 측정합니다. | context/affinity 분포 | latency 원인 분리 |
| 4 | GRO on/off에서 wire, DMA, stack, socket count를 비교합니다. | 계층별 packet 수 | aggregate 효과 설명 |
주의NAPI의 budget은 descriptor byte 수가 아니라 보통 처리한 packet 수 계약입니다. multi-buffer frame에서 descriptor 수를 그대로 반환하지 않습니다.
공개적으로 다시 확인할 수 있는 자료
공개되지 않은 vendor register나 integration별 offset을 추측해서 채우지 않았습니다. 아래 제조사 자료, architecture 문서와 Linux v6.18.37 원본에서 다시 확인할 수 있는 범위만 사용했습니다.
Linux stmmac driver
Synopsys GMAC/GMAC4/XGMAC, descriptor, NAPI, PTP와 offload 공개 설명
Linux NAPI
schedule, poll budget, completion과 IRQ 재활성화 계약
Linux v6.18.37 stmmac_main.c
open, xmit, RX, ISR와 NAPI poll 원본
Linux v6.18.37 dwmac4_dma.c
DMA channel, ring length, tail pointer와 interrupt enable
Linux v6.18.37 net/core/dev.c
NAPI core, NET_RX_SOFTIRQ와 receive stack 진입
Linux DMA API HOWTO
descriptor와 packet buffer의 CPU/device ownership, mapping과 barrier