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