パケット トラフィックの複製

このトピックでは、Hyper-V 拡張可能スイッチ拡張機能がパケットをクローンまたは複製し、拡張可能スイッチのデータ パスに挿入する方法について説明します。 パケットの複製の詳細については、「複製 NET_BUFFER_LIST 構造」を参照してください。

注: このページは、Hyper-V 拡張可能スイッチの概要ハイブリッド転送に関する情報と図を理解していることを前提とします。

注: 拡張可能スイッチ インターフェイスで、NDIS フィルター ドライバーは拡張可能スイッチ拡張機能と呼ばれ、ドライバー スタックは拡張可能スイッチ ドライバー スタックと呼ばれます。 拡張機能の詳細については、「Hyper-V 拡張可能スイッチ拡張機能」を参照してください。

拡張可能スイッチのフィルター処理と転送拡張機能では、次のガイドラインに従い、複製されたパケットを拡張可能スイッチのイングレスまたはエグレス データ パスに挿入できます。

  • 拡張機能は、まず複製されたパケットに NET_BUFFER_LIST 構造を割り当てる必要があります。 拡張機能は、元のパケットから複製されたパケットにパケット データをコピーする必要があります。 パケットを複製する方法の詳細については、「派生 NET_BUFFER_LIST 構造」を参照してください。

  • 拡張機能は、新しいパケットまたは複製されたパケットに NET_BUFFER_LIST 構造を割り当てた後、AllocateNetBufferListForwardingContext ハンドラー関数を呼び出してパケットの拡張可能スイッチ転送コンテキストを割り当てる必要があります。

    転送コンテキストは、パケットの帯域外 (OOB) データに存在します。 送信元ポートや 1 つ以上の宛先ポートの配列など、パケットの転送情報が含まれます。

    転送コンテキストの詳細については、「Hyper-V 拡張可能スイッチ転送コンテキスト」を参照してください。

  • 拡張機能は、 CopyNetBufferListInfo を呼び出して、既存のソース ポートを含む OOB データを元のパケットから複製されたパケットにコピーする必要があります。 拡張機能がパケットをイングレス データ パスに挿入することを計画している場合は、元のパケットの OOB データから宛先ポートもコピーする必要があります。

    OOB データをコピーする場合、拡張機能は次のガイドラインに従う必要があります。

    • フィルター処理拡張機能がパケットをイングレス データ パスに挿入することを計画している場合は、NDIS_SWITCH_COPY_NBL_INFO_FLAGS_PRE Standard Edition RVE_DESTINATIONS フラグを指定しない状態で CopyNetBufferListInfo を呼び出す必要があります。 これにより、元のパケットの宛先ポートが複製されたパケットにコピーされません。 フィルター拡張機能がこのパケットをイングレス データ パスに挿入すると、基になる転送拡張機能 (ドライバー スタックで有効になっている場合) または拡張可能スイッチのミニポート エッジによって、宛先ポートがパケットに追加されます。

    • フィルター処理拡張機能がパケットをエグレス データ パスに挿入することを計画している場合は、NDIS_SWITCH_COPY_NBL_INFO_FLAGS_PRE Standard Edition RVE_DESTINATIONS フラグを指定した状態で CopyNetBufferListInfo を呼び出す必要があります。 これにより、元のパケットの宛先ポートが複製されたパケットにコピーされます。

  • フィルター処理拡張機能がエグレス データ パスから取得したパケットを複製または複製している場合は、指定された NDIS_SWITCH_COPY_NBL_INFO_FLAGS_PRE Standard Edition RVE_DESTINATIONS フラグを指定した状態で CopyNetBufferListInfo を呼び出した後で、パケットの宛先ポートを変更できます。 この手順の詳細については、パケットの拡張可能スイッチのソース ポート データの変更を参照してください。

  • 転送拡張機能がイングレス データ パスから取得したパケットを複製または複製する場合は、パケットをイングレス データ パスに挿入する前に、パケットの新しい宛先ポートを追加する必要があります。 この手順の詳細については、拡張可能スイッチの宛先ポート データをパケットに追加するを参照してください。

  • 拡張機能が CopyNetBufferListInfo を呼び出すと、パケットには元のパケットに含まれていたものと同じソース ポート情報が割り当てられます。

    拡張機能は SetNetBufferListSource を呼び出して、パケットの帯域外 (OOB) データのソース ポート情報を変更できます。

    拡張機能では、パケットを特定のポートから送信されたかのように扱う必要がある場合があります。 これにより、そのポートのポリシーをパケットに適用できます。 拡張機能は SetNetBufferListSource を呼び出して、パケットのソース ポートを変更します。

    ただし、拡張機能がパケットのソース ポート識別子を NDIS_SWITCH_DEFAULT_PORT_ID に割り当てたい場合もあります。 たとえば、拡張機能では、外部ネットワーク上のデバイスに送信される独自の制御パケットの NDIS_SWITCH_DEFAULT_PORT_ID にソース ポート識別子を設定したい場合があります。

  • 標準 NDIS データ パスでは、拡張可能スイッチ以外の OOB データは、多くの場合、パケットが送信または受信として示されているかどうかに応じて異なる値を持ちます。 たとえば、NDIS_IPSEC_OFFLOAD_V2_HEADER_NET_BUFFER_LIST_INFO の OOB データは、送受信固有の構造の共用体です

    拡張可能スイッチのデータ パスでは、送信と受信の両方で、すべてのパケットが拡張ドライバー スタックを通過します。 このため、パケットの NET_BUFFER_LIST s構造内の拡張可能スイッチ以外の OOB データは、ドライバー スタックを通過するフローの期間を通じて送受信形式になります。

    この OOB データの形式は、パケットが拡張可能スイッチに到着したソース拡張可能スイッチ ポートによって異なります。 ソース ポートが外部ネットワーク アダプターに接続されている場合、拡張可能スイッチ以外の OOB データは受信形式になります。 その他のポートの場合、この OOB データは送信形式になります。

    ソース ポート情報は、NDIS_SWITCH_FORWARDING_DETAIL_NET_BUFFER_LIST_INFO 共用体(そのパケットの NET_BUFFER_LIST 構造の OOB データ内)に格納されます。 拡張機能は NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL マクロを使用してデータを取得します。

    注: 拡張機能がパケットの NET_BUFFER_LIST 構造を複製する場合は、OOB データを追加または変更する際に拡張可能スイッチ以外の OOB データを考慮する必要があります。 拡張機能は CopyNetBufferListInfo を呼び出して、ソース パケットから複製されたパケットにすべての OOB データをコピーできます。 この関数は、データがパケットにコピーされるときに OOB の送受信形式を維持します。

  • 拡張機能がパケットを複製すると、複製されたパケット データは、Hyper-V 親パーティションの親オペレーティング システムのローカルまたは高信頼メモリに配置されます。 このメモリーには、子パーティションからアクセスできません。 そのため、そのパーティションで実行されているゲスト オペレーティング システムによる非同期の更新から「安全」と見なされます。

    元のパケットが複製された後、拡張機能は、複製されたパケット内の NDIS_SWITCH_FORWARDING_DETAIL_NET_BUFFER_LIST_INFO 共用体を NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL マクロを使用して取得する必要があります。 拡張機能では、 IsPacketDataSafe メンバーを TRUE に設定する必要があります。 これは、すべてのパケット データが信頼されたメモリに配置されることを指定します。

拡張機能のフィルター処理と転送は、イングレスまたはエグレス データ パスに複製されたパケットを挿入するために、次のガイドラインに従う必要があります。

  • 拡張機能は NdisFSendNetBufferLists を呼び出して、複製されたパケットをイングレス データ パスに挿入する必要があります。 拡張機能は、適切な拡張可能スイッチ フラグ設定で SendFlags パラメーターを設定する必要があります。 これらのフラグ設定の詳細については、「Hyper-V 拡張可能スイッチの送受信フラグ」を参照してください。

    NDIS は、拡張機能の FilterSendNetBufferListsComplete関数を呼び出して、複製されたパケットの送信要求を完了する場合、割り当てられた転送コンテキストを解放するために FreeNetBufferListForwardingContextを呼び出す必要があります。 拡張機能は、パケットの NET_BUFFER_LIST 構造を解放または再利用する前に、これを行う必要があります。

    注: 拡張機能は、エグレス データ パスから取得したパケットのパケット データまたはソース ポートを変更する場合、複製されたパケットをイングレス データ パスに挿入する必要があります。 また、パケットの宛先ポートが保持されない場合は、複製されたパケットをイングレス データ パスに挿入する必要があります。

  • 拡張機能は NdisFIndicateReceiveNetBufferLists を呼び出して、複製されたパケットをエグレス データ パスに挿入する必要があります。 拡張機能は、適切な拡張可能スイッチ フラグ設定で ReceiveFlags パラメーターを設定する必要があります。

    NDIS が拡張機能の FilterReturnNetBufferLists 関数を呼び出して複製されたパケットの受信要求を完了する場合、拡張機能は、パケットのFreeNetBufferListForwardingContext の呼び出しをパケットの NET_BUFFER_LIST 構造の解放前に行う必要があります。

    : 転送拡張機能が NdisFIndicateReceiveNetBufferLists を呼び出す前に、複製されたパケットの宛先ポートを特定し、このデータをパケットの OOB データに追加する必要があります。

  • 拡張機能がパケットの NET_BUFFER_LIST 構造を複製する場合は、複製されたパケットの送受信要求が完了するまで、元のパケットの NET_BUFFER_LIST 構造の所有権を保持する必要があります。 拡張機能は、 ParentNetBufferList メンバーを複製されたパケットの NET_BUFFER_LIST 構造から使用して、元のパケットの NET_BUFFER_LIST 構造にリンクする必要があります。

    : NDIS 6.30 (Windows Server 2012) では、拡張機能は ParentNetBufferList メンバーを使用して元のパケットにリンクできますが、そうすることは必須ではありません。 NDIS 6.40 (Windows Server 2012 R2) 以降では、拡張機能は ParentNetBufferList メンバーを使用して元のパケットにリンクする必要があります。

    複製されたパケットの送受信要求が完了したら、拡張機能は元のパケットの送受信要求を完了する必要があります。

    : 拡張機能がパケットの NET_BUFFER_LIST 構造を複製した場合は、複製後に元のパケットの送受信要求を完了できます。

  • 拡張機能がパケットを複製する場合は、複製されるとすぐに元のパケットの送受信要求を完了できます。

転送またはフィルター処理拡張機能がエグレス データ パスでパケットを取得した場合、拡張機能がパケット データを変更したり、ソース ポートを変更したりする際に、このデータ パスに複製されたバージョンのパケットを挿入することはできません。 ただし、拡張機能は、これらのパケットをイングレス データ パスに挿入できます。 これにより、拡張可能スイッチのデータ パスを介してパケットを正しく転送およびフィルター処理できます。

: フィルタリング拡張機能は、パケットの宛先ポートが保持されていない場合にのみ、イングレス データ パスに複製されたパケットを挿入できます。

たとえば、拡張可能スイッチ エグレス データ パスで複数の宛先ポートを持つパケットが取得されたとします。 1 つの宛先ポートでデータ カプセル化などの特別な処理が必要な場合、転送またはフィルター処理拡張機能は、次の手順に従ってこれを処理します。

  1. 特別な処理を必要とするポートへのパケット配信を除外します。 拡張機能は、IsExcluded メンバーを宛先ポートの NDIS_SWITCH_PORT_DESTINATION 構造で 1 の値に設定することでこれを行います。 この手順の詳細については、「拡張可能スイッチ宛先ポートへのパケット配信の除外」を参照してください。

  2. 元のパケットを複製し、パケット データの必要な処理を実行します。

    : フィルタリング拡張機能は、複製されたパケットの宛先ポートを追加してはなりません。 このデータは、転送拡張機能または拡張可能スイッチのミニポート エッジによって後で追加されます。

  3. NdisMIndicateReceiveNetBufferLists を呼び出して、エグレス データ パスの元のパケットを転送します。

  4. NdisFSendNetBufferLists を呼び出して、イングレス データ パスに複製されたパケットを挿入します。

拡張可能スイッチのイングレスおよびエグレス データ パスの詳細については、「Hyper-V 拡張可能スイッチのデータ パス」を参照してください。

: キャプチャ拡張機能は、パケット トラフィックを複製できません。 ただし、パケット トラフィックを発信することはできます。 詳細については、「送信元パケット トラフィック」を参照してください。