> I see your point as I don’t really understand how to do the cancel-safe part. However I also don’t know where I would start on the filter driver. Is the miniport/filter pair the correct model to accomplish this? I’m boggled that this is such a difficult functionality to attain
For example if I take the NDIS 6.0 Filter Driver example from the sdk samples it doesn’t look like I’ll have to do too much to make it work with the IRP style IO for a userspace program, however how would I have to adjust the miniport driver and the filter driver so that they interact properly?
Uggh. Sorry. I failed to clearly communicate that the “filter driver” I was talking about is *NOT* an NDIS Light Weight Filter driver but a PnP Filter driver. The last thing you need is a LWF.
A PnP Filter driver is a participant in the NT I/O device stack for a PnP device. Basically it can get involved in IRP processing.
A LWF driver is a participant in the NDIS data & control path of a network stack.
The idea of using a lower PnP Filter ‘below’ the Miniport is to separate your problem into two ‘concerns’ each in their own driver.
Concern #1 is interfacing to NDIS as a (virtual) NIC. This must be an NDIS Miniport driver and NDIS will own the NT I/O dispatch as the “Port” driver. You cannot, for example, use WDF to manage IRP processing.
Concern #2 is interfacing to NT I/O (your application via Read/Write/DeviceIoControl). Here it would be really quite helpful to your productivity and the correctness of the solution if you could leverage WDF to manage the IRP processing.
You could of course forego WDF and use the NDIS registered device (control device) mechanism and handle the IRP processing as one would in a WDM (old-school) driver and you could use the IoCsqXxx cancel-safe-queue helper routines to deal with I/O cancelation and request parking, etc.
But if you could separate those concerns into two separate drivers, one and NDIS Miniport and the other a WDF PnP driver then you could build both in their required or optimal models.
That is all I was trying to get across. Communicating between the NDIS Miniport and the PnP Filter is quite simple. There was once a sample (in older WDKs) that demonstrated this. It was an NDIS Miniport driver layered over a PnP driver that managed the actual hardware. I recall the samples were called VNETMINI and some corresponding E100BX driver.
Also from a logistical standpoint how does one go about developing a project like this? Should I keep my miniport driver project as is and then have a separate project for the filter driver? Then to test you have to deploy both, install the miniport then install the filter onto it?
The overall project is two drivers and one INF file combined to create a single “Driver Package”. It is a single logical driver as far as PnP is concerned and when it is installed on your virtual device both the Miniport and PnP Filter will be installed as a single logical action.
Yes I’ve read through a couple Tun Tap drivers but can’t really understand their flow, presumably this is the adapter and then filter layered model?
I doubt any of the public source TunTap drivers implement this model and the reason is primarily because they all have their lineage trailing back to NT4 and Win9x. 
Irrespective of the choice of one Miniport or Miniport and lower Filter the flow is the same:
-
UM app opens some device for I/O.
-
UM app pends Read (or IOCTL) requests on the device to give the driver requests to complete inbound NDIS frames into. In other words, this is where your Miniport Send path will deposit frames ; e.g. copy whatever part of the packet you are capturing into the buffer described by the I/O request. At that point the I/O request is ‘completed’ and your UM app can then do what it does. The UM app needs to keep pending Read requests of course.
-
UM app issues a Write (or IOCTL) request on the device to give the driver a request describing a packet to inject into the Miniport Receive path. You can either copy and stage the data into a new buffer or you can get clever and describe the NetBuffer MDL chain to NDIS referencing the MDL chain from the I/O request. Just keep in mind that data copy is rarely the performance issue that people think it might be on modern CPUs and this type of problem. Also NDIS has some frame composition rules and frankly it is just easier to have a pool of NBLs that are all setup to hold frames for injection that are allocated ‘flat’ and just avoid all of the nonsense of assembling a MAC frame from whatever your UM app sends you.
-
When your UM app is done, it cancels any pending I/O (the Reads) and waits for Sends to complete and closes the device object.
Some of the confusion in the examples you might be looking at might come from trying to implement a “signal and poll” model of read instead of the more efficient model of pending read requests. If you see any goofiness that involves the UM app and driver sharing an event handle, that is what is going on. If you see things like convoluted buffering schemes (ring buffers or mapped shared memory) it is just a complex attempt at dealing with a non-problem (memory copy speed).
Good Luck,
Dave Cattley