void format_flags(struct ds *ds, const char *(*bit_to_string)(uint32_t), uint32_t flags, char del) { uint32_t bad = 0; if (!flags) { return; } while (flags) { uint32_t bit = rightmost_1bit(flags); const char *s; s = bit_to_string(bit); if (s) { ds_put_format(ds, "%s%c", s, del); } else { bad |= bit; } flags &= ~bit; } if (bad) { ds_put_format(ds, "0x%"PRIx32"%c", bad, del); } ds_chomp(ds, del); }
static void test_lex(const char *input) { struct ds output; ds_init(&output); struct lexer lexer; lexer_init(&lexer, input); ds_clear(&output); while (lexer_get(&lexer) != LEX_T_END) { size_t len = output.length; lex_token_format(&lexer.token, &output); /* Check that the formatted version can really be parsed back * losslessly. */ if (lexer.token.type != LEX_T_ERROR) { const char *s = ds_cstr(&output) + len; struct lexer l2; lexer_init(&l2, s); lexer_get(&l2); compare_token(&lexer.token, &l2.token); lexer_destroy(&l2); } ds_put_char(&output, ' '); } lexer_destroy(&lexer); ds_chomp(&output, ' '); puts(ds_cstr(&output)); ds_destroy(&output); }
static void output_line (struct line_reader *r, struct string *s, size_t n) { int unit = r->encoding_info.unit; output_bytes (r, s, n); r->head += unit; r->length -= unit; ds_chomp (s, ss_buffer (r->encoding_info.cr, unit)); }
enum ofperr ofputil_queue_get_config_reply_format(struct ds *string, const struct ofp_header *oh, const struct ofputil_port_map *port_map) { struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length)); struct ofputil_queue_config *queues = NULL; size_t allocated_queues = 0; size_t n = 0; int retval = 0; for (;;) { if (n >= allocated_queues) { queues = x2nrealloc(queues, &allocated_queues, sizeof *queues); } retval = ofputil_pull_queue_get_config_reply(&b, &queues[n]); if (retval) { break; } n++; } qsort(queues, n, sizeof *queues, compare_queues); ds_put_char(string, ' '); ofp_port_t port = 0; for (const struct ofputil_queue_config *q = queues; q < &queues[n]; q++) { if (q->port != port) { port = q->port; ds_put_cstr(string, "port="); ofputil_format_port(port, port_map, string); ds_put_char(string, '\n'); } ds_put_format(string, "queue %"PRIu32":", q->queue); print_queue_rate(string, "min_rate", q->min_rate); print_queue_rate(string, "max_rate", q->max_rate); ds_put_char(string, '\n'); } ds_chomp(string, ' '); free(queues); return retval != EOF ? retval : 0; }
/* 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; }