/* Returns true if the database is all cleaned up, false if more work is * required. */ bool chassis_cleanup(struct controller_ctx *ctx, const struct sbrec_chassis *chassis_rec) { if (!chassis_rec) { return true; } if (ctx->ovnsb_idl_txn) { ovsdb_idl_txn_add_comment(ctx->ovnsb_idl_txn, "ovn-controller: unregistering chassis '%s'", chassis_rec->name); sbrec_chassis_delete(chassis_rec); } return false; }
/* Returns true if the database is all cleaned up, false if more work is * required. */ bool chassis_cleanup(struct controller_ctx *ctx, const char *chassis_id) { if (!chassis_id) { return true; } /* Delete Chassis row. */ const struct sbrec_chassis *chassis_rec = get_chassis(ctx->ovnsb_idl, chassis_id); if (!chassis_rec) { return true; } if (ctx->ovnsb_idl_txn) { ovsdb_idl_txn_add_comment(ctx->ovnsb_idl_txn, "ovn-controller: unregistering chassis '%s'", chassis_id); sbrec_chassis_delete(chassis_rec); } return false; }
static const struct ovsrec_bridge * create_br_int(struct controller_ctx *ctx, const struct ovsrec_open_vswitch *cfg, const char *bridge_name) { if (!ctx->ovs_idl_txn) { return NULL; } ovsdb_idl_txn_add_comment(ctx->ovs_idl_txn, "ovn-controller: creating integration bridge '%s'", bridge_name); struct ovsrec_interface *iface; iface = ovsrec_interface_insert(ctx->ovs_idl_txn); ovsrec_interface_set_name(iface, bridge_name); ovsrec_interface_set_type(iface, "internal"); struct ovsrec_port *port; port = ovsrec_port_insert(ctx->ovs_idl_txn); ovsrec_port_set_name(port, bridge_name); ovsrec_port_set_interfaces(port, &iface, 1); struct ovsrec_bridge *bridge; bridge = ovsrec_bridge_insert(ctx->ovs_idl_txn); ovsrec_bridge_set_name(bridge, bridge_name); ovsrec_bridge_set_fail_mode(bridge, "secure"); const struct smap oc = SMAP_CONST1(&oc, "disable-in-band", "true"); ovsrec_bridge_set_other_config(bridge, &oc); ovsrec_bridge_set_ports(bridge, &port, 1); struct ovsrec_bridge **bridges; size_t bytes = sizeof *bridges * cfg->n_bridges; bridges = xmalloc(bytes + sizeof *bridges); memcpy(bridges, cfg->bridges, bytes); bridges[cfg->n_bridges] = bridge; ovsrec_open_vswitch_verify_bridges(cfg); ovsrec_open_vswitch_set_bridges(cfg, bridges, cfg->n_bridges + 1); return bridge; }
/* Returns this chassis's Chassis record, if it is available and is currently * amenable to a transaction. */ const struct sbrec_chassis * chassis_run(struct controller_ctx *ctx, const char *chassis_id, const struct ovsrec_bridge *br_int) { if (!ctx->ovnsb_idl_txn) { return NULL; } const struct ovsrec_open_vswitch *cfg; const char *encap_type, *encap_ip; static bool inited = false; cfg = ovsrec_open_vswitch_first(ctx->ovs_idl); if (!cfg) { VLOG_INFO("No Open_vSwitch row defined."); return NULL; } encap_type = smap_get(&cfg->external_ids, "ovn-encap-type"); encap_ip = smap_get(&cfg->external_ids, "ovn-encap-ip"); if (!encap_type || !encap_ip) { VLOG_INFO("Need to specify an encap type and ip"); return NULL; } char *tokstr = xstrdup(encap_type); char *save_ptr = NULL; char *token; uint32_t req_tunnels = 0; for (token = strtok_r(tokstr, ",", &save_ptr); token != NULL; token = strtok_r(NULL, ",", &save_ptr)) { uint32_t type = get_tunnel_type(token); if (!type) { VLOG_INFO("Unknown tunnel type: %s", token); } req_tunnels |= type; } free(tokstr); const char *hostname = smap_get_def(&cfg->external_ids, "hostname", ""); char hostname_[HOST_NAME_MAX + 1]; if (!hostname[0]) { if (gethostname(hostname_, sizeof hostname_)) { hostname_[0] = '\0'; } hostname = hostname_; } const char *bridge_mappings = get_bridge_mappings(&cfg->external_ids); const char *datapath_type = br_int && br_int->datapath_type ? br_int->datapath_type : ""; struct ds iface_types = DS_EMPTY_INITIALIZER; ds_put_cstr(&iface_types, ""); for (int j = 0; j < cfg->n_iface_types; j++) { ds_put_format(&iface_types, "%s,", cfg->iface_types[j]); } ds_chomp(&iface_types, ','); const char *iface_types_str = ds_cstr(&iface_types); const struct sbrec_chassis *chassis_rec = get_chassis(ctx->ovnsb_idl, chassis_id); if (chassis_rec) { if (strcmp(hostname, chassis_rec->hostname)) { sbrec_chassis_set_hostname(chassis_rec, hostname); } /* Determine new values for Chassis external-ids. */ const char *chassis_bridge_mappings = get_bridge_mappings(&chassis_rec->external_ids); const char *chassis_datapath_type = smap_get_def(&chassis_rec->external_ids, "datapath-type", ""); const char *chassis_iface_types = smap_get_def(&chassis_rec->external_ids, "iface-types", ""); /* If any of the external-ids should change, update them. */ if (strcmp(bridge_mappings, chassis_bridge_mappings) || strcmp(datapath_type, chassis_datapath_type) || strcmp(iface_types_str, chassis_iface_types)) { struct smap new_ids; smap_clone(&new_ids, &chassis_rec->external_ids); smap_replace(&new_ids, "ovn-bridge-mappings", bridge_mappings); smap_replace(&new_ids, "datapath-type", datapath_type); smap_replace(&new_ids, "iface-types", iface_types_str); sbrec_chassis_verify_external_ids(chassis_rec); sbrec_chassis_set_external_ids(chassis_rec, &new_ids); smap_destroy(&new_ids); } /* Compare desired tunnels against those currently in the database. */ uint32_t cur_tunnels = 0; bool same = true; for (int i = 0; i < chassis_rec->n_encaps; i++) { cur_tunnels |= get_tunnel_type(chassis_rec->encaps[i]->type); same = same && !strcmp(chassis_rec->encaps[i]->ip, encap_ip); same = same && smap_get_bool(&chassis_rec->encaps[i]->options, "csum", false); } same = same && req_tunnels == cur_tunnels; if (same) { /* Nothing changed. */ inited = true; ds_destroy(&iface_types); return chassis_rec; } else if (!inited) { struct ds cur_encaps = DS_EMPTY_INITIALIZER; for (int i = 0; i < chassis_rec->n_encaps; i++) { ds_put_format(&cur_encaps, "%s,", chassis_rec->encaps[i]->type); } ds_chomp(&cur_encaps, ','); VLOG_WARN("Chassis config changing on startup, make sure " "multiple chassis are not configured : %s/%s->%s/%s", ds_cstr(&cur_encaps), chassis_rec->encaps[0]->ip, encap_type, encap_ip); ds_destroy(&cur_encaps); } } ovsdb_idl_txn_add_comment(ctx->ovnsb_idl_txn, "ovn-controller: registering chassis '%s'", chassis_id); if (!chassis_rec) { struct smap ext_ids = SMAP_INITIALIZER(&ext_ids); smap_add(&ext_ids, "ovn-bridge-mappings", bridge_mappings); smap_add(&ext_ids, "datapath-type", datapath_type); smap_add(&ext_ids, "iface-types", iface_types_str); chassis_rec = sbrec_chassis_insert(ctx->ovnsb_idl_txn); sbrec_chassis_set_name(chassis_rec, chassis_id); sbrec_chassis_set_hostname(chassis_rec, hostname); sbrec_chassis_set_external_ids(chassis_rec, &ext_ids); smap_destroy(&ext_ids); } ds_destroy(&iface_types); int n_encaps = count_1bits(req_tunnels); struct sbrec_encap **encaps = xmalloc(n_encaps * sizeof *encaps); const struct smap options = SMAP_CONST1(&options, "csum", "true"); for (int i = 0; i < n_encaps; i++) { const char *type = pop_tunnel_name(&req_tunnels); encaps[i] = sbrec_encap_insert(ctx->ovnsb_idl_txn); sbrec_encap_set_type(encaps[i], type); sbrec_encap_set_ip(encaps[i], encap_ip); sbrec_encap_set_options(encaps[i], &options); } sbrec_chassis_set_encaps(chassis_rec, encaps, n_encaps); free(encaps); inited = true; return chassis_rec; }
void chassis_run(struct controller_ctx *ctx, const char *chassis_id) { if (!ctx->ovnsb_idl_txn) { return; } const struct ovsrec_open_vswitch *cfg; const char *encap_type, *encap_ip; static bool inited = false; cfg = ovsrec_open_vswitch_first(ctx->ovs_idl); if (!cfg) { VLOG_INFO("No Open_vSwitch row defined."); return; } encap_type = smap_get(&cfg->external_ids, "ovn-encap-type"); encap_ip = smap_get(&cfg->external_ids, "ovn-encap-ip"); if (!encap_type || !encap_ip) { VLOG_INFO("Need to specify an encap type and ip"); return; } char *tokstr = xstrdup(encap_type); char *save_ptr = NULL; char *token; uint32_t req_tunnels = 0; for (token = strtok_r(tokstr, ",", &save_ptr); token != NULL; token = strtok_r(NULL, ",", &save_ptr)) { uint32_t type = get_tunnel_type(token); if (!type) { VLOG_INFO("Unknown tunnel type: %s", token); } req_tunnels |= type; } free(tokstr); const char *hostname = smap_get(&cfg->external_ids, "hostname"); char hostname_[HOST_NAME_MAX + 1]; if (!hostname || !hostname[0]) { if (gethostname(hostname_, sizeof hostname_)) { hostname_[0] = '\0'; } hostname = hostname_; } const struct sbrec_chassis *chassis_rec = get_chassis(ctx->ovnsb_idl, chassis_id); if (chassis_rec) { if (strcmp(hostname, chassis_rec->hostname)) { sbrec_chassis_set_hostname(chassis_rec, hostname); } /* Compare desired tunnels against those currently in the database. */ uint32_t cur_tunnels = 0; bool same = true; for (int i = 0; i < chassis_rec->n_encaps; i++) { cur_tunnels |= get_tunnel_type(chassis_rec->encaps[i]->type); same = same && !strcmp(chassis_rec->encaps[i]->ip, encap_ip); } same = same && req_tunnels == cur_tunnels; if (same) { /* Nothing changed. */ inited = true; return; } else if (!inited) { struct ds cur_encaps = DS_EMPTY_INITIALIZER; for (int i = 0; i < chassis_rec->n_encaps; i++) { ds_put_format(&cur_encaps, "%s,", chassis_rec->encaps[i]->type); } ds_chomp(&cur_encaps, ','); VLOG_WARN("Chassis config changing on startup, make sure " "multiple chassis are not configured : %s/%s->%s/%s", ds_cstr(&cur_encaps), chassis_rec->encaps[0]->ip, encap_type, encap_ip); ds_destroy(&cur_encaps); } } ovsdb_idl_txn_add_comment(ctx->ovnsb_idl_txn, "ovn-controller: registering chassis '%s'", chassis_id); if (!chassis_rec) { chassis_rec = sbrec_chassis_insert(ctx->ovnsb_idl_txn); sbrec_chassis_set_name(chassis_rec, chassis_id); sbrec_chassis_set_hostname(chassis_rec, hostname); } int n_encaps = count_1bits(req_tunnels); struct sbrec_encap **encaps = xmalloc(n_encaps * sizeof *encaps); for (int i = 0; i < n_encaps; i++) { const char *type = pop_tunnel_name(&req_tunnels); encaps[i] = sbrec_encap_insert(ctx->ovnsb_idl_txn); sbrec_encap_set_type(encaps[i], type); sbrec_encap_set_ip(encaps[i], encap_ip); } sbrec_chassis_set_encaps(chassis_rec, encaps, n_encaps); free(encaps); inited = true; }