ネットワーク

ネットワークスタック(Ethernet・ARP・IPv4・ICMP・UDP・TCP(クライアントとサーバ)・DHCP・DNS)はアーキ非依存で、ゼロから作ったものです。同じソースが、5 つのターゲットすべてで動きます。

1 つのスタック、複数の NIC

ターゲットNIC
x86_64e1000
riscv64 / aarch64virtio-net
RV32(Pico 2 W)CYW43439 Wi-Fi
ARMv6-M(Pico W)CYW43439 Wi-Fi

スタックは、カードを名指ししません。使うのは、HAL が渡すものだけ——フレームを送る、取りに行く、リングへ返す。それに、ドライバが公開する MAC アドレスと受信待ちスロット。これらを実装した backend なら、どれでも差し込めます。同じスタックが、有線 Ethernet でも無線でも動きます。

Wi-Fi ドライバと、その依存

CYW43439 のドライバは Zig で、ベンダ SDK はコンパイルに入りません。gSPI のバスプログラムと、バスおよび join のコマンド列は、pico-sdk と cyw43-driver のソースを基にしています。

そして無線チップ自体はベンダのファームウェアで動きます。ファームウェア(約 224 KB)・NVRAM・CLM という 3 つのバイナリブロブを flash に書き込み、起動時にチップへストリームします。これは部品の性質であり、どの CYW43 ドライバも同じ 3 つを積みます。

カーネルが NIC を所有し、スクリプトが指揮する

層の分け方は、ほかのすべてと同じ二層です。カーネルがネットワークカードを所有し、スクリプトは FFI を通して指揮します。

riscv64 では、この境界に双方向のバッファ ABIが通ります。U-mode のアクターがポインタと長さを渡し、カーネルがページテーブルを歩いてそのポインタの全ページがユーザマップされていることを確認してから、読みまたは書きます。だからスクリプトは、境界を越えて整数だけでなく任意のバイト列(カスタムメッセージ、HTTP 応答)を送受信します。

aarch64 は同じ機構をファイル I/O にのみ使っています。TCP の FFI はありません。

**x86 と MCU の FFI 境界は、現状すべて整数です。**バッファ ABI はまだ配線していません。

割り込み駆動の受信(x86 のみ)

x86 では、受信をポーリングの刻みでなく割り込みで処理します。e1000 のレガシ INTx を割り込みコントローラ経由でベクタにルートし、割り込みサービスルーチンが線を de-assert し、割り込み終了を送り、ネットワークタスクを起こします。フレームは届いたときに処理されます。

**他のターゲットではポーリングです。**virtio-net のドライバには割り込みフックがありますが、割り込みコントローラからそこへ配線されていません。CYW43439 に至っては、受信割り込みが CPU に配線されていません(チップの制約)。フレームは、ドライバが要求したときにバスから出てきます。

TCP

クライアント(能動オープン)とサーバ(受動オープン。OS が小さな HTTP ページを配信する)。3-way ハンドシェイク、データ転送、FIN クローズ。シーケンス番号と確認応答番号は安全に wrap します。

同時接続3 本。各接続が端点・シーケンス状態・再送キュー・送信キュー・ウィンドウを自分で持つ
接続の対応づけ4-tuple 全体(RFC 793)。着信 SYN は空きスロットに入る
再送未確認セグメントを保持して再送。RTO 400 ms、3 s を上限に倍々、以降は諦める
高速再送重複 ACK 3 回で、失われたセグメントを即座に送り直し、ウィンドウを半分にする
輻輳制御接続毎の cwndssthresh。スロースタート中は RTT あたり 1 セグメント、抜けたらウィンドウあたり 1 セグメント。タイムアウトで閾値を半分にしてスロースタートへ戻る
フロー制御データはキューに積み、MSS に分割し、min(輻輳ウィンドウ, 相手の広告ウィンドウ) で送出を律速する
SACK双方向でネゴシエート。順序外の到着を捨てずに保持し、ACK で何が届いたかを名指しし、相手からの SACK で既に届いている分の再送を止める
ウィンドウスケーリング提示する(相手は 64 KiB を超える広告ができる)。こちら側のシフトは意図的に 0——大きな受信バッファを持たないため
アイドルタイムアウト相手から 20 秒

チェックサム

送信受信
TCP擬似ヘッダ込みで計算検証し、合わないセグメントは破棄
UDP擬似ヘッダ込みで計算送信側が付けていれば検証(0 は省略の意味。IPv4 はそれを許す)
IPv4 ヘッダ・ICMP計算検証

IPv4 のバージョン・ヘッダ長・全長・宛先 IP と、UDP の長さ境界も検証します。リリースビルドに境界チェックは無いため、検証を素通りした不正パケットは範囲外を読みます。不正なトラフィックは入口で捨てられます。

ワイヤ越しの分散

このスタックの上に、アクター層の位置透過が乗ります。リモートのアクターメッセージは、UDP ペイロードとして運ばれ、ローカルのメールボックスに届きます。

**実機で。**Pico 2 W(RP2350、MMU 無し)では、非特権・PMP 隔離のアクターの隣でこのスタックが特権タスクとして走ります。Wi-Fi に join し、DHCP で実 IP を取り、DNS を解決し、そのアクターのメッセージを実 LAN 越しに x86 ノードへ運びます。すべて 1 つのイメージです。

このスタックは、外へ送るだけでなく、**宛先にもなります。**自分のアドレスへの ARP に応え、オフリンクのトラフィックはゲートウェイへ送ります。だから、相手の側から会話を始められるし、別サブネットの相手にも届きます。

**オンリンクかオフリンクかは、ネットマスクとのビット比較で判定します。**マスクは既定で /24、サーバが渡せば DHCP のリースのマスクに置き換わるので、/24 でないサブネットも正しく経路制御されます。

詳細は アクター のページにあります。