windows wdf 驱动开发总结(9)--网络驱动开发(NDIS)

此篇文章来自Internet,写的挺不错的,在这里转贴过来。

NIC1394 网卡驱动收包过程:

网卡的发包和收包过程

网卡也叫“网络适配器”,英文全称为“Network Interface Card”,简称“NIC”,网卡是局域网中最基本的部件之一,它是连接计算机与网络的硬件设备。无论是双绞线连接、同轴电缆连接还是光纤连接,都必须借助于网卡才能实现数据的通信。

    网卡的主要工作原理是整理计算机上发往网线上的数据,并将数据分解为适当大小的数据包之后向网络上发送出去。当网络上一台计算机准备发送数据时,他的网卡开始工作了,首先网卡的芯片侦听在网络上是否有数据在流动,如果没有,他就把数据发送到网络上,在发送完成后再校验返回的数据,检验和发送的数据是否一致。对于全双工网卡,计算机的网卡芯片同时会接收到数据包,当接收到一个完整的数据包后,芯片的一引脚通知中断控制器,中断控制器再发出中断给CPU,由此,CPU随即调用该网卡的中断例程。从而完成收发包的过程。

每个NDIS_PACKET包表示一个可以由网卡发送的数据包。也就是说,这个包已经完全被上层封装好了,就差加上一个MAC头就可以发了(当然这个MAC头是网卡发送时自动加上的)。NDIS_PACKET要发送的数据是由一个链表结构的NDIS_BUFFER组成。之所以要这样来封装,是因为每经过一层协议的时候,该层的协议都要在数据的包头加上自己的信息,采用链表结构,只需要在原来链表的表头加上自己的信息,不需要再拷贝任何数据,就能够把包往下传给下一层驱动了,节约了时间和空间。

2.1 发包的过程:

要预先把发送的数据拷贝到一个物理连续的缓冲区里,然后把缓冲区的物理地址传递给网卡,启动网卡传输,网卡就用DMA方式把数据发送出去。发送成功后给出一个中断,表示发送完成。

具体细节:

1.)获取到一个NDIS_PACKET  Packet包以后,使用

NdisQueryPacket(

  Packet,

      &PhysicalBufferCount,

      &BufferCount,

       &pFirstBuffer,

      &TotalPacketLength);

获取整个包要发送的数据长度,就是TotalPacketLength里返回值。得到的返回值可以用来分配物理连续的缓冲区。

2.)把数据拷贝到刚才分配的物理连续的缓冲区里。循环使用

NdisQueryBufferSafe(

  pCurrBuff,

     &pVirtualAddress,

     &Length,

     NormalPagePriority);

获取NDIS_PACKET  Packet包链表结构里的每一个NDIS_BUFFER   pCurrBuff的线性地址(linear address),然后使用这些线性地址,

     NdisMoveMemory(

     (PVOID) ((ULONG) 物理连续的缓冲区,

     (PVOID)   pVirtualAddress,

     (ULONG)  Length);

把包拷贝到发送的缓冲区里。

 

3.)在物理连续的缓冲区有了一个完整的包以后,启动网卡DMA传输,开始传送。

2.2 收包的过程:

网卡接受到数据以后,就产生一个中断,在这个中断的DPC里,调用

     NdisMIndicateReceivePacket(

        pRtlAdapter->MiniportAdapterHandle,

        RevPacket,

        NumOfPkt

                  );

告诉系统收到了NumOfPkt个数据包了,RevPacket是收到的包的数组。

1.)在网卡驱动初始化的时候,需要分配一个Ring Buffer,这个Ring Buffer是给网卡接受数据使用的,由于是给网卡的DMA传输数据用的,所以Ring Buffer必须要是一个物理连续的内存。Ring Buffer顾名思义,是一个环状的缓冲区,当使用到缓冲区的尽头时,又重新从Buffer的开始循环使用。接受到的数据包刚开始就是被连续放在这个环状缓冲区里。

2.)当收到一个完好的数据包(就是Ring Buffer包含了完好的数据包),网卡发出中断,指出有数据包到来。然后,所有的处理都是在DPC里完成的。

每个收到的包都包含了如下的网卡额外加入的信息头:

typedef struct tagPACKETHEADER{

        USHORT  ROK : 1;        //接受到一个好的数据包。

        USHORT  FAE : 1;        //帧对齐错误。

        USHORT  CRC : 1;        //CRC校验错误。

        USHORT  LONG: 1;       //一个超过4KBytes的包。

        USHORT  RUNT: 1;       //一个小于64Bytes的包。

        USHORT  ISE : 1;

        USHORT  reserved : 7;

        USHORT  BAR : 1;       //收到一个广播包。

        USHORT  PAM : 1;       //收到发给自己的包。

        USHORT  MAR : 1;       //收到一个组播包。

        USHORT   PacketLength;  //很重要,这个长度是数据包长度+网卡加入的4个字节CRC

}PACKETHEADER, *PPACKETHEADER;

有了这些信息,先判断包是否是好的,如果是好的,那么创建一个NDIS_PACKET  Packet包,然后,把长度为(PacketLength-4)个字节的数据从接受Ring Buffer里拷贝出来,然后,调用NdisMIndicateReceivePacket通知系统,收到了包。

如果这个包是坏包,那么从新置位Ring Buffer缓冲区。这个做法很重要,不然后面收到的包就没法保证正确了。

2.3 注意事项:

1.)在收包的时候,如果采用事先分配的Packet,那么这个Packet必须调用:

        NDIS_SET_PACKET_HEADER_SIZE(Packet,ETHERNET_HEADER_SIZE);

不然,收到的数据包MAC层的协议内容会被拷贝到上层的内容里,造成错误。

2.)在资源分配之前,需要调用NdisMSetAttributesEx函数,否则会得出资源分配失败。

3.)从Ring Buffer拷贝数据出来,拷贝的起始(read_ptr)地址是由我们的驱动来维护的,所以,应该尽量小心维护这个指针。

4.)MyRtlQueryInformationMyRtlSetInformation都只是系统获取驱动支持的特性的手段,对硬件的操作很少,不需要很在意。

5.)数据包接收的算法直接影响到驱动的效率,应该尽量优化。

6.)在编写收包和发包的过程中,可以使用Sniffer工具来获取包,验证是否确实有包被发送或接收。

 

Windows网络架构图:

 

1.   网络应用程,Network applicantion,用户态的应用程序调用Windows操作系统提供的网络API,网络API包括:
a)   Windows
套接字(winsock
b)  
远程过程调用RPC
c)   Web
访问
API
d)  
命名管道和邮件槽

e)  
其他网络API
这些API既可以在用户模式下实现,也可以同时在用户模式和内核模式下实现。从本质上说这些API是下层提供接口的另一层封装而已。

   2.   TDI Clients,传输驱动程序接口客户,是内核模式的设备驱动程序,用于实现网络API的内核部分。将网络API的请求转换成IRP,通过TDI标准格式化后,发送给下层的协议驱动(也就是TDI传输器)。从sockets emulator的架构图看到,TDI Clients的实现可以有用户态的部分,也有内核态的部分。AFD辅助功能驱动程序通过向协议驱动程序发送TDI IRP来执行网络套接字操作,比如发送和接受消息。AFD没有不是确定使用哪一个协议驱动,而是上层通知其要使用的协议名称,然后AFD去打开相应协议的设备对象。

3.   TDI Transport ProvidersTDI传输器、NDIS协议驱动程序、协议驱动程序,所有这些其实就是指的同一个东西,我在后面就称其为协议驱动程序。这个部分就是我们对某个协议的具体实现部分。做过网络协议开发的朋友一定知道,协议其实就是双发协商好的一套通信的规则。以IP 协议为例,实际上就是对网络数据的一种处理方式,根据网络数据包的解析结构,做出相应的处理。Windowstcpip.sys就实现了多个协议,iptcpudparpicmpigmp,它为上层的TDI Clients提供了5个设备对象,用于访问使用这些协议,TDI Clients打开这些设备对象,向其发送IRP请求来实现自己的操作。通过

DDKDeviceTree我们可以得到这些设备对象

a)   /Device/Rawip

b)   /Device/Tcp

c)   /Device/Udp

d)   /Device/IPMULTICAST

e)   /Device/Ip

协议驱动程序处理的数据是通过NDIS库中提供的接口来获取的,不需要发送IRP来取得。在DDK XP中提供了一个协议驱动程序了源程序 NdisuioDDK XP后的版本提供的是Ndisport。在DriverEntry中我们可以看到,驱动程序一开始就注册了一个 NDIS_PROTOCOL_CHARACTERISTICS,这个结构体中是一堆NdisXxxx函数。NDIS

规范在这里就开始发挥它的作用了。

协议驱动程序的另一个作用就是监听网络数据,自己开发一个网络协议通过Ndis API获得所有的网络数据,但是不能够拦截网络数据,因为其他协议驱动也可以通过Nids API获取数据。一个典型的应用就是Winpcap了,使用NPF.SYS来捕获网络数据,并且做好充分缓冲处理,防止大数据量到来时出现数据包丢失的情况。详情情节winpcap的开源代码。

具体的协议驱动开发过程,我就不细述了,大家可以参看NdisuioDDK doc,我推荐

boywhp的一篇文档《NDIS协议驱动开发》给大家。

4.   NDISNetwork Driver Interface Specification,网络协议接口标准。从图中我们可以看到包裹在其中的两个驱动程序,一个是NDIS intermediate driverNDIS中间层驱动程序,另一个是NDIS minport driver,小端口驱动程序。下面简单介绍一下这

两个驱动程序:

a)   Ndis intermediate driverNDIS中间层驱动程序,对于上层的protocol driver它充当 minport driver的作用,对于下层的minport driver它充当一个protocol driver

的作用,所以在驱动程序 DriverEntry中就注册NDIS_PROTOCOL_CHARACTERISTICS NDIS_MINIPORT_CHARACTERISTICS,使用protocol characteristicsNDIS API miniport driver那里取得数据包,再用miniport characteristicsNDIS API向上层的 protocol driver发送数据包。Nids intermediate driver最大的优势就是所有miniport driver的数据包都要通过它这里倒手给protocol driver,所以网络防火墙就看上了这块风水宝地。现在很多网络防火墙都使用 NDIS intermediate driver做数据包的过滤和拦截工作,过滤的规则设置到 MPSendPacketsPTReceivePTReceiveRacket这三个函数。具体开发过程请大家参考DDK提供的PassThru源代码,www.ndis.com

网上有很多相关的资料。

NDIS 6.0之后,filter driver就取代了Ndis intermediate driverWDK中提供源码。

b)   Ndis miniport driver一般是由设备厂商提供的,在DDK中也提供了miniport driver的一个例子 e100bex,支持Intel EtherExpressTM PRO/100+ Ethernet PCI adapter Intel EtherExpressTM PRO/100B PCI adapter两款网络适配器。

5.   最后介绍一下总线,计算机总线有好几种,USB总线、ISA总线、PCI总线、虚拟总线等,一般都是以PCI总线作为根总线,在Windows系统中其他的总线可以理解为PCI总线上的一个设备。PCI总线作为根总线,其传输速度较高,可以达到133MB/S,显卡和

网卡很多都是用PCI插槽。

PCI-ISA桥设备,也称为南桥,实现了ISA总线与PCI总线的桥接, 南桥还包括终端、IDEUSBDMA等控制器设备。其中USB-HOST 设备实现了USB总线和PCI总线的桥接。HOST/PCI桥称为北桥,是主处理器中心啊到基础PCI局部总线。南桥和北桥组成

了主板的芯片组,通过芯片的扩展实现了多种总线与基础PCI局部总线的桥接。总线驱动程序和PNP管理器实现了即插即用的功能,物理设备对象PDO就是由总线驱动程序产生的。

 

 

  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值