int uinet_demo_process_args(struct uinet_demo_config *cfg, int argc, char **argv) { int oldopterr; int rv; oldopterr = opterr; opterr = 0; rv = demo_db[cfg->which].process_args(cfg, argc, argv); opterr = oldopterr; /* missing required argument to known option */ if (rv == ':') { printf("%s option `%s' requires an argument\n", uinet_demo_name(cfg->which), argv[optind-1]); return (-1); /* caller should stop argument processing */ } /* unknown option */ if (rv == '?') { optind--; /* move index back to point to option that was unknown */ return (0); /* caller should continue argument processing */ } /* invalid argument to known option */ if (rv > 0) { return (-1); /* caller should stop argument processing */ } /* rv is -1, caller should continue processing to notice end-of-arguments */ return (0); }
static void uinet_demo_base_init_cfg(struct uinet_demo_config *cfg, enum uinet_demo_id which, uint64_t instance_id, const char *name, int verbose) { if (name) snprintf(cfg->name, sizeof(cfg->name), "%s", name); else snprintf(cfg->name, sizeof(cfg->name), "%s %llu", uinet_demo_name(which), (unsigned long long)instance_id); cfg->id = instance_id; cfg->which = which; cfg->verbose = verbose; cfg->copy_every = 1; }
static void print_cfg(struct event_loop_config *elcfgs, unsigned int num_event_loops) { unsigned int i, j; unsigned int bridge_tos; struct event_loop_config *curloopcfg; struct stack_config *curstackcfg; struct interface_config *curifcfg; struct uinet_demo_config *curappcfg; unsigned int stack_index; unsigned int if_index; unsigned int app_index; int rxcpu, txcpu; for (i = 0; i < num_event_loops; i++) { curloopcfg = &elcfgs[i]; printf("Event loop [%s]: cpu=", curloopcfg->name); if (curloopcfg->cpu < 0) printf("auto"); else printf("%u", curloopcfg->cpu); printf("\n"); for (stack_index = 0; stack_index < curloopcfg->num_stacks; stack_index++) { curstackcfg = curloopcfg->scfgs[stack_index]; printf(" Stack instance [%s]: sts-mode=%s\n", curstackcfg->name, curstackcfg->sts ? "yes" : "no"); for (if_index = 0; if_index < curstackcfg->num_ifs; if_index++) { curifcfg = curstackcfg->ifcfgs[if_index]; printf(" Interface [%s (%s)]: type=%s rxbatch=%u txiqlen=%u gen=%s len=%u", curifcfg->ucfg.alias, curifcfg->ucfg.configstr, curifcfg->type_name, curifcfg->ucfg.rx_batch_size, curifcfg->ucfg.tx_inject_queue_len, curifcfg->generate ? "yes" : "no", curifcfg->generate ? curifcfg->gen_len : 0); printf(" bridge_to="); if (curifcfg->num_bridge_to) { for (j = 0; j < curifcfg->num_bridge_to; j++) { printf("%s%s (%s)", (j > 0) ? "," : "", curifcfg->bridge_to[j]->ucfg.alias, curifcfg->bridge_to[j]->ucfg.configstr); } } else printf("<none>"); if (curstackcfg->sts) txcpu = rxcpu = curloopcfg->cpu; else { txcpu = curifcfg->ucfg.tx_cpu; rxcpu = curifcfg->ucfg.rx_cpu; } print_cpu(" rxcpu", txcpu); print_cpu(" txcpu", txcpu); print_timestamp_mode(" tstamp", curifcfg->ucfg.timestamp_mode); switch (curifcfg->ucfg.type) { case UINET_IFTYPE_NETMAP: printf(" trace=0x%08x", curifcfg->ucfg.type_cfg.netmap.trace_mask); printf(" valebufs=%u", curifcfg->ucfg.type_cfg.netmap.vale_num_extra_bufs); break; case UINET_IFTYPE_PCAP: printf(" txio=%s", curifcfg->ucfg.type_cfg.pcap.use_file_io_thread ? "remote" : "local"); printf(" txsnaplen=%u", curifcfg->ucfg.type_cfg.pcap.file_snapshot_length); printf(" txfiles=%s", curifcfg->ucfg.type_cfg.pcap.file_per_flow ? "per-flow" : "single"); printf(" txmaxfds=%u", curifcfg->ucfg.type_cfg.pcap.max_concurrent_files); printf(" txdirbits=%u", curifcfg->ucfg.type_cfg.pcap.dir_bits); break; default: break; } printf("\n"); } if (if_index == 0) printf(" <no interfaces>\n"); for (app_index = 0; app_index < curstackcfg->num_apps; app_index++) { curappcfg = curstackcfg->acfgs[app_index]; printf(" %s [%s]: ", uinet_demo_name(curappcfg->which), curappcfg->name); uinet_demo_print_cfg(curappcfg); printf("\n"); } if (app_index == 0) printf(" <no apps>\n"); } if (stack_index == 0) printf(" <no stacks>\n"); } }
static void usage(const char *progname) { unsigned int i; printf("\n"); printf("Usage: %s [global] [default loop] [default stack] [[intf|app] ... ] [loop [stack [intf|app] ... ] ... ] ...\n", progname); printf("\n"); printf("This is a tool for creating and arranging libev event loops, libuinet\n"); printf("stack instances, libuinet network interfaces, and libuinet demo apps.\n"); printf("The model is that an event loop contains stack instances, and a stack\n"); printf("instance contains network interfaces and demo apps. That is not the\n"); printf("only way things can be arranged with libuinet, but it covers most of\n"); printf("the sensible cases.\n"); printf("\n"); printf("Global options:\n"); printf("\n"); printf(" --base-config [small|medium|large]\n"); printf(" Choose base global config to use (default 'medium')\n"); printf(" --config-only, -N Print the configuration and exit (can be specified at any point)\n"); printf(" --help, -h Print this message (can be specified at any point)\n"); printf(" --max-accept-queue <value>\n"); printf(" Set the maximum listen socket accept queue length\n"); printf(" --max-clusters <value> Set the upper limit on the global mbuf cluster pool size\n"); printf(" --max-sockets <value> Set the maximum number of sockets per stack instance\n"); printf(" --netmap-extra-bufs <buffers>\n"); printf(" Size of process-wide netmap extra buffer pool shared by netmapped physical interfaces\n"); printf(" --syncache-hash-size <value>\n"); printf(" Set the number of buckets in each stack instance's syncache hash\n"); printf(" --syncache-bucket-limit <value>\n"); printf(" Set the maximum number of entries in each syncache hash bucket\n"); printf(" --syncache-cache-limit <value>\n"); printf(" Set the maximum number of entries in each stack instance's syncache\n"); printf(" --tcb-hash-size <value> Set the number of buckets in each stack instance's tcp connection hash\n"); printf(" --verbose, -v [=level] Increase baseline verbosity, or set to given level (can use multiple times)\n"); printf("\n"); printf("Event loop options:\n"); printf("\n"); printf(" --eloop, -e Create a new event loop\n"); printf(" --eloop-cpu, -c <cpu> Bind the current event loop to the given CPU\n"); printf(" --stats, -m [=interval] Print stats for event loop and all it contains every <interval> seconds (default 1)\n"); printf(" --verbose, -v [=level] Increase event loop verbosity above the baseline, or set to given level (can use multiple times)\n"); printf("\n"); printf("Stack instance options:\n"); printf("\n"); printf(" --brief-tcp-stats [=interval]\n"); printf(" Print brief TCP stats every <interval> seconds (default 1)\n"); printf(" --stack, -s [=name] Create a new stack instance in the current event loop, with optional name\n"); printf(" --sts, -S Run stack instance in single-thread-stack mode\n"); printf(" --syncache-stats Print syncache stats for this stack instance when event loop stats are enabled\n"); printf("\n"); printf("Interface creation options:\n"); printf("\n"); printf(" --netmap, -n <config> Create a new netmap interface in the current stack using the given config string\n"); printf(" --pcap, -p <config> Create a new pcap interface in the current stack using the given config string\n"); printf("\n"); printf("General interface configuration options:\n"); printf("\n"); printf(" --bridge-to, -b <intf_list>\n"); printf(" Transmit all inbound packets on this interface from each of the given list of interfaces\n"); printf(" --gen, -g [=packet_len] Generate transmit packets of the given size (default %u)\n", DEFAULT_GEN_LEN); printf(" --iqlen, -I <value> Set max transmit inject queue length\n"); printf(" --pcap-tx-file-dirbits <n>\n"); printf(" Set number of bits of flow serial number to use for choosing subdirectories in pcap file-per-flow transmit-to-file mode (default 10)\n"); printf(" --pcap-tx-file-mode <mode>\n"); printf(" Set pcap transmit-to-file mode to one of [single-file, file-per-flow] (default single-file)\n"); printf(" --rxbatch, -R <value> Set receive processing batch size limit\n"); printf(" --rxcpu, -r <cpu> Bind interface receive thread to the given CPU (ignored in STS mode)\n"); printf(" --txcpu, -t <cpu> Bind interface transmit thread to the given CPU (ignored in STS mode)\n"); printf(" --timestamp-mode, -T <mode>\n"); printf(" Set interface timestamp mode to one of:\n"); for (i = 0; i < sizeof(timestamp_mode_table) / sizeof(timestamp_mode_table[0]); i++) { printf(" %16s %s\n", timestamp_mode_table[i].name, timestamp_mode_table[i].desc); } printf(" --trace-mask, -Z <mask> Mask of driver trace message enables (see driver source)\n"); printf("\n"); printf("Demo app creation options:\n"); printf("\n"); printf(" --connscale, -C [=name] Create a connscale client or server in the current stack, with optional name\n"); printf(" --echo, -E [=name] Create an echo server in the current stack, with optional name\n"); printf(" --nproxy, -O [=name] Create a non-transparent proxy server in the current stack, with optional name\n"); printf(" --passive, -P [=name] Create a passive reassembly server in the current stack, with optional name\n"); printf(" --passive-extract, -X [=name]\n"); printf(" Create a passive reassembly server that extracts http payloads in the current stack, with optional name\n"); printf("\n"); for (i = 0; i < UINET_NUM_DEMO_APPS; i++) { printf("Options for configuring %s instances:\n", uinet_demo_name(i)); printf("\n"); uinet_demo_print_usage(i); printf("\n"); } }