Atrybut gniazda używany do oznaczania czasu oprogramowania to SO_TIMESTAMPNS. Ten atrybut gniazda zwraca czas z zegara systemowego. Nie jest generowany w sprzęcie, lecz jest migawką czasu systemowego, gdy przerwanie jest obsługiwane w oprogramowaniu. Możemy uzyskać dostęp do tego znacznika czasu poprzez danych pomocniczych (cmsg), które nie jest częścią ładunku gniazda, używając:
int level, type;
struct cmsghdr *cm;
struct timespec *ts = NULL;
for (cm = CMSG_FIRSTHDR(&msg); cm != NULL; cm = CMSG_NXTHDR(&msg, cm))
{
level = cm->cmsg_level;
type = cm->cmsg_type;
if (SOL_SOCKET == level && SO_TIMESTAMPNS == type) {
ts = (struct timespec *) CMSG_DATA(cm);
printf("SW TIMESTAMP %ld.%09ld\n", (long)ts[0].tv_sec, (long)ts[0].tv_nsec);
}
}
Opcja gniazdo SO_TIMESTAMPING oferuje wiele różnych flagi, niektóre z nich są
SOF_TIMESTAMPING_TX_HARDWARE // Transmit timestamp generated in hardware by NIC clock
SOF_TIMESTAMPING_RX_HARDWARE // Receive timestamp generated in hardware by NIC clock
SOF_TIMESTAMPING_TX_SOFTWARE // Transmit timestamp generated in kernel driver by NIC clock
SOF_TIMESTAMPING_RX_SOFTWARE // Receive timestamp generated in kernel driver by NIC clock
Ta opcja gniazda nie jest obsługiwana przez wszystkie karty sieciowe (NIC). Obecnie wiele kart sieciowych obsługuje SO_TIMESTAMPING. Aby się dowiedzieć, czy dany sterownik interfejs obsługuje SO_TIMESTAMPING, przeznaczenie:
ethtool -T ethX // where X corresponds to your particular interface
ten powróci wszystkie atrybuty gniazdo eth.x obsługuje do timestamping.
Aby korzystać z funkcji sprzętu timestamping dostarczone przez konkretnego NIC, należy użyć kodu:
int flags;
flags = SOF_TIMESTAMPING_TX_HARDWARE
| SOF_TIMESTAMPING_RX_HARDWARE
| SOF_TIMESTAMPING_TX_SOFTWARE
| SOF_TIMESTAMPING_RX_SOFTWARE
| SOF_TIMESTAMPING_RAW_HARDWARE;
if (setsockopt(sd, SOL_SOCKET, SO_TIMESTAMPING, &flags, sizeof(flags)) < 0)
printf("ERROR: setsockopt SO_TIMESTAMPING\n");
int level, type;
struct cmsghdr *cm;
struct timespec *ts = NULL;
for (cm = CMSG_FIRSTHDR(&msg); cm != NULL; cm = CMSG_NXTHDR(&msg, cm))
{
if (SOL_SOCKET == level && SO_TIMESTAMPING == type) {
ts = (struct timespec *) CMSG_DATA(cm);
printf("HW TIMESTAMP %ld.%09ld\n", (long)ts[2].tv_sec, (long)ts[2].tv_nsec);
}
}
Hardware Jeśli obsługiwana, innego jądra. Zwykle taki sprzęt będzie używał czegoś podobnego do PTP, aby zachować synchronizację karty, więc powinieneś otrzymać sygnaturę czasową w stosunku do zegara (nie masz pewności, że jest monotoniczna - może ktoś inny może komentować). – Nim
@Nim, który jeden zwraca sprzęt, jeśli jest obsługiwany? SO_TIMESTAMPNS? Czy muszę włączyć sygnaturę czasową sprzętu? – Maverik
Zwykle sprzęt obsługujący tę funkcję będzie widział opcję gniazda ('SO_TIMESTAMPNS' lub' SO_TIMESTAMP'), a następnie stempluje pakiety. Na przykład, jeśli masz odpowiednią kartę Solarflare, ustawienie opcji spowoduje, że karta będzie miała znacznik czasu. Inaczej będzie zarządzany przez jądro. Szczerze mówiąc, naprawdę nie podoba mi się, że musisz czytać nagłówki kontrolne, aby otrzymać znacznik czasu - to okropny interfejs .. – Nim