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.
19 #include "lib/dynamic-string.h"
20 #include "lib/vswitch-idl.h"
21 #include "openvswitch/vlog.h"
22 #include "ovn/lib/ovn-sb-idl.h"
23 #include "ovn-controller.h"
25 VLOG_DEFINE_THIS_MODULE(chassis);
28 chassis_register_ovs_idl(struct ovsdb_idl *ovs_idl)
30 ovsdb_idl_add_table(ovs_idl, &ovsrec_table_open_vswitch);
31 ovsdb_idl_add_column(ovs_idl, &ovsrec_open_vswitch_col_external_ids);
35 pop_tunnel_name(uint32_t *type)
40 } else if (*type & STT) {
43 } else if (*type & VXLAN) {
52 chassis_run(struct controller_ctx *ctx, const char *chassis_id)
54 if (!ctx->ovnsb_idl_txn) {
58 const struct sbrec_chassis *chassis_rec;
59 const struct ovsrec_open_vswitch *cfg;
60 const char *encap_type, *encap_ip;
61 static bool inited = false;
63 chassis_rec = get_chassis(ctx->ovnsb_idl, chassis_id);
65 cfg = ovsrec_open_vswitch_first(ctx->ovs_idl);
67 VLOG_INFO("No Open_vSwitch row defined.");
71 encap_type = smap_get(&cfg->external_ids, "ovn-encap-type");
72 encap_ip = smap_get(&cfg->external_ids, "ovn-encap-ip");
73 if (!encap_type || !encap_ip) {
74 VLOG_INFO("Need to specify an encap type and ip");
78 char *tokstr = xstrdup(encap_type);
79 char *save_ptr = NULL;
81 uint32_t req_tunnels = 0;
82 for (token = strtok_r(tokstr, ",", &save_ptr); token != NULL;
83 token = strtok_r(NULL, ",", &save_ptr)) {
84 uint32_t type = get_tunnel_type(token);
86 VLOG_INFO("Unknown tunnel type: %s", token);
93 /* Compare desired tunnels against those currently in the database. */
94 uint32_t cur_tunnels = 0;
96 for (int i = 0; i < chassis_rec->n_encaps; i++) {
97 cur_tunnels |= get_tunnel_type(chassis_rec->encaps[i]->type);
98 same = same && !strcmp(chassis_rec->encaps[i]->ip, encap_ip);
100 same = same && req_tunnels == cur_tunnels;
103 /* Nothing changed. */
106 } else if (!inited) {
107 struct ds cur_encaps = DS_EMPTY_INITIALIZER;
108 for (int i = 0; i < chassis_rec->n_encaps; i++) {
109 ds_put_format(&cur_encaps, "%s,",
110 chassis_rec->encaps[i]->type);
112 ds_chomp(&cur_encaps, ',');
114 VLOG_WARN("Chassis config changing on startup, make sure "
115 "multiple chassis are not configured : %s/%s->%s/%s",
116 ds_cstr(&cur_encaps),
117 chassis_rec->encaps[0]->ip,
118 encap_type, encap_ip);
119 ds_destroy(&cur_encaps);
123 ovsdb_idl_txn_add_comment(ctx->ovnsb_idl_txn,
124 "ovn-controller: registering chassis '%s'",
128 chassis_rec = sbrec_chassis_insert(ctx->ovnsb_idl_txn);
129 sbrec_chassis_set_name(chassis_rec, chassis_id);
132 int n_encaps = count_1bits(req_tunnels);
133 struct sbrec_encap **encaps = xmalloc(n_encaps * sizeof *encaps);
134 for (int i = 0; i < n_encaps; i++) {
135 const char *type = pop_tunnel_name(&req_tunnels);
137 encaps[i] = sbrec_encap_insert(ctx->ovnsb_idl_txn);
139 sbrec_encap_set_type(encaps[i], type);
140 sbrec_encap_set_ip(encaps[i], encap_ip);
143 sbrec_chassis_set_encaps(chassis_rec, encaps, n_encaps);
149 /* Returns true if the database is all cleaned up, false if more work is
152 chassis_cleanup(struct controller_ctx *ctx, const char *chassis_id)
158 /* Delete Chassis row. */
159 const struct sbrec_chassis *chassis_rec
160 = get_chassis(ctx->ovnsb_idl, chassis_id);
164 if (ctx->ovnsb_idl_txn) {
165 ovsdb_idl_txn_add_comment(ctx->ovnsb_idl_txn,
166 "ovn-controller: unregistering chassis '%s'",
168 sbrec_chassis_delete(chassis_rec);