ifquery: add --dot to visualize a calculated solution
This commit is contained in:
parent
5c75cdcab0
commit
8138ca8485
1 changed files with 50 additions and 1 deletions
|
@ -61,6 +61,37 @@ print_interface(struct lif_interface *iface)
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
print_interface_dot(struct lif_dict *collection, struct lif_interface *iface, struct lif_interface *parent)
|
||||||
|
{
|
||||||
|
if (iface->is_up)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (parent != NULL)
|
||||||
|
printf("\"%s\" -> ", parent->ifname);
|
||||||
|
|
||||||
|
printf("\"%s\"", iface->ifname);
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
struct lif_dict_entry *entry = lif_dict_find(&iface->vars, "requires");
|
||||||
|
|
||||||
|
if (entry == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
char require_ifs[4096] = {};
|
||||||
|
strlcpy(require_ifs, entry->data, sizeof require_ifs);
|
||||||
|
char *reqp = require_ifs;
|
||||||
|
|
||||||
|
for (char *tokenp = lif_next_token(&reqp); *tokenp; tokenp = lif_next_token(&reqp))
|
||||||
|
{
|
||||||
|
struct lif_interface *child_if = lif_interface_collection_find(collection, tokenp);
|
||||||
|
|
||||||
|
print_interface_dot(collection, child_if, iface);
|
||||||
|
child_if->is_up = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ifquery_usage(void)
|
ifquery_usage(void)
|
||||||
{
|
{
|
||||||
|
@ -78,6 +109,7 @@ ifquery_usage(void)
|
||||||
fprintf(stderr, " -P, --pretty-print pretty print the interfaces instead of just listing\n");
|
fprintf(stderr, " -P, --pretty-print pretty print the interfaces instead of just listing\n");
|
||||||
fprintf(stderr, " -S, --state-file FILE use FILE for state\n");
|
fprintf(stderr, " -S, --state-file FILE use FILE for state\n");
|
||||||
fprintf(stderr, " -s, --state show configured state\n");
|
fprintf(stderr, " -s, --state show configured state\n");
|
||||||
|
fprintf(stderr, " -D, --dot generate a dependency graph\n");
|
||||||
|
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
@ -87,6 +119,7 @@ struct match_options {
|
||||||
char *exclude_pattern;
|
char *exclude_pattern;
|
||||||
char *include_pattern;
|
char *include_pattern;
|
||||||
bool pretty_print;
|
bool pretty_print;
|
||||||
|
bool dot;
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -94,6 +127,13 @@ list_interfaces(struct lif_dict *collection, struct match_options *opts)
|
||||||
{
|
{
|
||||||
struct lif_node *iter;
|
struct lif_node *iter;
|
||||||
|
|
||||||
|
if (opts->dot)
|
||||||
|
{
|
||||||
|
printf("digraph interfaces {\n");
|
||||||
|
printf("edge [color=blue fontname=Sans fontsize=10]\n");
|
||||||
|
printf("node [fontname=Sans fontsize=10]\n");
|
||||||
|
}
|
||||||
|
|
||||||
LIF_DICT_FOREACH(iter, collection)
|
LIF_DICT_FOREACH(iter, collection)
|
||||||
{
|
{
|
||||||
struct lif_dict_entry *entry = iter->data;
|
struct lif_dict_entry *entry = iter->data;
|
||||||
|
@ -112,9 +152,14 @@ list_interfaces(struct lif_dict *collection, struct match_options *opts)
|
||||||
|
|
||||||
if (opts->pretty_print)
|
if (opts->pretty_print)
|
||||||
print_interface(iface);
|
print_interface(iface);
|
||||||
|
else if (opts->dot)
|
||||||
|
print_interface_dot(collection, iface, NULL);
|
||||||
else
|
else
|
||||||
printf("%s\n", iface->ifname);
|
printf("%s\n", iface->ifname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (opts->dot)
|
||||||
|
printf("}\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -154,6 +199,7 @@ ifquery_main(int argc, char *argv[])
|
||||||
{"pretty-print", no_argument, 0, 'P'},
|
{"pretty-print", no_argument, 0, 'P'},
|
||||||
{"state-file", required_argument, 0, 'S'},
|
{"state-file", required_argument, 0, 'S'},
|
||||||
{"state", no_argument, 0, 's'},
|
{"state", no_argument, 0, 's'},
|
||||||
|
{"dot", no_argument, 0, 'D'},
|
||||||
{NULL, 0, 0, 0}
|
{NULL, 0, 0, 0}
|
||||||
};
|
};
|
||||||
struct match_options match_opts = {};
|
struct match_options match_opts = {};
|
||||||
|
@ -163,7 +209,7 @@ ifquery_main(int argc, char *argv[])
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
int c = getopt_long(argc, argv, "hVi:LaI:X:PS:s", long_options, NULL);
|
int c = getopt_long(argc, argv, "hVi:LaI:X:PS:sD", long_options, NULL);
|
||||||
if (c == -1)
|
if (c == -1)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -198,6 +244,9 @@ ifquery_main(int argc, char *argv[])
|
||||||
case 's':
|
case 's':
|
||||||
listing_stat = true;
|
listing_stat = true;
|
||||||
break;
|
break;
|
||||||
|
case 'D':
|
||||||
|
match_opts.dot = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue