From 675febfa2f31372e45e2a6a28ce19256b22106d7 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Fri, 23 Oct 2009 11:49:39 -0700 Subject: [PATCH] Factor out common code from utilities that multiplex commands. An upcoming commit will add yet another such utility and the code redundancy was getting to be a bit much. --- lib/command-line.c | 42 ++++++++++++++++- lib/command-line.h | 13 +++++- utilities/ovs-dpctl.c | 46 ++---------------- utilities/ovs-ofctl.c | 105 +++++++++++++----------------------------- 4 files changed, 89 insertions(+), 117 deletions(-) diff --git a/lib/command-line.c b/lib/command-line.c index 6b79c5ea..a2a43a1c 100644 --- a/lib/command-line.c +++ b/lib/command-line.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008 Nicira Networks. + * Copyright (c) 2008, 2009 Nicira Networks. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,6 +18,7 @@ #include "command-line.h" #include #include +#include #include "util.h" #include "vlog.h" @@ -47,3 +48,42 @@ long_options_to_short_options(const struct option options[]) return xstrdup(short_options); } +/* Runs the command designated by argv[0] within the command table specified by + * 'commands', which must be terminated by a command whose 'name' member is a + * null pointer. + * + * Command-line options should be stripped off, so that a typical invocation + * looks like "run_command(argc - optind, argv + optind, my_commands);". */ +void +run_command(int argc, char *argv[], const struct command commands[]) +{ + const struct command *p; + + if (argc < 1) { + ovs_fatal(0, "missing command name; use --help for help"); + } + + for (p = commands; p->name != NULL; p++) { + if (!strcmp(p->name, argv[0])) { + int n_arg = argc - 1; + if (n_arg < p->min_args) { + ovs_fatal(0, "'%s' command requires at least %d arguments", + p->name, p->min_args); + } else if (n_arg > p->max_args) { + ovs_fatal(0, "'%s' command takes at most %d arguments", + p->name, p->max_args); + } else { + p->handler(argc, argv); + if (ferror(stdout)) { + ovs_fatal(0, "write to stdout failed"); + } + if (ferror(stderr)) { + ovs_fatal(0, "write to stderr failed"); + } + return; + } + } + } + + ovs_fatal(0, "unknown command '%s'; use --help for help", argv[0]); +} diff --git a/lib/command-line.h b/lib/command-line.h index 426ce62e..bc2071ef 100644 --- a/lib/command-line.h +++ b/lib/command-line.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008 Nicira Networks. + * Copyright (c) 2008, 2009 Nicira Networks. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,7 +19,18 @@ /* Utilities for command-line parsing. */ +#include "compiler.h" + struct option; + +struct command { + const char *name; + int min_args; + int max_args; + void (*handler)(int argc, char *argv[]); +}; + char *long_options_to_short_options(const struct option *options); +void run_command(int argc, char *argv[], const struct command[]); #endif /* command-line.h */ diff --git a/utilities/ovs-dpctl.c b/utilities/ovs-dpctl.c index 5a0da820..08713eb0 100644 --- a/utilities/ovs-dpctl.c +++ b/utilities/ovs-dpctl.c @@ -43,56 +43,20 @@ #include "vlog.h" #define THIS_MODULE VLM_dpctl -struct command { - const char *name; - int min_args; - int max_args; - void (*handler)(int argc, char *argv[]); -}; - -static struct command all_commands[]; +static const struct command all_commands[]; static void usage(void) NO_RETURN; static void parse_options(int argc, char *argv[]); -int main(int argc, char *argv[]) +int +main(int argc, char *argv[]) { - struct command *p; - set_program_name(argv[0]); time_init(); vlog_init(); parse_options(argc, argv); signal(SIGPIPE, SIG_IGN); - - argc -= optind; - argv += optind; - if (argc < 1) - ovs_fatal(0, "missing command name; use --help for help"); - - for (p = all_commands; p->name != NULL; p++) { - if (!strcmp(p->name, argv[0])) { - int n_arg = argc - 1; - if (n_arg < p->min_args) - ovs_fatal(0, "'%s' command requires at least %d arguments", - p->name, p->min_args); - else if (n_arg > p->max_args) - ovs_fatal(0, "'%s' command takes at most %d arguments", - p->name, p->max_args); - else { - p->handler(argc, argv); - if (ferror(stdout)) { - ovs_fatal(0, "write to stdout failed"); - } - if (ferror(stderr)) { - ovs_fatal(0, "write to stderr failed"); - } - exit(0); - } - } - } - ovs_fatal(0, "unknown command '%s'; use --help for help", argv[0]); - + run_command(argc - optind, argv + optind, all_commands); return 0; } @@ -527,7 +491,7 @@ do_help(int argc UNUSED, char *argv[] UNUSED) usage(); } -static struct command all_commands[] = { +static const struct command all_commands[] = { { "add-dp", 1, INT_MAX, do_add_dp }, { "del-dp", 1, 1, do_del_dp }, { "add-if", 2, INT_MAX, do_add_if }, diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c index 665a2c7a..934c2741 100644 --- a/utilities/ovs-ofctl.c +++ b/utilities/ovs-ofctl.c @@ -59,68 +59,28 @@ #define MOD_PORT_CMD_FLOOD "flood" #define MOD_PORT_CMD_NOFLOOD "noflood" +/* Use strict matching for flow mod commands? */ +static bool strict; -/* Settings that may be configured by the user. */ -struct settings { - bool strict; /* Use strict matching for flow mod commands */ -}; - -struct command { - const char *name; - int min_args; - int max_args; - void (*handler)(const struct settings *, int argc, char *argv[]); -}; - -static struct command all_commands[]; +static const struct command all_commands[]; static void usage(void) NO_RETURN; -static void parse_options(int argc, char *argv[], struct settings *); +static void parse_options(int argc, char *argv[]); -int main(int argc, char *argv[]) +int +main(int argc, char *argv[]) { - struct settings s; - struct command *p; - set_program_name(argv[0]); time_init(); vlog_init(); - parse_options(argc, argv, &s); + parse_options(argc, argv); signal(SIGPIPE, SIG_IGN); - - argc -= optind; - argv += optind; - if (argc < 1) - ovs_fatal(0, "missing command name; use --help for help"); - - for (p = all_commands; p->name != NULL; p++) { - if (!strcmp(p->name, argv[0])) { - int n_arg = argc - 1; - if (n_arg < p->min_args) - ovs_fatal(0, "'%s' command requires at least %d arguments", - p->name, p->min_args); - else if (n_arg > p->max_args) - ovs_fatal(0, "'%s' command takes at most %d arguments", - p->name, p->max_args); - else { - p->handler(&s, argc, argv); - if (ferror(stdout)) { - ovs_fatal(0, "write to stdout failed"); - } - if (ferror(stderr)) { - ovs_fatal(0, "write to stderr failed"); - } - exit(0); - } - } - } - ovs_fatal(0, "unknown command '%s'; use --help for help", argv[0]); - + run_command(argc - optind, argv + optind, all_commands); return 0; } static void -parse_options(int argc, char *argv[], struct settings *s) +parse_options(int argc, char *argv[]) { enum { OPT_STRICT = UCHAR_MAX + 1 @@ -136,9 +96,6 @@ parse_options(int argc, char *argv[], struct settings *s) }; char *short_options = long_options_to_short_options(long_options); - /* Set defaults that we can figure out before parsing options. */ - s->strict = false; - for (;;) { unsigned long int timeout; int c; @@ -171,7 +128,7 @@ parse_options(int argc, char *argv[], struct settings *s) break; case OPT_STRICT: - s->strict = true; + strict = true; break; VCONN_SSL_OPTION_HANDLERS @@ -374,14 +331,14 @@ dump_trivial_stats_transaction(const char *vconn_name, uint8_t stats_type) } static void -do_show(const struct settings *s UNUSED, int argc UNUSED, char *argv[]) +do_show(int argc UNUSED, char *argv[]) { dump_trivial_transaction(argv[1], OFPT_FEATURES_REQUEST); dump_trivial_transaction(argv[1], OFPT_GET_CONFIG_REQUEST); } static void -do_status(const struct settings *s UNUSED, int argc, char *argv[]) +do_status(int argc, char *argv[]) { struct nicira_header *request, *reply; struct vconn *vconn; @@ -413,13 +370,13 @@ do_status(const struct settings *s UNUSED, int argc, char *argv[]) } static void -do_dump_desc(const struct settings *s UNUSED, int argc UNUSED, char *argv[]) +do_dump_desc(int argc UNUSED, char *argv[]) { dump_trivial_stats_transaction(argv[1], OFPST_DESC); } static void -do_dump_tables(const struct settings *s UNUSED, int argc UNUSED, char *argv[]) +do_dump_tables(int argc UNUSED, char *argv[]) { dump_trivial_stats_transaction(argv[1], OFPST_TABLE); } @@ -799,7 +756,7 @@ str_to_flow(char *string, struct ofp_match *match, struct ofpbuf *actions, } static void -do_dump_flows(const struct settings *s UNUSED, int argc, char *argv[]) +do_dump_flows(int argc, char *argv[]) { struct ofp_flow_stats_request *req; uint16_t out_port; @@ -815,7 +772,7 @@ do_dump_flows(const struct settings *s UNUSED, int argc, char *argv[]) } static void -do_dump_aggregate(const struct settings *s UNUSED, int argc, char *argv[]) +do_dump_aggregate(int argc, char *argv[]) { struct ofp_aggregate_stats_request *req; struct ofpbuf *request; @@ -831,7 +788,7 @@ do_dump_aggregate(const struct settings *s UNUSED, int argc, char *argv[]) } static void -do_add_flow(const struct settings *s UNUSED, int argc UNUSED, char *argv[]) +do_add_flow(int argc UNUSED, char *argv[]) { struct vconn *vconn; struct ofpbuf *buffer; @@ -859,7 +816,7 @@ do_add_flow(const struct settings *s UNUSED, int argc UNUSED, char *argv[]) } static void -do_add_flows(const struct settings *s UNUSED, int argc UNUSED, char *argv[]) +do_add_flows(int argc UNUSED, char *argv[]) { struct vconn *vconn; FILE *file; @@ -912,7 +869,7 @@ do_add_flows(const struct settings *s UNUSED, int argc UNUSED, char *argv[]) } static void -do_mod_flows(const struct settings *s, int argc UNUSED, char *argv[]) +do_mod_flows(int argc UNUSED, char *argv[]) { uint16_t priority, idle_timeout, hard_timeout; struct vconn *vconn; @@ -927,7 +884,7 @@ do_mod_flows(const struct settings *s, int argc UNUSED, char *argv[]) NULL, NULL, &priority, &idle_timeout, &hard_timeout); ofm = buffer->data; ofm->match = match; - if (s->strict) { + if (strict) { ofm->command = htons(OFPFC_MODIFY_STRICT); } else { ofm->command = htons(OFPFC_MODIFY); @@ -943,7 +900,7 @@ do_mod_flows(const struct settings *s, int argc UNUSED, char *argv[]) vconn_close(vconn); } -static void do_del_flows(const struct settings *s, int argc, char *argv[]) +static void do_del_flows(int argc, char *argv[]) { struct vconn *vconn; uint16_t priority; @@ -955,7 +912,7 @@ static void do_del_flows(const struct settings *s, int argc, char *argv[]) ofm = make_openflow(sizeof *ofm, OFPT_FLOW_MOD, &buffer); str_to_flow(argc > 2 ? argv[2] : "", &ofm->match, NULL, NULL, &out_port, &priority, NULL, NULL); - if (s->strict) { + if (strict) { ofm->command = htons(OFPFC_DELETE_STRICT); } else { ofm->command = htons(OFPFC_DELETE); @@ -973,7 +930,7 @@ static void do_del_flows(const struct settings *s, int argc, char *argv[]) } static void -do_monitor(const struct settings *s UNUSED, int argc UNUSED, char *argv[]) +do_monitor(int argc UNUSED, char *argv[]) { struct vconn *vconn; @@ -998,13 +955,13 @@ do_monitor(const struct settings *s UNUSED, int argc UNUSED, char *argv[]) } static void -do_dump_ports(const struct settings *s UNUSED, int argc UNUSED, char *argv[]) +do_dump_ports(int argc UNUSED, char *argv[]) { dump_trivial_stats_transaction(argv[1], OFPST_PORT); } static void -do_probe(const struct settings *s UNUSED, int argc UNUSED, char *argv[]) +do_probe(int argc UNUSED, char *argv[]) { struct ofpbuf *request; struct vconn *vconn; @@ -1021,7 +978,7 @@ do_probe(const struct settings *s UNUSED, int argc UNUSED, char *argv[]) } static void -do_mod_port(const struct settings *s UNUSED, int argc UNUSED, char *argv[]) +do_mod_port(int argc UNUSED, char *argv[]) { struct ofpbuf *request, *reply; struct ofp_switch_features *osf; @@ -1101,7 +1058,7 @@ do_mod_port(const struct settings *s UNUSED, int argc UNUSED, char *argv[]) } static void -do_ping(const struct settings *s UNUSED, int argc, char *argv[]) +do_ping(int argc, char *argv[]) { size_t max_payload = 65535 - sizeof(struct ofp_header); unsigned int payload; @@ -1148,7 +1105,7 @@ do_ping(const struct settings *s UNUSED, int argc, char *argv[]) } static void -do_benchmark(const struct settings *s UNUSED, int argc UNUSED, char *argv[]) +do_benchmark(int argc UNUSED, char *argv[]) { size_t max_payload = 65535 - sizeof(struct ofp_header); struct timeval start, end; @@ -1191,7 +1148,7 @@ do_benchmark(const struct settings *s UNUSED, int argc UNUSED, char *argv[]) } static void -do_execute(const struct settings *s UNUSED, int argc, char *argv[]) +do_execute(int argc, char *argv[]) { struct vconn *vconn; struct ofpbuf *request; @@ -1256,12 +1213,12 @@ do_execute(const struct settings *s UNUSED, int argc, char *argv[]) } static void -do_help(const struct settings *s UNUSED, int argc UNUSED, char *argv[] UNUSED) +do_help(int argc UNUSED, char *argv[] UNUSED) { usage(); } -static struct command all_commands[] = { +static const struct command all_commands[] = { { "show", 1, 1, do_show }, { "status", 1, 2, do_status }, { "monitor", 1, 3, do_monitor }, -- 2.30.2