[インデックス 18380] ファイルの概要
このコミットは、Go言語のネットワークパッケージにおけるPlan 9オペレーティングシステム上でのIPv4スタックの検出方法を改善するものです。具体的には、IPv4スタックの存在を確認するためのプローブ処理が、より堅牢な方法に変更されています。
コミット
commit 1e89eb2c317b20dbe1bb8650b9c5eeae37b26e72
Author: Jeff Sickel <jas@corpus-callosum.com>
Date: Thu Jan 30 09:49:32 2014 +0900
net: net: better IPv4 stack probe on Plan 9
LGTM=mischief, mikioh.mikioh
R=golang-codereviews, 0intro, mischief, mikioh.mikioh
CC=golang-codereviews
https://golang.org/cl/53960044
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/1e89eb2c317b20dbe1bb8650b9c5eeae37b26e72
元コミット内容
このコミットは、Go言語のnet
パッケージ内のsrc/pkg/net/ipsock_plan9.go
ファイルに対して行われた変更です。主な変更点は以下の通りです。
probe
関数のシグネチャからbufSize
引数が削除されました。- 変更前:
func probe(filename, query string, bufSize int) bool
- 変更後:
func probe(filename, query string) bool
- 変更前:
probeIPv4Stack
関数内のIPv4スタック検出ロジックが変更されました。- 変更前は、
netdir+"/ipselftab"
に対して"127.0.0.1"
をクエリとして使用していました。 - 変更後は、
netdir+"/iproute"
に対して"4i"
をクエリとして使用するようになりました。
- 変更前は、
probeIPv6Stack
関数内のIPv6スタック検出およびIPv4-mapping検出ロジックが変更されました。- IPv6スタック検出の
probe
呼び出しからbufSize
引数が削除されました。 - IPv4-mapping検出のクエリが
"4b"
から"4i"
に変更されました。
- IPv6スタック検出の
変更の背景
この変更の背景には、Plan 9オペレーティングシステムにおけるIPv4スタックの検出の信頼性向上が挙げられます。以前の検出方法では、ipselftab
ファイルに127.0.0.1
が存在するかどうかを確認していましたが、これは必ずしもIPv4スタックが完全に機能していることを保証するものではありませんでした。
Plan 9のネットワークスタックは、ファイルシステムを通じてネットワークデバイスや設定を操作するという独特の設計思想を持っています。ipselftab
は自己アドレスを管理するファイルですが、より広範なルーティング情報を提供するiproute
ファイルの方が、システムがIPv4通信を適切に処理できるかどうかを判断する上で、より正確な指標となります。
特に、"4i"
というクエリは、IPv4インターフェースの存在を確認するためのものであり、単にループバックアドレスが存在するかどうかをチェックするよりも、システムがIPv4ネットワークに接続可能であるか、またはIPv4パケットをルーティングできるかという、より実用的な意味でのIPv4スタックの健全性を判断するのに適しています。
この改善により、GoプログラムがPlan 9上でネットワーク機能を初期化する際に、IPv4スタックの有無をより正確に判断できるようになり、結果としてネットワーク関連の挙動が安定することが期待されます。
前提知識の解説
このコミットを理解するためには、以下のPlan 9オペレーティングシステムのネットワークに関する概念と、Go言語のネットワークパッケージの基本的な構造について理解しておく必要があります。
Plan 9のファイルシステムベースのネットワーク
Plan 9は、"Everything is a file"(すべてはファイルである)という哲学を徹底しており、ネットワークインターフェースやプロトコルスタックもファイルシステムを通じてアクセス・制御されます。
/net
ディレクトリ: Plan 9におけるネットワーク関連のファイルシステムツリーのルートです。このディレクトリ以下に、ネットワークインターフェース、プロトコルスタック、ルーティングテーブルなどがファイルとして表現されます。ipselftab
:/net/ipselftab
は、システムの自己アドレス(ローカルに設定されたIPアドレス)をリストするファイルです。これにはループバックアドレス(127.0.0.1
や::1
)などが含まれます。iproute
:/net/iproute
は、IPルーティングテーブルを管理するファイルです。このファイルにクエリを書き込むことで、特定のルーティング情報を取得したり、ルーティングエントリを追加・削除したりできます。ctl
ファイル: 多くのネットワークデバイスやプロトコルスタックのディレクトリにはctl
(control)ファイルが存在します。このファイルにコマンドを書き込むことで、そのデバイスやスタックの動作を制御できます。data
ファイル: ネットワークデバイスのdata
ファイルは、パケットの送受信に使用されます。
iproute
ファイルへのクエリ
iproute
ファイルは、特定の情報を取得するために特殊なクエリ文字列を受け付けます。
4i
: IPv4インターフェースに関する情報を要求するクエリです。システムにIPv4インターフェースが設定され、アクティブである場合に、関連情報が返されます。これは、システムがIPv4通信を行う能力があるかどうかの強力な指標となります。6i
: IPv6インターフェースに関する情報を要求するクエリです。4b
: IPv4ブロードキャストアドレスに関する情報を要求するクエリです。このクエリは、IPv4スタックの存在を間接的に示すものですが、4i
ほど直接的ではありません。
Go言語のnet
パッケージ
Go言語のnet
パッケージは、ネットワークI/Oプリミティブを提供します。これにはTCP/IP、UDP、ドメインネーム解決、Unixドメインソケットなどが含まれます。オペレーティングシステム固有のネットワーク機能へのアクセスは、内部的にOS固有のコード(例: ipsock_plan9.go
)を通じて抽象化されています。
probe
関数: このコミットで変更されているprobe
関数は、特定のファイル(例:/net/ipselftab
や/net/iproute
)に対してクエリを実行し、その結果に基づいてネットワークスタックの機能(例: IPv4やIPv6が利用可能か)を検出するためのユーティリティ関数です。
技術的詳細
このコミットの技術的な核心は、Plan 9におけるIPv4スタックの「プローブ(検出)」方法の変更にあります。
probe
関数の変更
probe
関数は、指定されたfilename
(例: /net/ipselftab
や/net/iproute
)を開き、query
文字列を書き込み、その結果を読み取ることで、特定のネットワーク機能の有無を判断します。
変更前は、probe
関数はbufSize
という引数を持っていました。これは、クエリの結果を読み取るためのバッファサイズを指定するものと考えられます。しかし、このコミットではbufSize
が削除されています。これは、以下のいずれかの理由によるものと推測されます。
- 不要な引数:
bufSize
が常に固定値(例: 128)で呼び出されており、関数のシグネチャから削除しても問題ない、あるいは内部で適切なバッファサイズが自動的に決定されるようになった。 - APIの簡素化:
probe
関数の利用側がバッファサイズを意識する必要がなくなり、APIがよりシンプルになった。 - Plan 9のファイルI/Oの特性: Plan 9のファイルシステムI/Oは、読み取り時に指定されたバッファサイズよりも少ないデータしか利用できない場合でも、利用可能なデータを返すため、厳密なバッファサイズ指定が不要になった可能性。
IPv4スタック検出の改善
最も重要な変更は、probeIPv4Stack
関数におけるIPv4スタックの検出方法です。
- 変更前:
probe(netdir+"/ipselftab", "127.0.0.1", 128)
- これは
/net/ipselftab
ファイルに"127.0.0.1"
を書き込み、その結果を読み取ることで、ループバックアドレスが自己アドレスとして設定されているかを確認していました。しかし、ループバックアドレスの存在は、必ずしもシステムが外部のIPv4ネットワークと通信できることを意味しません。例えば、IPv4ルーティングが設定されていない場合でも、ループバックアドレスは存在する可能性があります。
- これは
- 変更後:
probe(netdir+"/iproute", "4i")
- これは
/net/iproute
ファイルに"4i"
(IPv4インターフェース)を書き込み、その結果を読み取ります。/net/iproute
に"4i"
をクエリすると、システムにアクティブなIPv4インターフェースが存在する場合に、その情報が返されます。これは、システムがIPv4パケットを送受信できる能力があることを直接的に示唆するため、より堅牢なIPv4スタックの検出方法と言えます。
- これは
IPv6スタック検出におけるIPv4-mappingの変更
probeIPv6Stack
関数では、IPv6スタックの存在と、IPv6スタックがIPv4-mapped IPv6アドレスをサポートしているかどうかの両方を検出します。
- IPv6スタック検出:
r := probe(netdir+"/iproute", "6i")
- これはIPv6インターフェースの存在を確認するもので、変更はありませんが、
probe
関数のシグネチャ変更に伴いbufSize
引数が削除されています。
- これはIPv6インターフェースの存在を確認するもので、変更はありませんが、
- IPv4-mapping検出:
v = probe(netdir+"/iproute", "4i")
- 変更前は
"4b"
(IPv4ブロードキャストアドレス)をクエリしていましたが、変更後は"4i"
(IPv4インターフェース)をクエリするようになりました。これは、IPv4-mappedアドレスのサポートを判断する上で、ブロードキャストアドレスの存在よりもIPv4インターフェースの存在の方がより適切な指標であるという判断に基づいていると考えられます。IPv4-mappedアドレスは、IPv6ソケット上でIPv4通信を行うためのメカニズムであり、その機能が利用可能であるかを判断するには、基盤となるIPv4インターフェースの健全性を確認するのが自然です。
- 変更前は
これらの変更により、Goのnet
パッケージはPlan 9環境において、より正確かつ信頼性の高い方法でネットワークスタックの機能を判断できるようになりました。
コアとなるコードの変更箇所
変更はsrc/pkg/net/ipsock_plan9.go
ファイルに集中しています。
--- a/src/pkg/net/ipsock_plan9.go
+++ b/src/pkg/net/ipsock_plan9.go
@@ -12,7 +12,7 @@ import (
"syscall"
)
-func probe(filename, query string, bufSize int) bool {
+func probe(filename, query string) bool {
var file *file
var err error
if file, err = open(filename); err != nil {
@@ -37,7 +37,7 @@ func probe(filename, query string, bufSize int) bool {
}
func probeIPv4Stack() bool {
- return probe(netdir+"/ipselftab", "127.0.0.1", 128)
+ return probe(netdir+"/iproute", "4i")
}
// probeIPv6Stack returns two boolean values. If the first boolean
@@ -45,10 +45,10 @@ func probeIPv4Stack() bool {
// second boolean value is true, kernel supports IPv6 IPv4-mapping.
func probeIPv6Stack() (supportsIPv6, supportsIPv4map bool) {
// Plan 9 uses IPv6 natively, see ip(3).
- r := probe(netdir+"/iproute", "6i", 128)
+ r := probe(netdir+"/iproute", "6i")
v := false
if r {
- v = probe(netdir+"/iproute", "4b", 128)
+ v = probe(netdir+"/iproute", "4i")
}
return r, v
}
コアとなるコードの解説
probe
関数のシグネチャ変更
-func probe(filename, query string, bufSize int) bool {
+func probe(filename, query string) bool {
probe
関数からbufSize
引数が削除されました。これにより、この関数を呼び出す側は、結果を読み取るためのバッファサイズを意識する必要がなくなりました。これは、関数の内部実装がバッファサイズを適切に管理するか、あるいはPlan 9のファイルI/Oの特性上、この引数が不要になったことを示唆しています。
probeIPv4Stack
関数の変更
- return probe(netdir+"/ipselftab", "127.0.0.1", 128)
+ return probe(netdir+"/iproute", "4i")
probeIPv4Stack
関数は、システムがIPv4スタックをサポートしているかどうかを検出します。
変更前は、/net/ipselftab
ファイルにループバックアドレス"127.0.0.1"
をクエリしていました。これは、システムにIPv4の自己アドレスが設定されているかを確認するものでした。
変更後は、/net/iproute
ファイルに"4i"
(IPv4インターフェース)をクエリするようになりました。これは、システムにアクティブなIPv4インターフェースが存在するかどうかを直接的に確認するもので、より正確なIPv4スタックの検出を可能にします。
probeIPv6Stack
関数の変更
- r := probe(netdir+"/iproute", "6i", 128)
+ r := probe(netdir+"/iproute", "6i")
IPv6スタックの検出部分では、probe
関数のシグネチャ変更に伴い、bufSize
引数(128
)が削除されました。クエリ自体は"6i"
(IPv6インターフェース)のままで、IPv6スタックの存在を確認します。
- v = probe(netdir+"/iproute", "4b", 128)
+ v = probe(netdir+"/iproute", "4i")
IPv4-mappingのサポートを検出する部分では、クエリが"4b"
(IPv4ブロードキャストアドレス)から"4i"
(IPv4インターフェース)に変更されました。これにより、IPv4-mappedアドレスのサポートを判断する際に、より関連性の高いIPv4インターフェースの存在がチェックされるようになりました。
これらの変更は、Plan 9環境におけるGoのネットワーク機能の堅牢性と正確性を向上させるための重要な改善です。
関連リンク
- Go言語の
net
パッケージに関する公式ドキュメント: https://pkg.go.dev/net - Plan 9 from Bell Labs: https://9p.io/plan9/
- Plan 9のネットワークに関するドキュメント(
ip(3)
など): Plan 9のインストールに含まれるマニュアルページを参照するか、オンラインのPlan 9マニュアルを参照してください。例: http://man.cat-v.org/plan_9/3/ip
参考にした情報源リンク
- Go言語のコミット履歴とコードレビューシステム (Gerrit): https://go.googlesource.com/go および https://go-review.googlesource.com/
- Plan 9のネットワークに関する一般的な情報源(Stack Overflow, フォーラムなど)
- Plan 9のソースコードやマニュアルページ(特に
/net
ディレクトリの構造やip
コマンド、iproute
ファイルに関する記述) - このコミットのGerritレビューページ: https://golang.org/cl/53960044 (コミットメッセージに記載)
- Plan 9の
iproute
ファイルに関する情報: https://9p.io/magic/man2html/3/ip (Plan 9のip(3)
マニュアルページ) - Plan 9の
ipselftab
に関する情報: https://9p.io/magic/man2html/3/ipselftab (Plan 9のipselftab(3)
マニュアルページ) - Plan 9のネットワークスタックの設計思想に関する一般的な記事や論文。