Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tools/zep_dispatch: enhancements and fixes #19996

Merged
merged 12 commits into from
Jan 4, 2024
Merged
46 changes: 36 additions & 10 deletions dist/tools/zep_dispatch/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -131,17 +131,28 @@ static void dispatch_loop(int sock, int tap, dispatch_cb_t dispatch, void *ctx)

static topology_t topology;
static const char *graphviz_file = "example.gv";
static const char *pidfile;
static void _info_handler(int signal)
{
if (signal != SIGUSR1) {
return;
}

if (topology_print(graphviz_file, &topology)) {
fprintf(stderr, "can't open %s\n", graphviz_file);
}
else {
printf("graph written to %s\n", graphviz_file);
switch (signal) {
case SIGUSR1:
if (topology_print(graphviz_file, &topology)) {
fprintf(stderr, "can't open %s\n", graphviz_file);
}
else {
printf("graph written to %s\n", graphviz_file);
}
break;
case SIGUSR2:
topology_print_stats(&topology, true);
break;
case SIGINT:
case SIGTERM:
if (pidfile) {
unlink(pidfile);
}
exit(0);
break;
}
}

Expand Down Expand Up @@ -190,6 +201,7 @@ static void _print_help(const char *progname)

fprintf(stderr, "\noptional arguments:\n");
fprintf(stderr, "\t-t <file>\tLoad toplogy from file\n");
fprintf(stderr, "\t-p <file>\tStore PID in file\n");
fprintf(stderr, "\t-s <seed>\tRandom seed used to simulate packet loss\n");
fprintf(stderr, "\t-g <file>\tFile to dump topology as Graphviz visualisation on SIGUSR1\n");
fprintf(stderr, "\t-w <interface>\tSend frames to virtual 802.15.4 "
Expand All @@ -210,7 +222,7 @@ int main(int argc, char **argv)
.ai_flags = AI_NUMERICHOST,
};

while ((c = getopt(argc, argv, "t:s:g:w:")) != -1) {
while ((c = getopt(argc, argv, "t:s:g:w:p:")) != -1) {
switch (c) {
case 't':
topo_file = optarg;
Expand All @@ -227,6 +239,9 @@ int main(int argc, char **argv)
return tap_fd;
}
break;
case 'p':
pidfile = optarg;
break;
default:
_print_help(progname);
exit(1);
Expand Down Expand Up @@ -257,6 +272,9 @@ int main(int argc, char **argv)
if (graphviz_file) {
signal(SIGUSR1, _info_handler);
}
signal(SIGUSR2, _info_handler);
signal(SIGTERM, _info_handler);
signal(SIGINT, _info_handler);

struct addrinfo *server_addr;
int res = getaddrinfo(argv[0], argv[1],
Expand All @@ -282,6 +300,14 @@ int main(int argc, char **argv)

freeaddrinfo(server_addr);

if (pidfile) {
FILE *pf = fopen(pidfile, "w");
if (pf) {
fprintf(pf, "%u", getpid());
fclose(pf);
}
}

if (topology.flat) {
dispatch_loop(sock, tap_fd, _send_flat, &topology.nodes);
}
Expand Down
98 changes: 83 additions & 15 deletions dist/tools/zep_dispatch/topogen.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@
#include <math.h>
#include <unistd.h>

#ifndef CONFIG_USE_NUMERIC_NAMES
#define CONFIG_USE_NUMERIC_NAMES 1
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why isn't that a comandline option

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, I wasn't sure if I shouldn't remove it altogether.
The alphabetic names look nice for node numbers < 26, but once we use two letters, it's much more confusing than just numbering them.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lets keep them in hidden

#endif

struct node {
char name[8];
int x;
Expand All @@ -27,6 +31,7 @@ struct world {
unsigned h;
unsigned num_nodes;
struct node *nodes;
bool grid;
};

static unsigned random_range(unsigned lower, unsigned upper)
Expand All @@ -35,13 +40,31 @@ static unsigned random_range(unsigned lower, unsigned upper)
return lower + rand() % range;
}

static struct node *node_generate(struct node *n, const struct world *w,
unsigned range)
static struct node *node_generate(struct node *node, const struct world *w,
unsigned range, unsigned idx)
{
n->x = random_range(0, w->w);
n->y = random_range(0, w->h);
n->r = range;
return n;
if (w->grid) {
float width = w->w;
float height = w->h;
float num = w->num_nodes;

/* https://math.stackexchange.com/a/1039514 */
float n_x = sqrtf(num * width/height
+ powf(width - height, 2)/(4 * height*height))
- (width - height)/2;
float n_y = num / n_x;

unsigned step_x = width / n_x;
unsigned step_y = height / n_y;

node->x = (idx * step_x + step_x / 2) % w->w;
node->y = ((idx * step_x + step_x / 2) / w->w) * step_y + step_y / 2;
} else {
node->x = random_range(0, w->w);
node->y = random_range(0, w->h);
}
node->r = range;
return node;
}

static double node_distance(const struct node *a, const struct node *b)
Expand All @@ -51,7 +74,7 @@ static double node_distance(const struct node *a, const struct node *b)

static double node_distance_weight(const struct node *a, const struct node *b)
{
double w = 1 - node_distance(a, b) / a->r;
double w = 1 - pow(node_distance(a, b), 2) / pow(a->r, 2);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will this surprise people? (changing distance from linear to quadratic (more realistic))

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tbh I don't think there is currently anyone besides me using this


if (w < 0) {
return 0;
Expand All @@ -61,13 +84,18 @@ static double node_distance_weight(const struct node *a, const struct node *b)

static void node_name(struct node *n, unsigned idx)
{
if (CONFIG_USE_NUMERIC_NAMES) {
snprintf(n->name, sizeof(n->name), "n%03u", (uint16_t)idx + 1);
return;
}

char *s = n->name;
const char *end = s + sizeof(n->name) - 1;

do {
uint8_t rem = idx % 26;
idx /= 26;
*s++ = 'A' + rem;
idx -= rem;
} while (idx && s != end);
*s = 0;
}
Expand All @@ -82,9 +110,15 @@ static void world_gen(struct world *w, unsigned num_nodes,
w->nodes = calloc(num_nodes, sizeof(*w->nodes));

for (unsigned i = 0; i < num_nodes; ++i) {
node_generate(&w->nodes[i], w, random_range(range - var, range + var));
node_generate(&w->nodes[i], w, random_range(range - var, range + var), i);
node_name(&w->nodes[i], i);
}

if (!w->grid) {
/* place first node at origin */
w->nodes[0].x = 0;
w->nodes[0].y = 0;
}
}

static unsigned _color(const struct node *n, unsigned base)
Expand Down Expand Up @@ -154,22 +188,35 @@ static void _calc_connections(struct node *nodes, unsigned num)
}
}

static void _print_distance(struct node *nodes, unsigned num, bool recursive)
static void _print_distance(struct node *nodes, unsigned num, bool recursive, bool binary)
{
struct node *start = nodes;

if (recursive) {
for (unsigned i = 0; i < num; ++i) {
printf("%s\n", nodes[i].name);
}
}

for (unsigned i = 1; i < num; ++i) {
struct node *n = &nodes[i];

double to_node = node_distance_weight(start, n);
double from_node = node_distance_weight(n, start);

if (to_node > 0 || from_node > 0) {
if (binary) {
if (to_node >= 0.5) {
printf("%s\t%s\n", start->name, n->name);
}
if (from_node >= 0.5) {
printf("%s\t%s\n", n->name, start->name);
}
} else if (to_node > 0 || from_node > 0) {
printf("%s\t%s\t%.2f\t%.2f\n", start->name, n->name, to_node, from_node);
}

if (recursive) {
_print_distance(n, num - i, false);
_print_distance(n, num - i, false, binary);
}
}
}
Expand All @@ -183,7 +230,18 @@ static void _print_help(const char *name)
" [-r <range>]"
" [-v <variance of range>]"
" [-n <nodes>]"
" [-b][-g]"
"\n", name);

puts("\nOptions:");
puts("\t-s <seed>\trandom seed used for topology generation");
puts("\t-w <width>\twidth of the 2D topology");
puts("\t-h <height>\theight of the 2D topology");
puts("\t-r <range>\tRadio range of the nodes");
puts("\t-v <variance>\tmaximal random variance of radio range");
puts("\t-n <nodes>\tnumber of nodes in the topology");
puts("\t-b\t\tbinary links: link quality is rounded to 100% or 0%");
puts("\t-g\t\tnodes are organized as a grid");
}

int main(int argc, char** argv)
Expand All @@ -196,10 +254,18 @@ int main(int argc, char** argv)
unsigned range = 25;
unsigned var = 0;
unsigned num = 10;
bool binary = false;
bool grid = false;
char c;

while ((c = getopt(argc, argv, "s:w:h:r:v:n:")) != -1) {
while ((c = getopt(argc, argv, "s:w:h:r:v:n:bg")) != -1) {
switch (c) {
case 'b':
binary = true;
break;
case 'g':
grid = true;
break;
case 's':
seed = atoi(optarg);
break;
Expand All @@ -226,12 +292,14 @@ int main(int argc, char** argv)

srand(seed);

struct world w;
struct world w = {
.grid = grid,
};
world_gen(&w, num, width, height, range, var);

printf("# seed = %u\n", seed);
puts("# Connections");
_print_distance(w.nodes, w.num_nodes, true);
_print_distance(w.nodes, w.num_nodes, true, binary);
puts("");
puts("");
puts("# Node\tX\tY\trange\tcolor");
Expand Down
Loading
Loading