【復旧】TCP/IP プロトコルスタック自作入門(microps) 実施録

前置き

この記事は旧サイトの2023.9.16投稿の記事内容のリポストです。

はじまり

Twitterでこんなツイートが流れてきました。

資料とコードをみてみると、 C言語で簡易的な TCP/IP プロトコルスタックを自作してみよう!という内容でした。TCP/IP って普段何気なく使ってはいるもののふわっとした知識しかなかったのでこれを機にちょっとやってみようかな、と。以降では、実施してみた感想と、そのあとに microps を VSCode DevContainer で動作するために行った環境構築、実施中に出会った環境構築不備?のエラー(※暫定対処しかできていない…)をまとめておきます。

資料

Klab Expert Camp (Google Drive)
microps (Github)

感想(完走)

ネットワークのデバイスの管理からはじまり、Ether, ip, udp, tcp, arp と様々なプロトコルの実装で、普段何気なく使っている通信がこんな面倒なことをしてるんだなと改めて感じることが出来ました。特に最後の方のTCPは3wayハンドシェイクなど、ふわっと知ってはいましたが実際やると難しすぎて・・・。(シーケンス番号やら送信して受信しての流れが追い切れない(汗)。

TCP/IPプロトコル入門からは外れてしまうところですが、いわゆる連結リストやメモリの動的確保・解放、関数ポインタ、void * を用いた共通化など、なるほど実際こうやって使うんだというようなところも満載で、C言語の理解を深めるのにも良い教材と感じました。

正直理解を諦めて先に進んでしまったようなとこだと、シグナルやバリア同期など並行プログラミングとかLinuxのシグナルとかを知らないので厳しかった。またmicrps では util.c などに色々な便利関数群が作ってあって簡単にキューの操作やバイトオーダーの変換ができるようになっていました。ここもとりあえず util 頼りでした。

あとは本記事の最後に記載していますが、何故かVSCode で InteliSence がうまく効かずにとりあえず対処で済ませたりしたとこがあるのでそのあたりの原因も確認したいですね。

本来は5日間でこれをやりきっている方たちがいるようなのですが、1か月くらいかかりました。おともには前に興味がでて買ったはいいものの数ページ読んで積んでいた「これ1冊で丸わかり 完全図解ネットワークプロトコル入門」を横に携えてのぞみました。ただ踏み込んだとこだとやっぱり足りなかったですね。UDPのとことか。

総じていい内容でした。

環境構築(Day1以前)

最終的な環境はこちら
https://github.com/AlaAlba/microps/tree/work/.devcontainer

以下の要件に沿って環境構築しました。

– Ubuntu 20.04 を推奨
– 実機or仮想環境どちらでもOK(WindowsはWSL2で動作確認済)
– Dockerで構築する場合には –privileged または –cap-add=NET_ADMIN が必要
– 必要パッケージ(Ubuntuの場合)
– build-essential
– git
– iproute2
– iputils-ping
– netcat-openbsd

使ったことなかったのですが、これを機会にということで、VSCode Devcontainer を利用しています。
* Windows10
* Docker
* VSCode DevContainer

microps を clone したフォルダに、 .devcontainer フォルダを作成し、配下に devcontaienr.json , docker-compose.yml , Dockerfile を作成。

(参考)
Get started with development Containers in Visual Studio Code
Visual Studio Codeで使えるリモート環境のdevcontainerが意外と便利そうだったのでまとめ
Docker Compose な開発環境にちょい足し3分で作るVSCode devcontainer
VSCode Devcontainer 放浪記
Add non-root user to a container
【Rootless】VSCodeのDocker環境をRoot以外のユーザで実行する | ぺんぎんや
How to Set Docker Environment Variables {ARG and ENV}

注意点

docker-compose.yml の devices

Tutorial で sudo ip tuntap add mode tap user $USER name tap0 というコマンドが出てきますが、本箇所を追加しないと、 open: No such file or directory というエラーが表示されました。Docker Compose な開発環境にちょい足し3分で作るVSCode devcontainernetworking – ip tuntap add gives “open: No such file or directory” – Ask Ubuntu によると、Docker は tun/tap デバイスにマッピングしないため、手動で行う必要があるそうです。

–device /dev/net/tun:/dev/net/tun

Dockerfile Userの設定

Tutorial で $USER と指定している箇所があるが、devcontainer はデフォルトでは root ユーザーとなるらしく、また $USER は環境変数に定義されていません。そのため、# Create the user 以降の箇所でユーザーを dev-user として作成し、最後に ENV USER=$USERNAME で環境変数を設定しています。

作業録

P22~

以下の手順でコミットが見つかりませんでした。

git checkout bdbf73f -b work

原因は、fork したときには main ブランチしかとってきていなかったことです。以下の手順で、 bdbf73f のコミットがされている別ブランチを取得する必要がありました。

# オリジナルのリポジトリを upstrem としてリモートリポジトリに追加
git remote add upstream https://github.com/pandax381/microps.git

# フェッチ
git fetch upstream

# ブランチをチェックすると remotes/upstream/* が追加されている
git checkout -a
# * master
# remotes/origin/HEAD -> origin/master
#  remotes/origin/master
#  remotes/upstream/book1.0
#  remotes/upstream/kec3
#  remotes/upstream/kec5
#  remotes/upstream/master
#  remotes/upstream/rebuild

VSCode で net.c によくわからないエラー

STEP1 では net.c を新規追加するのですが、1行目のインクルードで、「コマンドラインエラー C/C++(1027) 指定されている言語モードは互換性がありません」というエラーが表示されていました。

よくわからず無視して進めていたんですが、このせいでコードの補完が全く効いていないという問題が発生してしまったため、解決方法を記載しておきます。

どうやら今開発環境は VSCode を利用しているのですが、 InteliSense が Makefile Tools によって効いているのが原因のようでした。

拡張機能は、ファイル内に Makefile が見つかるとアクティブになります${workspaceFolder}

よって、P41 の Makefile の修正を行えば解決します。今後の作業では先に Makefile を修正することを心がければよさそうです。

Makefile 使ったことないのでわかりませんでしたが、ここでビルド対象に含めないとソースファイルとして認識してくれないようです。

暫定対処しちゃったトコ(VSCodeの設定がオカシイ?)

microps を ドキュメント通りに進めるにあたり何故か make はできるんですが、VSCode上は Intelisence でエラー表記になるものがいくつか・・・。VSCodeのC言語用の設定、もしくはMakeFile用の設定がうまくいってない気がしますね・・・。とりあえずは以下の通りの定義追加などを行うとエラーもなくなり、補完も効くようになりました。しかし原因ははっきりしていません。

STEP2 : 識別子 “pthread_barrier_t” が定義されていませんC/C++(20)

#define _XOPEN_SOURCE 600 /* Or higher */ の定義をインクルード前で定義するとうまくいきましたが、オリジナルの microps ではそんな定義はされていないので、なぜ intelisence がオカシイのかがわかりません・・・。なお、VSCode上、問題として表示されているが、このままでも make は可能でした。
c – unknown type name “pthread_barrier_t” – Stack Overflow

STEP12 : ifreq でエラー

こっちは Intelisence で使用する言語標準のバージョンを変更すれば解消しました。
デフォルトではC**になっているので gnu23 などに変更。

STEP14, 16 : timercmp や timersub がintelisenceが効かない

sys/time.h みるとコンパイルでオフになってたので __USE_MISC を追加したら一応効くようになりました。謎です。

#ifndef __USE_MISC
#define __USE_MISC /* TODO: 暫定 timercmp用 intelisenceが効かない */
#endif

#include <sys/time.h>

STEP26 timercmp

これも同じように VSCode の Intelisence がエラー表示に。make はそのままでも通りました。暫定対処としては STEP14, 16 と同じように上記のインクルードと定義を追加すればエラー表記も取れました。ただこちらに関しては、 tcp.c はそもそも元々は sys/time.h すらインクルードされておらず、なぜこれで make 通るんだろう?ってなりました。

投稿日:

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です