lwIPで学ぶ組み込みTCP/IP
lwIP(lightweight IP)は、RAMが数十 kB程度の組み込み機器でも動作させやすい軽量TCP/IPスタックです。IPv4/IPv6、TCP、UDPなどの主要プロトコルに対応しています。実装の幅を生むのは、Raw/Netconn/Socketの3種類のAPIと、pbufによるコピー削減(いわゆるゼロコピー)です。あわせてNO_SYS(OSなし/スタンドアロン)とRTOS連携のどちらでも動作します。
この記事では位置づけ、内部構成、3API、チューニングの4テーマで設計判断と実装ポイントを整理します。
lwIPの位置づけとアーキテクチャ
lwIPは、スウェーデンの研究機関で開発が始まったオープンソースのTCP/IPスタックです。ライセンスはBSD系(いわゆる修正BSD、3条項BSD)です。主要なマイコンのSDKで採用されており、組み込みTCP/IP通信で広く利用されています。
軽量TCP/IPスタックとしてのlwIPの設計思想
設計目標は「フルスケールのTCP/IPを保ちつつRAM使用量を最小化する」ことです。必要なROMとRAMは、有効化する機能(IPv6、TLS、DHCP、DNSなど)やRTOS連携、バッファとプールの設定に大きく依存します。最小構成では数十kB級で動作する例もあります。ただし実装時には、ピーク時の同時接続数、ウィンドウサイズ、pbufとメモリプールの設定を含めた見積もりが必要です。このスタックは一般に32ビットクラス以上のマイコンでの採用が多く、機能構成によっては、より小規模なマイコンで動作させる例もあります。
対応プロトコルは、IPv4/IPv6、TCP、UDP、ICMP、IGMP、DHCP、DNS、SNMP、PPP、ARPなどです。いずれも組み込み機器で広く普及している主要なネットワークプロトコルです。
TCP層はふくそう制御、RTT(Round-Trip Time:ラウンドトリップ時間)推定、高速再送(fast retransmit)を備えています。RTTは往復遅延の尺度で、再送タイムアウト計算の基礎となります。
NO_SYSとOS対応モードの選択
lwIPはスタンドアロン動作(NO_SYS=1)と、RTOS連携モード(NO_SYS=0)の両方に対応します。NO_SYS構成では、受信フレームを入力関数へ渡す処理に加え、sys_check_timeouts()などのタイムアウト処理を周期的に呼び出します。このときメインループ内で長時間ブロックすると、タイムアウト処理が遅延します。その結果、TCPの再送やARPテーブルの更新などに影響が出ます。OS管理機能が不要なため、一般的にフットプリントを抑えられます。
RTOS連携ではNetconn/SocketのブロッキングAPIが使えるため、アプリケーションを簡潔に実装できます。リアルタイム性とアプリケーションの複雑さに応じてモードを選択しましょう。
lwIPの内部構成
レイヤごとに責務が明確に分割されており、各種のバッファやメモリプールの設定が性能とメモリ使用量に大きく影響します。
pbufバッファ管理とコピー削減の考え方
pbuf(packet buffer)はlwIPの中心的なデータ構造で、パケットをリンクリストで管理します。種類はPBUF_RAM(ヒープ確保)、PBUF_POOL(固定長メモリプール)、PBUF_ROM(不変データの参照)、PBUF_REF(既存データの参照)の4つです。用途に応じて使い分けます。
送信時にアプリケーションのデータバッファをPBUF_REFやPBUF_ROMで参照させると、コピー回数を削減できます(いわゆるゼロコピー送信)。ただし参照元のデータは、送信が完了するまで有効である必要があります。DMA送信や遅延送信では、送信完了前に参照元を破棄したり上書きしたりするとデータが壊れるため、寿命管理が重要です。
IPv4/TCP/UDP/ARPレイヤの構成
レイヤ間はpbufの受け渡しで接続され、受信パスはethernet_input、ip_input、tcp_input/udp_inputの順に処理されます。TCP層はコネクション管理テーブル(tcp_pcb)で接続状態や輻輳制御情報、未送信セグメント、未ACKセグメントを管理しています。ARPテーブルはL2の宛先MAC解決を担い、エントリ数(ARP_TABLE_SIZE)を環境に合わせて調整します。
メモリプール(MEMP/PBUF_POOL)の設定
lwIPは構成により、独自のメモリ管理機能である固定サイズのメモリプール(MEMP、PBUF_POOL)を利用できます。lwipopts.hでMEMP_NUM_TCP_PCB、MEMP_NUM_PBUF、PBUF_POOL_SIZEを製品要件に応じて設定してください。プールが枯渇すると受信パケットの破棄や新規接続の失敗につながるため、量産前にピーク負荷で評価しておくことが重要です。
3つのAPIと実装パターン
lwIPはRaw、Netconn、Socketの3種類のAPIを提供します。下層ほど高性能・軽量、上層ほど実装が容易という特徴があり、要求リアルタイム性と開発工数に応じて選びます。ここではマイコンメーカが提供するGUI設定ツールを例に、これらのAPIを利用するための基本的な設定方法を説明します。
Raw API(コールバック型)の特徴と用途
Raw APIはlwIPのネイティブAPIで、通信イベントをコールバック関数で処理します。特にNO_SYS環境での運用に適しており、lwIPのなかでは最大限の性能と最小限のフットプリントを実現できます。一方で状態管理をアプリケーション側でおこなう必要があり、複雑なアプリケーションでは可読性が落ちます。そのため、主に性能・メモリ効率が求められる組み込みシステムなどで多く使われています。
Netconn APIとSocket API(RTOS連携)
Netconn APIはRTOS環境で利用する順次(sequential)APIです。netconn_write()やnetconn_recv()などのブロッキング型インターフェースを提供します。Socket APIはその上にBSDソケット互換層を実装しており、send()やrecv()などで既存資産を移植しやすいのが利点です。両APIともRTOSのスレッドやセマフォ、メールボックスなどを利用するため、Raw APIと比べてメモリ使用量や処理時間が増加します。
コード生成ツール連携の典型構成
マイコンメーカが提供するコード生成ツールでは、Ethernet PHY(Physical Layer Transceiver:物理層トランシーバ)を設定できます。ここでlwIPミドルウェアを有効化すると、lwipopts.hがプロジェクト内に生成されます。生成される設定は、RTOSの有無や利用するAPI(Raw/Netconn/Socket)に合わせたものになります。
マイコンメーカが公開するアプリケーションノートには、HTTPサーバ、TFTPサーバ、TCP echo、UDP echoなどのサンプルが掲載されている例があります。スタンドアロン構成とRTOS構成の双方で示されており、初回実装時の参考になるでしょう。
パフォーマンスチューニングとデバッグ
lwIPのデフォルト設定は汎用性を重視しているため、産業用途では要件に応じたチューニングが重要です。ここでは、性能改善に効果の大きい設定項目とデバッグ機能について説明します。
TCP_WND・MSSとコピー削減によるスループット改善
TCP_WND(受信ウィンドウサイズ)は受信バッファ容量を決めます。lwIP本家のopt.hにおける既定値は、TCP_MSS=536 バイト、TCP_WND=4×TCP_MSS=2144 バイト(約2.1 kB)です。ただしこの値は、マイコンメーカが提供する移植層や、生成されたlwipopts.hによって変更されることがあります。
TCP_MSSはMaximum Segment Size(最大セグメントサイズ)の略で、1回のセグメントで運べるデータ量を表します。MTUはMaximum Transmission Unit(最大転送単位)を指します。Ethernet MTUが1500 バイトであれば、TCP_MSSは1460 バイトが一般的な値です。これはMTUからIPヘッダとTCPヘッダ分の40 バイトを引いた値にあたります。
産業用の高スループットを狙う場合は、TCP_MSSを1460 バイトへ設定します。TCP_WNDも帯域遅延積(BDP)を考慮して十分大きく取ります。16 kB以上とする構成も実務で採用されています。
PBUF_REFやPBUF_ROMを活用すると、送信時のコピーをさらに削減できます。ドライバやDMAがscatter-gatherに対応していれば、memcpyを減らしてCPU負荷を低減できます。
なおLWIP_NETIF_TX_SINGLE_PBUFはscatter-gather非対応のMACとの互換性のための設定で、有効にすると逆に送信前のmemcpyが発生しうる点に注意が必要です。ただしmemcpyの削減率の公式ベンチマークは公開されておらず、実装後はターゲット環境での計測が前提です。
lwIPの統計機能とログでのトラブルシューティング
lwIPはLWIP_STATSマクロでパケット数、エラー数、プール使用量などの統計をRAMに蓄積し、stats_display()で出力できます。デバッグログはLWIP_DEBUGで有効化し、PBUF_DEBUG・TCP_DEBUG・IP_DEBUGなどレイヤ単位で詳細度を設定します。これらのデバッグ機能はデフォルトでは無効なため、必要に応じて有効化し、開発時のみ統計とログを併用すると、接続不良やドロップの原因切り分けを効率的に進められるでしょう。
lwIPの設計思想を理解し、pbufやメモリプール、TCP_WNDを適切に調整することが、安定した稼働につながります。また、要件に応じたAPIの選択やログ機能を活用したデバッグをおこなうことにより、組み込みTCP/IPスタックを効率よく構築できるでしょう。
同カテゴリ「通信と外部インターフェース」のMQTT入門や産業用Ethernetの整理と組み合わせて読むと、上位プロトコル層から物理層までの全体像が見通せます。


