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

Improve motor interface

parent 6c2dd397
...@@ -87,14 +87,14 @@ static rtt_stat_t rtt_stats = {.min_rtt = INT_MAX}; ...@@ -87,14 +87,14 @@ static rtt_stat_t rtt_stats = {.min_rtt = INT_MAX};
static egress_param_t egress_params; static egress_param_t egress_params;
static egress_param_t egress_params2; static egress_param_t egress_params2;
static egress_stat_t egress_stats = {.packets_sent = 0, static egress_stat_t egress_stats = {.packets_sent = 0,
.min_kernel_latency = INT_MAX, .min_kernel_latency = INT_MAX,
.min_interval = INT_MAX}; .min_interval = INT_MAX};
static egress_stat_t egress_stats2 = {.packets_sent = 0, static egress_stat_t egress_stats2 = {.packets_sent = 0,
.min_kernel_latency = INT_MAX, .min_kernel_latency = INT_MAX,
.min_interval = 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_info;
static egress_info_t egress_info2; static egress_info_t egress_info2;
...@@ -107,6 +107,8 @@ static struct timespec measures_start; ...@@ -107,6 +107,8 @@ static struct timespec measures_start;
static struct timespec measures_end; static struct timespec measures_end;
static char send_data[MAX_BUFFER_SIZE]; static char send_data[MAX_BUFFER_SIZE];
static int reverse_motors = 0;
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 "
...@@ -131,7 +133,14 @@ static void help(char *argv[]) { ...@@ -131,7 +133,14 @@ static void help(char *argv[]) {
" -S Enable tracing until threshold is reached\n" " -S Enable tracing until threshold is reached\n"
" -U Interactive interval change\n" " -U Interactive interval change\n"
"\n", "\n",
argv[0]); argv[0]);
}
static double i_to_rps(int i) {
return ((double)USEC_PER_SEC) / (MOTOR_STEPS * i);
}
static int rps_to_i(double rps) {
return USEC_PER_SEC / (MOTOR_STEPS * rps);
} }
static void *print_thread(void *p) { static void *print_thread(void *p) {
...@@ -142,7 +151,9 @@ static void *print_thread(void *p) { ...@@ -142,7 +151,9 @@ static void *print_thread(void *p) {
nb_cycles >= ((unsigned int)thread_params.max_cycles)) nb_cycles >= ((unsigned int)thread_params.max_cycles))
break; break;
printf("Interval: %10" PRIu64 " Target: %10" PRIu64 "\n", thread_params.interval / 1000, main_params.target_interval); printf("RPS: %5F RPS Target: %5F s/100 RPS %5d\n", i_to_rps(thread_params.interval / 1000),
i_to_rps(main_params.target_interval),
main_params.transition_time);
printf("\033[%dA", 1); printf("\033[%dA", 1);
usleep(100000); usleep(100000);
...@@ -175,7 +186,7 @@ static void *packet_sending_thread(void *p) { ...@@ -175,7 +186,7 @@ static void *packet_sending_thread(void *p) {
CPU_SET(thread_params.affinity_cpu, &mask); CPU_SET(thread_params.affinity_cpu, &mask);
if (sched_setaffinity(0, sizeof(mask), &mask)) if (sched_setaffinity(0, sizeof(mask), &mask))
error(EXIT_FAILURE, errno, "Could not set CPU affinity to CPU %d\n", error(EXIT_FAILURE, errno, "Could not set CPU affinity to CPU %d\n",
thread_params.affinity_cpu); thread_params.affinity_cpu);
} }
clock_gettime(CLOCK_MONOTONIC, &measures_start); clock_gettime(CLOCK_MONOTONIC, &measures_start);
...@@ -244,6 +255,12 @@ static void *packet_sending_thread(void *p) { ...@@ -244,6 +255,12 @@ static void *packet_sending_thread(void *p) {
if (thread_params.enable_send_ts) { if (thread_params.enable_send_ts) {
tx_data = next.tv_sec * NSEC_PER_SEC + next.tv_nsec; tx_data = next.tv_sec * NSEC_PER_SEC + next.tv_nsec;
tx_data += thread_params.send_ts_delay; tx_data += thread_params.send_ts_delay;
if(reverse_motors) {
reverse_motors = 0;
tx_data = 17;
}
} }
// Update statistics // Update statistics
...@@ -253,8 +270,8 @@ static void *packet_sending_thread(void *p) { ...@@ -253,8 +270,8 @@ static void *packet_sending_thread(void *p) {
egress_stats.min_interval = _min_(interval_us, egress_stats.min_interval); egress_stats.min_interval = _min_(interval_us, egress_stats.min_interval);
egress_stats.max_interval = _max_(interval_us, egress_stats.max_interval); egress_stats.max_interval = _max_(interval_us, egress_stats.max_interval);
egress_stats.avg_interval = egress_stats.avg_interval =
(egress_stats.avg_interval * nb_cycles + interval_us) / (egress_stats.avg_interval * nb_cycles + interval_us) /
(nb_cycles + 1); (nb_cycles + 1);
if (thread_params.enable_threshold_tracing) { if (thread_params.enable_threshold_tracing) {
int jitter = (egress_stats.max_interval - egress_stats.min_interval); int jitter = (egress_stats.max_interval - egress_stats.min_interval);
...@@ -281,9 +298,9 @@ static void *packet_sending_thread(void *p) { ...@@ -281,9 +298,9 @@ static void *packet_sending_thread(void *p) {
next_increment = 0; next_increment = 0;
if(i_t < i_s) if(i_t < i_s)
end_t = (main_params.transition_time * USEC_PER_SEC * USEC_PER_SEC * (i_c - i_t)) / (MOTOR_STEPS * i_t * i_c); end_t = (main_params.transition_time * USEC_PER_SEC * USEC_PER_SEC * (i_c - i_t)) / (100 * MOTOR_STEPS * i_t * i_c);
else else
end_t = (main_params.transition_time * USEC_PER_SEC * USEC_PER_SEC * (i_t - i_c)) / (MOTOR_STEPS * i_t * i_c); end_t = (main_params.transition_time * USEC_PER_SEC * USEC_PER_SEC * (i_t - i_c)) / (100 * MOTOR_STEPS * i_t * i_c);
} }
...@@ -339,6 +356,28 @@ invalid_ts: ...@@ -339,6 +356,28 @@ invalid_ts:
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
static void motor_input(void) {
char user_input[255];
int v;
scanf("%s", user_input);
switch(user_input[0]) {
case 'a':
v = atoi(user_input + 1);
if(v)
main_params.transition_time = v;
break;
case 'r':
reverse_motors = 1;
break;
default:
v = rps_to_i(strtod(user_input, NULL));
if(v)
main_params.target_interval = v;
break;
}
}
/* /*
* Main thread: * Main thread:
* - Has non-real time priority * - Has non-real time priority
...@@ -420,7 +459,7 @@ int main(int argc, char *argv[]) { ...@@ -420,7 +459,7 @@ int main(int argc, char *argv[]) {
// 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)
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) // Initialize pthread attributes (default values)
if (pthread_attr_init(&attr)) { if (pthread_attr_init(&attr)) {
...@@ -463,34 +502,33 @@ int main(int argc, char *argv[]) { ...@@ -463,34 +502,33 @@ int main(int argc, char *argv[]) {
usleep(main_params.refresh_rate); usleep(main_params.refresh_rate);
if (main_params.interval_input) { if (main_params.interval_input) {
uint64_t user_input;
scanf("%" PRIu64, &user_input); motor_input();
if(user_input)
main_params.target_interval = user_input;
} }
else if (main_params.verbose) { else if (main_params.verbose) {
// RTT stats printing // RTT stats printing
if (tsn_task == RTT_TASK) { if (tsn_task == RTT_TASK) {
// N_CYCLES, RTT min / avg / max // N_CYCLES, RTT min / avg / max
printf("%9" PRIu64 ": RTT: %4d %4d %4d\n", nb_cycles, rtt_stats.min_rtt, printf("%9" PRIu64 ": 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); printf("\033[%dA", 1);
// Packet send stats printing // Packet send stats printing
} else { } else {
// N_CYCLES, error queue, measured send interval min / avg / max // N_CYCLES, error queue, measured send interval min / avg / max
printf("%9" PRIu64 ": [%4d, %4d], I (10us): %3d %3d %3d", 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.min_interval / 10, egress_stats.avg_interval / 10,
egress_stats.max_interval / 10); egress_stats.max_interval / 10);
// SOF_TX timestamps // SOF_TX timestamps
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,
egress_stats.avg_kernel_latency, egress_stats.avg_kernel_latency,
egress_stats.max_kernel_latency, egress_stats.max_kernel_latency,
(int)egress_stats.high_kernel_latency); (int)egress_stats.high_kernel_latency);
else else
printf("\n"); printf("\n");
...@@ -508,7 +546,7 @@ int main(int argc, char *argv[]) { ...@@ -508,7 +546,7 @@ int main(int argc, char *argv[]) {
} }
/* Critical TSN task /* Critical TSN task
*/ */
static void do_tsn_task(char *data, uint64_t next_txtime) { static void do_tsn_task(char *data, uint64_t next_txtime) {
struct timespec t1, t2; struct timespec t1, t2;
int rtt_us; int rtt_us;
...@@ -531,18 +569,18 @@ static void do_tsn_task(char *data, uint64_t next_txtime) { ...@@ -531,18 +569,18 @@ static void do_tsn_task(char *data, uint64_t next_txtime) {
rtt_stats.min_rtt = _min_(rtt_us, rtt_stats.min_rtt); rtt_stats.min_rtt = _min_(rtt_us, rtt_stats.min_rtt);
rtt_stats.max_rtt = _max_(rtt_us, rtt_stats.max_rtt); rtt_stats.max_rtt = _max_(rtt_us, rtt_stats.max_rtt);
rtt_stats.avg_rtt = rtt_stats.avg_rtt =
(((uint64_t)rtt_stats.avg_rtt) * (nb_cycles - 1) + rtt_us) / nb_cycles; (((uint64_t)rtt_stats.avg_rtt) * (nb_cycles - 1) + rtt_us) / nb_cycles;
if (rtt_us > MAX_RTT) if (rtt_us > MAX_RTT)
fprintf(stderr, "RTT value higher than MAX_RTT : %d ( > %d)\n", rtt_us, fprintf(stderr, "RTT value higher than MAX_RTT : %d ( > %d)\n", rtt_us,
MAX_RTT); MAX_RTT);
else else
rtt_hist[rtt_us]++; rtt_hist[rtt_us]++;
} }
} }
/* Print histogram /* Print histogram
*/ */
static void print_histograms() { static void print_histograms() {
uint64_t duration; uint64_t duration;
int duration_hour, duration_minutes; int duration_hour, duration_minutes;
...@@ -586,7 +624,7 @@ static void sighand(int sig_num) { ...@@ -586,7 +624,7 @@ static void sighand(int sig_num) {
} }
/* Process bash options /* Process bash options
*/ */
static void process_options(int argc, char *argv[]) { static void process_options(int argc, char *argv[]) {
for (;;) { for (;;) {
int c = getopt(argc, argv, "a:bc:d:e:ghi:l:p:q:r:s:tvTS:U:"); int c = getopt(argc, argv, "a:bc:d:e:ghi:l:p:q:r:s:tvTS:U:");
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
#include <linux/udp.h> #include <linux/udp.h>
#endif #endif
#define MOTOR_STEPS 20000 #define MOTOR_STEPS 800
#define NSEC_PER_SEC UINT64_C(1000000000) #define NSEC_PER_SEC UINT64_C(1000000000)
#define USEC_PER_SEC UINT64_C(1000000) #define USEC_PER_SEC UINT64_C(1000000)
......
...@@ -5,28 +5,44 @@ ...@@ -5,28 +5,44 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <fcntl.h> #include <fcntl.h>
static int gpio_state; static char path[64];
static char cmd[128]; static char cmd[128];
static char * one = "1"; static char * one = "1";
static char * zero = "0"; static char * zero = "0";
static int fd;
void enable_gpio(int gpio_index) { int enable_gpio(int * fd, int gpio_index) {
sprintf(cmd, "echo %d > /sys/class/gpio/export", gpio_index); FILE *fp;
system(cmd); char gpio_state_str[16];
sprintf(cmd, "echo out > /sys/class/gpio/gpio%d/direction", gpio_index); int gpio_state = 0;
system(cmd);
sprintf(cmd, "/sys/class/gpio/gpio%d/value", gpio_index); sprintf(path, "/sys/class/gpio/gpio%d/value", gpio_index);
fd = open(cmd, O_WRONLY); sprintf(cmd, "cat %s", path);
fp = popen(cmd, "r");
if (fp == NULL) {
fprintf(stderr, "Error when reading gpio\n");
exit(EXIT_FAILURE);
}
while (fgets(gpio_state_str, sizeof(gpio_state_str), fp) != NULL) {
gpio_state = atoi(gpio_state_str);
}
pclose(fp);
*fd = open(path, O_WRONLY);
return gpio_state;
} }
void toggle_gpio() { int toggle_gpio(int fd, int gpio_state) {
if(gpio_state) if(gpio_state)
write(fd, one, 1);
else
write(fd, zero, 1); write(fd, zero, 1);
else
write(fd, one, 1);
gpio_state = !gpio_state; gpio_state = !gpio_state;
return gpio_state;
} }
#ifndef GPIO_H #ifndef GPIO_H
#define GPIO_H #define GPIO_H
void enable_gpio(int gpio_index); int enable_gpio(int * fd, int gpio_index);
void toggle_gpio(); int toggle_gpio(int fd, int gpio_state);
#endif #endif
...@@ -88,8 +88,15 @@ static int64_t max_diff_ts = 0; ...@@ -88,8 +88,15 @@ static int64_t max_diff_ts = 0;
static int64_t avg_diff_ts = 0; static int64_t avg_diff_ts = 0;
static uint64_t high_diff_ts = 0; static uint64_t high_diff_ts = 0;
static int debug_latencies = 0;
static int interval_us; static int interval_us;
static int gpio86_fd;
static int gpio84_fd;
static int gpio86_state;
static int gpio84_state;
static int received_reverse_motor = 0;
static char ts_tracemark_buf[64]; static char ts_tracemark_buf[64];
static void help(char *argv[]) { static void help(char *argv[]) {
...@@ -110,6 +117,7 @@ static void help(char *argv[]) { ...@@ -110,6 +117,7 @@ static void help(char *argv[]) {
" -g Print histograms to sdtout on exit\n" " -g Print histograms to sdtout on exit\n"
" -t Enable timestamps\n" " -t Enable timestamps\n"
" -x Use AF_XDP sockets\n" " -x Use AF_XDP sockets\n"
" -D Debug latencies\n"
" -X Trace during XDP packet reception\n" " -X Trace during XDP packet reception\n"
" -T THRESHOLD Enable tracing until THRESHOLD is reached\n" " -T THRESHOLD Enable tracing until THRESHOLD is reached\n"
" -M Send tracemark when packet is received\n" " -M Send tracemark when packet is received\n"
...@@ -127,6 +135,7 @@ static void *emit_signal_thread(void *p) { ...@@ -127,6 +135,7 @@ static void *emit_signal_thread(void *p) {
int64_t emit_diff, ts_diff; int64_t emit_diff, ts_diff;
int latency_spike = 0; int latency_spike = 0;
int ret; int ret;
int reverse_motor = 0;
// Set thread CPU affinity // Set thread CPU affinity
if (thread_params.affinity_cpu) { if (thread_params.affinity_cpu) {
...@@ -142,34 +151,51 @@ static void *emit_signal_thread(void *p) { ...@@ -142,34 +151,51 @@ static void *emit_signal_thread(void *p) {
for (int i = 0;;i++) { for (int i = 0;;i++) {
pthread_cond_wait(&emit_signal_ts_received, &emit_signal_mutex); pthread_cond_wait(&emit_signal_ts_received, &emit_signal_mutex);
if(received_reverse_motor) {
received_reverse_motor = 0;
reverse_motor = 1;
continue;
}
ret = clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &emit_signal_next, NULL); ret = clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &emit_signal_next, NULL);
if (ret) { if (ret) {
fprintf(stderr, "clock_nanosleep returned error: %d, aborting...\n", ret); fprintf(stderr, "clock_nanosleep returned error: %d, aborting...\n", ret);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
toggle_gpio(); if(reverse_motor) {
gpio84_state = toggle_gpio(gpio84_fd, gpio84_state);
reverse_motor = 0;
}
else {
gpio86_state = toggle_gpio(gpio86_fd, gpio86_state);
usleep(3);
gpio86_state = toggle_gpio(gpio86_fd, gpio86_state);
}
clock_gettime(CLOCK_REALTIME, &current); clock_gettime(CLOCK_REALTIME, &current);
// Check if something went wrong if(debug_latencies) {
//if(i > 0) { //Check if something went wrong
// emit_diff = calcdiff_ns_signed(current, previous_emit); if(i > 0) {
// ts_diff = calcdiff_ns_signed(emit_signal_next, previous_ts); emit_diff = calcdiff_ns_signed(current, previous_emit);
// if((emit_diff < ((int64_t)thread_params.interval) - ERROR_MARGIN_NS) || ts_diff = calcdiff_ns_signed(emit_signal_next, previous_ts);
// (emit_diff > ((int64_t)thread_params.interval) + ERROR_MARGIN_NS)) { if((emit_diff < ((int64_t)thread_params.interval) - ERROR_MARGIN_NS) ||
// fprintf(stderr, "Signal emission interval reached error threshold: %" PRIi64 "\n", emit_diff); (emit_diff > ((int64_t)thread_params.interval) + ERROR_MARGIN_NS)) {
// latency_spike = 1; fprintf(stderr, "Signal emission interval reached error threshold: %" PRIi64 "\n", emit_diff);
// } latency_spike = 1;
// if((ts_diff < ((int64_t)thread_params.interval) - ERROR_MARGIN_NS) || }
// (ts_diff > ((int64_t)thread_params.interval) + ERROR_MARGIN_NS)) { if((ts_diff < ((int64_t)thread_params.interval) - ERROR_MARGIN_NS) ||
// fprintf(stderr, "Timestamp interval reached error threshold: %" PRIi64 "\n", ts_diff); (ts_diff > ((int64_t)thread_params.interval) + ERROR_MARGIN_NS)) {
// latency_spike = 1; fprintf(stderr, "Timestamp interval reached error threshold: %" PRIi64 "\n", ts_diff);
// } latency_spike = 1;
// if(latency_spike) { }
// fprintf(stderr, "Exiting... Current interval: %d\n", interval_us); if(latency_spike) {
// exit(EXIT_FAILURE); fprintf(stderr, "Exiting... Current interval: %d\n", interval_us);
// } exit(EXIT_FAILURE);
//} }
}
}
previous_emit = current; previous_emit = current;
previous_ts = emit_signal_next; previous_ts = emit_signal_next;
} }
...@@ -255,8 +281,14 @@ static void *tsn_thread(void *p) { ...@@ -255,8 +281,14 @@ static void *tsn_thread(void *p) {
else else
emit_signal_t = decode(ingress_stats.data); emit_signal_t = decode(ingress_stats.data);
if(emit_signal_t < UINT64_C(1576800000000000000) && emit_signal_t != 17)
continue;
pthread_mutex_lock(&emit_signal_mutex); pthread_mutex_lock(&emit_signal_mutex);
emit_signal_next = uint_to_ts(emit_signal_t); if(emit_signal_t == 17)
received_reverse_motor = 1;
else
emit_signal_next = uint_to_ts(emit_signal_t);
pthread_cond_signal(&emit_signal_ts_received); pthread_cond_signal(&emit_signal_ts_received);
pthread_mutex_unlock(&emit_signal_mutex); pthread_mutex_unlock(&emit_signal_mutex);
} }
...@@ -445,7 +477,8 @@ int main(int argc, char *argv[]) { ...@@ -445,7 +477,8 @@ int main(int argc, char *argv[]) {
pthread_mutex_init(&emit_signal_mutex, NULL); pthread_mutex_init(&emit_signal_mutex, NULL);
pthread_cond_init(&emit_signal_ts_received, NULL); pthread_cond_init(&emit_signal_ts_received, NULL);
enable_gpio(86); gpio86_state = enable_gpio(&gpio86_fd, 86);
gpio84_state = enable_gpio(&gpio84_fd, 84);
} }
create_thread(tsn_thread); create_thread(tsn_thread);
...@@ -577,7 +610,7 @@ static void process_options(int argc, char *argv[]) { ...@@ -577,7 +610,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, "a:b:cCs:d:f:ghi:p:r:tvxXT:GMS"); int c = getopt(argc, argv, "a:b:cCs:d:f:ghi:p:r:tvxDXT:GMS");
if (c == -1) break; if (c == -1) break;
...@@ -634,6 +667,9 @@ static void process_options(int argc, char *argv[]) { ...@@ -634,6 +667,9 @@ static void process_options(int argc, char *argv[]) {
case 'x': case 'x':
tsn_task = XDP_TASK; tsn_task = XDP_TASK;
break; break;
case 'D':
debug_latencies = 1;
break;
case 'X': case 'X':
main_params.enable_xdp_tracing = 1; main_params.enable_xdp_tracing = 1;
break; break;
......
#!/bin/bash
script_dir=$(dirname $(realpath $0))
usage() {
cat << ENDUSAGE
Usage: $0 [-h] [-is -c USEC] [-X]
-h Show help
-i Init motors
-s Start servers on olimex boards
-c USEC Specify which offset to use for the timestamp in the packet
-X Use XDP
BOARD_HOSTNAME Uses /etc/hosts to find the IP address associated to the hostname
ENDUSAGE
1>&2;
exit 1;
}
interval=1000
server_opts=""
delay=250
while getopts "hisc:X" opt; do
case "${opt}" in
h )
usage
;;
i )
init_motors=1
;;
s )
start_servers=1
;;
c )
delay=${OPTARG}
;;
X )
server_opts+=" -X "
;;
* )
usage
;;
esac
done
shift $((OPTIND-1))
board1="onyx"
board2="slate"
killall client;
killall run-client;
if [ -n "$init_motors" ]; then
$script_dir/sudossh $board1 "motor-scripts/motor-init";
$script_dir/sudossh $board2 "motor-scripts/motor-init";
$script_dir/sudossh $board1 "motor-scripts/motor-cw";
$script_dir/sudossh $board2 "motor-scripts/motor-ccw";
fi
if [ -n "$start_servers" ]; then
$script_dir/sudossh $board1 "killall server";
$script_dir/sudossh $board2 "killall server";
$script_dir/exec-ssh-nohup $board1 "run-server -c $interval $server_opts" server_log;
$script_dir/exec-ssh-nohup $board2 "run-server -c $interval $server_opts" server_log;
sleep 5;
fi
echo "$script_dir/run-client -i 40000 -c $delay -U 100 enp1s0 $board1 enp2s0 $board2";
$script_dir/run-client -i 40000 -c $delay -U 100 enp1s0 $board1 enp2s0 $board2
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