Commit 6c2dd397 authored by Joanne Hugé's avatar Joanne Hugé

Add option to send packets to two servers

parent 7a42d58b
...@@ -81,16 +81,27 @@ static uint64_t rtt_hist[MAX_RTT]; ...@@ -81,16 +81,27 @@ static uint64_t rtt_hist[MAX_RTT];
static uint64_t nb_cycles; static uint64_t nb_cycles;
static main_param_t main_params; static main_param_t main_params;
static thread_param_t thread_params; static thread_param_t thread_params;
static egress_param_t egress_params;
static ingress_param_t ingress_params; static ingress_param_t ingress_params;
static rtt_stat_t rtt_stats = {.min_rtt = INT_MAX}; static rtt_stat_t rtt_stats = {.min_rtt = INT_MAX};
static egress_stat_t egress_stats = {.min_kernel_latency = INT_MAX,
static egress_param_t egress_params;
static egress_param_t egress_params2;
static egress_stat_t egress_stats = {.packets_sent = 0,
.min_kernel_latency = INT_MAX,
.min_interval = INT_MAX}; .min_interval = INT_MAX};
static egress_stat_t egress_stats2 = {.packets_sent = 0,
.min_kernel_latency = INT_MAX,
.min_interval = INT_MAX};
static ingress_stat_t ingress_stats = {.min_kernel_latency = INT_MAX, static ingress_stat_t ingress_stats = {.min_kernel_latency = INT_MAX,
.min_interval = INT_MAX}; .min_interval = INT_MAX};
static egress_info_t egress_info;
static egress_info_t egress_info2;
static int enable_histograms; static int enable_histograms;
static int enable_etf; static int enable_etf;
static int enable_timestamps; static int enable_timestamps;
static int two_servers = 0;
static enum TSNTask tsn_task; static enum TSNTask tsn_task;
static struct timespec measures_start; static struct timespec measures_start;
static struct timespec measures_end; static struct timespec measures_end;
...@@ -99,7 +110,7 @@ static char send_data[MAX_BUFFER_SIZE]; ...@@ -99,7 +110,7 @@ static char send_data[MAX_BUFFER_SIZE];
static void help(char *argv[]) { static void help(char *argv[]) {
printf( printf(
"Usage: %s [-a CPU -p PRIO -i USEC -r USEC -l N] [-d BUF_LEN | -c " "Usage: %s [-a CPU -p PRIO -i USEC -r USEC -l N] [-d BUF_LEN | -c "
"DELAY -s NS] [-b -e OFFSET -q PK_PRIO -gtvT] IF IP\n\n" "DELAY -s NS] [-b -e OFFSET -q PK_PRIO -gtvT] IF IP IF2 IP2\n\n"
" -h Show help\n" " -h Show help\n"
" -f IF Set the network interface to be used\n" " -f IF Set the network interface to be used\n"
" -a CPU Pin the real time thread to CPU\n" " -a CPU Pin the real time thread to CPU\n"
...@@ -173,10 +184,12 @@ static void *packet_sending_thread(void *p) { ...@@ -173,10 +184,12 @@ static void *packet_sending_thread(void *p) {
if (thread_params.start_ts) { if (thread_params.start_ts) {
if (thread_params.start_ts < ts_to_uint(next)) { if (thread_params.start_ts < ts_to_uint(next)) {
fprintf(stderr, "start timestamp is in the past, aborting...\n"); fprintf(stderr, "start timestamp is in the past, aborting...\n");
fflush(stdout);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (thread_params.start_ts > (ts_to_uint(next) + UINT64_C(3600000000000))) { if (thread_params.start_ts > (ts_to_uint(next) + UINT64_C(3600000000000))) {
fprintf(stderr, "start timestamp is too high, aborting...\n"); fprintf(stderr, "start timestamp is too high, aborting...\n");
fflush(stdout);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
next = uint_to_ts(thread_params.start_ts); next = uint_to_ts(thread_params.start_ts);
...@@ -353,6 +366,8 @@ int main(int argc, char *argv[]) { ...@@ -353,6 +366,8 @@ int main(int argc, char *argv[]) {
main_params.interval_input = 0; main_params.interval_input = 0;
egress_params.packet_priority = 3; egress_params.packet_priority = 3;
egress_params.tx_buffer_len = 1024; egress_params.tx_buffer_len = 1024;
egress_params2.packet_priority = 3;
egress_params2.tx_buffer_len = 1024;
enable_etf = 0; enable_etf = 0;
enable_timestamps = 0; enable_timestamps = 0;
enable_histograms = 0; enable_histograms = 0;
...@@ -368,10 +383,20 @@ int main(int argc, char *argv[]) { ...@@ -368,10 +383,20 @@ int main(int argc, char *argv[]) {
// Process bash options // Process bash options
process_options(argc, argv); process_options(argc, argv);
main_params.target_interval = thread_params.interval / 1000;
set_latency_target(); set_latency_target();
egress_params.use_etf = enable_etf; egress_params.use_etf = enable_etf;
egress_params.use_timestamps = enable_timestamps; egress_params.use_timestamps = enable_timestamps;
egress_params2.use_etf = enable_etf;
egress_params2.use_timestamps = enable_timestamps;
egress_info.params = &egress_params;
egress_info.stats = &egress_stats;
egress_info.stats->kernel_latency_hist = kernel_latency_hist;
egress_info2.params = &egress_params2;
egress_info2.stats = &egress_stats2;
if (enable_histograms) { if (enable_histograms) {
// Init histograms // Init histograms
...@@ -388,8 +413,9 @@ int main(int argc, char *argv[]) { ...@@ -388,8 +413,9 @@ int main(int argc, char *argv[]) {
init_signals(sighand); init_signals(sighand);
// Initialize the UDP packet sending socket // Initialize the UDP packet sending socket
init_udp_send(&egress_params, &egress_stats, enable_histograms, init_udp_send(&egress_info, enable_histograms, thread_params.enable_etf_tracing);
thread_params.enable_etf_tracing, kernel_latency_hist); if(two_servers)
init_udp_send(&egress_info2, enable_histograms, thread_params.enable_etf_tracing);
// Initialize the UDP packet receiving socket if RTT is measured // Initialize the UDP packet receiving socket if RTT is measured
if (tsn_task == RTT_TASK) if (tsn_task == RTT_TASK)
...@@ -489,12 +515,14 @@ static void do_tsn_task(char *data, uint64_t next_txtime) { ...@@ -489,12 +515,14 @@ static void do_tsn_task(char *data, uint64_t next_txtime) {
// One way packet sending // One way packet sending
if (tsn_task == SEND_PACKET_TASK) { if (tsn_task == SEND_PACKET_TASK) {
send_udp_packet(data, next_txtime); send_udp_packet(data, next_txtime, &egress_info);
if(two_servers)
send_udp_packet(data, next_txtime, &egress_info2);
// Round Trip Time measurement // Round Trip Time measurement
} else if (tsn_task == RTT_TASK) { } else if (tsn_task == RTT_TASK) {
clock_gettime(CLOCK_MONOTONIC, &t1); clock_gettime(CLOCK_MONOTONIC, &t1);
send_udp_packet(data, next_txtime); send_udp_packet(data, next_txtime, &egress_info);
recv_udp_packet(); recv_udp_packet();
clock_gettime(CLOCK_MONOTONIC, &t2); clock_gettime(CLOCK_MONOTONIC, &t2);
...@@ -634,15 +662,21 @@ static void process_options(int argc, char *argv[]) { ...@@ -634,15 +662,21 @@ static void process_options(int argc, char *argv[]) {
} }
} }
if (argc != optind + 2) { if (argc != optind + 2 && argc != optind + 4) {
if (argc < optind + 2) if (argc < optind + 2)
fprintf(stderr, "You need to specifiy an interface and IP address\n"); fprintf(stderr, "You need to specifiy an interface and IP address\n");
else else
fprintf(stderr, "Too many arguments\n"); fprintf(stderr, "Wrong number of arguments");
help(argv); help(argv);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
strcpy(egress_params.network_if, argv[optind]); strcpy(egress_params.network_if, argv[optind]);
strcpy(egress_params.server_ip, argv[optind + 1]); strcpy(egress_params.server_ip, argv[optind + 1]);
if (argc == optind + 4) {
two_servers = 1;
strcpy(egress_params2.network_if, argv[optind + 2]);
strcpy(egress_params2.server_ip, argv[optind + 3]);
}
} }
...@@ -40,76 +40,67 @@ ...@@ -40,76 +40,67 @@
#include "tracer.h" #include "tracer.h"
static void *poll_thread(void *p); static void *poll_thread(void *p);
static void process_error_queue(); static void process_error_queue(egress_info_t * info);
static void init_tx_buffer(); static void init_tx_buffer(egress_info_t * info);
static int set_if(); static int set_if(egress_info_t * info);
static int so_timestamping_flags = static int so_timestamping_flags =
SOF_TIMESTAMPING_TX_SOFTWARE | SOF_TIMESTAMPING_SOFTWARE; SOF_TIMESTAMPING_TX_SOFTWARE | SOF_TIMESTAMPING_SOFTWARE;
static egress_param_t *params;
static egress_stat_t *stats;
static uint64_t *kernel_latency_hist;
static int use_histogram; static int use_histogram;
static int stop_tracing; static int stop_tracing;
static uint64_t packets_sent = 0;
static struct sock_txtime sk_txtime;
static char *tx_buffer;
static int sock_fd;
static int64_t timestamps_buffer[TIMESTAMP_BUFFER_SIZE];
static int ts_buf_read_index = 0;
static int ts_buf_write_index = 0;
/* /*
* Init UDP socket * Init UDP socket
*/ */
void init_udp_send(egress_param_t *_params, egress_stat_t *_stats, void init_udp_send(egress_info_t *info, int _use_histogram, int _stop_tracing) {
int _use_histogram, int _stop_tracing, uint64_t *_kernel_latency_hist) {
int set_if_err; int set_if_err;
pthread_t thread; pthread_t thread;
params = _params; egress_param_t *params = info->params;
stats = _stats; egress_stat_t *stats = info->stats;
kernel_latency_hist = _kernel_latency_hist;
stats->packets_sent = 0;
stats->ts_buf_read_index = 0;
stats->ts_buf_write_index = 0;
use_histogram = _use_histogram; use_histogram = _use_histogram;
stop_tracing = _stop_tracing; stop_tracing = _stop_tracing;
init_tx_buffer(); init_tx_buffer(info);
sock_fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); info->sock_fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (sock_fd < 0) error(EXIT_FAILURE, errno, "Socket creation failed\n"); if (info->sock_fd < 0) error(EXIT_FAILURE, errno, "Socket creation failed\n");
set_if_err = set_if(); set_if_err = set_if(info);
if (set_if_err < 0) error(EXIT_FAILURE, errno, "Couldn't set interface\n"); if (set_if_err < 0) error(EXIT_FAILURE, errno, "Couldn't set interface\n");
if (setsockopt(sock_fd, SOL_SOCKET, SO_PRIORITY, &params->packet_priority, if (setsockopt(info->sock_fd, SOL_SOCKET, SO_PRIORITY, &params->packet_priority,
sizeof(params->packet_priority))) sizeof(params->packet_priority)))
error(EXIT_FAILURE, errno, "Couldn't set socket priority\n"); error(EXIT_FAILURE, errno, "Couldn't set socket priority\n");
if (setsockopt(sock_fd, SOL_SOCKET, SO_BINDTODEVICE, params->network_if, if (setsockopt(info->sock_fd, SOL_SOCKET, SO_BINDTODEVICE, params->network_if,
strlen(params->network_if))) strlen(params->network_if)))
error(EXIT_FAILURE, errno, "setsockopt SO_BINDTODEVICE failed\n"); error(EXIT_FAILURE, errno, "setsockopt SO_BINDTODEVICE failed\n");
if (params->use_etf) { if (params->use_etf) {
sk_txtime.clockid = CLOCK_REALTIME; info->sk_txtime.clockid = CLOCK_REALTIME;
sk_txtime.flags = SOF_TXTIME_REPORT_ERRORS; info->sk_txtime.flags = SOF_TXTIME_REPORT_ERRORS;
if (setsockopt(sock_fd, SOL_SOCKET, SO_TXTIME, &sk_txtime, if (setsockopt(info->sock_fd, SOL_SOCKET, SO_TXTIME, &info->sk_txtime,
sizeof(sk_txtime))) sizeof(info->sk_txtime)))
error(EXIT_FAILURE, errno, "setsockopt SO_TXTIME failed\n"); error(EXIT_FAILURE, errno, "setsockopt SO_TXTIME failed\n");
} }
if (params->use_timestamps) { if (params->use_timestamps) {
if (setsockopt(sock_fd, SOL_SOCKET, SO_TIMESTAMPING, &so_timestamping_flags, if (setsockopt(info->sock_fd, SOL_SOCKET, SO_TIMESTAMPING, &so_timestamping_flags,
sizeof(so_timestamping_flags))) sizeof(so_timestamping_flags)))
error(EXIT_FAILURE, errno, "setsockopt SO_TIMESTAMPING failed\n"); error(EXIT_FAILURE, errno, "setsockopt SO_TIMESTAMPING failed\n");
} }
// Create poll thread // Create poll thread
if (pthread_create(&thread, NULL, poll_thread, NULL)) if (pthread_create(&thread, NULL, poll_thread, info))
error(EXIT_FAILURE, errno, "Couldn't create poll thread"); error(EXIT_FAILURE, errno, "Couldn't create poll thread");
} }
...@@ -117,7 +108,7 @@ void init_udp_send(egress_param_t *_params, egress_stat_t *_stats, ...@@ -117,7 +108,7 @@ void init_udp_send(egress_param_t *_params, egress_stat_t *_stats,
/* /*
* Sends udp packets * Sends udp packets
*/ */
void send_udp_packet(char *data, uint64_t txtime) { void send_udp_packet(char *data, uint64_t txtime, egress_info_t * info) {
struct msghdr msg; // Message hardware, sent to the socket struct msghdr msg; // Message hardware, sent to the socket
struct cmsghdr *cmsg; // Control message hardware, for txtime struct cmsghdr *cmsg; // Control message hardware, for txtime
char control[CMSG_SPACE(sizeof(txtime))] = {}; // Stores txtime char control[CMSG_SPACE(sizeof(txtime))] = {}; // Stores txtime
...@@ -126,23 +117,26 @@ void send_udp_packet(char *data, uint64_t txtime) { ...@@ -126,23 +117,26 @@ void send_udp_packet(char *data, uint64_t txtime) {
struct sockaddr_in sin; // Server address struct sockaddr_in sin; // Server address
struct timespec ts; // timestamp for userspace timestamping struct timespec ts; // timestamp for userspace timestamping
egress_param_t *params = info->params;
egress_stat_t *stats = info->stats;
if (params->use_timestamps) { if (params->use_timestamps) {
clock_gettime(CLOCK_REALTIME, &ts); clock_gettime(CLOCK_REALTIME, &ts);
timestamps_buffer[ts_buf_write_index] = ts_to_uint(ts); stats->timestamps_buffer[stats->ts_buf_write_index] = ts_to_uint(ts);
ts_buf_write_index = (ts_buf_write_index + 1) % TIMESTAMP_BUFFER_SIZE; stats->ts_buf_write_index = (stats->ts_buf_write_index + 1) % TIMESTAMP_BUFFER_SIZE;
} }
packets_sent++; stats->packets_sent++;
for(int i = 0; i < (int)params->tx_buffer_len; i++) for(int i = 0; i < (int)params->tx_buffer_len; i++)
tx_buffer[i] = data[i]; info->tx_buffer[i] = data[i];
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(params->server_ip); sin.sin_addr.s_addr = inet_addr(params->server_ip);
sin.sin_port = htons(SERVER_PORT_INT); sin.sin_port = htons(SERVER_PORT_INT);
iov.iov_base = tx_buffer; iov.iov_base = info->tx_buffer;
iov.iov_len = params->tx_buffer_len; iov.iov_len = params->tx_buffer_len;
memset(&msg, 0, sizeof(msg)); memset(&msg, 0, sizeof(msg));
...@@ -164,29 +158,31 @@ void send_udp_packet(char *data, uint64_t txtime) { ...@@ -164,29 +158,31 @@ void send_udp_packet(char *data, uint64_t txtime) {
msg.msg_controllen = cmsg->cmsg_len; msg.msg_controllen = cmsg->cmsg_len;
} }
sendmsgerr = sendmsg(sock_fd, &msg, 0); sendmsgerr = sendmsg(info->sock_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);
} }
static void *poll_thread(void *p) { static void *poll_thread(void *p) {
(void)p; egress_info_t * info = (egress_info_t *) p;
// Poll file descriptor // Poll file descriptor
struct pollfd poll_fd = {.fd = sock_fd}; struct pollfd poll_fd = {.fd = info->sock_fd};
while (1) { while (1) {
int ret; int ret;
ret = poll(&poll_fd, 1, -1); ret = poll(&poll_fd, 1, -1);
if (ret == 1 && poll_fd.revents & POLLERR) { if (ret == 1 && poll_fd.revents & POLLERR) {
process_error_queue(); process_error_queue(info);
} }
} }
return NULL; return NULL;
} }
static void process_error_queue() { static void process_error_queue(egress_info_t * info) {
int recv_ret; int recv_ret;
// IO vector // IO vector
...@@ -206,8 +202,11 @@ static void process_error_queue() { ...@@ -206,8 +202,11 @@ static void process_error_queue() {
struct cmsghdr *cmsg; struct cmsghdr *cmsg;
egress_stat_t *stats = info->stats;
// Timestamps and errors are received in the error queue // Timestamps and errors are received in the error queue
recv_ret = recvmsg(sock_fd, &msg, MSG_ERRQUEUE | MSG_DONTWAIT); recv_ret = recvmsg(info->sock_fd, &msg, MSG_ERRQUEUE | MSG_DONTWAIT);
if (recv_ret == -1) { if (recv_ret == -1) {
fprintf(stderr, "recvmsg() failed\n"); fprintf(stderr, "recvmsg() failed\n");
return; return;
...@@ -219,22 +218,22 @@ static void process_error_queue() { ...@@ -219,22 +218,22 @@ static void process_error_queue() {
struct timespec *stamp = (struct timespec *)CMSG_DATA(cmsg); struct timespec *stamp = (struct timespec *)CMSG_DATA(cmsg);
int kernel_latency = int kernel_latency =
(ts_to_uint(*stamp) - timestamps_buffer[ts_buf_read_index]) / 1000; (ts_to_uint(*stamp) - stats->timestamps_buffer[stats->ts_buf_read_index]) / 1000;
ts_buf_read_index = (ts_buf_read_index + 1) % TIMESTAMP_BUFFER_SIZE; stats->ts_buf_read_index = (stats->ts_buf_read_index + 1) % TIMESTAMP_BUFFER_SIZE;
stats->min_kernel_latency = stats->min_kernel_latency =
_min_(kernel_latency, stats->min_kernel_latency); _min_(kernel_latency, stats->min_kernel_latency);
stats->max_kernel_latency = stats->max_kernel_latency =
_max_(kernel_latency, stats->max_kernel_latency); _max_(kernel_latency, stats->max_kernel_latency);
stats->avg_kernel_latency = stats->avg_kernel_latency =
(stats->max_kernel_latency * packets_sent + kernel_latency) / (stats->max_kernel_latency * stats->packets_sent + kernel_latency) /
(packets_sent + 1); (stats->packets_sent + 1);
if (use_histogram) { if (use_histogram) {
if (kernel_latency > MAX_KERNEL_LATENCY) if (kernel_latency > MAX_KERNEL_LATENCY)
stats->high_kernel_latency++; stats->high_kernel_latency++;
else else
kernel_latency_hist[kernel_latency]++; stats->kernel_latency_hist[kernel_latency]++;
} }
} }
...@@ -264,24 +263,29 @@ static void process_error_queue() { ...@@ -264,24 +263,29 @@ static void process_error_queue() {
} }
// Sets the interface // Sets the interface
static int set_if() { static int set_if(egress_info_t * info) {
struct ifreq ifreq; struct ifreq ifreq;
egress_param_t * params = info->params;
memset(&ifreq, 0, sizeof(ifreq)); memset(&ifreq, 0, sizeof(ifreq));
strncpy(ifreq.ifr_name, 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)) if (ioctl(info->sock_fd, SIOCGIFINDEX, &ifreq))
error(EXIT_FAILURE, errno, "ioctl SIOCGIFINDEX failed\n"); error(EXIT_FAILURE, errno, "ioctl SIOCGIFINDEX failed\n");
return ifreq.ifr_ifindex; return ifreq.ifr_ifindex;
} }
static void init_tx_buffer() { static void init_tx_buffer(egress_info_t * info) {
egress_param_t * params = info->params;
if (params->tx_buffer_len < 1) { if (params->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);
} }
tx_buffer = malloc(params->tx_buffer_len); info->tx_buffer = malloc(params->tx_buffer_len);
} }
#ifndef SEND_PACKET_H #ifndef SEND_PACKET_H
#define SEND_PACKET_H #define SEND_PACKET_H
#include <arpa/inet.h>
#include <errno.h>
#include <error.h>
#include <fcntl.h>
#include <ifaddrs.h>
#include <inttypes.h>
#include <linux/errqueue.h>
#include <linux/ethtool.h>
#include <linux/net_tstamp.h>
#include <linux/sockios.h>
#include <net/if.h>
#include <netdb.h>
#include <netinet/in.h>
#include <poll.h>
#include <pthread.h>
#include <sched.h>
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include "common.h" #include "common.h"
typedef struct egress_param { typedef struct egress_param {
...@@ -16,6 +43,8 @@ typedef struct egress_param { ...@@ -16,6 +43,8 @@ typedef struct egress_param {
typedef struct egress_stat { typedef struct egress_stat {
uint64_t packets_sent;
uint64_t high_kernel_latency; uint64_t high_kernel_latency;
uint64_t invalid_parameter; uint64_t invalid_parameter;
uint64_t missed_deadline; uint64_t missed_deadline;
...@@ -28,13 +57,27 @@ typedef struct egress_stat { ...@@ -28,13 +57,27 @@ typedef struct egress_stat {
int avg_interval; int avg_interval;
int max_interval; int max_interval;
int ts_buf_read_index;
int ts_buf_write_index;
uint64_t *kernel_latency_hist;
int64_t timestamps_buffer[TIMESTAMP_BUFFER_SIZE];
} egress_stat_t; } egress_stat_t;
void init_udp_send(egress_param_t *_params, typedef struct egress_info {
egress_stat_t *_stats,
int _use_histogram, int _stop_tracing, int sock_fd;
uint64_t *_kernel_latency_hist);
struct sock_txtime sk_txtime;
char *tx_buffer;
egress_param_t *params;
egress_stat_t *stats;
} egress_info_t;
void send_udp_packet(char *data, uint64_t txtime); void init_udp_send(egress_info_t *info, int _use_histogram, int _stop_tracing);
void send_udp_packet(char *data, uint64_t txtime, egress_info_t * info);
#endif #endif
...@@ -71,6 +71,7 @@ static thread_param_t thread_params; ...@@ -71,6 +71,7 @@ static thread_param_t thread_params;
static ingress_param_t ingress_params; static ingress_param_t ingress_params;
static egress_param_t egress_params; static egress_param_t egress_params;
static egress_stat_t egress_stats = {.min_kernel_latency = INT_MAX}; static egress_stat_t egress_stats = {.min_kernel_latency = INT_MAX};
static egress_info_t egress_info;
static ingress_stat_t ingress_stats = {.min_kernel_latency = INT_MAX, static ingress_stat_t ingress_stats = {.min_kernel_latency = INT_MAX,
.min_interval = INT_MAX}; .min_interval = INT_MAX};
static int enable_histograms; static int enable_histograms;
...@@ -151,24 +152,24 @@ static void *emit_signal_thread(void *p) { ...@@ -151,24 +152,24 @@ static void *emit_signal_thread(void *p) {
clock_gettime(CLOCK_REALTIME, &current); clock_gettime(CLOCK_REALTIME, &current);
// Check if something went wrong // Check if something went wrong
if(i > 0) { //if(i > 0) {
emit_diff = calcdiff_ns_signed(current, previous_emit); // emit_diff = calcdiff_ns_signed(current, previous_emit);
ts_diff = calcdiff_ns_signed(emit_signal_next, previous_ts); // ts_diff = calcdiff_ns_signed(emit_signal_next, previous_ts);
if((emit_diff < ((int64_t)thread_params.interval) - ERROR_MARGIN_NS) || // if((emit_diff < ((int64_t)thread_params.interval) - ERROR_MARGIN_NS) ||
(emit_diff > ((int64_t)thread_params.interval) + ERROR_MARGIN_NS)) { // (emit_diff > ((int64_t)thread_params.interval) + ERROR_MARGIN_NS)) {
fprintf(stderr, "Signal emission interval reached error threshold: %" PRIi64 "\n", emit_diff); // fprintf(stderr, "Signal emission interval reached error threshold: %" PRIi64 "\n", emit_diff);
latency_spike = 1; // latency_spike = 1;
} // }
if((ts_diff < ((int64_t)thread_params.interval) - ERROR_MARGIN_NS) || // if((ts_diff < ((int64_t)thread_params.interval) - ERROR_MARGIN_NS) ||
(ts_diff > ((int64_t)thread_params.interval) + ERROR_MARGIN_NS)) { // (ts_diff > ((int64_t)thread_params.interval) + ERROR_MARGIN_NS)) {
fprintf(stderr, "Timestamp interval reached error threshold: %" PRIi64 "\n", ts_diff); // fprintf(stderr, "Timestamp interval reached error threshold: %" PRIi64 "\n", ts_diff);
latency_spike = 1; // latency_spike = 1;
} // }
if(latency_spike) { // if(latency_spike) {
fprintf(stderr, "Exiting... Current interval: %d\n", interval_us); // fprintf(stderr, "Exiting... Current interval: %d\n", interval_us);
exit(EXIT_FAILURE); // exit(EXIT_FAILURE);
} // }
} //}
previous_emit = current; previous_emit = current;
previous_ts = emit_signal_next; previous_ts = emit_signal_next;
} }
...@@ -221,7 +222,7 @@ static void *tsn_thread(void *p) { ...@@ -221,7 +222,7 @@ static void *tsn_thread(void *p) {
// RTT // RTT
if (tsn_task == RTT_TASK) { if (tsn_task == RTT_TASK) {
recv_udp_packet(); recv_udp_packet();
send_udp_packet("", 0); send_udp_packet("", 0, &egress_info);
// Receive packet // Receive packet
} else if (tsn_task == RECV_PACKET_TASK || tsn_task == XDP_TASK) { } else if (tsn_task == RECV_PACKET_TASK || tsn_task == XDP_TASK) {
...@@ -413,6 +414,9 @@ int main(int argc, char *argv[]) { ...@@ -413,6 +414,9 @@ int main(int argc, char *argv[]) {
ingress_params.use_timestamps = enable_timestamps; ingress_params.use_timestamps = enable_timestamps;
ingress_params.interval = thread_params.interval; ingress_params.interval = thread_params.interval;
egress_info.params = &egress_params;
egress_info.stats = &egress_stats;
// Init histograms // Init histograms
if (enable_histograms) { if (enable_histograms) {
memset(kernel_latency_hist, 0, sizeof(kernel_latency_hist)); memset(kernel_latency_hist, 0, sizeof(kernel_latency_hist));
...@@ -435,7 +439,7 @@ int main(int argc, char *argv[]) { ...@@ -435,7 +439,7 @@ int main(int argc, char *argv[]) {
// Initialize the UDP packet sending socket if RTT is measured // Initialize the UDP packet sending socket if RTT is measured
if (tsn_task == RTT_TASK) if (tsn_task == RTT_TASK)
init_udp_send(&egress_params, &egress_stats, 0, 0, NULL); init_udp_send(&egress_info, 0, 0);
if (thread_params.emit_signal) { if (thread_params.emit_signal) {
pthread_mutex_init(&emit_signal_mutex, NULL); pthread_mutex_init(&emit_signal_mutex, NULL);
......
...@@ -4,7 +4,7 @@ script_dir=$(dirname $(realpath $0)) ...@@ -4,7 +4,7 @@ script_dir=$(dirname $(realpath $0))
usage() { usage() {
cat << ENDUSAGE cat << ENDUSAGE
Usage: $0 [-h] QDISC_OPT [CLIENT_OPTS] BOARD_HOSTNAME Usage: $0 [-h] QDISC_OPT [CLIENT_OPTS] IF BOARD_HOSTNAME [IF2 BOARD_HOSTNAME2]
-h Show help -h Show help
QDISC_OPTS: [-e DELTA [-o USEC] -H] [-q] QDISC_OPTS: [-e DELTA [-o USEC] -H] [-q]
Which qdisc to use (will call create-qdisc script) Which qdisc to use (will call create-qdisc script)
...@@ -24,8 +24,8 @@ Usage: $0 [-h] QDISC_OPT [CLIENT_OPTS] BOARD_HOSTNAME ...@@ -24,8 +24,8 @@ Usage: $0 [-h] QDISC_OPT [CLIENT_OPTS] BOARD_HOSTNAME
(to be used with PTP) (to be used with PTP)
-d TX_BUF_LEN Length of the data sent in the packets -d TX_BUF_LEN Length of the data sent in the packets
-i USEC Interval at which the RT thread should send packets -i USEC Interval at which the RT thread should send packets
-I IF Network interface to use to send the packets
-a CPU CPU on which to pin the program -a CPU CPU on which to pin the program
-U Interactive interval change
TRACE_OPTS: -T [-P TRACER -E EVENTS -B SIZE] TRACE_OPTS: -T [-P TRACER -E EVENTS -B SIZE]
Options to trace with trace-cmd until ETF deadline is missed Options to trace with trace-cmd until ETF deadline is missed
(see trace-cmd man page and ftrace documentation) (see trace-cmd man page and ftrace documentation)
...@@ -56,7 +56,7 @@ etf_offset=500 ...@@ -56,7 +56,7 @@ etf_offset=500
tracecmd_events="-e irq -e sched -e net_dev_start_xmit -e net_dev_xmit -e net_dev_xmit_timeout" tracecmd_events="-e irq -e sched -e net_dev_start_xmit -e net_dev_xmit -e net_dev_xmit_timeout"
tracecmd_opts="" tracecmd_opts=""
while getopts "a:bc:d:e:o:ghi:qs:tB:E:I:HP:TS:" opt; do while getopts "a:bc:d:e:o:ghi:qs:tB:E:I:HP:TS:U:" opt; do
case "${opt}" in case "${opt}" in
h ) h )
usage usage
...@@ -106,9 +106,6 @@ while getopts "a:bc:d:e:o:ghi:qs:tB:E:I:HP:TS:" opt; do ...@@ -106,9 +106,6 @@ while getopts "a:bc:d:e:o:ghi:qs:tB:E:I:HP:TS:" opt; do
E ) E )
tracecmd_events=${OPTARG} tracecmd_events=${OPTARG}
;; ;;
I )
interface="${OPTARG}"
;;
H ) H )
qdisc_options+=" -H" qdisc_options+=" -H"
;; ;;
...@@ -123,20 +120,37 @@ while getopts "a:bc:d:e:o:ghi:qs:tB:E:I:HP:TS:" opt; do ...@@ -123,20 +120,37 @@ while getopts "a:bc:d:e:o:ghi:qs:tB:E:I:HP:TS:" opt; do
use_tracer=1 use_tracer=1
client_options+=" -S ${OPTARG}" client_options+=" -S ${OPTARG}"
;; ;;
U )
client_options+=" -U ${OPTARG}"
;;
* ) * )
usage usage
;; ;;
esac esac
done done
shift $((OPTIND-1)) shift $((OPTIND-1))
if [ -z "$1" ]; then
usage
fi
qdisc_options+=" -I $interface" qdisc_options+=" -I $interface"
client_options+=" -a $cpu" client_options+=" -a $cpu"
board_name=$1
if [ -z "$1" ] || [ -z "$2" ]; then
usage
fi
board_name=$2
board_ip=$(cat /etc/hosts | grep $board_name | awk '{print $1}') board_ip=$(cat /etc/hosts | grep $board_name | awk '{print $1}')
interface=$1
board2_ip=""
interface2=""
if [ -n "$3" ]; then
if [ -z "$4" ]; then
usage
fi
interface2=$3
board2_name=$4
board2_ip=$(cat /etc/hosts | grep $board2_name | awk '{print $1}')
fi
if [ -z "${use_histogram}" ]; then if [ -z "${use_histogram}" ]; then
client_options+=" -v" client_options+=" -v"
...@@ -174,18 +188,18 @@ cd $script_dir; ...@@ -174,18 +188,18 @@ cd $script_dir;
if [ -n "${use_histogram}" ]; then if [ -n "${use_histogram}" ]; then
echo "client $client_options $interface $board_ip > $output;mv $output ~/"; echo "client $client_options $interface $board_ip $interface2 $board2_ip > $output;mv $output ~/";
$script_dir/../packet-exchange/build/client $client_options $interface $board_ip > $output; $script_dir/../packet-exchange/build/client $client_options $interface $board_ip $interface2 $board2_ip > $output;
mv $output ~/; mv $output ~/;
elif [ -n "${use_tracer}" ]; then elif [ -n "${use_tracer}" ]; then
echo "trace-cmd record $tracecmd_opts $tracecmd_events ./client $client_options $interface $board_ip"; echo "trace-cmd record $tracecmd_opts $tracecmd_events ./client $client_options $interface $board_ip $interface2 $board2_ip";
trace-cmd record $tracecmd_opts $tracecmd_events $script_dir/../packet-exchange/build/client $client_options $interface $board_ip; trace-cmd record $tracecmd_opts $tracecmd_events $script_dir/../packet-exchange/build/client $client_options $interface $board_ip $interface2 $board2_ip;
else else
echo "client $client_options $interface $board_ip"; echo "client $client_options $interface $board_ip $interface2 $board2_ip";
$script_dir/../packet-exchange/build/client $client_options $interface $board_ip; $script_dir/../packet-exchange/build/client $client_options $interface $board_ip $interface2 $board2_ip;
fi fi
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