Commit 9076ab67 authored by Joanne Hugé's avatar Joanne Hugé

Add timestamps to debug latencies

parent 35713b52
...@@ -39,6 +39,7 @@ enum TSNTask {SEND_PACKET_TASK, RTT_TASK}; ...@@ -39,6 +39,7 @@ enum TSNTask {SEND_PACKET_TASK, RTT_TASK};
typedef struct thread_stat { typedef struct thread_stat {
int nb_cycles; int nb_cycles;
uint64_t rtt; uint64_t rtt;
struct packet_timestamps packet_ts;
} thread_stat_t; } thread_stat_t;
typedef struct thread_param { typedef struct thread_param {
...@@ -152,6 +153,12 @@ int main(int argc, char *argv[]) { ...@@ -152,6 +153,12 @@ int main(int argc, char *argv[]) {
if(param.tsn_task == RTT_TASK) { if(param.tsn_task == RTT_TASK) {
printf("RTT: %" PRIu64 " (%d)\n", param.stats.rtt, param.stats.nb_cycles); printf("RTT: %" PRIu64 " (%d)\n", param.stats.rtt, param.stats.nb_cycles);
} }
else if (param.enable_timestamps) {
printf("(%d)\n", param.stats.nb_cycles);
printf(" Enter send_udp_packet timestamp: %" PRIu64 "\n", param.stats.packet_ts.user_enter_send);
printf(" Call sendmsg timestamp : %" PRIu64 "\n", param.stats.packet_ts.user_call_sendmsg);
printf(" Leave kernel timestamp : %" PRIu64 "\n", param.stats.packet_ts.kernel_leave);
}
if (param.max_cycles) if (param.max_cycles)
if (param.max_cycles == param.stats.nb_cycles) break; if (param.max_cycles == param.stats.nb_cycles) break;
...@@ -164,7 +171,7 @@ static void do_tsn_task(struct thread_param * param, uint64_t next_txtime) { ...@@ -164,7 +171,7 @@ static void do_tsn_task(struct thread_param * param, uint64_t next_txtime) {
struct timespec t1, t2; struct timespec t1, t2;
if(param->tsn_task == SEND_PACKET_TASK) { if(param->tsn_task == SEND_PACKET_TASK) {
send_udp_packet(param->enable_etf, param->enable_timestamps, next_txtime, param->ip_address); param->stats.packet_ts = send_udp_packet(param->enable_etf, param->enable_timestamps, next_txtime, param->ip_address);
} }
else if(param->tsn_task == RTT_TASK) { else if(param->tsn_task == RTT_TASK) {
......
...@@ -7,8 +7,8 @@ ...@@ -7,8 +7,8 @@
* *
*/ */
#include "send_packet.h"
#define _GNU_SOURCE
#include <arpa/inet.h> #include <arpa/inet.h>
#include <errno.h> #include <errno.h>
#include <error.h> #include <error.h>
...@@ -37,16 +37,16 @@ ...@@ -37,16 +37,16 @@
#include <unistd.h> #include <unistd.h>
#include "utilities.h" #include "utilities.h"
#include "send_packet.h"
#define MESSAGE ((uint32_t)0x00FACADE) #define MESSAGE ((uint32_t)0x00FACADE)
static void print_timestamps(struct msghdr *msg, uint64_t txtime); static void process_timestamps(struct packet_timestamps *packet_ts);
static void process_timestamps(uint64_t txtime);
static void init_tx_buffer(size_t _tx_buffer_len); static void init_tx_buffer(size_t _tx_buffer_len);
static int so_priority = 3; static int so_priority = 3;
static struct sock_txtime sk_txtime; static struct sock_txtime sk_txtime;
static unsigned char * tx_buffer; static unsigned char *tx_buffer;
static size_t tx_buffer_len; static size_t tx_buffer_len;
static int fd; static int fd;
...@@ -69,8 +69,7 @@ static int set_if(char *network_if) { ...@@ -69,8 +69,7 @@ static int set_if(char *network_if) {
} }
static void init_tx_buffer(size_t _tx_buffer_len) { static void init_tx_buffer(size_t _tx_buffer_len) {
if (_tx_buffer_len < 1) {
if( _tx_buffer_len < 1) {
fprintf(stderr, "tx buffer length should be greater than 1\n"); fprintf(stderr, "tx buffer length should be greater than 1\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
...@@ -78,8 +77,8 @@ static void init_tx_buffer(size_t _tx_buffer_len) { ...@@ -78,8 +77,8 @@ static void init_tx_buffer(size_t _tx_buffer_len) {
tx_buffer_len = _tx_buffer_len; tx_buffer_len = _tx_buffer_len;
tx_buffer = malloc(tx_buffer_len); tx_buffer = malloc(tx_buffer_len);
for(int i = 0; i < ( ((int)tx_buffer_len) - 1); i++) { for (int i = 0; i < (((int)tx_buffer_len) - 1); i++) {
tx_buffer[i] = (unsigned char) i; tx_buffer[i] = (unsigned char)i;
} }
tx_buffer[tx_buffer_len - 1] = '\0'; tx_buffer[tx_buffer_len - 1] = '\0';
...@@ -89,7 +88,7 @@ static void init_tx_buffer(size_t _tx_buffer_len) { ...@@ -89,7 +88,7 @@ static void init_tx_buffer(size_t _tx_buffer_len) {
* Init UDP socket * Init UDP socket
*/ */
void init_udp_send(int use_etf, int use_timestamps, int packet_priority, void init_udp_send(int use_etf, int use_timestamps, int packet_priority,
char *network_if, size_t _tx_buffer_len) { char *network_if, size_t _tx_buffer_len) {
int index; int index;
struct timespec ts_mon; struct timespec ts_mon;
...@@ -99,7 +98,8 @@ void init_udp_send(int use_etf, int use_timestamps, int packet_priority, ...@@ -99,7 +98,8 @@ void init_udp_send(int use_etf, int use_timestamps, int packet_priority,
clock_gettime(CLOCK_MONOTONIC, &ts_mon); clock_gettime(CLOCK_MONOTONIC, &ts_mon);
clock_gettime(CLOCK_TAI, &ts_tai); clock_gettime(CLOCK_TAI, &ts_tai);
tai_offset = (ts_mon.tv_sec - ts_tai.tv_sec) * NSEC_PER_SEC + (ts_mon.tv_nsec - ts_tai.tv_nsec); tai_offset = (ts_mon.tv_sec - ts_tai.tv_sec) * NSEC_PER_SEC +
(ts_mon.tv_nsec - ts_tai.tv_nsec);
so_priority = packet_priority; so_priority = packet_priority;
...@@ -144,10 +144,11 @@ uint64_t get_txtime() { ...@@ -144,10 +144,11 @@ uint64_t get_txtime() {
} }
/* /*
* Sends udp packets using the ETF qdisc * Sends udp packets
*/ */
void send_udp_packet(int use_etf, int use_timestamps, uint64_t txtime, struct packet_timestamps send_udp_packet(int use_etf, int use_timestamps,
const char *server_ip) { uint64_t txtime,
const char *server_ip) {
char control[CMSG_SPACE(sizeof(txtime))] = {}; char control[CMSG_SPACE(sizeof(txtime))] = {};
struct sockaddr_in sin; struct sockaddr_in sin;
struct cmsghdr *cmsg; struct cmsghdr *cmsg;
...@@ -157,6 +158,14 @@ void send_udp_packet(int use_etf, int use_timestamps, uint64_t txtime, ...@@ -157,6 +158,14 @@ void send_udp_packet(int use_etf, int use_timestamps, uint64_t txtime,
int res; int res;
struct pollfd poll_fd = {fd, POLLPRI, 0}; struct pollfd poll_fd = {fd, POLLPRI, 0};
struct packet_timestamps packet_ts;
struct timespec ts;
if (use_timestamps) {
clock_gettime(CLOCK_MONOTONIC, &ts);
packet_ts.user_enter_send = ts_to_uint(ts);
}
memset(&sin, 0, sizeof(sin)); memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET; sin.sin_family = AF_INET;
sin.sin_addr.s_addr = inet_addr(server_ip); sin.sin_addr.s_addr = inet_addr(server_ip);
...@@ -184,6 +193,11 @@ void send_udp_packet(int use_etf, int use_timestamps, uint64_t txtime, ...@@ -184,6 +193,11 @@ void send_udp_packet(int use_etf, int use_timestamps, uint64_t txtime,
msg.msg_controllen = cmsg->cmsg_len; msg.msg_controllen = cmsg->cmsg_len;
} }
if (use_timestamps) {
clock_gettime(CLOCK_MONOTONIC, &ts);
packet_ts.user_call_sendmsg = ts_to_uint(ts);
}
sendmsgerr = sendmsg(fd, &msg, 0); sendmsgerr = sendmsg(fd, &msg, 0);
if (sendmsgerr < 0) if (sendmsgerr < 0)
error(EXIT_FAILURE, errno, "sendmsg failed, ret value: %d\n", sendmsgerr); error(EXIT_FAILURE, errno, "sendmsg failed, ret value: %d\n", sendmsgerr);
...@@ -191,13 +205,15 @@ void send_udp_packet(int use_etf, int use_timestamps, uint64_t txtime, ...@@ -191,13 +205,15 @@ void send_udp_packet(int use_etf, int use_timestamps, uint64_t txtime,
if (use_timestamps) { if (use_timestamps) {
res = poll(&poll_fd, 1, 0); res = poll(&poll_fd, 1, 0);
if (res > 0) if (res > 0)
process_timestamps(txtime); process_timestamps(&packet_ts);
else else
fprintf(stderr, "select failed\n"); fprintf(stderr, "select failed\n");
} }
return packet_ts;
} }
static void process_timestamps(uint64_t txtime) { static void process_timestamps(struct packet_timestamps *packet_ts) {
char data[256]; char data[256];
struct msghdr msg; struct msghdr msg;
struct iovec entry; struct iovec entry;
...@@ -206,6 +222,7 @@ static void process_timestamps(uint64_t txtime) { ...@@ -206,6 +222,7 @@ static void process_timestamps(uint64_t txtime) {
struct cmsghdr cm; struct cmsghdr cm;
char control[512]; char control[512];
} control; } control;
struct cmsghdr *cmsg;
memset(&msg, 0, sizeof(msg)); memset(&msg, 0, sizeof(msg));
msg.msg_iov = &entry; msg.msg_iov = &entry;
...@@ -219,42 +236,17 @@ static void process_timestamps(uint64_t txtime) { ...@@ -219,42 +236,17 @@ static void process_timestamps(uint64_t txtime) {
if (recvmsg(fd, &msg, MSG_ERRQUEUE | MSG_DONTWAIT) == -1) { if (recvmsg(fd, &msg, MSG_ERRQUEUE | MSG_DONTWAIT) == -1) {
fprintf(stderr, "recvmsg failed\n"); fprintf(stderr, "recvmsg failed\n");
} else { return;
print_timestamps(&msg, txtime);
} }
}
static void print_timestamps(struct msghdr *msg, uint64_t txtime) {
struct cmsghdr *cmsg;
for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) { for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
switch (cmsg->cmsg_level) { if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_TIMESTAMPING) {
case SOL_SOCKET: struct timespec *stamp = (struct timespec *)CMSG_DATA(cmsg);
printf("SOL_SOCKET "); packet_ts->kernel_leave = ts_to_uint(*stamp);
switch (cmsg->cmsg_type) { } else {
case SO_TIMESTAMPING: { fprintf(stderr, "process_timestamps: level %d type %d", cmsg->cmsg_level,
struct timespec *stamp = (struct timespec *)CMSG_DATA(cmsg); cmsg->cmsg_type);
uint64_t timestamp_ns =
stamp->tv_sec * NSEC_PER_SEC + stamp->tv_nsec;
printf("SO_TIMESTAMPING ");
printf("SW %" PRIu64 " - %" PRIu64 " (%" PRIi64 ") ", timestamp_ns,
txtime, ((int64_t)timestamp_ns) - txtime - tai_offset);
break;
}
default:
#ifdef DEBUG
printf("type %d", cmsg->cmsg_type);
#endif
break;
}
break;
default:
#ifdef DEBUG
printf("level %d type %d", cmsg->cmsg_level, cmsg->cmsg_type);
#endif
break;
} }
printf("\n");
} }
} }
......
...@@ -4,7 +4,13 @@ ...@@ -4,7 +4,13 @@
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
struct packet_timestamps {
uint64_t user_enter_send;
uint64_t user_call_sendmsg;
uint64_t kernel_leave;
};
void init_udp_send(int use_etf, int use_timestamps, int so_priority, char * network_if, size_t tx_buffer_len); void init_udp_send(int use_etf, int use_timestamps, int so_priority, char * network_if, size_t tx_buffer_len);
void send_udp_packet(int use_etf, int use_timestamps, uint64_t txtime, const char *server_ip); struct packet_timestamps send_udp_packet(int use_etf, int use_timestamps, uint64_t txtime, const char *server_ip);
#endif #endif
...@@ -6,6 +6,10 @@ ...@@ -6,6 +6,10 @@
#include "utilities.h" #include "utilities.h"
uint64_t ts_to_uint(struct timespec t) {
return t.tv_nsec * NSEC_PER_SEC + t.tv_sec;
}
void add_ns(struct timespec *t, uint64_t ns) { void add_ns(struct timespec *t, uint64_t ns) {
t->tv_nsec += ns; t->tv_nsec += ns;
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#define SERVER_PORT "50000" #define SERVER_PORT "50000"
#define SERVER_PORT_INT 50000 #define SERVER_PORT_INT 50000
uint64_t ts_to_uint(struct timespec t);
void add_ns(struct timespec *t, uint64_t ns); void add_ns(struct timespec *t, uint64_t ns);
uint64_t calcdiff_ns(struct timespec t1, struct timespec t2); uint64_t calcdiff_ns(struct timespec t1, struct timespec t2);
uint64_t max(uint64_t a, uint64_t b); uint64_t max(uint64_t a, uint64_t b);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment