Category: lwIP
lwIP 카테고리에 작성된 글 목록입니다.
lwIP Roadmap
작은 임베디드 네트워크 스택이 왜 가끔 멈출까. lwIP를 메모리 지도, 타이머, 호출 컨텍스트, 버퍼 수명주기 순서로 읽는 흐름입니다.
자동 생성된 넓은 주제보다 실제 bring-up과 부하 테스트에서 바로 부딪히는 문제만 남겨, 막힌 지점에서 다시 찾기 좋게 정리합니다.
시작과 설정
- lwIP 메모리 옵션 구조 정리: PBUF_POOL, MEM_SIZE, MEMP_NUM_*를 한 번에 보기
lwIP 메모리를 PBUF_POOL, MEM_SIZE, MEMP_NUM_*, OS 큐로 나눠 보는 출발점입니다.
타이머와 상태 관리
- lwIP 타이머가 안 돈다: NO_SYS에서 sys_check_timeouts() 빠지면 생기는 증상
NO_SYS에서 타이머 루프가 빠졌을 때 DHCP/ARP/TCP가 왜 흔들리는지 봅니다.
TCP/IP 코어와 스레드
- lwIP에서 ISR에서 바로 보내면 가끔 터진다: tcpip_thread로 넘기는 패턴 정리
ISR에서 lwIP API를 직접 호출하지 않고 tcpip_thread로 넘겨야 하는 이유를 정리합니다.
- lwIP에서 tcpip_thread 안에서 다시 기다리면 멈춘다: callback 안의 netconn/sockets 호출이 self-deadlock이 되는 이유
tcpip_thread 컨텍스트 안에서 다시 동기 API를 호출해 스스로 기다리며 멈추는 패턴을 정리합니다.
DHCP/ARP/UDP
- lwIP에서 링크는 붙었는데 DHCP가 안 돈다: netif_set_up() / netif_set_link_up() 순서를 같이 보자
링크는 살아있는데 DHCP가 시작되지 않거나 다시 안 붙을 때 netif 상태 전환 순서를 정리합니다.
- lwIP에서 링크 복구 후 UDP가 한동안 죽어 보인다: ARP 캐시와 netif 상태를 같이 보자
링크 복구 뒤 UDP 송신만 한동안 막힐 때 ARP 캐시와 netif 상태를 함께 보는 포인트를 정리합니다.
- lwIP에서 UDP send가 ERR_RTE로 실패한다: payload보다 netif 상태와 route를 먼저 보자
UDP 송신이 ERR_RTE로 실패할 때 payload가 아니라 netif up/link/default route 상태를 먼저 보는 흐름입니다.
- lwIP에서 UDP broadcast가 안 나간다: SO_BROADCAST와 netif flags를 같이 보자
UDP broadcast packet이 보이지 않을 때 SO_BROADCAST, netif flag, IP 설정, 송신 인터페이스를 나눠 보는 흐름입니다.
메모리와 버퍼
- lwIP pbuf가 가끔 터진다: PBUF_REF/POOL/RAM 수명주기와 zero-copy 함정
pbuf 타입과 zero-copy 수명주기를 잘못 다뤘을 때 랜덤 크래시가 나는 패턴을 봅니다.
- lwIP TCP 버퍼 설정 읽는 법: TCP_SND_BUF, TCP_WND, MEM_SIZE, MEMP_NUM_TCP_SEG, PBUF_POOL_SIZE
TCP 송신 버퍼, 수신 윈도우, MEM heap, tcp_seg pool, PBUF_POOL_SIZE를 같은 숫자처럼 보지 않도록 구분합니다.
- lwIP에서 UDP 길이가 가끔 잘못 읽힌다: pbuf 체인에서는 len 말고 tot_len을 봐야 한다
pbuf 체인에서 `len`만 보고 파싱해 UDP payload가 잘리거나 CRC처럼 오해되는 패턴을 정리합니다.
- lwIP RAW UDP callback 뒤에 수신이 멈춘다: pbuf_free를 놓치면 PBUF_POOL이 먼저 마른다
RAW UDP receive callback에서 pbuf 해제를 놓쳐 수신이 몇 분 뒤 멈추는 전형적인 패턴을 정리합니다.
TCP 디버깅
- lwIP RAW TCP가 '가끔 멈춘다': tcp_recved() 안 치면 윈도우가 안 열린다
RAW TCP에서 tcp_recved() 누락으로 receive window가 고정되며 멈추는 증상을 정리합니다.
- lwIP TCP 재시도 루프에서 RTOS delay가 필요한 이유: busy loop를 막고 CPU를 양보하기
TCP 송신 재시도 루프에서 busy loop를 피하기 위해 RTOS delay로 CPU를 양보해야 하는 이유를 정리합니다.
- lwIP에서 tcp_write()가 ERR_MEM을 돌려준다: free RAM보다 snd_buf와 snd_queuelen을 먼저 보자
tcp_write() ERR_MEM을 heap 부족으로만 보지 않고 snd_buf, snd_queuelen, tcp_seg pool, ACK 흐름으로 나눠 봅니다.
- lwIP RAW TCP에서 close가 가끔 실패한다: tcp_close()의 ERR_MEM은 free RAM보다 송신 잔여 상태를 먼저 봐야 한다
RAW TCP에서 tcp_close()가 ERR_MEM을 반환할 때 메모리 부족보다 unsent/unacked 상태를 먼저 보는 흐름을 정리합니다.
포팅과 성능
- lwIP에서 RX는 되는데 payload가 가끔 깨진다: DMA 버퍼와 D-Cache 순서를 같이 봐야 한다
DMA와 D-Cache 일관성이 맞지 않아 수신 데이터가 가끔 깨지거나 송신이 엉뚱해지는 패턴을 정리합니다.
- lwIP에서 ping은 되는데 TCP나 UDP만 이상하다: checksum offload를 반만 켜면 증상이 더 헷갈린다
하드웨어 checksum offload를 lwIP 옵션과 드라이버에서 반만 맞춰 두었을 때 보이는 증상을 정리합니다.
- lwIP에서 RX pbuf를 넘긴 뒤 가끔 깨진다: tcpip_input ownership을 먼저 정리하자
Ethernet RX 드라이버가 pbuf를 tcpip_input에 넘긴 뒤 free/reuse 책임을 잘못 처리할 때 생기는 문제를 정리합니다.
- lwIP에서 송신이 가끔 멈춘다: linkoutput에서 TX descriptor와 pbuf 수명을 같이 보자
netif linkoutput에서 TX descriptor 부족, pbuf chain 복사, zero-copy 수명주기가 섞일 때 송신이 멈추는 패턴을 정리합니다.
최근 글
-
lwIP에서 UDP broadcast가 안 나간다: SO_BROADCAST와 netif flags를 같이 보자
lwIP에서 UDP broadcast 송신이 timeout처럼 보이거나 패킷이 캡처되지 않으면 payload보다 SO_BROADCAST 또는 SOF_BROADCAST, NETIF_FLAG_BROADCAST, netif up/link, source IP, route를 먼저 확인해야 한다. RAW API, netconn/socket API, multi-netif 환경의 확인 순서를 정리한다.
-
lwIP에서 tcp_write()가 ERR_MEM을 돌려준다: free RAM보다 snd_buf와 snd_queuelen을 먼저 보자
lwIP RAW TCP에서 tcp_write()가 간헐적으로 ERR_MEM을 반환하면 free RAM보다 TCP_SND_BUF, TCP_SND_QUEUELEN, MEMP_NUM_TCP_SEG, unsent/unacked 큐를 먼저 확인해야 한다. 작은 write 반복, ACK 지연, sent callback 없는 busy loop가 송신 큐를 막는 패턴을 정리한다.
-
lwIP에서 송신이 가끔 멈춘다: linkoutput에서 TX descriptor와 pbuf 수명을 같이 보자
lwIP 포팅에서 수신은 되는데 송신이 부하 중 멈추거나 linkoutput이 실패하면 TX descriptor 회수, pbuf chain 처리, zero-copy pbuf lifetime을 같이 봐야 한다. 복사 기반 송신과 DMA zero-copy 송신에서 ownership 기준이 어떻게 달라지는지 정리한다.
-
-
lwIP에서 RX pbuf를 넘긴 뒤 가끔 깨진다: tcpip_input ownership을 먼저 정리하자
lwIP 포팅에서 RX 패킷을 tcpip_input()으로 넘긴 뒤 간헐적인 payload 깨짐, double free, PBUF_POOL 고갈이 보이면 pbuf ownership 규칙을 먼저 확인해야 한다. ERR_OK와 실패 반환값, DMA 버퍼 재사용, ISR 컨텍스트, 예외 경로별 pbuf_free 기준을 정리한다.
-
lwIP에서 UDP send가 ERR_RTE로 실패한다: payload보다 netif 상태와 route를 먼저 보자
lwIP에서 udp_sendto() 또는 socket sendto()가 ERR_RTE로 실패하면 UDP payload나 ARP보다 먼저 보낼 netif를 찾았는지 확인해야 한다. DHCP 완료 전 송신, default netif 누락, netif up/link 상태 불일치, IP 주소 미설정 같은 route 판단 지점을 bring-up 관점에서 정리한다.
-
lwIP RAW TCP에서 close가 가끔 실패한다: tcp_close()의 ERR_MEM은 free RAM보다 송신 잔여 상태를 먼저 봐야 한다
lwIP RAW TCP에서 연결 종료 시 tcp_close()가 가끔 ERR_MEM을 반환하면 단순 heap 부족으로 보면 오래 헤맨다. 아직 보내지 못한 세그먼트와 미확인 ACK 상태가 남아 있거나 close를 너무 이른 문맥에서 호출한 경우가 많아서, pcb 송신 상태와 콜백 흐름을 같이 보는 편이 빠르다.
-
lwIP에서 ping은 되는데 TCP나 UDP만 이상하다: checksum offload를 반만 켜면 증상이 더 헷갈린다
lwIP 포팅에서 ICMP는 되는데 TCP나 UDP만 깨지거나, 송신만 실패하고 수신은 정상처럼 보이면 checksum offload 설정 불일치를 먼저 확인해야 한다. lwIP 옵션과 MAC 드라이버가 같은 책임 분담을 보지 않으면 패킷은 나가도 상대가 조용히 버릴 수 있다.
-
lwIP TCP 버퍼 설정 읽는 법: TCP_SND_BUF, TCP_WND, MEM_SIZE, MEMP_NUM_TCP_SEG, PBUF_POOL_SIZE
lwIP의 TCP_SND_BUF, TCP_WND, MEM_SIZE, MEMP_NUM_TCP_SEG, PBUF_POOL_SIZE가 각각 어떤 병목을 만들고 어떤 메모리 예산과 연결되는지 일반화된 예시로 정리한다.
-
lwIP RAW UDP callback 뒤에 수신이 멈춘다: pbuf_free를 놓치면 PBUF_POOL이 먼저 마른다
lwIP에서 UDP는 처음엔 잘 되는데 몇 분 뒤부터 recv callback이 끊기거나 pbuf_alloc 실패가 보이면, 드라이버보다 먼저 RAW UDP callback에서 pbuf_free를 빠뜨린 경로를 확인해야 한다. 작은 누수 하나가 PBUF_POOL 고갈로 이어져 전체 RX 경로를 막을 수 있다.
-
lwIP에서 RX는 되는데 payload가 가끔 깨진다: DMA 버퍼와 D-Cache 순서를 같이 봐야 한다
lwIP 포팅에서 링크는 정상이고 인터럽트도 도는데 UDP payload나 ARP 내용이 가끔 깨져 보이면, pbuf보다 먼저 DMA 버퍼와 CPU D-Cache 일관성을 확인해야 한다. RX 전 invalidate, TX 후 clean 순서가 어긋나면 랜덤 패킷 손상처럼 보이는 증상이 반복된다.