NDIS relationship between Net Buffer MDL and SGL Elements

I know this might sound like a strange question. I’ve waffled between being convinced one way and then the other and then to not sure and back.

Background: I’m working on an NDIS 6.0 driver for Windows Embedded Compact 7. There are minor differences, mostly relaxed requirements, but very similar to desktop Windows NDIS.
When performing the processing for preparing a NET_BUFFER (ethernet frame) for processing, I scan the MDL in the NET_BUFFER structure. I do some optimizations to determine if I need to allocate a Scatter-Gather List or if the packets are small enough, just copy them to a preallocated shared-memory buffer. Sometimes I have to create a Scatter-Gather list to process to send to my hardware. If the supplied buffer is not aligned on a 64-byte boundary (hardware requirement) I have to use both. I’m not really wanting to get into the details further than that.

Now for the question:
Is there a 1-to-1 relationship between the number of MDLs and the number of elements in the SGL? The documentation doesn’t address this specifically that I can tell.

My first assumption is the relationship is 1:1. I base this upon a comment in wdm.h that states “An MDL describes pages in a virtual buffer in terms of physical pages”. This would lead me to believe there is a 1:1 relationship because each SGL Element represents a group of contiguous pages and so does an MDL.

Any NDIS Internals experts have a better insight?

Thanks,
Greg

I can’t tell if you made a mistake in asking your question, or if you misunderstand. An MDL essentially IS a scatter/gather list. Each entry in the MDL is a contiguous chunk of physical memory, and thus becomes one entry in the scatter/gather list.

It really depends on what you’re asking, specifically. I can tell you for the WDM/F interfaces, the relationship is not one to one. Logically adjacent (MDL) pages are combined into a single S/G element… so S/G elements can each be > PAGE_SIZE.

Peter

Windows Embedded Compact 7

I don’t own NDIS on that platform, although I’ve had lunch with the person who did. As far as I know, the answers to this question are the same as on Windows NT, so I’ll proceed to answer your question as if it was asked about NT.

Any NDIS Internals experts have a better insight?

This much actually isn’t specific to NDIS; it’ll be the same in any WDM stack. NDIS doesn’t really impose any restrictions on the shape of the MDL chain or its resulting SGL.

Is there a 1-to-1 relationship between the number of MDLs and the number of elements in the SGL? The documentation doesn’t address this specifically that I can tell.

No there is not a 1-to-1 relationship. Let me illustrate with a couple examples. Terminology: a scatter gather list (SGL) is a list of scatter gather elements (SGEs).

Example: 1 MDL but 2 entries in the SGL. An MDL describes a virtually-contiguous block of memory, which may not at all be physically-contiguous. (This is why it is a “Memory Descriptor List”; the list is a list of physical pages.) So any MDL whose ByteCount >= 2 could span more than one physical page. HAL’s DMA logic will try to map the MDL (even in the pathological case of 2 bytes spread across 2 pages). While the HAL does optimize for the case where the physical pages do happen to be contiguous, the network stack doesn’t typically guarantee this, so you’ll typically see each page land on a separate SGE.

Example: 2 MDLs but 1 entry in the SGL. Two MDLs could get really lucky and point to consecutive physical pages, so in theory, HAL could map that all to a single SGE. But our current HAL implementation does not bother trying for this optimization, since it’s so unlikely to happen in practice. But what can happen in practice is that the HAL decides that your device can’t directly address the pages, so it bounces the transfer. If the transfer is bounced, then you’ll get back a single SGE that points to the now-contiguous buffer.

Between the two examples above, you can have more SGEs than MDLs, or more MDLs than SGEs. So there’s no fixed relationship at all between SGEs and MDLs.

If you work out the upper bound, you’ll find that a 1500-byte packet could, in the most pathological case, be smeared across 1500 different SGEs. That’s obviously horrible, and while it’s unlikely to happen in practice, I have seen certain drivers (cough smb cough) send down a packet with more than 20 MDLs. So it’s very entirely reasonable to have some bouncing/coalescing logic in your driver, to avoid all the overheads of supporting highly-fragmented packets.

Reading back, and more carefully, I think Mr. Tippet has answered the actual question the OP asked… and not the one that I read and answered. The question was:

between the number of MDLs and the number of elements in the SGL? T

I read “MDLs” as shorthand for “MDL entries” (that is PFNs in a given MDL), not “MDL in an MDL chain”… which is super common in NDIS and not so much elsewhere in NT.

Bravo and thank you, again, Mr. Tippet.

P