
前言 前不久接到一个客户的问题。在 H743 上需要通过 UDP 发送大的数据包,涉及到 IP 分包的问题。他们在测试的过程中遇到了只要发送 6KB 的 UDP 数据包就会出现 hardfault 的问题。拿到这个问题的时候,调试得到了和客户一样的现象,程序进入hardfault,并且是由 Lwip 协议栈的 ip_reass_free_complete_datagram 函数触发。后经过一番调试,搞清楚了问题的原因,要说清楚,我们得先来看看 Lwip 中 IP 分包的实现。 IP 分包 因为以太网对一次传输数据的最大长度规定为 1500 字节,所以如果 UDP 的数据包大于这个长度,就会在 IP 层进行分包后,再通过以太网传输。用户数据通过 UDP 发送,数据封装的过程如下图: ![]() IP 首部一般是 20 字节,UDP 首部 8 字节,1500-20-8=1472,所以当发送的用户数据超过 1472 个字节后,IP 层就会分包。 分包和重组的工作都是在 IP 层自动完成,对于 UDP 层来说,不用关心这个过程。 Lwip 中 IP 数据重组的实现 Lwip 中通过 ip_reassdata 数据结构来描述一份正在被重组的 IP 数据报,其中的 p 字段指向第一个数据分片。Lwip 中可以同时处理多个 IP 数据报的重组,每个 IP 数据报对应一个 ip_reassdata 数据结构,并且通过结构中的 next 指针构成一个单向的 链表。reassdatagrams,指向 ip_reassdata 结构组成的链表的开头。 当以太网底层驱动接收到数据后,将数据传递给 Lwip 协议栈,ip_input 函数会根据当前是 IPv4 还是 IPV6 调用对应的处理函数。在 ip4_input 中,通过检查 IP 首部中的标志位和分片偏移量,来判断当前是否是一个 IP 分片包。如果是就调用ip4_reass 进行重组。 在整个 IP 数据报重组完成之前,接收到的 IP 分片包都保存在 buffer 中,如果其中的某个分片丢失,则重组就无法完成,而这些不全的 IP 分包数据不能一直占着 buffer,所以在 Lwip 中定义了 ip_reassdata 的生存时间,每 1 秒执行一次 ip_reass_tmr函数,将生存时间减 1,当减到 0 后就删除对应的 ip_reassdata 数据结构,以及其上挂的所有数据分片 pbuf。 Lwip 中 IP 数据分片的实现 发送的过程比接收的过程相对简单,大致就是:UDP 层将要发送的数据组装在一个 pbuf 中,然后调用 ip_output 发送数据,当然在这个过程中,协议栈会添加相应的 IP 首部数据。如果 IP 数据报的长度大于以太网的 MTU 时,Lwip 协议栈的 IP 层就会进行分片,将数据报分成两个或者更多进行发送。IP 分片的工作是在 ip_frag 函数中完成的。代码的实现在这里就不详细展开介绍了。我们这里主要讲的是,我们在应用 Lwip 的时候,哪些配置参数是需要注意的 完整版请查看:附件 |
Lwip中和IP分包相关的参数.pdf
下载346.09 KB, 下载次数: 4
STM32 GUI LTDC 最大像素时钟评估方法
【2025·STM32峰会】GUI解决方案实训分享1-对LVGL咖啡机例程的牛刀小试以及问题排查
OpenBLT移植到STM32F405开发板
为什么要先开启STM32外设时钟?
【STM32MP157】从ST官方例程中分析RPMsg-TTY/SDB核间通信的使用方法
【经验分享】STM32实例-RTC实时时钟实验④-获取RTC时间函数与中断服务函数
STM32 以太网 MAC Loopback 的实现
STM32功能安全设计包,助力产品功能安全认证
基于STM32启动过程startup_xxxx.s文件经验分享
HRTIM 指南