Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Obtain packet timestamp through ioctl call on socket file descriptor

I'm working on a system running embedded linux. I'm trying to obtain the packet timestamp from a stream I'm receiving on a socket.

After creating the socket, I do the following:

if (fd != -1) {
    int enabled = 1;
    setsockopt(fd, SOL_SOCKET, SO_TIMESTAMP, &enabled, sizeof(enabled);
}

After that I bind the socket, the socket is of type SOCK_STREAM. I successfully receive data on the socket, by calling the function recv(fd, buf, size, 0). Now in order to obtain the timestamp of the received data, I'm currently trying the following:

ret = recv(fd, buf, size, 0);
if (ret > 0) {
    struct timeval tv_ioctl;
    tv_ioctl.tv_sec = 0;
    tv_ioctl.tv_usec = 0;
    int error = ioctl(fd, SO_TIMESTAMP, &tv_ioctl);
    printf("%ld.%ld - error = %d", (long int)tv_ioctl.tv_sec, 
            (long int)tv_ioctl.tv_usec, error);
}

The output of the printf statement is always the following:

0.0 error = -1

The error = -1 indicates that the ioctl call has failed. I've performed a test with getsockopt to check if the SO_TIMESTAMP option is set, getsockopt returns 0 for the option SO_TIMESTAMP so it seems correctly set. I'm a bit lost here, how can I further investigate why the ioctl call seems to be failing?

like image 907
Gio Avatar asked Mar 16 '16 16:03

Gio


1 Answers

The ioctl to retrieve the most recent timestamp on the socket is SIOCGSTAMP; SO_TIMESTAMP is a socket option, not an ioctl. Your code should read:

int error = ioctl(fd, SIOCGSTAMP, &tv_ioctl);
                      ^^^^^^^^^^

The alternate method to retrieve timestamps is to change recv to recvmmsg and extract the timestamp from the ancillary data. This is more efficient as it involves fewer system calls (Socket reading and timestamps); the ioctl is simpler, though.

Note that SIOCGSTAMP and SO_TIMESTAMP are mutually exclusive - if you're going to use SIOCGSTAMP you should disable SO_TIMESTAMP (with enabled = 0). This is because SO_TIMESTAMP directs the kernel to make the timestamp available via recvmmsg ancillary data instead of via SIOCGSTAMP.

like image 169
ecatmur Avatar answered Nov 06 '22 16:11

ecatmur