时间戳输出数据包

我正在尝试获取传出数据包的准确时间戳(使用原始套接字发送)。根据Linux/Documentation/networking/timestamping.txt,“对于发送时间戳,传出的数据包将被附加到发送时间戳上并循环回套接字的错误队列。可以使用recvmsg(flags

= MSG_ERRQUEUE)进行接收。”

不幸的是,在原始套接字上调用时recvmsg总是返回-1(用socket(PF_INET, SOCK_RAW,

IPPROTO_RAW)SO_TIMESTAMP设置为1with

来创建setsockopt)。我究竟做错了什么?是否有更好的方法来获取传出数据包的准确时间戳?

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

#include <arpa/inet.h>

#include <linux/net_tstamp.h>

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <sys/types.h>

#include <sys/socket.h>

void die(char* s)

{

perror(s);

exit(1);

}

int main(int argc, char* argv[])

{

char* destination_ip = "10.0.0.1";

int destination_port = 1234;

int sock;

if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {

die("socket()");

}

int timestamp_flags = SOF_TIMESTAMPING_TX_SOFTWARE;

if (setsockopt(sock, SOL_SOCKET, SO_TIMESTAMPING, &timestamp_flags, sizeof(timestamp_flags)) < 0) {

die("setsockopt()");

}

struct sockaddr_in si_server;

memset(&si_server, 0, sizeof(si_server));

si_server.sin_family = AF_INET;

si_server.sin_port = htons(destination_port);

if (inet_aton(destination_ip, &si_server.sin_addr) == 0) {

die("inet_aton()");

}

const int buffer_len = 256;

char buffer[buffer_len];

const int n_packets = 10;

for (int i = 0; i < n_packets; ++i) {

sprintf(buffer, "Packet %d", i);

if (sendto(sock, buffer, buffer_len, 0, (const sockaddr*) &si_server, sizeof(si_server)) < 0) {

die("sendto()");

}

// Obtain the sent packet timestamp.

char data[256];

struct msghdr msg;

struct iovec entry;

struct sockaddr_in from_addr;

struct {

struct cmsghdr cm;

char control[512];

} control;

int res;

memset(&msg, 0, sizeof(msg));

msg.msg_iov = &entry;

msg.msg_iovlen = 1;

entry.iov_base = data;

entry.iov_len = sizeof(data);

msg.msg_name = (caddr_t)&from_addr;

msg.msg_namelen = sizeof(from_addr);

msg.msg_control = &control;

msg.msg_controllen = sizeof(control);

if (recvmsg(sock, &msg, MSG_ERRQUEUE) < 0) {

die("recvmsg()");

}

}

return 0;

}

回答:

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

根据去年9月的NetDev讨论,“没有驱动程序调用skb_tx_timestamp()”和“您需要调整NIC驱动程序以使用此TX时间戳记”。添加skb_tx_timestampe1000_xmit_frameon

的调用之后e1000_main.c,我能够(通过UDP套接字)获取传出数据包的时间戳。但是,我无法获得RAW套接字上传出数据包的时间戳(我仍然得到EAGAIN)。

以上是 时间戳输出数据包 的全部内容, 来源链接: utcz.com/qa/428161.html

回到顶部