タイムスタンプをパケットにアタッチする

ミニポート ドライバーがタイムスタンプ機能が存在し、現在有効になっていることを報告した後、ドライバーは、NET_BUFFER_LIST (NBL) 構造を使用して、パケットに関連するタイムスタンプを添付できます。

NIC のハードウェア タイムスタンプ機能とミニポート ドライバーのソフトウェア タイムスタンプ機能をオペレーティング システムに報告する方法の詳細については、「タイムスタンプ機能と現在の構成を報告する」を参照してください。

ハードウェア タイムスタンプ

NDIS_TIMESTAMP_CAPABILITY_FLAGS 構造のPtpV2OverUdpIPv4EventMsgReceiveHwPtpV2OverUdpIPv4AllMsgReceiveHwPtpV2OverUdpIPv4EventMsgTransmitHwPtpV2OverUdpIPv4AllMsgTransmitHwPtpV2OverUdpIPv6EventMsgReceiveHwPtpV2OverUdpIPv6AllMsgReceiveHwPtpV2OverUdpIPv6EventMsgTransmitHwPtpV2OverUdpIPv6AllMsgTransmitHwAllReceiveHwAllTransmitHwおよびTaggedTransmitHwフラグは、ミニポート ドライバーがサポートするハードウェア タイムスタンプを示します。

パケットの受信または送信時に NIC ハードウェアが生成するタイムスタンプは、64 ビット整数値で表されます。 これは、タイムスタンプがキャプチャされた時点での NIC ハードウェアのクロックの生の値である必要があります。 タイムスタンプは、NBL 構造の NetBufferListInfo 配列に格納されます。

ミニポート ドライバーは、NBL の NetBufferListInfo フィールドにタイムスタンプを設定する NET_BUFFER_LIST_TIMESTAMP 構造を使用できます。 ドライバーは、ハードウェアによって生成されたタイムスタンプを NET_BUFFER_LIST_TIMESTAMP 構造の Timestamp フィールドに入力し、NdisSetNblTimestampInfo ユーティリティ関数を呼び出して構造体を渡します。

ミニポート ドライバーは、NdisGetNblTimestampInfoNdisCopyNblTimestampInfo を使用してタイムスタンプを取得およびコピーできます。

特定のハードウェア タイムスタンプ設定が有効になっていても、その機能に対応するタイムスタンプが生成されない場合、ミニポートは NBL にアタッチするタイムスタンプを 0 に設定する必要があります。

Note

ハードウェア タイムスタンプを生成するために PTP バージョン 2 のパケットを認識する場合、実装では、PTP 仕様で指定されているマルチキャスト アドレス (IPv4 と IPv6 の両方) を使用するパケットにタイムスタンプの生成を制限しないでください。 実装では、UDP ヘッダーや PTP ペイロードを使用するなど、他の方法で PTP パケットを認識する必要があります。 そのため、PTP 実装で PTP 仕様で指定されたマルチキャスト アドレス (ユニキャスト アドレスが使用されている場合など) を使用しない可能性があるシナリオでは、タイムスタンプが生成されます。

受信側のタイムスタンプ

ハードウェアは、ハードウェアがメディアからフレームを受信する時点にできるだけ近いタイムスタンプを取得する必要があります。 このガイドラインは、IEEE 1588 標準で規定されています。

パケットを受信したら、ミニポート ドライバーは次を行う必要があります。

  1. ハードウェアがタイムスタンプをキャプチャしてから、ハードウェアが実際にフレームを受信するまでの間に存在する遅延のタイムスタンプを修正します。

  2. ハードウェアで生成されたタイムスタンプを NBL にアタッチします。 タイムスタンプは、NBL に含まれるフレーム (NET_BUFFER 構造) に対応します。

  3. NdisMIndicateReceiveNetBufferLists を呼び出して、NBL を NDIS に示します。

受信方向では、イーサネット ハードウェアのミニポート ドライバーは、NBL ごとに 1 つの NET_BUFFER のみを示す必要があることに注意してください。

送信側のタイムスタンプ

ハードウェアは、ハードウェアがメディアからフレームを送信する時点にできるだけ近いタイムスタンプを取得する必要があります。 このガイドラインは、IEEE 1588 標準で規定されています。

パケットを送信したら、ミニポート ドライバーは次を行う必要があります。

  1. ハードウェアがタイムスタンプをキャプチャしてから、ハードウェアが実際にフレームを送信するまでの間に存在する遅延のタイムスタンプを修正します。

  2. ハードウェアで生成されたタイムスタンプを NBL にアタッチします。 NBL に複数の NET_BUFFER が含まれている場合は、NBL の最初 のNET_BUFFER に対応するハードウェア タイムスタンプを NBL にアタッチする必要があります。

  3. NdisMSendNetBufferListsComplete を呼び出して、NBL を NDIS に完全に送信します。

TaggedTransmitHw機能フラグがサポートされ、現在有効になっていることを報告するミニポートと NIC ハードウェアは、送信用にミニポートに指定された NBL の NblFlags フィールドにNDIS_NBL_FLAGS_CAPTURE_TIMESTAMP_ON_TRANSMITフラグが設定されている場合にチェックする必要があります。 このフラグが設定されている場合、これは、その NBL に送信時間タイムスタンプが必要であり、NBL に対して送信時間ハードウェア タイムスタンプを生成する必要があることを示します。

ソフトウェアのタイムスタンプ

AllReceiveSwAllTransmitSw および TaggedTransmitSwNDIS_TIMESTAMP_CAPABILITY_FLAGS 構造のフラグは、ミニポートがソフトウェアタイムスタンプの生成をサポートしているかどうかを示します。

ソフトウェア タイムスタンプは 64 ビット整数値としても表され、ハードウェア タイムスタンプと同じスロットに、NET_BUFFER (NBL) 構造の NetBufferListInfo 配列に格納されます。

ソフトウェアタイムスタンプ機能が存在し、有効になっている場合、ミニポート ドライバーは、パフォーマンス カウンター値 (QPC) を使用して NBL のタイムスタンプを設定します。 ミニポート ドライバーは、次を行う必要があります。

  1. KeQueryPerformanceCounter を呼び出して QPC を取得します。

  2. NET_BUFFER_LIST_TIMESTAMP 構造の Timestamp フィールドに QPC を入力します。

  3. NdisSetNblTimestampInfo を呼び出し、NET_BUFFER_LIST_TIMESTAMP を渡すことによって、NBL のタイムスタンプを設定します。

受信時にミニポート ドライバーは、できるだけ早く、ただしパケットの到着より後に QPC をキャプチャする必要があります。

送信時、ミニポート ドライバーはパケットが送信のためにハードウェアに渡される前の、できるだけ遅らせたタイミングで QPC をキャプチャする必要があります。

TaggedTransmitSwフラグはTaggedTransmitHwフラグに似ていますが、ソフトウェアのタイムスタンプに対応します。 機能がサポートされ、有効になっている場合、ミニポートは NBL の NblFlags フィールドの NDIS_NBL_FLAGS_CAPTURE_TIMESTAMP_ON_TRANSMIT フラグをチェックする必要があります。 このフラグが設定されている場合、ミニポートは NBL の送信時間ソフトウェアタイムスタンプを生成する必要があります。