简体   繁体   English

Linux套接字的Linux时间戳

[英]Linux timestamping for TCP sockets

I am working in a project to get the receive and transmit time stamping from the NIC for TCP socket as mentioned in the document Linux timestamping . 我正在一个项目中工作,以便从文件Linux时间戳记中提到的接收和传输来自NIC for TCP套接字的时间戳 But all the documentation and test coding are done for UDP sockets. 但所有文档和测试编码都是针对UDP套接字完成的。 But I am getting the Transmit timestamping for the NIC and not getting the time stamping for the receive TCP packets. 但我正在获取NIC的传输时间戳,而不是获取接收TCP数据包的时间戳。

My Interface support the following time stamps 我的界面支持以下时间戳

    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)

I enable the timestamping for NIC after bind() using ioctl(sockfd, SIOCSHWTSTAMP, &net_device); 我使用ioctl(sockfd, SIOCSHWTSTAMP, &net_device);bind()之后启用了NIC的时间戳ioctl(sockfd, SIOCSHWTSTAMP, &net_device); with

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;

then enable the time stamping in the NIC through setsockopt() 然后通过setsockopt()启用NIC中的时间戳

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");
}

After the listen() and accept(), I do select() , and check whether fd is rfds then call the recvmsg() with following options 在listen()和accept()之后,我执行select() ,并检查fd是否为rfds然后使用以下选项调用recvmsg()

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;
}

But I am always getting the following message, 但我总是得到以下消息,

received short ancillary data (0/256)

I am not getting the ancillary data from the recvmsg() , I like to know whether linux support TCP receive hardware time stamping for the NIC. 我没有从recvmsg()获取辅助数据,我想知道linux是否支持TCP接收NIC的硬件时间戳。

Linux timestamping doesn't support the receive hardware or software timestamping for TCP. Linux时间戳不支持TCP的接收硬件或软件时间戳。 Documentation of linux timestamping mentioned only regarding the in terms of "packets". 关于linux时间戳的文档仅提到“数据包”方面的内容。 This refers UDP, which is used for the implementation of synchronization of PTP hardware clock in NIC, look the code of PTP daemon and linux ptp for more understanding. 这是指UDP,用于在NIC中实现PTP硬件时钟的同步,查看PTP守护进程的代码和linux ptp以获得更多的理解。 Linux 3.18 support only the timestamping in transmit. Linux 3.18仅支持传输中的时间戳。 So basically you can't achieve the linux timestamping for TCP in receiver. 所以基本上你无法在接收器中实现TCP的linux时间戳。

I was able to use SO_TIMESTAMPING with a TCP socket using a recent kernel version (4.18). 我能够使用最近的内核版本(4.18)将SO_TIMESTAMPING与TCP套接字一起使用。 This works for both TX and RX timestamps. 这适用于TX和RX时间戳。 I am still working on this but I can try to write a minimal proof of concept if you want. 我仍在努力,但如果你愿意,我可以尝试写一个最小的概念证明。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM