int main(int argc, char *argv[]) { char *unixctl_path = NULL; struct unixctl_server *unixctl; char *remote; bool exiting; int retval; set_program_name(argv[0]); retval = dpdk_init(argc,argv); argc -= retval; argv += retval; ovs_cmdl_proctitle_init(argc, argv); service_start(&argc, &argv); remote = parse_options(argc, argv, &unixctl_path); fatal_ignore_sigpipe(); ovsrec_init(); daemonize_start(); if (want_mlockall) { #ifdef HAVE_MLOCKALL if (mlockall(MCL_CURRENT | MCL_FUTURE)) { VLOG_ERR("mlockall failed: %s", ovs_strerror(errno)); } #else VLOG_ERR("mlockall not supported on this system"); #endif } retval = unixctl_server_create(unixctl_path, &unixctl); if (retval) { exit(EXIT_FAILURE); } unixctl_command_register("exit", "", 0, 0, ovs_vswitchd_exit, &exiting); bridge_init(remote); free(remote); exiting = false; while (!exiting) { memory_run(); if (memory_should_report()) { struct simap usage; simap_init(&usage); bridge_get_memory_usage(&usage); memory_report(&usage); simap_destroy(&usage); } bridge_run(); unixctl_server_run(unixctl); netdev_run(); memory_wait(); bridge_wait(); unixctl_server_wait(unixctl); netdev_wait(); if (exiting) { poll_immediate_wake(); } poll_block(); if (should_service_stop()) { exiting = true; } } bridge_exit(); unixctl_server_destroy(unixctl); service_stop(); return 0; }
int main(int argc, char *argv[]) { struct unixctl_server *unixctl; bool exiting; int retval; ovs_cmdl_proctitle_init(argc, argv); set_program_name(argv[0]); parse_options(argc, argv); fatal_ignore_sigpipe(); daemonize_start(); retval = unixctl_server_create(NULL, &unixctl); if (retval) { exit(EXIT_FAILURE); } unixctl_command_register("exit", "", 0, 0, ovn_controller_exit, &exiting); daemonize_complete(); ovsrec_init(); sbrec_init(); ofctrl_init(); lflow_init(); /* Connect to OVS OVSDB instance. We do not monitor all tables by * default, so modules must register their interest explicitly. */ struct idl_loop ovs_idl_loop = IDL_LOOP_INITIALIZER( ovsdb_idl_create(ovs_remote, &ovsrec_idl_class, false, true)); ovsdb_idl_add_table(ovs_idl_loop.idl, &ovsrec_table_open_vswitch); ovsdb_idl_add_column(ovs_idl_loop.idl, &ovsrec_open_vswitch_col_external_ids); chassis_register_ovs_idl(ovs_idl_loop.idl); encaps_register_ovs_idl(ovs_idl_loop.idl); binding_register_ovs_idl(ovs_idl_loop.idl); physical_register_ovs_idl(ovs_idl_loop.idl); get_initial_snapshot(ovs_idl_loop.idl); /* Connect to OVN SB database. */ char *ovnsb_remote = get_ovnsb_remote(ovs_idl_loop.idl); struct idl_loop ovnsb_idl_loop = IDL_LOOP_INITIALIZER( ovsdb_idl_create(ovnsb_remote, &sbrec_idl_class, true, true)); get_initial_snapshot(ovnsb_idl_loop.idl); /* Main loop. */ exiting = false; while (!exiting) { struct controller_ctx ctx = { .ovs_idl = ovs_idl_loop.idl, .ovs_idl_txn = idl_loop_run(&ovs_idl_loop), .ovnsb_idl = ovnsb_idl_loop.idl, .ovnsb_idl_txn = idl_loop_run(&ovnsb_idl_loop), }; const struct ovsrec_bridge *br_int = get_br_int(ctx.ovs_idl); const char *chassis_id = get_chassis_id(ctx.ovs_idl); if (chassis_id) { chassis_run(&ctx, chassis_id); encaps_run(&ctx, br_int, chassis_id); binding_run(&ctx, br_int, chassis_id); } if (br_int) { struct hmap flow_table = HMAP_INITIALIZER(&flow_table); lflow_run(&ctx, &flow_table); if (chassis_id) { physical_run(&ctx, br_int, chassis_id, &flow_table); } ofctrl_run(br_int, &flow_table); hmap_destroy(&flow_table); } unixctl_server_run(unixctl); unixctl_server_wait(unixctl); if (exiting) { poll_immediate_wake(); } idl_loop_commit_and_wait(&ovnsb_idl_loop); idl_loop_commit_and_wait(&ovs_idl_loop); if (br_int) { ofctrl_wait(); } poll_block(); } /* It's time to exit. Clean up the databases. */ bool done = false; while (!done) { struct controller_ctx ctx = { .ovs_idl = ovs_idl_loop.idl, .ovs_idl_txn = idl_loop_run(&ovs_idl_loop), .ovnsb_idl = ovnsb_idl_loop.idl, .ovnsb_idl_txn = idl_loop_run(&ovnsb_idl_loop), }; const struct ovsrec_bridge *br_int = get_br_int(ctx.ovs_idl); const char *chassis_id = get_chassis_id(ctx.ovs_idl); /* Run all of the cleanup functions, even if one of them returns false. * We're done if all of them return true. */ done = binding_cleanup(&ctx, chassis_id); done = chassis_cleanup(&ctx, chassis_id) && done; done = encaps_cleanup(&ctx, br_int) && done; if (done) { poll_immediate_wake(); } idl_loop_commit_and_wait(&ovnsb_idl_loop); idl_loop_commit_and_wait(&ovs_idl_loop); poll_block(); } unixctl_server_destroy(unixctl); lflow_destroy(); ofctrl_destroy(); idl_loop_destroy(&ovs_idl_loop); idl_loop_destroy(&ovnsb_idl_loop); free(ovnsb_remote); free(ovs_remote); exit(retval); } static void parse_options(int argc, char *argv[]) { enum { OPT_PEER_CA_CERT = UCHAR_MAX + 1, VLOG_OPTION_ENUMS, DAEMON_OPTION_ENUMS }; static struct option long_options[] = { {"help", no_argument, NULL, 'h'}, {"version", no_argument, NULL, 'V'}, VLOG_LONG_OPTIONS, DAEMON_LONG_OPTIONS, STREAM_SSL_LONG_OPTIONS, {"peer-ca-cert", required_argument, NULL, OPT_PEER_CA_CERT}, {NULL, 0, NULL, 0} }; char *short_options = ovs_cmdl_long_options_to_short_options(long_options); for (;;) { int c; c = getopt_long(argc, argv, short_options, long_options, NULL); if (c == -1) { break; } switch (c) { case 'h': usage(); case 'V': ovs_print_version(OFP13_VERSION, OFP13_VERSION); exit(EXIT_SUCCESS); VLOG_OPTION_HANDLERS DAEMON_OPTION_HANDLERS STREAM_SSL_OPTION_HANDLERS case OPT_PEER_CA_CERT: stream_ssl_set_peer_ca_cert_file(optarg); break; case '?': exit(EXIT_FAILURE); default: abort(); } } free(short_options); argc -= optind; argv += optind; if (argc == 0) { ovs_remote = xasprintf("unix:%s/db.sock", ovs_rundir()); } else if (argc == 1) { ovs_remote = xstrdup(argv[0]); } else { VLOG_FATAL("exactly zero or one non-option argument required; " "use --help for usage"); } } static void usage(void) { printf("%s: OVN controller\n" "usage %s [OPTIONS] [OVS-DATABASE]\n" "where OVS-DATABASE is a socket on which the OVS OVSDB server is listening.\n", program_name, program_name); stream_usage("OVS-DATABASE", true, false, false); daemon_usage(); vlog_usage(); printf("\nOther options:\n" " -h, --help display this help message\n" " -V, --version display version information\n"); exit(EXIT_SUCCESS); } static void ovn_controller_exit(struct unixctl_conn *conn, int argc OVS_UNUSED, const char *argv[] OVS_UNUSED, void *exiting_) { bool *exiting = exiting_; *exiting = true; unixctl_command_reply(conn, NULL); }
static void test_jsonrpc_main(int argc, char *argv[]) { struct ovs_cmdl_context ctx = { .argc = 0, }; ovs_cmdl_proctitle_init(argc, argv); set_program_name(argv[0]); service_start(&argc, &argv); parse_options(argc, argv); ctx.argc = argc - optind; ctx.argv = argv + optind; ovs_cmdl_run_command(&ctx, get_all_commands()); } static void parse_options(int argc, char *argv[]) { enum { OPT_BOOTSTRAP_CA_CERT = UCHAR_MAX + 1, DAEMON_OPTION_ENUMS }; static const struct option long_options[] = { {"verbose", optional_argument, NULL, 'v'}, {"help", no_argument, NULL, 'h'}, DAEMON_LONG_OPTIONS, {"bootstrap-ca-cert", required_argument, NULL, OPT_BOOTSTRAP_CA_CERT}, STREAM_SSL_LONG_OPTIONS, {NULL, 0, NULL, 0}, }; char *short_options = ovs_cmdl_long_options_to_short_options(long_options); for (;;) { int c = getopt_long(argc, argv, short_options, long_options, NULL); if (c == -1) { break; } switch (c) { case 'h': usage(); case 'v': vlog_set_verbosity(optarg); break; DAEMON_OPTION_HANDLERS STREAM_SSL_OPTION_HANDLERS case OPT_BOOTSTRAP_CA_CERT: stream_ssl_set_ca_cert_file(optarg, true); break; case '?': exit(EXIT_FAILURE); default: abort(); } } free(short_options); } static void usage(void) { printf("%s: JSON-RPC test utility\n" "usage: %s [OPTIONS] COMMAND [ARG...]\n" " listen LOCAL listen for connections on LOCAL\n" " request REMOTE METHOD PARAMS send request, print reply\n" " notify REMOTE METHOD PARAMS send notification and exit\n", program_name, program_name); stream_usage("JSON-RPC", true, true, true); daemon_usage(); vlog_usage(); printf("\nOther options:\n" " -h, --help display this help message\n"); exit(EXIT_SUCCESS); }
int main(int argc, char *argv[]) { const struct ovsdb_client_command *command; char *database; struct jsonrpc *rpc; ovs_cmdl_proctitle_init(argc, argv); set_program_name(argv[0]); parse_options(argc, argv); fatal_ignore_sigpipe(); daemon_become_new_user(false); if (optind >= argc) { ovs_fatal(0, "missing command name; use --help for help"); } for (command = get_all_commands(); ; command++) { if (!command->name) { VLOG_FATAL("unknown command '%s'; use --help for help", argv[optind]); } else if (!strcmp(command->name, argv[optind])) { break; } } optind++; if (command->need != NEED_NONE) { if (argc - optind > command->min_args && (isalpha((unsigned char) argv[optind][0]) && strchr(argv[optind], ':'))) { rpc = open_jsonrpc(argv[optind++]); } else { char *sock = xasprintf("unix:%s/db.sock", ovs_rundir()); rpc = open_jsonrpc(sock); free(sock); } } else { rpc = NULL; } if (command->need == NEED_DATABASE) { struct svec dbs; svec_init(&dbs); fetch_dbs(rpc, &dbs); if (argc - optind > command->min_args && svec_contains(&dbs, argv[optind])) { database = xstrdup(argv[optind++]); } else if (dbs.n == 1) { database = xstrdup(dbs.names[0]); } else if (svec_contains(&dbs, "Open_vSwitch")) { database = xstrdup("Open_vSwitch"); } else { jsonrpc_close(rpc); ovs_fatal(0, "no default database for `%s' command, please " "specify a database name", command->name); } svec_destroy(&dbs); } else { database = NULL; } if (argc - optind < command->min_args || argc - optind > command->max_args) { free(database); VLOG_FATAL("invalid syntax for '%s' (use --help for help)", command->name); } command->handler(rpc, database, argc - optind, argv + optind); free(database); jsonrpc_close(rpc); if (ferror(stdout)) { VLOG_FATAL("write to stdout failed"); } if (ferror(stderr)) { VLOG_FATAL("write to stderr failed"); } return 0; }