




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、Good is good, but better carries it.精益求精,善益求善。LWIP协议栈架构与设计解析LWIP协议栈及接口提取Version1.02012/06/20版本1.0姓名部门邮件作者雷岩L审阅版本历史版本日期修订姓名Rev1.02011/11/07FirstDraftleiyan目录TOCo1-3hzuHYPERLINKl_Toc328052376一、LWIP介绍PAGEREF_Toc328052376h5HYPERLINKl_Toc328052377二、LWIP源码分析PAGEREF_Toc328052377h7HYPERLINKl_Toc3280523781LW
2、IP协议栈的架构PAGEREF_Toc328052378h7HYPERLINKl_Toc3280523792各个文件夹介绍PAGEREF_Toc328052379h8HYPERLINKl_Toc3280523803模块及源文件介绍PAGEREF_Toc328052380h10HYPERLINKl_Toc328052381三、LWIP协议栈处理数据流程PAGEREF_Toc328052381h17HYPERLINKl_Toc328052382四、接口提取PAGEREF_Toc328052382h18LWIP介绍首先说明一下,这篇文档的主要目的是提取网络发送和接收数据的函数接口。然后用我们自己的驱
3、动网卡的接口函数替代程序中的接口。如果对LWIP协议栈本身没什么兴趣的,可以跳过第一、二、三章,直接阅读第四章,使用我们的接口代替第四章的接口就行了。写第一、二、三章的主要目的是为了方便理解数据的发送和接收在LWIP协议栈中是如何进行处理的。这便于我们理解提取出来的接口。LWIP是瑞典计算机科学院开发的一套用于嵌入式系统的开放源代码的轻量级的TCP/IP协议栈。传统的,或者说是典型的TCP/IP协议族的设计都是按照分层的思想来设计的。这样设计有个好处,就是每层相对于其他层独立,代码方便理解。缺点就是,每层之间进行数据交互的时候必须要进行复制,而数据的复制是很耗时的,这就降低了实时性。LWIP采
4、用了一种不同的设计方式来实现TCP/IP协议族。LWIP各层之间没有明显的界限,各层之间都可以访问到共享在内存中的数据。因为各层都可以访问共享内存,所以这就避免了内存复制产生的性能损失。但是并不是说LWIP就没有分层的概念了。只不过LWIP各层都是逻辑意义上的层。每个协议都以模块的形式被实现。而这些模块就共同组成了LWIP整体。下面一章将分析LWIP的源码,结合源码介绍这些模块。了解各个协议是怎么通过模块被实现的。其中这里最主要的是TCP协议模块的实现。TCP协议在LWIP协议栈中占得比例最大,有将近一半的代码是专门用来实现TCP协议的。所以重点会分析TCP协议。并且无线音频项目采用的也是TC
5、P协议传输数据。LWIP逻辑上被分为四个层:应用层,传输层,网络层和网络接口层。如下图1.1所示:图1.1LWIP协议栈的分层模型应用层主要是使用LWIP协议栈开发相应的网络通信程序。LWIP主要提供了三种接口供用户使用。三种接口分别为RAWAPI,NetconnAPI和BSDSocketAP。其中RAWAPI主要是采用回调函数的方式来完成数据的发送和接收,RAWAPI接口写的应用程序与LWIP协议栈处在同一个进程(或者称任务)中。NetconnAPI和BSDSocketAP工作于多线程方式中,要使用者两种接口,必须有多任务的操作系统的支持。这次项目采用的接口是RAWAPI。关于RAWAPI接
6、口如何写应用层程序,另写了一个专门的文档介绍。这里不列出。传输层。我们最熟悉的TCP协议,UDP协议,以及我们使用ping命令时采用的ICMP协议都处在这一层。这一层提供了一些专门的接口,用于处理与应用层和网络层的数据传送(注明,这里说的数据传送并不是指数据的拷贝。事实上,LWIP协议栈使用的是内存共享技术,各层都能访问这段共享内存,各层传递的就是数据结构指针,所以LWIP协议栈降低了内存复制所产生的性能损失)。关于这层函数,会在下面进行具体说明。网络层主要的协议是IP协议。这一层主要是对底层接收的数据包进行发送,转发,丢弃组合等功能。网络接口层是和底层硬件驱动交互的层。我们所需要提取的网络接
7、口就在这一层。LWIP源码分析LWIP协议栈的架构LWIP协议栈源码的架构如下图2.1所示:图2.1LWIP协议栈源码架构api目录:应用程序接口文件,包括netconn和BSD2种API。这个文件夹主要是为了方便应用程序编写而为应用层提供的API接口。core目录:ICMP,IP,TCP,UDP协议的实现文件,以及一些辅助函数,LWIP实现的核心代码。其中这个文件夹里面实现TCP协议的代码量几乎占了整个lwip协议栈的一半。重点会讨论TCP协议。在此也可以简单看出LWIP协议栈没有严格区分传输层和网络层,因为传输层的代码和网络层的代码放在一个文件夹里实现了。目录里还提供了RAWAPI接口的实
8、现。RAWAPI接口和上面两种接口一样,都是为了方便应用程序编写而为应用层提供的API接口。include目录:主要是LWIP协议栈使用的自定义的一些头文件。netif目录:这个目录里主要实现的是ARP协议。当然还有一些PPPOE等协议。当然PPPOE协议不是我们所关心的。port目录:最后写这个目录,主要是因为这个目录是我们最终所要修改的一个目录。可以看到此目录下包含一个ethernetif.c文件。这个文件提供了与底层网络驱动的一个接口。我们要实现与自己的网络接口驱动交互,必须修改这个文件里的接口,使这些接口为上层屏蔽细节信息。2各个文件夹介绍【1】api目录,如图2.2图2.2api目录
9、下的文件列表这个文件夹下面主要提供的是netconnAPI和BSDsocketAPI。这些接口不是我们所要关心的。所以直接忽略。我们使用下面文件夹里提供的RAWAPI接口。【2】core目录,如图2.3图2.3core目录下的文件列表这个文件下下面,ipv6文件夹和snmp文件夹我们不需要关心。主要关心的文件有icmp.cIp.cip_addr.cip_etif.cpbuf.cRaw.ctcp.ctcp_in.ctcp_out.cudp.c【3】include目录,如图2.4图2.4include目录下的文件列表这个文件夹下面主要包括所有.c文件用到的头文件。Ipv6文件夹我们不必关心。【4】
10、netif目录,如图2.5图2.5netif目录下的文件列表这个文件夹下面主要关心etharp.c这个文件其余的不必关心。其中文件夹PPP是关于点对点协议的,不必关心【5】port目录,如图2.6图2.6port目录下的文件列表这个文件夹下面关于arch目录,这个目录是移植时候主要修改的目录。这个目录下包含的是与体系结构相关的一些定义等。FreeRTOS这个文件夹不需要关心,因为这是基于实时操作系统的,而我们现在做的项目是基于单任务的,无需操作系统的支持。Standalone这个文件夹下面的ethernetif.c中给出的驱动接口。我们为自己的网络接口设计的驱动程最终用来代替这个文件里的接口。
11、上面所有文件大致描述了LWIP协议栈的几个模块:配置模块、初始化模块、NetIf模块、Mem(memp)模块、netarp模块、ip模块、udp模块、icmp模块、igmp模块和dhcp模块。由于篇幅限制,不能对每个源文件都做介绍。只对我们感兴趣的模块的源文件做相应的介绍。3模块及源文件介绍【1】配置模块配置模块的文件主要包含在include/lwip/opt.h里(这里及下文所指的路径均为相对路径)。配置模块通过各种宏定义的方式对系统、子模块进行了配置。比如,通过宏,配置了mem管理模块的参数。该配置模块还通过宏,配置了协议栈所支持的协议簇,通过宏定制的方式,决定了支持那些协议。/*LWIP
12、_ARP=1:EnableARPfunctionality.*/#ifndefLWIP_ARP#defineLWIP_ARP1#endif截取一段代码说明问题。上面的代码表示配置的时候支持ARP(地址解析协议)协议族,此代码下面对ARP协议族进行一些其他的配置。【2】初始化模块初始化模块(这里主要讲的是TCP协议的初始化模块)主要在文件api/tcpip.c中。贴上源代码voidtcpip_init(void(*initfunc)(void*),void*arg)lwip_init();tcpip_init_done=initfunc;tcpip_init_done_arg=arg;mbox=
13、sys_mbox_new(TCPIP_MBOX_SIZE);#ifLWIP_TCPIP_CORE_LOCKINGlock_tcpip_core=sys_sem_new(1);#endif/*LWIP_TCPIP_CORE_LOCKING*/sys_thread_new(TCPIP_THREAD_NAME,tcpip_thread,NULL,TCPIP_THREAD_STACKSIZE,TCPIP_THREAD_PRIO);这个初始化模块是如此的重要,以至于我们可以说这是整个程序的核心。首先调用lwip_init()初始化了所有的子模块。然后调用sys_thread_new()启动了协议栈管理进
14、程。所有的程序就在tcpip_thread这个进程里运行(这里说的是使用RAWAPI接口的情况)。【3】NetIf模块netif模块是非常重要的一个模块,主要是因为里面有一个netif的结构体。Netif模块为协议栈与底层驱动的接口模块,其将底层的一个网口设备描述成协议栈的一个接口设备(netinterface)。这个接口设备就是用上面说的netif结构体来描述。所以说neitif结构体很重要。Netif模块主要文件为core/netif.c和include/lwip/netif.h。structnetif/*pointertonextinlinkedlist*/structnetif*nex
15、t;/*IPaddressconfigurationinnetworkbyteorder*/structip_addrip_addr;structip_addrnetmask;structip_addrgw;/*Thisfunctioniscalledbythenetworkdevicedriver*topassapacketuptheTCP/IPstack.*/err_t(*input)(structpbuf*p,structnetif*inp);/*ThisfunctioniscalledbytheIPmodulewhenitwants*tosendapacketontheinterfac
16、e.Thisfunctiontypically*firstresolvesthehardwareaddress,thensendsthepacket.*/err_t(*output)(structnetif*netif,structpbuf*p,structip_addr*ipaddr);/*ThisfunctioniscalledbytheARPmodulewhenitwants*tosendapacketontheinterface.Thisfunctionoutputs*thepbufas-isonthelinkmedium.*/err_t(*linkoutput)(structneti
17、f*netif,structpbuf*p);#ifLWIP_NETIF_STATUS_CALLBACK/*Thisfunctioniscalledwhenthenetifstateissettoupordown*/void(*status_callback)(structnetif*netif);#endif/*LWIP_NETIF_STATUS_CALLBACK*/#ifLWIP_NETIF_LINK_CALLBACK/*Thisfunctioniscalledwhenthenetiflinkissettoupordown*/void(*link_callback)(structnetif*
18、netif);#endif/*LWIP_NETIF_LINK_CALLBACK*/*Thisfieldcanbesetbythedevicedriverandcouldpoint*tostateinformationforthedevice.*/void*state;#ifLWIP_DHCP/*theDHCPclientstateinformationforthisnetif*/structdhcp*dhcp;#endif/*LWIP_DHCP*/#ifLWIP_AUTOIP/*theAutoIPclientstateinformationforthisnetif*/structautoip*
19、autoip;#endif#ifLWIP_NETIF_HOSTNAME/*thehostnameforthisnetif,NULLisavalidvalue*/char*hostname;#endif/*LWIP_NETIF_HOSTNAME*/*maximumtransferunit(inbytes)*/u16_tmtu;/*numberofbytesusedinhwaddr*/u8_thwaddr_len;/*linklevelhardwareaddressofthisinterface*/u8_thwaddrNETIF_MAX_HWADDR_LEN;/*flags(seeNETIF_FL
20、AG_above)*/u8_tflags;/*descriptiveabbreviation*/charname2;/*numberofthisinterface*/u8_tnum;#ifLWIP_SNMP/*linktype(fromsnmp_ifTypeenumfromsnmp.h)*/u8_tlink_type;/*(estimate)linkspeed*/u32_tlink_speed;/*timestampatlastchangemade(up/down)*/u32_tts;/*counters*/u32_tifinoctets;u32_tifinucastpkts;u32_tifi
21、nnucastpkts;u32_tifindiscards;u32_tifoutoctets;u32_tifoutucastpkts;u32_tifoutnucastpkts;u32_tifoutdiscards;#endif/*LWIP_SNMP*/#ifLWIP_IGMP/*ThisfunctioncouldbecalledtoaddordeleteaentryinthemulticastfiltertableoftheethernetMAC.*/err_t(*igmp_mac_filter)(structnetif*netif,structip_addr*group,u8_taction
22、);#endif/*LWIP_IGMP*/#ifLWIP_NETIF_HWADDRHINTu8_t*addr_hint;#endif/*LWIP_NETIF_HWADDRHINT*/#ifENABLE_LOOPBACK/*Listofpacketstobequeuedforourselves.*/structpbuf*loop_first;structpbuf*loop_last;#ifLWIP_LOOPBACK_MAX_PBUFSu16_tloop_cnt_current;#endif/*LWIP_LOOPBACK_MAX_PBUFS*/#endif/*ENABLE_LOOPBACK*/;这
23、个结构体里所有的成员的作用都已经注释了,这里我们只关心两个成员:err_t(*input)(structpbuf*p,structnetif*inp);err_t(*output)(structnetif*netif,structpbuf*p,当收到一个信息包时,设备驱动程序调用input指针指向的函数。网络接口通过output指针连接到设备驱动。这个指针指向设备驱动中一个向物理网络发送信息包的函数,当信息包被发送时由IP层调用。这个字段由设备驱动的初始设置函数填充。也就是说,当我们从网络上接收一个数据的时候我们调用input函数指针指向的函数进行数据接收的处理。当我们要向网络中发送一个数据时
24、,我们调用output函数指针指向的那个函数进行数据的发送工作。因为这个netif结构体是与底层驱动进行交互的。所以input和output函数指针是直接指向网络驱动收发接口函数的。回到netif.c文件中,netif.c文件通过链表的方式描述了系统中的所有网口设备。因为系统中可能会有很多网络设备。【4】Mem(memp)模块其实mem和memp管理的是不同类型的内存,但都属于内存管理。所以放在了一起。Mem模块同一管理了协议栈使用的内容缓冲区,并管理pbuf结构以及报文的字段处理。主要的文件包括mem.c、memp.c、pbuf.c。这里我们所要关心的是内存管理单元所管理的pbuf结构体。t
25、ypedefenumPBUF_RAM,/*pbufdataisstoredinRAM*/PBUF_ROM,/*pbufdataisstoredinROM*/PBUF_REF,/*pbufcomesfromthepbufpool*/PBUF_POOL/*pbufpayloadreferstoRAM*/pbuf_type;如上所示,pbuf有四种类型(但是文档中只介绍了三种类型)。关于这四种类型的pbuf有什么区别请参考相应的文档,一句话说明四者的不同,主要是pbuf结构体中存放的数据的位置不同。一句话说明pbuf类型的选择。当接收网络数据包时,我们选择的pbuf是PBUF_POOL类型的。至于网
26、络数据包的发送,根据自己的实际情况自己选择。structpbuf*pbuf_alloc(pbuf_layerl,u16_tsize,pbuf_typetype);voidpbuf_realloc(structpbuf*p,u16_tsize);u8_tpbuf_header(structpbuf*p,s16_theader_size);voidpbuf_ref(structpbuf*p);voidpbuf_ref_chain(structpbuf*p);u8_tpbuf_free(structpbuf*p);u8_tpbuf_clen(structpbuf*p);voidpbuf_cat(st
27、ructpbuf*head,structpbuf*tail);voidpbuf_chain(structpbuf*head,structpbuf*tail);structpbuf*pbuf_dechain(structpbuf*p);err_tpbuf_copy(structpbuf*p_to,structpbuf*p_from);u16_tpbuf_copy_partial(structpbuf*p,void*dataptr,u16_tlen,u16_toffset);err_tpbuf_take(structpbuf*buf,constvoid*dataptr,u16_tlen);stru
28、ctpbuf*pbuf_coalesce(structpbuf*p,pbuf_layerlayer);这是对pbuf结构体进行操作的函数。【5】netarp模块netarp模块是处理arp协议的模块,主要源文件为netif/etharp.c。其主要入口函数为:err_tethernet_input(structpbuf*p,structnetif*netif)该入口函数通过判断输入报文p的协议类型来决定是按照arp协议进行处理还是将该报文提交到IP协议。如果报文是arp报文,该接口则调用etharp_arp_input,进行arp请求处理。如果是ip报文,该接口就调用etharp_ip_inp
29、ut进行arp更新,并调用ip_input接口,将报文提交给ip层。在该模块中,创建了设备的地址映射arp表,并提供地址映射关系查询接口。同时还提供了arp报文的发送接口。如下:err_tetharp_output(structnetif*netif,structpbuf*q,structip_addr*ipaddr)该接口需要注册到netif的output字段,ip层在输出报文时,通过该接口获取目标机的MAC地址,组合最终报文后,由该接口调用底层设备的驱动接口发送数据。在etharp_output接口中,判断报文类型,如果是广播包或者组播包,就调用etharp_send_ip(组装目标mac
30、和源mac)接口,etharp_send_ip调用netif结构中的设备驱动注册的linkoutput钩子函数发送最终报文。如果是单播包,etharp_output接口就调用etharp_query进行ip地址和MAC地址的映射,来获取到目标机的MAC地址。并在etharp_query中调用etharp_send_ip来发送最终组合报文。【6】ip模块ip模块实现了协议的ip层处理,主要文件为ipv4/ip.c。其主要入口函数为:err_tip_input(structpbuf*p,structnetif*inp)该接口通过判断输入报文的协议类型,将其输入到相应的上层协议模块中去。比如,将ud
31、p报文送到udp_input。该模块另外一个接口是输入函数,原型如下:err_tip_output(structpbuf*p,structip_addr*src,structip_addr*dest,u8_tttl,u8_ttos,u8_tproto)该接口通过路由表或者传输ip后,调用netif的output函数指针指向的函数发送报文。【7】udp模块不是我们所关心的,这里就不做介绍【8】icmp模块用的不多,不必关心【9】igmp模块用的不多,不必关心【10】dhcp模块可能会用到。dhcp模块用于获取设备ip地址的相关信息。其处理入口主要有这么几个:dpch的启动、dpch的接收报文处理
32、以及定时器模块的处理。主要的接口原型如下:err_tdhcp_start(structnetif*netif)该接口用于设备启动dhcp模块,主要是客户端的功能。该模块实现设备dhcp描述结构生成,并将dhcp的端口绑定到udp协议中,以及将本dhcp模块跟远端服务器端口进行绑定。最后启动dhcp申请。staticvoiddhcp_recv(void*arg,structudp_pcb*pcb,structpbuf*p,structip_addr*addr,u16_tport)该接口为一个注册接口,用于dhcp报文接收。在startdhcp时,该接口通过dhcp的udppcb注册到udp协议层。Udp进行报文处理后,根据端口调用该注册接口。该接口中,实现dhcp报文的协议处理。Voiddhcp_fine_tmr()Voiddhcp_coarse_tmr()这两个函数接口实现了dhcp的相关超时处理监控。上面一个用于请求应答超时处理。下面一个用于地址租用情况的到期处理。从源码分析看,上述的接口在应用lwip的协议栈时,需要重点关注。对于小内存应用的场合,该协议栈的内存管理以及pbuf应用部分需要自行改写LWIP协议栈处理数据流程协议栈处理数据的流程主要是处理TCP数据包。关于UDP数据报的处理流程暂且不做讨论。LWIP对TCP数据包的处理流程如下图3.1所示
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025-2030年中国金融电子支付设备市场发展趋势规划研究报告
- 2025-2030年中国调味紫菜市场十三五规划及发展战略研究报告
- 2025-2030年中国补血保健品市场十三五规划与发展策略分析报告
- 2025-2030年中国薯蓣皂素市场需求状况及发展前景分析报告
- 2025-2030年中国聚碳酸酯板(阳光板)行业运行态势与投资战略研究报告
- 2025-2030年中国稀土冶炼分离市场运营趋势规划研究报告
- 简易短期租房合同范本
- 知识产权质押贷款合同示例
- 员工保密合同格式
- 2024-2025学年五年级下册数学《露在外面的面》(教案)
- 房屋买卖合同预交定金协议
- Altium-Designer-电路设计与制作教案
- DL∕T 657-2015 火力发电厂模拟量控制系统验收测试规程
- 小米创业思考(商业思考)
- 供应商评估与筛选管理制度
- DB4409-T 44-2023 地理标志产品 化橘红质量等级
- JTG F40-2004 公路沥青路面施工技术规范
- 黄龙溪古镇文化旅游发展现状与对策研究
- JT-T-1045-2016道路运输企业车辆技术管理规范
- 2024年事业单位卫生系统(护理学)招聘考试题库与答案
- 互联网金融 个人网络消费信贷 贷后催收风控指引
评论
0/150
提交评论