OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 5084|回复: 9

H750+Lwip2.0.3+FreeRTOS Ping大包会丢包,清空分片包链的时候会跑飞

[复制链接]

1

主题

3

帖子

0

精华

新手上路

积分
27
金钱
27
注册时间
2019-9-20
在线时间
5 小时
发表于 2019-9-20 19:01:40 | 显示全部楼层 |阅读模式
1金钱
  1. static int
  2. ip_reass_free_complete_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev)
  3. {
  4.   u16_t pbufs_freed = 0;
  5.   u16_t clen;
  6.   struct pbuf *p;
  7.   struct ip_reass_helper *iprh;

  8.   LWIP_ASSERT("prev != ipr", prev != ipr);
  9.   if (prev != NULL) {
  10.     LWIP_ASSERT("prev->next == ipr", prev->next == ipr);
  11.   }

  12.   MIB2_STATS_INC(mib2.ipreasmfails);
  13. #if LWIP_ICMP
  14.   iprh = (struct ip_reass_helper *)ipr->p->payload;
  15.   if (iprh->start == 0) {
  16.     /* The first fragment was received, send ICMP time exceeded. */
  17.     /* First, de-queue the first pbuf from r->p. */
  18.     p = ipr->p;
  19.     ipr->p = iprh->next_pbuf;
  20.     /* Then, copy the original header into it. */
  21.     SMEMCPY(p->payload, &ipr->iphdr, IP_HLEN);
  22.     icmp_time_exceeded(p, ICMP_TE_FRAG);
  23.     clen = pbuf_clen(p);
  24.     LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff);
  25.     pbufs_freed = (u16_t)(pbufs_freed + clen);
  26.     pbuf_free(p);
  27.   }
  28. #endif /* LWIP_ICMP */

  29.   /* First, free all received pbufs.  The individual pbufs need to be released
  30.      separately as they have not yet been chained */
  31.   p = ipr->p;
  32.   while (p != NULL) {
  33.     struct pbuf *pcur;
  34.     iprh = (struct ip_reass_helper *)p->payload;
  35.     pcur = p;
  36.     /* get the next pointer before freeing */
  37.     p = iprh->next_pbuf;
  38.     clen = pbuf_clen(pcur);
  39.     LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff);
  40.     pbufs_freed = (u16_t)(pbufs_freed + clen);
  41.     pbuf_free(pcur);
  42.   }
  43.   /* Then, unchain the struct ip_reassdata from the list and free it. */
  44.   ip_reass_dequeue_datagram(ipr, prev);
  45.   LWIP_ASSERT("ip_reass_pbufcount >= pbufs_freed", ip_reass_pbufcount >= pbufs_freed);
  46.   ip_reass_pbufcount = (u16_t)(ip_reass_pbufcount - pbufs_freed);

  47.   return pbufs_freed;
  48. }
复制代码
现象:ping超过mtu的字节数时,分片数据丢包,导致开启reass定时器,这里进入上面的函数来释放分片数据链,通过 (struct ip_reass_helper *)p->payload来释放分片包,但这里会指向异常地址,导致hardfault。工具:IAR

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

31

主题

2183

帖子

0

精华

资深版主

Rank: 8Rank: 8

积分
14287
金钱
14287
注册时间
2018-8-3
在线时间
1147 小时
发表于 2019-9-20 19:20:12 | 显示全部楼层
回复

使用道具 举报

12

主题

76

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
231
金钱
231
注册时间
2018-6-15
在线时间
33 小时
发表于 2019-9-23 16:26:20 | 显示全部楼层
楼主问题解决了嘛
回复

使用道具 举报

1

主题

3

帖子

0

精华

新手上路

积分
27
金钱
27
注册时间
2019-9-20
在线时间
5 小时
 楼主| 发表于 2019-9-25 19:14:54 | 显示全部楼层
陈其旦 发表于 2019-9-23 16:26
楼主问题解决了嘛

并没有啊,先暂时关闭接收分片了
回复

使用道具 举报

1

主题

3

帖子

0

精华

新手上路

积分
27
金钱
27
注册时间
2019-9-20
在线时间
5 小时
 楼主| 发表于 2019-9-25 19:15:38 | 显示全部楼层
自顶,卡在这里很久了
回复

使用道具 举报

0

主题

4

帖子

0

精华

新手入门

积分
19
金钱
19
注册时间
2019-5-8
在线时间
4 小时
发表于 2020-7-19 07:16:41 | 显示全部楼层
楼主,你好。我用打印寄存器的方式判定异常也是跟你的问题一模一样,能否加为好友以前探讨一下这个技术问题?
回复

使用道具 举报

0

主题

4

帖子

0

精华

新手入门

积分
19
金钱
19
注册时间
2019-5-8
在线时间
4 小时
发表于 2020-7-19 07:48:12 | 显示全部楼层
回复

使用道具 举报

0

主题

4

帖子

0

精华

新手入门

积分
19
金钱
19
注册时间
2019-5-8
在线时间
4 小时
发表于 2020-7-19 07:49:34 | 显示全部楼层
楼主,请试试这个药方:
https://savannah.nongnu.org/bugs ... m&item_id=38210
如果药方有效,请一定要回来答复一下,谢谢!
回复

使用道具 举报

1

主题

2

帖子

0

精华

新手入门

积分
14
金钱
14
注册时间
2020-7-13
在线时间
5 小时
发表于 2020-7-23 11:38:08 来自手机 | 显示全部楼层
楼主你好,最近也在调试网络能否添加好友,相互探讨
回复

使用道具 举报

0

主题

4

帖子

0

精华

新手入门

积分
19
金钱
19
注册时间
2019-5-8
在线时间
4 小时
发表于 2020-8-26 11:30:47 | 显示全部楼层
我这边有一个项目,现场用了70多台这样的设备。接到的反馈是,总有5-10台设备运行3-14天就完全没有反应,重启就正常。哪台设备,能正常运行多少天才死机,是随机的。后来最终定位是Lwip处理分片包数据确实是有BUG。经过3个月的时间,我修复了这个问题。其中包括长期运行了仅2个月来验证修复效果,没有一台出问题了。这里提供我的解决方案,大家可参考:
static int
ip_reass_remove_oldest_datagram(struct ip_hdr *fraghdr, int pbufs_needed)
{
  /* @ToDo Can't we simply remove the last datagram in the
   *       linked list behind reassdatagrams?
   */
  struct ip_reassdata *r, *oldest, *prev, *oldest_prev;
  int pbufs_freed = 0, pbufs_freed_current;
  int other_datagrams;

  /* Free datagrams until being allowed to enqueue 'pbufs_needed' pbufs,
   * but don't free the datagram that 'fraghdr' belongs to! */
  do {
    oldest = NULL;
    prev = NULL;
    oldest_prev = NULL;
    other_datagrams = 0;
    r = reassdatagrams;
    while (r != NULL) {
      if (!IP_ADDRESSES_AND_ID_MATCH(&r->iphdr, fraghdr)) {
        /* Not the same datagram as fraghdr */
        other_datagrams++;
        if (oldest == NULL) {
          oldest = r;
          oldest_prev = prev;
        } else if (r->timer <= oldest->timer) {
          /* older than the previous oldest */
          oldest = r;
          oldest_prev = prev;
        }
      }
      if (r->next != NULL) {
        prev = r;
      }
      r = r->next;
    }

//    if (oldest != NULL) {
        //fix 如果待删除的是头结点,而oldest->next 节点不能为空;
        // 否则运行ip_reass_dequeue_datagram(ipr, prev)后,将导致删掉头结点后
        // 头结点指向NULL;
        if (oldest != NULL && (!(oldest==reassdatagrams && oldest->next==NULL))) {
      pbufs_freed_current = ip_reass_free_complete_datagram(oldest, oldest_prev);
      pbufs_freed += pbufs_freed_current;
    }
  }        
  
//  while ((pbufs_freed < pbufs_needed) && (other_datagrams > 1));
       
  while (((pbufs_freed < pbufs_needed) && (other_datagrams > 1))
          && (!(oldest==reassdatagrams && NULL==oldest_prev))
          && (!(oldest==NULL && oldest_prev==NULL)));//迫使程序务必不要删掉头结点的数据;

  return pbufs_freed;
}
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-24 14:27

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表