Import from old repository commit 61ef2b42a9c4ba8e1600f15bb0236765edc2ad45.
[openvswitch] / vswitchd / ovs-vswitchd.c
1 /* Copyright (c) 2008, 2009 Nicira Networks
2  * 
3  * This program is free software: you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License as published by
5  * the Free Software Foundation, either version 3 of the License, or
6  * (at your option) any later version.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
15  *
16  * In addition, as a special exception, Nicira Networks gives permission
17  * to link the code of its release of vswitchd with the OpenSSL project's
18  * "OpenSSL" library (or with modified versions of it that use the same
19  * license as the "OpenSSL" library), and distribute the linked
20  * executables.  You must obey the GNU General Public License in all
21  * respects for all of the code used other than "OpenSSL".  If you modify
22  * this file, you may extend this exception to your version of the file,
23  * but you are not obligated to do so.  If you do not wish to do so,
24  * delete this exception statement from your version.
25  */
26
27 #include <config.h>
28
29 #include <assert.h>
30 #include <errno.h>
31 #include <getopt.h>
32 #include <limits.h>
33 #include <signal.h>
34 #include <stdlib.h>
35 #include <string.h>
36
37 #include "bridge.h"
38 #include "cfg.h"
39 #include "command-line.h"
40 #include "compiler.h"
41 #include "daemon.h"
42 #include "fault.h"
43 #include "leak-checker.h"
44 #include "mgmt.h"
45 #include "ovs-vswitchd.h"
46 #include "poll-loop.h"
47 #include "port.h"
48 #include "proc-net-compat.h"
49 #include "process.h"
50 #include "signals.h"
51 #include "svec.h"
52 #include "timeval.h"
53 #include "unixctl.h"
54 #include "util.h"
55 #include "vconn-ssl.h"
56 #include "vconn.h"
57
58 #include "vlog.h"
59 #define THIS_MODULE VLM_vswitchd
60
61 static void parse_options(int argc, char *argv[]);
62 static void usage(void) NO_RETURN;
63 static void reload(struct unixctl_conn *, const char *args);
64
65 static bool need_reconfigure;
66 static struct unixctl_conn **conns;
67 static size_t n_conns;
68
69 int
70 main(int argc, char *argv[])
71 {
72     struct unixctl_server *unixctl;
73     struct signal *sighup;
74     int retval;
75
76     set_program_name(argv[0]);
77     register_fault_handlers();
78     time_init();
79     vlog_init();
80     parse_options(argc, argv);
81     signal(SIGPIPE, SIG_IGN);
82     sighup = signal_register(SIGHUP);
83     process_init();
84
85     die_if_already_running();
86     daemonize();
87
88     retval = unixctl_server_create(NULL, &unixctl);
89     if (retval) {
90         ovs_fatal(retval, "could not listen for control connections");
91     }
92     unixctl_command_register("vswitchd/reload", reload);
93
94     cfg_read();
95     mgmt_init();
96     bridge_init();
97     port_init();
98     mgmt_reconfigure();
99
100     need_reconfigure = false;
101     for (;;) {
102         if (need_reconfigure || signal_poll(sighup)) {
103             need_reconfigure = false;
104             vlog_reopen_log_file();
105             reconfigure();
106         }
107         mgmt_run();
108         if (bridge_run()) {
109             need_reconfigure = true;
110         }
111         unixctl_server_run(unixctl);
112
113         if (need_reconfigure) {
114             poll_immediate_wake();
115         }
116         signal_wait(sighup);
117         mgmt_wait();
118         bridge_wait();
119         unixctl_server_wait(unixctl);
120         poll_block();
121     }
122
123     return 0;
124 }
125
126 static void
127 reload(struct unixctl_conn *conn, const char *args UNUSED)
128 {
129     need_reconfigure = true;
130     conns = xrealloc(conns, sizeof *conns * (n_conns + 1));
131     conns[n_conns++] = conn;
132 }
133
134 void
135 reconfigure(void)
136 {
137     size_t i;
138
139     cfg_read();
140     bridge_reconfigure();
141     mgmt_reconfigure();
142     port_reconfigure();
143
144     for (i = 0; i < n_conns; i++) {
145         unixctl_command_reply(conns[i], 202, NULL);
146     }
147     free(conns);
148     conns = NULL;
149     n_conns = 0;
150 }
151
152 static void
153 parse_options(int argc, char *argv[])
154 {
155     enum {
156         OPT_PEER_CA_CERT = UCHAR_MAX + 1,
157         OPT_FAKE_PROC_NET,
158         VLOG_OPTION_ENUMS,
159         LEAK_CHECKER_OPTION_ENUMS
160     };
161     static struct option long_options[] = {
162         {"help",        no_argument, 0, 'h'},
163         {"version",     no_argument, 0, 'V'},
164         {"fake-proc-net", no_argument, 0, OPT_FAKE_PROC_NET},
165         DAEMON_LONG_OPTIONS,
166         VLOG_LONG_OPTIONS,
167         LEAK_CHECKER_LONG_OPTIONS,
168 #ifdef HAVE_OPENSSL
169         VCONN_SSL_LONG_OPTIONS
170         {"peer-ca-cert", required_argument, 0, OPT_PEER_CA_CERT},
171 #endif
172         {0, 0, 0, 0},
173     };
174     char *short_options = long_options_to_short_options(long_options);
175     const char *config_file;
176     int error;
177
178     for (;;) {
179         int c;
180
181         c = getopt_long(argc, argv, short_options, long_options, NULL);
182         if (c == -1) {
183             break;
184         }
185
186         switch (c) {
187         case 'H':
188         case 'h':
189             usage();
190
191         case 'V':
192             OVS_PRINT_VERSION(OFP_VERSION, OFP_VERSION);
193             exit(EXIT_SUCCESS);
194
195         case OPT_FAKE_PROC_NET:
196             error = proc_net_compat_init();
197             if (error) {
198                 ovs_fatal(error, "failed to initialize /proc/net "
199                           "compatibility");
200             }
201             break;
202
203         VLOG_OPTION_HANDLERS
204         DAEMON_OPTION_HANDLERS
205         VCONN_SSL_OPTION_HANDLERS
206         LEAK_CHECKER_OPTION_HANDLERS
207
208 #ifdef HAVE_OPENSSL
209         case OPT_PEER_CA_CERT:
210             vconn_ssl_set_peer_ca_cert_file(optarg);
211             break;
212 #endif
213
214         case '?':
215             exit(EXIT_FAILURE);
216
217         default:
218             abort();
219         }
220     }
221     free(short_options);
222
223     argc -= optind;
224     argv += optind;
225
226     if (argc != 1) {
227         ovs_fatal(0, "config file is only non-option argument; "
228                 "use --help for usage");
229     }
230
231     config_file = argv[0];
232     error = cfg_set_file(config_file);
233     if (error) {
234        ovs_fatal(error, "failed to add configuration file \"%s\"", 
235                 config_file);
236     }
237 }
238
239 static void
240 usage(void)
241 {
242     printf("%s: virtual switch daemon\n"
243            "usage: %s [OPTIONS] CONFIG\n"
244            "CONFIG is a configuration file in ovs-vswitchd.conf(5) format.\n",
245            program_name, program_name);
246     daemon_usage();
247     vlog_usage();
248     printf("\nLegacy compatibility options:\n"
249            " --fake-proc-net          simulate some files in /proc/net\n"
250            "\nOther options:\n"
251            "  -h, --help              display this help message\n"
252            "  -V, --version           display version information\n");
253     leak_checker_usage();
254     exit(EXIT_SUCCESS);
255 }