Branch data Line data Source code
1 : : /* Copyright (c) 2015, 2016 Nicira, Inc.
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 <errno.h>
19 : : #include <getopt.h>
20 : : #include <signal.h>
21 : : #include <stdlib.h>
22 : : #include <string.h>
23 : :
24 : : #include "command-line.h"
25 : : #include "compiler.h"
26 : : #include "daemon.h"
27 : : #include "dirs.h"
28 : : #include "openvswitch/dynamic-string.h"
29 : : #include "fatal-signal.h"
30 : : #include "poll-loop.h"
31 : : #include "stream.h"
32 : : #include "stream-ssl.h"
33 : : #include "unixctl.h"
34 : : #include "util.h"
35 : : #include "openvswitch/vconn.h"
36 : : #include "openvswitch/vlog.h"
37 : : #include "ovn/lib/ovn-sb-idl.h"
38 : : #include "ovn/lib/ovn-util.h"
39 : : #include "vtep/vtep-idl.h"
40 : :
41 : : #include "binding.h"
42 : : #include "gateway.h"
43 : : #include "vtep.h"
44 : : #include "ovn-controller-vtep.h"
45 : :
46 : : static unixctl_cb_func ovn_controller_vtep_exit;
47 : :
48 : : static void parse_options(int argc, char *argv[]);
49 : : OVS_NO_RETURN static void usage(void);
50 : :
51 : : static char *vtep_remote;
52 : : static char *ovnsb_remote;
53 : : static char *default_db_;
54 : :
55 : : int
56 : 7 : main(int argc, char *argv[])
57 : : {
58 : : struct unixctl_server *unixctl;
59 : : bool exiting;
60 : : int retval;
61 : :
62 : 7 : ovs_cmdl_proctitle_init(argc, argv);
63 : 7 : set_program_name(argv[0]);
64 : 7 : service_start(&argc, &argv);
65 : 7 : parse_options(argc, argv);
66 : 7 : fatal_ignore_sigpipe();
67 : :
68 : 7 : daemonize_start(false);
69 : :
70 : 7 : retval = unixctl_server_create(NULL, &unixctl);
71 [ - + ]: 7 : if (retval) {
72 : 0 : exit(EXIT_FAILURE);
73 : : }
74 : 7 : unixctl_command_register("exit", "", 0, 0, ovn_controller_vtep_exit,
75 : : &exiting);
76 : :
77 : 7 : daemonize_complete();
78 : :
79 : 7 : vteprec_init();
80 : 7 : sbrec_init();
81 : :
82 : : /* Connect to VTEP database. */
83 : 7 : struct ovsdb_idl_loop vtep_idl_loop = OVSDB_IDL_LOOP_INITIALIZER(
84 : : ovsdb_idl_create(vtep_remote, &vteprec_idl_class, true, true));
85 : 7 : ovsdb_idl_get_initial_snapshot(vtep_idl_loop.idl);
86 : :
87 : : /* Connect to OVN SB database. */
88 : 7 : struct ovsdb_idl_loop ovnsb_idl_loop = OVSDB_IDL_LOOP_INITIALIZER(
89 : : ovsdb_idl_create(ovnsb_remote, &sbrec_idl_class, true, true));
90 : 7 : ovsdb_idl_get_initial_snapshot(ovnsb_idl_loop.idl);
91 : :
92 : : /* Main loop. */
93 : 7 : exiting = false;
94 [ + + ]: 276 : while (!exiting) {
95 : 1076 : struct controller_vtep_ctx ctx = {
96 : 269 : .vtep_idl = vtep_idl_loop.idl,
97 : 269 : .vtep_idl_txn = ovsdb_idl_loop_run(&vtep_idl_loop),
98 : 269 : .ovnsb_idl = ovnsb_idl_loop.idl,
99 : 269 : .ovnsb_idl_txn = ovsdb_idl_loop_run(&ovnsb_idl_loop),
100 : : };
101 : :
102 : 269 : gateway_run(&ctx);
103 : 269 : binding_run(&ctx);
104 : 269 : vtep_run(&ctx);
105 : 269 : unixctl_server_run(unixctl);
106 : :
107 : 269 : unixctl_server_wait(unixctl);
108 [ + + ]: 269 : if (exiting) {
109 : 7 : poll_immediate_wake();
110 : : }
111 : 269 : ovsdb_idl_loop_commit_and_wait(&vtep_idl_loop);
112 : 269 : ovsdb_idl_loop_commit_and_wait(&ovnsb_idl_loop);
113 : 269 : poll_block();
114 [ - + ]: 269 : if (should_service_stop()) {
115 : 269 : exiting = true;
116 : : }
117 : : }
118 : :
119 : : /* It's time to exit. Clean up the databases. */
120 : 7 : bool done = false;
121 [ + + ]: 34 : while (!done) {
122 : 108 : struct controller_vtep_ctx ctx = {
123 : 27 : .vtep_idl = vtep_idl_loop.idl,
124 : 27 : .vtep_idl_txn = ovsdb_idl_loop_run(&vtep_idl_loop),
125 : 27 : .ovnsb_idl = ovnsb_idl_loop.idl,
126 : 27 : .ovnsb_idl_txn = ovsdb_idl_loop_run(&ovnsb_idl_loop),
127 : : };
128 : :
129 : : /* Run all of the cleanup functions, even if one of them returns false.
130 : : * We're done if all of them return true. */
131 : 27 : done = binding_cleanup(&ctx);
132 [ + + ][ + - ]: 27 : done = gateway_cleanup(&ctx) && done;
133 [ + + ][ + + ]: 27 : done = vtep_cleanup(&ctx) && done;
134 [ + + ]: 27 : if (done) {
135 : 7 : poll_immediate_wake();
136 : : }
137 : :
138 : 27 : ovsdb_idl_loop_commit_and_wait(&vtep_idl_loop);
139 : 27 : ovsdb_idl_loop_commit_and_wait(&ovnsb_idl_loop);
140 : 27 : poll_block();
141 : : }
142 : :
143 : 7 : unixctl_server_destroy(unixctl);
144 : :
145 : 7 : ovsdb_idl_loop_destroy(&vtep_idl_loop);
146 : 7 : ovsdb_idl_loop_destroy(&ovnsb_idl_loop);
147 : :
148 : 7 : free(ovnsb_remote);
149 : 7 : free(vtep_remote);
150 : 7 : free(default_db_);
151 : 7 : service_stop();
152 : :
153 : 7 : exit(retval);
154 : : }
155 : :
156 : : static const char *
157 : 0 : default_db(void)
158 : : {
159 [ # # ]: 0 : if (!default_db_) {
160 : 0 : default_db_ = xasprintf("unix:%s/db.sock", ovs_rundir());
161 : : }
162 : 0 : return default_db_;
163 : : }
164 : :
165 : : static void
166 : 7 : parse_options(int argc, char *argv[])
167 : : {
168 : : enum {
169 : : OPT_PEER_CA_CERT = UCHAR_MAX + 1,
170 : : OPT_BOOTSTRAP_CA_CERT,
171 : : VLOG_OPTION_ENUMS,
172 : : DAEMON_OPTION_ENUMS
173 : : };
174 : :
175 : : static struct option long_options[] = {
176 : : {"ovnsb-db", required_argument, NULL, 'd'},
177 : : {"vtep-db", required_argument, NULL, 'D'},
178 : : {"help", no_argument, NULL, 'h'},
179 : : {"version", no_argument, NULL, 'V'},
180 : : VLOG_LONG_OPTIONS,
181 : : DAEMON_LONG_OPTIONS,
182 : : STREAM_SSL_LONG_OPTIONS,
183 : : {"peer-ca-cert", required_argument, NULL, OPT_PEER_CA_CERT},
184 : : {"bootstrap-ca-cert", required_argument, NULL, OPT_BOOTSTRAP_CA_CERT},
185 : : {NULL, 0, NULL, 0}
186 : : };
187 : 7 : char *short_options = ovs_cmdl_long_options_to_short_options(long_options);
188 : :
189 : : for (;;) {
190 : : int c;
191 : :
192 : 44 : c = getopt_long(argc, argv, short_options, long_options, NULL);
193 [ + + ]: 44 : if (c == -1) {
194 : 7 : break;
195 : : }
196 : :
197 [ + + - - : 37 : switch (c) {
+ + - - +
- + + - -
- - - - -
- - - ]
198 : : case 'd':
199 : 7 : ovnsb_remote = xstrdup(optarg);
200 : 7 : break;
201 : :
202 : : case 'D':
203 : 7 : vtep_remote = xstrdup(optarg);
204 : 7 : break;
205 : :
206 : : case 'h':
207 : 0 : usage();
208 : :
209 : : case 'V':
210 : 0 : ovs_print_version(OFP13_VERSION, OFP13_VERSION);
211 : 0 : exit(EXIT_SUCCESS);
212 : :
213 : 8 : VLOG_OPTION_HANDLERS
214 : 15 : DAEMON_OPTION_HANDLERS
215 : 0 : STREAM_SSL_OPTION_HANDLERS
216 : :
217 : : case OPT_PEER_CA_CERT:
218 : 0 : stream_ssl_set_peer_ca_cert_file(optarg);
219 : 0 : break;
220 : :
221 : : case OPT_BOOTSTRAP_CA_CERT:
222 : 0 : stream_ssl_set_ca_cert_file(optarg, true);
223 : 0 : break;
224 : :
225 : : case '?':
226 : 0 : exit(EXIT_FAILURE);
227 : :
228 : : default:
229 : 0 : abort();
230 : : }
231 : 37 : }
232 : 7 : free(short_options);
233 : :
234 [ - + ]: 7 : if (!ovnsb_remote) {
235 : 0 : ovnsb_remote = xstrdup(default_sb_db());
236 : : }
237 : :
238 [ - + ]: 7 : if (!vtep_remote) {
239 : 0 : vtep_remote = xstrdup(default_db());
240 : : }
241 : 7 : }
242 : :
243 : : static void
244 : 0 : usage(void)
245 : : {
246 : 0 : printf("\
247 : : %s: OVN controller VTEP\n\
248 : : usage %s [OPTIONS]\n\
249 : : \n\
250 : : Options:\n\
251 : : --vtep-db=DATABASE connect to vtep database at DATABASE\n\
252 : : (default: %s)\n\
253 : : --ovnsb-db=DATABASE connect to ovn-sb database at DATABASE\n\
254 : : (default: %s)\n\
255 : : -h, --help display this help message\n\
256 : : -o, --options list available options\n\
257 : : -V, --version display version information\n\
258 : : ", program_name, program_name, default_db(), default_db());
259 : 0 : stream_usage("database", true, false, false);
260 : 0 : daemon_usage();
261 : 0 : vlog_usage();
262 : 0 : exit(EXIT_SUCCESS);
263 : : }
264 : :
265 : :
266 : : static void
267 : 7 : ovn_controller_vtep_exit(struct unixctl_conn *conn, int argc OVS_UNUSED,
268 : : const char *argv[] OVS_UNUSED, void *exiting_)
269 : : {
270 : 7 : bool *exiting = exiting_;
271 : 7 : *exiting = true;
272 : :
273 : 7 : unixctl_command_reply(conn, NULL);
274 : 7 : }
|