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

印刷ビューの終了

更新: 2016 年 11 月
 
 

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

GLDv3 フレームワークは、MAC プラグインと、MAC ドライバサービスのルーチンおよび構造体に対する、関数呼び出しベースのインタフェースです。GLDv3 フレームワークは、必要な STREAMS エントリポイントを GLDv3 準拠ドライバに代わって実装し、DLPI との互換性を実現します。

GLDv3 の MAC 登録

GLDv3 は、MAC_PLUGIN_IDENT_ETHER タイプのプラグインに登録するドライバ用のドライバ API を定義します。

GLDv3 の MAC 登録プロセス

    GLDv3 デバイスドライバは、次の手順を実行して MAC 層に登録する必要があります。

  • sys/mac_ether.hsys/mac_provider.h の 2 つの MAC ヘッダーファイルをインクルードします。その他の MAC 関連ヘッダーファイルはドライバにインクルードしないでください。

  • mac_callbacks 構造体を生成します。

  • mac_init_ops() 関数をその _init() エントリポイントで呼び出します。

  • mac_alloc() 関数をその attach() エントリポイントで呼び出し、mac_register 構造体を割り当てます。

  • mac_register 構造体を生成し、mac_register() 関数をその attach() エントリポイントで呼び出します。

  • mac_unregister() 関数をその detach() エントリポイントで呼び出します。

  • mac_fini_ops() 関数をその _fini() エントリポイントで呼び出します。

  • misc/mac への依存性とリンクします。

    # ld -N"misc/mac" xx.o -o xx

GLDv3 の MAC 登録関数

GLDv3 インタフェースには、MAC 層への登録中に通知されるドライバエントリポイントと、ドライバによって呼び出される MAC エントリポイントが含まれています。

mac_init_ops() および mac_fini_ops() 関数
void mac_init_ops(struct dev_ops *ops, const char *name);

GLDv3 デバイスドライバは mod_install(9F) を呼び出す前に、mac_init_ops(9F) 関数をその _init(9E) エントリポイントで呼び出す必要があります。

void mac_fini_ops(struct dev_ops *ops);

GLDv3 デバイスドライバは mod_remove(9F) を呼び出したあとに、mac_fini_ops(9F) 関数をその _fini(9E) エントリポイントで呼び出す必要があります。

使用例 111  mac_init_ops() および mac_fini_ops() 関数
int
_init(void)
{
        int     rv;
        mac_init_ops(&xx_devops, "xx");
        if ((rv = mod_install(&xx_modlinkage)) != DDI_SUCCESS) {
                mac_fini_ops(&xx_devops);
        }
        return (rv);
}

int
_fini(void)
{
        int     rv;
        if ((rv = mod_remove(&xx_modlinkage)) == DDI_SUCCESS) {
                mac_fini_ops(&xx_devops);
        }
        return (rv);
}
mac_alloc() および mac_free() 関数
mac_register_t *mac_alloc(uint_t version);

mac_alloc(9F) 関数は新しい mac_register 構造体を割り当て、この構造体へのポインタを返します。新しい構造体を mac_register() に渡す前に構造体のメンバーを初期化してください。mac_alloc() が戻る前に、MAC 専用要素が MAC 層によって初期化されます。version の値は MAC_VERSION_V1 である必要があります。

void mac_free(mac_register_t *mregp);

mac_free(9F) 関数は、以前に mac_alloc() によって割り当てられた mac_register 構造体を解放します。

mac_register() および mac_unregister() 関数
int mac_register(mac_register_t *mregp, mac_handle_t *mhp);

新しいインスタンスを MAC 層に登録するために、GLDv3 ドライバは mac_register(9F) 関数をその attach(9E) エントリポイントで呼び出す必要があります。mregp 引数は、mac_register 登録情報構造体へのポインタです。成功した場合、mhp 引数は新しい MAC インスタンスの MAC ハンドルへのポインタです。このハンドルは、mac_tx_update()mac_link_update()mac_rx() などのほかのルーチンで必要になります。

使用例 112  mac_alloc()mac_register()、および mac_free() 関数と mac_register 構造体
int
xx_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
{
        mac_register_t        *macp;

/* ... */

        if ((macp = mac_alloc(MAC_VERSION)) == NULL) {
                xx_error(dip, "mac_alloc failed");
                goto failed;
        }

        macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
        macp->m_driver = xxp;
        macp->m_dip = dip;
        macp->m_src_addr = xxp->xx_curraddr;
        macp->m_callbacks = &xx_m_callbacks;
        macp->m_min_sdu = 0;
        macp->m_max_sdu = ETHERMTU;
        macp->m_margin = VLAN_TAGSZ;

        if (mac_register(macp, &xxp->xx_mh) == DDI_SUCCESS) {
                mac_free(macp);
                return (DDI_SUCCESS);
        }

/* failed to register with MAC */
        mac_free(macp);
failed:
        /* ... */
}
int mac_unregister(mac_handle_t mh);

mac_unregister(9F) 関数は、以前に mac_register() によって登録された MAC インスタンスを登録解除します。mh 引数は、mac_register() によって割り当てられた MAC ハンドルです。mac_unregister()detach(9E) エントリポイントから呼び出してください。

使用例 113  mac_unregister() 関数
int
xx_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
{
        xx_t        *xxp; /* driver soft state */

        /* ... */

        switch (cmd) {
        case DDI_DETACH:

                if (mac_unregister(xxp->xx_mh) != 0) {
                        return (DDI_FAILURE);
                }
        /* ... */
}

GLDv3 の MAC 登録データ構造体

このセクションで説明する構造体は、sys/mac_provider.h ヘッダーファイルで定義されます。sys/mac_ether.h および sys/mac_provider.h MAC ヘッダーファイルを GLDv3 ドライバにインクルードします。その他の MAC 関連ヘッダーファイルはインクルードしないでください。

mac_register(9S) データ構造体は、mac_alloc() によって割り当てられ、mac_register() に渡される MAC 登録情報構造体です。新しい構造体を mac_register() に渡す前に構造体のメンバーを初期化してください。mac_alloc() が戻る前に、MAC 専用要素が MAC 層によって初期化されます。構造体の m_version メンバーは MAC バージョンです。MAC バージョンを変更しないでください。構造体の m_type_ident メンバーは MAC タイプ識別子です。MAC タイプ識別子は MAC_PLUGIN_IDENT_ETHER に設定してください。mac_register 構造体の m_callbacks メンバーは、mac_callbacks 構造体のインスタンスへのポインタです。

mac_callbacks(9S) データ構造体は、デバイスドライバがそのエントリポイントを MAC 層に公開するために使用する構造体です。これらのエントリポイントは、ドライバを制御するために MAC 層によって使用されます。これらのエントリポイントは、アダプタの起動と停止、マルチキャストアドレスの管理、プロミスキュアス (promiscuous) モードの設定、アダプタの機能の照会、プロパティーの取得と設定などのタスクを実行するために使用されます。すべての必須およびオプション GLDv3 エントリポイントの一覧については、表 19 を参照してください。mac_register 構造体の m_callbacks フィールドには、mac_callbacks 構造体へのポインタを指定します。

mac_callbacks 構造体の mc_callbacks メンバーは、次のフラグを組み合わせたビットマスクであり、ドライバで実装されるオプションエントリポイントを指定します。mac_callbacks 構造体のほかのメンバーは、ドライバの各エントリポイントへのポインタです。

MC_IOCTL

mc_ioctl() エントリポイントが存在します。

MC_GETCAPAB

mc_getcapab() エントリポイントが存在します。

MC_SETPROP

mc_setprop() エントリポイントが存在します。

MC_GETPROP

mc_getprop() エントリポイントが存在します。

MC_PROPINFO

mc_propinfo() エントリポイントが存在します。

MC_PROPERTIES

すべてのプロパティーエントリポイントが存在します。MC_PROPERTIES を設定すると、MC_SETPROPMC_GETPROP、および MC_PROPINFO の 3 つのフラグすべてを設定したことになります。

使用例 114  mac_callbacks 構造体
#define XX_M_CALLBACK_FLAGS \
    (MC_IOCTL | MC_GETCAPAB | MC_PROPERTIES)

static mac_callbacks_t xx_m_callbacks = {
        XX_M_CALLBACK_FLAGS,
        xx_m_getstat,     /* mc_getstat() */
        xx_m_start,       /* mc_start() */
        xx_m_stop,        /* mc_stop() */
        xx_m_promisc,     /* mc_setpromisc() */
        xx_m_multicst,    /* mc_multicst() */
        xx_m_unicst,      /* mc_unicst() */
        xx_m_tx,          /* mc_tx() */
        NULL,             /* Reserved, do not use */
        xx_m_ioctl,       /* mc_ioctl() */
        xx_m_getcapab,    /* mc_getcapab() */
        NULL,             /* Reserved, do not use */
        NULL,             /* Reserved, do not use */
        xx_m_setprop,     /* mc_setprop() */
        xx_m_getprop,     /* mc_getprop() */
        xx_m_propinfo     /* mc_propinfo() */
};

GLDv3 の機能

GLDv3 が実装する機能メカニズムでは、GLDv3 ドライバでサポートされている機能をフレームワークで照会して有効化できます。機能を報告するにはmc_getcapab(9E) エントリポイントを使用します。機能がドライバによってサポートされている場合は、機能固有のエントリポイントやフラグなど、その機能についての情報を mc_getcapab() を通して渡します。mc_getcapab() エントリポイントへのポインタを mac_callback 構造体で渡します。GLDv3 の MAC 登録データ構造体 構造体の詳細は、GLDv3 MAC Registration Data Structuresを参照してください。

boolean_t mc_getcapab(void *driver_handle, mac_capab_t cap, void *cap_data);

cap 引数は、照会する機能のタイプを指定します。cap に指定できる値は MAC_CAPAB_HCKSUM (ハードウェアチェックサムオフロード)、MAC_CAPAB_LSO (ラージセグメントオフロード)、または MAC_CAPAB_RINGS です。機能データをフレームワークに返すには、cap_data 引数を使用します。

ドライバが cap の機能をサポートする場合、mc_getcapab() エントリポイントは B_TRUE を返す必要があります。ドライバが cap の機能をサポートしない場合、mc_getcapab()B_FALSE を返す必要があります。

使用例 115  mc_getcapab() エントリポイント
static boolean_t
xx_m_getcapab(void *arg, mac_capab_t cap, void *cap_data)
{
        switch (cap) {
        case MAC_CAPAB_HCKSUM: {
                uint32_t *txflags = cap_data;
                *txflags = HCKSUM_INET_FULL_V4 | HCKSUM_IPHDRCKSUM;
                break;
        }
        case MAC_CAPAB_LSO: {
                /* ... */
                break;
        }
			 case MAC_CAPAB_RINGS: {


                /* ... */


                break;


        }
        default:
                return (B_FALSE);
        }
        return (B_TRUE);
}

MAC リング機能

次のセクションからは、サポートされている機能と、対応する機能ごとに返されるデータについて説明します。

リングとリンググループのレイヤー 2 分類

送信ハードウェアリングと受信ハードウェアリングはどちらも DMA チャネルであり、デバイスドライバはこれらを公開できます。リングはリンググループに関連付けられます。受信リンググループには 1 つ以上の MAC アドレスが関連付けられますが、ある受信グループに関連付けられた MAC アドレスのいずれかに一致するネットワークトラフィックはすべて、そのグループのいずれかのリング経由で NIC から配信される必要があります。受信リンググループへのトラフィックの配信は、ハードウェアのレイヤー 2 分類によって可能になります。

受信リングとリンググループとのマッピングは動的または静的に行うことができます。動的リンググループでは、フレームワークからのリクエストに応じてグループ間でリングを移動できるため、グループのサイズを動的に縮小または拡大できます。一方、静的リンググループでは、リングは静的にグループに割り当てられ、その割り当てを変更することはできません。

受信グループに複数のリングが含まれている場合、NIC は、RSS (Receive Side Scaling) などのハッシュメカニズムを使ってそれらのリング間にトラフィックを分散させることで、複数の接続がそれぞれ異なるリングに割り当てられるようにする必要があります。

受信グループのどれか 1 つ (通常はインデックス 0 にある最初のグループ) をデフォルトグループとして指定する必要があります。この受信グループには次の特性が割り当てられます。

  • リングを少なくとも 1 つ持つべきです。

  • NIC のプライマリ MAC クライアントに割り当てられます。プライマリ MAC クライアントには NIC のプライマリ MAC アドレスが割り当てられ、通常は IP になります。

  • ネットワークから受信されたすべてのマルチキャストおよびブロードキャストトラフィックを受信するために使用する必要があります。

  • NIC がプロミスキュアスモードになっている場合、デフォルト以外の受信グループに割り当てられた MAC アドレスに一致しないトラフィックをすべて、これを使って受信する必要があります。

受信リングや受信リンググループのハードウェア実装について注意すべき点を次に示します。

  • 複数の受信リングが実装されているがレイヤー 2 分類はサポートされていない場合、ハードウェアは、すべてのリングが属する単一の受信リンググループをフレームワークに公開すべきです。

  • レイヤー 2 ハードウェア分類は実装されているが RSS はサポートされていない場合、ハードウェアは、それぞれ 1 つのリングを含む受信グループを複数個登録すべきです。

  • レイヤー 2 ハードウェア分類と RSS の両方が実装されている場合、ハードウェアは、それぞれ 1 つ以上のリングを含む受信グループを複数個登録すべきです。

  • レイヤー 2 ハードウェア分類も RSS も実装されていない場合、ハードウェアは、リング機能を通知しないか、あるいは単一の擬似リングとリンググループを備えたリング機能を通知すべきであり、これらを使えば、アダプタに対してトラフィックの有無を動的にポーリングできます。

リングとグループの登録プロセスの概要

リングをフレームワークに登録する際には、フレームワークからドライバへの各種呼び出しで構成されるプロセスを実行します。次の手順はその登録プロセスを説明したものです。

  1. フレームワークは、ドライバの MAC_CAPAB_RINGS 機能のクエリーを行うために、ドライバを呼び出します。呼び出しは、送信リング用と受信リング用にそれぞれ 1 回ずつ行われます。詳細は、MAC_CAPAB_RINGS 機能を参照してください。

  2. フレームワークは、1 つ前の段階で得られた mr_rget(9E) および mr_gget(9E) エントリポイントを使って特定のリングまたはリンググループに関する情報を取得します。詳細は、mr_rget(9E) およびmr_gget(9E) のマニュアルページを参照してください。

  3. フレームワークがリングを使用する際は、1 つ前の段階で通知されたように、mgi_start(9E) エントリポイントでリンググループを開始したあと、mri_start(9E) エントリポイントを使ってリングを開始します。

    これで、リングが mgi_stop(9E) および mri_stop(9E) エントリポイント経由で停止されるまで、トラフィックをリング経由で流すことができます。

MAC_CAPAB_RINGS 機能

フレームワークはハードウェアの送信リングと受信リングのサポートに関する情報を取得するため、cap 引数の MAC_CAPAB_RINGS を送信し、mac_capab_rings 構造体を指している cap_data フィールドに情報が返されることを想定します。

フレームワークは、mac_capab_rings(9S) 構造体を割り当て、mr_type メンバーを受信リングの場合は MAC_RING_TYPE_RX に、送信リングの場合は MAC_RING_TYPE_TX にそれぞれ設定します。すると、ドライバによって構造体 mac_capab_rings の残りのメンバーに情報が設定されます。

mac_capab_rings 構造体に定義されているフィールドは次のとおりです。

mr_version

MAC_RINGS_VERSION_1 に設定する必要があります。

mr_rnum

リングの数。

mr_gnum

グループの数。

mr_group_type

次の値が定義されています。

  • MAC_GROUP_TYPE_DYNAMIC – グループは動的です。

  • MAC_GROUP_TYPE_STATIC – グループは静的です。

詳細は、リングとリンググループのレイヤー 2 分類を参照してください。

mr_gget()

リンググループの詳細情報を取得するドライバエントリポイント。詳細は、mr_gget エントリポイントを参照してください。

mr_rget()

リングの詳細情報を取得するドライバエントリポイント。詳細は、mr_rget エントリポイントを参照してください。

mr_gaddring()

リングをグループに追加するドライバエントリポイント。mr_gaddring(9E) を参照してください。

mr_gremring()

グループからリングを削除するドライバエントリポイント。mr_gremring(9E) を参照してください。

mr_gget() エントリポイント

mr_gnum パラメータに示されたグループ数に対応する有効なグループインデックスごとに、mr_gget(9E) エントリポイントがフレームワークによって呼び出されます。詳細は、mr_gget(9E) を参照してください。mr_gget() を呼び出すと、ドライバによって mac_group_info 構造体にグループ情報が返されます。構造体自体はフレームワークによって事前に割り当てられ、構造体の設定はドライバによって行われます。

mac_group_info 構造体に定義されているフィールドは次のとおりです。

mgi_driver

後続のグループエントリポイント呼び出し時にフレームワークによって使用される不透明なドライバグループハンドル。

mgi_count

グループ内のリング数。

mgi_flags

グループフラグ MAC_GROUP_DEFAULT は、そのグループがデフォルトグループであることを示します。詳細は、リングとリンググループのレイヤー 2 分類を参照してください。

mgi_start

グループ開始エントリポイント。

mgi_stop

グループ停止エントリポイント。

mgi_addmac

ユニキャスト MAC アドレス追加エントリポイント。

mgi_remmac

ユニキャスト MAC アドレス削除エントリポイント。

mgi_addvlan

ハードウェアの VLAN フィルタリング、タグ付け、および VLAN タグのストリップを追加するエントリポイント。

mgi_remvlan

ハードウェアの VLAN フィルタリング、タグ付け、および VLAN タグのストリップを削除するエントリポイント。

mgi_setmtu

RX グループ MTU 設定エントリポイント

mgi_getsriov_info

グループの SR-IOV 情報を取得するエントリポイント。詳細は、リンググループと SR-IOV を参照してください。

詳細は、mac_group_info(9S) およびmac_group_info(9E) を参照してください。


注 - mgi_addmac(9E) およびmgi_remmac(9E) エントリポイントは、受信グループでのみ使用されます。デバイスドライバがリング機能をサポートしている場合は必ず、mc_unicst(9E) エントリポイントを NULL に設定する必要があります。

注 - mgi_addvlan() エントリポイントは次のアクションを実行します。
  • これは、NIC によって許可される必要のある、送信用および受信用の VLAN ID を定義します。つまり、構成されたリストに含まれていないタグ付きパケットはすべてドロップされます。

  • MAC_GROUP_VLAN_TRANSPARENT_ENABLE フラグが設定されていた場合、これは、その特定の VLAN ID のハードウェア VLAN タグ付けやストリップの有効化も行います。


mr_rget() エントリポイント

MAC_CAPAB_RINGS 呼び出しで通知された mr_gnummr_rnum にそれぞれ示されたグループ数とリング数に対応する有効なグループインデックスおよびリングインデックスごとに、mr_rget(9E) エントリポイントがフレームワークによって呼び出されます。詳細は、mr_rget(9E) を参照してください。

mr_rget() 呼び出しが完了すると、ドライバによって mac_ring_info 構造体にリング情報が返されます。構造体はフレームワークによって事前に割り当てられ、構造体の設定はドライバによって行われます。

mac_ring_info 構造体に定義されているフィールドは次のとおりです。

mri_driver

後続のリングエントリポイント呼び出し時にフレームワークによって使用される不透明なドライバグループハンドル。

mri_start

リング開始エントリポイント。

mri_stop

リング停止エントリポイント

mri_stat

リング統計エントリポイント。詳細は、GLDv3 のネットワーク統計情報を参照してください。

mri_tx

リング送信エントリポイント。詳細は、送信データパスを参照してください。

mri_poll

リングポーリングエントリポイント。詳細は、受信データパス を参照してください。

mri_intr_ddi_handle

このリングの割り込みに関連付けられた DDI 割り込みハンドル。

mri_intr_enable(9E)

RX リングの割り込みを有効にします。詳細は、受信データパスを参照してください。

mri_intr_disable(9E)

RX リングの割り込みを無効にします。詳細は、受信データパス を参照してください。

詳細は、mac_group_info(9S)mac_ring_info(9S) のマニュアルページを参照してください。


注 - mri_tx() を設定する必要があるのは送信リングの場合だけであり、mri_poll() を設定する必要があるのは受信リングの場合だけです。

注 - ドライバがリング機能を実装している場合は、mac_callbacks 構造体の mc_tx() エントリポイントを NULL に設定する必要があります。
リンググループと SR-IOV

SR-IOV に対応したデバイスドライバが、自身が SR-IOV に対応していることを MAC_CAPAB_RINGS 機能を使ってフレームワークに通知するには、mgi_getsriov_info(9E) グループエントリポイントを実装します。このエントリポイントの実装は、PF ドライバが担当します。

mgi_getsriov_info(9E) を呼び出すと、ドライバによって mac_sriov_info 構造体に SR-IOV 情報が返されます。構造体はフレームワークによって事前に割り当てられ、構造体の設定はドライバによって行われます。

PF (物理機能) ドライバインスタンスは、VF (仮想機能) と同じ数の送信および受信リンググループを登録します。PF ドライバによって通知されるこれらのリンググループは特殊なもので、VF の管理に使用されます。これらのリンググループ内をデータが通過することは一切ありません。これらは、ユニキャスト MAC アドレスの構成、MTU の設定、VLAN フィルタの追加、VLAN フィルタの削除、VLAN ハードウェアの削除、および VF の VLAN タグ付けやストリップの実行を行うために使用されます。


注 - VF ドライバは自身が参加する MAC マルチキャストグループをプログラミングします。PF ドライバはこれらのアドレスのプログラミングを制御しません。

PF ドライバによって設定される msi_vf_index 構造体メンバーには、リンググループに対応する VF インデックスが設定されます。これは、デバイスドライバが pci_plist_getvf(9F) 関数を呼び出す際に使用するのと同じインデックスです。

SR-IOV ドライバの詳細については、SR-IOV ドライバを参照してください。

ハードウェアチェックサムオフロード

ハードウェアチェックサムオフロードのサポートについてのデータを取得するために、フレームワークは cap 引数で MAC_CAPAB_HCKSUM を送信します。ハードウェアチェックサムオフロード機能情報を参照してください。

ハードウェアによるチェックサム計算が有効なときに、チェックサムオフロードのメタデータを照会したり、パケット単位でのハードウェアによるチェックサム計算のメタデータを取得したりするには、mac_hcksum_get(9F) を使用します。mac_hcksum_get 関数のフラグを参照してください。

チェックサムオフロードのメタデータを設定するには、mac_hcksum_set(9F) を使用します。mac_hcksum_set 関数のフラグを参照してください。

詳細は、ハードウェアによるチェックサム計算: ハードウェアおよびハードウェアによるチェックサム計算: MAC 層を参照してください。

ハードウェアチェックサムオフロード機能情報

MAC_CAPAB_HCKSUM 機能についての情報をフレームワークに渡すために、ドライバは uint32_t を指し示す cap_data で次のフラグの組み合わせを設定する必要があります。これらのフラグは、アウトバウンドパケットに対してドライバが実行できるハードウェアチェックサムオフロードのレベルを示します。

HCKSUM_INET_PARTIAL

1 の補数による部分チェックサム機能

HCKSUM_INET_FULL_V4

IPv4 パケット対象の 1 の補数による完全チェックサム機能

HCKSUM_INET_FULL_V6

IPv6 パケット対象の 1 の補数による完全チェックサム機能

HCKSUM_IPHDRCKSUM

IPv4 ヘッダーのチェックサムオフロード機能

mac_hcksum_get() 関数のフラグ

mac_hcksum_get()flags 引数は次の値の組み合わせです。

HCK_FULLCKSUM

このパケットの完全チェックサムを計算します。

HCK_FULLCKSUM_OK

完全チェックサムがハードウェアで検証済みであり、正確です。

HCK_PARTIALCKSUM

mac_hcksum_get() に渡されるほかのパラメータに基づいて、1 の補数による部分チェックサムを計算します。HCK_PARTIALCKSUM HCK_FULLCKSUM と相互排他です。

HCK_IPV4_HDRCKSUM

IP ヘッダーのチェックサムを計算します。

HCK_IPV4_HDRCKSUM_OK

IP ヘッダーのチェックサムはハードウェアで検証済みであり、正確です。

mac_hcksum_set() 関数のフラグ

mac_hcksum_set()flags 引数は次の値の組み合わせです。

HCK_FULLCKSUM

完全チェックサムが計算され、value 引数を介して渡されました。

HCK_FULLCKSUM_OK

完全チェックサムがハードウェアで検証済みであり、正確です。

HCK_PARTIALCKSUM

部分チェックサムが計算され、value 引数を介して渡されました。HCK_PARTIALCKSUM HCK_FULLCKSUM と相互排他です。

HCK_IPV4_HDRCKSUM

IP ヘッダーのチェックサムが計算され、value 引数を介して渡されました。

HCK_IPV4_HDRCKSUM_OK

IP ヘッダーのチェックサムはハードウェアで検証済みであり、正確です。

ラージセグメント (送信) オフロード

ラージセグメント (送信) オフロードのサポートを照会するために、フレームワークは cap 引数で MAC_CAPAB_LSO を送信し、mac_capab_lso(9S) 構造体を指し示す cap_data に情報が返されることを想定します。フレームワークは mac_capab_lso 構造体を割り当て、この構造体へのポインタを cap_data に渡します。mac_capab_lso 構造体は lso_basic_tcp_ipv4(9S) 構造体と lso_flags メンバーで構成されます。ドライバインスタンスが TCP/IPv4 での LSO をサポートする場合、LSO_TX_BASIC_TCP_IPV4 フラグを lso_flags に設定し、デバイスインスタンスがサポートする最大ペイロードサイズを lso_basic_tcp_ipv4 構造体の lso_max メンバーに設定します。

パケット単位での LSO のメタデータを取得するには、mac_lso_get(9F) を使用します。このパケットに対して LSO が有効な場合、mac_lso_get()flags 引数に HW_LSO フラグが設定されます。ラージセグメントのセグメンテーション中に使用される最大セグメントサイズ (MSS) は、mss 引数によって指示される場所を介して返されます。詳細は、ラージセグメントオフロードを参照してください。

GLDv3 のデータパス

    データパスエントリポイントは、次のコンポーネントで構成されます。

  • ドライバによってエクスポートされ、パケット送信のために GLDv3 フレームワークによって呼び出されるコールバック。

  • 転送フロー制御およびパケット受信のためにドライバによって呼び出される GLDv3 フレームワークのエントリポイント。


注 - ドライバがリング機能を実装している場合、そのドライバによって送信および受信されるデータはすべて、リング固有のエントリポイントを介して渡されます。

送信データパス

GLDv3 フレームワークがメッセージブロックをドライバに渡すために呼び出す送信エントリポイントのタイプは、ベースとなるドライバの MAC_CAPAB_RINGS サポートによって異なります。ドライバが MAC_CAPAB_RINGS 機能をサポートしている場合、フレームワークは mri_tx(9E) リングエントリポイントを呼び出します。それ以外の場合、フレームワークは mc_tx(9E) エントリポイントを呼び出します。

したがって、デバイスドライバは mc_tx()mri_tx() のいずれかに送信エントリポイントへのポインタを指定する必要があります。詳細は、GLDv3 の MAC 登録データ構造体およびmr_rget エントリポイントを参照してください。

使用例 116  mc_tx() および mri_tx() エントリポイント
mblk_t *
xx_m_tx(void *arg, mblk_t *mp)
{
        xx_t    *xxp = arg;
        mblk_t   *nmp;

        mutex_enter(&xxp->xx_xmtlock);

        if (xxp->xx_flags & XX_SUSPENDED) {
                while ((nmp = mp) != NULL) {
                        xxp->xx_carrier_errors++;
                        mp = mp->b_next;
                        freemsg(nmp);
                }
                mutex_exit(&xxp->xx_xmtlock);
                return (NULL);
        }

        while (mp != NULL) {
                nmp = mp->b_next;
                mp->b_next = NULL;

                if (!xx_send(xxp, mp)) {
                        mp->b_next = nmp;
                        break;
                }
                mp = nmp;
        }
        mutex_exit(&xxp->xx_xmtlock);

        return (mp);
}

次のセクションでは、ハードウェアへのデータ転送に関連する事項について説明します。

フロー制御

ハードウェアリソース不足のためドライバがパケットを送信できない場合、ドライバは送信できなかったパケットのサブチェーンを返します。利用可能な記述子があとから増えたとき、ドライバは mac_tx_update(9F) または mac_tx_ring(9F) を呼び出してフレームワークに通知する必要があります。ドライバは、自身がリング機能を実装しているかどうかに応じていずれかの関数を呼び出します。

ハードウェアによるチェックサム計算: ハードウェア

ドライバでハードウェアチェックサムのサポート (ハードウェアチェックサムオフロードを参照) を指定した場合、ドライバは次のタスクを実行する必要があります。

  • mac_hcksum_get(9F) を使用して、ハードウェアチェックサムのメタデータの全パケットを確認します。

  • 必要なチェックサム計算を実行するようにハードウェアをプログラミングします。

ラージセグメントオフロード

ドライバで LSO 機能 (ラージセグメント (送信) オフロードを参照) を指定した場合、ドライバは mac_lso_get(9F) を使用して、パケットに対して LSO を実行する必要があるかどうかを照会する必要があります。

仮想 LAN: ハードウェア

管理者が VLAN を構成した場合、アウトバウンドパケットが mc_tx() エントリポイントを介してドライバに渡される前に、MAC 層が必要な VLAN ヘッダーをアウトバウンドパケットに挿入します。ただし、ハードウェアが VLAN タグ付けをサポートしている場合、ハードウェアにタグ付けがオフロードされます。詳細は、mr_gget エントリポイントを参照してください。

受信データパス

受信データパスは割り込み駆動とポーリング駆動のいずれかになります。

受信割り込みデータパス

注: ドライバがリング機能をサポートしていない場合、ドライバの割り込みハンドラ内で mac_rx(9F) 関数を呼び出すことで、1 つ以上のパケットのチェーンをスタック上方の MAC 層に渡します。mac_rx() または mac_rx_ring() の呼び出し中は、相互排他ロックやその他のロックを保持しないでください。特に、mac_rx() または mac_rx_ring() の呼び出し中に転送スレッドによって取得される可能性があるロックを保持しないでください。

割り込みモードでは、NIC でパケットチェーンが受信され、それをドライバから取得可能な場合は常に、ドライバから上方のフレームワークにパケットチェーンが送信されます。パケットチェーンでは 1 つ以上の mblk_tb_next を介して互いに連結されているため、パケット単位の処理のオーバーヘッドを減らすことができます。割り込みモードで受信されたパケットを上方のフレームワークに渡すには、mac_rx_ring() エントリポイントを呼び出します。

void mac_rx_ring(mac_handle_t mh, mac_ring_handle_t mrh, mblk_t *mp_chain, int64_tmr_gen_num)

mh_handle は、デバイスドライバが mac_register() 関数経由でのカーネルへの登録時に取得した MAC ハンドルに対応しています。mrh _handle は、mr_rget() 呼び出しの一部としてドライバに渡されたフレームワークリングハンドルです。mr_gen_num は、mri_start() エントリポイント経由で受信リングを開始する際にフレームワークによって指定された生成番号に設定する必要があります。ドライバから提供されたリング生成番号は、フレームワークに保持されているリング生成番号と比較されます。これらが一致しない場合、受信されたパケットはそのリングの古い割り当てからの古いパケットであるとみなされ、ドロップされます。

受信ポーリングデータパス

割り込み駆動のパス経由でパケットを受信できるだけでなく、フレームワークではポーリングベースのデータパスもサポートされています。ポーリングモードでは、スタック内で実行されているカーネルスレッドが、ポーリングエントリポイント経由でドライバからパケットを取得します。このため、スタックは、パケットを処理するタイミングやその優先度を効率的に制御しながら、システムに入ってくる割り込みの数を実際の負荷に基づいて減らすことができます。さらに、スタックはポーリングを使用することで、受信トラフィックに対して帯域幅制限をより効率的に適用できますが、これは特に、仮想化シナリオではクリティカルになります。ホストは、割り込みモードとポーリングモードを必要に応じて切り替えます。あるリングがポーリングモードになっている場合、ドライバはその受信リング経由で受信されたパケットを mac_rx_ring() 関数を使って配信すべきではありません。ポーリングモードでは割り込みが無効化されるため、このことが保証されます。代わりにフレームワークは、ドライバによって mac_ring_info 構造体の一部として公開された mri_poll() エントリポイントを呼び出します。詳細は、mr_rget エントリポイントを参照してください。

割り込みモードとポーリングモードの切り替え

デフォルトでは、開始後のリングは割り込みモードになっているはずです。リングは、割り込みモードになっているかぎり、受信したパケットをエントリポイント経由でチェーンの形式で渡すべきです。ホストは、リングをポーリングモードに切り替える際に、その割り込みを無効化するために、mac_ring_info 構造体経由で事前に公開された mac_intr 構造体を介してエントリポイントを呼び出します。

ハードウェアによるチェックサム計算: MAC 層

ドライバでハードウェアチェックサムのサポート (ハードウェアチェックサムオフロードを参照) を指定した場合、ドライバは mac_hcksum_set(9F) 関数を使用して、ハードウェアによるチェックサム計算のメタデータをパケットと関連付ける必要があります。

仮想 LAN: MAC 層

VLAN パケットは、そのタグとともに MAC 層に渡される必要があります。パケットから VLAN ヘッダーを取り除かないでください。ただし、ハードウェアが VLAN ストリップをサポートしており、かつフレームワークがハードウェアに VLAN タグのストリップをリクエストした場合、ハードウェアは VLAN タグをストリップすることでパフォーマンスを改善できます。詳細は、mr_gget エントリポイントを参照してください。

GLDv3 の状態変更通知

ドライバは次の関数を呼び出して、ドライバの状態が変化したことをネットワークスタックに通知できます。

void mac_tx_update(mac_handle_t mh);
void mac_tx_ring_update(mac_handle_t mh, mac_ring_handle_t rh)

mac_tx_update(9F)または mac_tx_ring(9F) 関数は、より多くの TX 記述子が使用可能になったことをフレームワークに通知します。空でないパケットチェーンを mc_tx() または mri_tx() が返した場合、ドライバはリソースが利用可能になったらただちに mac_tx_update() または mac_tx_ring_update() を呼び出して、未送信として返送されたパケットの再送を試みるよう MAC 層に通知する必要があります。mc_tx() および mri_tx() エントリポイントの詳細は、送信データパスを参照してください。

void mac_link_update(mac_handle_t mh, link_state_t new_state);

mac_link_update(9F) 関数は、メディアリンクの状態が変化したことを MAC 層に通知します。new_state 引数は次のいずれかの値である必要があります。

LINK_STATE_UP

メディアリンクは稼働しています。

LINK_STATE_DOWN

メディアリンクはダウンしています。

LINK_STATE_UNKNOWN

メディアリンクの状態は不明です。

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

デバイスドライバは、管理対象のデバイスインスタンスに関する一連の統計情報を管理します。MAC 層は、ドライバの mc_getstat(9E) エントリポイントを介してこれらの統計情報を照会します。

int mc_getstat(void *driver_handle, uint_t stat, uint64_t *stat_value);

GLDv3 フレームワークは stat を使用して、照会する統計情報を指定します。ドライバは stat_value を使用して、stat で指定された統計情報の値を返します。統計情報の値が返された場合、mc_getstat() は 0 を返す必要があります。stat の統計情報がドライバでサポートされていない場合、mc_getstat()ENOTSUP を返す必要があります。

GLDv3 でサポートされる統計情報は、汎用の MAC 統計情報と Ethernet 固有の統計情報を合わせたものです。サポートされる統計情報の完全な一覧については、mc_getstat(9E) のマニュアルページを参照してください。

使用例 117  mc_getstat() エントリポイント
int
xx_m_getstat(void *arg, uint_t stat, uint64_t *val)
{
        xx_t    *xxp = arg;

        mutex_enter(&xxp->xx_xmtlock);
        if ((xxp->xx_flags & (XX_RUNNING|XX_SUSPENDED)) == XX_RUNNING)
                xx_reclaim(xxp);
        mutex_exit(&xxp->xx_xmtlock);

        switch (stat) {
        case MAC_STAT_MULTIRCV:
                *val = xxp->xx_multircv;
                break;
        /* ... */
        case ETHER_STAT_MACRCV_ERRORS:
                *val = xxp->xx_macrcv_errors;
                break;
        /* ... */
        default:
                return (ENOTSUP);
        }
        return (0);
}

mri_stat() リングエントリポイントは、リング機能をサポートするすべてのデバイスドライバで実装する必要のある必須のリングエントリポイントです。このエントリポイントは、ハードウェア送信リングおよび受信リングのそれぞれに維持された統計のクエリーを行うために、フレームワークによって使用されます。

ハードウェア送信リングの場合、フレームワークは次の統計のクエリーを行います。

  • MAC_STAT_OERRORS

  • MAC_STAT_OBYTES

  • MAC_STAT_OPACKETS

ハードウェア受信リングの場合、フレームワークは次の統計のクエリーを行います。

  • MAC_STAT_IERRORS

  • MAC_STAT_RBYTES

  • MAC_STAT_IPACKETS

GLDv3 のプロパティー

プロパティーの不変属性を返すには、mc_propinfo(9E) エントリポイントを使用します。この情報にはアクセス権、デフォルト値、および値の許容範囲が含まれています。この特定のドライバインスタンスのプロパティー値を設定するには、mc_setprop(9E) を使用します。プロパティーの現在の値を返すには、mc_getprop(9E)を使用します。

プロパティーとその型の完全な一覧については、mc_propinfo(9E) のマニュアルページを参照してください。

mc_propinfo() エントリポイントは、mac_prop_info_set_perm()mac_prop_info_set_default()、および mac_prop_info_set_range() 関数を呼び出して、デフォルト値、アクセス権、値の許容範囲など、照会するプロパティーの特定の属性を関連付けます。

mac_prop_info_set_default_uint8(9F)mac_prop_info_set_default_str(9F)、および mac_prop_info_set_default_link_flowctrl(9F) 関数は、デフォルト値を特定のプロパティーと関連付けます。mac_prop_info_set_range_uint32(9F) 関数は、特定のプロパティーについて値の許容範囲を関連付けます。

mac_prop_info_set_perm(9F) 関数はプロパティーのアクセス権を指定します。アクセス権は次のいずれかの値になります。

MAC_PROP_PERM_READ

プロパティーは読み取り専用

MAC_PROP_PERM_WRITE

プロパティーは書き込み専用

MAC_PROP_PERM_RW

プロパティーは読み書き可能

mc_propinfo() エントリポイントで特定のプロパティーについて mac_prop_info_set_perm() を呼び出さない場合、GLDv3 フレームワークはそのプロパティーのアクセス権を読み書き可能 (MAC_PROP_PERM_RW) と想定します。

mc_propinfo(9E) のマニュアルページに列挙されたプロパティーに加えて、ドライバではそのドライバ専用のプロパティーも公開できます。ドライバでサポートするドライバ専用プロパティーを指定するには、mac_register 構造体の m_priv_props フィールドを使用します。フレームワークは MAC_PROP_PRIVATE プロパティー ID を mc_setprop()mc_getprop()、または mc_propinfo() に渡します。詳細は、mc_propinfo (9E) のマニュアルページを参照してください。

GLDv3 のインタフェースのサマリー

次の表は、GLDv3 ネットワークデバイスドライバのフレームワークを構成するエントリポイント、その他の DDI 関数、およびデータ構造体の一覧です。

表 19  GLDv3 のインタフェース
インタフェース名
説明
必須のエントリポイント
ドライバからネットワーク統計情報を取得します。GLDv3 のネットワーク統計情報を参照してください。
ドライバインスタンスを起動します。GLDv3 フレームワークは、何らかの操作が試みられる前に起動エントリポイントを呼び出します。
ドライバインスタンスを停止します。MAC 層は、デバイスが切り離される前に停止エントリポイントを呼び出します。
デバイスドライバインスタンスのプロミスキュアス (promiscuous) モードを変更します。
マルチキャストアドレスを追加または削除します。
プライマリユニキャストアドレスを設定します。デバイスは mac_rx() を使用して、宛先 MAC アドレスが新しいユニキャストアドレスと一致するパケットの送信を開始する必要があります。受信データパス の詳細は、Receive Data Path()を参照してください。
1 つ以上のパケットを送信します。送信データパスを参照してください。
送信および受信リングの情報を取得します。詳細は、mr_rget エントリポイントを参照してください。
送信および受信リングの情報を取得します。詳細は、mr_gget エントリポイントを参照してください。
受信グループにリングを追加します。これが必要になるのは、動的リンググループがサポートされている場合だけです。MAC_CAPAB_RINGS 機能を参照してください。
受信グループからリングを削除します。これが必要になるのは、動的リンググループがサポートされている場合だけです。MAC_CAPAB_RINGS 機能を参照してください。
mri_tx(9E)
TX リングのパケットを送信します。詳細は、mr_rget エントリポイントを参照してください。
mri_poll()
RX リングに対してパケットのポーリングを行います。詳細は、mr_rget エントリポイントを参照してください。
mri_stat()
リングの統計。詳細は、mr_rget エントリポイントを参照してください。
RX リングの割り込みを有効にします。詳細は、mr_rget エントリポイントを参照してください。
RX リングの割り込みを無効にします。詳細は、mr_rget エントリポイントを参照してください。
ドライバの RX リンググループ用ハードウェアに MAC アドレスをプログラミングします。詳細は、mr_gget エントリポイントを参照してください。
以前にプログラミングされた MAC アドレスを、ドライバの RX リンググループ用ハードウェアから削除します。詳細は、mr_gget エントリポイントを参照してください。
オプションのエントリポイント
省略可能な ioctl ドライバインタフェース。この機能はデバッグ目的の使用のみが想定されています。
機能を取得します。GLDv3 の機能を参照してください。
プロパティー値を設定します。GLDv3 のプロパティーを参照してください。
プロパティー値を取得します。GLDv3 のプロパティーを参照してください。
プロパティーについての情報を取得します。GLDv3 のプロパティーを参照してください。
mri_start()
リングを開始します。詳細は、mr_rget エントリポイントを参照してください
mri_stop()
リングを停止します。詳細は、mr_rget エントリポイントを参照してください。
リンググループを開始します。詳細は、mr_gget エントリポイントを参照してください。
リンググループを停止します。詳細は、mr_gget エントリポイントを参照してください。
mgi_addvlan()
ハードウェアの VLAN フィルタリングを有効にします。詳細は、mr_gget エントリポイントを参照してください。
mgi_remvlan()
以前にプログラミングされた VLAN フィルタを削除します。詳細は、mr_gget エントリポイントを参照してください。
mgi_setmtu()
RX グループの MTU を設定します。詳細は、mr_gget エントリポイントを参照してください。
mgi_get_sriov_info()
SR-IOV 情報を取得します。詳細は、リンググループと SR-IOV を参照してください。
データ構造体
登録情報。GLDv3 の MAC 登録データ構造体を参照してください。
ドライバコールバック。GLDv3 の MAC 登録データ構造体を参照してください。
LSO メタデータ。ラージセグメント (送信) オフロードを参照してください。
TCP/IPv4 用の LSO メタデータ。ラージセグメント (送信) オフロードを参照してください。
詳細は、MAC リング機能を参照してください。
詳細は、mr_gget エントリポイントを参照してください。
詳細は、mr_rget エントリポイントを参照してください。
mac_intr_t
mac_sriov_info
MAC 登録関数
新しい mac_register 構造体を割り当てます。GLDv3 の MAC 登録を参照してください。
mac_register 構造体を解放します。
MAC 層に登録します。
MAC 層から登録解除します。
ドライバの dev_ops(9S) 構造体を初期化します。
ドライバの dev_ops 構造体を解放します。
データ転送関数
受信したパケットを上位層に渡します。受信データパスを参照してください。
mac_rx_ring(9F)
受信したパケットを上位層に渡します。受信データパスを参照してください。
TX リソースが利用可能です。GLDv3 の状態変更通知を参照してください。
mac_tx_ring_update(9F)
TX リソースが利用可能です。詳細は、GLDv3 の状態変更通知を参照してください。
リンク状態が変化しました。
ハードウェアチェックサム情報を取得します。ハードウェアチェックサムオフロードおよび送信データパスを参照してください。
ハードウェアチェックサム情報を添付します。ハードウェアチェックサムオフロードおよび受信データパスを参照してください。
LSO 情報を取得します。ラージセグメント (送信) オフロードを参照してください。
プロパティー関数
プロパティーのアクセス権を設定します。GLDv3 のプロパティーを参照してください。
プロパティー値を設定します。
プロパティー値の範囲を設定します。