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