Go to main content
Oracle® Solaris 11.3 デバイスドライバの記述

印刷ビューの終了

更新: 2016 年 11 月
 
 

GLDv2 ネットワークデバイスドライバフレームワーク

GLDv2 は、ローカルエリアネットワーク用のデバイスドライバをサポートする、マルチスレッド化された、ロード可能かつ複製可能なカーネルモジュールです。Oracle Solaris OS のローカルエリアネットワーク (LAN) デバイスドライバは、Data Link Provider Interface (DLPI) を使用してネットワークプロトコルスタックと通信する STREAMS ベースのドライバです。これらのプロトコルスタックは、ネットワークドライバを使用して LAN 上でパケットを送受信します。GLDv2 では、STREAMS および DLPI の機能のうち、Oracle Solaris LAN ドライバのためのほとんどの機能を実装しています。GLDv2 は、多くのネットワークドライバで共有可能な共通コードを提供します。GLDv2 を使用することで、コードの重複が減少し、ネットワークドライバが簡素化されます。

GLDv2 の詳細は、gld(7D) のマニュアルページを参照してください。

STREAMS ドライバについては、STREAMS Programming Guide の パート II, Kernel Interface,に記載されています。特に、STREAMS ガイドの第 9 章「STREAMS Drivers」を参照してください。STREAMS フレームワークはメッセージベースのフレームワークです。STREAMS ドライバ固有のインタフェースには、STREAMS メッセージキュー処理エントリポイントが含まれています。

DLPI は、OSI 参照モデルのデータリンク層のデータリンクサービス (DLS) に対するインタフェースの仕様を定義します。DLPI により、DLS ユーザーは DLS プロバイダのプロトコルについて特別な知識がなくても、仕様に準拠した各種 DLS プロバイダにアクセスして利用できます。DLPI では、M_PROTO および M_PCPROTO タイプの STREAMS メッセージを利用して DLS プロバイダにアクセスする仕様が定められています。DLPI モジュールは、STREAMS ioctl 呼び出しを使用して MAC 下位層にリンクします。Oracle Solaris 固有の DLPI 拡張機能を含む DLPI プロトコルの詳細は、dlpi(7P) のマニュアルページを参照してください。DLPI 全般に関する情報は、DLPI 標準 (http://www.opengroup.org/pubs/catalog/c811.htm) を参照してください。

    GLDv2 を使用して実装される Oracle Solaris ネットワークドライバは、次の 2 つの部分に分けることができます。

  • 汎用コンポーネント。STREAMS および DLPI インタフェースを扱います。

  • デバイス固有コンポーネント。特定のハードウェアデバイスを扱います。

    • misc/gld への依存性とリンクすることにより、GLDv2 モジュールへのドライバの依存性を示します。GLDv2 モジュールの場所は、SPARC システムでは /kernel/misc/sparcv9/gld、64 ビット x86 システムでは /kernel/misc/amd64/gld、32 ビット x86 システムでは /kernel/misc/gld です。

    • GLDv2 への登録: ドライバはその attach(9E) エントリポイントで、ドライバのほかのエントリポイントへのポインタを GLDv2 に知らせます。GLDv2 はこれらのポインタを使用して、gld(9E) エントリポイントを呼び出します。

    • gld(9F) 関数を呼び出して、データを処理したり、ほかの GLDv2 サービスを利用したりします。gld_mac_info(9S) 構造体は、GLDv2 とデバイス固有ドライバ間のプライマリデータインタフェースです。

GLDv2 ドライバは、完全形式の MAC 層パケットを処理する必要があり、論理リンク制御 (LLC) 処理を実行してはなりません。

GLDv2 のデバイスサポート

    GLDv2 フレームワークは次の種類のデバイスをサポートします。

  • DL_ETHER: ISO 8802-3、IEEE 802.3 プロトコル

  • DL_TPR: IEEE 802.5、Token Passing Ring

  • DL_FDDI: ISO 9314-2、Fibre Distributed Data Interface

Ethernet V2 および ISO 8802-3 (IEEE 802.3)

DL_ETHER タイプとして宣言されたデバイスについて、GLDv2 は Ethernet V2 および ISO 8802-3 (IEEE 802.3) の両方のパケット処理をサポートします。Ethernet V2 では、ユーザーはプロバイダのプロトコルについて特別な知識がなくても、仕様に準拠したデータリンクサービスプロバイダにアクセスできます。サービスアクセスポイント (SAP) は、ユーザーがサービスプロバイダと通信するときに通過するポイントです。

0 - 255 の範囲の SAP 値にバインドされたストリームは同等として扱われ、ユーザーが 8802-3 モードの使用を求めていることを示します。DL_BIND_REQ の SAP 値がこの範囲内の場合、GLDv2 は、そのストリームの後続の各 DL_UNITDATA_REQ メッセージの長さを計算します。この長さには 14 バイトのメディアアクセス制御 (MAC) ヘッダーは含まれません。GLDv2 はその後、計算した長さの 8802-3 フレームを MAC フレームヘッダーの type フィールドに転送します。この長さは 1500 を超えることはありません。

0 - 1500 の範囲の type フィールドを持つフレームは 8802-3 フレームとみなされます。これらのフレームは、8802-3 モードで開いているすべてのストリームに経路指定されます。SAP 値が 0 - 255 の範囲であるストリームは 8802-3 モードとみなされます。複数のストリームが 8802-3 モードである場合、着信フレームは複製され、これらのストリームに経路指定されます。

1500 より大きい SAP 値にバインドされたストリームは Ethernet V2 モードとみなされます。これらのストリームは、Ethernet MAC ヘッダーの type の値が、ストリームのバインド先である SAP の値と完全一致する着信パケットを受信します。

TPR と FDDI: SNAP 処理

DL_TPR および DL_FDDI のメディアタイプ向けに、GLDv2 は最小限の SNAP (Sub-Net Access Protocol) 処理を実装します。この処理は、255 より大きい SAP 値にバインドされたあらゆるストリームが対象となります。0 - 255 の範囲の SAP 値は LLC SAP 値です。そのような値は、メディアパケットフォーマットによって通常どおりに伝送されます。SAP 値が 255 より大きい場合、16 ビット Ethernet V2 スタイルの SAP 値を伝送するには、LLC ヘッダーに従属する SNAP ヘッダーが必要です。

SNAP ヘッダーは、宛先 SAP 0xAA が指定された LLC ヘッダーとして伝送されます。SAP 値が 255 より大きい発信パケットには、次の形式の LLC+SNAP ヘッダーが必要です。

AA AA 03 00 00 00 XX XX

XX XX は、Ethernet V2 スタイルの type に対応する 16 ビット SAP を表します。このヘッダーは、0 以外の組織固有識別子フィールドのサポートに固有のものです。03 以外の LLC 制御フィールドは、SAP 0xAA を持つ LLC パケットとみなされます。これ以外の SNAP フォーマットを使用するクライアントは、LLC を使用し、SAP 0xAA にバインドする必要があります。

着信パケットが前述したフォーマットに適合しているかどうかのチェックが行われます。適合するパケットは、パケットの 16 ビット SNAP タイプにバインドされたすべてのストリームと照合されます。また、これらのパケットは LLC SNAP SAP 0xAA に一致するものとみなされます。

LLC SAP として受信されたすべてのパケットは、メディアタイプ DL_ETHER の項目で説明したように、LLC SAP にバインドされているすべての上位層ストリームに渡されます。

TPR: 発信元ルーティング

DL_TPR タイプのデバイス向けに、GLDv2 は発信元ルーティングの最小限のサポートを実装します。

    発信元ルーティングのサポートには次のタスクが含まれています。

  • ブリッジメディアを介して送信されるパケットのルーティング情報を指定します。ルーティング情報は MAC ヘッダーに格納されます。この情報は経路の特定に使用されます。

  • 経路を学習します。

  • 可能性のある複数の経路についての情報を要求し、そのような情報の要求に応答します。

  • 利用可能な経路の中から選択します。

発信元ルーティングにより、発信パケットの MAC ヘッダーにルーティング情報フィールドが付加されます。また、このサポートにより着信パケットの経路指定情報フィールドが認識されます。

GLDv2 の発信元ルーティングのサポートでは、ISO 8802-2 (IEEE 802.2) のセクション 9 で定義されている、完全な経路特定エンティティー (route determination entity、RDE) は実装されません。ただしこのサポートでは、同一ネットワークまたはブリッジ接続されたネットワークに存在する可能性がある、あらゆる RDE 実装との相互運用が可能です。

GLDv2 の DLPI プロバイダ

GLDv2 は、Style 1 および Style 2 両方の DLPI プロバイダを実装します。物理接続点 (PPA) は、システムが物理通信メディアと接続するポイントです。その物理メディアを介したすべての通信が PPA を通過します。Style 1 プロバイダは、開かれているメジャーデバイスまたはマイナーデバイスに基づいて、ストリームを特定の PPA に接続します。Style 2 プロバイダの場合、DLS ユーザーは DL_ATTACH_REQ を使用して、接続先 PPA を明示的に指定する必要があります。この場合、open(9E) がユーザーと GLDv2 の間にストリームを作成したあとに、DL_ATTACH_REQ が特定の PPA をそのストリームと関連付けます。Style 2 は 0 のマイナー番号によって示されます。マイナー番号が 0 でないデバイスノードが開かれている場合、Style 1 が示され、マイナー番号から 1 を引いた PPA が関連付けられます。Style 1 と Style 2 の両方が開いている場合、デバイスは複製されます。

GLDv2 の DLPI プリミティブ

GLDv2 はいくつかの DLPI プリミティブを実装します。DL_INFO_REQ プリミティブは、DLPI ストリームについての情報を要求します。メッセージは 1 つの M_PROTO メッセージブロックで構成されます。GLDv2 はこの要求に対して、デバイス依存の値を DL_INFO_ACK 応答で返します。これらの値は、gld_register(9F) 関数に渡す gld_mac_info(9S) 構造体で GLDv2 ベースのドライバが指定した情報に基づきます。

    すべての GLDv2 ベースのドライバに代わって、GLDv2 が次の値を返します。

  • バージョンは DL_VERSION_2 です。

  • サービスモードは DL_CLDLS です。GLDv2 はコネクションレスモードのサービスを実装します。

  • プロバイダのスタイルは、ストリームが開かれた方法に応じて DL_STYLE1 または DL_STYLE2 です。

  • 省略可能なサービス品質 (QOS) サポートはありません。QOS フィールドは 0 です。


注 - DLPI 仕様とは異なり、ストリームが PPA に接続される前であっても、GLDv2 は DL_INFO_ACK でデバイスの正確なアドレス長およびブロードキャストアドレスを返します。

DL_ATTACH_REQ プリミティブは、PPA をストリームと関連付けるために使用されます。この要求は、Style 2 の DLS プロバイダが通信を行う物理メディアを特定するために必要です。完了すると、状態が DL_UNATTACHED から DL_UNBOUND に変化します。メッセージは 1 つの M_PROTO メッセージブロックで構成されます。Style 1 モードの使用時はこの要求は許可されません。Style 1 を使用して開かれたストリームは、オープンの完了時点ですでに PPA に接続されているためです。

DL_DETACH_REQ プリミティブは、PPA をストリームから切り離すことを要求します。この切り離しは、ストリームが Style 2 を使用して開かれた場合にのみ許可されます。

DL_BIND_REQ および DL_UNBIND_REQ プリミティブは、DLSAP (データリンクサービスアクセスポイント) をストリームにバインドまたはバインド解除します。ストリームに関連付けられた PPA は、そのストリームの DL_BIND_REQ の処理が完了する前に初期化を完了します。複数のストリームを同じ SAP にバインドできます。この場合、それぞれのストリームが、その SAP で受信されたすべてのパケットのコピーを受信します。

DL_ENABMULTI_REQ および DL_DISABMULTI_REQ プリミティブは、個々のマルチキャストグループアドレスの受信を有効または無効にします。アプリケーションまたはその他の DLS ユーザーは、これらのプリミティブを繰り返し使用するとマルチキャストアドレスの集合を作成または変更できます。これらのプリミティブが受け入れられるには、ストリームが PPA に接続されている必要があります。

DL_PROMISCON_REQ および DL_PROMISCOFF_REQ プリミティブは、ストリーム単位でプロミスキュアス (promiscuous) モードを有効または無効にします。この制御は物理レベルまたは SAP レベルで機能します。DL プロバイダは、メディアで受信したすべてのメッセージを DLS ユーザーに経路指定します。このルーティングは、DL_DETACH_REQ または DL_PROMISCOFF_REQ が受信されるか、ストリームが閉じられるまで有効です。物理レベルのプロミスキュアスの受信は、メディア上のすべてのパケットに対して、またはマルチキャストパケットに限定して指定できます。


注 - これらのプロミスキュアス (promiscuous) モードプリミティブが受け入れられるには、ストリームが PPA に接続されている必要があります。

DL_UNITDATA_REQ プリミティブは、コネクションレス型転送でデータを送信するために使用されます。このサービスは肯定応答を伴わないため、配信は保証されません。メッセージは 1 つの M_PROTO メッセージブロックと、それに続く 1 つ以上の M_DATA ブロック (少なくとも 1 バイトのデータを含む) で構成されます。

DL_UNITDATA_IND タイプは、パケットをアップストリームに渡すときに使用します。パケットは、プリミティブを DL_UNITDATA_IND に設定した M_PROTO メッセージに格納されます。

DL_PHYS_ADDR_REQ プリミティブは、ストリームに接続された PPA とその時点で関連付けられている MAC アドレスを要求します。アドレスは DL_PHYS_ADDR_ACK プリミティブによって返されます。Style 2 を使用している場合、このプリミティブは DL_ATTACH_REQ が成功したあとに限り有効です。

DL_SET_PHYS_ADDR_REQ プリミティブは、ストリームに接続された PPA とその時点で関連付けられている MAC アドレスを変更します。このプリミティブは、現在および将来にわたってこのデバイスに接続されるすべてのストリームに影響を及ぼします。アドレスの変更後は、現在または将来に開かれてこのデバイスに接続されるすべてのストリームが、この新しい物理アドレスを取得します。新しい物理アドレスは、このプリミティブを使用して物理アドレスをふたたび変更するか、またはドライバが再ロードされるまで有効です。


注 - スーパーユーザーは、ほかのストリームが同じ PPA にバインドされている間も PPA の物理アドレスを変更できます。

DL_GET_STATISTICS_REQ プリミティブは、ストリームに接続された PPA に関連する統計情報を含む DL_GET_STATISTICS_ACK 応答を要求します。DL_ATTACH_REQ を使用して Style 2 のストリームを特定の PPA に接続しておかないと、このプリミティブは成功しません。

GLDv2 の入出力制御関数

GLDv2 は、ここで説明する ioctl ioc_cmd 関数を実装します。認識できない ioctl コマンドを受信した場合、gld(9E) で説明しているように、GLDv2 はそのコマンドをデバイス固有ドライバの gldm_ioctl() ルーチンに渡します。

DLIOCRAW ioctl 関数は、snoop(1M) コマンドをはじめとした一部の DLPI アプリケーションで使用されます。DLIOCRAW コマンドはストリームを raw モードにします。raw モードでは、ドライバはパケットを DL_UNITDATA_IND 形式に変換せずに、MAC レベルの着信パケットをそのまま M_DATA メッセージでアップストリームに渡します。DL_UNITDATA_IND 形式は、通常時に着信パケットの報告に使用されます。パケットの SAP フィルタリングは、raw モードのストリームに対しても実行されます。ストリームのユーザーがすべての着信パケットの受信を求める場合、ユーザーは適切なプロミスキュアス (promiscuous) モードを選択する必要もあります。raw モードの選択に成功したあとも、アプリケーションは完全形式のパケットを、転送用の M_DATA メッセージとしてドライバに送信できます。DLIOCRAW には引数がありません。いったん raw モードが有効になると、ストリームを閉じるまでモードは変化しません。

GLDv2 ドライバの要件

GLDv2 ベースのドライバでは、ヘッダーファイル <sys/gld.h> をインクルードする必要があります。

また、GLDv2 ベースのドライバは、次のように –N"misc/gld" オプションを使用してリンクする必要があります。

%ld -r -N"misc/gld" xx.o -o xx

GLDv2 では、デバイス固有ドライバのために次の関数が実装されています。

module_info(9S) 構造体の mi_idname 要素は、ドライバの名前を指定する文字列です。この文字列は、ファイルシステムで定義されたドライバモジュールの名前と完全に一致する必要があります。

読み取り側の qinit(9S) 構造体では、次の要素を指定します。

qi_putp

NULL

qi_srvp

gld_rsrv

qi_qopen

gld_open

qi_qclose

gld_close

書き込み側の qinit (9S) 構造体では、次の要素を指定します。

qi_putp

gld_wput

qi_srvp

gld_wsrv

qi_qopen

NULL

qi_qclose

NULL

dev_ops(9S) 構造体の devo_getinfo 要素では、getinfo(9E) ルーチンとして gld_getinfo を指定します。

ドライバの attach(9E) 関数は、ハードウェア固有デバイスドライバを GLDv2 の機能と関連付けます。attach() はその後、デバイスおよびドライバを使用できるように準備します。

attach(9E) 関数は、gld_mac_alloc() を使用して gld_mac_info(9S) 構造体を割り当てます。ドライバは通常、macinfo 構造体で定義されているよりも多くの情報をデバイスごとに保存する必要があります。ドライバで、必要な追加のデータ構造体を割り当て、その構造体へのポインタを gld_mac_info(9S) 構造体の gldm_private メンバーに保存します。

attach(9E) ルーチンは、gld_mac_info(9S) のマニュアルページの説明に従って macinfo 構造体を初期化する必要があります。その後、attach() ルーチンは gld_register() を呼び出して、ドライバを GLDv2 モジュールとリンクします。ドライバでは必要に応じてレジスタをマップし、完全に初期化して、gld_register() を呼び出す前に割り込みを受け付けるように準備してください。attach(9E ) 関数は割り込みを追加しますが、デバイスによってこれらの割り込みを生成させてはなりません。ドライバでは、ハードウェアが静止状態であることを保証するために、gld_register() を呼び出す前にハードウェアをリセットしてください。gld_register() が呼び出される前にデバイスが割り込みを生成する可能性がある状態にデバイスが陥らないようにする必要があります。デバイスはあとから、GLDv2 がドライバの gldm_start() エントリポイント (gld (9E) のマニュアルページで説明) を呼び出したときに起動されます。gld_register() が成功したあとであれば、GLDv2 によって gld(9E) エントリポイントをいつでも呼び出すことができます。

gld_register() が成功した場合、attach(9E) ルーチンは DDI_SUCCESS を返します。gld_register() が失敗した場合、DDI_FAILURE が返されます。エラーが発生した場合、attach(9E) ルーチンは、gld_register() が呼び出される前に割り当てられたすべてのリソースを解放します。さらにその後、attach ルーチンは DDI_FAILURE を返します。エラーの起きた macinfo 構造体は決して再利用しないでください。そのような構造体は、gld_mac_free() を使用して解放してください。

detach(9E) 関数は、gld_unregister() を呼び出すことによって、ドライバを GLDv2 から登録解除することを試みます。gld_unregister() の詳細は、gld(9F) のマニュアルページを参照してください。detach(9E) ルーチンは ddi_get_driver_private(9F) を使用することで、必要な gld_mac_info(9S) 構造体へのポインタをデバイスの非公開データから取得できます。gld_unregister() は、ドライバを切り離すことのできない特定の条件をチェックします。チェックに失敗した場合、gld_unregister()DDI_FAILURE を返します。この場合、ドライバの detach (9E) ルーチンはデバイスを動作状態にしたまま DDI_FAILURE を返す必要があります。

チェックに成功した場合、gld_unregister() はデバイスの割り込み中止を確認します。必要に応じて、ドライバの gldm_stop() ルーチンが呼び出されます。ドライバは GLDv2 フレームワークからリンク解除され、その後、gld_unregister()DDI_SUCCESS を返します。この場合、detach(9E) ルーチンは割り込みを削除し、attach(9E) ルーチンで割り当てられたすべての macinfo データ構造体を gld_mac_free() を使用して解放します。その後、detach() ルーチンは DDI_SUCCESS を返します。ルーチンでは gld_mac_free() を呼び出す前に割り込みを削除する必要があります。

GLDv2 のネットワーク統計情報

Oracle Solaris ネットワークドライバは統計情報変数を実装する必要があります。GLDv2 はいくつかのネットワーク統計情報を集計しますが、その他の統計情報は GLDv2 ベースのドライバによって計測される必要があります。GLDv2 は、GLDv2 ベースのドライバによる、標準的なネットワークドライバ統計情報の報告をサポートします。GLDv2 は kstat(7D) および kstat(9S) メカニズムを使用して統計情報を報告します。DLPI コマンド DL_GET_STATISTICS_REQ を使用して現在の統計情報カウンタを取得することもできます。すべての統計情報は符号なしで管理されます。特に指定のないかぎり、統計情報は 32 ビットです。

GLDv2 は次の統計情報を管理および報告します。

rbytes64

インタフェース上で正常に受信された合計バイト数。64 ビット統計情報を格納します。

rbytes

インタフェース上で正常に受信された合計バイト数。

obytes64

インタフェース上で転送を要求した合計バイト数。64 ビット統計情報を格納します。

obytes

インタフェース上で転送を要求した合計バイト数。

ipackets64

インタフェース上で正常に受信された合計パケット数。64 ビット統計情報を格納します。

ipackets

インタフェース上で正常に受信された合計パケット数。

opackets64

インタフェース上で転送を要求した合計パケット数。64 ビット統計情報を格納します。

opackets

インタフェース上で転送を要求した合計パケット数。

multircv

グループアドレスや機能アドレスを含む、正常に受信されたマルチキャストパケット数 (long)。

multixmt

グループアドレスや機能アドレスを含む、転送が要求されたマルチキャストパケット数 (long)。

brdcstrcv

正常に受信されたブロードキャストパケット数 (long)。

brdcstxmt

転送を要求したブロードキャストパケット数 (long)。

unknowns

どのストリームにも受け入れられなかった有効受信パケット数 (long)。

noxmtbuf

転送バッファーがビジーだったか、転送用にバッファーを割り当てることができなかったため出力時に破棄されたパケット数 (long)。

blocked

キューがフロー制御されていたため受信パケットをストリームに入れることができなかった回数 (long)。

xmtretry

リソース不足のため遅延されたあとに転送が再試行された回数 (long)。

promisc

インタフェースの現在の「プロミスキュアス」状態 (文字列)。

デバイス依存ドライバは、次の統計情報を追跡し、インスタンスごとに専用の構造体に格納します。統計情報を報告するために、GLDv2 はドライバの gldm_get_stats() エントリポイントを呼び出します。gldm_get_stats() はその後、gld_stats(9S) 構造体内のデバイス固有の統計情報を更新します。詳細は、gldm_get_stats(9E) のマニュアルページを参照してください。GLDv2 はその後、次に示す名前付き統計情報変数を使用して、更新された統計情報を報告します。

ifspeed

インタフェースの現在の推定帯域幅 (ビット/秒)。64 ビット統計情報を格納します。

media

デバイスで使用している現在のメディアタイプ (文字列)。

intr

割り込みハンドラが呼び出されて割り込みが発生した回数 (long)。

norcvbuf

受信用バッファーを割り当てることができなかったために、有効な着信パケットが破棄されたことが判明している回数 (long)。

ierrors

受信されたがエラーにより処理できなかった合計パケット数 (long)。

oerrors

エラーが原因で正常に転送されなかった合計パケット数 (long)。

missed

受信時にハードウェアによってドロップされたことが判明しているパケット数 (long)。

uflo

転送時に FIFO がアンダーフローした回数 (long)。

oflo

受信中に受信側がオーバーフローした回数 (long)。

次の統計情報グループは、DL_ETHER 型のネットワークに適用されます。これらの統計情報は、前述のように、そのタイプのデバイス固有ドライバによって管理されます。

align_errors

受信時にフレームエラーが発生した (整数個のオクテットが含まれていなかった) パケット数 (long)。

fcs_errors

受信時に CRC エラーが記録されたパケット数 (long)。

duplex

インタフェースの現在の二重モード (文字列)。

carrier_errors

転送試行時にキャリアが失われたか、または検出されなかった回数 (long)。

collisions

転送中の Ethernet 衝突数 (long)。

ex_collisions

転送時に発生した衝突が多すぎて、転送エラーとなったフレーム数 (long)。

tx_late_collisions

遅れて (512 ビットタイム) 発生した転送衝突の回数 (long)。

defer_xmts

衝突は発生しなかったが、メディアがビジー状態だったために初回の転送試行が遅延されたパケット数 (long)。

first_collisions

衝突が 1 回だけ発生したが正常に転送されたパケット数。

multi_collisions

複数の衝突が発生したが正常に転送されたパケット数。

sqe_errors

SQE テストエラーが報告された回数。

macxmt_errors

キャリアエラーと衝突エラー以外の転送 MAC エラーが発生したパケット数。

macrcv_errors

align_errorsfcs_errors、および toolong_errors 以外の MAC エラーが発生した受信パケット数。

toolong_errors

最大許容長を超えていた受信パケット数。

runt_errors

最小許容長に満たなかった受信パケット数 (long )。

次の統計情報グループは、DL_TPR タイプのネットワークに適用されます。これらの統計情報は、前述のように、そのタイプのデバイス固有ドライバによって管理されます。

line_errors

非データビットまたは FCS エラーのあった受信パケット数。

burst_errors

ハーフビットタイマー 5 回の間に変位が検出されなかったことが検出された回数。

signal_losses

リングでシグナル損失状態が検出された回数。

ace_errors

A と C がともに 0 の AMP または SMP フレームのあとに、AMP フレームが介在することなく別の SMP フレームが続いた回数。

internal_errors

ステーションが内部エラーを認識した回数。

lost_frame_errors

転送中に TRR タイマーが期限切れになった回数。

frame_copied_errors

このステーション宛てのフレームが、FS フィールドの「A」ビットを 1 に設定して受信された回数。

token_errors

アクティブモニターとして動作しているステーションが、トークンの転送を必要とするエラー状態を認識した回数。

freq_errors

着信シグナルの周波数が予期された周波数と異なっていた回数。

次の統計情報グループは、DL_FDDI タイプのネットワークに適用されます。これらの統計情報は、前述のように、そのタイプのデバイス固有ドライバによって管理されます。

mac_errors

別の MAC ではエラーが検出されず、この MAC ではエラーが検出されたフレーム数。

mac_lost_errors

フレームが取り除かれるなどのフォーマットエラーが発生した受信フレーム数。

mac_tokens

制限なしトークンと制限付きトークンを合計した受信トークン数。

mac_tvx_expired

TVX が期限切れになった回数。

mac_late

この MAC のリセット後またはトークン受信後の TRT 期限切れの回数。

mac_ring_ops

リングが「Ring Not Operational」状態から「Ring Operational」状態になった回数。

GLDv2 の宣言とデータ構造体

このセクションでは、gld_mac_info (9S) および gld_stats 構造体について説明します。

gld_mac_info 構造体

GLDv2 MAC 情報 (gld_mac_info) 構造体は、デバイス固有ドライバを GLDv2 とリンクするメインデータインタフェースです。この構造体には、GLDv2 に必要なデータと、追加の省略可能なドライバ固有情報構造体へのポインタが含まれています。

gld_mac_info 構造体は gld_mac_alloc() を使用して割り当てます。構造体を解放するには gld_mac_free() を使用します。この構造体の長さは Oracle Solaris OS、GLDv2、またはその両方のリリースによって異なる可能性があるため、ドライバ側でこの構造体の長さを想定してはいけません。GLDv2 専用であり、このドキュメントに記載されていない構造体のメンバーを、デバイス固有ドライバによって設定したり読み取ったりしないでください。

gld_mac_info(9S) 構造体には次のフィールドが含まれています。

caddr_t              gldm_private;              /* Driver private data */
int                  (*gldm_reset)();           /* Reset device */
int                  (*gldm_start)();           /* Start device */
int                  (*gldm_stop)();            /* Stop device */
int                  (*gldm_set_mac_addr)();    /* Set device phys addr */
int                  (*gldm_set_multicast)();   /* Set/delete multicast addr */
int                  (*gldm_set_promiscuous)(); /* Set/reset promiscuous mode */
int                  (*gldm_send)();            /* Transmit routine */
uint_t               (*gldm_intr)();            /* Interrupt handler */
int                  (*gldm_get_stats)();       /* Get device statistics */
int                  (*gldm_ioctl)();           /* Driver-specific ioctls */
char                 *gldm_ident;               /* Driver identity string */
uint32_t             gldm_type;                 /* Device type */
uint32_t             gldm_minpkt;               /* Minimum packet size */
                                                /* accepted by driver */
uint32_t             gldm_maxpkt;               /* Maximum packet size */
                                                /* accepted by driver */
uint32_t             gldm_addrlen;              /* Physical address length */
int32_t              gldm_saplen;               /* SAP length for DL_INFO_ACK */
unsigned char        *gldm_broadcast_addr;      /* Physical broadcast addr */
unsigned char        *gldm_vendor_addr;         /* Factory MAC address */
t_uscalar_t          gldm_ppa;                  /* Physical Point of */
                                                /* Attachment (PPA) number */
dev_info_t           *gldm_devinfo;             /* Pointer to device's */
                                                /* dev_info node */
ddi_iblock_cookie_t  gldm_cookie;               /* Device's interrupt */
                                                /* block cookie */

構造体の gldm_private メンバーはデバイスドライバから認識できます。gldm_private はデバイス固有のドライバ専用でもあります。gldm_private が GLDv2 によって使用または変更されることはありません。gldm_private は従来、非公開データへのポインタとして使用され、ドライバによって定義と割り当ての両方が行われるインスタンスごとのデータ構造体を指し示します。

次のグループの構造体メンバーは、gld_register() を呼び出す前にドライバによって設定する必要があり、その後はドライバによって変更しないでください。gld_register() は構造体メンバーの値を使用またはキャッシュする可能性があるため、gld_register() の呼び出し後にドライバによって値が変更されると予期しない結果を招くことがあります。これらの構造体の詳細は、gld(9E) のマニュアルページを参照してください。

gldm_reset

ドライバのエントリポイントへのポインタ。

gldm_start

ドライバのエントリポイントへのポインタ。

gldm_stop

ドライバのエントリポイントへのポインタ。

gldm_set_mac_addr

ドライバのエントリポイントへのポインタ。

gldm_set_multicast

ドライバのエントリポイントへのポインタ。

gldm_set_promiscuous

ドライバのエントリポイントへのポインタ。

gldm_send

ドライバのエントリポイントへのポインタ。

gldm_intr

ドライバのエントリポイントへのポインタ。

gldm_get_stats

ドライバのエントリポイントへのポインタ。

gldm_ioctl

ドライバのエントリポイントへのポインタ。このポインタは null にすることができます。

gldm_ident

デバイスの簡単な説明を含む文字列へのポインタ。このポインタは、システムメッセージでデバイスを識別するために使用されます。

gldm_type

ドライバが扱うデバイスのタイプ。GLDv2 では現在、次の値がサポートされています。

  • DL_ETHER (ISO 8802-3 (IEEE 802.3) および Ethernet Bus)

  • DL_TPR (IEEE 802.5 Token Passing Ring)

  • DL_FDDI (ISO 9314-2 Fibre Distributed Data Interface)

GLDv2 を正しく動作させるには、この構造体メンバーを適切に設定する必要があります。

gldm_minpkt

最小の Service Data Unit サイズ: デバイスが転送できる最小のパケットサイズであり、MAC ヘッダーを含みません。必要なパディングをデバイス固有ドライバが処理する場合、このサイズは 0 に設定できます。

gldm_maxpkt

最大の Service Data Unit サイズ: デバイスが転送できる最大のパケットサイズであり、MAC ヘッダーを含みません。Ethernet の場合、この数値は 1500 です。

gldm_addrlen

デバイスが処理する物理アドレスの長さ (バイト単位)。Ethernet、トークンリング、および FDDI の場合、この構造体メンバーの値は 6 です。

gldm_saplen

ドライバが使用する SAP アドレスの長さ (バイト単位)。GLDv2 ベースのドライバの場合、この長さは常に -2 に設定されます。-2 の長さは、2 バイトの SAP 値がサポートされること、および DLSAP アドレスで物理アドレスの後ろに SAP が入ることを示します。詳細は、DLPI 仕様の Appendix A.2「Message DL_INFO_ACK」を参照してください。

gldm_broadcast_addr

転送に使用するブロードキャストアドレスが格納されたバイト配列の長さ gldm_addrlen へのポインタ。ドライバはブロードキャストアドレスを保持する領域を提供し、その領域に適切な値を入れ、そのアドレスを指し示すように gldm_broadcast_addr を設定する必要があります。Ethernet、トークンリング、および FDDI の場合、ブロードキャストアドレスは通常、0xFF-FF-FF-FF-FF-FF です。

gldm_vendor_addr

ベンダーが提供するデバイスのネットワーク物理アドレスが格納されたバイト配列の長さ gldm_addrlen へのポインタ。ドライバはこのアドレスを保持する領域を提供し、デバイスから読み取った情報をその領域に入れ、そのアドレスを指し示すように gldm_vendor_addr を設定する必要があります。

gldm_ppa

デバイスのこのインスタンスに対応する PPA 番号。PPA 番号は常に、ddi_get_instance(9F) から返されるインスタンス番号に設定される必要があります。

gldm_devinfo

このデバイスに対応する dev_info ノードへのポインタ。

gldm_cookie

次のいずれかのルーチンによって返される割り込みブロック cookie。

この cookie は、gld_recv() の呼び出し元になる、デバイスの受信割り込みに対応する必要があります。

gld_stats 構造体

gldm_get_stats() を呼び出したあとに、GLDv2 ベースのドライバは gld_stats 構造体を使用して、統計情報および状態情報を GLDv2 に伝達します。gld (9E) および gld (7D) のマニュアルページを参照してください。この構造体のメンバーは、GLDv2 ベースのドライバによって設定され、GLDv2 が統計情報を報告するときに使用されます。次の表では、GLDv2 によって報告される統計情報変数の名前をコメントで示しています。各統計情報の意味の詳しい説明は、gld(7D) のマニュアルページを参照してください。

ドライバではこの構造体の長さについて何らかの想定を行ってはなりません。構造体の長さは Oracle Solaris OS、GLDv2、またはその両方のリリースによって異なる場合があります。GLDv2 専用であり、このドキュメントに記載されていない構造体のメンバーを、デバイス固有ドライバによって設定したり読み取ったりしないでください。

構造体の次のメンバーは、すべてのメディアタイプに対して定義されます。

uint64_t    glds_speed;                   /* ifspeed */
uint32_t    glds_media;                   /* media */
uint32_t    glds_intr;                    /* intr */
uint32_t    glds_norcvbuf;                /* norcvbuf */
uint32_t    glds_errrcv;                  /* ierrors */
uint32_t    glds_errxmt;                  /* oerrors */
uint32_t    glds_missed;                  /* missed */
uint32_t    glds_underflow;               /* uflo */
uint32_t    glds_overflow;                /* oflo */

構造体の次のメンバーは、メディアタイプ DL_ETHER に対して定義されます。

uint32_t    glds_frame;                   /* align_errors */
uint32_t    glds_crc;                     /* fcs_errors */
uint32_t    glds_duplex;                  /* duplex */
uint32_t    glds_nocarrier;               /* carrier_errors */
uint32_t    glds_collisions;              /* collisions */
uint32_t    glds_excoll;                  /* ex_collisions */
uint32_t    glds_xmtlatecoll;             /* tx_late_collisions */
uint32_t    glds_defer;                   /* defer_xmts */
uint32_t    glds_dot3_first_coll;         /* first_collisions */
uint32_t    glds_dot3_multi_coll;         /* multi_collisions */
uint32_t    glds_dot3_sqe_error;          /* sqe_errors */
uint32_t    glds_dot3_mac_xmt_error;      /* macxmt_errors */
uint32_t    glds_dot3_mac_rcv_error;      /* macrcv_errors */
uint32_t    glds_dot3_frame_too_long;     /* toolong_errors */
uint32_t    glds_short;                   /* runt_errors */

構造体の次のメンバーは、メディアタイプ DL_TPR に対して定義されます。

uint32_t    glds_dot5_line_error          /* line_errors */
uint32_t    glds_dot5_burst_error         /* burst_errors */
uint32_t    glds_dot5_signal_loss         /* signal_losses */
uint32_t    glds_dot5_ace_error           /* ace_errors */
uint32_t    glds_dot5_internal_error      /* internal_errors */
uint32_t    glds_dot5_lost_frame_error    /* lost_frame_errors */
uint32_t    glds_dot5_frame_copied_error  /* frame_copied_errors */
uint32_t    glds_dot5_token_error         /* token_errors */
uint32_t    glds_dot5_freq_error          /* freq_errors */

構造体の次のメンバーは、メディアタイプ DL_FDDI に対して定義されます。

uint32_t    glds_fddi_mac_error;          /* mac_errors */
uint32_t    glds_fddi_mac_lost;           /* mac_lost_errors */
uint32_t    glds_fddi_mac_token;          /* mac_tokens */
uint32_t    glds_fddi_mac_tvx_expired;    /* mac_tvx_expired */
uint32_t    glds_fddi_mac_late;           /* mac_late */
uint32_t    glds_fddi_mac_ring_op;        /* mac_ring_ops */

前出の統計情報変数のほとんどは、特定のイベントが検出された回数を示すカウンタです。次の統計情報は回数を表しません。

glds_speed

インタフェースの現在の推定帯域幅 (ビット/秒)。帯域幅の変動のないインタフェース、または正確な推定ができないインタフェースの場合、このオブジェクトには公称の帯域幅が入ります。

glds_media

ハードウェアで使用されているメディア (配線) またはコネクタのタイプ。次のメディア名がサポートされています。

  • GLDM_AUI

  • GLDM_BNC

  • GLDM_TP

  • GLDM_10BT

  • GLDM_100BT

  • GLDM_100BTX

  • GLDM_100BT4

  • GLDM_RING4

  • GLDM_RING16

  • GLDM_FIBER

  • GLDM_PHYMII

  • GLDM_UNKNOWN

glds_duplex

インタフェースの現在の二重状態。サポートされる値は GLD_DUPLEX_HALF および GLD_DUPLEX_FULL です。GLD_DUPLEX_UNKNOWN を指定することもできます。

GLDv2 関数の引数

GLDv2 ルーチンでは次の引数が使用されます。

macinfo

gld_mac_info(9S) 構造体へのポインタ。

macaddr

有効な MAC アドレスが格納された文字配列の先頭へのポインタ。配列の長さはドライバによって、gld_mac_info(9S) 構造体の gldm_addrlen 要素で指定されます。

multicastaddr

マルチキャストアドレス、グループアドレス、または機能アドレスが格納された文字配列の先頭へのポインタ。配列の長さはドライバによって、gld_mac_info(9S) 構造体の gldm_addrlen 要素で指定されます。

multiflag

マルチキャストアドレスの受信を有効にするか無効にするかを示すフラグ。この引数に指定する値は GLD_MULTI_ENABLE または GLD_MULTI_DISABLE です。

promiscflag

有効にするプロミスキュアス (promiscuous) モードが存在する場合に、その種類を示すフラグ。この引数に指定する値は GLD_MAC_PROMISC_PHYSGLD_MAC_PROMISC_MULTI、または GLD_MAC_PROMISC_NONE です。

mp

gld_ioctl() は、実行する ioctl が格納されている STREAMS メッセージブロックへのポインタとして mp を使用します。gldm_send() は、転送するパケットが格納されている STREAMS メッセージブロックへのポインタとして mp を使用します。gld_recv() は、受信したパケットが格納されているメッセージブロックへのポインタとして mp を使用します。

stats

統計情報カウンタの現在値が入る gld_stats (9S) 構造体へのポインタ。

q

ioctl への応答に使用される queue(9S) 構造体へのポインタ。

dip

デバイスの dev_info 構造体へのポインタ。

name

デバイスのインタフェース名。

GLDv2 のエントリポイント

エントリポイントは、GLDv2 とのインタフェースとして設計されたデバイス固有ネットワークドライバによって実装される必要があります。

gld_mac_info(9S) 構造体は、デバイス固有ドライバと GLDv2 モジュール間の通信のためのメイン構造体です。gld(7D) のマニュアルページを参照してください。この構造体の一部の要素は、ここで説明するエントリポイントへの関数ポインタです。デバイス固有ドライバは、gld_register() を呼び出す前に、その attach(9E) ルーチンでこれらの関数ポインタを初期化する必要があります。

gldm_reset() エントリポイント

int prefix_reset(gld_mac_info_t *macinfo);

gldm_reset() は、ハードウェアを初期状態にリセットします。

gldm_start() エントリポイント

int prefix_start(gld_mac_info_t *macinfo);

gldm_start() は、デバイスによる割り込みの生成を有効にします。また gldm_start() は、gld_recv() を呼び出して受信データパケットを GLDv2 に配信できるようにドライバを準備します。

gldm_stop() エントリポイント

int prefix_stop(gld_mac_info_t *macinfo);

gldm_stop() は、デバイスによる割り込みの生成を無効にし、デバイスが gld_recv() を呼び出してデータパケットを GLDv2 に配信しないようにします。GLDv2 は、デバイスがこれ以上割り込みをかけないようにするために、gldm_stop() ルーチンを利用します。gldm_stop() による処理は失敗してはなりません。この関数は常に GLD_SUCCESS を返します。

gldm_set_mac_addr() エントリポイント

int prefix_set_mac_addr(gld_mac_info_t *macinfo, unsigned char *macaddr);

gldm_set_mac_addr() は、ハードウェアがデータの受信に使用する物理アドレスを設定します。この関数は、渡された MAC アドレス macaddr を介してデバイスをプログラミングできるようにします。要求にこたえるために十分なリソースが現在利用できない場合、gldm_set_mac_add() は GLD_NORESOURCES を返します。要求された関数がサポートされていない場合、gldm_set_mac_add() は GLD_NOTSUPPORTED を返す必要があります。

gldm_set_multicast() エントリポイント

int prefix_set_multicast(gld_mac_info_t *macinfo, 
     unsigned char *multicastaddr, int multiflag);

gldm_set_multicast() は、特定のマルチキャストアドレスのデバイスレベルでの受信を有効または無効にします。3 番目の引数 multiflagGLD_MULTI_ENABLE に設定した場合、gldm_set_multicast() はマルチキャストアドレス宛てのパケットを受信するようにインタフェースを設定します。gldm_set_multicast() は、2 番目の引数によって指示されたマルチキャストアドレスを使用します。multiflagGLD_MULTI_DISABLE に設定した場合、ドライバは指定されたマルチキャストアドレスの受信を無効にできます。

この関数は、GLDv2 でマルチキャストアドレス、グループアドレス、または機能アドレスの受信を有効または無効にしようとするたびに呼び出されます。GLDv2 は、デバイスがどのような方法でマルチキャストをサポートするのか、またどのような方法でこの関数を呼び出して特定のマルチキャストアドレスを有効または無効にするのかについて、何の想定も行いません。デバイスによっては、ハッシュアルゴリズムとビットマスクを使用して、マルチキャストアドレスの集合を有効にする場合があります。この手順は認められており、GLDv2 が余分なパケットをフィルタリングして除外します。1 つのアドレスを無効にするとデバイスレベルで複数のアドレスが無効になる可能性がある場合、デバイスドライバで必要な情報を保持するようにしてください。これによって、GLDv2 が有効にしたが無効にはしていないアドレスを無効にすることを防ぎます。

gldm_set_multicast() は、すでに有効になっている特定のマルチキャストアドレスを有効にするために呼び出されることはありません。同様に、現在有効になっていないアドレスを無効にするために gldm_set_multicast () が呼び出されることもありません。GLDv2 は同じマルチキャストアドレスに対する複数の要求を追跡します。GLDv2 がドライバのエントリポイントを呼び出すのは、特定のマルチキャストアドレスの有効化を求める最初の要求、または無効化を求める最後の要求が行われたときだけです。その時点でリソースが不足していて要求を満たすことができない場合、この関数は GLD_NORESOURCES を返します。要求された関数がサポートされていない場合、この関数は GLD_NOTSUPPORTED を返します。

gldm_set_promiscuous() エントリポイント

int prefix_set_promiscuous(gld_mac_info_t *macinfo, int promiscflag);

gldm_set_promiscuous() は、プロミスキュアス (promiscuous) モードを有効または無効にします。この関数は、GLDv2 がメディア上のすべてのパケットの受信を有効または無効にしようとするたびに呼び出されます。関数の対象範囲を、メディア上のマルチキャストパケットに限定することもできます。2 番目の引数 promiscflag の値を GLD_MAC_PROMISC_PHYS に設定すると、この関数は物理レベルのプロミスキュアス (promiscuous) モードを有効にします。物理レベルのプロミスキュアス (promiscuous) モードが有効になると、メディア上のすべてのパケットが受信されます。promiscflagGLD_MAC_PROMISC_MULTI に設定すると、すべてのマルチキャストパケットの受信が有効になります。promiscflagGLD_MAC_PROMISC_NONE に設定すると、プロミスキュアス (promiscuous) モードが無効になります。

プロミスキュアス (promiscuous) マルチキャストモードの場合、マルチキャスト限定のプロミスキュアス (promiscuous) モードを備えていないデバイス用のドライバでは、デバイスを物理プロミスキュアス (promiscuous) モードに設定する必要があります。これにより、すべてのマルチキャストパケットの受信が保証されます。この場合、ルーチンは GLD_SUCCESS を返します。GLDv2 ソフトウェアが余分なパケットをフィルタリングして除外します。その時点でリソースが不足していて要求を満たすことができない場合、この関数は GLD_NORESOURCES を返します。要求された関数がサポートされていない場合、gld_set_promiscuous() 関数は GLD_NOTSUPPORTED を返します。

上位互換性のために、gldm_set_promiscuous() ルーチンは、promiscflag の認識できない値をすべて GLD_MAC_PROMISC_PHYS として扱います。

gldm_send() エントリポイント

int prefix_send(gld_mac_info_t *macinfo, mblk_t *mp);

gldm_send() は、転送するパケットをデバイスのキューに入れます。このルーチンには、送信するパケットが格納された STREAMS メッセージを渡します。メッセージには複数のメッセージブロックが含まれる場合があります。send() ルーチンは、メッセージのすべてのメッセージブロックをたどって、送信パケット全体にアクセスする必要があります。長さが 0 のメッセージ継続ブロックがチェーンに含まれる場合に、そのブロックを認識してスキップするようにドライバを準備してください。またドライバでは、パケットが最大許容パケットサイズを超えないことをチェックしてください。ドライバは必要に応じて、最小許容パケットサイズにパケットをパディングする必要があります。送信ルーチンがパケットを正常に転送するか、またはキューに入れた場合、GLD_SUCCESS が返されます。

パケットの転送がただちに受け入れられなかった場合、送信ルーチンは GLD_NORESOURCES を返します。この場合、GLDv2 はあとで再試行します。gldm_send()GLD_NORESOURCES を返した場合、あとでリソースが利用可能になった時点でドライバは gld_sched() を呼び出す必要があります。この gld_sched() の呼び出しは、ドライバが以前に転送キューに入れることができなかったパケットを再試行するよう GLDv2 に通知します (ドライバの gldm_stop() ルーチンが呼び出されても、ドライバが gldm_send() ルーチンから GLD_NORESOURCES を返すまで、ドライバはこの義務を免除されます。ただし、gld_sched() を余分に呼び出しても、誤った動作になることはありません)。

ドライバの送信ルーチンが GLD_SUCCESS を返した場合、メッセージが不要になった時点でドライバはそのメッセージを解放する必要があります。ハードウェアが DMA を使用してデータを直接読み取る場合、ドライバはハードウェアが完全にデータを読み取るまでメッセージを解放してはなりません。この場合、ドライバは割り込みルーチンでメッセージを解放できます。ドライバは別の方法として、将来の送信操作の開始時にバッファーを再要求することもできます。送信ルーチンが GLD_SUCCESS 以外に何も返さない場合、ドライバはメッセージを解放してはいけません。ネットワークまたはリンクパートナーとの物理接続がないときに gldm_send() が呼び出された場合は、GLD_NOLINK を返します。

gldm_intr() エントリポイント

int prefix_intr(gld_mac_info_t *macinfo);

gldm_intr() は、デバイスが割り込みをかけた可能性があるときに呼び出されます。割り込みをほかのデバイスと共有している可能性があるので、ドライバはデバイスのステータスを調べ、実際に割り込みが発生したかどうかを判別する必要があります。ドライバが制御しているデバイスで割り込みが起きなかった場合、このルーチンは DDI_INTR_UNCLAIMED を返す必要があります。それ以外の場合は、割り込みを処理して DDI_INTR_CLAIMED を返す必要があります。パケットの正常な受信によって割り込みが発生した場合、このルーチンは受信パケットを M_DATA 型の STREAMS メッセージに格納し、メッセージを gld_recv() に渡します。

gld_recv() は、着信パケットをアップストリーム方向に、ネットワークプロトコルスタックの該当する次の層に渡します。gld_recv() を呼び出す前に、ルーチンは STREAMS メッセージの b_rptr および b_wptr メンバーを正しく設定する必要があります。

ドライバでは、gld_recv() の呼び出し中に mutex ロックまたはまたはその他のロックを保持しないようにしてください。特に、転送スレッドが使用する可能性のあるロックが、gld_recv() の呼び出し中に保持されていてはなりません。場合によっては、gld_recv() を呼び出す割り込みスレッドが発信パケットを送信し、結果的にドライバの gldm_send() ルーチンが呼び出されてしまうためです。gld_recv() の呼び出し時に gldm_intr() によって保持されている mutex を gldm_send() が取得しようとすると、mutex エントリの再帰性が原因でパニックが発生します。gld_recv() の呼び出しでドライバが保持する mutex をほかのドライバのエントリポイントが取得しようとすると、デッドロックに陥る可能性があります。

割り込みコードは、どのようなエラーの発生時にも統計情報カウンタを 1 増やします。このエラーには、受信データに必要なバッファーの割り当て失敗に加えて、CRC エラーやフレームエラーなどのハードウェア固有エラーが含まれています。

gldm_get_stats() エントリポイント

int prefix_get_stats(gld_mac_info_t *macinfo, struct gld_stats *stats);

gldm_get_stats() は、ハードウェア、ドライバ専用カウンタ、またはその両方から統計情報を収集し、stats で指し示された gld_stats(9S) 構造体を更新します。このルーチンは、統計情報要求を受けたときに GLDv2 によって呼び出されます。GLDv2 は統計情報要求に対する応答を作成する前に、gldm_get_stats() メカニズムを使用してデバイス依存の統計情報をドライバから取得します。定義された統計情報カウンタの詳細は、gld_stats(9S)gld(7D)、およびqreply(9F) のマニュアルページを参照してください。

gldm_ioctl() エントリポイント

int prefix_ioctl(gld_mac_info_t *macinfo, queue_t *q, mblk_t *mp);

gldm_ioctl() は、デバイス固有の ioctl コマンドを実装します。ドライバで ioctl 関数を実装しない場合、この要素は null として指定できます。ドライバはメッセージブロックを ioctl 応答メッセージに変換し、GLD_SUCCESS を返す前に qreply(9F) 関数を呼び出す必要があります。この関数は常に GLD_SUCCESS を返します。ドライバでは必要に応じて、qreply (9F) に渡すメッセージでエラーを報告してください。gldm_ioctl 要素が NULL として指定されている場合、GLDv2 は M_IOCNAK 型のメッセージを EINVAL エラーとともに返します。

GLDv2 の戻り値

GLDv2 の一部のエントリポイント関数は、これまでに説明した制限事項に従い、次の値を返す可能性があります。

GLD_BADARG

誤ったマルチキャストアドレス、誤った MAC アドレス、誤ったパケットなどの不適切な引数を関数が検出した場合

GLD_FAILURE

ハードウェア障害の場合

GLD_SUCCESS

成功した場合

GLDv2 のサービスルーチン

このセクションでは、GLDv2 のサービスルーチンの構文および説明を示します。

gld_mac_alloc() 関数

gld_mac_info_t *gld_mac_alloc(dev_info_t *dip);

gld_mac_alloc() は新しい gld_mac_info(9S) 構造体を割り当て、その構造体へのポインタを返します。構造体の GLDv2 専用要素の一部は、gld_mac_alloc() が戻る前に初期化される可能性があります。ほかのすべての要素は 0 に初期化されます。デバイスドライバは、gld_mac_info 構造体へのポインタを gld_register() に渡す前に、gld_mac_info(9S) のマニュアルページの説明に従って一部の構造体メンバーを初期化する必要があります。

gld_mac_free() 関数

void gld_mac_free(gld_mac_info_t *macinfo);

gld_mac_free() は、以前に gld_mac_alloc() によって割り当てられた gld_mac_info(9S) 構造体を解放します。

gld_register() 関数

int gld_register(dev_info_t *dip, char *name, gld_mac_info_t *macinfo);

gld_register() は、デバイスドライバの attach(9E) ルーチンから呼び出されます。gld_register() は、GLDv2 ベースのデバイスドライバを GLDv2 フレームワークとリンクします。gld_register() を呼び出す前に、デバイスドライバの attach (9E) ルーチンは gld_mac_alloc() を使用して gld_mac_info(9S ) 構造体を割り当ててから、いくつかの構造体要素を初期化します。詳細は、gld_mac_info (9S) を参照してください。gld_register() の呼び出しが成功すると、次の処理が実行されます。

  • デバイス固有ドライバを GLDv2 システムとリンクする

  • ddi_set_driver_private(9F) を使用して、デバイス固有ドライバの非公開データポインタが macinfo 構造体を指し示すように設定する

  • マイナーデバイスノードを作成する

  • DDI_SUCCESS を返す

gld_register() に渡されるデバイスインタフェース名は、ファイルシステムに存在するドライバモジュールの名前と完全一致する必要があります。

gld_register() が成功した場合、ドライバの attach (9E) ルーチンは DDI_SUCCESS を返します。gld_register()DDI_SUCCESS を返さない場合、attach(9E) ルーチンは gld_register() を呼び出す前に、割り当て済みのリソースをすべて解放してから DDI_FAILURE を返します。

gld_unregister() 関数

int gld_unregister(gld_mac_info_t *macinfo);

gld_unregister() はデバイスドライバの detach(9E) 関数によって呼び出され、成功した場合に次のタスクを実行します。

  • 必要であればドライバの gldm_stop() ルーチンを呼び出して、デバイスの割り込みを確実に中止させる

  • マイナーデバイスノードを削除する

  • デバイス固有ドライバを GLDv2 システムからリンク解除する

  • DDI_SUCCESS を返す

gld_unregister()DDI_SUCCESS を返す場合、detach(9E) ルーチンは、attach(9E) ルーチンで割り当てられたデータ構造体があればすべて解放し (gld_mac_free() を使用して macinfo 構造体を解放)、DDI_SUCCESS を返します。gld_unregister()DDI_SUCCESS を返さない場合、ドライバの detach(9E) ルーチンは、デバイスを動作状態にしたまま DDI_FAILURE を返す必要があります。

gld_recv() Function

void gld_recv(gld_mac_info_t *macinfo, mblk_t *mp);

gld_recv() はドライバの割り込みハンドラによって呼び出され、受信したパケットをアップストリームに渡します。ドライバは raw パケットが格納された M_DATA 型の STREAMS メッセージを作成して渡す必要があります。gld_recv () は、どの STREAMS キューがパケットのコピーを受信するかを調べ、必要に応じてパケットを複製します。gld_recv() はその後、必要に応じて DL_UNITDATA_IND メッセージをフォーマットし、データをすべての該当するストリームに渡します。

ドライバでは、gld_recv() の呼び出し中に mutex ロックまたはまたはその他のロックを保持しないようにしてください。特に、転送スレッドが使用する可能性のあるロックが、gld_recv() の呼び出し中に保持されていてはなりません。場合によっては、gld_recv() を呼び出す割り込みスレッドが、発信パケットの送信を含む処理を実行します。パケット転送の結果として、ドライバの gldm_send() ルーチンが呼び出されてしまいます。gld_recv() の呼び出し時に gldm_intr() によって保持されている mutex を gldm_send() が取得しようとすると、mutex エントリの再帰性が原因でパニックが発生します。gld_recv() の呼び出しでドライバが保持する mutex をほかのドライバのエントリポイントが取得しようとすると、デッドロックに陥る可能性があります。

gld_sched() 関数

void gld_sched(gld_mac_info_t *macinfo);

gld_sched() はデバイスドライバによって呼び出され、停止されていたアウトバウンドパケットを再スケジューリングします。ドライバの gldm_send() ルーチンが GLD_NORESOURCES を返すたびに、ドライバは gld_sched() を呼び出して、以前に送信できなかったパケットを再試行するよう GLDv2 フレームワークに通知する必要があります。 リソースが利用可能になると、GLDv2 がドライバの gldm_send() ルーチンに発信パケットを渡す処理を再開するよう、ただちに gld_sched() が呼び出されます (ドライバの gldm_stop() ルーチンが呼び出される場合、gldm_send() から GLD_NORESOURCES が返されるまでの間、ドライバは再試行する必要はありません。ただし、gld_sched() を余分に呼び出しても、誤った動作になることはありません)。

gld_intr() 関数

uint_t gld_intr(caddr_t);

gld_intr() は GLDv2 のメイン割り込みハンドラです。gld_intr() は通常、デバイスドライバの ddi_add_intr(9F) 呼び出しで割り込みルーチンとして指定されます。割り込みハンドラへの引数は、ddi_add_intr(9F) の呼び出しで int_handler_arg として指定されます。この引数は gld_mac_info(9S) 構造体へのポインタである必要があります。gld_intr() は、該当する場合、デバイスドライバの gldm_intr() 関数を呼び出し、gld_mac_info (9S) 構造体にそのポインタを渡します。ただし、高レベル割り込みを使用する場合、ドライバは独自の上位割り込みハンドラを提供し、その中からソフト割り込みをトリガーする必要があります。この場合、gld_intr() は通常、ddi_add_softintr() の呼び出しでソフト割り込みハンドラとして指定されます。gld_intr() は、割り込みハンドラに適した値を返します。