ovn: Rename Pipeline table to Logical_Flow table.
[cascardo/ovs.git] / ovn / controller / ovn-controller.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 "ovn-controller.h"
19
20 #include <errno.h>
21 #include <getopt.h>
22 #include <signal.h>
23 #include <stdlib.h>
24 #include <string.h>
25
26 #include "command-line.h"
27 #include "compiler.h"
28 #include "daemon.h"
29 #include "dirs.h"
30 #include "openvswitch/vconn.h"
31 #include "openvswitch/vlog.h"
32 #include "ovn/lib/ovn-sb-idl.h"
33 #include "poll-loop.h"
34 #include "fatal-signal.h"
35 #include "lib/vswitch-idl.h"
36 #include "smap.h"
37 #include "stream.h"
38 #include "stream-ssl.h"
39 #include "unixctl.h"
40 #include "util.h"
41
42 #include "ofctrl.h"
43 #include "binding.h"
44 #include "chassis.h"
45 #include "encaps.h"
46 #include "physical.h"
47 #include "lflow.h"
48
49 VLOG_DEFINE_THIS_MODULE(main);
50
51 static unixctl_cb_func ovn_controller_exit;
52
53 #define DEFAULT_BRIDGE_NAME "br-int"
54
55 static void parse_options(int argc, char *argv[]);
56 OVS_NO_RETURN static void usage(void);
57
58 static char *ovs_remote;
59
60 static void
61 get_initial_snapshot(struct ovsdb_idl *idl)
62 {
63     while (1) {
64         ovsdb_idl_run(idl);
65         if (ovsdb_idl_has_ever_connected(idl)) {
66             return;
67         }
68         ovsdb_idl_wait(idl);
69         poll_block();
70     }
71 }
72
73 static const struct ovsrec_bridge *
74 get_br_int(struct ovsdb_idl *ovs_idl)
75 {
76     const struct ovsrec_open_vswitch *cfg = ovsrec_open_vswitch_first(ovs_idl);
77     if (!cfg) {
78         return NULL;
79     }
80
81     const char *br_int_name = smap_get(&cfg->external_ids, "ovn-bridge");
82     if (!br_int_name) {
83         br_int_name = DEFAULT_BRIDGE_NAME;
84     }
85
86     const struct ovsrec_bridge *br;
87     OVSREC_BRIDGE_FOR_EACH (br, ovs_idl) {
88         if (!strcmp(br->name, br_int_name)) {
89             return br;
90         }
91     }
92
93     static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
94     VLOG_WARN_RL(&rl, "%s: integration bridge does not exist", br_int_name);
95     return NULL;
96 }
97
98 static const char *
99 get_chassis_id(const struct ovsdb_idl *ovs_idl)
100 {
101     const struct ovsrec_open_vswitch *cfg = ovsrec_open_vswitch_first(ovs_idl);
102     return cfg ? smap_get(&cfg->external_ids, "system-id") : NULL;
103 }
104
105 /* Retrieves the OVN Southbound remote location from the
106  * "external-ids:ovn-remote" key in 'ovs_idl' and returns a copy of it.
107  *
108  * XXX ovn-controller does not support this changing mid-run, but that should
109  * be addressed later. */
110 static char *
111 get_ovnsb_remote(struct ovsdb_idl *ovs_idl)
112 {
113     while (1) {
114         ovsdb_idl_run(ovs_idl);
115
116         const struct ovsrec_open_vswitch *cfg
117             = ovsrec_open_vswitch_first(ovs_idl);
118         if (cfg) {
119             const char *remote = smap_get(&cfg->external_ids, "ovn-remote");
120             if (remote) {
121                 return xstrdup(remote);
122             }
123         }
124
125         VLOG_INFO("OVN OVSDB remote not specified.  Waiting...");
126         ovsdb_idl_wait(ovs_idl);
127         poll_block();
128     }
129 }
130
131 struct idl_loop {
132     struct ovsdb_idl *idl;
133     unsigned int skip_seqno;
134
135     struct ovsdb_idl_txn *committing_txn;
136     unsigned int precommit_seqno;
137
138     struct ovsdb_idl_txn *open_txn;
139 };
140
141 #define IDL_LOOP_INITIALIZER(IDL) { .idl = (IDL) }
142
143 static void
144 idl_loop_destroy(struct idl_loop *loop)
145 {
146     if (loop) {
147         ovsdb_idl_destroy(loop->idl);
148     }
149 }
150
151 static struct ovsdb_idl_txn *
152 idl_loop_run(struct idl_loop *loop)
153 {
154     ovsdb_idl_run(loop->idl);
155     loop->open_txn = (loop->committing_txn
156                       || ovsdb_idl_get_seqno(loop->idl) == loop->skip_seqno
157                       ? NULL
158                       : ovsdb_idl_txn_create(loop->idl));
159     return loop->open_txn;
160 }
161
162 static void
163 idl_loop_commit_and_wait(struct idl_loop *loop)
164 {
165     if (loop->open_txn) {
166         loop->committing_txn = loop->open_txn;
167         loop->open_txn = NULL;
168
169         loop->precommit_seqno = ovsdb_idl_get_seqno(loop->idl);
170     }
171
172     struct ovsdb_idl_txn *txn = loop->committing_txn;
173     if (txn) {
174         enum ovsdb_idl_txn_status status = ovsdb_idl_txn_commit(txn);
175         if (status != TXN_INCOMPLETE) {
176             switch (status) {
177             case TXN_TRY_AGAIN:
178                 /* We want to re-evaluate the database when it's changed from
179                  * the contents that it had when we started the commit.  (That
180                  * might have already happened.) */
181                 loop->skip_seqno = loop->precommit_seqno;
182                 if (ovsdb_idl_get_seqno(loop->idl) != loop->skip_seqno) {
183                     poll_immediate_wake();
184                 }
185                 break;
186
187             case TXN_SUCCESS:
188                 /* If the database has already changed since we started the
189                  * commit, re-evaluate it immediately to avoid missing a change
190                  * for a while. */
191                 if (ovsdb_idl_get_seqno(loop->idl) != loop->precommit_seqno) {
192                     poll_immediate_wake();
193                 }
194                 break;
195
196             case TXN_UNCHANGED:
197             case TXN_ABORTED:
198             case TXN_NOT_LOCKED:
199             case TXN_ERROR:
200                 break;
201
202             case TXN_UNCOMMITTED:
203             case TXN_INCOMPLETE:
204                 OVS_NOT_REACHED();
205
206             }
207             ovsdb_idl_txn_destroy(txn);
208             loop->committing_txn = NULL;
209         }
210     }
211
212     ovsdb_idl_wait(loop->idl);
213 }
214
215 int
216 main(int argc, char *argv[])
217 {
218     struct unixctl_server *unixctl;
219     bool exiting;
220     int retval;
221
222     ovs_cmdl_proctitle_init(argc, argv);
223     set_program_name(argv[0]);
224     parse_options(argc, argv);
225     fatal_ignore_sigpipe();
226
227     daemonize_start();
228
229     retval = unixctl_server_create(NULL, &unixctl);
230     if (retval) {
231         exit(EXIT_FAILURE);
232     }
233     unixctl_command_register("exit", "", 0, 0, ovn_controller_exit, &exiting);
234
235     daemonize_complete();
236
237     ovsrec_init();
238     sbrec_init();
239
240     ofctrl_init();
241     lflow_init();
242
243     /* Connect to OVS OVSDB instance.  We do not monitor all tables by
244      * default, so modules must register their interest explicitly.  */
245     struct idl_loop ovs_idl_loop = IDL_LOOP_INITIALIZER(
246         ovsdb_idl_create(ovs_remote, &ovsrec_idl_class, false, true));
247     ovsdb_idl_add_table(ovs_idl_loop.idl, &ovsrec_table_open_vswitch);
248     ovsdb_idl_add_column(ovs_idl_loop.idl,
249                          &ovsrec_open_vswitch_col_external_ids);
250     chassis_register_ovs_idl(ovs_idl_loop.idl);
251     encaps_register_ovs_idl(ovs_idl_loop.idl);
252     binding_register_ovs_idl(ovs_idl_loop.idl);
253     physical_register_ovs_idl(ovs_idl_loop.idl);
254     get_initial_snapshot(ovs_idl_loop.idl);
255
256     /* Connect to OVN SB database. */
257     char *ovnsb_remote = get_ovnsb_remote(ovs_idl_loop.idl);
258     struct idl_loop ovnsb_idl_loop = IDL_LOOP_INITIALIZER(
259         ovsdb_idl_create(ovnsb_remote, &sbrec_idl_class, true, true));
260     get_initial_snapshot(ovnsb_idl_loop.idl);
261
262     /* Main loop. */
263     exiting = false;
264     while (!exiting) {
265         struct controller_ctx ctx = {
266             .ovs_idl = ovs_idl_loop.idl,
267             .ovs_idl_txn = idl_loop_run(&ovs_idl_loop),
268             .ovnsb_idl = ovnsb_idl_loop.idl,
269             .ovnsb_idl_txn = idl_loop_run(&ovnsb_idl_loop),
270         };
271
272         const struct ovsrec_bridge *br_int = get_br_int(ctx.ovs_idl);
273         const char *chassis_id = get_chassis_id(ctx.ovs_idl);
274
275         if (chassis_id) {
276             chassis_run(&ctx, chassis_id);
277             encaps_run(&ctx, br_int, chassis_id);
278             binding_run(&ctx, br_int, chassis_id);
279         }
280
281         if (br_int) {
282             struct hmap flow_table = HMAP_INITIALIZER(&flow_table);
283             lflow_run(&ctx, &flow_table);
284             if (chassis_id) {
285                 physical_run(&ctx, br_int, chassis_id, &flow_table);
286             }
287             ofctrl_run(br_int, &flow_table);
288             hmap_destroy(&flow_table);
289         }
290
291         unixctl_server_run(unixctl);
292
293         unixctl_server_wait(unixctl);
294         if (exiting) {
295             poll_immediate_wake();
296         }
297
298         idl_loop_commit_and_wait(&ovnsb_idl_loop);
299         idl_loop_commit_and_wait(&ovs_idl_loop);
300
301         if (br_int) {
302             ofctrl_wait();
303         }
304         poll_block();
305     }
306
307     /* It's time to exit.  Clean up the databases. */
308     bool done = false;
309     while (!done) {
310         struct controller_ctx ctx = {
311             .ovs_idl = ovs_idl_loop.idl,
312             .ovs_idl_txn = idl_loop_run(&ovs_idl_loop),
313             .ovnsb_idl = ovnsb_idl_loop.idl,
314             .ovnsb_idl_txn = idl_loop_run(&ovnsb_idl_loop),
315         };
316
317         const struct ovsrec_bridge *br_int = get_br_int(ctx.ovs_idl);
318         const char *chassis_id = get_chassis_id(ctx.ovs_idl);
319
320         /* Run all of the cleanup functions, even if one of them returns false.
321          * We're done if all of them return true. */
322         done = binding_cleanup(&ctx, chassis_id);
323         done = chassis_cleanup(&ctx, chassis_id) && done;
324         done = encaps_cleanup(&ctx, br_int) && done;
325         if (done) {
326             poll_immediate_wake();
327         }
328
329         idl_loop_commit_and_wait(&ovnsb_idl_loop);
330         idl_loop_commit_and_wait(&ovs_idl_loop);
331         poll_block();
332     }
333
334     unixctl_server_destroy(unixctl);
335     lflow_destroy();
336     ofctrl_destroy();
337
338     idl_loop_destroy(&ovs_idl_loop);
339     idl_loop_destroy(&ovnsb_idl_loop);
340
341     free(ovnsb_remote);
342     free(ovs_remote);
343
344     exit(retval);
345 }
346
347 static void
348 parse_options(int argc, char *argv[])
349 {
350     enum {
351         OPT_PEER_CA_CERT = UCHAR_MAX + 1,
352         VLOG_OPTION_ENUMS,
353         DAEMON_OPTION_ENUMS
354     };
355
356     static struct option long_options[] = {
357         {"help", no_argument, NULL, 'h'},
358         {"version", no_argument, NULL, 'V'},
359         VLOG_LONG_OPTIONS,
360         DAEMON_LONG_OPTIONS,
361         STREAM_SSL_LONG_OPTIONS,
362         {"peer-ca-cert", required_argument, NULL, OPT_PEER_CA_CERT},
363         {NULL, 0, NULL, 0}
364     };
365     char *short_options = ovs_cmdl_long_options_to_short_options(long_options);
366
367     for (;;) {
368         int c;
369
370         c = getopt_long(argc, argv, short_options, long_options, NULL);
371         if (c == -1) {
372             break;
373         }
374
375         switch (c) {
376         case 'h':
377             usage();
378
379         case 'V':
380             ovs_print_version(OFP13_VERSION, OFP13_VERSION);
381             exit(EXIT_SUCCESS);
382
383         VLOG_OPTION_HANDLERS
384         DAEMON_OPTION_HANDLERS
385         STREAM_SSL_OPTION_HANDLERS
386
387         case OPT_PEER_CA_CERT:
388             stream_ssl_set_peer_ca_cert_file(optarg);
389             break;
390
391         case '?':
392             exit(EXIT_FAILURE);
393
394         default:
395             abort();
396         }
397     }
398     free(short_options);
399
400     argc -= optind;
401     argv += optind;
402
403     if (argc == 0) {
404         ovs_remote = xasprintf("unix:%s/db.sock", ovs_rundir());
405     } else if (argc == 1) {
406         ovs_remote = xstrdup(argv[0]);
407     } else {
408         VLOG_FATAL("exactly zero or one non-option argument required; "
409                    "use --help for usage");
410     }
411 }
412
413 static void
414 usage(void)
415 {
416     printf("%s: OVN controller\n"
417            "usage %s [OPTIONS] [OVS-DATABASE]\n"
418            "where OVS-DATABASE is a socket on which the OVS OVSDB server is listening.\n",
419                program_name, program_name);
420     stream_usage("OVS-DATABASE", true, false, false);
421     daemon_usage();
422     vlog_usage();
423     printf("\nOther options:\n"
424            "  -h, --help              display this help message\n"
425            "  -V, --version           display version information\n");
426     exit(EXIT_SUCCESS);
427 }
428
429 static void
430 ovn_controller_exit(struct unixctl_conn *conn, int argc OVS_UNUSED,
431              const char *argv[] OVS_UNUSED, void *exiting_)
432 {
433     bool *exiting = exiting_;
434     *exiting = true;
435
436     unixctl_command_reply(conn, NULL);
437 }