簡體   English   中英

Linux套接字的Linux時間戳

[英]Linux timestamping for TCP sockets

我正在一個項目中工作,以便從文件Linux時間戳記中提到的接收和傳輸來自NIC for TCP套接字的時間戳 但所有文檔和測試編碼都是針對UDP套接字完成的。 但我正在獲取NIC的傳輸時間戳,而不是獲取接收TCP數據包的時間戳。

我的界面支持以下時間戳

    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)

我使用ioctl(sockfd, SIOCSHWTSTAMP, &net_device);bind()之后啟用了NIC的時間戳ioctl(sockfd, SIOCSHWTSTAMP, &net_device);

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

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

但我總是得到以下消息,

received short ancillary data (0/256)

我沒有從recvmsg()獲取輔助數據,我想知道linux是否支持TCP接收NIC的硬件時間戳。

Linux時間戳不支持TCP的接收硬件或軟件時間戳。 關於linux時間戳的文檔僅提到“數據包”方面的內容。 這是指UDP,用於在NIC中實現PTP硬件時鍾的同步,查看PTP守護進程的代碼和linux ptp以獲得更多的理解。 Linux 3.18僅支持傳輸中的時間戳。 所以基本上你無法在接收器中實現TCP的linux時間戳。

我能夠使用最近的內核版本(4.18)將SO_TIMESTAMPING與TCP套接字一起使用。 這適用於TX和RX時間戳。 我仍在努力,但如果你願意,我可以嘗試寫一個最小的概念證明。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM