uboot下tftp在tp-link路由器上不通

博客讲述了在UBoot环境下,使用TFTP进行升级时遇到的问题,即在TP-Link路由器上无法通信,而在交换机和Kernel下却正常。通过抓包分析,发现UBoot未计算UDP校验和,而TP-Link路由器要求校验和。解决方案是在UBoot协议栈构建UDP包时计算校验和,从而成功解决通信问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题描述

1、Uboot下执行tftp命令,在交换机上可以下载升级;在tp-link路由器上失败。

2、Kernel下执行tftp命令,交换机上和tp-link路由器上均可成功。

3、Uboot下,tp-link路由器上一个包也抓不到,TFTP_RRQ包也没发过来。

4、均可以ping通。
uboot下现象:

HKVS # updateb
*******************************************************
*    ATTENTION: PLEASE READ THIS NOTICE CAREFULLY!    *
* DO NOT reset the device, or disrupt this process.   *
* If this process fails, the device might be unusable.*
* If you find this too risky, power off device now.   *
* or press the SPACE key to start the process now     *
*******************************************************

Trying eth0
link up on port 0, speed 100, full duplex
Using eth0 device
TFTP from server 10.15.2.44; our IP address is 10.15.2.45
Filename 'u-boot_8127.bin'.
Load address: 0x81000000
Loading: T T T T T T T T T T T T T T T T T T T 

wireshark抓包:

Wireshark抓不到包

问题重现

使用TP-link路由器,uboot下用tftp进行升级可重现此问题

排查过程

原因分析

  • 抓包分析

因为uboot下TP-link路由器上是抓不到包的,所以我们在交换机上进行抓包进行对比,为了使我们抓的包有对比性,主要抓了下面两个包:

1、在交换机上,uboot下,执行tftp命令进行抓包

2、在交换机上,kernel下,执行tftp命令进行抓包

我们选取这两个包是因为:

1、在交换机上,uboot、kernel下执行tftp命令均可以的;

2、在路由器上,uboot下执行tftp命令不通,kernel下执行tftp命令可以。

这样我们可以分析出kernel下的tftp包和uboot下tftp包的区别。

  • 原因一:uboot问题

1、cpsw模块

这个模块主要的功能是初始化硬件,我们对8147芯片的配置和PHY模块(Realtek RTL8201)配置主要在这里执行。

在TCP/IP网络中,数据包通过socket传入到传输层中,再经过网络层最后传入数据链路层,数据链路层通过EMAC的GMII/RGMII/RMII端口进行数据通信,通过MDIO读写PHY寄存器,数据流的传输参考下图:

2、eth模块

主要注册一个eth设备,提供eth_write,eth_read,eth_init,eth_halt等操作,这个模块一般屏蔽了硬件的差异,为上层提供统一的API

3、net模块

这个模块主要实现一个简单的协议栈,主要是构建相应的包,例如我们使用的tftp协议,是一个udp包,这里主要就实现了udp包的构建及解析。

4、tftp模块

这个模块主要是应用层的传输数据的协议

这几个模块的具体的关系及调用关系可以参考下图:

  • 原因二:TP-link路由器问题

1、把tftp包抛弃,包过不了路由器因为在OS下,tftp在TP-link路由器,交换机上均可以通;在Uboot下路由器上不通,交换机上通。所以在OS下抓路由器的包与Uboot下抓交换机的包,进行对比,找出两个包的差别,下图分别是OS下路由器的包,与uboot下交换机的包:

OS下包:

Uboot下包:

这两个包进行对比可以发现主要有以下不同:

IP地址不同

端口号不同

Checksum不同,OS下做了Checksum的校验,Uboot下没有做checksum的校验

这样我们就大概知道在路由器上不通的原因可能是因为没有做Checksum的计算的缘故

解决方案

基于以上的分析,我们在协议栈构建UDP包的时候做UDP的校验和的计算,然后进行测试,结果在路由器上和交换机上tftp均可使用,至此问题解决。

总结

1、通过我们的分析,可以发现uboot下在TP-link上路由器上不通,主要是因为Uboot下没有做UDP的校验和,而是默认赋值0,也就是不使能udp校验和,UDP协议规定UDP校验和的计算是可选的,这也是在交换机上可以通的原因。

2、但是在TP-link上不通,说明TP-link上的做法是必须进行UDP校验和的计算,否则包就给丢弃,这也是TP-link路由器的一个缺陷。

附件:



CheckSum(ushort *buffer,uint size)
{    
    ulong cksum = 0;    
    while(size > 1){        
        cksum += *buffer++;        
        size -= sizeof(ushort);    
    }
    if(size){        
        cksum += *(uchar*)buffer; <span style="white-space: pre;">      </span>//奇数   
    }    
    cksum = (cksum >> 16) + (cksum & 0xffff);    
    cksum += (cksum >> 16);<span style="white-space: pre;">     </span> <span style="white-space: pre;">        </span>//进位   
    return ~((ushort)cksum);<span style="white-space: pre;">           </span>//取反
}

 unsigned 
 UdpCheckSum(uint saddr,uint daddr, ushort *buffer, uint size)
{  
    uchar Buf[1024];    
    typedef struct pseudo_hdr    
    {        
        uint  src;
        uint  dst;
        uchar         mbz;
        uchar         proto;
        ushort        len;
    }pseudo_hdr;

    ulong sum = 0;    
    pseudo_hdr *ph;
    uint ph_len = sizeof(struct pseudo_hdr);
    ph = (pseudo_hdr*)Buf;

    ph->src = saddr;    
    ph->dst = daddr;    
    ph->mbz = 0;    
    ph->proto = IPPROTO_UDP;
    ph->len = htons(size);       <span style="white-space: pre;">       </span>//size = Udp header + payload 

    /*******************************************************************************
        buffer = udpheader + payload,  size = sizeof(udpheader + payload) 
        ph_len + size = persudo_udp_head_len + UDP_head_len + payload_len
    ********************************************************************************/

    memcpy(Buf + ph_len, buffer, size); 

    sum = CheckSum((ushort*)Buf, ph_len + size);

    return sum;
}
不死uboot-tplink703n,说下使用方法 1:先刷我编译的u-boot分区可以写的版本,对应压缩包里面的mtd_write_able.bin这个固件, 2:ssh登陆到路由器,用winscp拷贝gen_uboot.sh和tuboot.bin到/tmp文件夹中. 3:putty中执行脚本 命令是 sh gen_uboot.sh 4:会在/tmp文件夹中生成128kb并且保存了你mac信息的完整uboot uboot.bin这个文件 在这里,用Winscp登陆路由将/tmp/uboot.bin拷贝到自己电脑里面,用UltraEdit打开,找到最后面有很多FF的地方,再慢慢向前找到FF开始的地方就可以看到MAC地址了,将其进行修改即可(建议在原来的基础上面修改一位即可,可减少因MAC地址不符而变砖机的风险),改完记得删除路由/tmp/uboot.bin,再把改过的重新上传到/tmp。可参考下图: 5:执行 mtd -r write uboot.bin u-boot 6:路由器会自动重启,如果可以成功引导,说明你刷新成功了,一般不会错的,淡定 7:开机前,按着reset键再开机会进入uboot的救援模式,设置本机ip 192.168.1.2 掩码255.255.255.0 访问192.168.1.1 就可以看到救援模式了.切记使用火狐可以刷新成功 8:压缩包里面还提供了最新trunk_luci的编译版本,因为mtd_write_able.bin这个版本使用dreambox的源码编译,无线驱动不起来,所以同学们不要以为自己的无线挂了,刷新trunk+luci版后可以确定无线是好的 9:必须用以上说的办法生成完整版128kb的uboot再刷新,不然丢失mac信息,无线必
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值