Branch data Line data Source code
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 : :
18 : : #include "vtep.h"
19 : :
20 : : #include "lib/hash.h"
21 : : #include "openvswitch/hmap.h"
22 : : #include "openvswitch/shash.h"
23 : : #include "lib/smap.h"
24 : : #include "lib/sset.h"
25 : : #include "lib/util.h"
26 : : #include "ovn-controller-vtep.h"
27 : : #include "openvswitch/vlog.h"
28 : : #include "ovn/lib/ovn-sb-idl.h"
29 : : #include "vtep/vtep-idl.h"
30 : :
31 : 14 : VLOG_DEFINE_THIS_MODULE(vtep);
32 : :
33 : : struct vtep_rec_physical_locator_list_entry {
34 : : struct ovs_list locators_node;
35 : : const struct vteprec_physical_locator *vteprec_ploc;
36 : : };
37 : :
38 : : struct mmr_hash_node_data {
39 : : const struct vteprec_mcast_macs_remote *mmr;
40 : : struct shash physical_locators;
41 : : };
42 : :
43 : : /*
44 : : * Scans through the Binding table in ovnsb, and updates the vtep logical
45 : : * switch tunnel keys and the 'Ucast_Macs_Remote' table in the VTEP
46 : : * database.
47 : : *
48 : : */
49 : :
50 : : /* Searches the 'chassis_rec->encaps' for the first vtep tunnel
51 : : * configuration, returns the 'ip'. Unless duplicated, the returned
52 : : * pointer cannot live past current vtep_run() execution. */
53 : : static const char *
54 : 95 : get_chassis_vtep_ip(const struct sbrec_chassis *chassis_rec)
55 : : {
56 [ + - ]: 95 : if (chassis_rec) {
57 : : size_t i;
58 : :
59 [ + - ]: 95 : for (i = 0; i < chassis_rec->n_encaps; i++) {
60 [ + - ]: 95 : if (!strcmp(chassis_rec->encaps[i]->type, "vxlan")) {
61 : 95 : return chassis_rec->encaps[i]->ip;
62 : : }
63 : : }
64 : : }
65 : :
66 : 0 : return NULL;
67 : : }
68 : :
69 : : /* Creates a new 'Ucast_Macs_Remote'. */
70 : : static struct vteprec_ucast_macs_remote *
71 : 6 : create_umr(struct ovsdb_idl_txn *vtep_idl_txn, const char *mac,
72 : : const struct vteprec_logical_switch *vtep_ls)
73 : : {
74 : 6 : struct vteprec_ucast_macs_remote *new_umr =
75 : : vteprec_ucast_macs_remote_insert(vtep_idl_txn);
76 : :
77 : 6 : vteprec_ucast_macs_remote_set_MAC(new_umr, mac);
78 : 6 : vteprec_ucast_macs_remote_set_logical_switch(new_umr, vtep_ls);
79 : :
80 : 6 : return new_umr;
81 : : }
82 : :
83 : : /* Creates a new 'Physical_Locator'. */
84 : : static struct vteprec_physical_locator *
85 : 5 : create_pl(struct ovsdb_idl_txn *vtep_idl_txn, const char *chassis_ip)
86 : : {
87 : 5 : struct vteprec_physical_locator *new_pl =
88 : : vteprec_physical_locator_insert(vtep_idl_txn);
89 : :
90 : 5 : vteprec_physical_locator_set_dst_ip(new_pl, chassis_ip);
91 : 5 : vteprec_physical_locator_set_encapsulation_type(new_pl, VTEP_ENCAP_TYPE);
92 : :
93 : 5 : return new_pl;
94 : : }
95 : :
96 : : /* Creates a new 'Mcast_Macs_Remote'. */
97 : : static void
98 : 8 : vtep_create_mmr(struct ovsdb_idl_txn *vtep_idl_txn, const char *mac,
99 : : const struct vteprec_logical_switch *vtep_ls,
100 : : const struct vteprec_physical_locator_set *ploc_set)
101 : : {
102 : 8 : struct vteprec_mcast_macs_remote *new_mmr =
103 : : vteprec_mcast_macs_remote_insert(vtep_idl_txn);
104 : :
105 : 8 : vteprec_mcast_macs_remote_set_MAC(new_mmr, mac);
106 : 8 : vteprec_mcast_macs_remote_set_logical_switch(new_mmr, vtep_ls);
107 : 8 : vteprec_mcast_macs_remote_set_locator_set(new_mmr, ploc_set);
108 : 8 : }
109 : :
110 : : /* Compares previous and new mmr locator sets and returns true if they
111 : : * differ and false otherwise. This function also preps a new locator
112 : : * set for database write.
113 : : *
114 : : * 'locators_list' is the new set of locators for the associated
115 : : * 'Mcast_Macs_Remote' entry passed in and is queried to generate the
116 : : * new set of locators in vtep database format. */
117 : : static bool
118 : 232 : vtep_process_pls(const struct ovs_list *locators_list,
119 : : const struct mmr_hash_node_data *mmr_ext,
120 : : struct vteprec_physical_locator **locators)
121 : : {
122 : 232 : size_t n_locators_prev = 0;
123 : 232 : size_t n_locators_new = ovs_list_size(locators_list);
124 : 232 : bool locator_lists_differ = false;
125 : :
126 [ + + ]: 232 : if (mmr_ext) {
127 : 69 : n_locators_prev = mmr_ext->mmr->locator_set->n_locators;
128 : : }
129 [ + + ]: 232 : if (n_locators_prev != n_locators_new) {
130 : 8 : locator_lists_differ = true;
131 : : }
132 : :
133 [ + + ]: 232 : if (n_locators_new) {
134 : 75 : int i = 0;
135 : : struct vtep_rec_physical_locator_list_entry *ploc_entry;
136 [ + + ]: 167 : LIST_FOR_EACH (ploc_entry, locators_node, locators_list) {
137 : 184 : locators[i] = (struct vteprec_physical_locator *)
138 : 92 : ploc_entry->vteprec_ploc;
139 [ + + ][ - + ]: 92 : if (mmr_ext && !shash_find_data(&mmr_ext->physical_locators,
140 : 84 : locators[i]->dst_ip)) {
141 : 0 : locator_lists_differ = true;
142 : : }
143 : 92 : i++;
144 : : }
145 : : }
146 : :
147 : 232 : return locator_lists_differ;
148 : : }
149 : :
150 : : /* Creates a new 'Mcast_Macs_Remote' entry if needed and also cleans up
151 : : * out-dated remote mcast mac entries as needed. */
152 : : static void
153 : 232 : vtep_update_mmr(struct ovsdb_idl_txn *vtep_idl_txn,
154 : : struct ovs_list *locators_list,
155 : : const struct vteprec_logical_switch *vtep_ls,
156 : : const struct mmr_hash_node_data *mmr_ext)
157 : : {
158 : 232 : struct vteprec_physical_locator **locators = NULL;
159 : 232 : size_t n_locators_new = ovs_list_size(locators_list);
160 : : bool mmr_changed;
161 : :
162 : 232 : locators = xmalloc(n_locators_new * sizeof *locators);
163 : :
164 : 232 : mmr_changed = vtep_process_pls(locators_list, mmr_ext, locators);
165 : :
166 [ + + ][ - + ]: 232 : if (mmr_ext && !n_locators_new) {
167 : 0 : vteprec_mcast_macs_remote_delete(mmr_ext->mmr);
168 [ + + ][ + + ]: 232 : } else if ((mmr_ext && mmr_changed) ||
[ + + ]
169 [ + + ]: 163 : (!mmr_ext && n_locators_new)) {
170 : :
171 : 8 : const struct vteprec_physical_locator_set *ploc_set =
172 : : vteprec_physical_locator_set_insert(vtep_idl_txn);
173 : :
174 : 8 : vtep_create_mmr(vtep_idl_txn, "unknown-dst", vtep_ls, ploc_set);
175 : :
176 : 8 : vteprec_physical_locator_set_set_locators(ploc_set, locators,
177 : : n_locators_new);
178 : : }
179 : 232 : free(locators);
180 : 232 : }
181 : :
182 : : /* Updates the vtep Logical_Switch table entries' tunnel keys based
183 : : * on the port bindings. */
184 : : static void
185 : 216 : vtep_lswitch_run(struct shash *vtep_pbs, struct sset *vtep_pswitches,
186 : : struct shash *vtep_lswitches)
187 : : {
188 : 216 : struct sset used_ls = SSET_INITIALIZER(&used_ls);
189 : : struct shash_node *node;
190 : :
191 : : /* Collects the logical switch bindings from port binding entries.
192 : : * Since the binding module has already guaranteed that each vtep
193 : : * logical switch is bound only to one ovn-sb logical datapath,
194 : : * we can just iterate and assign tunnel key to vtep logical switch. */
195 [ + + ][ - + ]: 367 : SHASH_FOR_EACH (node, vtep_pbs) {
196 : 151 : const struct sbrec_port_binding *port_binding_rec = node->data;
197 : 151 : const char *pswitch_name = smap_get(&port_binding_rec->options,
198 : : "vtep-physical-switch");
199 : 151 : const char *lswitch_name = smap_get(&port_binding_rec->options,
200 : : "vtep-logical-switch");
201 : : const struct vteprec_logical_switch *vtep_ls;
202 : :
203 : : /* If 'port_binding_rec->chassis' exists then 'pswitch_name'
204 : : * and 'lswitch_name' must also exist. */
205 [ + - ][ - + ]: 151 : if (!pswitch_name || !lswitch_name) {
206 : : /* This could only happen when someone directly modifies the
207 : : * database, (e.g. using ovn-sbctl). */
208 [ # # ]: 0 : VLOG_ERR("logical port (%s) with no 'options:vtep-physical-"
209 : : "switch' or 'options:vtep-logical-switch' specified "
210 : : "is bound to chassis (%s).",
211 : : port_binding_rec->logical_port,
212 : : port_binding_rec->chassis->name);
213 : 0 : continue;
214 : : }
215 : 151 : vtep_ls = shash_find_data(vtep_lswitches, lswitch_name);
216 : : /* Also checks 'pswitch_name' since the same 'lswitch_name' could
217 : : * exist in multiple vtep database instances and be bound to different
218 : : * ovn logical networks. */
219 [ + - ][ + + ]: 151 : if (vtep_ls && sset_find(vtep_pswitches, pswitch_name)) {
220 : : int64_t tnl_key;
221 : :
222 [ + + ]: 150 : if (sset_find(&used_ls, lswitch_name)) {
223 : 5 : continue;
224 : : }
225 : :
226 : 145 : tnl_key = port_binding_rec->datapath->tunnel_key;
227 [ + - ]: 145 : if (vtep_ls->n_tunnel_key
228 [ + + ]: 145 : && vtep_ls->tunnel_key[0] != tnl_key) {
229 [ - + ]: 11 : VLOG_DBG("set vtep logical switch (%s) tunnel key from "
230 : : "(%"PRId64") to (%"PRId64")", vtep_ls->name,
231 : : vtep_ls->tunnel_key[0], tnl_key);
232 : : }
233 : 145 : vteprec_logical_switch_set_tunnel_key(vtep_ls, &tnl_key, 1);
234 : :
235 : : /* OVN is expected to always use source node replication mode,
236 : : * hence the replication mode is hard-coded for each logical
237 : : * switch in the context of ovn-controller-vtep. */
238 : 145 : vteprec_logical_switch_set_replication_mode(vtep_ls, "source_node");
239 : 145 : sset_add(&used_ls, lswitch_name);
240 : : }
241 : : }
242 : : /* Resets the tunnel keys for unused vtep logical switches. */
243 [ + + ][ - + ]: 448 : SHASH_FOR_EACH (node, vtep_lswitches) {
244 [ + + ]: 232 : if (!sset_find(&used_ls, node->name)) {
245 : 87 : int64_t tnl_key = 0;
246 : 87 : vteprec_logical_switch_set_tunnel_key(node->data, &tnl_key, 1);
247 : : }
248 : : }
249 : 216 : sset_destroy(&used_ls);
250 : 216 : }
251 : :
252 : : /* Updates the vtep 'Ucast_Macs_Remote' and 'Mcast_Macs_Remote' tables based
253 : : * on non-vtep port bindings. */
254 : : static void
255 : 216 : vtep_macs_run(struct ovsdb_idl_txn *vtep_idl_txn, struct shash *ucast_macs_rmts,
256 : : struct shash *mcast_macs_rmts, struct shash *physical_locators,
257 : : struct shash *vtep_lswitches, struct shash *non_vtep_pbs)
258 : : {
259 : : struct shash_node *node;
260 : : struct hmap ls_map;
261 : :
262 : : /* Maps from ovn logical datapath tunnel key (which is also the vtep
263 : : * logical switch tunnel key) to the corresponding vtep logical switch
264 : : * instance. Also, the shash map 'added_macs' is used for checking
265 : : * duplicated MAC addresses in the same ovn logical datapath. 'mmr_ext'
266 : : * is used to track mmr info per LS that needs creation/update and
267 : : * 'locators_list' collects the new physical locators to be bound for
268 : : * an mmr_ext; 'physical_locators' is used to track existing locators and
269 : : * filter duplicates per logical switch. */
270 : : struct ls_hash_node {
271 : : struct hmap_node hmap_node;
272 : :
273 : : const struct vteprec_logical_switch *vtep_ls;
274 : : struct shash added_macs;
275 : :
276 : : struct ovs_list locators_list;
277 : : struct shash physical_locators;
278 : : struct mmr_hash_node_data *mmr_ext;
279 : : };
280 : :
281 : 216 : hmap_init(&ls_map);
282 [ + + ][ - + ]: 448 : SHASH_FOR_EACH (node, vtep_lswitches) {
283 : 232 : const struct vteprec_logical_switch *vtep_ls = node->data;
284 : : struct ls_hash_node *ls_node;
285 : :
286 [ - + ]: 232 : if (!vtep_ls->n_tunnel_key) {
287 : 0 : continue;
288 : : }
289 : 232 : ls_node = xmalloc(sizeof *ls_node);
290 : 232 : ls_node->vtep_ls = vtep_ls;
291 : 232 : shash_init(&ls_node->added_macs);
292 : 232 : shash_init(&ls_node->physical_locators);
293 : 232 : ovs_list_init(&ls_node->locators_list);
294 : 232 : ls_node->mmr_ext = NULL;
295 : 232 : hmap_insert(&ls_map, &ls_node->hmap_node,
296 : : hash_uint64((uint64_t) vtep_ls->tunnel_key[0]));
297 : : }
298 : :
299 [ + + ][ - + ]: 357 : SHASH_FOR_EACH (node, non_vtep_pbs) {
300 : 141 : const struct sbrec_port_binding *port_binding_rec = node->data;
301 : : const struct sbrec_chassis *chassis_rec;
302 : : struct ls_hash_node *ls_node;
303 : : const char *chassis_ip;
304 : : int64_t tnl_key;
305 : : size_t i;
306 : :
307 : 141 : chassis_rec = port_binding_rec->chassis;
308 [ - + ]: 141 : if (!chassis_rec) {
309 : 0 : continue;
310 : : }
311 : :
312 : 141 : tnl_key = port_binding_rec->datapath->tunnel_key;
313 [ + + ][ - + ]: 141 : HMAP_FOR_EACH_WITH_HASH (ls_node, hmap_node,
314 : : hash_uint64((uint64_t) tnl_key),
315 : : &ls_map) {
316 [ + - ]: 95 : if (ls_node->vtep_ls->tunnel_key[0] == tnl_key) {
317 : 95 : break;
318 : : }
319 : : }
320 : : /* If 'ls_node' is NULL, that means no vtep logical switch is
321 : : * attached to the corresponding ovn logical datapath, so pass.
322 : : */
323 [ + + ]: 141 : if (!ls_node) {
324 : 46 : continue;
325 : : }
326 : :
327 : 95 : chassis_ip = get_chassis_vtep_ip(chassis_rec);
328 : : /* Unreachable chassis, continue. */
329 [ - + ]: 95 : if (!chassis_ip) {
330 : : static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
331 [ # # ]: 0 : VLOG_INFO_RL(&rl, "VTEP tunnel encap on chassis (%s) not found",
332 : : chassis_rec->name);
333 : 0 : continue;
334 : : }
335 : :
336 : 95 : const struct vteprec_physical_locator *pl =
337 : : shash_find_data(physical_locators, chassis_ip);
338 [ + + ]: 95 : if (!pl) {
339 : 5 : pl = create_pl(vtep_idl_txn, chassis_ip);
340 : 5 : shash_add(physical_locators, chassis_ip, pl);
341 : : }
342 : :
343 : 95 : const struct vteprec_physical_locator *ls_pl =
344 : 95 : shash_find_data(&ls_node->physical_locators, chassis_ip);
345 [ + + ]: 95 : if (!ls_pl) {
346 : 92 : struct vtep_rec_physical_locator_list_entry *ploc_entry =
347 : : xmalloc(sizeof *ploc_entry);
348 : 92 : ploc_entry->vteprec_ploc = pl;
349 : 92 : ovs_list_push_back(&ls_node->locators_list,
350 : : &ploc_entry->locators_node);
351 : 92 : shash_add(&ls_node->physical_locators, chassis_ip, pl);
352 : : }
353 : :
354 : 95 : char *mac_tnlkey = xasprintf("%s_%"PRId64, "unknown-dst", tnl_key);
355 : 95 : ls_node->mmr_ext = shash_find_data(mcast_macs_rmts, mac_tnlkey);
356 : :
357 [ + + ][ + - ]: 95 : if (ls_node->mmr_ext &&
358 : 87 : ls_node->mmr_ext->mmr->logical_switch == ls_node->vtep_ls) {
359 : :
360 : : /* Delete the entry from the hash table so the mmr does not get
361 : : * removed from the DB later on during stale checking. */
362 : 87 : shash_find_and_delete(mcast_macs_rmts, mac_tnlkey);
363 : : }
364 : 95 : free(mac_tnlkey);
365 : :
366 [ + + ]: 185 : for (i = 0; i < port_binding_rec->n_mac; i++) {
367 : : const struct vteprec_ucast_macs_remote *umr;
368 : : const struct sbrec_port_binding *conflict;
369 : 90 : char *mac = port_binding_rec->mac[i];
370 : :
371 : : /* Checks for duplicate MAC in the same vtep logical switch. */
372 : 90 : conflict = shash_find_data(&ls_node->added_macs, mac);
373 [ + + ]: 90 : if (conflict) {
374 [ + - ]: 3 : VLOG_WARN("MAC address (%s) has already been known to be "
375 : : "on logical port (%s) in the same logical "
376 : : "datapath, so just ignore this logical port (%s)",
377 : : mac, conflict->logical_port,
378 : : port_binding_rec->logical_port);
379 : 3 : continue;
380 : : }
381 : 87 : shash_add(&ls_node->added_macs, mac, port_binding_rec);
382 : :
383 : 87 : char *mac_ip_tnlkey = xasprintf("%s_%s_%"PRId64, mac, chassis_ip,
384 : : tnl_key);
385 : 87 : umr = shash_find_data(ucast_macs_rmts, mac_ip_tnlkey);
386 : : /* If finds the 'umr' entry for the mac, ip, and tnl_key, deletes
387 : : * the entry from shash so that it is not gargage collected.
388 : : *
389 : : * If not found, creates a new 'umr' entry. */
390 [ + + ][ + - ]: 87 : if (umr && umr->logical_switch == ls_node->vtep_ls) {
391 : 81 : shash_find_and_delete(ucast_macs_rmts, mac_ip_tnlkey);
392 : : } else {
393 : : const struct vteprec_ucast_macs_remote *new_umr;
394 : 6 : new_umr = create_umr(vtep_idl_txn, mac, ls_node->vtep_ls);
395 : 6 : vteprec_ucast_macs_remote_set_locator(new_umr, pl);
396 : : }
397 : 87 : free(mac_ip_tnlkey);
398 : : }
399 : : }
400 : :
401 : : /* Removes all remaining 'umr's, since they do not exist anymore. */
402 [ + + ][ - + ]: 220 : SHASH_FOR_EACH (node, ucast_macs_rmts) {
403 : 4 : vteprec_ucast_macs_remote_delete(node->data);
404 : : }
405 : : struct ls_hash_node *iter, *next;
406 [ + + ][ - + ]: 448 : HMAP_FOR_EACH_SAFE (iter, next, hmap_node, &ls_map) {
[ + + ]
407 : : struct vtep_rec_physical_locator_list_entry *ploc_entry;
408 : 232 : vtep_update_mmr(vtep_idl_txn, &iter->locators_list,
409 : 232 : iter->vtep_ls, iter->mmr_ext);
410 [ + + ]: 324 : LIST_FOR_EACH_POP(ploc_entry, locators_node,
411 : : &iter->locators_list) {
412 : 92 : free(ploc_entry);
413 : : }
414 : 232 : hmap_remove(&ls_map, &iter->hmap_node);
415 : 232 : shash_destroy(&iter->added_macs);
416 : 232 : shash_destroy(&iter->physical_locators);
417 : 232 : free(iter);
418 : : }
419 : 216 : hmap_destroy(&ls_map);
420 : :
421 : : /* Clean stale 'Mcast_Macs_Remote' */
422 : : struct mmr_hash_node_data *mmr_ext;
423 [ + + ][ - + ]: 221 : SHASH_FOR_EACH (node, mcast_macs_rmts) {
424 : 5 : mmr_ext = node->data;
425 : 5 : vteprec_mcast_macs_remote_delete(mmr_ext->mmr);
426 : : }
427 : 216 : }
428 : :
429 : : /* Resets all logical switches' 'tunnel_key' to NULL */
430 : : static bool
431 : 19 : vtep_lswitch_cleanup(struct ovsdb_idl *vtep_idl)
432 : : {
433 : : const struct vteprec_logical_switch *vtep_ls;
434 : 19 : bool done = true;
435 : :
436 [ + + ]: 45 : VTEPREC_LOGICAL_SWITCH_FOR_EACH (vtep_ls, vtep_idl) {
437 [ + + ]: 26 : if (vtep_ls->n_tunnel_key) {
438 : 10 : vteprec_logical_switch_set_tunnel_key(vtep_ls, NULL, 0);
439 : 10 : done = false;
440 : : }
441 : : }
442 : :
443 : 19 : return done;
444 : : }
445 : :
446 : : /* Removes all entries in the 'Ucast_Macs_Remote' table in the vtep database.
447 : : * Returns true when all done (i.e. no entry to remove). */
448 : : static bool
449 : 19 : vtep_ucast_macs_cleanup(struct ovsdb_idl *vtep_idl)
450 : : {
451 : : const struct vteprec_ucast_macs_remote *umr;
452 : :
453 [ + + ]: 19 : VTEPREC_UCAST_MACS_REMOTE_FOR_EACH (umr, vtep_idl) {
454 : 2 : vteprec_ucast_macs_remote_delete(umr);
455 : 2 : return false;
456 : : }
457 : :
458 : 17 : return true;
459 : : }
460 : :
461 : : /* Removes all entries in the 'Mcast_Macs_Remote' table in vtep database.
462 : : * Returns true when all done (i.e. no entry to remove). */
463 : : static bool
464 : 19 : vtep_mcast_macs_cleanup(struct ovsdb_idl *vtep_idl)
465 : : {
466 : : const struct vteprec_mcast_macs_remote *mmr;
467 : :
468 [ + + ]: 19 : VTEPREC_MCAST_MACS_REMOTE_FOR_EACH (mmr, vtep_idl) {
469 : 3 : vteprec_mcast_macs_remote_delete(mmr);
470 : 3 : return false;
471 : : }
472 : :
473 : 16 : return true;
474 : : }
475 : :
476 : : /* Updates vtep logical switch tunnel keys. */
477 : : void
478 : 269 : vtep_run(struct controller_vtep_ctx *ctx)
479 : : {
480 [ + + ]: 269 : if (!ctx->vtep_idl_txn) {
481 : 53 : return;
482 : : }
483 : :
484 : 216 : struct sset vtep_pswitches = SSET_INITIALIZER(&vtep_pswitches);
485 : 216 : struct shash vtep_lswitches = SHASH_INITIALIZER(&vtep_lswitches);
486 : 216 : struct shash ucast_macs_rmts = SHASH_INITIALIZER(&ucast_macs_rmts);
487 : 216 : struct shash mcast_macs_rmts = SHASH_INITIALIZER(&mcast_macs_rmts);
488 : 216 : struct shash physical_locators = SHASH_INITIALIZER(&physical_locators);
489 : 216 : struct shash vtep_pbs = SHASH_INITIALIZER(&vtep_pbs);
490 : 216 : struct shash non_vtep_pbs = SHASH_INITIALIZER(&non_vtep_pbs);
491 : : const struct vteprec_physical_switch *vtep_ps;
492 : : const struct vteprec_logical_switch *vtep_ls;
493 : : const struct vteprec_ucast_macs_remote *umr;
494 : : const struct sbrec_port_binding *port_binding_rec;
495 : : const struct vteprec_mcast_macs_remote *mmr;
496 : : struct shash_node *node;
497 : :
498 : : /* Collects 'Physical_Switch's. */
499 [ + + ]: 449 : VTEPREC_PHYSICAL_SWITCH_FOR_EACH (vtep_ps, ctx->vtep_idl) {
500 : 233 : sset_add(&vtep_pswitches, vtep_ps->name);
501 : : }
502 : :
503 : : /* Collects 'Logical_Switch's. */
504 [ + + ]: 448 : VTEPREC_LOGICAL_SWITCH_FOR_EACH (vtep_ls, ctx->vtep_idl) {
505 : 232 : shash_add(&vtep_lswitches, vtep_ls->name, vtep_ls);
506 : : }
507 : :
508 : : /* Collects 'Ucast_Macs_Remote's. */
509 [ + + ]: 301 : VTEPREC_UCAST_MACS_REMOTE_FOR_EACH (umr, ctx->vtep_idl) {
510 : 85 : char *mac_ip_tnlkey =
511 [ + - ][ + - ]: 170 : xasprintf("%s_%s_%"PRId64, umr->MAC,
512 : 170 : umr->locator ? umr->locator->dst_ip : "",
513 [ + - ]: 85 : umr->logical_switch && umr->logical_switch->n_tunnel_key
514 : 85 : ? umr->logical_switch->tunnel_key[0] : INT64_MAX);
515 : :
516 : 85 : shash_add(&ucast_macs_rmts, mac_ip_tnlkey, umr);
517 : 85 : free(mac_ip_tnlkey);
518 : : }
519 : :
520 : : /* Collects 'Mcast_Macs_Remote's. */
521 [ + + ]: 308 : VTEPREC_MCAST_MACS_REMOTE_FOR_EACH (mmr, ctx->vtep_idl) {
522 : 92 : struct mmr_hash_node_data *mmr_ext = xmalloc(sizeof *mmr_ext);;
523 : 92 : char *mac_tnlkey =
524 [ + - ]: 184 : xasprintf("%s_%"PRId64, mmr->MAC,
525 [ + - ]: 92 : mmr->logical_switch && mmr->logical_switch->n_tunnel_key
526 : 92 : ? mmr->logical_switch->tunnel_key[0] : INT64_MAX);
527 : :
528 : 92 : shash_add(&mcast_macs_rmts, mac_tnlkey, mmr_ext);
529 : 92 : mmr_ext->mmr = mmr;
530 : :
531 : 92 : shash_init(&mmr_ext->physical_locators);
532 [ + + ]: 219 : for (size_t i = 0; i < mmr->locator_set->n_locators; i++) {
533 : 127 : shash_add(&mmr_ext->physical_locators,
534 : 127 : mmr->locator_set->locators[i]->dst_ip,
535 : 127 : mmr->locator_set->locators[i]);
536 : : }
537 : :
538 : 92 : free(mac_tnlkey);
539 : : }
540 : :
541 : : /* Collects 'Physical_Locator's. */
542 : : const struct vteprec_physical_locator *pl;
543 [ + + ]: 417 : VTEPREC_PHYSICAL_LOCATOR_FOR_EACH (pl, ctx->vtep_idl) {
544 : 201 : shash_add(&physical_locators, pl->dst_ip, pl);
545 : : }
546 : :
547 : : /* Collects and classifies 'Port_Binding's. */
548 [ + + ]: 601 : SBREC_PORT_BINDING_FOR_EACH(port_binding_rec, ctx->ovnsb_idl) {
549 : 385 : struct shash *target =
550 [ + + ]: 385 : !strcmp(port_binding_rec->type, "vtep") ? &vtep_pbs : &non_vtep_pbs;
551 : :
552 [ + + ]: 385 : if (!port_binding_rec->chassis) {
553 : 93 : continue;
554 : : }
555 : 292 : shash_add(target, port_binding_rec->logical_port, port_binding_rec);
556 : : }
557 : :
558 : 216 : ovsdb_idl_txn_add_comment(ctx->vtep_idl_txn,
559 : : "ovn-controller-vtep: update logical switch "
560 : : "tunnel keys and 'ucast_macs_remote's");
561 : :
562 : 216 : vtep_lswitch_run(&vtep_pbs, &vtep_pswitches, &vtep_lswitches);
563 : 216 : vtep_macs_run(ctx->vtep_idl_txn, &ucast_macs_rmts,
564 : : &mcast_macs_rmts, &physical_locators,
565 : : &vtep_lswitches, &non_vtep_pbs);
566 : :
567 : 216 : sset_destroy(&vtep_pswitches);
568 : 216 : shash_destroy(&vtep_lswitches);
569 : 216 : shash_destroy(&ucast_macs_rmts);
570 [ + + ][ - + ]: 221 : SHASH_FOR_EACH (node, &mcast_macs_rmts) {
571 : 5 : struct mmr_hash_node_data *mmr_ext = node->data;
572 : 5 : shash_destroy(&mmr_ext->physical_locators);
573 : 5 : free(mmr_ext);
574 : : }
575 : 216 : shash_destroy(&mcast_macs_rmts);
576 : 216 : shash_destroy(&physical_locators);
577 : 216 : shash_destroy(&vtep_pbs);
578 : 216 : shash_destroy(&non_vtep_pbs);
579 : : }
580 : :
581 : : /* Cleans up all related entries in vtep. Returns true when done (i.e. there
582 : : * is no change made to 'ctx->vtep_idl'), otherwise returns false. */
583 : : bool
584 : 27 : vtep_cleanup(struct controller_vtep_ctx *ctx)
585 : : {
586 [ + + ]: 27 : if (!ctx->vtep_idl_txn) {
587 : 8 : return false;
588 : : }
589 : :
590 : : bool all_done;
591 : :
592 : 19 : ovsdb_idl_txn_add_comment(ctx->vtep_idl_txn,
593 : : "ovn-controller-vtep: cleaning up vtep "
594 : : "configuration");
595 : 19 : all_done = vtep_lswitch_cleanup(ctx->vtep_idl);
596 [ + + ][ + + ]: 19 : all_done = vtep_ucast_macs_cleanup(ctx->vtep_idl) && all_done;
597 [ + + ][ + + ]: 19 : all_done = vtep_mcast_macs_cleanup(ctx->vtep_idl) && all_done;
598 : :
599 : 19 : return all_done;
600 : : }
|