Ubuntu 22.04.3中RealTek RTL8125网卡IEEE-1588/PTP硬件时间戳支持问题及ptp4l崩溃解决求助
我有一台搭载技嘉B650 AORUS ELITE AX主板的台式机,安装了Ubuntu 22.04.3系统,想把它作为IEEE-1588(Precision Time Protocol,PTP)主时钟,在一个仅包含非管理交换机和一台待同步设备的小型局域网中使用。
初始问题:无硬件时间戳支持,软件模式稳定性不足
启动ptp4l时我发现系统中没有/dev/ptpX节点,用ethtool -T检查网卡接口后,发现它似乎不支持硬件时间戳;而软件时间戳模式下,同步稳定性完全达不到我的需求——偏移量无法稳定在1000ns以内,还经常出现±100000ns的大幅跳变:
$ ethtool -T enp8s0 Time stamping parameters for enp8s0: Capabilities: software-transmit software-receive software-system-clock PTP Hardware Clock: none Hardware Transmit Timestamp Modes: none Hardware Receive Filter Modes: none
通过lspci确认网卡型号为RealTek RTL8125 2.5GbE控制器:
$ lspci | grep Ethernet 08:00.0 Ethernet controller: Realtek Semiconductor Co., Ltd. RTL8125 2.5GbE Controller (rev 05)
根据RealTek的官方资料,这款网卡应该支持PTP硬件时间戳,于是我尝试了官方提供的2.5G/5G Linux驱动(r8125版本9.012.04)。虽然官方标注该驱动仅支持到内核6.4,但我当前内核是6.5.0-15-generic,还是尝试编译安装了——编译时我在Makefile中开启了PTP支持,安装后ethtool -T确实显示硬件时间戳功能已启用:
ethtool -T enp8s0 Time stamping parameters for enp8s0: Capabilities: hardware-transmit software-transmit hardware-receive software-receive software-system-clock hardware-raw-clock PTP Hardware Clock: 0 Hardware Transmit Timestamp Modes: off on Hardware Receive Filter Modes: none ptpv2-l4-event ptpv2-l4-sync ptpv2-l4-delay-req ptpv2-event ptpv2-sync ptpv2-delay-req
新问题:ptp4l启动后直接崩溃
但当我启动ptp4l时,进程直接被杀死,内核日志中出现了空指针解引用的错误:
$ sudo ptp4l -i enp8s0 -p /dev/ptp0 -m ptp4l[2665.771]: selected /dev/ptp0 as PTP clock Killed
查看dmesg的错误日志片段:
[ 2891.569055] BUG: kernel NULL pointer dereference, address: 0000000000000000
[ 2891.569059] #PF: supervisor instruction fetch in kernel mode
[ 2891.569061] #PF: error_code(0x0010) - not-present page
...(省略中间栈追踪及模块信息)
[ 2891.915727] note: ptp4l[7502] exited with irqs disabled
尝试过的其他方案
我发现apt仓库中有r8125-dkms包,但这个版本(9.007.01)默认未开启PTP支持,安装后ethtool -T依然显示无硬件时间戳。我尝试修改/usr/src/下的Makefile并重新用dkms安装,但没有效果——而且该版本和RealTek官方的9.012.04差异很大,由于内核PTP相关结构体已变更,直接添加PTP支持会导致编译失败。
当前排查进展
目前我还没找到完整解决方案,但排查中发现了关键线索:内核的ptp_clock_info结构体移除了adjfreq成员,替换为adjfine。RealTek官方的9.012.04驱动确实没有设置adjfreq,但也没有实现新的adjfine等必要成员函数,而现在内核的ptp_clock_adjtime函数会调用adjfine:
static int ptp_clock_adjtime(struct posix_clock *pc, struct __kernel_timex *tx) { struct ptp_clock *ptp = container_of(pc, struct ptp_clock, clock); struct ptp_clock_info *ops; ... ops = ptp->info; ... } else if (tx->modes & ADJ_FREQUENCY) { long ppb = scaled_ppm_to_ppb(tx->freq); if (ppb > ops->max_adj || ppb < -ops->max_adj) return -ERANGE; err = ops->adjfine(ops, tx->freq); ptp->dialed_frequency = tx->freq; } ... return err; }
我尝试用空函数“伪造”这些未实现的函数,但ptp4l会卡在port 1: assuming the grand master role步骤无法继续。看起来我要么需要修改tx->modes的使用逻辑(目前不知道具体操作方法),要么就得正确实现驱动中的这些函数。目前我已经联系了驱动维护团队,但还未收到回复。
希望有人能帮我解决这个问题,不管是通过调整ptp4l配置、打驱动补丁还是其他方法。我最核心的需求是实现稳定的PTP同步,当然能用上硬件时间戳是最优选择。
备注:内容来源于stack exchange,提问作者Douglas B




