2015-02-26 3 views
11

Я работаю над проектом, чтобы получить штамп приема и передачи от NIC для сокета TCP, как указано в документе Linux timestamping. Но вся документация и тестовое кодирование выполняются для сокетов UDP. Но я получаю временную метку передачи для сетевого адаптера и не получаю штамповку времени для приема пакетов TCP.Linux timestamping для сокетов TCP

Моего интерфейс поддерживает следующие временные метку

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) 

я включаю временные отметки для NIC после bind() использования ioctl(sockfd, SIOCSHWTSTAMP, &net_device); с

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; 

включите время штамповки в NIC через 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"); 
} 

После прослушивания() и принимаю(), я select() и проверить fd является rfds затем вызвать recvmsg() со следующими опциями

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

Но я всегда получаю следующее сообщение,

received short ancillary data (0/256) 

Я не получаю вспомогательные данные от recvmsg(), мне нравится знать, поддерживает ли linux TCP приемку аппаратного времени для NIC.

+0

Вы нашли способ? –

ответ

3

Linux timestamping не поддерживает получение аппаратного или программного обеспечения timestamping для TCP. Документация по временной привязке linux упоминается только в отношении «пакетов». Это относится к UDP, который используется для реализации синхронизации аппаратных часов PTP в NIC, для получения более полного понимания смотрите код PTP-демона и linux ptp. Linux 3.18 поддерживает только временную привязку в передаче. Таким образом, в основном вы не можете достичь лингвистической привязки linux для TCP в приемнике.

+0

так или иначе, чтобы получить временные метки для TCP? –

+0

Стоит добавить, что некоторые сетевые адаптеры и драйверы Linux поддерживают общую временную привязку UDP-пакетов, а не только для PTP. –

+0

Я знаю, что это старый, но я думаю, что 'libpcap' поддерживает временную привязку аппаратного обеспечения TCP. – xeon48

Смежные вопросы