INFO: Implementation of 64-Bit Statistics in Network Interface Card (NIC) Drivers (263131)
The information in this article applies to:
- Microsoft Windows 2000 Server
- Microsoft Windows 2000 Advanced Server
- Microsoft Windows 2000 Professional
- Microsoft Windows 2000 Driver Development Kit (DDK)
- Microsoft Windows XP Driver Development Kit (DDK)
This article was previously published under Q263131 SUMMARY
Miniport statistics are maintained in 32-bit counters. These counters can overflow very quickly given today's media speeds (for example, it takes about 68 seconds at a sustained throughput of 500 megabits per second [Mpbs] to overflow a 32-bit byte counter). Larger counters are therefore needed. This article shows how to implement 64-bit counters in your driver to resolve this problem (at a sustained throughput of 10 gigabits per second, it takes 467 years to overflow a 64-bit byte counter).
MORE INFORMATION
All Gigabit Ethernet drivers must support 64-bit counters for at least the following object identifiers (OIDs). Microsoft recommends that all 100 Mbps and above network interface card (NIC) drivers should support 64-bit counters. Drivers may support 64-bit counters for other statistics OIDs (for example, OID_GEN_XMIT_ERROR):
// Required statistics.
#define OID_GEN_XMIT_OK 0x00020101
#define OID_GEN_RCV_OK 0x00020102
// Optional statistics.
#define OID_GEN_DIRECTED_BYTES_XMIT 0x00020201
#define OID_GEN_DIRECTED_FRAMES_XMIT 0x00020202
#define OID_GEN_MULTICAST_BYTES_XMIT 0x00020203
#define OID_GEN_MULTICAST_FRAMES_XMIT 0x00020204
#define OID_GEN_BROADCAST_BYTES_XMIT 0x00020205
#define OID_GEN_BROADCAST_FRAMES_XMIT 0x00020206
#define OID_GEN_DIRECTED_BYTES_RCV 0x00020207
#define OID_GEN_DIRECTED_FRAMES_RCV 0x00020208
#define OID_GEN_MULTICAST_BYTES_RCV 0x00020209
#define OID_GEN_MULTICAST_FRAMES_RCV 0x0002020A
#define OID_GEN_BROADCAST_BYTES_RCV 0x0002020B
#define OID_GEN_BROADCAST_FRAMES_RCV 0x0002020C
Implementation
The length of the buffer (InformationBufferLength) that is passed in an NDIS_REQUEST for a statistics OID is used to determine how many bits (64, 128, 256, and so on) are required.
The semantics of fields in NDIS_REQUEST.DATA.QUERY_INFORMATION for statistics is as follows: On Input to NDIS/Miniport
InformationBufferLength = 4 // or 8 bytes depending on what the requestor needs.
On Completion
BytesWritten = MIN(InformationBufferLength, N)
where N is the maximum bytes of statistics implemented by the miniport:
BytesNeeded = N
A miniport that implements 64-bit counters follows the algorithm above to copy the right amount of data to satisfy the request.
A code example follows:
//
// The driver's adapter structure:
//
typedef struct _NICDRIVER_ADAPTER
{
...
ULONG64 TransmitsOk;
...
} _NICDRIVER_ADAPTER, *PNICDRIVER_ADAPTER;
NDIS_STATUS
NicDriverQueryInformation(
IN NDIS_HANDLE MiniportAdapterContext,
IN NDIS_OID Oid,
IN PVOID InformationBuffer,
IN ULONG InformationBufferLength,
OUT PULONG BytesWritten,
OUT PULONG BytesNeeded
)
{
PNICDRIVER_ADAPTER pAdapter;
PVOID MoveSource;
ULONG MoveBytes;
ULONG GenericUlong;
ULONG64 GenericLargeCounter;
ULONG MyBytesNeeded;
NDIS_STATUS Status;
pAdapter = (PNICDRIVER_ADAPTER)MiniportAdapterContext;
MoveSource = &GenericUlong;
MoveBytes = sizeof(GenericUlong);
MyBytesNeeded = MoveBytes;
Status = NDIS_STATUS_SUCCESS;
switch (Oid)
{
case OID_GEN_MAC_OPTIONS:
GenericUlong = (ULONG)(NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |
NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA |
NDIS_MAC_OPTION_NO_LOOPBACK);
break;
case OID_GEN_XMIT_OK:
//
// Modified code to handle 64-bit statistics:
//
GenericLargeCounter = pAdapter->TransmitsOk;
MoveSource = &GenericLargeCounter;
MyBytesNeeded = sizeof(GenericLargeCounter);
//
// A statistics counter is at least a ULONGs worth.
//
if (InformationBufferLength < sizeof(ULONG))
{
// Set up for failure return below.
MoveBytes = MyBytesNeeded;
break;
}
MoveBytes = MIN(InformationBufferLength, MyBytesNeeded);
break;
// Case statements for other OIDs.
}
if (Status == NDIS_STATUS_SUCCESS)
{
*BytesNeeded = MyBytesNeeded;
if (MoveBytes > InformationBufferLength)
{
Status = NDIS_STATUS_BUFFER_TOO_SHORT;
}
else
{
*BytesWritten = MoveBytes;
if (MoveBytes != 0)
{
NdisMoveMemory(InformationBuffer, MoveSource, MoveBytes);
}
}
}
Modification Type: | Minor | Last Reviewed: | 7/27/2004 |
---|
Keywords: | kbinfo kbNDIS kbnetwork KB263131 |
---|
|