1、TCPIP协议栈lwip的移植Word版TCP/IP协议栈lwip的移植新建几个头文件Include/lwipopts.hInclude/arch/cc.hInclude/arch/perf.hInclude/arch/sys_arch.h除头文件外还需要添加一个C文件:sys_arch.c。说明在doc/sys_arch.txt中。修改netif/Ethernetif.c。结构对齐的几个宏对于一个结构下载下来的LWIP的通用定义如下:PACK_STRUCT_BEGINstruct icmp_echo_hdr PACK_STRUCT_FIELD(u8_t type); PACK_STRUCT_
2、FIELD(u8_t code); PACK_STRUCT_FIELD(u16_t chksum); PACK_STRUCT_FIELD(u16_t id); PACK_STRUCT_FIELD(u16_t seqno);PACK_STRUCT_STRUCT;PACK_STRUCT_EN#define PACK_STRUCT_FIELD(x)这个宏是为了字节序的转换,由于是用的小端,就不用转换了直接定义为#define PACK_STRUCT_FIELD(x)x#define PACK_STRUCT_STRUCT#define PACK_STRUCT_BEGIN#define PACK_STR
3、UCT_END以上三个宏都是为了做结构体对齐用:对于gcc的编译器在结构体后跟个关键字就okstruct ip_hdr ;_attribute_ (_packed_)因此可以定义为#define PACK_STRUCT_STRUCT _attribute_ (_packed_)#define PACK_STRUCT_BEGIN#define PACK_STRUCT_END对于vc的编译器就郁闷了,vc做结构体对齐是这样做的#pragma pack(1) /结构体按照1字节对齐struct ip_hdr ;#pragma pack()/结构体按照编译器默认值对齐但是VC的编译器不允许将预处理做为
4、宏,也就是不允许这种宏替代#define PACK_STRUCT_BEGIN #pragma pack(1)所以想靠宏替换来完成字节对齐是不行了,于是就动了大工夫做了如下处理#ifdef WIN32#define PACK_STRUCT_STRUCT#define PACK_STRUCT_BEGIN#define PACK_STRUCT_END#else#define PACK_STRUCT_STRUCT _attribute_ (_packed_)#define PACK_STRUCT_BEGIN#define PACK_STRUCT_ENDendifPACK_STRUCT_BEGIN#if
5、def WIN32#pragma pack(1)#endifstruct icmp_echo_hdr PACK_STRUCT_FIELD(u8_t type); PACK_STRUCT_FIELD(u8_t code); PACK_STRUCT_FIELD(u16_t chksum); PACK_STRUCT_FIELD(u16_t id); PACK_STRUCT_FIELD(u16_t seqno);PACK_STRUCT_STRUCT;#ifdef WIN32#pragma pack()#endifPACK_STRUCT_END这样一改在VC下和GCC都可以了,不过每个结构上都要修改一下
6、,这个是黑郁闷黑郁闷啊“轻量级”保护lightweight synchronization mechanisms -SYS_ARCH_DECL_PROTECT(x) - declare a protection state variable.SYS_ARCH_PROTECT(x) - enterprotection mode.SYS_ARCH_UNPROTECT(x) - leaveprotection mode.这三个宏定义一个快速的“保护”和“解除保护”操作。例如进入保护可以是屏蔽中断或使用一个信号量或mutex。注意:进入保护后还允许再次进入保护,旧的保护标志通过lev返回,退出保护时再
7、恢复。如果没有定义这三个宏,Sys.h中有一段代码进行了判断。#ifndef SYS_ARCH_PROTECT如果没有定义SYS_ARCH_PROTECT,那么可以在lwipopts.h中定义宏SYS_LIGHTWEIGHT_PROT,并在sys_arch.c中定义函数sys_arch_protect()和sys_arch_unprotect(lev)#if SYS_LIGHTWEIGHT_PROT#define SYS_ARCH_DECL_PROTECT(lev) sys_prot_t lev/* SYS_ARCH_PROTECT* Perform a fast protect. This
8、could be implemented by* disabling interrupts for an embedded system or by using a semaphore or* mutex.The implementation should allow calling SYS_ARCH_PROTECT when* already protected. The old protection level is returned in the variable* lev. This macro will default to calling the sys_arch_protect(
9、) function* which should be implemented in sys_arch.c. If a particular port needs a* different implementation, then this macro may be defined in sys_arch.h*/#define SYS_ARCH_PROTECT(lev) lev = sys_arch_protect()/* SYS_ARCH_UNPROTECT* Perform a fast set of the protection level to lev. This could be*
10、implemented by setting the interrupt level to lev within the MACRO or by* using a semaphore or mutex. This macro will default to calling the* sys_arch_unprotect() function which should be implemented in* sys_arch.c. If a particular port needs a different implementation, then* this macro may be defin
11、ed in sys_arch.h*/#define SYS_ARCH_UNPROTECT(lev) sys_arch_unprotect(lev)sys_prot_t sys_arch_protect(void);void sys_arch_unprotect(sys_prot_t pval);#else#define SYS_ARCH_DECL_PROTECT(lev)#define SYS_ARCH_PROTECT(lev)#define SYS_ARCH_UNPROTECT(lev)#endif /* SYS_LIGHTWEIGHT_PROT */#endif /* SYS_ARCH_P
12、ROTECT */LWIP_COMPAT_MUTEX定义此宏表示用信号量来代替mutex。Init.c不定义NO_SYS和“#define NO_SYS 0”的效果是一样的。下面这些宏对代码有影响:LWIP_SOCKETLWIP_ARPLWIP_RAWLWIP_UDPLWIP_TCPLWIP_SNMPLWIP_AUTOIPLWIP_IGMPLWIP_DNSLWIP_TIMERSvoidlwip_init(void) /* Sanity check user-configurable values */ lwip_sanity_check(); /* Modules initialization
13、 */ stats_init();#if !NO_SYS sys_init();#endif /* !NO_SYS */ mem_init(); memp_init(); pbuf_init(); netif_init();#if LWIP_SOCKET lwip_socket_init();#endif /* LWIP_SOCKET */ ip_init();#if LWIP_ARP etharp_init();#endif /* LWIP_ARP */#if LWIP_RAW raw_init();#endif /* LWIP_RAW */#if LWIP_UDP udp_init();#
14、endif /* LWIP_UDP */#if LWIP_TCP tcp_init();#endif /* LWIP_TCP */#if LWIP_SNMP snmp_init();#endif /* LWIP_SNMP */#if LWIP_AUTOIP autoip_init();#endif /* LWIP_AUTOIP */#if LWIP_IGMP igmp_init();#endif /* LWIP_IGMP */#if LWIP_DNS dns_init();#endif /* LWIP_DNS */#if LWIP_TIMERS sys_timeouts_init();#end
15、if /* LWIP_TIMERS */netif_add函数它添加一个网络接口到lwip,一个网卡应该是一个网络接口。本地回环也是一个网络接口,它已经在tcpip_init中的lwip_init调用netif_init被添加。/* Add a network interface to the list of lwIP netifs.* param netif a pre-allocated netif structure* param ipaddr IP address for the new netif* param netmask network mask for the new net
16、if* param gw default gateway IP address for the new netif* param state opaque data passed to the new netif* param init callback function that initializes the interface* param input callback function that is called to pass* ingress packets up in the protocol layer stack.* return netif, or NULL if fai
17、led.*/struct netif *netif_add(struct netif *netif, ip_addr_t *ipaddr, ip_addr_t *netmask, ip_addr_t *gw, void *state, netif_init_fn init, netif_input_fn input)Struct net_if在初始化用netif_add添加到lwip中。/* Generic data structure used for all lwIP network interfaces.* The following fields should be filled in
18、 by the initialization* function for the device driver: hwaddr_len, hwaddr, mtu, flags */struct netif /* pointer to next in linked list */ struct netif *next; /* IP address configuration in network byte order */ ip_addr_t ip_addr; ip_addr_t netmask; ip_addr_t gw; /* This function is called by the ne
19、twork device driver * to pass a packet up the TCP/IP stack. */ netif_input_fn input;/网卡数据接收函数,自定义设置 /* This function is called by the IP module when it wants * to send a packet on the interface. This function typically * first resolves the hardware address, then sends the packet. */ netif_output_fn
20、output;/发送无连接的数据包,如广播包,多播包,最终还是调用下面的linkoutput函数。固定设置为etharp_output。 /* This function is called by the ARP module when it wants * to send a packet on the interface. This function outputs * the pbuf as-is on the link medium. */ netif_linkoutput_fn linkoutput;/发送有连接的数据包,已经包含MAC,类型等数据。#if LWIP_NETIF_ST
21、ATUS_CALLBACK /* This function is called when the netif state is set to up or down */ netif_status_callback_fn status_callback;#endif /* LWIP_NETIF_STATUS_CALLBACK */#if LWIP_NETIF_LINK_CALLBACK /* This function is called when the netif link is set to up or down */ netif_status_callback_fn link_call
22、back;#endif /* LWIP_NETIF_LINK_CALLBACK */ /* This field can be set by the device driver and could point * to state information for the device. */ void *state;/一般设置为网卡的私有数据,如netif-state = ethernetif;#if LWIP_DHCP /* the DHCP client state information for this netif */ struct dhcp *dhcp;#endif /* LWIP
23、_DHCP */#if LWIP_AUTOIP /* the AutoIP client state information for this netif */ struct autoip *autoip;#endif#if LWIP_NETIF_HOSTNAME /* the hostname for this netif, NULL is a valid value */ char* hostname;#endif /* LWIP_NETIF_HOSTNAME */ /* maximum transfer unit (in bytes) */ u16_t mtu; /* number of
24、 bytes used in hwaddr */ u8_t hwaddr_len; /* link level hardware address of this interface */ u8_t hwaddrNETIF_MAX_HWADDR_LEN; /* flags (see NETIF_FLAG_ above) */ u8_t flags; /* descriptive abbreviation */ char name2; /* number of this interface */ u8_t num;#if LWIP_SNMP /* link type (from snmp_ifTy
25、pe enum from snmp.h) */ u8_t link_type; /* (estimate) link speed */ u32_t link_speed; /* timestamp at last change made (up/down) */ u32_t ts; /* counters */ u32_t ifinoctets; u32_t ifinucastpkts; u32_t ifinnucastpkts; u32_t ifindiscards; u32_t ifoutoctets; u32_t ifoutucastpkts; u32_t ifoutnucastpkts
26、; u32_t ifoutdiscards;#endif /* LWIP_SNMP */#if LWIP_IGMP /* This function could be called to add or delete a entry in the multicast filter table of the ethernet MAC.*/ netif_igmp_mac_filter_fn igmp_mac_filter;#endif /* LWIP_IGMP */#if LWIP_NETIF_HWADDRHINT u8_t *addr_hint;#endif /* LWIP_NETIF_HWADD
27、RHINT */#if ENABLE_LOOPBACK /* List of packets to be queued for ourselves. */ struct pbuf *loop_first; struct pbuf *loop_last;#if LWIP_LOOPBACK_MAX_PBUFS u16_t loop_cnt_current;#endif /* LWIP_LOOPBACK_MAX_PBUFS */#endif /* ENABLE_LOOPBACK */;struct pbuf一个网络包可能由多个pbuf组成,字段tot_len指定这个网络包的大小,字段len是当前pb
28、uf包含数据的大小。判断一个网络包的最后一个包不能以next字段等于空来判断,它可能不为空,下一个pbuf为下一个网络包的内容。应该计算tot_len来判断一个包的结束。struct pbuf /* next pbuf in singly linked pbuf chain */ struct pbuf *next;/下一个pbuf /* pointer to the actual data in the buffer */ void *payload;/当前结构数据内容 /* * total length of this buffer and all next buffers in chai
29、n * belonging to the same packet. * * For non-queue packet chains this is the invariant: * p-tot_len = p-len + (p-next? p-next-tot_len: 0) */ u16_t tot_len; /* length of this buffer */ u16_t len; /* pbuf_type as u8_t instead of enum to save space */ u8_t /*pbuf_type*/ type; /* misc flags */ u8_t flags; /* * the reference count always equals the number of pointers * that refer to this pbuf. This can be pointers from an application, * the stack itself, or pbuf-next pointers from a chain.
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1