📜 ⬆️ ⬇️

NDIS. NET_BUFFER architecture

We continue the series of articles about NDIS. In this topic, we consider the versions of NDIS, and the principles of packet transfer between stack drivers and the NET_BUFFER architecture. image



Introduction


')
First, let's look at the versions of NDIS and their features due to the fact that there are a little more than one of them.



Old trash in the form of W2K with its NDIS 4.0 I will not touch, because there is no sense to support it. Microsoft also stops supporting NDIS 5.1 in Windows 8.
As you can see from the list, a huge gap lies between NDIS 5.x and NDIS 6.x. In fact, from the general, they only have an architectural feature and a library of functions. The rest of the filling was moved to improve performance. By the way, this increase was investigated by 20%, so that at least in something Vista is better than its predecessor. Driver-filters were added to the architecture, which were lacking in previous versions. The principles of packet transfer have changed dramatically, namely: if before the intermediate driver had to implement at least three functions of receiving and sending packets, now the number of these functions is in any case one. This is made possible by the new packet-passing architecture called NET_BUFFER. We will talk about it below.

NET_BUFFER architecture


So what is it? In fact, NET_BUFFER is a replacement for the previous NDIS_BUFFER'y, but first things first. What happened? The driver implements three functions of sending and receiving packets. Speaking Russian, we call these functions like this:



It is clear that in order to receive one packet, it was necessary to perform a bunch of actions. And for intermediate drivers, in general, disassemble the package to the bone, assemble your own (for you can’t touch something that’s not yours) and send it. Therefore, the NET_BUFFER architecture was introduced in NDIS 6.x.
According to this architecture, it is sufficient to implement 2 functions each for receiving and sending a packet (now it is not a packet, but a buffer, therefore, take these words as synonyms below when it comes to NDIS 6+). Yes, I lied about 2x, but these two do not do anything special and wander from the driver to the driver without changes. So, the functions of receiving and sending, I will write here their signatures for a general understanding:

VOID FilterSendNetBufferLists( IN NDIS_HANDLE FilterModuleContext, IN PNET_BUFFER_LIST NetBufferLists, IN NDIS_PORT_NUMBER PortNumber, IN ULONG SendFlags ); VOID FilterReceiveNetBufferLists( IN NDIS_HANDLE FilterModuleContext, IN PNET_BUFFER_LIST NetBufferLists, IN NDIS_PORT_NUMBER PortNumber, IN ULONG NumberOfNetBufferLists, IN ULONG ReceiveFlags ); 


The first parameters are essentially a pointer that will pass you NDIS. When registering the driver, or rather when it is attached to the queue, you can specify this very pointer. So we always have a reference to a user variable, which, as we know, has unlimited scope. Very comfortably.
The second parameters are pointers to NET_BUFFER lists. We will deal with this later.
All other parameters are rarely used, so we will not consider them.

We turn to the architecture itself.
The picture below roughly describes the architecture:

image

Each NET_BUFFER can describe a package like the image below:
image

Our package is stored in the shaded space. As you can see, this is not necessarily a continuous block of memory; one packet can be scattered throughout the system address space. It is also advised to store packages in non-paged memory (for reference: when trying to access the paged memory at IRQL> = DISPATCH_LEVEL, we will get a blue screen with the code D1. DRIVER_IRQL_NOT_LESS_OR_EQUAL, the most frequent driver-writer error).

Immediately the question why leave empty space in front of the package? So that when the IP packet goes down, it turns into an Ethernet frame to send. And in order not to rebuild this case, the Ethernet header is simply written before the packet. Thoughtfully enough. The same principle is implemented in the top level drivers. All information about the so-called. The backfill (also known as DataOffset) of the space, offset, and buffer length is stored in the NET_BUFFER structure. I also want to note that the buffer size can be changed, i.e. the beginning of the buffer can be moved to the left, or the end to the right. Special functions exported by the NDIS kernel are used for this.

Instead of conclusion


This article intends to miss a huge amount of detail that I encountered in the process of studying the NDIS subsystem. I do not publish them, because the amount of material, however, would not fit in any reasonable framework. At the same time I try to shed light on some key features that I consider basic to understand the essence of what is happening.

Additional literature read here:

www.codemachine.com/article_ndis6nbls.html
msdn.microsoft.com/en-us/library/ff564881 (v = vs.85) .aspx

Until next time.

Source: https://habr.com/ru/post/113255/


All Articles