2015-02-26 14 views
11

Tôi đang làm việc trong một dự án để nhận được và truyền thời gian dán tem từ NIC cho ổ cắm TCP như đã đề cập trong tài liệu Linux timestamping. Nhưng tất cả các tài liệu và kiểm tra mã hóa được thực hiện cho các ổ cắm UDP. Nhưng tôi nhận được timestamping Transmit cho NIC và không nhận được thời gian dán tem cho các gói tin TCP nhận được.Linux timestamping cho cổng TCP

My Interface hỗ trợ các tem thời gian sau

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) 

tôi cho phép các timestamping cho NIC sau bind() sử dụng ioctl(sockfd, SIOCSHWTSTAMP, &net_device); với

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; 

sau đó kích hoạt thời gian dập trong NIC qua 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"); 
} 

Sau khi lắng nghe() và chấp nhận(), tôi làm select(), và kiểm tra xem fd được rfds sau đó gọi các recvmsg() với các tùy chọn sau đây

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

Nhưng tôi luôn nhận được thông báo sau,

received short ancillary data (0/256) 

Tôi không nhận được các dữ liệu phụ trợ từ recvmsg(), tôi muốn biết liệu hỗ trợ linux TCP nhận được phần cứng thời gian dán tem cho NIC.

+0

bạn có tìm thấy cách nào không? –

Trả lời

3

Timestamping Linux không hỗ trợ nhận thời gian phần cứng hoặc phần mềm cho TCP. Tài liệu về timestamping linux được đề cập chỉ liên quan đến "gói". Điều này đề cập đến UDP, được sử dụng để thực hiện đồng bộ hóa đồng hồ phần cứng PTP trong NIC, xem mã của PTP daemon và linux ptp để hiểu rõ hơn. Linux 3.18 chỉ hỗ trợ dấu thời gian trong quá trình truyền. Vì vậy, về cơ bản bạn không thể đạt được timestamping linux cho TCP trong máy thu.

+0

dù sao để nhận dấu thời gian cho TCP thì sao? –

+0

Đáng giá thêm là một số NIC và trình điều khiển Linux hỗ trợ timestamping chung của gói UDP, không chỉ dành cho PTP. –

+0

Tôi biết đây là cũ, nhưng tôi nghĩ 'libpcap' hỗ trợ timestamping phần cứng TCP. – xeon48

Các vấn đề liên quan