U-Boot에서 tftp 명령으로 커널 이미지나 rootfs를 받아오다가 진행률이 멈추거나, Loading: * 이후로 아무 반응 없이 프롬프트로 돌아와 버리는 경우가 있다. 케이블도 꽂혀 있고 서버도 떠 있는데 왜 멈추는지는 로그 한 줄만 봐서는 알기 어렵다. 이 글에서는 원인이 될 수 있는 지점들을 정리하고, QEMU로 성공/실패 케이스를 각각 실제로 재현해본다.
원인이 될 수 있는 지점들
| 원인 | 증상 |
|---|---|
serverip/ipaddr가 실제 네트워크와 안 맞음 | “Loading:” 이후 ARP Retry count exceeded; starting again로 즉시 중단 |
| 스위치 STP로 인해 링크업 직후 포트가 forwarding 상태가 아님 | 부팅 후 곧바로 tftp를 시작하면 수십 초간 패킷이 전부 드롭됨 |
| PHY RGMII 클럭 지연 등 보드 하드웨어 신호 문제 | 작은 파일은 되는데 큰 이미지 전송 중간에 멈추거나 깨짐 |
| TFTP 서버가 windowsize/blocksize 확장을 지원하지 않음 | 협상 단계에서 재시도를 반복하다 멈춤 |
| 타임아웃/재시도 횟수 기본값이 실제 왕복 지연보다 짧음 | 느린 네트워크에서 정상 전송인데도 재시도 후 실패로 종료 |
QEMU로 실제 재현하기
mainline U-Boot를 qemu_arm64_defconfig로 빌드해 QEMU의 usermode 네트워크(내장 TFTP 서버, 게이트웨이 10.0.2.2)로 정상 전송부터 확인했다.
=> setenv ipaddr 10.0.2.15
=> setenv serverip 10.0.2.2
=> tftp 0x40200000 test.bin
Using virtio-net#31 device
TFTP from server 10.0.2.2; our IP address is 10.0.2.15
Filename 'test.bin'.
Load address: 0x40200000
Loading: *#####################################
6.2 MiB/s
done
Bytes transferred = 524288 (80000 hex)
이제 serverip만 존재하지 않는 주소(10.0.2.50)로 바꿔서, “서버는 있는데 응답이 없는” 흔한 상황을 재현했다.
=> setenv serverip 10.0.2.50
=> tftp 0x40200000 test.bin
Using virtio-net#31 device
TFTP from server 10.0.2.50; our IP address is 10.0.2.15
Filename 'test.bin'.
Load address: 0x40200000
Loading: *
ARP Retry count exceeded; starting again
이 메시지는 U-Boot 소스의 net/arp.c에 그대로 있다.
if (arp_wait_try >= CONFIG_NET_RETRY_COUNT) {
puts("\nARP Retry count exceeded; starting again\n");
...
}즉 tftp 자체가 아니라 그 앞 단계인 ARP 응답을 CONFIG_NET_RETRY_COUNT번 재시도할 때까지 못 받은 것이다. 실제 환경에서는 잘못된 serverip/게이트웨이 설정, 혹은 스위치가 그 시점에 ARP 브로드캐스트를 포워딩하지 않는 상태(STP 등)일 때 이 메시지가 나온다.
tftp 전에 ping으로 먼저 경로를 확인하면 ARP 문제인지 아닌지를 빠르게 구분할 수 있다.
=> ping 10.0.2.2
Using virtio-net#31 device
host 10.0.2.2 is alive
타임아웃/재시도 관련 환경변수
net/tftp.c의 tftp_start()는 아래 환경변수를 읽어 타임아웃과 블록/윈도 크기를 조정한다(CONFIG_NET_TFTP_VARS 활성화 시).
| 환경변수 | 역할 |
|---|---|
tftpblocksize | TFTP 블록 크기(옥텟 옵션) 협상값 지정 |
tftpwindowsize | ACK 없이 연속으로 보낼 블록 수(RFC 7440 windowsize) 지정 |
tftptimeout | 블록 하나에 대한 타임아웃(ms), 최소 1000 |
tftptimeoutcountmax | 타임아웃 재시도 최대 횟수 |
서버가 windowsize 확장을 지원하지 않아 재협상을 반복한다면 setenv tftpwindowsize 1로 꺼보고, 네트워크 자체가 느려 정상 전송인데도 끊긴다면 tftptimeout/tftptimeoutcountmax를 늘려서 구분한다.
주의사항
- 관리형 스위치를 쓴다면 보드가 물린 포트에 portfast(edge port) 설정이 있는지 확인할 것 — STP forwarding delay 때문에 링크업 직후 몇십 초간 부팅 스크립트가 실패하는 경우가 흔하다.
- 같은 케이블/포트에서 작은 파일은 되는데 큰 이미지에서만 멈춘다면 소프트웨어보다 PHY/RGMII 배선 쪽(보드 디바이스 트리의 클럭 지연 설정 등) 하드웨어 원인을 의심할 것 — 이 부분은 QEMU 가상 NIC로는 재현이 안 돼 이 글에서 직접 검증하지 못했다.
tftptimeoutcountmax를 무작정 늘리기 전에ping으로 경로가 살아있는지부터 확인할 것 — 경로 자체가 끊겨 있으면 재시도 횟수를 늘려도 결국 실패한다.
마무리
tftp가 멈추는 지점이 “Loading:” 직후인지, 진행 중간인지에 따라 원인 성격이 다르다. ARP 단계에서 막힌다면 IP/게이트웨이나 스위치 설정을, 전송 도중 멈춘다면 서버의 확장 옵션 지원 여부나 하드웨어 신호 문제를 먼저 의심하면 된다.