UDP 受信セグメント結合オフロード (URO)
Windows 11 バージョン 24H2 以降では、UDP 受信セグメント結合オフロード (URO) により、ネットワーク インターフェイス カード (NIC) が UDP 受信セグメントを結合できるようになります。 NIC は、ルールのセットに一致する同じフローの UDP データグラムを論理的に連続したバッファーに結合できます。 これらの結合されたデータグラムは、1 つの大きなパケットとして Windows ネットワーク スタックに示されます。
UDP データグラムを結合すると、高帯域幅フローでパケットを処理するための CPU コストが削減され、スループットが高くなり、バイトあたりのサイクル数が少なくなります。
次のセクションでは、UDP パケットを結合するための規則と、URO ミニポート ドライバーを記述する方法について説明します。
- UDP パケット を結合するための
規則 - URO ミニポート ドライバーの を書き込む
- URO ドライバーのプログラミングに関する考慮事項
UDP パケットの結合に関する規則
URO 結合は、次のすべての条件を満たすパケットでのみ試行できます。
IpHeader.Version
はすべてのパケットで同じです。IpHeader.SourceAddress
とIpHeader.DestinationAddress
はすべてのパケットで同じです。UdpHeader.SourcePort
とUdpHeader.DestinationPort
はすべてのパケットで同じです。UdpHeader.Length
は、最後のパケットを除くすべてのパケットで同じですが、これは少なくなる可能性があります。UdpHeader.Length
は 0 以外である必要があります。UdpHeader.Checksum
、0 以外の場合は、すべてのパケットで正しい必要があります。 つまり、受信チェックサム オフロードはパケットを検証する必要があります。Layer 2 headers
は、すべてのパケットで同じである必要があります。
パケットが IPv4 の場合は、次の条件も満たす必要があります。
- すべてのパケットに対して、
IPv4Header.Protocol
が 17(UDP)である必要があります。 EthernetHeader.EtherType
== すべてのパケットに対して0x0800です。- 受信したパケットの
IPv4Header.HeaderChecksum
が正しい必要があります。 つまり、受信チェックサム オフロードではヘッダーを検証する必要があります。 - すべてのパケット
IPv4Header.HeaderLength
== 5 (IPv4 オプション ヘッダーなし) です。 IPv4Header.ToS
はすべてのパケットで同じです。IPv4Header.ECN
はすべてのパケットで同じです。IPv4Header.DontFragment
はすべてのパケットで同じです。IPv4Header.TTL
はすべてのパケットで同じです。-
IPv4Header.TotalLength
==UdpHeader.Length
* + すべてのパッケージ長 (IPv4Header
)。
パケットが IPv6 の場合は、次の条件も満たす必要があります。
- 拡張ヘッダーなしのすべてのパケットについて、
IPv6Header.NextHeader
== 17 (UDP) です。 - すべてのパケットに対して
EthernetHeader.EtherType
が 0x86dd (IPv6) です。 IPv6Header.TrafficClass
とIPv6Header.ECN
はすべてのパケットで同じです。IPv6Header.FlowLabel
はすべてのパケットで同じです。IPv6Header.HopLimit
はすべてのパケットで同じです。- すべてのパケットに対して
IPv6Header.PayloadLength
==UdpHeader.Length
。
URO パケット構造
結果として得られる単一結合ユニット (SCU) には、単一の IP ヘッダーと UDP ヘッダーが必要です。その後に、結合されたすべてのデータグラムの UDP ペイロードが連結されている必要があります。
URO 表示では、IPv4Header.TotalLength
フィールドを SCU の合計長に設定するか、または IPv6Header.PayloadLength
フィールドを UDP ペイロードの長さに設定し、UdpHeader.Length
フィールドを合体ペイロードの長さに設定する必要があります。
レイヤー 2 (L2) ヘッダーが結合されたデータグラムに存在する場合、SCU には有効な L2 ヘッダーが含まれている必要があります。 SCU の L2 ヘッダーは、結合されたデータグラムの L2 ヘッダーに似ている必要があります。
チェックサムの検証と表示
URO 表示では、IPv4Header.HeaderChecksum
フィールドと UdpHeader.Checksum
フィールドをゼロに設定し、SCU のチェックサム オフロードアウトオブバンド情報に IPv4 と UDP チェックサムの成功を示す情報を入力する必要があります。
結合されるすべての条件に一致するがチェックサム検証に失敗するパケットは、個別に指定する必要があります。 その後に受信したパケットは、それ以前に受信したパケットと結合してはなりません。
たとえば、同じフローからパケット 1、2、3、4、5 を受信したが、パケット 3 はチェックサム検証に失敗したとします。 パケット 1 とパケット 2 は一緒に結合でき、パケット 4 とパケット 5 は一緒に結合できますが、パケット 3 はどちらの SCU とも結合しないでください。 パケット 1 とパケット 2 は、パケット 4 および 5 と結合してはなりません。 パケット 2 は SCU の最後のパケットであり、パケット 4 は新しい SCU を開始します。 さらに、パケット 1 とパケット 2 を含む SCU は、パケット 3 を示す前に指定する必要があります。パケット 3 は、パケット 4 と 5 を含む SCU の前に指定する必要があります。
パケット結合とフロー分離
ハードウェアとメモリの許可に従って、複数のフローからのパケットを並列に結合できます。 異なるフローのパケットを結合することはできません。
インターリーブされた複数の受信からのパケットは、それぞれのフローに分離、結合できます。 たとえば、フロー A、B、C を指定すると、パケットが A、A、B、C、B、A の順序で到着した場合、A フローからのパケットは AAA に結合され、B フローからのパケットは BB に結合されますが、C フローからのパケットは通常示されるか、フロー C から保留中の SCU と結合されます。
特定のフロー内のパケットは、互いに並べ替えてはなりません。 たとえば、A フローからのパケットは、B フローと C フローの間で受信したパケットに関係なく、受信した順序で結合する必要があります。
URO を制御するための INF キーワード
レジストリ キー設定で URO を有効または無効にするには、次のキーワードを使用できます。
*UdpRsc
列挙標準化 INF キーワードには、次の属性があります。
SubkeyName: INF ファイルで指定する必要があり、レジストリに表示されるキーワードの名前。
ParamDesc: SubkeyName に関連付けられている表示テキスト。
値: リスト内の各オプションに関連付けられている列挙整数値。 この値は、NDI\params\SubkeyName\Valueに格納されます。
EnumDesc: メニューに表示される各値に関連付けられている表示テキスト。
既定の: メニューの既定値。
SubkeyName | ParamDesc | 価値 | EnumDesc |
---|---|---|---|
*UdpRsc |
URO | 0 | いいえ |
1 (既定値) | 有効 |
列挙キーワードの使用の詳細については、「列挙キーワードの」を参照してください。
URO ミニポート ドライバーを記述する
NDIS 6.89 以降では、URO の NDIS インターフェイスは、TCP/IP と NDIS ミニポート ドライバー間の通信を容易にします。
URO機能のレポート
ミニポート ドライバーは、NdisMSetMiniportAttributes 関数に渡される、NDIS_OFFLOAD 構造体の UdpRsc
メンバーの URO のサポートをアドバタイズします。
URO 機能のクエリ
ミニポート ドライバーが URO をサポートしているかどうかを確認するには、NDIS ドライバーとその他のアプリケーションは、NDIS_OFFLOAD
構造体を返す OID_TCP_OFFLOAD_HARDWARE_CAPABILITIES OID を照会できます。
URO の状態を照会する
現在の URO 状態を確認するには、NDIS ドライバーとその他のアプリケーションは、OID_TCP_OFFLOAD_CURRENT_CONFIG OID 要求を照会できます。 NDIS はこの OID を処理し、ミニポートに渡しません。
URO の状態を変更する
URO は、OID_TCP_OFFLOAD_PARAMETERS OID 要求を発行することによって有効または無効にすることができます。 この OID は、NDIS_OFFLOAD_PARAMETERS 構造体を使用します。 この構造体では、UdpRsc.Enabled
メンバーは次の値を持つことができます。
価値 | 意味 |
---|---|
NDIS_OFFLOAD_PARAMETERS_UDP_RSC_NO_CHANGE 0 |
ミニポート ドライバーは、現在の設定を変更しないでください。 |
NDIS_OFFLOAD_PARAMETERS_UDP_RSC_DISABLED 1 |
URO は無効です。 |
NDIS_OFFLOAD_PARAMETERS_UDP_RSC_ENABLED 2 |
URO が有効になっています。 |
ドライバーが NDIS_OFFLOAD_PARAMETERS_UDP_RSC_DISABLED
フラグが設定された OID_TCP_OFFLOAD_PARAMETERS OID 要求を処理する場合、NIC は、既存のすべての結合セグメントと未処理の URO 表示が示されるまで、要求の完了を待機する必要があります。 これにより、NDIS コンポーネント間での URO の有効化/無効化イベントの同期が保証されます。
ミニポート ドライバーが、OID_TCP_OFFLOAD_PARAMETERS OID リクエストを処理したら、更新されたオフロード状態を含む NDIS_STATUS_TASK_OFFLOAD_CURRENT_CONFIG 状態表示を発行する必要があります。
NDIS_OFFLOAD_PARAMETERS の NDIS_OFFLOAD_PARAMETERS_SKIP_REGISTRY_UPDATE
フラグを使用すると、ランタイムのみの URO を無効にできます。 このフラグで行われた変更はレジストリに保存されません。
NDIS 6.89 以降での URO のオプトアウト
NDIS 6.89 以降を対象とするドライバーは、URO パケットを理解し、適切に処理する必要があります。 URO をオプトアウトするには:
- ライトウェイト フィルター (LWF) ドライバーは、NDIS_FILTER_DRIVER_CHARACTERISTICS 構造体で
NDIS_FILTER_DRIVER_UDP_RSC_NOT_SUPPORTED
フラグを設定します。 - プロトコル ドライバーは、NDIS_PROTOCOL_DRIVER_CHARACTERISTICS 構造体で
NDIS_PROTOCOL_DRIVER_UDP_RSC_NOT_SUPPORTED
フラグを設定します。
この方法により、URO に慣れていないコンポーネントが URO NBL を受け取らないようにします。 NDIS は、URO をサポートしていない LWF またはプロトコル ドライバーが存在する場合、バインド中にミニポートの URO を無効にします。
URO ドライバーのプログラミングに関する考慮事項
URO 対応ミニポート ドライバーを実装する場合は、次の問題を考慮してください。
Winsock URO API
Winsock URO API の詳細については、IPPROTO_UDP ソケット オプションを参照してください。 UDP_RECV_MAX_COALESCED_SIZE
と UDP_COALESCED_INFO
に関する情報を参照してください。
Windows TCP/IP スタックの更新
Microsoft TCP/IP トランスポートでは、NDIS とのバインド時に URO が有効になります。ただし、構成でこれを妨げる場合を除きます。
WFP コールアウトでは、FWPS_CALLOUT2 の FWP_CALLOUT_FLAG_ALLOW_URO
を使用して、URO のサポートをアドバタイズできます。 互換性のない WFP 吹き出しが URO に依存するレイヤーに登録されている場合、OS はコールアウトの登録中に URO を無効にします。
ソケットがハードウェア オフロード サイズ以上の最大合体サイズを持つ URO にオプトインすると、スタックは、ハードウェアから変更されていない NBL をソケットに配信します。 ソケットがより小さい最大合体サイズにオプトインすると、スタックは合体受信をソケットの小さいサイズに分割します。
ソケットが URO にオプトインしない場合、スタックはそのソケットの受信を再セグメント化します。 ハードウェア URO がない場合、既存のソフトウェア URO 機能は引き続き使用できます。