在Linux下,如何以编程方式检查给定NIC是否支持传输时间戳?
我试图找到一种方法,在Linux和C下,通过编程检查给定NIC是否支持软件传输时间戳(在Linux下,如何以编程方式检查给定NIC是否支持传输时间戳?,c,linux,sockets,linux-kernel,timestamp,C,Linux,Sockets,Linux Kernel,Timestamp,我试图找到一种方法,在Linux和C下,通过编程检查给定NIC是否支持软件传输时间戳(SOF_timestamp\u TX_software),以便在不支持的情况下恢复到其他类型的时间戳(或完全禁用它们) 特别是,我的目标是在调用ioctl(SIOCSHWTSTAMP)并检查其返回值(可以找到更新的文档)时,检查它们是否得到支持,就像对硬件时间戳一样 ethtool-T已经提供了此信息,但我认为调用system()或popen()不是一个好主意,因为ethtool可能没有安装在系统上,我肯定不想
SOF_timestamp\u TX_software
),以便在不支持的情况下恢复到其他类型的时间戳(或完全禁用它们)
特别是,我的目标是在调用ioctl(SIOCSHWTSTAMP)
并检查其返回值(可以找到更新的文档)时,检查它们是否得到支持,就像对硬件时间戳一样
ethtool-T
已经提供了此信息,但我认为调用system()
或popen()
不是一个好主意,因为ethtool
可能没有安装在系统上,我肯定不想将其作为运行程序的先决条件
在进行一点实验时,我使用了以下代码的改编:
相反,如果我尝试通过无线接口启动示例程序,而不支持任何类型的传输时间戳,如ethtool
所述:
$ ethtool -T wlp1s0
Time stamping parameters for wlp1s0:
Capabilities:
software-receive (SOF_TIMESTAMPING_RX_SOFTWARE)
software-system-clock (SOF_TIMESTAMPING_SOFTWARE)
PTP Hardware Clock: none
Hardware Transmit Timestamp Modes: none
Hardware Receive Filter Modes: none
对于与软件传输时间戳有关的内容,我从未收到任何循环回错误队列的消息,如果-1
被指定为poll
超时,则会导致无限期等待;如果指定了超时,则会导致EAGAIN
错误(当设置超时时,所有时间都会过期):
sudo./test wlp1s0
节目开始了。
来源IP:172.22.116.105
迭代:0-HW_邮票?0
测试开始了。
已发送数据包编号0/10
..........
使用UDP套接字和原始套接字时的结果相同(通过将#define raw_SOCKET
设置为1
或0
)
为了避免等待永远不会出现的回送消息(或等待超时过期),我是否可以通过编程方式检查给定接口是否支持SOF_TIMESTAMPING_TX_SOFTWARE
,并最终禁用程序中的整个机制,在尝试检索无法检索的传输时间戳之前
非常感谢您。您应该使用与
ethtool
相同的界面。有一个名为SIOCETHTOOL
的特定ioctl,它从驱动程序级别检索有关时间戳功能的信息。这是一个简短的示例(为了简洁起见,缺少错误处理等):
RX时间戳也是如此。通过这种方式,您应该能够确定时间戳是否受支持。请注意。是的,谢谢!实际上,我并没有把太多的注意力放在
strncpy
/strcpy
调用上,因为这只是一个示例代码,但这肯定是代码中需要解决的问题,主要是对于没有IFNAMSIZ
的调用,它应该已经考虑到接口名称的最大大小加上终止的零字节。
$ sudo ./test enp0s31f6
Program started.
source IP: 192.168.1.210
Iteration: 0 - HW_STAMPS? 0
Test started.
Sent packet number 0/10
HW: 0 s, 0 ns
ts[1] - ???: 0 s, 0 ns
SW: 1563878575 s, 690256891 ns
Sent packet number 1/10
HW: 0 s, 0 ns
ts[1] - ???: 0 s, 0 ns
SW: 1563878576 s, 690468816 ns
Sent packet number 2/10
HW: 0 s, 0 ns
ts[1] - ???: 0 s, 0 ns
SW: 1563878577 s, 691003245 ns
Sent packet number 3/10
HW: 0 s, 0 ns
ts[1] - ???: 0 s, 0 ns
SW: 1563878578 s, 691365791 ns
Sent packet number 4/10
HW: 0 s, 0 ns
ts[1] - ???: 0 s, 0 ns
SW: 1563878579 s, 691940147 ns
Sent packet number 5/10
HW: 0 s, 0 ns
ts[1] - ???: 0 s, 0 ns
SW: 1563878580 s, 692198712 ns
Sent packet number 6/10
HW: 0 s, 0 ns
ts[1] - ???: 0 s, 0 ns
SW: 1563878581 s, 692543005 ns
Sent packet number 7/10
HW: 0 s, 0 ns
ts[1] - ???: 0 s, 0 ns
SW: 1563878582 s, 692856348 ns
Sent packet number 8/10
HW: 0 s, 0 ns
ts[1] - ???: 0 s, 0 ns
SW: 1563878583 s, 693098097 ns
Sent packet number 9/10
HW: 0 s, 0 ns
ts[1] - ???: 0 s, 0 ns
SW: 1563878584 s, 693612477 ns
Iteration: 1 - HW_STAMPS? 1
Test started.
Sent packet number 0/10
HW: 1563878585 s, 717541747 ns
ts[1] - ???: 0 s, 0 ns
SW: 0 s, 0 ns
Sent packet number 1/10
HW: 1563878586 s, 718023872 ns
ts[1] - ???: 0 s, 0 ns
SW: 0 s, 0 ns
Sent packet number 2/10
HW: 1563878587 s, 718505122 ns
ts[1] - ???: 0 s, 0 ns
SW: 0 s, 0 ns
Sent packet number 3/10
HW: 1563878588 s, 719091997 ns
ts[1] - ???: 0 s, 0 ns
SW: 0 s, 0 ns
Sent packet number 4/10
HW: 1563878589 s, 719689747 ns
ts[1] - ???: 0 s, 0 ns
SW: 0 s, 0 ns
Sent packet number 5/10
HW: 1563878590 s, 720231247 ns
ts[1] - ???: 0 s, 0 ns
SW: 0 s, 0 ns
Sent packet number 6/10
HW: 1563878591 s, 720462747 ns
ts[1] - ???: 0 s, 0 ns
SW: 0 s, 0 ns
Sent packet number 7/10
HW: 1563878592 s, 721012872 ns
ts[1] - ???: 0 s, 0 ns
SW: 0 s, 0 ns
Sent packet number 8/10
HW: 1563878593 s, 721272372 ns
ts[1] - ???: 0 s, 0 ns
SW: 0 s, 0 ns
Sent packet number 9/10
HW: 1563878594 s, 721588497 ns
ts[1] - ???: 0 s, 0 ns
SW: 0 s, 0 ns
$ ethtool -T wlp1s0
Time stamping parameters for wlp1s0:
Capabilities:
software-receive (SOF_TIMESTAMPING_RX_SOFTWARE)
software-system-clock (SOF_TIMESTAMPING_SOFTWARE)
PTP Hardware Clock: none
Hardware Transmit Timestamp Modes: none
Hardware Receive Filter Modes: none
sudo ./test wlp1s0
Program started.
source IP: 172.22.116.105
Iteration: 0 - HW_STAMPS? 0
Test started.
Sent packet number 0/10
.....<stops here>.....
// Specify the ethtool parameter family (timestamping)
struct ethtool_ts_info tsi = {.cmd = ETHTOOL_GET_TS_INFO};
// Specify interface to use (eth1 in this example) and pass data buffer
struct ifreq ifr = {.ifr_name = "eth1", .ifr_data = (void*)&tsi};
// Create a socket for the ioctl command
int fd = socket(AF_INET, SOCK_DGRAM, 0);
// Perform the ioctl
ioctl(fd, SIOCETHTOOL, &ifr);
// and analyze the results
if (tsi.so_timestamping & SOF_TIMESTAMPING_TX_HARDWARE)
printf("%s supports hardware tx timestamps\n", ifr.ifr_name);
if (tsi.so_timestamping & SOF_TIMESTAMPING_TX_SOFTWARE)
printf("%s supports software tx timestamps\n", ifr.ifr_name);