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

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

このコミットは、Go言語のsyscallパッケージにNetBSDオペレーティングシステム向けのif_announceメッセージのサポートを追加するものです。これにより、GoプログラムがNetBSDシステム上でネットワークインターフェースの到着(追加)や出発(削除)といったイベントを検知し、それに対応できるようになります。

コミット

  • コミットハッシュ: d41dede2803d36db138a0f3220dcd9ebf4749a25
  • Author: Mikio Hara mikioh.mikioh@gmail.com
  • Date: Sun Feb 24 12:06:24 2013 +0900

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

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

元コミット内容

syscall: add if_announce support for netbsd

Update #4866.

R=golang-dev, bradfitz, dave
CC=golang-dev
https://golang.org/cl/7382052

変更の背景

この変更の背景には、NetBSDシステムにおけるネットワークインターフェースの動的な管理があります。NetBSDのようなUNIX系OSでは、ネットワークインターフェース(例: イーサネットカード、Wi-Fiアダプタ、仮想インターフェースなど)がシステムに接続されたり、取り外されたりする際に、そのイベントをアプリケーションに通知するメカニズムが存在します。if_announceメッセージはそのような通知メカニズムの一つです。

Go言語のsyscallパッケージは、Goプログラムから基盤となるオペレーティングシステムのシステムコールやデータ構造にアクセスするためのインターフェースを提供します。ネットワーク関連のアプリケーション、特にネットワークインターフェースの状態変化に反応する必要があるデーモンやサービスをNetBSD上でGoで記述する場合、if_announceメッセージを処理する機能が不可欠となります。

このコミットは、GoのsyscallパッケージがNetBSDのif_announceメッセージを認識し、Goの型として表現できるようにすることで、Go開発者がNetBSDのネットワークインターフェースイベントをより容易に扱えるようにすることを目的としています。コミットメッセージにあるUpdate #4866は、おそらくGoプロジェクトの内部トラッカーにおける特定の課題や機能リクエストに対応するものであると考えられます。

前提知識の解説

Go言語のsyscallパッケージ

Go言語のsyscallパッケージは、Goプログラムがオペレーティングシステム(OS)の低レベルな機能にアクセスするためのインターフェースを提供します。これには、ファイル操作、プロセス管理、ネットワーク通信など、OSが提供するシステムコールやデータ構造のラッパーが含まれます。syscallパッケージは、OS固有の定数、構造体、関数などを定義しており、クロスプラットフォームなGoプログラムでは通常直接使用されませんが、OS固有の機能やパフォーマンスが要求される場合には不可欠です。

NetBSD

NetBSDは、オープンソースのUNIX系オペレーティングシステムであり、その設計の移植性の高さで知られています。非常に多くのハードウェアアーキテクチャで動作し、組み込みシステムからサーバーまで幅広い用途で利用されています。ネットワークスタックはBSD系の伝統を受け継いでおり、ネットワークインターフェースの管理やルーティングに関する独自のメカニズムを持っています。

if_announceメッセージ

NetBSDを含む一部のBSD系OSでは、ネットワークインターフェースの追加(到着)や削除(出発)といったイベントが発生した際に、カーネルがユーザー空間のプロセスに通知するためのメッセージを生成します。これがif_announceメッセージです。これらのメッセージは、通常、ルーティングソケット(PF_ROUTE)を通じてアプリケーションに配信されます。アプリケーションはこれらのメッセージを監視することで、ネットワークインターフェースの動的な変化を検知し、それに応じて動作を変更することができます。

struct if_announcemsghdr

if_announceメッセージのヘッダ部分を定義するC言語の構造体です。この構造体には、メッセージの長さ、バージョン、タイプ、関連するインターフェースのインデックス、インターフェース名、そしてイベントの種類(到着か出発か)などの情報が含まれます。Goのsyscallパッケージでは、C言語の構造体をGoの構造体としてマッピングし、Goプログラムからアクセスできるようにします。

IFAN_ARRIVALIFAN_DEPARTURE

これらはif_announceメッセージ内でイベントの種類を示す定数です。

  • IFAN_ARRIVAL: ネットワークインターフェースがシステムに「到着」した(追加された)ことを示します。
  • IFAN_DEPARTURE: ネットワークインターフェースがシステムから「出発」した(削除された)ことを示します。

これらの定数を使用することで、Goプログラムは受信したif_announceメッセージがどの種類のイベントを通知しているのかを判別できます。

zerrors_netbsd_*.goztypes_netbsd_*.go

Goのsyscallパッケージには、OS固有の定数や型定義を自動生成するメカニズムがあります。zerrors_netbsd_*.goファイルはNetBSD固有のエラーコードやその他の定数を定義し、ztypes_netbsd_*.goファイルはNetBSD固有のC言語の構造体をGoの構造体として定義します。これらのファイルは、異なるアーキテクチャ(例: 386, amd64, arm)ごとに生成されるため、ファイル名にアーキテクチャ名が含まれています。このコミットでは、if_announceに関連する新しい定数と型がこれらのファイルに追加されています。

技術的詳細

このコミットは、GoのsyscallパッケージがNetBSDのif_announceメッセージを適切に処理できるようにするための、低レベルな型と定数の追加に焦点を当てています。

  1. types_netbsd.goの変更:

    • SizeofIfAnnounceMsghdrという新しい定数が追加されました。これはC言語のstruct if_announcemsghdrのサイズをGo側で参照するためのものです。C.sizeof_struct_if_announcemsghdrを使用して、Cのヘッダファイルから実際のサイズを取得します。
    • IfAnnounceMsghdrという新しいGoの型が追加されました。これはC言語のstruct if_announcemsghdrに対応するGoの構造体であり、C.struct_if_announcemsghdrをラップしています。これにより、Goプログラム内でif_announceメッセージのヘッダをGoの型として扱うことができるようになります。
  2. zerrors_netbsd_*.goの変更:

    • IFAN_ARRIVALIFAN_DEPARTUREという2つの新しい定数が追加されました。これらはif_announceメッセージが示すイベントの種類(到着または出発)を表す値です。これらの定数は、NetBSDのシステムヘッダファイルで定義されている対応するC言語の定数と同じ値を持つように設定されます。これにより、Goプログラムは受信したメッセージのWhatフィールドをこれらの定数と比較することで、イベントの種類を判別できます。
  3. ztypes_netbsd_*.goの変更:

    • SizeofIfAnnounceMsghdr定数の具体的な値が、各アーキテクチャ(386, amd64, arm)のztypes_netbsd_*.goファイルにハードコードされました。これは、C.sizeof_struct_if_announcemsghdrがビルド時に解決された実際のサイズです。
    • IfAnnounceMsghdr構造体のGo言語での具体的な定義が、各アーキテクチャのztypes_netbsd_*.goファイルに追加されました。この構造体は、Msglen, Version, Type, Index, Name, Whatといったフィールドを持ち、それぞれがNetBSDのstruct if_announcemsghdrの対応するフィールドにマッピングされます。Nameフィールドはインターフェース名を格納するための固定サイズの配列であり、Whatフィールドはイベントの種類(IFAN_ARRIVALまたはIFAN_DEPARTURE)を示します。

これらの変更により、GoのsyscallパッケージはNetBSDのif_announceメッセージをGoの型として表現し、その内容をGoプログラムから直接アクセスできるようになります。これにより、Goで書かれたネットワークアプリケーションがNetBSDシステム上でインターフェースの動的な変化に反応する機能を実現するための基盤が提供されます。

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

src/pkg/syscall/types_netbsd.go

--- a/src/pkg/syscall/types_netbsd.go
+++ b/src/pkg/syscall/types_netbsd.go
@@ -171,11 +171,12 @@ 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
-	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
+	SizeofIfAnnounceMsghdr = C.sizeof_struct_if_announcemsghdr
+	SizeofRtMsghdr         = C.sizeof_struct_rt_msghdr
+	SizeofRtMetrics        = C.sizeof_struct_rt_metrics
 )
 
 type IfMsghdr C.struct_if_msghdr
@@ -184,6 +185,8 @@ type IfData C.struct_if_data
 
 type IfaMsghdr C.struct_ifa_msghdr
 
+type IfAnnounceMsghdr C.struct_if_announcemsghdr
+
 type RtMsghdr C.struct_rt_msghdr
 
 type RtMetrics C.struct_rt_metrics

src/pkg/syscall/zerrors_netbsd_386.go, src/pkg/syscall/zerrors_netbsd_amd64.go, src/pkg/syscall/zerrors_netbsd_arm.go

(各アーキテクチャで同様の変更)

--- a/src/pkg/syscall/zerrors_netbsd_386.go
+++ b/src/pkg/syscall/zerrors_netbsd_386.go
@@ -572,6 +572,8 @@ const (
 	ICANON                            = 0x100
 	ICRNL                             = 0x100
 	IEXTEN                            = 0x400
+	IFAN_ARRIVAL                      = 0x0
+	IFAN_DEPARTURE                    = 0x1
 	IFA_ROUTE                         = 0x1
 	IFF_ALLMULTI                      = 0x200
 	IFF_BROADCAST                     = 0x2

src/pkg/syscall/ztypes_netbsd_386.go, src/pkg/syscall/ztypes_netbsd_amd64.go, src/pkg/syscall/ztypes_netbsd_arm.go

(各アーキテクチャで同様の変更)

--- a/src/pkg/syscall/ztypes_netbsd_386.go
+++ b/src/pkg/syscall/ztypes_netbsd_386.go
@@ -219,11 +219,12 @@ type FdSet struct {
 }
 
 const (
-	SizeofIfMsghdr  = 0x98
-	SizeofIfData    = 0x84
-	SizeofIfaMsghdr = 0x18
-	SizeofRtMsghdr  = 0x78
-	SizeofRtMetrics = 0x50
+	SizeofIfMsghdr         = 0x98
+	SizeofIfData           = 0x84
+	SizeofIfaMsghdr        = 0x18
+	SizeofIfAnnounceMsghdr = 0x18
+	SizeofRtMsghdr         = 0x78
+	SizeofRtMetrics        = 0x50
 )
 
 type IfMsghdr struct {
@@ -272,6 +273,15 @@ type IfaMsghdr struct {
 	Pad_cgo_0 [6]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/types_netbsd.go

  • SizeofIfAnnounceMsghdr = C.sizeof_struct_if_announcemsghdr:
    • C.sizeof_struct_if_announcemsghdrは、C言語のヘッダファイルからstruct if_announcemsghdrのサイズを取得するためのGoのCgo機能です。この行は、Goプログラムがこの構造体のメモリサイズを正確に知るために必要です。これは、ルーティングソケットから読み取ったバイト列をGoの構造体にキャストする際に重要になります。
  • type IfAnnounceMsghdr C.struct_if_announcemsghdr:
    • この行は、C言語のstruct if_announcemsghdrをGoのIfAnnounceMsghdr型としてエイリアス(別名)を定義しています。これにより、Goプログラム内でC言語の構造体を直接参照する代わりに、Goの型システムに統合された形で扱うことができます。これは、GoのsyscallパッケージがC言語のシステムコールインターフェースをGoの慣用的な方法でラップするための一般的なパターンです。

src/pkg/syscall/zerrors_netbsd_*.go

  • IFAN_ARRIVAL = 0x0
  • IFAN_DEPARTURE = 0x1
    • これらの行は、NetBSDのif_announceメッセージで使われるイベントタイプを示す定数をGoに導入しています。IFAN_ARRIVALはインターフェースの追加、IFAN_DEPARTUREはインターフェースの削除を意味します。これらの定数は、GoプログラムがIfAnnounceMsghdr構造体のWhatフィールドの値を解釈するために使用されます。値はNetBSDのシステムヘッダで定義されているものと一致します。

src/pkg/syscall/ztypes_netbsd_*.go

  • SizeofIfAnnounceMsghdr = 0x18 (例: 386, armの場合。amd64も同様)
    • types_netbsd.goで定義されたSizeofIfAnnounceMsghdrの具体的な値が、各アーキテクチャのztypes_netbsd_*.goファイルにハードコードされています。これは、ビルド時にCgoが解決した実際のサイズです。この値は、Goプログラムがルーティングソケットから読み取るメッセージのバイト数を正確に把握するために使用されます。
  • type IfAnnounceMsghdr struct { ... }:
    • この構造体は、NetBSDのstruct if_announcemsghdrのGo言語での具体的な表現です。各フィールドはC言語の構造体の対応するフィールドにマッピングされます。
      • Msglen uint16: メッセージ全体の長さ。
      • Version uint8: メッセージのバージョン。
      • Type uint8: メッセージのタイプ(例: RTM_IFANNOUNCE)。
      • Index uint16: イベントが発生したネットワークインターフェースのインデックス。
      • Name [16]int8: ネットワークインターフェースの名前(例: "em0", "lo0")。Goでは固定サイズの配列として表現されます。
      • What uint16: イベントの種類(IFAN_ARRIVALまたはIFAN_DEPARTURE)。

これらの変更により、GoのsyscallパッケージはNetBSDのif_announceメッセージをGoの型として表現し、その内容をGoプログラムから直接アクセスできるようになります。これにより、Goで書かれたネットワークアプリケーションがNetBSDシステム上でインターフェースの動的な変化に反応する機能を実現するための基盤が提供されます。

関連リンク

参考にした情報源リンク

  • Go issue 4866: 残念ながら、公式のgolang/go GitHubリポジトリでは、このコミットメッセージに記載されている#4866という特定のIssueを見つけることができませんでした。これは、内部のトラッキングシステムで使われていた番号であるか、あるいはGoLandのIssueトラッカー(GO-4859など)のように、Go関連の別のプロジェクトのIssueを参照している可能性があります。
  • NetBSD if_announcemsghdr (一般的な情報源): NetBSDのシステムプログラミングに関するドキュメントや、BSD系のネットワークスタックに関する一般的な情報源が参考になります。例えば、NetBSDのソースコードやmanページ(rtm_ifannounce(4)など)が該当します。