Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 15399] ファイルの概要

このコミットは、Go言語の syscall パッケージにおいて、FreeBSDシステムコールに対する if_announce イベントのサポートを追加するものです。これにより、GoプログラムがFreeBSD上でネットワークインターフェースの到着(IFAN_ARRIVAL)や離脱(IFAN_DEPARTURE)といったイベントを検知し、処理できるようになります。

コミット

commit b1d51c63d6626e0e78f5ea0e1f4b6eda4af045e0
Author: Mikio Hara <mikioh.mikioh@gmail.com>
Date:   Sun Feb 24 12:04:48 2013 +0900

    syscall: add if_announce support for freebsd
    
    Update #4866.
    
    R=golang-dev, dave
    CC=golang-dev
    https://golang.org/cl/7398047

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/b1d51c63d6626e0e78f5ea0e1f4b6eda4af045e0

元コミット内容

syscall: add if_announce support for freebsd

このコミットは、FreeBSDにおける if_announce イベントのサポートをGo言語の syscall パッケージに追加します。これは、Issue #4866 に関連する更新です。

変更の背景

Go言語の syscall パッケージは、オペレーティングシステムの低レベルな機能(システムコール)にアクセスするためのインターフェースを提供します。FreeBSDのようなUNIX系OSでは、ネットワークインターフェースの追加や削除といったイベントをカーネルがユーザーランドに通知するメカニズムが存在します。このメカニズムの一つが if_announce です。

このコミットが作成された背景には、GoプログラムがFreeBSD環境でネットワークインターフェースの状態変化をより詳細に、かつ効率的に監視・応答できるようにするという目的があります。具体的には、新しいネットワークインターフェースがシステムに接続された際(IFAN_ARRIVAL)や、既存のインターフェースが切断された際(IFAN_DEPARTURE)に、Goプログラムがこれらのイベントを検知し、適切な処理を実行できるようになることが求められました。

コミットメッセージに記載されている #4866 は、この機能追加の必要性を示唆するGoのIssueトラッカー上の課題番号であると考えられます。Goの標準ライブラリが様々なOSのシステムコールをサポートする中で、FreeBSD固有の重要なネットワークイベント通知メカニズムである if_announce のサポートは、FreeBSD上でのGoアプリケーションのネットワーク機能の充実と安定性向上に寄与します。

前提知識の解説

FreeBSDの if_announce

FreeBSDにおける if_announce は、カーネルがネットワークインターフェースに関するイベントをユーザーランドに通知するためのメカニズムです。これは ifnet フレームワークの一部であり、ネットワークインターフェースのライフサイクル管理(作成、登録、破棄など)に関連するイベントをシグナルします。

具体的には、以下のようなイベントが if_announce を通じて通知されます。

  • IFAN_ARRIVAL: 新しいネットワークインターフェースがシステムに接続された、または利用可能になったことを示します。
  • IFAN_DEPARTURE: ネットワークインターフェースがシステムから切断された、または利用不可能になったことを示します。

これらのイベントは、ユーザーランドのユーティリティ(例: devd(8))が監視し、インターフェースの状態変化に応じて特定のアクションやスクリプトをトリガーするために利用されます。

Go言語の syscall パッケージ

Go言語の syscall パッケージは、Goプログラムが基盤となるオペレーティングシステムのプリミティブに直接アクセスするための低レベルなインターフェースを提供します。これにより、プロセス管理、ファイル操作、ネットワーク通信などのシステムコールを直接実行できます。

syscall パッケージの主な特徴は以下の通りです。

  • 低レベルな相互作用: GoアプリケーションとOSカーネル間の橋渡し役となり、プロセス作成、ファイルの読み書き、メモリ管理などのサービスを要求します。
  • プラットフォーム固有: syscall パッケージ内の関数や定数の詳細、および利用可能性は、オペレーティングシステム(Windows, Linux, macOSなど)によって大きく異なります。
  • 新規コードでの非推奨: 標準Goライブラリの syscall パッケージは「ロックダウン」されており、新しい開発では golang.org/x/sys パッケージ、特にUnix系システムでは golang.org/x/sys/unix の使用が強く推奨されています。これは、外部パッケージの方がより多くのシステムコールをサポートし、移植性が高く、新しい更新やシステム固有の実装が適用されるためです。
  • 高レベルな代替: ほとんどの一般的なプログラミングタスクでは、Goの標準ライブラリが提供する ostimenet などのより移植性が高く、使いやすい高レベルなパッケージを使用することが推奨されます。可能な限り、syscall よりもこれらの高レベルなパッケージを優先すべきです。

このコミットは、syscall パッケージがまだ活発にOS固有の機能を取り込んでいた時期のものであり、FreeBSDの if_announce をGoプログラムから利用可能にするための基盤を構築するものです。

技術的詳細

このコミットは、FreeBSDの if_announce イベントをGoの syscall パッケージで扱えるようにするために、主に以下の変更を行っています。

  1. mkerrors.sh の更新: mkerrors.sh は、Goの syscall パッケージがOS固有のエラーコードや定数を生成するために使用するスクリプトです。このスクリプトに IFAN というプレフィックスを持つ定数(IFAN_ARRIVAL, IFAN_DEPARTURE など)を認識させるための正規表現が追加されています。これにより、FreeBSDのカーネルヘッダーファイルからこれらの定数が正しくGoのコードに変換されるようになります。

  2. types_freebsd.go の更新: このファイルは、FreeBSD固有のシステムコールに関連するGoの型定義を含んでいます。

    • SizeofIfAnnounceMsghdr という定数が追加され、C.sizeof_struct_if_announcemsghdr のサイズが定義されています。これは、if_announce メッセージヘッダーのサイズを示すものです。
    • IfAnnounceMsghdr という新しいGoの構造体型が追加されています。この構造体は、FreeBSDカーネルが if_announce イベントを通知する際に使用する struct if_announcemsghdr に対応します。
  3. zerrors_freebsd_*.go ファイルの更新: zerrors_freebsd_386.go, zerrors_freebsd_amd64.go, zerrors_freebsd_arm.go は、それぞれ32ビット、64ビット、ARMアーキテクチャ向けのFreeBSD固有のエラーコードや定数を定義する自動生成ファイルです。これらのファイルに IFAN_ARRIVALIFAN_DEPARTURE の定数が追加されています。これらの定数は、ネットワークインターフェースの到着と離脱を示すイベントタイプです。

  4. ztypes_freebsd_*.go ファイルの更新: ztypes_freebsd_386.go, ztypes_freebsd_amd64.go, ztypes_freebsd_arm.go は、FreeBSD固有のシステムコールに関連するGoの型定義を自動生成するファイルです。

    • SizeofIfAnnounceMsghdr 定数の具体的な値(例: 0x18)が各アーキテクチャ向けに追加されています。これは、if_announcemsghdr 構造体の実際のサイズを示します。
    • IfAnnounceMsghdr 構造体のGo言語での定義が追加されています。この構造体は、Msglen (メッセージ長)、Version (バージョン)、Type (メッセージタイプ)、Index (インターフェースインデックス)、Name (インターフェース名)、What (イベントタイプ、IFAN_ARRIVAL または IFAN_DEPARTURE) などのフィールドを持ちます。これらのフィールドは、FreeBSDカーネルが if_announce イベントを通知する際に送信する情報に対応します。

これらの変更により、Goプログラムは syscall パッケージを通じてFreeBSDの if_announce イベントを受信し、その内容をGoの構造体として解釈できるようになります。これにより、Goで書かれたネットワーク関連のツールやデーモンが、FreeBSD環境下でネットワークインターフェースの動的な変化に適切に対応できるようになります。

コアとなるコードの変更箇所

このコミットにおけるコアとなるコードの変更箇所は以下のファイルに集中しています。

  1. src/pkg/syscall/mkerrors.sh:

    --- a/src/pkg/syscall/mkerrors.sh
    +++ b/src/pkg/syscall/mkerrors.sh
    @@ -207,7 +207,7 @@ ccflags="$@"
     		$2 ~ /^LINUX_REBOOT_CMD_/ ||
     		$2 ~ /^LINUX_REBOOT_MAGIC[12]$/ ||
     		$2 !~ "NLA_TYPE_MASK" &&
    -		$2 ~ /^(NETLINK|NLM|NLMSG|NLA|IFA|RT|RTCF|RTN|RTPROT|RTNH|ARPHRD|ETH_P)_/ ||
    +		$2 ~ /^(NETLINK|NLM|NLMSG|NLA|IFA|IFAN|RT|RTCF|RTN|RTPROT|RTNH|ARPHRD|ETH_P)_/ ||
     		$2 ~ /^SIOC/ ||
     		$2 ~ /^TIOC/ ||
     		$2 ~ /^(IFF|IFT|NET_RT|RTM|RTF|RTV|RTA|RTAX)_/ ||
    
  2. src/pkg/syscall/types_freebsd.go:

    --- a/src/pkg/syscall/types_freebsd.go
    +++ b/src/pkg/syscall/types_freebsd.go
    @@ -193,12 +193,13 @@ type FdSet C.fd_set
     // Routing and interface messages
     
     const (
    -	SizeofIfMsghdr   = C.sizeof_struct_if_msghdr
    -	SizeofIfData     = C.sizeof_struct_if_data
    -	SizeofIfaMsghdr  = C.sizeof_struct_ifa_msghdr
    -	SizeofIfmaMsghdr = C.sizeof_struct_ifma_msghdr
    -	SizeofRtMsghdr   = C.sizeof_struct_rt_msghdr
    -	SizeofRtMetrics  = C.sizeof_struct_rt_metrics
    +	SizeofIfMsghdr         = C.sizeof_struct_if_msghdr
    +	SizeofIfData           = C.sizeof_struct_if_data
    +	SizeofIfaMsghdr        = C.sizeof_struct_ifa_msghdr
    +	SizeofIfmaMsghdr       = C.sizeof_struct_ifma_msghdr
    +	SizeofIfAnnounceMsghdr = C.sizeof_struct_if_announcemsghdr
    +	SizeofRtMsghdr         = C.sizeof_struct_rt_msghdr
    +	SizeofRtMetrics        = C.sizeof_struct_rt_metrics
     )
     
     type IfMsghdr C.struct_if_msghdr
    @@ -209,6 +210,8 @@ type IfaMsghdr C.struct_ifa_msghdr
     
     type IfmaMsghdr C.struct_ifma_msghdr
     
    +type IfAnnounceMsghdr C.struct_if_announcemsghdr
    +
     type RtMsghdr C.struct_rt_msghdr
     
     type RtMetrics C.struct_rt_metrics
    
  3. src/pkg/syscall/zerrors_freebsd_386.go (amd64, armも同様):

    --- a/src/pkg/syscall/zerrors_freebsd_386.go
    +++ b/src/pkg/syscall/zerrors_freebsd_386.go
    @@ -369,6 +369,8 @@ const (
      	F_UNLCK                           = 0x2
      	F_UNLCKSYS                        = 0x4
      	F_WRLCK                           = 0x3
    +	IFAN_ARRIVAL                      = 0x0
    +	IFAN_DEPARTURE                    = 0x1
      	IFF_ALLMULTI                      = 0x200
      	IFF_ALTPHYS                       = 0x4000
      	IFF_BROADCAST                     = 0x2
    
  4. src/pkg/syscall/ztypes_freebsd_386.go (amd64, armも同様):

    --- a/src/pkg/syscall/ztypes_freebsd_386.go
    +++ b/src/pkg/syscall/ztypes_freebsd_386.go
    @@ -271,12 +271,13 @@ type FdSet struct {
     }
     
     const (
    -	SizeofIfMsghdr   = 0x60
    -	SizeofIfData     = 0x50
    -	SizeofIfaMsghdr  = 0x14
    -	SizeofIfmaMsghdr = 0x10
    -	SizeofRtMsghdr   = 0x5c
    -	SizeofRtMetrics  = 0x38
    +	SizeofIfMsghdr         = 0x60
    +	SizeofIfData           = 0x50
    +	SizeofIfaMsghdr        = 0x14
    +	SizeofIfmaMsghdr       = 0x10
    +	SizeofIfAnnounceMsghdr = 0x18
    +	SizeofRtMsghdr         = 0x5c
    +	SizeofRtMetrics        = 0x38
     )
     
     type IfMsghdr struct {
    @@ -339,6 +340,15 @@ type IfmaMsghdr struct {
     	Pad_cgo_0 [2]byte
     }
     
    +type IfAnnounceMsghdr struct {
    +	Msglen  uint16
    +	Version uint8
    +	Type    uint8
    +	Index   uint16
    +	Name    [16]int8
    +	What    uint16
    +}
    +
     type RtMsghdr struct {
     	Msglen    uint16
     	Version   uint8
    

コアとなるコードの解説

src/pkg/syscall/mkerrors.sh の変更

mkerrors.sh は、Goの syscall パッケージがC言語のヘッダーファイルから定数を自動生成する際に使用するシェルスクリプトです。変更点では、正規表現 ^(NETLINK|NLM|NLMSG|NLA|IFA|RT|RTCF|RTN|RTPROT|RTNH|ARPHRD|ETH_P)_/|IFAN が追加されています。 これは、IFAN_ で始まる定数(例: IFAN_ARRIVAL, IFAN_DEPARTURE)も自動生成の対象に含めることを意味します。これにより、FreeBSDカーネルが定義する if_announce 関連の定数がGoの syscall パッケージで利用可能になります。

src/pkg/syscall/types_freebsd.go の変更

このファイルは、FreeBSD固有のシステムコールに関連するGoの型定義を手動で記述する場所です。

  • SizeofIfAnnounceMsghdr = C.sizeof_struct_if_announcemsghdr の追加は、C言語の struct if_announcemsghdr のサイズをGoの定数として定義しています。これは、GoがCの構造体を扱う際にメモリレイアウトを正しく理解するために必要です。
  • type IfAnnounceMsghdr C.struct_if_announcemsghdr の追加は、C言語の struct if_announcemsghdr に対応するGoの型エイリアスを定義しています。これにより、Goコード内でこの構造体を型安全に参照できるようになります。

src/pkg/syscall/zerrors_freebsd_*.go の変更

これらのファイルは、mkerrors.sh スクリプトによって自動生成される、FreeBSD固有の定数定義を含んでいます。各アーキテクチャ(386, amd64, arm)向けに、IFAN_ARRIVALIFAN_DEPARTURE の定数が追加されています。

  • IFAN_ARRIVAL = 0x0: ネットワークインターフェースが到着したことを示すイベントタイプ。
  • IFAN_DEPARTURE = 0x1: ネットワークインターフェースが離脱したことを示すイベントタイプ。 これらの定数は、Goプログラムが if_announce メッセージを受信した際に、どのようなイベントが発生したかを識別するために使用されます。

src/pkg/syscall/ztypes_freebsd_*.go の変更

これらのファイルも、mkerrors.sh スクリプトによって自動生成される、FreeBSD固有の型定義を含んでいます。各アーキテクチャ向けに以下の変更が行われています。

  • SizeofIfAnnounceMsghdr 定数の具体的な値(例: 0x18 for 386/arm, 0x18 for amd64)が追加されています。これは、if_announcemsghdr 構造体の実際のバイトサイズを示し、Goがこの構造体を正しくパースするために重要です。
  • IfAnnounceMsghdr 構造体のGo言語での定義が追加されています。この構造体は、FreeBSDカーネルが if_announce イベントを通知する際に送信するメッセージのフォーマットをGoで表現したものです。
    • Msglen uint16: メッセージ全体の長さ。
    • Version uint8: メッセージのバージョン。
    • Type uint8: メッセージのタイプ(例: RTM_IFANNOUNCE)。
    • Index uint16: イベントが発生したネットワークインターフェースのインデックス。
    • Name [16]int8: インターフェースの名前(例: "em0", "lo0")。
    • What uint16: 発生したイベントの種類(IFAN_ARRIVAL または IFAN_DEPARTURE)。

これらの変更により、GoプログラムはFreeBSDの if_announce イベントをシステムコールレベルで捕捉し、そのバイナリデータをGoの構造体にマッピングして、イベントの詳細をプログラム的に利用できるようになります。

関連リンク

参考にした情報源リンク