这几天在为一个网络控制器实现IEEE 1588单步时间戳的驱动,几经调试终于完工了。顺便分享一下调试方法,当然如果你想玩1588的单步时间戳,首先得有支持这个功能的硬件平台。如果对1588报文单步时间戳不了解,可以查看我之前的文章“IEEE 1588 Sync报文单步时间戳”。
平台和工具
我用的平台就不透露了,测试使用两块板子,网口直连。用到的软件包括,
- Linux:这是我板子的OS,包含我要验证的驱动。
- tcpdump:抓包工具,位于板子的文件系统。
- linuxptp:开源PTP软件,位于板子的文件系统。
- Wireshark,Windows电脑上的软件,用来查看抓包文件。
调试方法
- 两个板子网口直连,启动Linux。
- 配置IP地址,确保两个网口能ping通。
- 一个板子做接收,运行tcpdump抓包,可直接查看,也可以保存成pcap文件在Wireshark中打开查看。
- 另一个板子做发送,运行ptp4l做master,发送单步Sync报文。
发送方命令
使用L2 Ethernet协议,运行ptp4l做master,发送单步时间戳Sync报文
代码语言:javascript复制# ptp4l -i eth0 -m --twoStepFlag=0 -2
ptp4l[613.615]: selected /dev/ptp0 as PTP clock
ptp4l[613.652]: port 1: INITIALIZING to LISTENING on INIT_COMPLETE
ptp4l[613.653]: port 0: INITIALIZING to LISTENING on INIT_COMPLETE
ptp4l[619.801]: port 1: LISTENING to MASTER on ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES
ptp4l[619.802]: selected local clock 00e00c.fffe.001600 as best master
ptp4l[619.802]: port 1: assuming the grand master role
使用UDP/IPv4协议,运行ptp4l做master,发送单步时间戳Sync报文
代码语言:javascript复制# ptp4l -i eth0 -m --twoStepFlag=0
ptp4l[636.150]: selected /dev/ptp0 as PTP clock
ptp4l[636.152]: port 1: INITIALIZING to LISTENING on INIT_COMPLETE
ptp4l[636.153]: port 0: INITIALIZING to LISTENING on INIT_COMPLETE
ptp4l[643.497]: port 1: LISTENING to MASTER on ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES
ptp4l[643.497]: selected local clock 00e00c.fffe.001600 as best master
ptp4l[643.497]: port 1: assuming the grand master role
接收方命令和结果
使用tcpdump直接查看接收报文完整的数据
代码语言:javascript复制# tcpdump -i eth0 -xx
可以看到对L2 Ethernet报文和UDP/IPv4报文,PTP消息的correctionField和originTimestamp字段的数值,直接就解析出来了。
L2 Ethernet:
UDP/IPv4:
结束语
Sync报文发送的硬件时间戳应该是originTimestamp和correctionField相加。根据1588标准的规定,originTimestamp和实际发送硬件时间戳差值不能超过1s,所以对具体的硬件,如果originTimestamp是在发送报文前由软件填写的,那么一定要在填写后立即发送,使得correctionField不能超过1s。当前验证的硬件就是这种实现,所以correctionField在2us多,应该还是合理的。如果硬件做单步时间戳的同时,又支持回写时间戳,那就可以拿回写时间戳和单步时间戳(originTimestamp correctionField)比较。如果相等,就说明硬件工作没有问题。