lwIP bring-up 할 때 이런 상태를 꽤 자주 본다.
- PHY 링크 LED는 켜져 있다
- 패킷 캡처를 보면 브로드캐스트도 보인다
- 그런데 DHCP Discover가 안 나가거나, 재연결 뒤에 다시 IP를 못 받는다
처음 보면 PHY 드라이버나 DHCP 서버부터 의심하게 된다.
그런데 실제로는 netif 상태 전환 순서가 어긋난 경우가 많다.
오늘 글은 그 순서를 짧게 정리하는 메모다.
먼저 구분할 것: up과 link up은 다르다
lwIP에서 자주 헷갈리는 상태가 이 둘이다.
netif_set_up(): 인터페이스를 관리 상태에서 올림netif_set_link_up(): 실제 물리 링크가 살아있다고 알림
둘 다 이름이 “올린다”라서 같은 뜻처럼 보이는데,
실제로는 역할이 다르다.
간단히 보면 이렇다.
netif up
= 이 인터페이스를 스택이 사용 가능 상태로 본다
link up
= PHY/driver 기준으로 실제 링크가 살아있다
DHCP는 이 상태 전환이 맞아야 자연스럽게 붙는다.
전형적인 실패 패턴 1: link만 올리고 netif는 down 상태
드라이버 코드에서 PHY 인터럽트를 받고 바로 이런 식으로 처리하는 경우가 있다.
netif_set_link_up(&gnetif);
dhcp_start(&gnetif);
그런데 netif 자체가 아직 up이 아니면,
상태머신이 기대한 순서로 안 돌 수 있다.
증상은 보통 이렇다.
- DHCP가 아예 시작 안 하는 것처럼 보임
- 첫 bring-up에서는 되는데 재부팅/재연결 뒤 랜덤하게 실패
- ARP나 UDP는 일부 보이는데 IP 할당만 안 됨
즉 “링크가 보인다”와 “인터페이스가 동작 준비됐다”를 분리해서 봐야 한다.
전형적인 실패 패턴 2: 링크 이벤트마다 dhcp_start()를 중복 호출
링크가 flap 되거나 케이블을 재삽입하면,
상태 전환이 생각보다 자주 발생한다.
이때 흔한 코드가 이거다.
link up interrupt
-> netif_set_link_up()
-> dhcp_start()
또 다른 init path
-> netif_set_up()
-> dhcp_start()
이렇게 두 군데에서 DHCP 시작을 건드리면,
테스트에 따라 멀쩡해 보이기도 하고
어떤 환경에서는 lease 재획득이 꼬이기도 한다.
특히 재연결 이슈는 “한 군데에서만 시작/정지한다” 원칙이 없으면 길어진다.
bring-up에서 무난한 순서
가장 덜 헷갈리는 흐름은 보통 이렇다.
1) netif_add()
2) netif_set_default() 필요 시 설정
3) netif_set_up()
4) PHY 링크 확인
5) 링크가 살아있으면 netif_set_link_up()
6) DHCP를 쓸 경우 dhcp_start()
링크가 나중에 올라오는 구조라면,
핵심은 상태를 한 군데에서 관리하는 것이다.
boot:
netif_add()
netif_set_up()
phy link callback:
if (link up) {
netif_set_link_up()
dhcp_start() 또는 dhcp_network_changed() 정책 수행
} else {
netif_set_link_down()
dhcp_stop() 여부는 정책에 맞게 결정
}
프로젝트마다 DHCP 재시작 정책은 다르지만,
up/down과 link up/down을 섞어 쓰면 디버깅이 어려워진다.
재연결 뒤에만 안 붙는 이유
처음 부팅에서는 잘 되는데,
케이블 재삽입이나 스위치 재연결 뒤에만 안 붙는 경우가 있다.
이건 보통 상태 복구가 반쪽이라서 그렇다.
1) 링크 down은 알렸는데 up 때 DHCP를 다시 안 건다
한 번 lease를 받았다는 이유로
재연결 뒤에는 DHCP를 따로 건드리지 않는 코드가 있다.
그런데 네트워크가 바뀌었거나,
상대 스위치/서버 상태가 달라졌으면 그대로 못 붙을 수 있다.
2) link up 전에 dhcp_start()를 먼저 친다
이 경우는 초기화 타이밍에 따라
Discover가 안 나가거나, 나가도 재시도 흐름이 예상과 다르게 보일 수 있다.
3) 드라이버 링크 이벤트가 중복/지연된다
PHY polling과 인터럽트를 같이 쓰면
상태 전환이 두 번 들어오는 경우가 있다.
그러면 로그에는 link up/down이 맞는 것처럼 보여도,
실제로는 DHCP start/stop이 꼬여 있다.
확인할 로그 포인트
이 이슈는 패킷 캡처만 보면 애매할 때가 많다.
그래서 나는 상태 로그를 같이 남긴다.
netif is up/downlink is up/downdhcp_start()/dhcp_stop()호출 시각dhcp_supplied_address()또는 IP 할당 시각- PHY 이벤트 발생 순서
이 다섯 줄만 있어도 “링크는 붙었는데 DHCP 상태머신이 안 돌았다”를 빨리 확인할 수 있다.
구현 쪽 팁
- 링크 이벤트 콜백 한 군데에서만
netif_set_link_up/down()을 호출 netif_set_up()은 부팅 초기화 경로에서 한 번만 처리- DHCP 시작/정지 정책을 함수 하나로 모아 중복 호출을 줄임
- 링크 flap 테스트를 따로 해서 재삽입 시퀀스를 반복 확인
특히 bring-up 초반에는,
“IP가 안 붙는다”를 DHCP 서버 탓으로 넘기기 전에
내 상태 전환 로그부터 정리하는 게 훨씬 빠르다.
빠른 체크리스트
netif_set_up()이 실제로 호출되는지 확인- 링크 up 전에
dhcp_start()가 먼저 호출되지 않는지 확인 - 링크 재삽입 뒤 DHCP 재시작 정책이 있는지 확인
- link 이벤트 경로가 둘 이상인지 확인(폴링 + IRQ 중복)
- 패킷 캡처와 상태 로그를 같은 시간축으로 비교
한 줄 요약
lwIP에서 링크는 살아있는데 DHCP가 안 붙으면, PHY보다 먼저 netif_set_up(), netif_set_link_up(), dhcp_start()의 호출 순서와 중복 상태 전환부터 확인하는 게 제일 빠르다.
추천 키워드
lwIP, DHCP, netif, link up, ethernet bring-up, embedded network
DevBJ | 오늘을살자, Log Today