Signed-off-by: Justin Pettit <jpet...@nicira.com> --- ovn/controller/chassis.c | 88 ++++++++++++++++++++++++++--------- ovn/controller/encaps.c | 20 ++++---- ovn/controller/ovn-controller.8.xml | 10 +++- ovn/controller/ovn-controller.c | 14 ++++++ ovn/controller/ovn-controller.h | 11 ++++ ovn/controller/physical.c | 2 +- 6 files changed, 109 insertions(+), 36 deletions(-)
diff --git a/ovn/controller/chassis.c b/ovn/controller/chassis.c index 9d6a77a..894000d 100644 --- a/ovn/controller/chassis.c +++ b/ovn/controller/chassis.c @@ -16,6 +16,7 @@ #include <config.h> #include "chassis.h" +#include "lib/dynamic-string.h" #include "lib/vswitch-idl.h" #include "openvswitch/vlog.h" #include "ovn/lib/ovn-sb-idl.h" @@ -30,6 +31,23 @@ chassis_register_ovs_idl(struct ovsdb_idl *ovs_idl) ovsdb_idl_add_column(ovs_idl, &ovsrec_open_vswitch_col_external_ids); } +static const char * +pop_tunnel_name(uint32_t *type) +{ + if (*type & GENEVE) { + *type &= ~GENEVE; + return "geneve"; + } else if (*type & STT) { + *type &= ~STT; + return "stt"; + } else if (*type & VXLAN) { + *type &= ~VXLAN; + return "vxlan"; + } + + OVS_NOT_REACHED(); +} + void chassis_run(struct controller_ctx *ctx, const char *chassis_id) { @@ -40,13 +58,10 @@ chassis_run(struct controller_ctx *ctx, const char *chassis_id) const struct sbrec_chassis *chassis_rec; const struct ovsrec_open_vswitch *cfg; const char *encap_type, *encap_ip; - struct sbrec_encap *encap_rec; static bool inited = false; chassis_rec = get_chassis_by_name(ctx->ovnsb_idl, chassis_id); - /* xxx Need to support more than one encap. Also need to support - * xxx encap options. */ cfg = ovsrec_open_vswitch_first(ctx->ovs_idl); if (!cfg) { VLOG_INFO("No Open_vSwitch row defined."); @@ -60,23 +75,45 @@ chassis_run(struct controller_ctx *ctx, const char *chassis_id) 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); + if (chassis_rec) { - int i; - - for (i = 0; i < chassis_rec->n_encaps; i++) { - if (!strcmp(chassis_rec->encaps[i]->type, encap_type) - && !strcmp(chassis_rec->encaps[i]->ip, encap_ip)) { - /* Nothing changed. */ - inited = true; - return; - } else if (!inited) { - VLOG_WARN("Chassis config changing on startup, make sure " - "multiple chassis are not configured : %s/%s->%s/%s", - chassis_rec->encaps[i]->type, - chassis_rec->encaps[i]->ip, - encap_type, encap_ip); - } + uint32_t cur_tunnels = 0; + for (int i = 0; i < chassis_rec->n_encaps; i++) { + cur_tunnels |= get_tunnel_type(chassis_rec->encaps[i]->type); + } + if (req_tunnels == cur_tunnels + && !strcmp(chassis_rec->encaps[0]->ip, encap_ip)) { + /* 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); } } @@ -89,12 +126,19 @@ chassis_run(struct controller_ctx *ctx, const char *chassis_id) sbrec_chassis_set_name(chassis_rec, chassis_id); } - encap_rec = sbrec_encap_insert(ctx->ovnsb_idl_txn); + 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(encap_rec, encap_type); - sbrec_encap_set_ip(encap_rec, encap_ip); + sbrec_encap_set_type(encaps[i], type); + sbrec_encap_set_ip(encaps[i], encap_ip); + } - sbrec_chassis_set_encaps(chassis_rec, &encap_rec, 1); + sbrec_chassis_set_encaps(chassis_rec, encaps, n_encaps); + free(encaps); inited = true; } diff --git a/ovn/controller/encaps.c b/ovn/controller/encaps.c index de1aef3..dfb11c0 100644 --- a/ovn/controller/encaps.c +++ b/ovn/controller/encaps.c @@ -210,20 +210,18 @@ bridge_delete_port(const struct ovsrec_bridge *br, static struct sbrec_encap * preferred_encap(const struct sbrec_chassis *chassis_rec) { - size_t i; - - /* For hypervisors, we only support Geneve and STT encapsulations. - * Sets are returned alphabetically, so "geneve" will be preferred - * over "stt". For gateways, we only support VXLAN encapsulation. */ - for (i = 0; i < chassis_rec->n_encaps; i++) { - if (!strcmp(chassis_rec->encaps[i]->type, "geneve") - || !strcmp(chassis_rec->encaps[i]->type, "stt") - || !strcmp(chassis_rec->encaps[i]->type, "vxlan")) { - return chassis_rec->encaps[i]; + struct sbrec_encap *best_encap = NULL; + uint32_t best_type = 0; + + for (int i = 0; i < chassis_rec->n_encaps; i++) { + uint32_t tun_type = get_tunnel_type(chassis_rec->encaps[i]->type); + if (tun_type > best_type) { + best_type = tun_type; + best_encap = chassis_rec->encaps[i]; } } - return NULL; + return best_encap; } void diff --git a/ovn/controller/ovn-controller.8.xml b/ovn/controller/ovn-controller.8.xml index b0aee10..24d34ef 100644 --- a/ovn/controller/ovn-controller.8.xml +++ b/ovn/controller/ovn-controller.8.xml @@ -104,7 +104,13 @@ <dd> <p> The encapsulation type that a chassis should use to connect to - this node. Supported tunnel types for connecting hypervisors + this node. Multiple encapsulation types may be specified with + a comma-separated list. Each listed encapsulation type will + be paired with <code>ovn-encap-ip</code>. + </p> + + <p> + Supported tunnel types for connecting hypervisors are <code>geneve</code> and <code>stt</code>. Gateways may use <code>geneve</code>, <code>vxlan</code>, or <code>stt</code>. @@ -120,7 +126,7 @@ <dt><code>external_ids:ovn-encap-ip</code></dt> <dd> The IP address that a chassis should use to connect to this node - using encapsulation type specified by + using encapsulation types specified by <code>external_ids:ovn-encap-type</code>. </dd> diff --git a/ovn/controller/ovn-controller.c b/ovn/controller/ovn-controller.c index f1bc524..eca32b3 100644 --- a/ovn/controller/ovn-controller.c +++ b/ovn/controller/ovn-controller.c @@ -57,6 +57,20 @@ OVS_NO_RETURN static void usage(void); static char *ovs_remote; +uint32_t +get_tunnel_type(const char *name) +{ + if (!strcmp(name, "geneve")) { + return GENEVE; + } else if (!strcmp(name, "stt")) { + return STT; + } else if (!strcmp(name, "vxlan")) { + return VXLAN; + } + + return 0; +} + static const struct ovsrec_bridge * get_bridge(struct ovsdb_idl *ovs_idl, const char *br_name) { diff --git a/ovn/controller/ovn-controller.h b/ovn/controller/ovn-controller.h index be89b5f..8b10675 100644 --- a/ovn/controller/ovn-controller.h +++ b/ovn/controller/ovn-controller.h @@ -41,4 +41,15 @@ get_chassis_by_name(struct ovsdb_idl *ovnsb_idl, const char *chassis_id) return chassis_rec; } +/* Must be a bit-field ordered from most-preferred (higher number) to + * least-preferred (lower number). */ +enum chassis_tunnel_type { + GENEVE = 1 << 2, + STT = 1 << 1, + VXLAN = 1 << 0 +}; + +uint32_t get_tunnel_type(const char *name); + + #endif /* ovn/ovn-controller.h */ diff --git a/ovn/controller/physical.c b/ovn/controller/physical.c index b26db63..ca495c0 100644 --- a/ovn/controller/physical.c +++ b/ovn/controller/physical.c @@ -54,7 +54,7 @@ struct chassis_tunnel { struct hmap_node hmap_node; const char *chassis_id; ofp_port_t ofport; - enum chassis_tunnel_type { GENEVE, STT, VXLAN } type; + enum chassis_tunnel_type type; }; static struct chassis_tunnel * -- 1.7.5.4 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev