主题中讨论的其他器件: SK-AM62
工具与软件:
尊敬的专家:
我的主要问题是尝试使用 tftp 从 AM625 Linux 用户空间下载大文件时出现可重复的超时。 有趣的是、这可以通过 IPv4连接到 tftp 服务器(我的笔记本电脑)、但现在我尝试通过 IPv6链路本地连接来实现。 请注意、我的设置使用 IPv6上的 UDP。
使用 tftp 服务器上的 Wireshark 调试时、我注意到下载在从 AM625发送到我的笔记本电脑的 UDP 封装校验和到达零时超时。 (UDP 数据包内容是一些 ACK 消息、数据包 ID 向上计数、因此 UDP 校验和从某个初始值向下计数到零。) 似乎我的笔记本电脑放弃了带有 UDP 校验和0的 ACK 响应、这是 RFC 2460的强制要求、它描述了 IPv6上的 UDP:
o 与 IPv4不同、当 UDP 数据包由 IPv6节点发起时、 UDP 校验和不是可选的。 发送信号 IPv6节点必须在源自 UDP 数据包时计算 UDP 以及伪标头(如有)上的校验和 计算得出结果为零、必须将其更改为十六进制 用于放置在 UDP 标头中的 FFFF。 IPv6接收器必须 丢弃包含零校验和的 UDP 数据包、并应记录下来 误差。 [强调地雷]
暂时我可以使用来解决该问题
ethtool --offload eth0 tx off在 tftp 下载之前;但是、如果我理解正确、这将为所有 TCP 和 UDP 通信的所有互联网校验和计算(之后在生产环境中)增加 CPU 的负担。
为了验证该问题、我编写了一个小的 python 脚本来发送某个小的 UDP 软件包、经过改编后的 UDP 校验和为零(经过一些试错)。
import socket
from time import sleep
from itertools import cycle
ip6 = "fe80::443a:64c4:2cd8:fd26"
dev = "eth0"
addr = f"{ip6}%{dev}"
port = 8648
family, type_, proto, canonname, sockaddr = socket.getaddrinfo(
addr,
port,
family=socket.AF_INET6,
type=socket.SOCK_DGRAM,
proto=socket.IPPROTO_UDP,
).pop()
sock_send = socket.socket(family=family, type=type_, proto=proto)
sock_send.sendto(b"t0z-\r\n", sockaddr) # effects UDP_checksum == 0
实际上、硬件卸载逻辑似乎错误地处理了零情况(应将0x0000替换为0xFFFF)。 INSEAD 是 UDP 数据包通过 UDP 校验和零发送的、如接收端通过 Wireshark 指示:

问题:我们是否遗漏了 AM625硬件的某些配置、该配置改变了特殊情况(0 --> 0xFFFF)下的 IPv6-UDP-校验和的计算? 或者这是硬件错误吗、我们必须使用由软件计算的 UDP-Checksums。
提前感谢此致、
Lukas Rauber

