Solaris 8 のソフトウェア開発 (追補)

Generic LAN ドライバ (GLD) の概要

GLD は、Solaris ローカルエリアネットワークデバイスドライバをサポートする、クローン化可能でロード可能なマルチスレッド化カーネルモジュールです。Solaris のローカルエリアネットワーク (LAN) デバイスドライバは、DLPI を使用してネットワークプロトコルスタックと通信する、STREAMS ベースのドライバです。これらのプロトコルスタックは、ネットワークドライバを使用して、ローカルエリアネットワーク上でパケットを送受信します。ネットワークデバイスドライバは、DDI/DKI 仕様、STREAMS 仕様、DLPI 仕様、およびデバイスそのもののプログラム式インタフェースの要件を満たすように実装する必要があります。

GLD には、Solaris LAN ドライバに必要な STREAMS および DLPI 機能の大部分が実装されています。いくつかの Solaris ネットワークドライバは GLD を使用して実装されています。

GLD を使用して実装された Solaris ネットワークドライバは、2 種類の部分で構成されます。STREAMS および DLPI インタフェースを扱う汎用コンポーネント、および特定のハードウェアデバイスを扱うデバイス固有のコンポーネントです。デバイス固有のモジュールは、GLD モジュール (/kernel/misc/gld に存在する) への依存を意味し、ドライバの attach(9E) 関数内から GLD に自身を登録します。正常に読み込まれると、ドライバは DLPI に準拠することになります。ドライバのデバイス固有の部分は、データを受信するとき、または GLD のサービスが必要になったときに、gld(9F) 関数を呼び出します。GLD は、デバイス固有のドライバが GLD に登録するときに提供したポインタを介して、デバイス固有のドライバの gld(9E) エントリポイントを呼び出します。gld_mac_info(9S) 構造体が GLD とデバイス固有のドライバ間のメインデータインタフェースです。

GLD 機能が現在サポートしているデバイスのタイプは、DL_ETHERDL_TPR、および DL_FDDI です。GLD ドライバは、フルフォームの MAC レイヤーパケットを処理することが想定されており、論理リンク制御 (LLC) の処理は想定されていません。

状況によっては、GLD 機能を使用しないで 、DLPI に完全に準拠したドライバを実装する場合もあるでしょう。これには、ISO 8802 スタイル (IEEE 802) ではない LAN デバイスの場合、または GLD ではサポートされないデバイスタイプまたは DLPI サービスが必要な場合、などがあります。

タイプ DL_ETHER : Ethernet V2 および ISO 8802-3 (IEEE 802.3)

タイプとして DL_ETHER が指定されたデバイスについては、GLD は Ethernet V2 と ISO 8802-3 (IEEE 802.3) の両方のパケット処理をサポートします。Ethernet V2 によって、データリンクサービスのユーザーは、プロバイダのプロトコルを特に知らなくても、さまざまな適合するデータリンクサービスプロバイダにアクセスして利用することができます。サービスアクセスポイント (SAP) は、ユーザーがサービスプロバイダと通信するときに通過するポイントです。

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

0 〜 1500 の範囲の type フィールドを持つメディアから受信されたフレームはすべて、8802-3 フレームとみなされ、8802-3 モードのオープンなすべての Stream (0 〜 255 の範囲の SAP 値に結合された Stream) にルーティングされます。8802-3 モードの Stream が複数ある場合、着信フレームがコピーされて、該当するそれぞれの Stream にルーティングされます。

1500 より大きい SAP 値 (Ethernet V2 モード) と結合された Stream は、Ethernet MAC ヘッダーの type 値が、Stream と結合された SAP 値と正確に一致する着信パケットを受信します。

タイプ DL_TPR および DL_FDDI : SNAP 処理

メディアタイプ DL_TPR および DL_FDDI については、GLD は 255 より大きい SAP 値と結合された Stream に、最小限の Sub-Net Access Protocol (SNAP) 処理を実装します。0 〜 255 の範囲の SAP 値は LLC SAP 値であり、メディアパケットフォーマットによって通常どおりに伝送されます。255 より大きい SAP 値には、LLC ヘッダーに従属し、16 ビット Ethernet V2 スタイルの SAP 値を伝送する SNAP ヘッダーが必要です。

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


AA AA 03 00 00 00 XX XX

XX XX は、Ethernet V2 スタイルの type に対応する 16 ビットの SAP を表します。これがサポートされる唯一の SNAP ヘッダーのクラスです。ゼロ以外の OUI フィールドおよび 03 以外の LLC 制御フィールドは、SAP 0xAA を持つ LLC パケットとみなされます。これ以外の SNAP フォーマットを使用するクライアントは、LLC を使用し、SAP 0xAA に結合する必要があります。

着信パケットは上記のフォーマットに当てはまるかどうかが検証されます。このフォーマットに当てはまるパケットは、そのパケットの 16 ビット SNAP タイプに結合された Stream と照合されるとともに、LLC SNAP SAP 0xAA と一致するとみなされます。

LLC SAP として受信されたパケットは、メディアタイプ DL_ETHER の箇所で説明したように、LLC SAP と結合されているすべての Stream に渡されます。

タイプ DL_TPR : ソースルーティング

タイプ DL_TPR デバイスについては、GLD は最小限のソースルーティングサポートを実装します。ソースルーティングにより、ブリッジングされたメディア上でパケットを送信するステーションは、ネットワーク上でパケットがたどるルートを決定づけるルーティング情報を (パケットの MAC ヘッダーに) 指定できます。

GLD が提供するソースルーティングは、ルートを学習し、可能性のある複数のルートについて情報を要求するように指示し、要求に応答し、使用できる複数のルートの中から選択する機能があります。さらに、発信パケットの MAC ヘッダーに Routing Information Fields を追加したり、着信パケット内のこのようなフィールドを認識したりします。

GLD のソースルーティングは、ISO 8802-2 (IEEE 802.2) の Section 9 で指定されている Route Determination Entity (RDE) を完全に実装するわけではありません。しかし、同じ (または縮約された) ネットワークに存在し得るソースルーティング実装方式と相互運用を行うように設計されています。

Style 1 および 2 のプロバイダ

GLD は、Style 1 および Style 2 のプロバイダを両方とも実装します。Physical Point of Attachment (PPA) は、システムが物理通信メディアと接続するポイントです。その物理メディア上の通信はすべて、PPA を通過します。Style 1 のプロバイダは、オープンされているメジャー/マイナーデバイスに基づいて、特定の PPA に Stream を接続します。Style 2 のプロバイダは、DLS ユーザーが DL_ATTACH_REQ を使用して必要な PPA を明示的に特定するよう要求します。その場合、open(9E) がユーザーと GLD 間の Stream を作成し、その後、DL_ATTACH_REQ が所定の PPA とその Stream を対応付けます。Style 2 はゼロのマイナー番号で示されます。マイナー番号がゼロ以外のデバイスノードがオープンしている場合、Style 1 が示され、対応する PPA はマイナー番号から 1 を差し引いたものになります。Style 1 と Style 2 が両方とも open の場合、デバイスはクローン化されます。

実装される DLPI プリミティブ

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


注 -

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


PPA と Stream を対応付けるために、DL_ATTACH_REQ プリミティブが呼び出されます。この要求は、Style 2 の DLS プロバイダが通信を行う物理メディアを特定するために必要です。完了すると、状態が DL_UNATTACHED から DL_UNBOUND に変わります。メッセージは 1 つの M_PROTO メッセージブロックで構成されます。ドライバを Style 1 モードで使用している場合は、この要求を発行できません。Style 1 を使用してオープンされた Stream は、オープンの完了時には PPA にすでに接続されているからです。

DL_DETACH_REQ プリミティブは、Stream から PPA を切り離すことを要求します。これが認められるのは、Stream が Style 2 を使用してオープンされた場合だけです。

DL_BIND_REQ プリミティブおよび DL_UNBIND_REQ プリミティブは、DLSAP と Stream の結合および結合解除を行います。各 Stream と対応付けられた PPA は、DL_BIND_REQ の処理が完了したときに初期化されます。複数の Stream を同じ SAP に結合できますが、このような Stream はそれぞれ、その SAP で受信したパケットのコピーを受け取ります。

DL_ENABMULTI_REQ プリミティブおよび DL_DISABMULTI_REQ プリミティブは、個々のマルチキャストグループアドレスの受け付けを可能または不可能にします。1 組のマルチキャストアドレスを繰り返し作成し、これらのプリミティブを使用して Stream 単位で変更できます。これらのプリミティブが受け入れられるように、Stream を PPA に接続する必要があります。

DL_PROMISCON_REQ プリミティブおよび DL_PROMISCOFF_REQ プリミティブは、物理レベルまたは SAP レベルのどちらかで、プロミスキュアス (promiscuous) モードを Stream 単位で有効または無効にします。DL Provider は、DL_DETACH_REQ または DL_PROMISCOFF_REQ を受信するまで、または Stream がクローズされるまで、そのメディアで受信したすべてのメッセージを DLS ユーザーにルーティングします。物理レベルのプロミスキュアスモードは、そのメディア上の全パケットに指定することも、マルチキャストパケットに限定して指定することもできます。


注 -

これらのプロミスキュアスモードのプリミティブが受け入れられるように、Stream を PPA に接続する必要があります。


DL_UNITDATA_REQ プリミティブは、コネクションレス型転送でデータを送信する場合に使用します。これは未承認のサービスなので、配信の保証はありません。メッセージは 1 つの M_PROTO メッセージブロックとそれに続く 1 つ以上の M_DATA ブロック (1 バイト以上のデータを含む) で構成されます。

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

DL_PHYS_ADDR_REQ プリミティブは、DL_PHYS_ADDR_ACK プリミティブで、Stream に接続された PPA にその時点で対応付けられている MAC アドレスを返します。Style 2 を使用している場合、このプリミティブが有効なのは DL_ATTACH_REQ が成功した場合に限られます。

DL_SET_PHYS_ADDR_REQ プリミティブは、Stream に接続された PPA にその時点で対応付けられている MAC アドレスを変更します。このプリミティブは、現在および将来にわたりこのデバイスに接続された他のすべての Stream に作用します。いったん変更すると、現在オープンしている、または今後オープンされてこのデバイスに接続されるすべての Stream が、この新しい物理アドレスを取得できます。新しい物理アドレスは、このプリミティブを使用して再び物理アドレスを変更するまで、またはドライバがリロードされるまで有効です。


注 -

PPA の物理アドレスは、他の Stream が同じ PPA に結合されているときに、スーパーユーザーが変更できます。


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

実装される ioctl 関数

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

DLIOCRAW ioctl 関数は、snoop(1M) コマンドをはじめ、一部の DLPI アプリケーションで使用されます。DLIOCRAW コマンドは、Stream を raw モードにして、受信時に、着信パケットの報告に通常使用される DL_UNITDATA_IND 形式に変換するのではなく、M_DATA メッセージで MAC レベルのパケット全体がアップストリーム送信されるようにします。パケット SAP のフィルタリングは、raw モードの Stream にも実行されます。Stream のユーザーがすべての着信パケットの受け取りを希望する場合は、適切なプロミスキュアスモード (複数可) も選択しなければなりません。raw モードを正しく選択しているアプリケーションは、フルフォーマットのパケットを伝送する M_DATA メッセージとしてドライバに送ることもできます。DLIOCRAW は引数を使用しません。raw モードが有効になった Stream は、クローズされるまでそのモードのままです。

GLD ドライバの要件

GLD ベースのドライバには、ヘッダーファイル <sys/gld.h> が組み込まれていなければなりません。さらに、次の宣言が含まれていることも必要です。


char _depends_on[] = "misc/gld";

GLD はデバイス固有のドライバのために、open(9E) および close(9E) 関数の他に、要求される STREAMS の put(9E) および srv(9E) 関数を実装します。さらに、ドライバ用に getinfo(9E) 関数も実装します。

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) 関数は、ハードウェア固有のデバイスドライバと GLD 機能を対応付け、デバイスとドライバを使用できるように準備を整える一切の作業を行います。

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

attach(9E) ルーチンは、gld_mac_info(9S) に記述されているように macinfo 構造体を初期化し、その後 gld_register() を呼び出して、ドライバと GLD モジュールを結びつけなければなりません。ドライバは必要に応じてレジスタをマップし、完全に初期化して、gld_register() を呼び出す前に割り込みを受け付けるように準備する必要があります。attach(9E) 関数が割り込みを追加することはあっても、デバイスに割り込みを発生させてはなりません。ドライバは、ハードウェアが確実に静止しているように、gld_register() を呼び出す前に、ハードウェアをリセットする必要があります。gld_register() の呼び出し前に、デバイスが起動されたり、割り込みが発生するような状態になったりしてはなりません。これは、gld(9E) に記載されているように、後に GLD がドライバの gldm_start() エントリポイントを呼び出した時点で行います。gld_register() が正常に完了すると、GLD はいつでも gld(9E) エントリポイントを呼び出すことができます。

attach(9E) ルーチンは、gld_register() が正常に完了した場合は、DDI_SUCCESS を返します。gld_register() がエラーになった場合は、DDI_FAILURE を返し、gld_register() を呼び出す前に割り当てられたあらゆるリソースを、attach(9E)ルーチンで割り当て解除する必要があります。そして、DDI_FAILURE を返します。どのような状況でも、エラーの起きた macinfo 構造体を再利用することがあってはなりません。gld_mac_free() を使用して、割り当てを解除する必要があります。

detach(9E) 関数は、GLD からドライバの登録を解除しようとします。これは、gld(9F) に記載されている gld_unregister() を呼び出すことによって行います。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() ルーチンを呼び出して) デバイスの割り込み中止を確認し、ドライバを GLD フレームワークから切り離し、DDI_SUCCESS を返します。この場合、detach(9E) ルーチンは割り込みを削除し、attach(9E) ルーチンに割り当てられていたすべてのデータ構造を (macinfo 構造体の割り当てを解除する gld_mac_free() を使用して) 割り当て解除したうえで、DDI_SUCCESS を返さなければなりません。gld_mac_free() を呼び出す前に割り込みを削除することが重要です。

ネットワーク統計

Solaris ネットワークドライバは統計変数を実装しなければなりません。一部のネットワーク統計については、GLD 本体で記録されますが、他のネットワーク統計は GLD ベースのドライバごとにカウントする必要があります。GLD は、GLD ベースのドライバによるネットワークドライバ統計の標準セットのレポートをサポートします。統計は、kstat(7D) および kstat(9S) メカニズムを使用して、GLD が報告します。DLPI コマンドの DL_GET_STATISTICS_REQ を使用して、現在の統計カウンタを検索することもできます。統計は特に指定が無い限り、いずれも符号無しで維持され、32 ビットです。

GLD が維持および報告する統計は、次のとおりです。

rbytes64

インタフェース上で正常に受信したトータルのバイト数 (64 ビット)

rbytes

インタフェース上で正常に受信したトータルのバイト数

obytes64

インタフェース上で送信を要求したトータルのバイト数 (64 ビット)

obytes

インタフェース上で送信を要求したトータルのバイト数

ipackets64

インタフェース上で正常に受信したトータルのパケット数 (64ビット)

ipackets

インタフェース上で正常に受信したトータルのパケット数

opackets64

インタフェース上で送信を要求したトータルのパケット数 (64 ビット)

opackets

インタフェース上で送信を要求したトータルのパケット数

multircv

グループおよび機能アドレスを含め、正常に受信したマルチキャストパケット (long)

multixmt

グループおよび機能アドレスを含め、送信を要求したマルチキャストパケット (long)

brdcstrcv

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

brdcstxmt

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

unknowns

どの Stream も受け付けなかった有効な受信パケット (long)

noxmtbuf

送信バッファが使用中だった、または送信バッファを割り当てることができなかったために、出力で廃棄されたパケット (long)

blocked

キューがフロー制御にされていたために、受信パケットを Stream に格納できなかった回数 (long)

xmtretry

リソース不足のために送信が遅延された後で、送信が再試行された回数 (long)

promisc

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

デバイス依存型のドライバは、次の統計情報をカウントし、専用のインスタンス別構造体でその記録を保管します。統計情報を報告するように求められた GLD は、gld(9E) に記述されているように、ドライバの gldm_get_stats() エントリポイントを呼び出して、gld_stats(9S) 構造体のデバイス固有の統計情報を更新します。GLD は次に、以下に示す名前付き統計変数を使用して、更新された統計情報を報告します。

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、fcs、too-long エラー以外の MAC エラーが起きた受信パケット

toolong_errors

許容される最大長を超えていた受信パケット

runt_errors

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

次の統計グループは、DL_TPR タイプのネットワークに適用されます。これらの統計は、上記同様、そのタイプのデバイス固有のドライバによって維持されます。

line_errors

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

burst_errors

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

signal_losses

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

ace_errors

AMP フレームの介入の無い、別の同様の SMP フレームが続く、A、C が共に 0 の 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」状態になった回数