Merge commit 'origin/citrix'
[sliver-openvswitch.git] / vswitchd / ovs-vswitchd.c
1 /* Copyright (c) 2008, 2009 Nicira Networks
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15
16 #include <config.h>
17
18 #include <assert.h>
19 #include <errno.h>
20 #include <getopt.h>
21 #include <limits.h>
22 #include <signal.h>
23 #include <stdlib.h>
24 #include <string.h>
25
26 #include "bridge.h"
27 #include "cfg.h"
28 #include "command-line.h"
29 #include "compiler.h"
30 #include "daemon.h"
31 #include "fault.h"
32 #include "leak-checker.h"
33 #include "mgmt.h"
34 #include "ovs-vswitchd.h"
35 #include "poll-loop.h"
36 #include "port.h"
37 #include "proc-net-compat.h"
38 #include "process.h"
39 #include "signals.h"
40 #include "svec.h"
41 #include "timeval.h"
42 #include "unixctl.h"
43 #include "util.h"
44 #include "vconn-ssl.h"
45 #include "vconn.h"
46
47 #include "vlog.h"
48 #define THIS_MODULE VLM_vswitchd
49
50 static void parse_options(int argc, char *argv[]);
51 static void usage(void) NO_RETURN;
52 static void reload(struct unixctl_conn *, const char *args);
53
54 static bool need_reconfigure;
55 static struct unixctl_conn **conns;
56 static size_t n_conns;
57
58 int
59 main(int argc, char *argv[])
60 {
61     struct unixctl_server *unixctl;
62     struct signal *sighup;
63     int retval;
64
65     set_program_name(argv[0]);
66     register_fault_handlers();
67     time_init();
68     vlog_init();
69     parse_options(argc, argv);
70     signal(SIGPIPE, SIG_IGN);
71     sighup = signal_register(SIGHUP);
72     process_init();
73
74     die_if_already_running();
75     daemonize();
76
77     retval = unixctl_server_create(NULL, &unixctl);
78     if (retval) {
79         ovs_fatal(retval, "could not listen for control connections");
80     }
81     unixctl_command_register("vswitchd/reload", reload);
82
83     cfg_read();
84     mgmt_init();
85     bridge_init();
86     port_init();
87     mgmt_reconfigure();
88
89     need_reconfigure = false;
90     for (;;) {
91         if (need_reconfigure || signal_poll(sighup)) {
92             need_reconfigure = false;
93             vlog_reopen_log_file();
94             reconfigure();
95         }
96         if (mgmt_run()) {
97             need_reconfigure = true;
98         }
99         if (bridge_run()) {
100             need_reconfigure = true;
101         }
102         unixctl_server_run(unixctl);
103
104         if (need_reconfigure) {
105             poll_immediate_wake();
106         }
107         signal_wait(sighup);
108         mgmt_wait();
109         bridge_wait();
110         unixctl_server_wait(unixctl);
111         poll_block();
112     }
113
114     return 0;
115 }
116
117 static void
118 reload(struct unixctl_conn *conn, const char *args UNUSED)
119 {
120     need_reconfigure = true;
121     conns = xrealloc(conns, sizeof *conns * (n_conns + 1));
122     conns[n_conns++] = conn;
123 }
124
125 void
126 reconfigure(void)
127 {
128     size_t i;
129
130     cfg_read();
131     bridge_reconfigure();
132     mgmt_reconfigure();
133     port_reconfigure();
134
135     for (i = 0; i < n_conns; i++) {
136         unixctl_command_reply(conns[i], 202, NULL);
137     }
138     free(conns);
139     conns = NULL;
140     n_conns = 0;
141 }
142
143 static void
144 parse_options(int argc, char *argv[])
145 {
146     enum {
147         OPT_PEER_CA_CERT = UCHAR_MAX + 1,
148         OPT_FAKE_PROC_NET,
149         VLOG_OPTION_ENUMS,
150         LEAK_CHECKER_OPTION_ENUMS
151     };
152     static struct option long_options[] = {
153         {"help",        no_argument, 0, 'h'},
154         {"version",     no_argument, 0, 'V'},
155         {"fake-proc-net", no_argument, 0, OPT_FAKE_PROC_NET},
156         DAEMON_LONG_OPTIONS,
157         VLOG_LONG_OPTIONS,
158         LEAK_CHECKER_LONG_OPTIONS,
159 #ifdef HAVE_OPENSSL
160         VCONN_SSL_LONG_OPTIONS
161         {"peer-ca-cert", required_argument, 0, OPT_PEER_CA_CERT},
162 #endif
163         {0, 0, 0, 0},
164     };
165     char *short_options = long_options_to_short_options(long_options);
166     const char *config_file;
167     int error;
168
169     for (;;) {
170         int c;
171
172         c = getopt_long(argc, argv, short_options, long_options, NULL);
173         if (c == -1) {
174             break;
175         }
176
177         switch (c) {
178         case 'H':
179         case 'h':
180             usage();
181
182         case 'V':
183             OVS_PRINT_VERSION(OFP_VERSION, OFP_VERSION);
184             exit(EXIT_SUCCESS);
185
186         case OPT_FAKE_PROC_NET:
187             error = proc_net_compat_init();
188             if (error) {
189                 ovs_fatal(error, "failed to initialize /proc/net "
190                           "compatibility");
191             }
192             break;
193
194         VLOG_OPTION_HANDLERS
195         DAEMON_OPTION_HANDLERS
196         VCONN_SSL_OPTION_HANDLERS
197         LEAK_CHECKER_OPTION_HANDLERS
198
199 #ifdef HAVE_OPENSSL
200         case OPT_PEER_CA_CERT:
201             vconn_ssl_set_peer_ca_cert_file(optarg);
202             break;
203 #endif
204
205         case '?':
206             exit(EXIT_FAILURE);
207
208         default:
209             abort();
210         }
211     }
212     free(short_options);
213
214     argc -= optind;
215     argv += optind;
216
217     if (argc != 1) {
218         ovs_fatal(0, "config file is only non-option argument; "
219                 "use --help for usage");
220     }
221
222     config_file = argv[0];
223     error = cfg_set_file(config_file);
224     if (error) {
225        ovs_fatal(error, "failed to add configuration file \"%s\"", 
226                 config_file);
227     }
228 }
229
230 static void
231 usage(void)
232 {
233     printf("%s: Open vSwitch daemon\n"
234            "usage: %s [OPTIONS] CONFIG\n"
235            "CONFIG is a configuration file in ovs-vswitchd.conf(5) format.\n",
236            program_name, program_name);
237     daemon_usage();
238     vlog_usage();
239     printf("\nLegacy compatibility options:\n"
240            " --fake-proc-net          simulate some files in /proc/net\n"
241            "\nOther options:\n"
242            "  -h, --help              display this help message\n"
243            "  -V, --version           display version information\n");
244     leak_checker_usage();
245     exit(EXIT_SUCCESS);
246 }