2
0
mirror of https://github.com/openvswitch/ovs synced 2025-10-21 14:49:41 +00:00
Files
openvswitch/vswitchd/ovs-vswitchd.c
Ben Pfaff cc01d0bb79 Implement stress option framework.
Stress options allow developers testing Open vSwitch to trigger behavior
that otherwise would occur only in corner cases.  Developers and testers
can thereby more easily discover bugs that would otherwise manifest only
rarely or nondeterministically.  Stress options may cause surprising
behavior even when they do not actually reveal bugs, so they should only be
enabled as part of testing Open vSwitch.

This commit implements the framework and adds a few example stress options.

This commit started from code written by Andrew Lambeth.

Suggested-by: Henrik Amren <henrik@nicira.com>
CC: Andrew Lambeth <wal@nicira.com>
2010-11-30 13:44:01 -08:00

247 lines
6.0 KiB
C

/* Copyright (c) 2008, 2009, 2010 Nicira Networks
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <config.h>
#include <assert.h>
#include <errno.h>
#include <getopt.h>
#include <limits.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_MLOCKALL
#include <sys/mman.h>
#endif
#include "bridge.h"
#include "command-line.h"
#include "compiler.h"
#include "daemon.h"
#include "dpif.h"
#include "dummy.h"
#include "leak-checker.h"
#include "netdev.h"
#include "ovsdb-idl.h"
#include "poll-loop.h"
#include "proc-net-compat.h"
#include "process.h"
#include "signals.h"
#include "stream-ssl.h"
#include "stream.h"
#include "stress.h"
#include "svec.h"
#include "timeval.h"
#include "unixctl.h"
#include "util.h"
#include "vconn.h"
#include "vlog.h"
#include "vswitchd/vswitch-idl.h"
VLOG_DEFINE_THIS_MODULE(vswitchd);
static unixctl_cb_func ovs_vswitchd_exit;
static const char *parse_options(int argc, char *argv[]);
static void usage(void) NO_RETURN;
int
main(int argc, char *argv[])
{
struct unixctl_server *unixctl;
struct signal *sighup;
const char *remote;
bool exiting;
int retval;
proctitle_init(argc, argv);
set_program_name(argv[0]);
stress_init_command();
remote = parse_options(argc, argv);
signal(SIGPIPE, SIG_IGN);
sighup = signal_register(SIGHUP);
process_init();
ovsrec_init();
die_if_already_running();
daemonize_start();
retval = unixctl_server_create(NULL, &unixctl);
if (retval) {
exit(EXIT_FAILURE);
}
unixctl_command_register("exit", ovs_vswitchd_exit, &exiting);
daemonize_complete();
bridge_init(remote);
exiting = false;
while (!exiting) {
if (signal_poll(sighup)) {
vlog_reopen_log_file();
}
bridge_run();
unixctl_server_run(unixctl);
dp_run();
netdev_run();
signal_wait(sighup);
bridge_wait();
unixctl_server_wait(unixctl);
dp_wait();
netdev_wait();
if (exiting) {
poll_immediate_wake();
}
poll_block();
}
return 0;
}
static const char *
parse_options(int argc, char *argv[])
{
enum {
OPT_PEER_CA_CERT = UCHAR_MAX + 1,
OPT_MLOCKALL,
OPT_FAKE_PROC_NET,
VLOG_OPTION_ENUMS,
LEAK_CHECKER_OPTION_ENUMS,
OPT_BOOTSTRAP_CA_CERT,
OPT_ENABLE_DUMMY
};
static struct option long_options[] = {
{"help", no_argument, 0, 'h'},
{"version", no_argument, 0, 'V'},
{"mlockall", no_argument, 0, OPT_MLOCKALL},
{"fake-proc-net", no_argument, 0, OPT_FAKE_PROC_NET},
DAEMON_LONG_OPTIONS,
VLOG_LONG_OPTIONS,
LEAK_CHECKER_LONG_OPTIONS,
#ifdef HAVE_OPENSSL
STREAM_SSL_LONG_OPTIONS
{"peer-ca-cert", required_argument, 0, OPT_PEER_CA_CERT},
{"bootstrap-ca-cert", required_argument, 0, OPT_BOOTSTRAP_CA_CERT},
#endif
{"enable-dummy", no_argument, 0, OPT_ENABLE_DUMMY},
{0, 0, 0, 0},
};
char *short_options = long_options_to_short_options(long_options);
int error;
for (;;) {
int c;
c = getopt_long(argc, argv, short_options, long_options, NULL);
if (c == -1) {
break;
}
switch (c) {
case 'H':
case 'h':
usage();
case 'V':
OVS_PRINT_VERSION(OFP_VERSION, OFP_VERSION);
exit(EXIT_SUCCESS);
case OPT_MLOCKALL:
#ifdef HAVE_MLOCKALL
if (mlockall(MCL_CURRENT | MCL_FUTURE)) {
VLOG_ERR("mlockall failed: %s", strerror(errno));
}
#else
VLOG_ERR("mlockall not supported on this system");
#endif
break;
case OPT_FAKE_PROC_NET:
error = proc_net_compat_init();
if (error) {
ovs_fatal(error, "failed to initialize /proc/net "
"compatibility");
}
break;
VLOG_OPTION_HANDLERS
DAEMON_OPTION_HANDLERS
LEAK_CHECKER_OPTION_HANDLERS
#ifdef HAVE_OPENSSL
STREAM_SSL_OPTION_HANDLERS
case OPT_PEER_CA_CERT:
stream_ssl_set_peer_ca_cert_file(optarg);
break;
case OPT_BOOTSTRAP_CA_CERT:
stream_ssl_set_ca_cert_file(optarg, true);
break;
#endif
case OPT_ENABLE_DUMMY:
dummy_enable();
break;
case '?':
exit(EXIT_FAILURE);
default:
abort();
}
}
free(short_options);
argc -= optind;
argv += optind;
if (argc != 1) {
ovs_fatal(0, "database socket is only non-option argument; "
"use --help for usage");
}
return argv[0];
}
static void
usage(void)
{
printf("%s: Open vSwitch daemon\n"
"usage: %s [OPTIONS] DATABASE\n"
"where DATABASE is a socket on which ovsdb-server is listening.\n",
program_name, program_name);
stream_usage("DATABASE", true, false, true);
daemon_usage();
vlog_usage();
printf("\nLegacy compatibility options:\n"
" --fake-proc-net simulate some files in /proc/net\n"
"\nOther options:\n"
" -h, --help display this help message\n"
" -V, --version display version information\n");
leak_checker_usage();
exit(EXIT_SUCCESS);
}
static void
ovs_vswitchd_exit(struct unixctl_conn *conn, const char *args OVS_UNUSED,
void *exiting_)
{
bool *exiting = exiting_;
*exiting = true;
unixctl_command_reply(conn, 200, NULL);
}