Linux内核UDP接收时间戳 [英] Linux kernel UDP reception timestamp

查看:1038
本文介绍了Linux内核UDP接收时间戳的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在阅读Linux内核的网络时间戳记文档还有一些我不清楚的东西.

I've been reading the network timestamping documentation of linux kernel and there is something that it's not clear to me.

SO_TIMESTAMPNS提供的时间戳记在哪里生成?在硬件还是内核中?如果是这样,它会在引发新数据包的中断时立即发芽吗?

Where is the timestamp provided by SO_TIMESTAMPNS generated? In hardware or in the kernel? If so it is gerated as soon as an interrupt for a new packet is raised?

SO_TIMESTAMPING还应该允许生成硬件时间戳.所有网卡都支持吗? SO_TIMESTAMPING与选项SOF_TIMESTAMPING_RX_HARDWARE and SO_TIMESTAMPNS如何配合? 在那种情况下,硬件时间戳是指系统时钟还是NIC时钟?在第二种情况下,如何检索NIC时钟以计算经过时间?

SO_TIMESTAMPING should also allow the generation of hardware timestamps. Is this supported by all the NICs? How does SO_TIMESTAMPING with options SOF_TIMESTAMPING_RX_HARDWARE and SO_TIMESTAMPNS? In that case is the hardware timestamp referring to the system clock or to the NIC clock? In the second case how to retrieve the NIC clock to compute elapsed time?

推荐答案

用于软件时间戳的套接字属性为SO_TIMESTAMPNS.此套接字属性从系统时钟返回时间.它不是在硬件中生成的,而是在软件中处理中断时系统时间的快照.我们可以使用不属于套接字有效负载的辅助数据(CMSG)来访问此时间戳,方法是:

The socket attribute used for software timestamping is, SO_TIMESTAMPNS. This socket attribute returns the time from the system clock. It is not generated in the hardware, rather it is the snapshot of the system time when the interrupt is handled in the software. We can access this timestamp through the ancillary data (CMSG) that is not part of the socket payload, using:

int level, type;
struct cmsghdr *cm;
struct timespec *ts = NULL;
for (cm = CMSG_FIRSTHDR(&msg); cm != NULL; cm = CMSG_NXTHDR(&msg, cm))
{
    level = cm->cmsg_level;
    type  = cm->cmsg_type;
    if (SOL_SOCKET == level && SO_TIMESTAMPNS == type) {
        ts = (struct timespec *) CMSG_DATA(cm);
        printf("SW TIMESTAMP %ld.%09ld\n", (long)ts[0].tv_sec, (long)ts[0].tv_nsec);
    }
}

SO_TIMESTAMPING套接字选项提供了许多不同的标志,其中一些是

The SO_TIMESTAMPING socket option offers many different flags, some of them are,

SOF_TIMESTAMPING_TX_HARDWARE // Transmit timestamp generated in hardware by NIC clock
SOF_TIMESTAMPING_RX_HARDWARE // Receive  timestamp generated in hardware by NIC clock
SOF_TIMESTAMPING_TX_SOFTWARE // Transmit timestamp generated in kernel driver by NIC clock
SOF_TIMESTAMPING_RX_SOFTWARE // Receive  timestamp generated in kernel driver by NIC clock

并非所有网络接口卡(NIC)都支持此套接字选项.当前,许多以太网NIC支持SO_TIMESTAMPING.为了找到特定的接口驱动程序是否支持SO_TIMESTAMPING,请使用:

This socket option is not supported by all Network Interface Cards (NICs). Currently many ethernet NICs support SO_TIMESTAMPING. In order to find if a particular interface driver supports SO_TIMESTAMPING, use:

ethtool -T ethX // where X corresponds to your particular interface

这将返回ethX支持的所有套接字属性以进行时间戳记.

This will return all the socket attributes ethX supports for timestamping.

要使用特定NIC提供的硬件时间戳功能,请使用以下代码:

To use hardware timestamping feature provided by a particular NIC, use the code:

int flags;
flags   = SOF_TIMESTAMPING_TX_HARDWARE
            | SOF_TIMESTAMPING_RX_HARDWARE 
            | SOF_TIMESTAMPING_TX_SOFTWARE
            | SOF_TIMESTAMPING_RX_SOFTWARE 
            | SOF_TIMESTAMPING_RAW_HARDWARE;
    if (setsockopt(sd, SOL_SOCKET, SO_TIMESTAMPING, &flags, sizeof(flags)) < 0)
        printf("ERROR: setsockopt SO_TIMESTAMPING\n");

int level, type;
struct cmsghdr *cm;
struct timespec *ts = NULL;
for (cm = CMSG_FIRSTHDR(&msg); cm != NULL; cm = CMSG_NXTHDR(&msg, cm))
{
     if (SOL_SOCKET == level && SO_TIMESTAMPING == type) {
        ts = (struct timespec *) CMSG_DATA(cm);
        printf("HW TIMESTAMP %ld.%09ld\n", (long)ts[2].tv_sec, (long)ts[2].tv_nsec);
      }
}

这篇关于Linux内核UDP接收时间戳的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆