From 9974174d5b7719fe03d36fefe12a4c02f4b4d048 Mon Sep 17 00:00:00 2001 From: Robert McMahon Date: Mon, 22 Dec 2025 12:27:12 -0800 Subject: [PATCH] use sub commands for iperf major command --- components/app_console/cmd_iperf.c | 268 +++++++++++++++++++---------- 1 file changed, 178 insertions(+), 90 deletions(-) diff --git a/components/app_console/cmd_iperf.c b/components/app_console/cmd_iperf.c index 7d0fc90..969b101 100644 --- a/components/app_console/cmd_iperf.c +++ b/components/app_console/cmd_iperf.c @@ -30,7 +30,6 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ - #include #include #include "esp_log.h" @@ -40,112 +39,201 @@ #include "iperf.h" #include "app_console.h" +// --- Forward Declarations --- +static int iperf_do_start(int argc, char **argv); +static int iperf_do_stop(int argc, char **argv); +static int iperf_do_status(int argc, char **argv); +static int iperf_do_set(int argc, char **argv); +static int iperf_do_save(int argc, char **argv); +static int iperf_do_reload(int argc, char **argv); +static int iperf_do_clear(int argc, char **argv); + // ============================================================================ -// COMMAND: iperf +// COMMAND: iperf (Dispatcher) // ============================================================================ -static struct { - struct arg_lit *start, *stop, *status, *save, *reload; - struct arg_lit *clear_nvs; - struct arg_str *ip; - struct arg_int *port, *pps, *len, *burst; - struct arg_lit *help; - struct arg_end *end; -} iperf_args; +static void print_iperf_usage(void) { + printf("Usage: iperf [args]\n"); + printf("Subcommands:\n"); + printf(" start Start traffic generation\n"); + printf(" stop Stop traffic generation\n"); + printf(" status Show current statistics\n"); + printf(" set Configure parameters (IP, Port, PPS, etc.)\n"); + printf(" save Save configuration to NVS\n"); + printf(" reload Reload configuration from NVS\n"); + printf(" clear Reset configuration to defaults\n"); + printf("\nType 'iperf --help' for details.\n"); +} static int cmd_iperf(int argc, char **argv) { - int nerrors = arg_parse(argc, argv, (void **)&iperf_args); - if (nerrors > 0) { - arg_print_errors(stderr, iperf_args.end, argv[0]); - return 1; - } - - if (iperf_args.help->count > 0) { - printf("Usage: iperf [options]\n"); - printf(" --start Start traffic\n"); - printf(" --stop Stop traffic\n"); - printf(" --save Save config to NVS\n"); - printf(" --reload Reload config from NVS\n"); - printf(" --clear-nvs Reset to defaults\n"); - printf(" -c Set Dest IP\n"); - printf(" --pps Set Packets Per Sec\n"); + if (argc < 2 || strcmp(argv[1], "help") == 0 || strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-h") == 0) { + print_iperf_usage(); return 0; } - // --- Actions: NVS Management --- - if (iperf_args.clear_nvs->count > 0) { - iperf_param_clear(); - printf("iPerf Configuration cleared (Reset to defaults).\n"); - app_console_update_prompt(); - return 0; - } + if (strcmp(argv[1], "start") == 0) return iperf_do_start(argc - 1, &argv[1]); + if (strcmp(argv[1], "stop") == 0) return iperf_do_stop(argc - 1, &argv[1]); + if (strcmp(argv[1], "status") == 0) return iperf_do_status(argc - 1, &argv[1]); + if (strcmp(argv[1], "set") == 0) return iperf_do_set(argc - 1, &argv[1]); + if (strcmp(argv[1], "save") == 0) return iperf_do_save(argc - 1, &argv[1]); + if (strcmp(argv[1], "reload") == 0) return iperf_do_reload(argc - 1, &argv[1]); + if (strcmp(argv[1], "clear") == 0) return iperf_do_clear(argc - 1, &argv[1]); - if (iperf_args.reload->count > 0) { - iperf_param_init(); // Force re-read - printf("Configuration reloaded from NVS.\n"); - } + printf("Unknown subcommand '%s'.\n", argv[1]); + print_iperf_usage(); + return 1; +} - // --- Actions: Parameter Updates --- - bool config_changed = false; - iperf_cfg_t cfg; - iperf_param_get(&cfg); // Get current staging - - if (iperf_args.ip->count > 0) { cfg.dip = inet_addr(iperf_args.ip->sval[0]); config_changed = true; } - if (iperf_args.port->count > 0) { cfg.dport = (uint16_t)iperf_args.port->ival[0]; config_changed = true; } - if (iperf_args.len->count > 0) { cfg.send_len = (uint32_t)iperf_args.len->ival[0]; config_changed = true; } - if (iperf_args.burst->count > 0) { cfg.burst_count = (uint32_t)iperf_args.burst->ival[0]; config_changed = true; } - if (iperf_args.pps->count > 0) { - if (iperf_args.pps->ival[0] > 0) { - cfg.target_pps = (uint32_t)iperf_args.pps->ival[0]; - config_changed = true; - } - } - - if (config_changed) { - iperf_param_set(&cfg); - printf("RAM configuration updated.\n"); - } - - if (iperf_args.save->count > 0) { - bool changed = false; - if (iperf_param_save(&changed) == ESP_OK) { - printf(changed ? "Configuration saved to NVS.\n" : "No changes to save (NVS matches RAM).\n"); - } else { - printf("Error saving to NVS.\n"); - } - } - - // --- Actions: Execution --- - if (iperf_args.stop->count > 0) iperf_stop(); - if (iperf_args.start->count > 0) iperf_start(); - if (iperf_args.status->count > 0) iperf_print_status(); - - app_console_update_prompt(); +// ---------------------------------------------------------------------------- +// Sub-command: start +// ---------------------------------------------------------------------------- +static int iperf_do_start(int argc, char **argv) { + iperf_start(); return 0; } +// ---------------------------------------------------------------------------- +// Sub-command: stop +// ---------------------------------------------------------------------------- +static int iperf_do_stop(int argc, char **argv) { + iperf_stop(); + return 0; +} + +// ---------------------------------------------------------------------------- +// Sub-command: status +// ---------------------------------------------------------------------------- +static int iperf_do_status(int argc, char **argv) { + iperf_print_status(); + return 0; +} + +// ---------------------------------------------------------------------------- +// Sub-command: set (Configuration) +// ---------------------------------------------------------------------------- +static struct { + struct arg_str *ip; + struct arg_int *port; + struct arg_int *pps; + struct arg_int *len; + struct arg_int *burst; + struct arg_lit *help; + struct arg_end *end; +} set_args; + +static int iperf_do_set(int argc, char **argv) { + // REVERTED: Now uses standard iPerf syntax ("client" / "-c") + set_args.ip = arg_str0("c", "client", "", "Destination IP"); + set_args.port = arg_int0("p", "port", "", "Destination Port"); + set_args.pps = arg_int0(NULL, "pps", "", "Packets Per Second"); + set_args.len = arg_int0("l", "len", "", "Packet Length"); + set_args.burst = arg_int0("b", "burst", "", "Burst Count"); + set_args.help = arg_lit0("h", "help", "Help"); + set_args.end = arg_end(20); + + int nerrors = arg_parse(argc, argv, (void **)&set_args); + if (nerrors > 0) { + // --- CUSTOM ERROR HINTING --- + // Check if user tried to use "--ip" + for (int i = 0; i < argc; i++) { + if (strcmp(argv[i], "--ip") == 0) { + printf("Error: Invalid option '--ip'. Did you mean '--client' (or -c) to set the destination IP?\n"); + return 1; + } + } + // Fallback to standard error + arg_print_errors(stderr, set_args.end, argv[0]); + return 1; + } + + if (set_args.help->count > 0) { + printf("Usage: iperf set [options]\n"); + arg_print_glossary(stdout, (void **)&set_args, " %-25s %s\n"); + return 0; + } + + iperf_cfg_t cfg; + iperf_param_get(&cfg); + bool changed = false; + + if (set_args.ip->count > 0) { + cfg.dip = inet_addr(set_args.ip->sval[0]); + changed = true; + } + if (set_args.port->count > 0) { + cfg.dport = (uint16_t)set_args.port->ival[0]; + changed = true; + } + if (set_args.len->count > 0) { + cfg.send_len = (uint32_t)set_args.len->ival[0]; + changed = true; + } + if (set_args.burst->count > 0) { + cfg.burst_count = (uint32_t)set_args.burst->ival[0]; + changed = true; + } + if (set_args.pps->count > 0) { + if (set_args.pps->ival[0] > 0) { + cfg.target_pps = (uint32_t)set_args.pps->ival[0]; + changed = true; + } else { + printf("Error: PPS must be > 0.\n"); + return 1; + } + } + + if (changed) { + iperf_param_set(&cfg); + printf("Configuration updated (RAM only). Run 'iperf save' to persist.\n"); + } else { + printf("No changes specified.\n"); + } + + return 0; +} + +// ---------------------------------------------------------------------------- +// Sub-command: save +// ---------------------------------------------------------------------------- +static int iperf_do_save(int argc, char **argv) { + bool changed = false; + if (iperf_param_save(&changed) == ESP_OK) { + printf(changed ? "Configuration saved to NVS.\n" : "No changes to save (NVS matches RAM).\n"); + } else { + printf("Error saving to NVS.\n"); + } + return 0; +} + +// ---------------------------------------------------------------------------- +// Sub-command: reload +// ---------------------------------------------------------------------------- +static int iperf_do_reload(int argc, char **argv) { + iperf_param_init(); // Force re-read from NVS + printf("Configuration reloaded from NVS.\n"); + return 0; +} + +// ---------------------------------------------------------------------------- +// Sub-command: clear +// ---------------------------------------------------------------------------- +static int iperf_do_clear(int argc, char **argv) { + iperf_param_clear(); + printf("iPerf Configuration cleared (Reset to defaults).\n"); + return 0; +} + +// ---------------------------------------------------------------------------- +// Registration +// ---------------------------------------------------------------------------- + void register_iperf_cmd(void) { - iperf_args.start = arg_lit0(NULL, "start", "Start"); - iperf_args.stop = arg_lit0(NULL, "stop", "Stop"); - iperf_args.status = arg_lit0(NULL, "status", "Status"); - iperf_args.save = arg_lit0(NULL, "save", "Save"); - iperf_args.reload = arg_lit0(NULL, "reload", "Reload"); - iperf_args.clear_nvs = arg_lit0(NULL, "clear-nvs", "Clear NVS"); - - iperf_args.ip = arg_str0("c", "client", "", "IP"); - iperf_args.port = arg_int0("p", "port", "", "Port"); - iperf_args.pps = arg_int0(NULL, "pps", "", "PPS"); - iperf_args.len = arg_int0(NULL, "len", "", "Len"); - iperf_args.burst = arg_int0(NULL, "burst", "", "Burst"); - - iperf_args.help = arg_lit0("h", "help", "Help"); - iperf_args.end = arg_end(20); - const esp_console_cmd_t cmd = { .command = "iperf", - .help = "Traffic Gen", + .help = "Traffic Gen: start, stop, set, status", + .hint = " [args]", .func = &cmd_iperf, - .argtable = &iperf_args + .argtable = NULL }; ESP_ERROR_CHECK(esp_console_cmd_register(&cmd)); }