🎃

LightWeightIP(LwIP)を紐解く(UDP/TCP用の構造体)

に公開

下記の記事の続きになります。

https://zenn.dev/toms_emb_fv/articles/2fc8bf84a619eb

前回の記事ではLightWieghtIPの概要と構造を示したので、
この記事では、LightWeightIPのデータ構造にフォーカスしてまとめています。

LightWeightIPのデータ構造

LightWeightIPのデータ構造を下記に示します。

データ構造.png

UDPの通信を「udp_pcb」という構造体で、TCPの通信を「tcp_pcb」というデータの塊を使って制御・管理します。
加えて、「udp_pcb」と「tcp_pcb」が実際に通信を行う際には、Ethernet,WLAN,BLEのドライバに関するデータの塊「netif」を使って通信を行います。

IPアドレスやポート番号、データの送受信を行うバッファなどの情報は「udp_pcb」と「tcp_pcb」が持っており、物理層(Ethernet, WLAN, BLE等)のデバイスドライバに関する情報は「netif」が持っていると考えてください。

udp_pcb(UDPの管理用データ)

udp_pcbの定義はリポジトリのこちらにあります。

構造体にはたくさんパラメータが定義されていますが、LwIPを使用するうえでは下記のようなイメージで考えればよいかと思います。主にUDPを通信を行うための送信元と受信先の情報(IPアドレスとポート)を保持することになります。

udp_pcb.png

また、上記の情報の通り、udp_pcbは送信元と受信先の組み合わせ一つにつき、一つ存在します。
よって、送信先が変わる場合や、別ポートでの通信時は別のudp_pcbを使用します。下記の図のようなイメージです。

udp_pcb組み合わせ.drawio.png

上記において、local IPアドレスとlocalポートはudp_pcbを保持している側のIPアドレス、ポート番号を指しており、remote IPアドレスとremoteポートは通信先のIPアドレスとポート委番号を指しています。

tcp_pcb(TCPの管理用データ)

tcp_pcbの定義はリポジトリのこちらにあります。

こちらの構造体にもたくさんのパラメータが定義されていますが、LwIPを使用するうえでは下記のようなイメージで問題ないかと思います。

tcp_pcb.png

上記にある「送信バッファ」というのは送信に行うデータをリスト構造で保持するものです。

tcp_pcbの送信バッファ

TCPはUDPと違ってコネクションを確立したり、再送制御や順序制御などを行う必要があるので、送信バッファは下記のようにリスト構造の送信バッファリスト「unacked」と「unsent」を持っています。

tcp_pcbバッファ構造.png

上記の図にも示した通り、「unsent」はまだ送信を行っていないバッファをリストで持ち、「unacked」はすでに送信済みでackを待っているバッファをリストで持っています。
「unsent」は、輻輳制御などの影響ですぐにデータ送信できないことがあるので、リスト構造にしてデータを保持しています。
また、「unacked」は、ACKが返ってこない場合の再送制御を行うために、リスト構造にしてデータを保持しています。

tcp_pcbの受信バッファ

送信バッファがリスト構造になっているのに対し、基本的に受信バッファはリスト構造で保持していません。
データが受信された際、その都度受信したデータの処理を行います。

netif(デバイスドライバの管理用データ)

「netif」はデバイスドライバを管理するためのデータ構造です。ソースコード上ではこちらで定義されています。
下記の図のように、通信処理を行うネットワークインターフェース一つにつき、一つ存在します。

netif構造体.png

また、「netif」に格納されているのは下記の図に示したようなデータです。

netif詳細.png

通信に必要なIPアドレス関連の情報と、データを送受信する際に呼び出される関数、ネットワークのステータスが変わった時にそれをデバイスドライバやネットワークインターフェースにも反映させるためのコールバック関数など、デバイスドライバを制御・管理するための情報がまとめられています。
こちらも「tcp_pcb」や「udp_pcb」と同様パラメータは多いですが、よく使うのは上記の図に示した情報になるかと思います。

参考資料

Discussion