LCOV - code coverage report
Current view: top level - ovn/controller-vtep - vtep.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 230 239 96.2 %
Date: 2016-09-14 01:02:56 Functions: 14 14 100.0 %
Branches: 133 168 79.2 %

           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                 :            : }

Generated by: LCOV version 1.12