1 /* Copyright (c) 2015, 2016 Nicira, Inc.
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:
7 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 #include "ovn-controller.h"
28 #include "command-line.h"
32 #include "openvswitch/dynamic-string.h"
34 #include "fatal-signal.h"
37 #include "lib/vswitch-idl.h"
40 #include "openvswitch/vconn.h"
41 #include "openvswitch/vlog.h"
42 #include "ovn/lib/ovn-sb-idl.h"
46 #include "poll-loop.h"
47 #include "lib/bitmap.h"
50 #include "stream-ssl.h"
55 VLOG_DEFINE_THIS_MODULE(main);
57 static unixctl_cb_func ovn_controller_exit;
58 static unixctl_cb_func ct_zone_list;
60 #define DEFAULT_BRIDGE_NAME "br-int"
62 static void parse_options(int argc, char *argv[]);
63 OVS_NO_RETURN static void usage(void);
65 static char *ovs_remote;
67 struct local_datapath *
68 get_local_datapath(const struct hmap *local_datapaths, uint32_t tunnel_key)
70 struct hmap_node *node = hmap_first_with_hash(local_datapaths, tunnel_key);
72 ? CONTAINER_OF(node, struct local_datapath, hmap_node)
76 struct patched_datapath *
77 get_patched_datapath(const struct hmap *patched_datapaths, uint32_t tunnel_key)
79 struct hmap_node *node = hmap_first_with_hash(patched_datapaths,
82 ? CONTAINER_OF(node, struct patched_datapath, hmap_node)
86 const struct sbrec_chassis *
87 get_chassis(struct ovsdb_idl *ovnsb_idl, const char *chassis_id)
89 const struct sbrec_chassis *chassis_rec;
91 SBREC_CHASSIS_FOR_EACH(chassis_rec, ovnsb_idl) {
92 if (!strcmp(chassis_rec->name, chassis_id)) {
101 get_tunnel_type(const char *name)
103 if (!strcmp(name, "geneve")) {
105 } else if (!strcmp(name, "stt")) {
107 } else if (!strcmp(name, "vxlan")) {
114 const struct ovsrec_bridge *
115 get_bridge(struct ovsdb_idl *ovs_idl, const char *br_name)
117 const struct ovsrec_bridge *br;
118 OVSREC_BRIDGE_FOR_EACH (br, ovs_idl) {
119 if (!strcmp(br->name, br_name)) {
126 static const struct ovsrec_bridge *
127 create_br_int(struct controller_ctx *ctx,
128 const struct ovsrec_open_vswitch *cfg,
129 const char *bridge_name)
131 if (!ctx->ovs_idl_txn) {
135 ovsdb_idl_txn_add_comment(ctx->ovs_idl_txn,
136 "ovn-controller: creating integration bridge '%s'", bridge_name);
138 struct ovsrec_interface *iface;
139 iface = ovsrec_interface_insert(ctx->ovs_idl_txn);
140 ovsrec_interface_set_name(iface, bridge_name);
141 ovsrec_interface_set_type(iface, "internal");
143 struct ovsrec_port *port;
144 port = ovsrec_port_insert(ctx->ovs_idl_txn);
145 ovsrec_port_set_name(port, bridge_name);
146 ovsrec_port_set_interfaces(port, &iface, 1);
148 struct ovsrec_bridge *bridge;
149 bridge = ovsrec_bridge_insert(ctx->ovs_idl_txn);
150 ovsrec_bridge_set_name(bridge, bridge_name);
151 ovsrec_bridge_set_fail_mode(bridge, "secure");
152 const struct smap oc = SMAP_CONST1(&oc, "disable-in-band", "true");
153 ovsrec_bridge_set_other_config(bridge, &oc);
154 ovsrec_bridge_set_ports(bridge, &port, 1);
156 struct ovsrec_bridge **bridges;
157 size_t bytes = sizeof *bridges * cfg->n_bridges;
158 bridges = xmalloc(bytes + sizeof *bridges);
159 memcpy(bridges, cfg->bridges, bytes);
160 bridges[cfg->n_bridges] = bridge;
161 ovsrec_open_vswitch_verify_bridges(cfg);
162 ovsrec_open_vswitch_set_bridges(cfg, bridges, cfg->n_bridges + 1);
167 static const struct ovsrec_bridge *
168 get_br_int(struct controller_ctx *ctx)
170 const struct ovsrec_open_vswitch *cfg;
171 cfg = ovsrec_open_vswitch_first(ctx->ovs_idl);
176 const char *br_int_name = smap_get(&cfg->external_ids, "ovn-bridge");
178 br_int_name = DEFAULT_BRIDGE_NAME;
181 const struct ovsrec_bridge *br;
182 br = get_bridge(ctx->ovs_idl, br_int_name);
184 return create_br_int(ctx, cfg, br_int_name);
190 get_chassis_id(const struct ovsdb_idl *ovs_idl)
192 const struct ovsrec_open_vswitch *cfg = ovsrec_open_vswitch_first(ovs_idl);
193 const char *chassis_id = cfg ? smap_get(&cfg->external_ids, "system-id") : NULL;
196 static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1);
197 VLOG_WARN_RL(&rl, "'system-id' in Open_vSwitch database is missing.");
203 /* Retrieves the OVN Southbound remote location from the
204 * "external-ids:ovn-remote" key in 'ovs_idl' and returns a copy of it.
206 * XXX ovn-controller does not support this changing mid-run, but that should
207 * be addressed later. */
209 get_ovnsb_remote(struct ovsdb_idl *ovs_idl)
212 ovsdb_idl_run(ovs_idl);
214 const struct ovsrec_open_vswitch *cfg
215 = ovsrec_open_vswitch_first(ovs_idl);
217 const char *remote = smap_get(&cfg->external_ids, "ovn-remote");
219 return xstrdup(remote);
223 VLOG_INFO("OVN OVSDB remote not specified. Waiting...");
224 ovsdb_idl_wait(ovs_idl);
229 /* Retrieves the OVN Southbound remote's json session probe interval from the
230 * "external-ids:ovn-remote-probe-interval" key in 'ovs_idl' and returns it.
232 * This function must be called after get_ovnsb_remote(). */
234 get_ovnsb_remote_probe_interval(struct ovsdb_idl *ovs_idl, int *value)
236 const struct ovsrec_open_vswitch *cfg = ovsrec_open_vswitch_first(ovs_idl);
241 const char *probe_interval =
242 smap_get(&cfg->external_ids, "ovn-remote-probe-interval");
243 if (probe_interval) {
244 if (str_to_int(probe_interval, 10, value)) {
248 VLOG_WARN("Invalid value for OVN remote probe interval: %s",
256 main(int argc, char *argv[])
258 struct unixctl_server *unixctl;
262 ovs_cmdl_proctitle_init(argc, argv);
263 set_program_name(argv[0]);
264 service_start(&argc, &argv);
265 parse_options(argc, argv);
266 fatal_ignore_sigpipe();
268 daemonize_start(false);
270 retval = unixctl_server_create(NULL, &unixctl);
274 unixctl_command_register("exit", "", 0, 0, ovn_controller_exit, &exiting);
276 daemonize_complete();
285 /* Connect to OVS OVSDB instance. We do not monitor all tables by
286 * default, so modules must register their interest explicitly. */
287 struct ovsdb_idl_loop ovs_idl_loop = OVSDB_IDL_LOOP_INITIALIZER(
288 ovsdb_idl_create(ovs_remote, &ovsrec_idl_class, false, true));
289 ovsdb_idl_add_table(ovs_idl_loop.idl, &ovsrec_table_open_vswitch);
290 ovsdb_idl_add_column(ovs_idl_loop.idl,
291 &ovsrec_open_vswitch_col_external_ids);
292 ovsdb_idl_add_column(ovs_idl_loop.idl, &ovsrec_open_vswitch_col_bridges);
293 ovsdb_idl_add_table(ovs_idl_loop.idl, &ovsrec_table_interface);
294 ovsdb_idl_add_column(ovs_idl_loop.idl, &ovsrec_interface_col_name);
295 ovsdb_idl_add_column(ovs_idl_loop.idl, &ovsrec_interface_col_type);
296 ovsdb_idl_add_column(ovs_idl_loop.idl, &ovsrec_interface_col_options);
297 ovsdb_idl_add_table(ovs_idl_loop.idl, &ovsrec_table_port);
298 ovsdb_idl_add_column(ovs_idl_loop.idl, &ovsrec_port_col_name);
299 ovsdb_idl_add_column(ovs_idl_loop.idl, &ovsrec_port_col_interfaces);
300 ovsdb_idl_add_column(ovs_idl_loop.idl, &ovsrec_port_col_external_ids);
301 ovsdb_idl_add_table(ovs_idl_loop.idl, &ovsrec_table_bridge);
302 ovsdb_idl_add_column(ovs_idl_loop.idl, &ovsrec_bridge_col_ports);
303 ovsdb_idl_add_column(ovs_idl_loop.idl, &ovsrec_bridge_col_name);
304 ovsdb_idl_add_column(ovs_idl_loop.idl, &ovsrec_bridge_col_fail_mode);
305 ovsdb_idl_add_column(ovs_idl_loop.idl, &ovsrec_bridge_col_other_config);
306 chassis_register_ovs_idl(ovs_idl_loop.idl);
307 encaps_register_ovs_idl(ovs_idl_loop.idl);
308 binding_register_ovs_idl(ovs_idl_loop.idl);
309 physical_register_ovs_idl(ovs_idl_loop.idl);
310 ovsdb_idl_get_initial_snapshot(ovs_idl_loop.idl);
312 /* Connect to OVN SB database. */
313 char *ovnsb_remote = get_ovnsb_remote(ovs_idl_loop.idl);
314 struct ovsdb_idl_loop ovnsb_idl_loop = OVSDB_IDL_LOOP_INITIALIZER(
315 ovsdb_idl_create(ovnsb_remote, &sbrec_idl_class, true, true));
316 ovsdb_idl_get_initial_snapshot(ovnsb_idl_loop.idl);
318 int probe_interval = 0;
319 if (get_ovnsb_remote_probe_interval(ovs_idl_loop.idl, &probe_interval)) {
320 ovsdb_idl_set_probe_interval(ovnsb_idl_loop.idl, probe_interval);
323 /* Initialize connection tracking zones. */
324 struct simap ct_zones = SIMAP_INITIALIZER(&ct_zones);
325 unsigned long ct_zone_bitmap[BITMAP_N_LONGS(MAX_CT_ZONES)];
326 bitmap_set1(ct_zone_bitmap, 0); /* Zone 0 is reserved. */
327 unixctl_command_register("ct-zone-list", "", 0, 0,
328 ct_zone_list, &ct_zones);
333 struct controller_ctx ctx = {
334 .ovs_idl = ovs_idl_loop.idl,
335 .ovs_idl_txn = ovsdb_idl_loop_run(&ovs_idl_loop),
336 .ovnsb_idl = ovnsb_idl_loop.idl,
337 .ovnsb_idl_txn = ovsdb_idl_loop_run(&ovnsb_idl_loop),
340 /* Contains "struct local_datpath" nodes whose hash values are the
341 * tunnel_key of datapaths with at least one local port binding. */
342 struct hmap local_datapaths = HMAP_INITIALIZER(&local_datapaths);
344 struct hmap patched_datapaths = HMAP_INITIALIZER(&patched_datapaths);
346 const struct ovsrec_bridge *br_int = get_br_int(&ctx);
347 const char *chassis_id = get_chassis_id(ctx.ovs_idl);
350 chassis_run(&ctx, chassis_id);
351 encaps_run(&ctx, br_int, chassis_id);
352 binding_run(&ctx, br_int, chassis_id, &ct_zones, ct_zone_bitmap,
357 patch_run(&ctx, br_int, &local_datapaths, &patched_datapaths);
359 struct lport_index lports;
360 struct mcgroup_index mcgroups;
361 lport_index_init(&lports, ctx.ovnsb_idl);
362 mcgroup_index_init(&mcgroups, ctx.ovnsb_idl);
364 enum mf_field_id mff_ovn_geneve = ofctrl_run(br_int);
366 pinctrl_run(&ctx, &lports, br_int);
368 struct hmap flow_table = HMAP_INITIALIZER(&flow_table);
369 lflow_run(&ctx, &lports, &mcgroups, &local_datapaths,
370 &patched_datapaths, &ct_zones, &flow_table);
372 physical_run(&ctx, mff_ovn_geneve,
373 br_int, chassis_id, &ct_zones, &flow_table,
374 &local_datapaths, &patched_datapaths);
376 ofctrl_put(&flow_table);
377 hmap_destroy(&flow_table);
378 mcgroup_index_destroy(&mcgroups);
379 lport_index_destroy(&lports);
382 struct local_datapath *cur_node, *next_node;
383 HMAP_FOR_EACH_SAFE (cur_node, next_node, hmap_node, &local_datapaths) {
384 hmap_remove(&local_datapaths, &cur_node->hmap_node);
387 hmap_destroy(&local_datapaths);
389 struct patched_datapath *pd_cur_node, *pd_next_node;
390 HMAP_FOR_EACH_SAFE (pd_cur_node, pd_next_node, hmap_node,
391 &patched_datapaths) {
392 hmap_remove(&patched_datapaths, &pd_cur_node->hmap_node);
395 hmap_destroy(&patched_datapaths);
397 unixctl_server_run(unixctl);
399 unixctl_server_wait(unixctl);
401 poll_immediate_wake();
408 ovsdb_idl_loop_commit_and_wait(&ovnsb_idl_loop);
409 ovsdb_idl_loop_commit_and_wait(&ovs_idl_loop);
411 if (should_service_stop()) {
416 /* It's time to exit. Clean up the databases. */
419 struct controller_ctx ctx = {
420 .ovs_idl = ovs_idl_loop.idl,
421 .ovs_idl_txn = ovsdb_idl_loop_run(&ovs_idl_loop),
422 .ovnsb_idl = ovnsb_idl_loop.idl,
423 .ovnsb_idl_txn = ovsdb_idl_loop_run(&ovnsb_idl_loop),
426 const struct ovsrec_bridge *br_int = get_br_int(&ctx);
427 const char *chassis_id = get_chassis_id(ctx.ovs_idl);
429 /* Run all of the cleanup functions, even if one of them returns false.
430 * We're done if all of them return true. */
431 done = binding_cleanup(&ctx, chassis_id);
432 done = chassis_cleanup(&ctx, chassis_id) && done;
433 done = encaps_cleanup(&ctx, br_int) && done;
435 poll_immediate_wake();
438 ovsdb_idl_loop_commit_and_wait(&ovnsb_idl_loop);
439 ovsdb_idl_loop_commit_and_wait(&ovs_idl_loop);
443 unixctl_server_destroy(unixctl);
448 simap_destroy(&ct_zones);
450 ovsdb_idl_loop_destroy(&ovs_idl_loop);
451 ovsdb_idl_loop_destroy(&ovnsb_idl_loop);
461 parse_options(int argc, char *argv[])
464 OPT_PEER_CA_CERT = UCHAR_MAX + 1,
465 OPT_BOOTSTRAP_CA_CERT,
470 static struct option long_options[] = {
471 {"help", no_argument, NULL, 'h'},
472 {"version", no_argument, NULL, 'V'},
475 STREAM_SSL_LONG_OPTIONS,
476 {"peer-ca-cert", required_argument, NULL, OPT_PEER_CA_CERT},
477 {"bootstrap-ca-cert", required_argument, NULL, OPT_BOOTSTRAP_CA_CERT},
480 char *short_options = ovs_cmdl_long_options_to_short_options(long_options);
485 c = getopt_long(argc, argv, short_options, long_options, NULL);
495 ovs_print_version(OFP13_VERSION, OFP13_VERSION);
499 DAEMON_OPTION_HANDLERS
500 STREAM_SSL_OPTION_HANDLERS
502 case OPT_PEER_CA_CERT:
503 stream_ssl_set_peer_ca_cert_file(optarg);
506 case OPT_BOOTSTRAP_CA_CERT:
507 stream_ssl_set_ca_cert_file(optarg, true);
523 ovs_remote = xasprintf("unix:%s/db.sock", ovs_rundir());
524 } else if (argc == 1) {
525 ovs_remote = xstrdup(argv[0]);
527 VLOG_FATAL("exactly zero or one non-option argument required; "
528 "use --help for usage");
535 printf("%s: OVN controller\n"
536 "usage %s [OPTIONS] [OVS-DATABASE]\n"
537 "where OVS-DATABASE is a socket on which the OVS OVSDB server is listening.\n",
538 program_name, program_name);
539 stream_usage("OVS-DATABASE", true, false, false);
542 printf("\nOther options:\n"
543 " -h, --help display this help message\n"
544 " -V, --version display version information\n");
549 ovn_controller_exit(struct unixctl_conn *conn, int argc OVS_UNUSED,
550 const char *argv[] OVS_UNUSED, void *exiting_)
552 bool *exiting = exiting_;
555 unixctl_command_reply(conn, NULL);
559 ct_zone_list(struct unixctl_conn *conn, int argc OVS_UNUSED,
560 const char *argv[] OVS_UNUSED, void *ct_zones_)
562 struct simap *ct_zones = ct_zones_;
563 struct ds ds = DS_EMPTY_INITIALIZER;
564 struct simap_node *zone;
566 SIMAP_FOR_EACH(zone, ct_zones) {
567 ds_put_format(&ds, "%s %d\n", zone->name, zone->data);
570 unixctl_command_reply(conn, ds_cstr(&ds));