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

TCP套接字的Linux时间戳
EN

Stack Overflow用户
提问于 2015-02-26 12:36:26
回答 2查看 5.2K关注 0票数 12

我正在一个项目中工作,以从Linux timestamping获得接收和传输时间戳,如文档Linux timestamping中提到的那样。但是所有的文档和测试编码都是针对UDP套接字完成的。但是我得到的是NIC的传输时间戳,而不是接收TCP数据包的时间戳。

我的接口支持以下时间戳

代码语言:javascript
复制
    Time stamping parameters for enp4s0:
Capabilities:
    hardware-transmit     (SOF_TIMESTAMPING_TX_HARDWARE)
    software-transmit     (SOF_TIMESTAMPING_TX_SOFTWARE)
    hardware-receive      (SOF_TIMESTAMPING_RX_HARDWARE)
    software-receive      (SOF_TIMESTAMPING_RX_SOFTWARE)
    software-system-clock (SOF_TIMESTAMPING_SOFTWARE)
    hardware-raw-clock    (SOF_TIMESTAMPING_RAW_HARDWARE)
PTP Hardware Clock: 3
Hardware Transmit Timestamp Modes:
    off                   (HWTSTAMP_TX_OFF)
    on                    (HWTSTAMP_TX_ON)
Hardware Receive Filter Modes:
    none                  (HWTSTAMP_FILTER_NONE)
    all                   (HWTSTAMP_FILTER_ALL)

我在bind()之后启用NIC的时间戳,使用ioctl(sockfd, SIOCSHWTSTAMP, &net_device);

代码语言:javascript
复制
memset(&net_device, 0, sizeof(net_device));
strncpy(net_device.ifr_name, interface_name, sizeof(net_device.ifr_name));
net_device.ifr_data = (void *)&tstconfig;
memset(&tstconfig, 0, sizeof(tstconfig));

tstconfig.tx_type = HWTSTAMP_TX_OFF;
tstconfig.rx_filter = HWTSTAMP_FILTER_ALL;

然后通过setsockopt()在网卡中启用时间戳。

代码语言:javascript
复制
int opt= 0;
opt |= SOF_TIMESTAMPING_RX_HARDWARE;
opt |= SOF_TIMESTAMPING_RAW_HARDWARE;
if (setsockopt(sockfd, SOL_SOCKET, SO_TIMESTAMPING,
           (char *)&opt, sizeof(opt))) {
    error(1, 0, "setsockopt timestamping");
    bail("setsockopt SO_TIMESTAMPING");
}

在listen()和accept()之后,我执行select(),并检查fd是否是rfds,然后使用以下选项调用recvmsg()

代码语言:javascript
复制
int rc;
struct iovec vec[1];
struct msghdr msg;
char data[8192];
struct cmsghdr *cmsg;

union {
    struct cmsghdr cm;
    char control[256];
} cmsg_un;

vec[0].iov_base = data;
vec[0].iov_len = sizeof(data);

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

msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_iov = vec;
msg.msg_iovlen = 1;
msg.msg_control = cmsg_un.control;
msg.msg_controllen = sizeof(cmsg_un.control);   
rc = recvmsg(flow->fd, &msg, 0);

printf("tried reading %d bytes, got %d", bytes, rc);
if (msg.msg_flags & MSG_TRUNC) {
    printf("received truncated message\n");
    return 0;
}

if (msg.msg_flags & MSG_CTRUNC) {
    printf("received truncated ancillary data\n");
    return 0;
}

if (msg.msg_controllen <= 0) {
    printf("`received short ancillary data (%ld/%ld)`\n",
            (long)msg.msg_controllen, (long)sizeof(cmsg_un.control));
    return 0;
}

但我总是收到以下信息,

代码语言:javascript
复制
received short ancillary data (0/256)

我没有从recvmsg()获得辅助数据,我想知道linux是否收到NIC的硬件时间戳。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-02-27 16:40:40

Linux时间戳不支持TCP的接收硬件或软件时间戳。linux时间戳的文档只在“数据包”方面提到。这是指UDP,它用于实现NIC中PTP硬件时钟的同步,请参阅PTP守护进程和linux的代码,以获得更多的了解。Linux 3.18只支持传输中的时间戳。因此,基本上您不能在接收端实现TCP的linux时间戳。

票数 3
EN

Stack Overflow用户

发布于 2018-10-24 08:02:19

我能够使用最近的内核版本(4.18)使用带有TCP套接字的SO_TIMESTAMPING。这适用于TX和RX时间戳。我仍在研究这个问题,但如果你愿意的话,我可以尝试写一个概念的最小证明。

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

https://stackoverflow.com/questions/28742665

复制
相关文章

相似问题

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