gpt4 book ai didi

c - 如何精确或近似地测量接收数据包的延迟

转载 作者:行者123 更新时间:2023-12-05 03:35:22 25 4
gpt4 key购买 nike

我正在尝试测量数据包进入 Rx 缓冲区并复制到应用程序内存时的延迟。我正在用这段代码测量它:

struct timespec start, end;

clock_gettime(CLOCK_REALTIME, &start);
recvfrom(sock, msg, msg_len, 0, &client, &client_addrlen);
clock_gettime(CLOCK_REALTIME, &end);

我知道这不能精确测量延迟。但是,我可以通过接收许多数据包、测量每个数据包并计算它们来计算平均延迟。有什么方法可以更精确地测量延迟吗? (例如,latency =(recvfrom() 完成的时间)-(NIC 从中接收数据包的时间))

对于设备和设备驱动程序,我使用的是 Mellanox connectx-3 和 mlx4_en。

最佳答案

我能够通过 recvmsg() 获得几乎精确的数字。

引用

代码

我正在重现第一个链接中的代码。此代码不是准备运行的,而只是工作代码中的一个片段。

static struct timespec handle_time(struct msghdr *msg) {
struct cmsghdr *cmsg = CMSG_FIRSTHDR(msg);
struct scm_timestamping *ts = (struct scm_timestamping *)CMSG_DATA(cmsg);
return ts->ts[0];
}

...
char ctrl[64];
char *msg = malloc(64);

int val = SOF_TIMESTAMPING_RX_HARDWARE | SOF_TIMESTAMPING_RX_SOFTWARE
| SOF_TIMESTAMPING_SOFTWARE | SOF_TIMESTAMPING_RAW_HARDWARE;

setsockopt(sock_fd, SOL_SOCKET, SO_TIMESTAMPING, &val, sizeof(val));

// user buffer
struct iovec iov = {
.iov_base = msg,
.iov_len = msg_len,
};

// ancillary message header
struct msghdr m = {
.msg_name = &client_addr, // struct sockaddr_in
.msg_namelen = client_addrlen, // socklen_t
.msg_iov = &iov,
.msg_iovlen = 1,
.msg_control = &ctrl,
.msg_controllen = sizeof(ctrl),
};

while (1) {
memset(msg, 0, msg_len);
num_received = recvmsg(sock_fd, &m, 0);
start = handle_time(&m);
clock_gettime(CLOCK_REALTIME, &end);

if (verbose) {
double elapsed_time = time_diff(start, end) / 1000;
total_elapsed += elapsed_time;
count++;
printf("%f us %f us\n", elapsed_time, total_elapsed / count);
}

if (sendto(sock_fd, msg, msg_len, 0, (struct sockaddr *) &client_addr, client_addrlen) < 0) {
perror("\nMessage Send Failed\n");
fprintf(stderr, "Value of errno: %d\n", errno);
}
}

关键点是使用setsockopt()recvmsg()。关键机制是当你为某个套接字FD设置一个选项时,内核会根据时间戳标志设置一个时间戳。在你设置它们之后,如果你收到一个带有 struct msghdr 的消息,内核将以 SW 或 HW 的方式审计时间戳。当您查看数据时,您将能够获得 3 个时间戳。这些信息可以解释如下:

The structure can return up to three timestamps. This is a legacyfeature. At least one field is non-zero at any time. Most timestampsare passed in ts[0]. Hardware timestamps are passed in ts[2]. ts[1] used to hold hardware timestamps converted to system time. Instead, expose the hardware clock device on the NIC directly as a HW PTP clock source, to allow time conversion in userspace and optionally synchronize system time with a userspace PTP stack such as linuxptp. For the PTP clock API, see Documentation/driver-api/ptp.rst.

有关详细信息,请参阅 Documentation/networking/timestamping.txt 中的 2.1。

如果你想看到硬件时间戳,那么你需要有一个特定的硬件(引用 this comment )并用 ioctl() 改变它的特性。但是,有一个名为 linuxptp 的便捷工具可以完成这项工作。

关于c - 如何精确或近似地测量接收数据包的延迟,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69888516/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com