I'm receiving packets via recvmsg()
and expecting 3 timestamps:
- Software
- Hardware (NIC) converted to software
- Hardware (NIC)
I see the first and third timestamps but I get zeros for the second.
I'm basing my code on this Onload example:
https://github.com/Xilinx-CNS/onload/blob/master/src/tests/onload/hwtimestamping/rx_timestamping.c
I export the environment variable for timestamping:
export EF_RX_TIMESTAMPING=1
I preload the onload library.
I set the socket options:
int enable = SOF_TIMESTAMPING_RX_HARDWARE | SOF_TIMESTAMPING_RAW_HARDWARE |
SOF_TIMESTAMPING_SYS_HARDWARE | SOF_TIMESTAMPING_SOFTWARE;
assert(setsockopt(sock, SOL_SOCKET, SO_TIMESTAMPING, &enable, sizeof(int)) == 0);
I create the message header and use recvmsg()
to retrieve packets:
while(_running)
{
struct iovec iov;
char control[1024];
struct msghdr msg;
iov.iov_base = buffer;
iov.iov_len = 2048;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_namelen = sizeof(struct sockaddr_in);
msg.msg_control = control;
msg.msg_controllen = 1024;
int num bytes = recvmsg(sock, &msg, 0);
handle_time(&msg);
LOG("Got packet");
}
and I read the timestamps:
static void handle_time(struct msghdr* msg)
{
struct timespec* ts = NULL;
struct cmsghdr* cmsg;
for( cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg,cmsg) ) {
if( cmsg->cmsg_level != SOL_SOCKET )
continue;
switch( cmsg->cmsg_type ) {
case SO_TIMESTAMPNS:
ts = (struct timespec*) CMSG_DATA(cmsg);
break;
case SO_TIMESTAMPING:
ts = (struct timespec*) CMSG_DATA(cmsg);
break;
default:
/* Ignore other cmsg options */
break;
}
}
print_time(ts);
}
static void print_time(struct timespec* ts)
{
if( ts != NULL ) {
/* Hardware timestamping provides three timestamps -
* system (software)
* transformed (hw converted to sw)
* raw (hardware)
* in that order - though depending on socket option, you may have 0 in
* some of them.
*/
printf("timestamps " TIME_FMT TIME_FMT TIME_FMT "\n",
(uint64_t)ts[0].tv_sec, (uint64_t)ts[0].tv_nsec,
(uint64_t)ts[1].tv_sec, (uint64_t)ts[1].tv_nsec,
(uint64_t)ts[2].tv_sec, (uint64_t)ts[2].tv_nsec );
} else
{
printf( "no timestamp\n" );
}
}
Is there anything missing to receive the second timestamp?