1 /* Copyright (c) 2015 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.
22 #include "lib/vswitch-idl.h"
23 #include "openvswitch/dynamic-string.h"
24 #include "openvswitch/vlog.h"
25 #include "ovn/lib/ovn-sb-idl.h"
26 #include "ovn-controller.h"
28 VLOG_DEFINE_THIS_MODULE(chassis);
32 #define HOST_NAME_MAX 255
33 #endif /* HOST_NAME_MAX */
36 chassis_register_ovs_idl(struct ovsdb_idl *ovs_idl)
38 ovsdb_idl_add_table(ovs_idl, &ovsrec_table_open_vswitch);
39 ovsdb_idl_add_column(ovs_idl, &ovsrec_open_vswitch_col_external_ids);
43 pop_tunnel_name(uint32_t *type)
48 } else if (*type & STT) {
51 } else if (*type & VXLAN) {
60 get_bridge_mappings(const struct smap *ext_ids)
62 const char *bridge_mappings = smap_get(ext_ids, "ovn-bridge-mappings");
63 return bridge_mappings ? bridge_mappings : "";
67 chassis_run(struct controller_ctx *ctx, const char *chassis_id)
69 if (!ctx->ovnsb_idl_txn) {
73 const struct ovsrec_open_vswitch *cfg;
74 const char *encap_type, *encap_ip;
75 static bool inited = false;
77 cfg = ovsrec_open_vswitch_first(ctx->ovs_idl);
79 VLOG_INFO("No Open_vSwitch row defined.");
83 encap_type = smap_get(&cfg->external_ids, "ovn-encap-type");
84 encap_ip = smap_get(&cfg->external_ids, "ovn-encap-ip");
85 if (!encap_type || !encap_ip) {
86 VLOG_INFO("Need to specify an encap type and ip");
90 char *tokstr = xstrdup(encap_type);
91 char *save_ptr = NULL;
93 uint32_t req_tunnels = 0;
94 for (token = strtok_r(tokstr, ",", &save_ptr); token != NULL;
95 token = strtok_r(NULL, ",", &save_ptr)) {
96 uint32_t type = get_tunnel_type(token);
98 VLOG_INFO("Unknown tunnel type: %s", token);
104 const char *hostname = smap_get(&cfg->external_ids, "hostname");
105 char hostname_[HOST_NAME_MAX + 1];
106 if (!hostname || !hostname[0]) {
107 if (gethostname(hostname_, sizeof hostname_)) {
110 hostname = hostname_;
113 const char *bridge_mappings = get_bridge_mappings(&cfg->external_ids);
115 const struct sbrec_chassis *chassis_rec
116 = get_chassis(ctx->ovnsb_idl, chassis_id);
119 if (strcmp(hostname, chassis_rec->hostname)) {
120 sbrec_chassis_set_hostname(chassis_rec, hostname);
123 const char *chassis_bridge_mappings
124 = get_bridge_mappings(&chassis_rec->external_ids);
125 if (strcmp(bridge_mappings, chassis_bridge_mappings)) {
127 smap_clone(&new_ids, &chassis_rec->external_ids);
128 smap_replace(&new_ids, "ovn-bridge-mappings", bridge_mappings);
129 sbrec_chassis_verify_external_ids(chassis_rec);
130 sbrec_chassis_set_external_ids(chassis_rec, &new_ids);
131 smap_destroy(&new_ids);
134 /* Compare desired tunnels against those currently in the database. */
135 uint32_t cur_tunnels = 0;
137 for (int i = 0; i < chassis_rec->n_encaps; i++) {
138 cur_tunnels |= get_tunnel_type(chassis_rec->encaps[i]->type);
139 same = same && !strcmp(chassis_rec->encaps[i]->ip, encap_ip);
141 same = same && req_tunnels == cur_tunnels;
144 /* Nothing changed. */
147 } else if (!inited) {
148 struct ds cur_encaps = DS_EMPTY_INITIALIZER;
149 for (int i = 0; i < chassis_rec->n_encaps; i++) {
150 ds_put_format(&cur_encaps, "%s,",
151 chassis_rec->encaps[i]->type);
153 ds_chomp(&cur_encaps, ',');
155 VLOG_WARN("Chassis config changing on startup, make sure "
156 "multiple chassis are not configured : %s/%s->%s/%s",
157 ds_cstr(&cur_encaps),
158 chassis_rec->encaps[0]->ip,
159 encap_type, encap_ip);
160 ds_destroy(&cur_encaps);
164 ovsdb_idl_txn_add_comment(ctx->ovnsb_idl_txn,
165 "ovn-controller: registering chassis '%s'",
169 struct smap ext_ids = SMAP_CONST1(&ext_ids, "ovn-bridge-mappings",
171 chassis_rec = sbrec_chassis_insert(ctx->ovnsb_idl_txn);
172 sbrec_chassis_set_name(chassis_rec, chassis_id);
173 sbrec_chassis_set_hostname(chassis_rec, hostname);
174 sbrec_chassis_set_external_ids(chassis_rec, &ext_ids);
177 int n_encaps = count_1bits(req_tunnels);
178 struct sbrec_encap **encaps = xmalloc(n_encaps * sizeof *encaps);
179 for (int i = 0; i < n_encaps; i++) {
180 const char *type = pop_tunnel_name(&req_tunnels);
182 encaps[i] = sbrec_encap_insert(ctx->ovnsb_idl_txn);
184 sbrec_encap_set_type(encaps[i], type);
185 sbrec_encap_set_ip(encaps[i], encap_ip);
188 sbrec_chassis_set_encaps(chassis_rec, encaps, n_encaps);
194 /* Returns true if the database is all cleaned up, false if more work is
197 chassis_cleanup(struct controller_ctx *ctx, const char *chassis_id)
203 /* Delete Chassis row. */
204 const struct sbrec_chassis *chassis_rec
205 = get_chassis(ctx->ovnsb_idl, chassis_id);
209 if (ctx->ovnsb_idl_txn) {
210 ovsdb_idl_txn_add_comment(ctx->ovnsb_idl_txn,
211 "ovn-controller: unregistering chassis '%s'",
213 sbrec_chassis_delete(chassis_rec);