2015-02-26 32 views
11

Pracuję w projekcie, aby uzyskać odbiór czasu nadawania i wysyłania z gniazda NIC dla TCP, jak wspomniano w dokumencie Linux timestamping. Ale cała dokumentacja i kodowanie testowe są wykonywane dla gniazd UDP. Dostaję jednak znacznik czasu transmisji dla karty NIC i nie otrzymuję sygnatury czasowej dla odbieranych pakietów TCP.Czas na Linuksa dla gniazd TCP

My Interfejs obsługuje następujące znaczniki czasu

Time stamping parameters for enp4s0: 
Capabilities: 
    hardware-transmit  (SOF_TIMESTAMPING_TX_HARDWARE) 
    software-transmit  (SOF_TIMESTAMPING_TX_SOFTWARE) 
    hardware-receive  (SOF_TIMESTAMPING_RX_HARDWARE) 
    software-receive  (SOF_TIMESTAMPING_RX_SOFTWARE) 
    software-system-clock (SOF_TIMESTAMPING_SOFTWARE) 
    hardware-raw-clock (SOF_TIMESTAMPING_RAW_HARDWARE) 
PTP Hardware Clock: 3 
Hardware Transmit Timestamp Modes: 
    off     (HWTSTAMP_TX_OFF) 
    on     (HWTSTAMP_TX_ON) 
Hardware Receive Filter Modes: 
    none     (HWTSTAMP_FILTER_NONE) 
    all     (HWTSTAMP_FILTER_ALL) 

I umożliwią znaczników czasu dla karty sieciowej po bind() użyciu ioctl(sockfd, SIOCSHWTSTAMP, &net_device); z

memset(&net_device, 0, sizeof(net_device)); 
strncpy(net_device.ifr_name, interface_name, sizeof(net_device.ifr_name)); 
net_device.ifr_data = (void *)&tstconfig; 
memset(&tstconfig, 0, sizeof(tstconfig)); 

tstconfig.tx_type = HWTSTAMP_TX_OFF; 
tstconfig.rx_filter = HWTSTAMP_FILTER_ALL; 

następnie włączyć czas tłoczenia w NIC poprzez setsockopt()

int opt= 0; 
opt |= SOF_TIMESTAMPING_RX_HARDWARE; 
opt |= SOF_TIMESTAMPING_RAW_HARDWARE; 
if (setsockopt(sockfd, SOL_SOCKET, SO_TIMESTAMPING, 
      (char *)&opt, sizeof(opt))) { 
    error(1, 0, "setsockopt timestamping"); 
    bail("setsockopt SO_TIMESTAMPING"); 
} 

Po listen() i accept(), mam select() i sprawdzić, czy fd jest rfds następnie wywołać recvmsg() z następujących opcji

int rc; 
struct iovec vec[1]; 
struct msghdr msg; 
char data[8192]; 
struct cmsghdr *cmsg; 

union { 
    struct cmsghdr cm; 
    char control[256]; 
} cmsg_un; 

vec[0].iov_base = data; 
vec[0].iov_len = sizeof(data); 

memset(&msg, 0, sizeof(msg)); 
memset(&from_addr, 0, sizeof(from_addr)); 
memset(&cmsg_un, 0, sizeof(cmsg_un)); 

msg.msg_name = NULL; 
msg.msg_namelen = 0; 
msg.msg_iov = vec; 
msg.msg_iovlen = 1; 
msg.msg_control = cmsg_un.control; 
msg.msg_controllen = sizeof(cmsg_un.control); 
rc = recvmsg(flow->fd, &msg, 0); 

printf("tried reading %d bytes, got %d", bytes, rc); 
if (msg.msg_flags & MSG_TRUNC) { 
    printf("received truncated message\n"); 
    return 0; 
} 

if (msg.msg_flags & MSG_CTRUNC) { 
    printf("received truncated ancillary data\n"); 
    return 0; 
} 

if (msg.msg_controllen <= 0) { 
    printf("`received short ancillary data (%ld/%ld)`\n", 
      (long)msg.msg_controllen, (long)sizeof(cmsg_un.control)); 
    return 0; 
} 

Ale ja zawsze otrzymuję komunikat,

received short ancillary data (0/256) 

Nie dostaję pomocniczych danych od recvmsg(), chciałbym wiedzieć, czy obsługa Linux-a obsługuje protokół TCP w postaci znacznika czasu dla karty NIC.

+0

czy znalazłeś sposób? –

Odpowiedz

3

Znacznik czasu Linuksa nie obsługuje sygnatury czasowej odbioru lub oprogramowania dla protokołu TCP. Dokumentacja znacznika czasu linux wspomniana tylko w odniesieniu do terminów "pakiety". Odnosi się to do UDP, który jest używany do implementacji synchronizacji zegara sprzętowego PTP w NIC, sprawdź kod demona PTP i linux ptp w celu lepszego zrozumienia. Linux 3.18 obsługuje tylko znacznik czasu w transmisji. Zasadniczo nie można uzyskać znacznika czasu dla protokołu TCP w odbiorniku.

+0

mimo to, aby uzyskać znaczniki czasu dla protokołu TCP? –

+0

Warto dodać, że niektóre karty NIC i Linux obsługują ogólne znaczniki czasowe pakietów UDP, a nie tylko PTP. –

+0

Wiem, że jest stary, ale myślę, że 'libpcap' obsługuje znacznik czasu sprzętu TCP. – xeon48