NDIS学习笔记二——(模拟丢包)
今天本來想發篇正式點的BLOG,沒想到沒有保存住, 以后word打開不敢隨便關閉啥提示了。
以下是網絡上的文章的摘錄,但已經能反應整個的思路過程。
NDIS驅動結構簡介
其中,最上層是一個NDIS Protocol Driver,它向上提供一個Transport Driver Interface(TDI),向下通過NDIS接口與下面的NDIS中間層的上邊界交互,NDIS中間層的下邊界通過NDIS接口與下層的NDIS Miniport Driver交互。最后,由NDIS Miniport Driver利用NDIS接口與物理網絡設備NetCard交互。NetCard是由不同的網卡設備產商提供的,而NDIS接口庫是由Microsoft開發好的,為什么NDIS Miniport Driver不是直接與物理網卡交互,而是通過NDIS接口與下物理網卡交互呢?(我想很多人都會和我當初一樣,有這個疑問)。
事實上,這是由于Windows系統為了提高可移植性,而設計出一個硬件抽象層(HAL),硬件抽象層在內部處理不同的硬件之間的差異,并且暴露出一個統一的接口給核心驅動開發者。例如:在Intel構架的系統中,內存和外部設備的端口采用分別編址,如果要從某個外部設備的端口上讀寫數據的話,可能要通過專用指令IN/OUT讀寫,而在Alpha構架的系統上,采用的是統一編址的方式,所以對外部設備的IO端口進行讀寫的話還是通過訪問內存的指令,HAL提供一組服務支持函數,如果要訪問外部設備上的端口數據可以使用READ_PORT_UCHAR/WRITE_PORT_UCHAR等等,核心驅動開發者不用去考慮不同硬件構架的之間的差異。在NDIS Miniport Driver中,NetCard驅動的程序,正是這樣通過NDIS接口提供的一組類似功能的函數,與物理的網絡設備進行交互。其中,最上層是一個NDIS Protocol Driver,它向上提供一個Transport Driver Interface(TDI),向下通過NDIS接口與下面的NDIS中間層的上邊界交互,NDIS中間層的下邊界通過NDIS接口與下層的NDIS Miniport Driver交互。最后,由NDIS Miniport Driver利用NDIS接口與物理網絡設備NetCard交互。
NDIS接口簡介
原來的通信可以看成下面的樣子:
協議棧處理過信息后發給Minport,或則Minport接受信息后發給協議棧,而我們在中間加了一層后變成下圖所示:
在wddk中passthru的例子來說具體的各個接口如下圖所示:
1.底層驅動使用NdisMIndicateReceive / NdisMEthIndicateReceive通知上層已經收到數據報文
2.在PtReceive中如果通過NdisGetReceivedPacket得到了一個完整的packet,就分配我們自己的MyPacket,根據底下傳上來的packet設置MyPacket,然后調用NdisMIndicateReceivePacket通知NDIS,NDIS會接著調用上層協議驅動的相應PtReceive例程。如果此時MyPacket的status是NDIS_STATUS_RESOURCES,我們就在本函數中釋放我們分配的MyPacket;否則我們在上層發送4的時候,在MPReturnPacket中釋放MyPacket.
3.在PtReceive中如果通過NdisGetReceivedPacket不能得到一個完整的packet,那我們就直接調用NdisMEthIndicateReceive等函數通知NDIS。
4.當上層協議驅動得到了一個完整的數據報文并且處理完畢以后,它會調用NdisReturnPacket,然后NDIS會調用我們的MPReturnPacket.
5.在我們的MPReturnPacket中,釋放我們自己分配的MyPacket,然后同樣的向下層調用NdisReturnPacket。下層會釋放他們自己分配的packet
6.如果3發生,當底層miniport驅動收到了一個完整的數據報文,它會調用NdisMEthIndicateReceiveComplete,然后NDIS會調用我們的PtReceiveComplete
7.我們的PtReceiveComplete同樣的會調用NdisMEthIndicateReceiveComplete,通知NDIS“我們已經收到了完整的報文”
8.當上層協議驅動得知底層已經收到了完整的數據報文以后,可能會調用NdisTransferData,要求下層把剩余的數據傳上來。
9.8的調用會導致NDIS調用我們的MPTransferData例程。在MPTransferData中,做同樣的調用NdisTransferData。注意該函數的返回值:如果返回success,說明剩余的數據立刻就傳上來了。此時會立即返回。10、11兩步驟就不會調用;如果返回pending,表明底層在此阻塞,底層會在稍后的時候調用10
10.當底層miniport驅動做好了一個完整的packet,它會調用NdisTransferDataComplete
11.同樣在我們的PtTransferDataComplete中,會作出同樣的調用。
發送示例如下:
1.Protocol driver調用NdisSend向下層發送數據報文。
2. Passthru的MPSend/MPSendPacket例程根據上層傳下來的數據報文分配MyPacket,調用NdisSend發送到下層。如果返回pending,就在PtSendComplete中釋放我們的MyPacket;否則就在本函數中緊接著釋放MyPacket。
3. 當下層miniport driver發送完成MyPacket以后,會調用NdisMSendComplete
4. NDIS接著調用passthru的PtSendComplete,在這個函數里邊,我們應該釋放MyPacket,并且通知上層protocol driver去釋放它們的packet。
丟包模擬概要
知道這個過程之后就可以模擬丟包,整體架構如下:
下面為丟包模擬結構圖:
(1)協議驅動調用NdisSend 向下層發送數據包Packet;
(2)NDIS 調用中間層驅動的MPSendPackets 函數將上層傳遞下來的數據包構建另一個數據包MyPacket,同樣調用NdisSend 將此數據包傳遞到下一層驅動。如果返回pending,就在步驟(5)中釋放MyPacket 的資源,否則在本函數中立即釋放資源;
(3)網卡驅動收到從中間層傳遞下來的MyPacket;
(4)網卡驅動調用NdisSend 發送MyPacket;
(5)網卡驅動調用NdisMSendComplete,NDIS 接著調用中間層的PtSendComplete 函數釋放步驟(2)中MyPacket 的所有資源,并通知上層協議驅動釋放步驟(1)中Packet 的資源;
(6)協議驅動釋放Packet 的所有資源。
本文對中間層驅動程序進行修改,在步驟(2)中間層中的MPSendPackets 函數中完成步驟(5),網卡驅動就無法得到上層傳遞的數據包從而實現了包丟棄。修改后發送流程如圖3中虛線所示。
注意點
本文的例子也是網絡上最多的(本來就是抄襲網絡),但是其中Passthru的例子只適應于 wddk6.0以下,如果您的操作系統我一樣是win7 64的則需要通過另外的方式來實現,請參考wddk下的filter例子。以后會再說。
總結
以上是生活随笔為你收集整理的NDIS学习笔记二——(模拟丢包)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 电脑的dwg文件怎么打开如何打开电脑
- 下一篇: 互联网协议入门(1)