Commit 44317e4e authored by Joanne Hugé's avatar Joanne Hugé

WIP: rewrite and clean up code

parent c7b294cd
......@@ -8,6 +8,7 @@
#define _GNU_SOURCE
#include <errno.h>
#include <error.h>
#include <limits.h>
#include <pthread.h>
#include <sched.h>
#include <signal.h>
......@@ -18,9 +19,9 @@
#include <time.h>
#include <unistd.h>
#include "common.h"
#include "recv_packet.h"
#include "send_packet.h"
#include "common.h"
// Structs
......@@ -48,14 +49,14 @@ typedef struct main_param {
// Static functions
static void process_options(int argc, char *argv[]);
static void do_tsn_task(struct thread_param *param, char *data, uint64_t next_txtime);
static void do_tsn_task(char *data, uint64_t next_txtime);
static void print_histograms();
static void sighand(int sig_num);
// Static variables
static int64_t kernel_latency_hist[MAX_KERNEL_LATENCY]++;
static int64_t rtt_hist[MAX_RTT_LATENCY]++;
static int64_t kernel_latency_hist[MAX_KERNEL_LATENCY];
static int64_t rtt_hist[MAX_RTT];
static int nb_cycles;
......@@ -64,6 +65,8 @@ static thread_param_t thread_params;
static rtt_stat_t rtt_stats;
static egress_stat_t egress_stats;
static egress_param_t egress_params;
static ingress_stat_t ingress_stats;
static ingress_param_t ingress_params;
static int enable_histograms;
static int enable_affinity;
......@@ -114,7 +117,7 @@ static void *packet_sending_thread(void *p) {
}
// Set thread priority
priority.sched_priority = param->priority;
priority.sched_priority = thread_params.priority;
if (sched_setscheduler(0, SCHED_FIFO, &priority))
error(EXIT_FAILURE, errno, "Couldn't set priority");
......@@ -122,7 +125,7 @@ static void *packet_sending_thread(void *p) {
// Measure from CLOCK_TAI to generate timestamp
clock_gettime(CLOCK_TAI, &next);
next_txtime = next.tv_sec * NSEC_PER_SEC + next.tv_nsec;
next_txtime += param->etf_offset;
next_txtime += thread_params.etf_offset;
} else {
next_txtime = 0;
}
......@@ -183,8 +186,8 @@ int main(int argc, char *argv[]) {
if (enable_histograms) {
// Init histograms
memset(kernel_latency, 0, MAX_KERNEL_LATENCY);
memset(rtt_latency, 0, MAX_RTT_LATENCY);
memset(kernel_latency_hist, 0, MAX_KERNEL_LATENCY);
memset(rtt_hist, 0, MAX_RTT);
}
// Catch breaks with sighand to print the histograms
......@@ -193,17 +196,20 @@ int main(int argc, char *argv[]) {
// Initialize the UDP packet sending socket
init_udp_send(&egress_params,
&egress_stats,
&thread_params,
enable_histograms,
kernel_latency_hist);
// Initialize the UDP packet receiving socket if RTT is measured
if (tsn_task == RTT_TASK)
init_udp_recv(0, network_config.network_if);
init_udp_recv(&ingress_params,
&ingress_stats,
enable_histograms,
kernel_latency_hist);
// Create the real time thread
if (pthread_create(&thread, NULL, packet_sending_thread, NULL));
error(EXIT_FAILURE, errno, "Couldn't create thread");
if (pthread_create(&thread, NULL, packet_sending_thread, NULL))
;
error(EXIT_FAILURE, errno, "Couldn't create thread");
// Verbose loop
for (;;) {
......@@ -213,15 +219,15 @@ int main(int argc, char *argv[]) {
if (tsn_task == RTT_TASK) {
printf("%10d: RTT: %4d %4d %4d\n", nb_cycles, rtt_stats.min_rtt,
rtt_stats.avg_rtt,
rtt_stats.max_rtt);
rtt_stats.avg_rtt,
rtt_stats.max_rtt);
printf("\033[%dA", 1);
} else if (enable_timestamps) {
printf("%10d: K: %4d %4d %4d\n",
nb_cycles, egress_stats.min_kernel_latency,
egress_stats.avg_kernel_latency,
egress_stats.max_kernel_latency);
egress_stats.avg_kernel_latency,
egress_stats.max_kernel_latency);
printf("\033[%dA", 1);
}
}
......@@ -259,13 +265,12 @@ static void do_tsn_task(char *data, uint64_t next_txtime) {
rtt_stats.min_rtt = min(rtt_us, rtt_stats.min_rtt);
rtt_stats.max_rtt = max(rtt_us, rtt_stats.max_rtt);
rtt_stats.avg_rtt = (((uint64_t)rtt_stats.avg_rtt) * (nb_cycles-1) + rtt_us) / nb_cycles;
rtt_stats.avg_rtt = (((uint64_t)rtt_stats.avg_rtt) * (nb_cycles - 1) + rtt_us) / nb_cycles;
if (rtt_us > MAX_RTT_VAL)
fprintf(stderr, "RTT value higher than MAX_RTT_VAL : %d ( > %d)\n", rtt_us, MAX_RTT_VAL);
else
rtt_hist[rtt_us]++;
}
if (rtt_us > MAX_RTT)
fprintf(stderr, "RTT value higher than MAX_RTT : %d ( > %d)\n", rtt_us, MAX_RTT);
else
rtt_hist[rtt_us]++;
}
}
......@@ -275,7 +280,7 @@ static void print_histograms() {
uint64_t duration;
int duration_hour, duration_minutes, interval;
int max_hist_val, nb_hists;
uint64_t * histogram;
uint64_t *histogram;
clock_gettime(CLOCK_MONOTONIC, &measures_end);
......@@ -283,7 +288,7 @@ static void print_histograms() {
duration_hour = duration / NSEC_PER_SEC / 3600;
duration_minutes = duration / NSEC_PER_SEC / 60 - duration_hour * 60;
interval = param->interval / 1000;
interval = thread_params.interval / 1000;
if (tsn_task == SEND_PACKET_TASK) {
printf("{\"measure_sets\": [{"
......@@ -296,7 +301,12 @@ static void print_histograms() {
"},"
"\"props\": [",
interval, duration_hour, duration_minutes, thread_params.etf_offset);
histogram = kernel_latency_hist;
histogram = kernel_latency_hist;
max_hist_val = 0;
for (int j = 0; j < MAX_KERNEL_LATENCY; j++)
if (histogram[j])
max_hist_val = j > max_hist_val ? j : max_hist_val;
} else if (tsn_task == RTT_TASK) {
printf("{\"measure_sets\": [{"
......@@ -309,15 +319,14 @@ static void print_histograms() {
"},"
"\"props\": [",
interval, duration_hour, duration_minutes, thread_params.etf_offset);
histogram = rtt_hist;
histogram = rtt_hist;
max_hist_val = 0;
for (int j = 0; j < MAX_RTT; j++)
if (histogram[j])
max_hist_val = j > max_hist_val ? j : max_hist_val;
}
max_hist_val = 0;
for (int j = 0; j < MAX_HIST_VAL; j++)
if (histogram[j])
max_hist_val = j > max_hist_val ? j : max_hist_val;
printf("[");
for (int j = 0; j < max_hist_val; j++)
printf("%" PRIi64 "%s", histogram[j], (j + 1 < max_hist_val ? ", " : ""));
......@@ -410,5 +419,5 @@ static void process_options(int argc, char *argv[]) {
help(argv);
exit(EXIT_FAILURE);
}
strcpy(egress_params.ip_address, argv[optind]);
strcpy(egress_params.server_ip, argv[optind]);
}
......@@ -32,8 +32,8 @@ uint64_t calcdiff_ns(struct timespec t1, struct timespec t2) {
return diff;
}
uint64_t max(uint64_t a, uint64_t b) { return a > b ? a : b; }
uint64_t min(uint64_t a, uint64_t b) { return a < b ? a : b; }
int max(int a, int b) { return a > b ? a : b; }
int min(int a, int b) { return a < b ? a : b; }
static void sighand_wrapper(int sig) {
......
......@@ -13,26 +13,20 @@
#define SERVER_PORT_INT 50000
#define MAX_KERNEL_LATENCY 1000
#define MAX_RTT_LATENCY 1000
#define MAX_RTT 1000
#define MAX_JITTER 1000
#define MAX_BUFFER_SIZE 1024
typedef struct packet_info {
uint64_t userspace_enter_ts;
uint64_t userspace_exit_ts;
uint64_t kernelspace_ts;
char data[MAX_BUFFER_SIZE];
} packet_info_t;
uint64_t ts_to_uint(struct timespec t);
void add_ns(struct timespec *t, uint64_t ns);
uint64_t calcdiff_ns(struct timespec t1, struct timespec t2);
uint64_t max(uint64_t a, uint64_t b);
uint64_t min(uint64_t a, uint64_t b);
void init_signals(void (*_sighand)(int), int enable_histograms);
int min(int a, int b);
int max(int a, int b);
extern void (*previous_handlers[NSIG])(int);
#endif
......@@ -26,7 +26,7 @@
#include <unistd.h>
#include "common.h"
#include "send_packet.h"
#include "recv_packet.h"
static char rx_buffer[MAX_BUFFER_SIZE];
static int sock_fd;
......@@ -34,6 +34,11 @@ static int sock_fd;
static int so_timestamping_flags =
SOF_TIMESTAMPING_RX_SOFTWARE | SOF_TIMESTAMPING_SOFTWARE;
static ingress_param_t *params;
static ingress_stat_t *stats;
static uint64_t *kernel_latency_hist;
static int use_histogram;
static uint64_t timestamps_buffer[64];
static int ts_buf_read_index = 0;
static int ts_buf_write_index = 0;
......@@ -43,7 +48,7 @@ static int set_if() {
struct ifreq ifreq;
memset(&ifreq, 0, sizeof(ifreq));
strncpy(ifreq.ifr_name, ingress_params->network_if, sizeof(ifreq.ifr_name) - 1);
strncpy(ifreq.ifr_name, params->network_if, sizeof(ifreq.ifr_name) - 1);
if (ioctl(sock_fd, SIOCGIFINDEX, &ifreq))
error(EXIT_FAILURE, errno, "ioctl SIOCGIFINDEX failed\n");
......@@ -53,7 +58,7 @@ static int set_if() {
void init_udp_recv(ingress_param_t *_params,
ingress_stat_t *_stats,
int use_histogram,
int _use_histogram,
uint64_t *_kernel_latency_hist) {
int getaddrinfo_err;
int set_if_err;
......@@ -125,7 +130,7 @@ void recv_udp_packet() {
struct timespec ts;
if (use_timestamps) {
if (params->use_timestamps) {
clock_gettime(CLOCK_REALTIME, &ts);
timestamps_buffer[ts_buf_write_index++] = ts_to_uint(ts);
}
......@@ -171,25 +176,6 @@ void recv_udp_packet() {
strcpy(stats->data, rx_buffer);
}
static void fill_histograms(packet_info_t *packet_info, int64_t histograms[NB_HISTOGRAMS][MAX_HIST_VAL]) {
uint64_t user_space_time = packet_info->userspace_exit_ts - packet_info->userspace_enter_ts;
uint64_t kernel_space_time = packet_info->userspace_enter_ts - packet_info->kernelspace_ts;
user_space_time /= 1000u;
kernel_space_time /= 1000u;
if (user_space_time > MAX_HIST_VAL)
fprintf(stderr, "user_space_time value too high: %" PRIu64 "us\n", user_space_time);
else
histograms[0][user_space_time]++;
if (kernel_space_time > MAX_HIST_VAL)
fprintf(stderr, "kernel_space_time value too high: %" PRIu64 "us\n", kernel_space_time);
else
histograms[1][kernel_space_time]++;
}
#ifdef DEBUG
/*
......
#ifndef RECV_PACKET
#define RECV_PACKET
#include "utilities.h"
void init_udp_recv(ingress_param_t *_params,
ingress_stat_t *stats,
int use_histogram,
uint64_t *_kernel_latency_hist);
void recv_udp_packet();
void init_udp_recv(ingress_param_t *params,
uint64_t *kernel_latency_hist);
void recv_udp_packet(int nb_cycles);
#include "common.h"
typedef struct ingress_param {
char network_if[16];
int use_timestamps;
size_t tx_buffer_len;
} ingress_param_t;
typedef struct ingress_stat {
uint64_t high_kernel_latency;
int min_kernel_latency;
int avg_kernel_latency;
int max_kernel_latency;
......@@ -33,6 +22,18 @@ typedef struct ingress_stat {
int avg_interval;
int max_interval;
} egress_stat_t;
uint64_t high_kernel_latency;
uint64_t packets_received;
int lost_packets;
char data[MAX_BUFFER_SIZE];
} ingress_stat_t;
void init_udp_recv(ingress_param_t *_params,
ingress_stat_t *stats,
int use_histogram,
uint64_t *_kernel_latency_hist);
void recv_udp_packet();
#endif
......@@ -34,10 +34,10 @@
#include <sys/types.h>
#include <unistd.h>
#include "send_packet.h"
#include "common.h"
#include "send_packet.h"
static void * poll_thread(void *p);
static void *poll_thread(void *p);
static void process_error_queue();
static void init_tx_buffer();
......@@ -46,10 +46,11 @@ static int set_if();
static int so_timestamping_flags =
SOF_TIMESTAMPING_TX_SOFTWARE | SOF_TIMESTAMPING_SOFTWARE;
egress_param_t * params;
egress_stat_t * stats;
uint64_t * kernel_latency_hist;
int use_histogram;
static egress_param_t *params;
static egress_stat_t *stats;
static uint64_t *kernel_latency_hist;
static int use_histogram;
static uint64_t packets_sent = 0;
static struct sock_txtime sk_txtime;
static char *tx_buffer;
......@@ -62,10 +63,10 @@ static int ts_buf_write_index = 0;
/*
* Init UDP socket
*/
void init_udp_send(egress_param_t * _params,
egress_stat_t * _stats,
int _use_histogram,
uint64_t * _kernel_latency_hist) {
void init_udp_send(egress_param_t *_params,
egress_stat_t *_stats,
int _use_histogram,
uint64_t *_kernel_latency_hist) {
int set_if_err;
pthread_t thread;
......@@ -73,7 +74,7 @@ void init_udp_send(egress_param_t * _params,
params = _params;
stats = _stats;
kernel_latency_hist = _kernel_latency_hist;
use_histogram = _use_histogram
use_histogram = _use_histogram;
init_tx_buffer();
......@@ -116,7 +117,7 @@ void init_udp_send(egress_param_t * _params,
* Sends udp packets
*/
void send_udp_packet(char *data,
uint64_t txtime, int nb_cycles) {
uint64_t txtime) {
struct msghdr msg; // Message hardware, sent to the socket
struct cmsghdr *cmsg; // Control message hardware, for txtime
......@@ -131,11 +132,13 @@ void send_udp_packet(char *data,
timestamps_buffer[ts_buf_write_index++] = ts_to_uint(ts);
}
packets_sent++;
strcpy(tx_buffer, data);
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = inet_addr(server_ip);
sin.sin_addr.s_addr = inet_addr(params->server_ip);
sin.sin_port = htons(SERVER_PORT_INT);
iov.iov_base = tx_buffer;
......@@ -165,7 +168,7 @@ void send_udp_packet(char *data,
error(EXIT_FAILURE, errno, "sendmsg failed, ret value: %d\n", sendmsgerr);
}
static void * poll_thread(void *p) {
static void *poll_thread(void *p) {
(void)p;
// Poll file descriptor
......@@ -175,13 +178,15 @@ static void * poll_thread(void *p) {
int ret;
ret = poll(&poll_fd, 1, -1);
if (ret == 1 && p_fd.revents & POLLERR) {
process_error_queue(nb_cycles);
if (ret == 1 && poll_fd.revents & POLLERR) {
process_error_queue();
}
}
}
static void process_error_queue(int nb_cycles) {
static void process_error_queue() {
int recv_ret;
// IO vector
unsigned char data_buffer[256]; // Buffer in io vector
struct iovec iov = {
......@@ -201,8 +206,8 @@ static void process_error_queue(int nb_cycles) {
struct cmsghdr *cmsg;
// Timestamps and errors are received in the error queue
res = recvmsg(sock_fd, &msg, MSG_ERRQUEUE | MSG_DONTWAIT);
if (res == -1) {
recv_ret = recvmsg(sock_fd, &msg, MSG_ERRQUEUE | MSG_DONTWAIT);
if (recv_ret == -1) {
fprintf(stderr, "recvmsg() failed\n");
return;
}
......@@ -213,12 +218,11 @@ static void process_error_queue(int nb_cycles) {
struct timespec *stamp = (struct timespec *)CMSG_DATA(cmsg);
uint64_t kernel_latency = ts_to_uint(stamp) - timestamps_buffer[ts_buf_read_index++];
kernel_latency /= 1000u;
int kernel_latency = (ts_to_uint(*stamp) - timestamps_buffer[ts_buf_read_index++]) / 1000;
stats->min_kernel_latency = min(kernel_latency, stats->min_kernel_latency);
stats->max_kernel_latency = max(kernel_latency, stats->max_kernel_latency);
stats->avg_kernel_latency = (stats->max_kernel_latency * (nb_cycles-1) + kernel_latency) / nb_cycles;
stats->avg_kernel_latency = (stats->max_kernel_latency * (packets_sent - 1) + kernel_latency) / packets_sent;
if (use_histogram) {
if (kernel_latency > MAX_KERNEL_LATENCY)
......@@ -248,7 +252,6 @@ static void process_error_queue(int nb_cycles) {
}
}
}
}
// Sets the interface
......
......@@ -3,13 +3,6 @@
#include "common.h"
void init_udp_send(egress_param_t *_params,
egress_stat_t *_stats,
int _use_histogram,
uint64_t *_kernel_latency_hist);
void send_udp_packet(char *data, uint64_t txtime, int nb_cycles);
typedef struct egress_param {
int packet_priority;
size_t tx_buffer_len;
......@@ -33,4 +26,11 @@ typedef struct egress_stat {
} egress_stat_t;
void init_udp_send(egress_param_t *_params,
egress_stat_t *_stats,
int _use_histogram,
uint64_t *_kernel_latency_hist);
void send_udp_packet(char *data, uint64_t txtime);
#endif
......@@ -10,6 +10,7 @@
#include <errno.h>
#include <error.h>
#include <inttypes.h>
#include <limits.h>
#include <netdb.h>
#include <netinet/in.h>
#include <pthread.h>
......@@ -30,18 +31,6 @@
// Structs
typedef struct thread_stat {
int min_interval;
int avg_interval;
int max_interval;
int packets_received;
int lost_packets;
char *data[MAX_BUFFER_SIZE];
} thread_stat_t;
typedef struct thread_param {
int interval;
int priority;
......@@ -51,7 +40,6 @@ typedef struct thread_param {
typedef struct main_params {
int refresh_rate;
int verbose;
size_t tx_buffer_len;
} main_param_t;
static void process_options(int argc, char *argv[]);
......@@ -67,13 +55,14 @@ static main_param_t main_params;
static thread_param_t thread_params;
static ingress_stat_t ingress_stats;
static ingress_param_t ingress_params;
static egress_stat_t egress_stats;
static egress_param_t egress_params;
static int enable_histograms;
static int enable_affinity;
static int enable_timestamps;
enum TSNTask { RECV_PACKET_TASK,
RTT_TASK };
enum TSNTask { RECV_PACKET_TASK, RTT_TASK };
static enum TSNTask tsn_task;
struct timespec measures_start;
......@@ -126,7 +115,7 @@ static void *packet_receiving_thread(void *p) {
clock_gettime(CLOCK_MONOTONIC, &measures_start);
// Packet receiving loop
for (stats->packets_received = 0;; stats->packets_received++) {
for (ingress_stats.packets_received = 0;; ingress_stats.packets_received++) {
if (tsn_task == RTT_TASK) {
......@@ -139,10 +128,11 @@ static void *packet_receiving_thread(void *p) {
clock_gettime(CLOCK_MONOTONIC, &current);
current_packet_id = recv_udp_packet();
recv_udp_packet();
current_packet_id = atoi(ingress_stats.data);
// If this is not the first received packet
if (stats->packets_received) {
if (ingress_stats.packets_received) {
int interval_us = calcdiff_ns(current, previous) / 1000;
ingress_stats.min_interval = min(interval_us, ingress_stats.min_interval);
......@@ -192,13 +182,12 @@ int main(int argc, char *argv[]) {
// Process bash options
process_options(argc, argv);
ingress_params.use_histograms = enable_histograms;
ingress_params.use_timestamps = enable_timestamps;
if (enable_histograms) {
// Init histograms
memset(kernel_latency_hist, 0, MAX_LATENCY_VAL);
memset(jitter_hist, 0, MAX_JITTER_VAL);
memset(kernel_latency_hist, 0, MAX_KERNEL_LATENCY);
memset(jitter_hist, 0, MAX_JITTER);
}
// Catch breaks with sighand to print the histograms
......@@ -213,6 +202,7 @@ int main(int argc, char *argv[]) {
// Initialize the UDP packet sending socket if RTT is measured
if (tsn_task == RTT_TASK)
init_udp_send(&egress_params,
&egress_stats,
0,
NULL);
......@@ -228,7 +218,7 @@ int main(int argc, char *argv[]) {
if (tsn_task == RECV_PACKET_TASK) {
int jitter = ingress_stats->max_interval - ingress_stats->min_interval;
int jitter = ingress_stats.max_interval - ingress_stats.min_interval;
printf("%10d: J: %4d, I: %4d %4d %4d",
ingress_stats.packets_received,
......@@ -240,9 +230,11 @@ int main(int argc, char *argv[]) {
if (enable_timestamps) {
printf(", K: %4d %4d %4d, D: %5s, L: %4d\n",
kernel_space_time,
stats->packet_info.data,
stats->lost_packets);
ingress_stats.min_kernel_latency,
ingress_stats.avg_kernel_latency,
ingress_stats.max_kernel_latency,
ingress_stats.data,
ingress_stats.lost_packets);
} else {
printf("\n");
}
......@@ -258,7 +250,7 @@ static void print_histograms() {
uint64_t duration;
int duration_hour, duration_minutes, interval;
int max_hist_val, min_hist_val;
int max_latency, min_latency, max_jitter, min_jitter;
clock_gettime(CLOCK_MONOTONIC, &measures_end);
......@@ -331,8 +323,8 @@ static void sighand(int sig_num) {
print_histograms();
if (stats.lost_packets)
fprintf(stderr, "%d packets were lost\n", stats.lost_packets);
if (ingress_stats.lost_packets)
fprintf(stderr, "%d packets were lost\n", ingress_stats.lost_packets);
exit(EXIT_SUCCESS);
}
......@@ -354,7 +346,7 @@ static void process_options(int argc, char *argv[]) {
break;
case 'b':
tsn_task = RTT_TASK;
strcpy(ingress_params.ip_address, optarg);
strcpy(egress_params.server_ip, optarg);
break;
case 'd':
ingress_params.tx_buffer_len = atoi(optarg);
......
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