2017-05-26 3 views
4

引用形式は、このonline kernel docLinuxのTCPソケットのタイムスタンプオプション

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

}

何のタイムスタンプはここに利用できない理由を任意のアイデア?ありがとう

ソリューション 太陽フレアNICでonloadを使用してハードウェアタイムスタンプとともにソフトウェアタイムスタンプを取得できました。 ソフトウェアのタイムスタンプだけを取得する方法はまだ分かりません。

+0

私は 'SO_TIMESTAMPING'が持つ' cmsg_type'に合わせて、正しい値であることを疑います。 – Igor

+0

申し訳ありませんが私はあなたのポイントを取得していません。あなたはより詳細になりますか? – FaceBro

+0

まだ心配していません。他にも問題があります。すべての警告をオンにしてコードをコンパイルし、ビルド出力とプログラムの出力を共有します。 – Igor

答えて

2

最後のコメントであなたが与えたリンク、次のように述べています

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 
+0

カーネル文書の最後に記載したコメントは見つかりません。そして、実際には文書を何度も読んで、セクション1.4で説明したようにTCPタイムスタンプがサポートされています。 – FaceBro

+0

私は上記のリンクの最後にコメントがあるとは思わない。上記のコメントの場所を教えてください。 セクション1.4では、TCPのタイムスタンプがサポートされていることを明確に述べています。 – FaceBro

+0

この回答は、別のSOスレッドから来ています。https://stackoverflow.com/questions/36041740/obtain-packet-timestamp-through-ioctl-call-on-socket-file-descriptor そして私はこれらのコメントの権威を非常に疑っています。より多くの権限が必要です。 – FaceBro