Commit a05737a7 authored by Joanne Hugé's avatar Joanne Hugé

Merge branch 'packet-exchange' into dev

parents d3203589 d495022a
...@@ -6,11 +6,13 @@ SERVER_SRCS = server.c ...@@ -6,11 +6,13 @@ SERVER_SRCS = server.c
SERVER_SRCS += recv_packet.c SERVER_SRCS += recv_packet.c
SERVER_SRCS += send_packet.c SERVER_SRCS += send_packet.c
SERVER_SRCS += common.c SERVER_SRCS += common.c
SERVER_SRCS += tracer.c
CLIENT_SRCS = client.c CLIENT_SRCS = client.c
CLIENT_SRCS += recv_packet.c CLIENT_SRCS += recv_packet.c
CLIENT_SRCS += send_packet.c CLIENT_SRCS += send_packet.c
CLIENT_SRCS += common.c CLIENT_SRCS += common.c
CLIENT_SRCS += tracer.c
SERVER_OBJS = $(SERVER_SRCS:%.c=%.o) SERVER_OBJS = $(SERVER_SRCS:%.c=%.o)
CLIENT_OBJS = $(CLIENT_SRCS:%.c=%.o) CLIENT_OBJS = $(CLIENT_SRCS:%.c=%.o)
......
...@@ -16,12 +16,14 @@ ...@@ -16,12 +16,14 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <sys/mman.h>
#include <time.h> #include <time.h>
#include <unistd.h> #include <unistd.h>
#include "common.h" #include "common.h"
#include "recv_packet.h" #include "recv_packet.h"
#include "send_packet.h" #include "send_packet.h"
#include "tracer.h"
// Structs // Structs
...@@ -39,12 +41,15 @@ typedef struct thread_param { ...@@ -39,12 +41,15 @@ typedef struct thread_param {
unsigned int max_cycles; unsigned int max_cycles;
int priority; int priority;
int etf_offset; int etf_offset;
uint64_t latency_threshold;
} thread_param_t; } thread_param_t;
typedef struct main_param { typedef struct main_param {
int refresh_rate; int refresh_rate;
int verbose; int verbose;
int enable_tracing;
int enable_graph;
} main_param_t; } main_param_t;
// Static functions // Static functions
...@@ -67,7 +72,8 @@ static egress_param_t egress_params; ...@@ -67,7 +72,8 @@ 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_stat_t egress_stats = {.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};
...@@ -85,35 +91,33 @@ static char send_data[MAX_BUFFER_SIZE]; ...@@ -85,35 +91,33 @@ static char send_data[MAX_BUFFER_SIZE];
static void help(char *argv[]) { static void help(char *argv[]) {
printf( printf(
"Usage: %s -f IF [-abthgv] [-e ETF_OFFSET] [-d BUF_LEN] [-i USEC] [-l " "Usage: %s -f IF [-abthgv] [-e ETF_OFFSET] [-d BUF_LEN] [-i USEC] [-l N]"
"N] [-p PRIO] [-q PACKET_PRIO] [-r USEC]\n\n", "[-p PRIO] [-q PACKET_PRIO] [-r USEC] [-T LATENCY_THRESHOLD -G]\n\n",
argv[0]); " -a Run the real time thread on CPU1\n"
printf(" -a Run the real time thread on CPU1\n"); " -b Measure RTT\n"
printf(" -b Measure RTT\n"); " -d BUF_LEN Set the length of tx buffer\n"
printf(" -d BUF_LEN Set the length of tx buffer\n");
printf(
" -e ETF_OFFSET Set a txtime with an offset of ETF_OFFSET " " -e ETF_OFFSET Set a txtime with an offset of ETF_OFFSET "
"us (to be used in an ETF qdisc)\n"); "us (to be used in an ETF qdisc)\n"
printf(" -f IF Set the network interface to be used\n"); " -f IF Set the network interface to be used\n"
printf(" -g Print histograms to sdtout on exit\n"); " -g Print histograms to sdtout on exit\n"
printf(" -h Show help\n"); " -h Show help\n"
printf(
" -i USEC Wake up the real time thread every USEC " " -i USEC Wake up the real time thread every USEC "
"microseconds (Default: 10ms)\n"); "microseconds (Default: 10ms)\n"
printf(
" -l N Wake up the real time thread N times " " -l N Wake up the real time thread N times "
"(Default: 0)\n"); "(Default: 0)\n"
printf(
" -p PRIO Run the real time thread at priority " " -p PRIO Run the real time thread at priority "
"PRIO\n"); "PRIO\n"
printf( " -q PACKET_PRIO Send packets with PACKET_PRIO priority\n"
" -q PACKET_PRIO Send packets with PACKET_PRIO priority\n");
printf(
" -r USEC Refresh the non real time main thread " " -r USEC Refresh the non real time main thread "
"every USEC microseconds (Default: 50ms)\n"); "every USEC microseconds (Default: 50ms)\n"
printf(" -t Enable timestamps\n"); " -t Enable timestamps\n"
printf(" -v Verbose\n"); " -v Verbose\n"
printf("\n"); " -T LATENCY_THRESHOLD Enable tracing until LATENCY_THRESHOLD is "
"reached\n"
" -G Enable function_graph tracer, used with "
"-T\n"
"\n",
argv[0]);
} }
/* /*
...@@ -121,9 +125,8 @@ static void help(char *argv[]) { ...@@ -121,9 +125,8 @@ static void help(char *argv[]) {
*/ */
static void *packet_sending_thread(void *p) { static void *packet_sending_thread(void *p) {
(void)p; (void)p;
struct timespec next; struct timespec next, current, previous;
uint64_t next_txtime; uint64_t next_txtime;
struct sched_param priority;
cpu_set_t mask; cpu_set_t mask;
// Set thread CPU affinity // Set thread CPU affinity
...@@ -134,11 +137,6 @@ static void *packet_sending_thread(void *p) { ...@@ -134,11 +137,6 @@ static void *packet_sending_thread(void *p) {
error(EXIT_FAILURE, errno, "Could not set CPU affinity to CPU #1\n"); error(EXIT_FAILURE, errno, "Could not set CPU affinity to CPU #1\n");
} }
// Set thread priority
priority.sched_priority = thread_params.priority;
if (sched_setscheduler(0, SCHED_FIFO, &priority))
error(EXIT_FAILURE, errno, "Couldn't set priority");
if (enable_etf) { if (enable_etf) {
// Measure from CLOCK_TAI to generate timestamp // Measure from CLOCK_TAI to generate timestamp
clock_gettime(CLOCK_TAI, &next); clock_gettime(CLOCK_TAI, &next);
...@@ -148,6 +146,9 @@ static void *packet_sending_thread(void *p) { ...@@ -148,6 +146,9 @@ static void *packet_sending_thread(void *p) {
next_txtime = 0; next_txtime = 0;
} }
// Start tracing
if (main_params.enable_tracing) tracing(1);
clock_gettime(CLOCK_MONOTONIC, &next); clock_gettime(CLOCK_MONOTONIC, &next);
clock_gettime(CLOCK_MONOTONIC, &measures_start); clock_gettime(CLOCK_MONOTONIC, &measures_start);
...@@ -157,6 +158,8 @@ static void *packet_sending_thread(void *p) { ...@@ -157,6 +158,8 @@ static void *packet_sending_thread(void *p) {
nb_cycles >= ((unsigned int)thread_params.max_cycles)) nb_cycles >= ((unsigned int)thread_params.max_cycles))
break; break;
clock_gettime(CLOCK_MONOTONIC, &current);
sprintf(send_data, "%d", (int)(nb_cycles % 1000)); sprintf(send_data, "%d", (int)(nb_cycles % 1000));
do_tsn_task(send_data, next_txtime); do_tsn_task(send_data, next_txtime);
...@@ -164,6 +167,25 @@ static void *packet_sending_thread(void *p) { ...@@ -164,6 +167,25 @@ static void *packet_sending_thread(void *p) {
if (enable_etf) next_txtime += thread_params.interval; if (enable_etf) next_txtime += thread_params.interval;
if (nb_cycles) {
int interval_us = calcdiff_ns(current, previous) / 1000;
egress_stats.min_interval = min(interval_us, egress_stats.min_interval);
egress_stats.max_interval = max(interval_us, egress_stats.max_interval);
egress_stats.avg_interval =
(egress_stats.avg_interval * nb_cycles + interval_us) /
(nb_cycles + 1);
}
// If the latency hits the tracing threshold, stop tracing
if (main_params.enable_tracing &&
(egress_stats.max_interval > thread_params.latency_threshold)) {
tracing(0);
break;
}
previous = current;
clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &next, NULL); clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &next, NULL);
} }
...@@ -176,6 +198,8 @@ static void *packet_sending_thread(void *p) { ...@@ -176,6 +198,8 @@ static void *packet_sending_thread(void *p) {
*/ */
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
pthread_t thread; pthread_t thread;
struct sched_param param;
pthread_attr_t attr;
// Default configuration values // Default configuration values
thread_params.interval = 100000 * 1000; thread_params.interval = 100000 * 1000;
...@@ -184,6 +208,8 @@ int main(int argc, char *argv[]) { ...@@ -184,6 +208,8 @@ int main(int argc, char *argv[]) {
main_params.refresh_rate = 50000; main_params.refresh_rate = 50000;
main_params.verbose = 0; main_params.verbose = 0;
main_params.enable_tracing = 0;
main_params.enable_graph = 0;
enable_affinity = 0; enable_affinity = 0;
enable_etf = 0; enable_etf = 0;
...@@ -194,6 +220,12 @@ int main(int argc, char *argv[]) { ...@@ -194,6 +220,12 @@ int main(int argc, char *argv[]) {
egress_params.packet_priority = 3; egress_params.packet_priority = 3;
egress_params.tx_buffer_len = 1024; egress_params.tx_buffer_len = 1024;
/* Lock all current and future pages from preventing of being paged to swap */
if (mlockall(MCL_CURRENT | MCL_FUTURE)) {
perror("mlockall failed");
/* exit(-1) or do error handling */
}
// Process bash options // Process bash options
process_options(argc, argv); process_options(argc, argv);
...@@ -206,6 +238,11 @@ int main(int argc, char *argv[]) { ...@@ -206,6 +238,11 @@ int main(int argc, char *argv[]) {
memset(rtt_hist, 0, sizeof(rtt_hist)); memset(rtt_hist, 0, sizeof(rtt_hist));
} }
if (main_params.enable_tracing) {
// Enable ftrace
setup_tracer(main_params.enable_graph);
}
// Catch breaks with sighand to print the histograms // Catch breaks with sighand to print the histograms
init_signals(sighand, enable_histograms); init_signals(sighand, enable_histograms);
...@@ -218,8 +255,34 @@ int main(int argc, char *argv[]) { ...@@ -218,8 +255,34 @@ int main(int argc, char *argv[]) {
init_udp_recv(&ingress_params, &ingress_stats, enable_histograms, init_udp_recv(&ingress_params, &ingress_stats, enable_histograms,
kernel_latency_hist); kernel_latency_hist);
/* Initialize pthread attributes (default values) */
if (pthread_attr_init(&attr)) {
fprintf(stderr, "init pthread attributes failed\n");
exit(EXIT_FAILURE);
}
/* Set a specific stack size */
if (pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN)) {
fprintf(stderr, "pthread setstacksize failed\n");
exit(EXIT_FAILURE);
}
/* Set scheduler policy and priority of pthread */
if (pthread_attr_setschedpolicy(&attr, SCHED_FIFO)) {
fprintf(stderr, "pthread setschedpolicy failed\n");
exit(EXIT_FAILURE);
}
param.sched_priority = thread_params.priority;
if (pthread_attr_setschedparam(&attr, &param)) {
fprintf(stderr, "pthread setschedparam failed\n");
exit(EXIT_FAILURE);
}
/* Use scheduling parameters of attr */
if (pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED)) {
fprintf(stderr, "pthread setinheritsched failed\n");
exit(EXIT_FAILURE);
}
// Create the real time thread // Create the real time thread
if (pthread_create(&thread, NULL, packet_sending_thread, NULL)) if (pthread_create(&thread, &attr, packet_sending_thread, NULL))
error(EXIT_FAILURE, errno, "Couldn't create packet sending thread"); error(EXIT_FAILURE, errno, "Couldn't create packet sending thread");
// Verbose loop // Verbose loop
...@@ -232,9 +295,11 @@ int main(int argc, char *argv[]) { ...@@ -232,9 +295,11 @@ int main(int argc, char *argv[]) {
rtt_stats.avg_rtt, rtt_stats.max_rtt); rtt_stats.avg_rtt, rtt_stats.max_rtt);
printf("\033[%dA", 1); printf("\033[%dA", 1);
} else { } else {
printf("%9" PRIu64 ": [%4d, %4d]", nb_cycles, printf("%9" PRIu64 ": [%4d, %4d], I (10us): %3d %3d %3d", nb_cycles,
(int)egress_stats.invalid_parameter, (int)egress_stats.invalid_parameter,
(int)egress_stats.missed_deadline); (int)egress_stats.missed_deadline,
egress_stats.min_interval / 10, egress_stats.avg_interval / 10,
egress_stats.max_interval / 10);
if (enable_timestamps) { if (enable_timestamps) {
printf(", K: %4d %4d %4d [%4d]\n", egress_stats.min_kernel_latency, printf(", K: %4d %4d %4d [%4d]\n", egress_stats.min_kernel_latency,
...@@ -340,7 +405,7 @@ static void process_options(int argc, char *argv[]) { ...@@ -340,7 +405,7 @@ static void process_options(int argc, char *argv[]) {
int network_if_specified = 0; int network_if_specified = 0;
for (;;) { for (;;) {
int c = getopt(argc, argv, "abd:e:f:ghi:l:p:q:r:tv"); int c = getopt(argc, argv, "abd:e:f:ghi:l:p:q:r:tvT:G");
if (c == -1) break; if (c == -1) break;
...@@ -394,6 +459,13 @@ static void process_options(int argc, char *argv[]) { ...@@ -394,6 +459,13 @@ static void process_options(int argc, char *argv[]) {
case 'v': case 'v':
main_params.verbose = 1; main_params.verbose = 1;
break; break;
case 'T':
main_params.enable_tracing = 1;
thread_params.latency_threshold = atoi(optarg);
break;
case 'G':
main_params.enable_graph = 1;
break;
} }
} }
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
#define MAX_BUFFER_SIZE 1024 #define MAX_BUFFER_SIZE 1024
#define TIMESTAMP_BUFFER_SIZE 64 #define TIMESTAMP_BUFFER_SIZE 4096
uint64_t ts_to_uint(struct timespec t); 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);
......
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
*/ */
#define _GNU_SOURCE #define _GNU_SOURCE
#include "send_packet.h"
#include <arpa/inet.h> #include <arpa/inet.h>
#include <errno.h> #include <errno.h>
#include <error.h> #include <error.h>
...@@ -35,7 +37,6 @@ ...@@ -35,7 +37,6 @@
#include <unistd.h> #include <unistd.h>
#include "common.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 process_error_queue();
...@@ -56,18 +57,15 @@ static struct sock_txtime sk_txtime; ...@@ -56,18 +57,15 @@ static struct sock_txtime sk_txtime;
static char *tx_buffer; static char *tx_buffer;
static int sock_fd; static int sock_fd;
static uint64_t timestamps_buffer[TIMESTAMP_BUFFER_SIZE]; static int64_t timestamps_buffer[TIMESTAMP_BUFFER_SIZE];
static int ts_buf_read_index = 0; static int ts_buf_read_index = 0;
static int ts_buf_write_index = 0; static int ts_buf_write_index = 0;
/* /*
* Init UDP socket * Init UDP socket
*/ */
void init_udp_send(egress_param_t *_params, void init_udp_send(egress_param_t *_params, egress_stat_t *_stats,
egress_stat_t *_stats, int _use_histogram, uint64_t *_kernel_latency_hist) {
int _use_histogram,
uint64_t *_kernel_latency_hist) {
int set_if_err; int set_if_err;
pthread_t thread; pthread_t thread;
...@@ -79,12 +77,10 @@ void init_udp_send(egress_param_t *_params, ...@@ -79,12 +77,10 @@ void init_udp_send(egress_param_t *_params,
init_tx_buffer(); init_tx_buffer();
sock_fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); sock_fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (sock_fd < 0) if (sock_fd < 0) error(EXIT_FAILURE, errno, "Socket creation failed\n");
error(EXIT_FAILURE, errno, "Socket creation failed\n");
set_if_err = set_if(); set_if_err = set_if();
if (set_if_err < 0) if (set_if_err < 0) error(EXIT_FAILURE, errno, "Couldn't set interface\n");
error(EXIT_FAILURE, errno, "Couldn't set interface\n");
if (setsockopt(sock_fd, SOL_SOCKET, SO_PRIORITY, &params->packet_priority, if (setsockopt(sock_fd, SOL_SOCKET, SO_PRIORITY, &params->packet_priority,
sizeof(params->packet_priority))) sizeof(params->packet_priority)))
...@@ -98,7 +94,8 @@ void init_udp_send(egress_param_t *_params, ...@@ -98,7 +94,8 @@ void init_udp_send(egress_param_t *_params,
sk_txtime.clockid = CLOCK_TAI; sk_txtime.clockid = CLOCK_TAI;
sk_txtime.flags = SOF_TXTIME_REPORT_ERRORS; sk_txtime.flags = SOF_TXTIME_REPORT_ERRORS;
if (setsockopt(sock_fd, SOL_SOCKET, SO_TXTIME, &sk_txtime, sizeof(sk_txtime))) if (setsockopt(sock_fd, SOL_SOCKET, SO_TXTIME, &sk_txtime,
sizeof(sk_txtime)))
error(EXIT_FAILURE, errno, "setsockopt SO_TXTIME failed\n"); error(EXIT_FAILURE, errno, "setsockopt SO_TXTIME failed\n");
} }
...@@ -113,19 +110,18 @@ void init_udp_send(egress_param_t *_params, ...@@ -113,19 +110,18 @@ void init_udp_send(egress_param_t *_params,
error(EXIT_FAILURE, errno, "Couldn't create poll thread"); error(EXIT_FAILURE, errno, "Couldn't create poll thread");
} }
/* /*
* Sends udp packets * Sends udp packets
*/ */
void send_udp_packet(char *data, void send_udp_packet(char *data, uint64_t txtime) {
uint64_t txtime) { struct msghdr msg; // Message hardware, sent to the socket
struct cmsghdr *cmsg; // Control message hardware, for txtime
struct msghdr msg; // Message hardware, sent to the socket char control[CMSG_SPACE(sizeof(txtime))] = {}; // Stores txtime
struct cmsghdr *cmsg; // Control message hardware, for txtime struct iovec iov; // The iovec structures stores the TX buffer
char control[CMSG_SPACE(sizeof(txtime))] = {}; // Stores txtime
struct iovec iov; // The iovec structures stores the TX buffer
int sendmsgerr; int sendmsgerr;
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
if (params->use_timestamps) { if (params->use_timestamps) {
clock_gettime(CLOCK_REALTIME, &ts); clock_gettime(CLOCK_REALTIME, &ts);
...@@ -170,7 +166,6 @@ void send_udp_packet(char *data, ...@@ -170,7 +166,6 @@ void send_udp_packet(char *data,
} }
static void *poll_thread(void *p) { static void *poll_thread(void *p) {
(void)p; (void)p;
// Poll file descriptor // Poll file descriptor
struct pollfd poll_fd = {.fd = sock_fd}; struct pollfd poll_fd = {.fd = sock_fd};
...@@ -191,20 +186,19 @@ static void process_error_queue() { ...@@ -191,20 +186,19 @@ static void process_error_queue() {
int recv_ret; int recv_ret;
// IO vector // IO vector
unsigned char data_buffer[256]; // Buffer in io vector unsigned char data_buffer[256]; // Buffer in io vector
struct iovec iov = { struct iovec iov = {.iov_base = data_buffer, .iov_len = sizeof(data_buffer)};
.iov_base = data_buffer,
.iov_len = sizeof(data_buffer)};
// Control data, will store error or timestamps // Control data, will store error or timestamps
unsigned char msg_control[CMSG_SPACE(sizeof(struct sock_extended_err)) + CMSG_SPACE(sizeof(struct timespec))]; unsigned char msg_control[CMSG_SPACE(sizeof(struct sock_extended_err)) +
CMSG_SPACE(sizeof(struct timespec))];
// Message hardware structure, containts IO vector and control message hardware // Message hardware structure, containts IO vector and control message
struct msghdr msg = { // hardware
.msg_iov = &iov, struct msghdr msg = {.msg_iov = &iov,
.msg_iovlen = 1, .msg_iovlen = 1,
.msg_control = msg_control, .msg_control = msg_control,
.msg_controllen = sizeof(msg_control)}; .msg_controllen = sizeof(msg_control)};
struct cmsghdr *cmsg; struct cmsghdr *cmsg;
...@@ -218,15 +212,19 @@ static void process_error_queue() { ...@@ -218,15 +212,19 @@ static void process_error_queue() {
for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) { for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
// If a timestamp was received // If a timestamp was received
if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_TIMESTAMPING) { if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_TIMESTAMPING) {
struct timespec *stamp = (struct timespec *)CMSG_DATA(cmsg); struct timespec *stamp = (struct timespec *)CMSG_DATA(cmsg);
int kernel_latency = (ts_to_uint(*stamp) - timestamps_buffer[ts_buf_read_index]) / 1000; int kernel_latency =
(ts_to_uint(*stamp) - timestamps_buffer[ts_buf_read_index]) / 1000;
ts_buf_read_index = (ts_buf_read_index + 1) % TIMESTAMP_BUFFER_SIZE; ts_buf_read_index = (ts_buf_read_index + 1) % TIMESTAMP_BUFFER_SIZE;
stats->min_kernel_latency = min(kernel_latency, stats->min_kernel_latency); stats->min_kernel_latency =
stats->max_kernel_latency = max(kernel_latency, stats->max_kernel_latency); min(kernel_latency, stats->min_kernel_latency);
stats->avg_kernel_latency = (stats->max_kernel_latency * packets_sent + kernel_latency) / (packets_sent + 1); stats->max_kernel_latency =
max(kernel_latency, stats->max_kernel_latency);
stats->avg_kernel_latency =
(stats->max_kernel_latency * packets_sent + kernel_latency) /
(packets_sent + 1);
if (use_histogram) { if (use_histogram) {
if (kernel_latency > MAX_KERNEL_LATENCY) if (kernel_latency > MAX_KERNEL_LATENCY)
...@@ -238,21 +236,19 @@ static void process_error_queue() { ...@@ -238,21 +236,19 @@ static void process_error_queue() {
} }
// If an error was received // If an error was received
else { else {
struct sock_extended_err *serr = (void *)CMSG_DATA(cmsg); struct sock_extended_err *serr = (void *)CMSG_DATA(cmsg);
if (serr->ee_origin != SO_EE_ORIGIN_TXTIME) if (serr->ee_origin != SO_EE_ORIGIN_TXTIME) continue;
continue;
switch (serr->ee_code) { switch (serr->ee_code) {
case SO_EE_CODE_TXTIME_INVALID_PARAM: case SO_EE_CODE_TXTIME_INVALID_PARAM:
stats->invalid_parameter++; stats->invalid_parameter++;
break; break;
case SO_EE_CODE_TXTIME_MISSED: case SO_EE_CODE_TXTIME_MISSED:
stats->missed_deadline++; stats->missed_deadline++;
break; break;
default: default:
fprintf(stderr, "Uknown TxTime error\n"); fprintf(stderr, "Uknown TxTime error\n");
} }
} }
} }
......
...@@ -24,6 +24,10 @@ typedef struct egress_stat { ...@@ -24,6 +24,10 @@ typedef struct egress_stat {
int avg_kernel_latency; int avg_kernel_latency;
int max_kernel_latency; int max_kernel_latency;
int min_interval;
int avg_interval;
int max_interval;
} egress_stat_t; } egress_stat_t;
void init_udp_send(egress_param_t *_params, void init_udp_send(egress_param_t *_params,
......
This diff is collapsed.
#include "tracer.h"
#define _GNU_SOURCE
#include <errno.h>
#include <error.h>
#include <fcntl.h>
#include <getopt.h>
#include <limits.h>
#include <linux/unistd.h>
#include <pthread.h>
#include <sched.h>
#include <signal.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/prctl.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/sysinfo.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/utsname.h>
#include <time.h>
#include <unistd.h>
/*
* From cyclictest code source
*/
#define KVARS 32
#define KVARNAMELEN 32
#define KVALUELEN 32
#define MAX_PATH 255
static char *fileprefix;
static char *procfileprefix = "/proc/sys/kernel/";
static char *debugfileprefix = "/sys/kernel/debug/tracing/";
static int trace_fd = -1;
static int tracemark_fd = -1;
static int kernvar(int mode, const char *name, char *value,
size_t sizeofvalue) {
char filename[128];
int retval = 1;
int path;
size_t len_prefix = strlen(fileprefix), len_name = strlen(name);
memcpy(filename, fileprefix, len_prefix);
memcpy(filename + len_prefix, name, len_name + 1);
path = open(filename, mode);
if (path >= 0) {
if (mode == O_RDONLY) {
int got;
if ((got = read(path, value, sizeofvalue)) > 0) {
retval = 0;
value[got - 1] = '\0';
}
} else if (mode == O_WRONLY) {
if (write(path, value, sizeofvalue) == sizeofvalue) retval = 0;
}
close(path);
}
return retval;
}
static void setkernvar(const char *name, char *value) {
if (kernvar(O_WRONLY, name, value, strlen(value)))
fprintf(stderr, "could not set %s to %s\n", name, value);
}
void setup_tracer(int enable_graph) {
char trace_path[MAX_PATH];
char tracemark_path[MAX_PATH];
fileprefix = procfileprefix;
setkernvar("ftrace_enabled", "1");
fileprefix = debugfileprefix;
// Clear old traces by setting tracer to nop first
setkernvar("current_tracer", "nop");
if(enable_graph)
setkernvar("current_tracer", "function_graph");
else
setkernvar("current_tracer", "function");
// Open tracing_on file
strcpy(trace_path, fileprefix);
strcat(trace_path, "tracing_on");
if ((trace_fd = open(trace_path, O_WRONLY)) == -1)
printf("unable to open %s for tracing", trace_path);
// Open trace mark file
strcpy(tracemark_path, fileprefix);
strcat(tracemark_path, "trace_marker");
if ((tracemark_fd = open(tracemark_path, O_WRONLY)) == -1)
printf("unable to open %s for tracing", tracemark_path);
tracing(0);
}
void tracing(int on) {
if (on)
write(trace_fd, "1", 1);
else
write(trace_fd, "0", 1);
}
void tracemark(char * s) {
write(tracemark_fd, s, strlen(s));
}
#ifndef TRACER_H
#define TRACER_H
void setup_tracer(int enable_graph);
void tracing(int on);
void tracemark(char * s);
#endif
#!/bin/bash
usage() {
cat << ENDUSAGE
Usage: $0 CMD
$0 sudo CMD
ENDUSAGE
exit 1;
}
if [ -z "$1" ]; then
usage
fi
if [ $1 == "sudo" ]; then
if [ -z "$2" ]; then
usage
fi
./sudossh emerald "$2";
./sudossh slate "$2";
./sudossh onyx "$2";
else
ssh emerald $1&
ssh onyx $1&
ssh slate $1
fi
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
script_dir=$(dirname $(realpath $0)) script_dir=$(dirname $(realpath $0))
usage() { usage() {
echo "Usage: $0 (-e delta [-o etf_offset] | -p) [-bgt] [-i INTERVAL] [-d TX_BUFFER_LEN] [emerald|slate|onyx]" 1>&2; echo "Usage: $0 (-e delta [-o etf_offset] | -p) [-bgt] [-i INTERVAL] [-d TX_BUFFER_LEN] [-T LATENCY_THRESHOLD -G] [emerald|slate|onyx]" 1>&2;
exit 1; exit 1;
} }
...@@ -16,7 +16,7 @@ qdisc_options="" ...@@ -16,7 +16,7 @@ qdisc_options=""
ip="192.168.99." ip="192.168.99."
etf_offset=500 etf_offset=500
while getopts "bd:e:o:ghi:pt" opt; do while getopts "bd:e:o:ghi:ptT:G" opt; do
case "${opt}" in case "${opt}" in
b ) b )
client_options+=" -b" client_options+=" -b"
...@@ -52,6 +52,12 @@ while getopts "bd:e:o:ghi:pt" opt; do ...@@ -52,6 +52,12 @@ while getopts "bd:e:o:ghi:pt" opt; do
use_timestamps=1 use_timestamps=1
client_options+=" -t" client_options+=" -t"
;; ;;
T )
client_options+=" -T ${OPTARG}"
;;
G )
client_options+=" -G"
;;
* ) * )
usage usage
;; ;;
...@@ -102,8 +108,8 @@ fi ...@@ -102,8 +108,8 @@ fi
client_options+=" -i $interval" client_options+=" -i $interval"
echo "create_qdisc $qdisc_options"; echo "create-qdisc $qdisc_options";
$script_dir/create_qdisc $qdisc_options; $script_dir/create-qdisc $qdisc_options;
echo "make client"; echo "make client";
cd $script_dir/../packet-exchange/build; cd $script_dir/../packet-exchange/build;
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
script_dir=$(dirname $(realpath $0)) script_dir=$(dirname $(realpath $0))
usage() { usage() {
echo "Usage: $0 [[-bt] [-g INTERVAL]] | (-d NB_PACKETS [-i INTERVAL])" 1>&2; echo "Usage: $0 [[-bt] [-g INTERVAL]] | (-d NB_PACKETS [-i INTERVAL]) [-T LATENCY_THRESHOLD -G]" 1>&2;
exit 1; exit 1;
} }
...@@ -12,7 +12,7 @@ server_options="-a -p 99 -f eth0" ...@@ -12,7 +12,7 @@ server_options="-a -p 99 -f eth0"
ip="192.168.99." ip="192.168.99."
tcpdump_interval=1000000 tcpdump_interval=1000000
while getopts "b:htd:i:g:" opt; do while getopts "b:htd:i:g:T:G" opt; do
case "${opt}" in case "${opt}" in
b ) b )
use_rtt=1 use_rtt=1
...@@ -37,6 +37,12 @@ while getopts "b:htd:i:g:" opt; do ...@@ -37,6 +37,12 @@ while getopts "b:htd:i:g:" opt; do
t ) t )
server_options+=" -t" server_options+=" -t"
;; ;;
T )
client_options+=" -T ${OPTARG}"
;;
G )
client_options+=" -G"
;;
* ) * )
usage usage
;; ;;
...@@ -73,8 +79,8 @@ if [ -n "${use_tcpdump}" ]; then ...@@ -73,8 +79,8 @@ if [ -n "${use_tcpdump}" ]; then
echo "tshark -r tmp.pcap --disable-protocol dcp-etsi --disable-protocol dcp-pft -t e -E separator=, -T fields -e frame.number -e frame.time_epoch -e data.data > tmp.out"; echo "tshark -r tmp.pcap --disable-protocol dcp-etsi --disable-protocol dcp-pft -t e -E separator=, -T fields -e frame.number -e frame.time_epoch -e data.data > tmp.out";
tshark -r server_stats_tmp.pcap --disable-protocol dcp-etsi --disable-protocol dcp-pft -t e -E separator=, -T fields -e frame.number -e frame.time_epoch -e data.data > server_stats_tmp.out; tshark -r server_stats_tmp.pcap --disable-protocol dcp-etsi --disable-protocol dcp-pft -t e -E separator=, -T fields -e frame.number -e frame.time_epoch -e data.data > server_stats_tmp.out;
echo "txtime_stats.py -f server_pcap_stats -i $tcpdump_interval"; echo "txtime-stats.py -f server_pcap_stats -i $tcpdump_interval";
$script_dir/txtime_stats.py -f server_stats_tmp.out -i $tcpdump_interval; $script_dir/txtime-stats.py -f server_stats_tmp.out -i $tcpdump_interval;
else else
echo "make server"; echo "make server";
......
#!/bin/expect
spawn ssh [lindex $argv 0]
expect "oli@"
send -- "sudo [lindex $argv 1]\r"
expect "assword"
send -- "olimex\r"
expect {
"Do you want to continue?" {
send "Y\r"
exp_continue
}
"oli@" {
exit
}
}
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