首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Linux套接字硬件时间戳

Linux套接字硬件时间戳
EN

Stack Overflow用户
提问于 2019-03-05 01:56:16
回答 1查看 1K关注 0票数 1

我正在做一个研究网络同步的项目。因为我想获得最佳性能,所以我尝试将软件时间戳结果与硬件时间戳结果进行比较。

我关注了之前评论的问题:Linux kernel UDP reception timestamp,但经过几次测试后,我在尝试获取硬件接收时间戳时遇到了一些问题。

我的场景由两个设备组成,一台PC和一块Gateworks Ventana板,这两个设备都应该等待数据包在其网络中广播,并对其接收时间进行时间戳,我尝试了此代码(某些部分已被省略):

代码语言:javascript
复制
int rc=1;
int flags;

flags   = SOF_TIMESTAMPING_RX_HARDWARE
        | SOF_TIMESTAMPING_RAW_HARDWARE;
rc = setsockopt(sock, SOL_SOCKET,SO_TIMESTAMPING, &flags, sizeof(flags));

rc = bind(sock, (struct sockaddr *) &serv_addr, sizeof(serv_addr));

struct msghdr msg;
struct iovec iov;
char pktbuf[2048];

char ctrl[CMSG_SPACE(sizeof(struct timespec))];
struct cmsghdr *cmsg = (struct cmsghdr *) &ctrl;

msg.msg_control = (char *) ctrl;
msg.msg_controllen = sizeof(ctrl);

msg.msg_name = &serv_addr;
msg.msg_namelen = sizeof(serv_addr);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
iov.iov_base = pktbuf;
iov.iov_len = sizeof(pktbuf);

//struct timeval time_kernel, time_user;
//int timediff = 0;

FILE *f = fopen("server.csv", "w");
if (f == NULL) {
    error("Error opening file!\n");
    exit(1);
}
fprintf(f, "Time\n");

struct timespec ts;
int level, type;
int i;
for (i = 0; i < 10; i++) {

    rc = recvmsg(sock, &msg, 0);


    for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; cmsg = CMSG_NXTHDR(&msg, cmsg))
    {
        level = cmsg->cmsg_level;
        type  = cmsg->cmsg_type;
        if (SOL_SOCKET == level && SO_TIMESTAMPING == type) {
            //ts = (struct timespec *) CMSG_DATA(cmsg);
            memcpy(&ts, CMSG_DATA(cmsg), sizeof(ts));
            printf("HW TIMESTAMP %ld.%09ld\n", (long)ts.tv_sec, (long)ts.tv_nsec);
           }
    }

}

printf("COMPLETED\n");
fclose(f);
close(sock);
return 0;
}

在这两个设备上,我在收到数据包后得到的输出:

代码语言:javascript
复制
HW TIMESTAMP 0.000000000

另一方面,如果使用相同的代码,我的标志是:

代码语言:javascript
复制
flags   = SOF_TIMESTAMPING_RX_HARDWARE
        | SOF_TIMESTAMPING_RX_SOFTWARE
        | SOF_TIMESTAMPING_SOFTWARE;

我得到了适当的时间戳:

代码语言:javascript
复制
HW TIMESTAMP 1551721801.970270543

然而,它们似乎是软件时间戳的。处理收到数据包的硬件时间戳的正确解决方案/方法是什么?

EN

回答 1

Stack Overflow用户

发布于 2021-01-14 03:52:08

首先,使用ethtool -T "your NIC"确保您的硬件支持硬件时间戳功能。

您需要显式地告诉Linux启用NIC的硬件时间戳功能。为了达到这个目的,你需要有一个ioctl()调用。

你需要做的就是用SIOCSHWTSTAMP来调用它,这是一个设备请求码,用来指示你想要处理的设备以及你想要做的事情。例如,有一个名为CDROMSTOP的代码来停止cdrom驱动器。您还需要使用ifreq结构来配置NIC。

你需要这样的东西:

代码语言:javascript
复制
struct ifreq ifconfig;
strncpy(config.ifr_name, "your NIC name", sizeof(ifconfig.ifr_name));
ioctl("your file descriptor" , SIOCSHWTSTAMP, &ifconfig);

这里有一些你可以查阅的页面:ioctl manual pageifreq manual pageRead part 3

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54988917

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档