1 关键字

DHCPDHCP client;获取IP慢;

2 问题描述

系统版本:OpenHarmony 3.2 Release

问题现象:设备网口为自动获取IP模式,通过网线接入网络进行DHCP拨号,网卡获取到IP的时间较长,大概在60~120

      才能获取到IP

3 问题原因

     正常机制

  一般网卡能够在10~15秒获取到IP地址。

    异常机制

    网口插上网线后需要1~2分钟的时间才获取到IP地址。

4 解决方案

OpenHarmony底座代码/foundation/communication/wifi/dhcp/services/dhcp_client/src/dhcp_socket.c文件,

修改CheckPacketIpSum函数。

在调用CheckUdpPacket返回失败后,删除sleep 500ms的处理,立即返回处理其他接收到的报文。

  

 

5 定位过程

1、定位前需要对DHCP协议以及DHCP client实现有大致的了解

  首先简单了解下DHCP获取IP地址的过程。下图就是DHCP获取IP的过程,主要由4个报文交互完成设备(AP)作为

      DHCP client获取IP的流程,对应的报文分别为:discoveryofferrequestACK

              

   另外,在DHCP client进程收发包时,由于设备是没有IP地址的,因此在通过socket收包时要使用raw socket来接收报文。

 当DHCP拨号成功之后,收包socket就切换普通的socket了。

2、DHCP client获取IP的代码流程

                   DHCP client的代码实现在\foundation\communication\wifi\dhcp\services\dhcp_client\目录下。

                  1) dhcp_ipv4.c中的StartIpv4函数就是DHCP client获取IP的主要函数。

                 

 

                 2)  DhcpRequestHandle函数主要实现DHCP报文的发送,这里调用InitSelecting函数来发送discovery报文。

                

 

                    DhcpResponseHandle函数主要实现socket接收到报文的处理。

               

 

  1.  

3、通过wireshark抓包查看DHCP的交互

     如果设备上能够进行wireshark抓包,可以很直观的看到DHCP获取IP地址的交互过程,能够比较快的看出DHCP交互的

     哪个阶段有问题,再结合日志来分析具体的问题根因。

     本案例中,由于设备无法对网卡进行镜像抓包,只能从头到尾分析日志来确定问题点。

  1.  

4、寻找DHCP获取IP地址的异常日志

      1) 先找到发送discovery报文的日志。代码中发送discovery报文的是InitSelecting函数,此函数处理流程的最后有一条日志,

        记录了以下的关键信息:

        > 发送discovery报文的次数g_sentPacketNum

        > 发送下一个discovery报文距离当前的间隔时间uTimeoutSec

        > 本次发送discovery报文后等待接收offer报文的超时时间g_timeoutTimestamp

                  

 

    在问题日志中搜索InitSelecting这个关键字,以下为搜索结果。从日志上可以看出,discovery报文按照1s2s4s

    8s16s32s间隔进行重发。重复发送6discovery报文共耗时大概1分钟,前5discovery报文重发耗时约30s

    最后一次discovery报文重发超时时间间隔32s

             DHCP client一直在重复发送discovery,需要找出为什么一直没有收到offer报文。

          

 

   2) 从” InitSelecting() DhcpDiscover g_sentPacketNum:0,timeoutSec:1,timestamp:868.”开始往下看日志,看是否能够找到

     有异常的地方。

     由日志上可以看到与代码实现一致的函数调用关系:

     发送discovery报文流程

                StartIpv4àDhcpRequestHandleàInitSelectingàDhcpDiscover

     接收offer报文的流程

                StartIpv4àDhcpResponseHandleàGetDhcpRawPacket

   3) 发现日志中有”CheckUdpPacket() failed, pPacket->udp.dest:16327 error, htons:17408!”的记录。

 

            

 

            CheckUdpPacket函数的调用流程是:

           GetDhcpRawPacketàCheckPacketIpSumàCheckUdpPacket

    也就是在收包流程中函数调用失败了。

        

   日志结合代码看,CheckUdpPacket函数在检查收到的报文是否为DHCP报文时失败了,表示这里收到的报文

   不是DHCP报文。前面已经提到,由于设备目前还没有获取到IP地址,是使用raw socket来收包的,如果网络

   环境中有许多其他的UDP报文这里就会返回失败。

        4)  CheckUdpPacket返回失败后的处理是什么呢?

          

       调用CheckUdpPacket的上一级函数是CheckPacketIpSum。由CheckPacketIpSum的实现看出在

   CheckUdpPacket处理失败时,sleep 500ms

   考虑下这里进程睡眠500ms的影响?当网络环境中有很多这类UDP的杂包时,在等待offer报文时只要

   收到一个非DHCPUDP报文,就要睡眠500ms,这样有可能使DHCP client进程无法收到预期的offer

   报文,并需要多次重发discoveryDHCP获取IP的时长受到网络环境的影响。

 

  5) 为了验证上述分析的正确性,缩短CheckPacketIpSum调用CheckUdpPacket返回失败时sleep的时长为1ms

    编译版本进行验证。结果DHCP client获取IP的速度显著提升,说明这里sleep的处理正是导致DHCP client

    获取IP地址慢的原因。

6 知识分享

        1、DHCP client获取IP地址的流程为二轮交互,4个报文分别为:discoveryofferrequestACK

        2、raw socket收包会收到网卡上所有的报文。

Logo

社区规范:仅讨论OpenHarmony相关问题。

更多推荐