时间戳传出数据包

时间:2012-07-31 00:12:53

标签: c linux timestamp raw-sockets

我正在尝试获取传出数据包的准确时间戳(使用原始套接字发送)。根据{{​​3}},“对于发送时间戳,传出的数据包将循环回到套接字的错误队列,并附带发送时间戳。可以使用recvmsg(flags = MSG_ERRQUEUE)接收。”。

不幸的是,recvmsg在原始套接字上调用时始终返回-1(使用socket(PF_INET, SOCK_RAW, IPPROTO_RAW)创建,SO_TIMESTAMP设置为1 {{1} }})。我究竟做错了什么?有没有更好的方法来获得传出数据包的准确时间戳?

附录(资料):

我还尝试从通过UDP套接字发送的数据包中获取时间戳(下面的源代码),setsockopt返回recvmsg:错误是“资源暂时不可用”(-1

附录(源代码):

EAGAIN

4 个答案:

答案 0 :(得分:8)

查看Linux内核源代码,我发现负责将包含数据包时间戳的消息放入错误队列的函数是skb_tx_timestamp。这个函数应该由NIC驱动程序调用,不幸的是,e1000驱动程序没有调用它(硬件时间戳有类似的功能,但这显然取决于支持它的NIC驱动程序)。

根据去年9月的this NetDev discussion,“没有驱动程序调用skb_tx_timestamp()”和“你需要调整你的网卡驱动程序才能使用这个TX时间戳”。在skb_tx_timestamp上向e1000_xmit_frame添加了对e1000_main.c的调用后,我能够获取传出数据包的时间戳(通过UDP套接字)。但是我无法获得RAW套接字上的传出数据包的时间戳(我仍然得到EAGAIN)。

答案 1 :(得分:5)

很难知道你做错了什么,因为我们看不到你的代码。

然而: 文档说SO_TIMESTAMP用于传入数据包,而SO_TIMESTAMPING用于传出数据包。

内核文档包含一个完整的示例,您可以将其作为基础 - 尽管它使用UDP,但您应该能够将其调整为使用RAW套接字。 请参阅linux内核Documentation/networking/timestamping/timestamping.c

编辑:似乎普遍支持传输时间戳,请参阅例如here。即使在今天,只有少数的nic驱动程序实现了软件支持,还有一些具有硬件支持。

答案 2 :(得分:2)

仅在当前内核代码中为SOCK_DGRAM套接字调用sock_tx_timestamp。

BTW,文档/ networking / networking / timestamping / timestamping.c非常准确。

SO_TIMESTAMP / SO_TIMESTAMPNS / SO_TIMESTAMPING / SIOCGSTAMP / SIOCGSTAMPNS类似。其中任何一个都可以使应用程序获取收到的数据包的时间戳。

使用SOF_TIMESTAMPING_TX_SOFTWARE,上述任何一个标志也将为应用程序提供MSG_ERRQUEUE中的CMSG,指示发送数据包的时间戳。

但是SOF_TIMESTAMPING_RX_SOFTWARE根本没用。它甚至不能用于禁用报告接收数据包的时间戳。

答案 3 :(得分:0)

我认为,你必须提到时间戳标志为

int timestamp_flags |= SOF_TIMESTAMPING_TX_SOFTWARE;
timestamp_flags |= SOF_TIMESTAMPING_SOFTWARE;

在从msg队列错误中获取数据之前,还必须检查所有系统调用的strerror。这将帮助您摆脱EAGAIN消息。