PACKET_BROADCAST:链路层广播
PACKET_MULTICAST:链路层组播
PACKET_SELF:发给自己的帧
PACKET_OTHERHOST:发给别人的帧(监听模式时会有这种帧)
最后调用netif_rx()把数据传送给协议层。netif_rx()里数据放入处理队列然后返回,真正的处理是在中断返回以后,这样可以减少中断时间。调用netif_rx()以后,
驱动程序就不能再存取数据缓冲区skb。
2.2.6硬件帧头(hard_header)
硬件一般都会在上层数据发送之前加上自己的硬件帧头,比如以太网(Ethernet)就有14字节的帧头。这个帧头是加在上层ip、ipx等数据包的前面的。驱动程序提供一个hard_header方法,协议层(ip、ipx、arp等)在发送数据之前会调用这段程序。
硬件帧头的长度必须填在dev->hard_header_len,这样协议层回在数据之前保留好硬件帧头的空间。这样hard_header程序只要调用skb_push然后正确填入硬件帧头就可以了。
在协议层调用hard_header时,传送的参数包括(2.0.xx):数据的sk_buff,device指针,protocol,目的地址(daddr),源地址(saddr),数据长度(len)。数据长度不要使用sk_buff中的参数,因为调用hard_header时数据可能还没完全组织好。saddr是NULL的话是使用缺省地址(default)。daddr是NULL表明协议层不知道硬件目的地址。如果hard_header完全填好了硬件帧头,则返回添加的字节数。如果硬件帧头中的信息还不完全(比如daddr为NULL,但是帧头中需要目的硬件地址。典型的情况是以太网需要地址解析(arp)),则返回负字节数。hard_header返回负数的情况下,协议层会做进一步的buildheader的工作。目前Linux系统里就是做arp(如果hard_header返回正,dev->arp=1,表明不需要做arp,返回负,dev->arp=0,做arp)。
对hard_header的调用在每个协议层的处理程序里。如ip_output。
2.2.7地址解析(xarp)
有些网络有硬件地址(比如Ethernet),并且在发送硬件帧时需要知道目的硬件地址。这样就需要上层协议地址(ip、ipx)和硬件地址的对应。这个对应是通过地址解析完成的。需要做arp的的设备在发送之前会调用驱动程序的rebuild_header方法。调用的主要参数包括指向硬件帧头的指针,协议层地址。如果驱动程序能够解析硬件地址,就返回1,如果不能,返回0。
对rebuild_header的调用在net/core/dev.c的do_dev_queue_xmit()里。
2.2.8参数设置和统计数据
在驱动程序里还提供一些方法供系统对设备的参数进行设置和读取信息。一般只有超级用户(root)权限才能对设备参数进行设置。设置方法有:
dev->set_mac_address()
当用户调用ioctl类型为SIOCSIFHWADDR时是要设置这个设备的mac地址。一般对mac地址的设置没有太大意义的。
dev->set_config()
当用户调用ioctl时类型为SIOCSIFMAP时,系统会调用驱动程序的set_config方法。用户会传递一个ifmap结构包含需要的I/O、中断等参数。
dev->do_ioctl()
如果用户调用ioctl时类型在SIOCDEVPRIVATE和SIOCDEVPRIVATE+15之间,系统会调用驱动程序的这个方法。一般是设置设备的专用数据。
读取信息也是通过ioctl调用进行。除次之外驱动程序还可以提供一个
dev->get_stats方法,返回一个enet_statistics结构,包含发送接收的统计信息。ioctl的处理在net/core/dev.c的dev_ioctl()和dev_ifsioc()里。
linuxman@263.net
.3网络驱动程序中用到的数据结构
最重要的是网络设备的数据结构。定义在include/linux/netdevice.h里。它的注释已经足够详尽。
structdevice
{
/*
*ThisisthefirstfiELDofthe"visible"partofthisstructure
*(i.e.asseenbyusersinthe"SPACe.c"file).Itisthename
*theinterface.
*/
char*name;
/*I/OspecifICfields-FIXME:MergetheseandstructiFMaPINtoone*/
unsignedlongrmem_end;/*shmem"recv"end*/
unsignedlongrmem_start;/*shmem"recv"start*/
unsignedlongmem_end;/*sharedmemend*/
unsignedlongmem_start;/*sharedMEMStart*/
unsignedlongbase_addr;/*deviceI/Oaddress*/
unsignedcharIRQ;/*deviceIRQnumber*/
/*Low-levelstatusflags.*/
volatileunsignedcharstart,/*startanoperation*/
interrupt;/*interruptarrived*/
/*在处理中断时interrupt设为1,处理完清0。*/
unsignedlongtbusy;/*transmitterbusymustbelongfor
bitops*/
structdevice*next;
/*Thedeviceinitializationfunction.CalLEDonlyonce.*/
/*指向驱动程序的初始化方法。*/
int(*init)(structdevice*dev);
/*Somehardwarealsoneedsthesefields,buttheyarenotpartofthe
usualsetspecifiedinSpace.c.*/
/*一些硬件可以在一块板上支持多个接口,可能用到if_port。*/
unsignedcharif_port;/*SelectableAUI,TP,..*/
unsignedcharDMA;/*DMAchannel*/
structenet_statistics*(*get_stats)(structdevice*dev);
/*
*Thismarkstheendofthe"visible"partofthestructure.All
*fieldshereafterareinternaltothesystem,andmaychangeat
*will(read:maybecleanedupatwill).
*/
/*Thesemaybeneededforfuturenetwork-power-downcode.*/
/*trans_start记录最后一次成功发送的时间。可以用来确定硬件是否工作正常。*/
unsignedlongtrans_start;/*Time(injiffies)oflastTx*/
unsignedlonglast_rx;/*TimeoflastRx*/
/*flags里面有很多内容,定义在include/linux/if.h里。*/
unsignedshortflags;/*interfaceflags(alaBSD)*/
unsignedshortfamily;/*addressfamilyID(AF_INET)*/
unsignedshortmetric;/*routingmetric(notused)*/
unsignedshortmtu;/*interfaceMTUvalue*/
/*type标明物理硬件的类型。主要说明硬件是否需要arp。定义在
include/linux/if_arp.h里。*/
unsignedshorttype;/*interfacehardwaretype*/
/*上层协议层根据hard_header_len在发送数据缓冲区前面预留硬件帧头空间。*/
unsignedshorthard_header_len;/*hardwarehdrlength*/
/*priv指向驱动程序自己定义的一些参数。*/
void*priv;/*pointertoprivatEDAta*/
/*Interfaceaddressinfo.*/
unsignedcharbroadcast[MAX_ADDR_LEN];/*hwbcastadd*/
unsignedcharpad;/*makedev_addralignedto8
bytes*/
unsignedchardev_addr[MAX_ADDR_LEN];/*hwaddress*/
unsignedcharaddr_len;/*hardwareaddresslength*/
unsignedlongpa_addr;/*protocoladdress*/
unsignedlongpa_brdaddr;/*protocolbroadcastaddr*/
unsignedlongpa_dstaddr;/*protocolP-Pothersideaddr*/
unsignedlongpa_mask;/*protocolnetmask*/
unsignedshortpa_alen;/*protocoladdresslength*/
structdev_mc_list*mc_list;/*Multicastmacaddresses*/
intmc_count;/*Numberofinstalledmcasts*/
structip_mc_list*ip_mc_list;/*IPmulticastfiLTErchain*/
上一篇:用VB和单片机开发串行通信软件