0371c3826653883db7794f3ffb4e672c2f99f8d8
[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 const struct sbrec_chassis *
61 get_chassis(struct ovsdb_idl *ovnsb_idl, const char *chassis_id)
62 {
63     const struct sbrec_chassis *chassis_rec;
64
65     SBREC_CHASSIS_FOR_EACH(chassis_rec, ovnsb_idl) {
66         if (!strcmp(chassis_rec->name, chassis_id)) {
67             break;
68         }
69     }
70
71     return chassis_rec;
72 }
73
74 static const struct ovsrec_bridge *
75 get_bridge(struct ovsdb_idl *ovs_idl, const char *br_name)
76 {
77     const struct ovsrec_bridge *br;
78     OVSREC_BRIDGE_FOR_EACH (br, ovs_idl) {
79         if (!strcmp(br->name, br_name)) {
80             return br;
81         }
82     }
83     return NULL;
84 }
85
86 static const struct ovsrec_bridge *
87 create_br_int(struct controller_ctx *ctx,
88               const struct ovsrec_open_vswitch *cfg,
89               const char *bridge_name)
90 {
91     if (!ctx->ovs_idl_txn) {
92         return NULL;
93     }
94
95     ovsdb_idl_txn_add_comment(ctx->ovs_idl_txn,
96             "ovn-controller: creating integration bridge '%s'", bridge_name);
97
98     struct ovsrec_interface *iface;
99     iface = ovsrec_interface_insert(ctx->ovs_idl_txn);
100     ovsrec_interface_set_name(iface, bridge_name);
101     ovsrec_interface_set_type(iface, "internal");
102
103     struct ovsrec_port *port;
104     port = ovsrec_port_insert(ctx->ovs_idl_txn);
105     ovsrec_port_set_name(port, bridge_name);
106     ovsrec_port_set_interfaces(port, &iface, 1);
107
108     struct ovsrec_bridge *bridge;
109     bridge = ovsrec_bridge_insert(ctx->ovs_idl_txn);
110     ovsrec_bridge_set_name(bridge, bridge_name);
111     ovsrec_bridge_set_fail_mode(bridge, "secure");
112     const struct smap oc = SMAP_CONST1(&oc, "disable-in-band", "true");
113     ovsrec_bridge_set_other_config(bridge, &oc);
114     ovsrec_bridge_set_ports(bridge, &port, 1);
115
116     struct ovsrec_bridge **bridges;
117     size_t bytes = sizeof *bridges * cfg->n_bridges;
118     bridges = xmalloc(bytes + sizeof *bridges);
119     memcpy(bridges, cfg->bridges, bytes);
120     bridges[cfg->n_bridges] = bridge;
121     ovsrec_open_vswitch_verify_bridges(cfg);
122     ovsrec_open_vswitch_set_bridges(cfg, bridges, cfg->n_bridges + 1);
123
124     return bridge;
125 }
126
127 static const struct ovsrec_bridge *
128 get_br_int(struct controller_ctx *ctx)
129 {
130     const struct ovsrec_open_vswitch *cfg;
131     cfg = ovsrec_open_vswitch_first(ctx->ovs_idl);
132     if (!cfg) {
133         return NULL;
134     }
135
136     const char *br_int_name = smap_get(&cfg->external_ids, "ovn-bridge");
137     if (!br_int_name) {
138         br_int_name = DEFAULT_BRIDGE_NAME;
139     }
140
141     const struct ovsrec_bridge *br;
142     br = get_bridge(ctx->ovs_idl, br_int_name);
143     if (!br) {
144         return create_br_int(ctx, cfg, br_int_name);
145     }
146     return br;
147 }
148
149 static const char *
150 get_chassis_id(const struct ovsdb_idl *ovs_idl)
151 {
152     const struct ovsrec_open_vswitch *cfg = ovsrec_open_vswitch_first(ovs_idl);
153     return cfg ? smap_get(&cfg->external_ids, "system-id") : NULL;
154 }
155
156 static char *
157 patch_port_name(const struct ovsrec_bridge *b1, const struct ovsrec_bridge *b2)
158 {
159     return xasprintf("patch-%s-to-%s", b1->name, b2->name);
160 }
161
162 /*
163  * Return true if the port is a patch port from b1 to b2
164  */
165 static bool
166 match_patch_port(const struct ovsrec_port *port,
167                  const struct ovsrec_bridge *b1,
168                  const struct ovsrec_bridge *b2)
169 {
170     struct ovsrec_interface *iface;
171     size_t i;
172     char *peer_port_name;
173     bool res = false;
174
175     peer_port_name = patch_port_name(b2, b1);
176
177     for (i = 0; i < port->n_interfaces; i++) {
178         iface = port->interfaces[i];
179         if (strcmp(iface->type, "patch")) {
180             continue;
181         }
182         const char *peer;
183         peer = smap_get(&iface->options, "peer");
184         if (peer && !strcmp(peer, peer_port_name)) {
185             res = true;
186             break;
187         }
188     }
189
190     free(peer_port_name);
191
192     return res;
193 }
194
195 static void
196 create_patch_port(struct controller_ctx *ctx,
197                   const char *network,
198                   const struct ovsrec_bridge *b1,
199                   const struct ovsrec_bridge *b2)
200 {
201     if (!ctx->ovs_idl_txn) {
202         return;
203     }
204
205     char *port_name = patch_port_name(b1, b2);
206     char *peer_port_name = patch_port_name(b2, b1);
207
208     ovsdb_idl_txn_add_comment(ctx->ovs_idl_txn,
209             "ovn-controller: creating patch port '%s' from '%s' to '%s'",
210             port_name, b1->name, b2->name);
211
212     struct ovsrec_interface *iface;
213     iface = ovsrec_interface_insert(ctx->ovs_idl_txn);
214     ovsrec_interface_set_name(iface, port_name);
215     ovsrec_interface_set_type(iface, "patch");
216     const struct smap options = SMAP_CONST1(&options, "peer", peer_port_name);
217     ovsrec_interface_set_options(iface, &options);
218
219     struct ovsrec_port *port;
220     port = ovsrec_port_insert(ctx->ovs_idl_txn);
221     ovsrec_port_set_name(port, port_name);
222     ovsrec_port_set_interfaces(port, &iface, 1);
223     const struct smap ids = SMAP_CONST1(&ids, "ovn-patch-port", network);
224     ovsrec_port_set_external_ids(port, &ids);
225
226     struct ovsrec_port **ports;
227     ports = xmalloc(sizeof *ports * (b1->n_ports + 1));
228     memcpy(ports, b1->ports, sizeof *ports * b1->n_ports);
229     ports[b1->n_ports] = port;
230     ovsrec_bridge_verify_ports(b1);
231     ovsrec_bridge_set_ports(b1, ports, b1->n_ports + 1);
232
233     free(ports);
234     free(port_name);
235     free(peer_port_name);
236 }
237
238 static void
239 create_patch_ports(struct controller_ctx *ctx,
240                    const char *network,
241                    struct shash *existing_ports,
242                    const struct ovsrec_bridge *b1,
243                    const struct ovsrec_bridge *b2)
244 {
245     size_t i;
246
247     for (i = 0; i < b1->n_ports; i++) {
248         if (match_patch_port(b1->ports[i], b1, b2)) {
249             /* Patch port already exists on b1 */
250             shash_find_and_delete(existing_ports, b1->ports[i]->name);
251             break;
252         }
253     }
254     if (i == b1->n_ports) {
255         create_patch_port(ctx, network, b1, b2);
256     }
257 }
258
259 static void
260 init_existing_ports(struct controller_ctx *ctx,
261                     struct shash *existing_ports)
262 {
263     const struct ovsrec_port *port;
264
265     OVSREC_PORT_FOR_EACH (port, ctx->ovs_idl) {
266         if (smap_get(&port->external_ids, "ovn-patch-port")) {
267             shash_add(existing_ports, port->name, port);
268         }
269     }
270 }
271
272 static void
273 remove_port(struct controller_ctx *ctx,
274             const struct ovsrec_port *port)
275 {
276     const struct ovsrec_bridge *bridge;
277
278     /* We know the port we want to delete, but we have to find the bridge its on
279      * to do so.  Note this only runs on a config change that should be pretty
280      * rare. */
281     OVSREC_BRIDGE_FOR_EACH (bridge, ctx->ovs_idl) {
282         size_t i;
283         for (i = 0; i < bridge->n_ports; i++) {
284             if (bridge->ports[i] != port) {
285                 continue;
286             }
287             struct ovsrec_port **new_ports;
288             new_ports = xmemdup(bridge->ports,
289                     sizeof *new_ports * (bridge->n_ports - 1));
290             if (i != bridge->n_ports - 1) {
291                 /* Removed port was not last */
292                 new_ports[i] = bridge->ports[bridge->n_ports - 1];
293             }
294             ovsrec_bridge_verify_ports(bridge);
295             ovsrec_bridge_set_ports(bridge, new_ports, bridge->n_ports - 1);
296             free(new_ports);
297             ovsrec_port_delete(port);
298             return;
299         }
300     }
301 }
302
303 static void
304 parse_bridge_mappings(struct controller_ctx *ctx,
305                       const struct ovsrec_bridge *br_int,
306                       const char *mappings_cfg)
307 {
308     struct shash existing_ports = SHASH_INITIALIZER(&existing_ports);
309     init_existing_ports(ctx, &existing_ports);
310
311     char *cur, *next, *start;
312     next = start = xstrdup(mappings_cfg);
313     while ((cur = strsep(&next, ",")) && *cur) {
314         char *network, *bridge = cur;
315         const struct ovsrec_bridge *ovs_bridge;
316
317         network = strsep(&bridge, ":");
318         if (!bridge || !*network || !*bridge) {
319             VLOG_ERR("Invalid ovn-bridge-mappings configuration: '%s'",
320                     mappings_cfg);
321             break;
322         }
323
324         ovs_bridge = get_bridge(ctx->ovs_idl, bridge);
325         if (!ovs_bridge) {
326             VLOG_WARN("Bridge '%s' not found for network '%s'",
327                     bridge, network);
328             continue;
329         }
330
331         create_patch_ports(ctx, network, &existing_ports, br_int, ovs_bridge);
332         create_patch_ports(ctx, network, &existing_ports, ovs_bridge, br_int);
333     }
334     free(start);
335
336     /* Any ports left in existing_ports are related to configuration that has
337      * been removed, so we should delete the ports now. */
338     struct shash_node *port_node, *port_next_node;
339     SHASH_FOR_EACH_SAFE (port_node, port_next_node, &existing_ports) {
340         struct ovsrec_port *port = port_node->data;
341         shash_delete(&existing_ports, port_node);
342         remove_port(ctx, port);
343     }
344     shash_destroy(&existing_ports);
345 }
346
347 static void
348 init_bridge_mappings(struct controller_ctx *ctx,
349                      const struct ovsrec_bridge *br_int)
350 {
351     const char *mappings_cfg = "";
352     const struct ovsrec_open_vswitch *cfg;
353
354     cfg = ovsrec_open_vswitch_first(ctx->ovs_idl);
355     if (cfg) {
356         mappings_cfg = smap_get(&cfg->external_ids, "ovn-bridge-mappings");
357         if (!mappings_cfg) {
358             mappings_cfg = "";
359         }
360     }
361     parse_bridge_mappings(ctx, br_int, mappings_cfg);
362 }
363
364 /* Retrieves the OVN Southbound remote location from the
365  * "external-ids:ovn-remote" key in 'ovs_idl' and returns a copy of it.
366  *
367  * XXX ovn-controller does not support this changing mid-run, but that should
368  * be addressed later. */
369 static char *
370 get_ovnsb_remote(struct ovsdb_idl *ovs_idl)
371 {
372     while (1) {
373         ovsdb_idl_run(ovs_idl);
374
375         const struct ovsrec_open_vswitch *cfg
376             = ovsrec_open_vswitch_first(ovs_idl);
377         if (cfg) {
378             const char *remote = smap_get(&cfg->external_ids, "ovn-remote");
379             if (remote) {
380                 return xstrdup(remote);
381             }
382         }
383
384         VLOG_INFO("OVN OVSDB remote not specified.  Waiting...");
385         ovsdb_idl_wait(ovs_idl);
386         poll_block();
387     }
388 }
389
390 int
391 main(int argc, char *argv[])
392 {
393     struct unixctl_server *unixctl;
394     bool exiting;
395     int retval;
396
397     ovs_cmdl_proctitle_init(argc, argv);
398     set_program_name(argv[0]);
399     service_start(&argc, &argv);
400     parse_options(argc, argv);
401     fatal_ignore_sigpipe();
402
403     daemonize_start(false);
404
405     retval = unixctl_server_create(NULL, &unixctl);
406     if (retval) {
407         exit(EXIT_FAILURE);
408     }
409     unixctl_command_register("exit", "", 0, 0, ovn_controller_exit, &exiting);
410
411     daemonize_complete();
412
413     ovsrec_init();
414     sbrec_init();
415
416     ofctrl_init();
417     lflow_init();
418
419     /* Connect to OVS OVSDB instance.  We do not monitor all tables by
420      * default, so modules must register their interest explicitly.  */
421     struct ovsdb_idl_loop ovs_idl_loop = OVSDB_IDL_LOOP_INITIALIZER(
422         ovsdb_idl_create(ovs_remote, &ovsrec_idl_class, false, true));
423     ovsdb_idl_add_table(ovs_idl_loop.idl, &ovsrec_table_open_vswitch);
424     ovsdb_idl_add_column(ovs_idl_loop.idl,
425                          &ovsrec_open_vswitch_col_external_ids);
426     ovsdb_idl_add_column(ovs_idl_loop.idl, &ovsrec_open_vswitch_col_bridges);
427     ovsdb_idl_add_table(ovs_idl_loop.idl, &ovsrec_table_interface);
428     ovsdb_idl_add_column(ovs_idl_loop.idl, &ovsrec_interface_col_name);
429     ovsdb_idl_add_column(ovs_idl_loop.idl, &ovsrec_interface_col_type);
430     ovsdb_idl_add_column(ovs_idl_loop.idl, &ovsrec_interface_col_options);
431     ovsdb_idl_add_table(ovs_idl_loop.idl, &ovsrec_table_port);
432     ovsdb_idl_add_column(ovs_idl_loop.idl, &ovsrec_port_col_name);
433     ovsdb_idl_add_column(ovs_idl_loop.idl, &ovsrec_port_col_interfaces);
434     ovsdb_idl_add_column(ovs_idl_loop.idl, &ovsrec_port_col_external_ids);
435     ovsdb_idl_add_table(ovs_idl_loop.idl, &ovsrec_table_bridge);
436     ovsdb_idl_add_column(ovs_idl_loop.idl, &ovsrec_bridge_col_ports);
437     ovsdb_idl_add_column(ovs_idl_loop.idl, &ovsrec_bridge_col_name);
438     ovsdb_idl_add_column(ovs_idl_loop.idl, &ovsrec_bridge_col_fail_mode);
439     ovsdb_idl_add_column(ovs_idl_loop.idl, &ovsrec_bridge_col_other_config);
440     chassis_register_ovs_idl(ovs_idl_loop.idl);
441     encaps_register_ovs_idl(ovs_idl_loop.idl);
442     binding_register_ovs_idl(ovs_idl_loop.idl);
443     physical_register_ovs_idl(ovs_idl_loop.idl);
444     ovsdb_idl_get_initial_snapshot(ovs_idl_loop.idl);
445
446     /* Connect to OVN SB database. */
447     char *ovnsb_remote = get_ovnsb_remote(ovs_idl_loop.idl);
448     struct ovsdb_idl_loop ovnsb_idl_loop = OVSDB_IDL_LOOP_INITIALIZER(
449         ovsdb_idl_create(ovnsb_remote, &sbrec_idl_class, true, true));
450     ovsdb_idl_get_initial_snapshot(ovnsb_idl_loop.idl);
451
452     /* Main loop. */
453     exiting = false;
454     while (!exiting) {
455         struct controller_ctx ctx = {
456             .ovs_idl = ovs_idl_loop.idl,
457             .ovs_idl_txn = ovsdb_idl_loop_run(&ovs_idl_loop),
458             .ovnsb_idl = ovnsb_idl_loop.idl,
459             .ovnsb_idl_txn = ovsdb_idl_loop_run(&ovnsb_idl_loop),
460         };
461
462         const struct ovsrec_bridge *br_int = get_br_int(&ctx);
463         const char *chassis_id = get_chassis_id(ctx.ovs_idl);
464
465         /* Map bridges to local nets from ovn-bridge-mappings */
466         if (br_int) {
467             init_bridge_mappings(&ctx, br_int);
468         }
469
470         if (chassis_id) {
471             chassis_run(&ctx, chassis_id);
472             encaps_run(&ctx, br_int, chassis_id);
473             binding_run(&ctx, br_int, chassis_id);
474         }
475
476         if (br_int) {
477             enum mf_field_id mff_ovn_geneve = ofctrl_run(br_int);
478
479             struct hmap flow_table = HMAP_INITIALIZER(&flow_table);
480             lflow_run(&ctx, &flow_table);
481             if (chassis_id) {
482                 physical_run(&ctx, mff_ovn_geneve,
483                              br_int, chassis_id, &flow_table);
484             }
485             ofctrl_put(&flow_table);
486             hmap_destroy(&flow_table);
487         }
488
489         unixctl_server_run(unixctl);
490
491         unixctl_server_wait(unixctl);
492         if (exiting) {
493             poll_immediate_wake();
494         }
495
496         ovsdb_idl_loop_commit_and_wait(&ovnsb_idl_loop);
497         ovsdb_idl_loop_commit_and_wait(&ovs_idl_loop);
498
499         if (br_int) {
500             ofctrl_wait();
501         }
502         poll_block();
503         if (should_service_stop()) {
504             exiting = true;
505         }
506     }
507
508     /* It's time to exit.  Clean up the databases. */
509     bool done = false;
510     while (!done) {
511         struct controller_ctx ctx = {
512             .ovs_idl = ovs_idl_loop.idl,
513             .ovs_idl_txn = ovsdb_idl_loop_run(&ovs_idl_loop),
514             .ovnsb_idl = ovnsb_idl_loop.idl,
515             .ovnsb_idl_txn = ovsdb_idl_loop_run(&ovnsb_idl_loop),
516         };
517
518         const struct ovsrec_bridge *br_int = get_br_int(&ctx);
519         const char *chassis_id = get_chassis_id(ctx.ovs_idl);
520
521         /* Run all of the cleanup functions, even if one of them returns false.
522          * We're done if all of them return true. */
523         done = binding_cleanup(&ctx, chassis_id);
524         done = chassis_cleanup(&ctx, chassis_id) && done;
525         done = encaps_cleanup(&ctx, br_int) && done;
526         if (done) {
527             poll_immediate_wake();
528         }
529
530         ovsdb_idl_loop_commit_and_wait(&ovnsb_idl_loop);
531         ovsdb_idl_loop_commit_and_wait(&ovs_idl_loop);
532         poll_block();
533     }
534
535     unixctl_server_destroy(unixctl);
536     lflow_destroy();
537     ofctrl_destroy();
538
539     ovsdb_idl_loop_destroy(&ovs_idl_loop);
540     ovsdb_idl_loop_destroy(&ovnsb_idl_loop);
541
542     free(ovnsb_remote);
543     free(ovs_remote);
544     service_stop();
545
546     exit(retval);
547 }
548
549 static void
550 parse_options(int argc, char *argv[])
551 {
552     enum {
553         OPT_PEER_CA_CERT = UCHAR_MAX + 1,
554         OPT_BOOTSTRAP_CA_CERT,
555         VLOG_OPTION_ENUMS,
556         DAEMON_OPTION_ENUMS
557     };
558
559     static struct option long_options[] = {
560         {"help", no_argument, NULL, 'h'},
561         {"version", no_argument, NULL, 'V'},
562         VLOG_LONG_OPTIONS,
563         DAEMON_LONG_OPTIONS,
564         STREAM_SSL_LONG_OPTIONS,
565         {"peer-ca-cert", required_argument, NULL, OPT_PEER_CA_CERT},
566         {"bootstrap-ca-cert", required_argument, NULL, OPT_BOOTSTRAP_CA_CERT},
567         {NULL, 0, NULL, 0}
568     };
569     char *short_options = ovs_cmdl_long_options_to_short_options(long_options);
570
571     for (;;) {
572         int c;
573
574         c = getopt_long(argc, argv, short_options, long_options, NULL);
575         if (c == -1) {
576             break;
577         }
578
579         switch (c) {
580         case 'h':
581             usage();
582
583         case 'V':
584             ovs_print_version(OFP13_VERSION, OFP13_VERSION);
585             exit(EXIT_SUCCESS);
586
587         VLOG_OPTION_HANDLERS
588         DAEMON_OPTION_HANDLERS
589         STREAM_SSL_OPTION_HANDLERS
590
591         case OPT_PEER_CA_CERT:
592             stream_ssl_set_peer_ca_cert_file(optarg);
593             break;
594
595         case OPT_BOOTSTRAP_CA_CERT:
596             stream_ssl_set_ca_cert_file(optarg, true);
597             break;
598
599         case '?':
600             exit(EXIT_FAILURE);
601
602         default:
603             abort();
604         }
605     }
606     free(short_options);
607
608     argc -= optind;
609     argv += optind;
610
611     if (argc == 0) {
612         ovs_remote = xasprintf("unix:%s/db.sock", ovs_rundir());
613     } else if (argc == 1) {
614         ovs_remote = xstrdup(argv[0]);
615     } else {
616         VLOG_FATAL("exactly zero or one non-option argument required; "
617                    "use --help for usage");
618     }
619 }
620
621 static void
622 usage(void)
623 {
624     printf("%s: OVN controller\n"
625            "usage %s [OPTIONS] [OVS-DATABASE]\n"
626            "where OVS-DATABASE is a socket on which the OVS OVSDB server is listening.\n",
627                program_name, program_name);
628     stream_usage("OVS-DATABASE", true, false, false);
629     daemon_usage();
630     vlog_usage();
631     printf("\nOther options:\n"
632            "  -h, --help              display this help message\n"
633            "  -V, --version           display version information\n");
634     exit(EXIT_SUCCESS);
635 }
636
637 static void
638 ovn_controller_exit(struct unixctl_conn *conn, int argc OVS_UNUSED,
639              const char *argv[] OVS_UNUSED, void *exiting_)
640 {
641     bool *exiting = exiting_;
642     *exiting = true;
643
644     unixctl_command_reply(conn, NULL);
645 }