下記の記事の続きになります。
前回の記事ではLightWieghtIPの概要と構造を示したので、
この記事では、LightWeightIPのデータ構造にフォーカスしてまとめています。
LightWeightIPのデータ構造
LightWeightIPのデータ構造を下記に示します。
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は送信元と受信先の組み合わせ一つにつき、一つ存在します。
よって、送信先が変わる場合や、別ポートでの通信時は別のudp_pcbを使用します。下記の図のようなイメージです。
上記において、local IPアドレスとlocalポートはudp_pcbを保持している側のIPアドレス、ポート番号を指しており、remote IPアドレスとremoteポートは通信先のIPアドレスとポート委番号を指しています。
tcp_pcb(TCPの管理用データ)
tcp_pcbの定義はリポジトリのこちらにあります。
こちらの構造体にもたくさんのパラメータが定義されていますが、LwIPを使用するうえでは下記のようなイメージで問題ないかと思います。
上記にある「送信バッファ」というのは送信に行うデータをリスト構造で保持するものです。
tcp_pcbの送信バッファ
TCPはUDPと違ってコネクションを確立したり、再送制御や順序制御などを行う必要があるので、送信バッファは下記のようにリスト構造の送信バッファリスト「unacked」と「unsent」を持っています。
上記の図にも示した通り、「unsent」はまだ送信を行っていないバッファをリストで持ち、「unacked」はすでに送信済みでackを待っているバッファをリストで持っています。
「unsent」は、輻輳制御などの影響ですぐにデータ送信できないことがあるので、リスト構造にしてデータを保持しています。
また、「unacked」は、ACKが返ってこない場合の再送制御を行うために、リスト構造にしてデータを保持しています。
tcp_pcbの受信バッファ
送信バッファがリスト構造になっているのに対し、基本的に受信バッファはリスト構造で保持していません。
データが受信された際、その都度受信したデータの処理を行います。
netif(デバイスドライバの管理用データ)
「netif」はデバイスドライバを管理するためのデータ構造です。ソースコード上ではこちらで定義されています。
下記の図のように、通信処理を行うネットワークインターフェース一つにつき、一つ存在します。
また、「netif」に格納されているのは下記の図に示したようなデータです。
通信に必要なIPアドレス関連の情報と、データを送受信する際に呼び出される関数、ネットワークのステータスが変わった時にそれをデバイスドライバやネットワークインターフェースにも反映させるためのコールバック関数など、デバイスドライバを制御・管理するための情報がまとめられています。
こちらも「tcp_pcb」や「udp_pcb」と同様パラメータは多いですが、よく使うのは上記の図に示した情報になるかと思います。
参考資料
- Githubリポジトリ
https://github.com/lwip-devs/lwip - LwIP初版設計書
https://www.artila.com/download/RIO/RIO-2010PG/lwip.pdf