2016-03-16 24 views
6

Sto lavorando a un sistema che esegue Linux incorporato. Sto cercando di ottenere il timestamp del pacchetto da un flusso che sto ricevendo su un socket.Ottenere la data/ora del pacchetto tramite la chiamata ioctl sul descrittore del file socket

Dopo aver creato il socket, faccio la seguente:

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

Dopo che mi legano alla presa, la presa è di tipo SOCK_STREAM. Ricevo correttamente i dati sul socket, chiamando la funzione recv(fd, buf, size, 0). Ora, al fine di ottenere il timestamp dei dati ricevuti, Attualmente sto cercando il seguente:

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); 
} 

L'uscita del printf è sempre la seguente:

0,0 errore = - 1

l'errore = -1 indica che la chiamata ioctl ha fallito. Ho eseguito un test con getsockopt per verificare se è impostata l'opzione SO_TIMESTAMP, getsockopt restituisce 0 per l'opzione SO_TIMESTAMP quindi sembra impostato correttamente. Sono un po 'perso qui, come posso indagare ulteriormente perché la chiamata ioctl sembra fallire?

+1

Guardando a [QUESTO] (https://vilimpoc.org/research/ku-latency/), sembra che "SO_TIMESTAMP' sia usato per impostare l'opzione, non per recuperare i dati. Devi usare [recvmsg] (http://linux.die.net/man/2/recvmsg) per ottenere informazioni. – LPs

+0

Quando ricevi un errore da una chiamata di sistema dovresti stampare 'errno' o' strerror() 'o usare' perror() 'per farlo per te. Come hai scoperto, -1 non ti dice nulla di utile. – EJP

risposta

4

L'ioctl per recuperare il timestamp più recente sulla presa è SIOCGSTAMP; SO_TIMESTAMP è un'opzione socket, non un ioctl. Il codice dovrebbe leggere:

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

Il metodo alternativo per recuperare timestamp è quello di cambiare recv-recvmmsg ed estrarre il timestamp dai dati ausiliari. Questo è più efficiente in quanto comporta un minor numero di chiamate di sistema (Socket reading and timestamps); l'ioctl è più semplice, però.

noti che SIOCGSTAMP e SO_TIMESTAMP si escludono a vicenda - se avete intenzione di utilizzare SIOCGSTAMP si dovrebbe disabilitare SO_TIMESTAMP (con enabled = 0). Questo perché SO_TIMESTAMP indirizza il kernel a rendere disponibile il timestamp tramite i dati ausiliari recvmmsg anziché tramite SIOCGSTAMP.

+0

Lo sto provando ora con SIOCGSTAMP, ho impostato l'opzione SO_TIMESTAMP su 0 con setsockopt. Tuttavia la chiamata ioctl sta ancora restituendo -1. È necessario abilitare SIOCGSTAMP o è possibile che non sia supportato dal driver di periferica? – Gio

+0

@Gio cosa è impostato su "errno"? L'unica ragione per cui sono consapevole che SIOCGSTAMP fallire è se SO_TIMESTAMP è abilitato, nel qual caso sarà impostato su ENOENT. – ecatmur

+0

'printf ("% s ", strerror (errno))' stampa "Nessun file o directory". – Gio