ovn-controller: Rename init functions that just register IDL columns.
[cascardo/ovs.git] / ovn / controller / binding.c
1 /* Copyright (c) 2015 Nicira, Inc.
2  *
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:
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
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.
14  */
15
16 #include <config.h>
17 #include "binding.h"
18
19 #include "lib/sset.h"
20 #include "lib/util.h"
21 #include "lib/vswitch-idl.h"
22 #include "openvswitch/vlog.h"
23 #include "ovn/lib/ovn-sb-idl.h"
24 #include "ovn-controller.h"
25
26 VLOG_DEFINE_THIS_MODULE(binding);
27
28 void
29 binding_register_ovs_idl(struct ovsdb_idl *ovs_idl)
30 {
31     ovsdb_idl_add_table(ovs_idl, &ovsrec_table_open_vswitch);
32     ovsdb_idl_add_column(ovs_idl, &ovsrec_open_vswitch_col_bridges);
33
34     ovsdb_idl_add_table(ovs_idl, &ovsrec_table_bridge);
35     ovsdb_idl_add_column(ovs_idl, &ovsrec_bridge_col_name);
36     ovsdb_idl_add_column(ovs_idl, &ovsrec_bridge_col_ports);
37
38     ovsdb_idl_add_table(ovs_idl, &ovsrec_table_port);
39     ovsdb_idl_add_column(ovs_idl, &ovsrec_port_col_name);
40     ovsdb_idl_add_column(ovs_idl, &ovsrec_port_col_interfaces);
41
42     ovsdb_idl_add_table(ovs_idl, &ovsrec_table_interface);
43     ovsdb_idl_add_column(ovs_idl, &ovsrec_interface_col_name);
44     ovsdb_idl_add_column(ovs_idl, &ovsrec_interface_col_external_ids);
45 }
46
47 static void
48 get_local_iface_ids(const struct ovsrec_bridge *br_int, struct sset *lports)
49 {
50     int i;
51
52     for (i = 0; i < br_int->n_ports; i++) {
53         const struct ovsrec_port *port_rec = br_int->ports[i];
54         const char *iface_id;
55         int j;
56
57         if (!strcmp(port_rec->name, br_int->name)) {
58             continue;
59         }
60
61         for (j = 0; j < port_rec->n_interfaces; j++) {
62             const struct ovsrec_interface *iface_rec;
63
64             iface_rec = port_rec->interfaces[j];
65             iface_id = smap_get(&iface_rec->external_ids, "iface-id");
66             if (!iface_id) {
67                 continue;
68             }
69             sset_add(lports, iface_id);
70         }
71     }
72 }
73
74 void
75 binding_run(struct controller_ctx *ctx, const struct ovsrec_bridge *br_int,
76             const char *chassis_id)
77 {
78     const struct sbrec_chassis *chassis_rec;
79     const struct sbrec_binding *binding_rec;
80     struct sset lports, all_lports;
81     const char *name;
82
83     if (!ctx->ovnsb_idl_txn) {
84         return;
85     }
86
87     chassis_rec = get_chassis_by_name(ctx->ovnsb_idl, chassis_id);
88     if (!chassis_rec) {
89         return;
90     }
91
92     sset_init(&lports);
93     sset_init(&all_lports);
94     if (br_int) {
95         get_local_iface_ids(br_int, &lports);
96     } else {
97         /* We have no integration bridge, therefore no local logical ports.
98          * We'll remove our chassis from all port binding records below. */
99     }
100     sset_clone(&all_lports, &lports);
101
102     ovsdb_idl_txn_add_comment(ctx->ovnsb_idl_txn,
103                               "ovn-controller: updating bindings for '%s'",
104                               chassis_id);
105
106     SBREC_BINDING_FOR_EACH(binding_rec, ctx->ovnsb_idl) {
107         if (sset_find_and_delete(&lports, binding_rec->logical_port) ||
108                 (binding_rec->parent_port && binding_rec->parent_port[0] &&
109                  sset_contains(&all_lports, binding_rec->parent_port))) {
110             if (binding_rec->chassis == chassis_rec) {
111                 continue;
112             }
113             if (binding_rec->chassis) {
114                 VLOG_INFO("Changing chassis for lport %s from %s to %s",
115                           binding_rec->logical_port,
116                           binding_rec->chassis->name,
117                           chassis_rec->name);
118             }
119             sbrec_binding_set_chassis(binding_rec, chassis_rec);
120         } else if (binding_rec->chassis == chassis_rec) {
121             sbrec_binding_set_chassis(binding_rec, NULL);
122         }
123     }
124
125     SSET_FOR_EACH (name, &lports) {
126         VLOG_DBG("No binding record for lport %s", name);
127     }
128     sset_destroy(&lports);
129     sset_destroy(&all_lports);
130 }
131
132 /* Returns true if the database is all cleaned up, false if more work is
133  * required. */
134 bool
135 binding_cleanup(struct controller_ctx *ctx, const char *chassis_id)
136 {
137     if (!ctx->ovnsb_idl_txn) {
138         return false;
139     }
140
141     if (!chassis_id) {
142         return true;
143     }
144     const struct sbrec_chassis *chassis_rec
145         = get_chassis_by_name(ctx->ovnsb_idl, chassis_id);
146     if (!chassis_rec) {
147         return true;
148     }
149
150     ovsdb_idl_txn_add_comment(ctx->ovnsb_idl_txn,
151                               "ovn-controller: removing all bindings for '%s'",
152                               chassis_id);
153
154     const struct sbrec_binding *binding_rec;
155     bool any_changes = false;
156     SBREC_BINDING_FOR_EACH(binding_rec, ctx->ovnsb_idl) {
157         if (binding_rec->chassis == chassis_rec) {
158             sbrec_binding_set_chassis(binding_rec, NULL);
159             any_changes = true;
160         }
161     }
162     return !any_changes;
163 }