【问题标题】:Linux TCP socket timestamping optionLinux TCP 套接字时间戳选项
【发布时间】:2017-10-27 07:27:12
【问题描述】:

引用此online kernel doc

  • SO_TIMESTAMPING 在接收、传输或两者上生成时间戳。支持 多个时间戳来源,包括硬件。支持生成 套接字的时间戳。

Linux 支持 TCP 时间戳,我尝试编写一些演示代码来获取 TCP 数据包的任何时间戳。

服务器代码如下:

//Bind
if( bind(socket_desc,(struct sockaddr *)&server , sizeof(server)) < 0)
{
    perror("bind failed. Error");
    return 1;
}
puts("bind done");

//Listen
listen(socket_desc , 3);

//Accept and incoming connection
puts("Waiting for incoming connections...");
int c = sizeof(struct sockaddr_in);

client_sock = accept(socket_desc, (struct sockaddr *)&client, (socklen_t*)&c);
if (client_sock < 0)
{
    perror("accept failed");
    return 1;
}

// Note: I am trying to get software timestamp only here..
int oval = SOF_TIMESTAMPING_RX_SOFTWARE | SOF_TIMESTAMPING_SOFTWARE;
int olen = sizeof( oval );
if ( setsockopt( client_sock, SOL_SOCKET, SO_TIMESTAMPING, &oval, olen ) < 0 )
    { perror( "setsockopt TIMESTAMP"); exit(1); }

puts("Connection accepted");

char    buf[] = "----------------------------------------";
int len = strlen( buf );

struct iovec    myiov[1] = { {buf, len } };

unsigned char   cbuf[ 40 ] = { 0 };
int     clen = sizeof( cbuf ); 

struct msghdr   mymsghdr = { 0 };
mymsghdr.msg_name   = NULL;
mymsghdr.msg_namelen    = 0;
mymsghdr.msg_iov    = myiov;
mymsghdr.msg_iovlen = 1;
mymsghdr.msg_control    = cbuf;
mymsghdr.msg_controllen = clen;
mymsghdr.msg_flags  = 0;

int read_size = recvmsg( client_sock, &mymsghdr, 0);

if(read_size == 0)
{
  puts("Client disconnected");
  fflush(stdout);
}
else if(read_size == -1)
{
  perror("recv failed");
}
else
{
  struct msghdr *msgp = &mymsghdr;
  printf("msg received: %s \n",(char*)msgp->msg_iov[0].iov_base);// This line is successfully hit.
  // Additional info: print msgp->msg_controllen inside gdb is 0.
  struct cmsghdr    *cmsg;
  for ( cmsg = CMSG_FIRSTHDR( msgp );
      cmsg != NULL;
      cmsg = CMSG_NXTHDR( msgp, cmsg ) )
  {
    printf("Time GOT!\n"); // <-- This line is not hit.
    if (( cmsg->cmsg_level == SOL_SOCKET )
        &&( cmsg->cmsg_type == SO_TIMESTAMPING ))
      printf("TIME GOT2\n");// <-- of course , this line is not hit
  } 

}

任何想法为什么这里没有可用的时间戳?谢谢

解决方案 我可以使用带有 solarflare NIC 的 onload 来获取软件时间戳和硬件时间戳。 仍然不知道如何单独获取软件时间戳。

【问题讨论】:

  • 我怀疑SO_TIMESTAMPING 是匹配cmsg_type 的正确值。
  • 对不起,我没有明白你的意思。能详细点吗?
  • 没关系。还有其他问题。编译您的代码并打开所有警告并共享构建输出以及程序的输出。
  • 这只是整个服务器代码的一部分,不过你可以不费吹灰之力地构建它。
  • @Igor 啊,我明白你的第一条评论的意思。但问题是一开始就没有匹配 cmsg_type 的 cmsg,没有返回控制 msg。

标签: sockets tcp linux-kernel timestamp setsockopt


【解决方案1】:

你在最后的 cmets 中给出的链接说:

I've discovered why it doesn't work. SIOCGSTAMP only works for UDP
packets or RAW sockets, but does not work for TCP. – Gio Mar 17 '16 at 9:331    

it doesn't make sense to ask for timestamps for TCP, because there's
no direct correlation between arriving packets and data becoming 
available. If you really want timestamps for TCP you'll have to use 
RAW sockets and implement your own TCP stack (or use a userspace TCP
library). – ecatmur Jul 4 '16 at 10:39 

【讨论】:

  • 我没有找到你在内核文档末尾提到的cmets。而且我实际上已经多次阅读文档,支持TCP时间戳,如1.4节所述。
  • 我认为上面链接的末尾没有 cmets。你能告诉在哪里可以找到上面的评论吗?第 1.4 节明确指出支持 TCP 时间戳记。
  • 这个答案来自另一个 SO 线程stackoverflow.com/questions/36041740/… 我非常怀疑这些 cmets 的权威性。需要更多权限。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-10-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-10
  • 1970-01-01
相关资源
最近更新 更多