LCOV - code coverage report
Current view: top level - ovn/controller-vtep - gateway.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 74 80 92.5 %
Date: 2016-09-14 01:02:56 Functions: 6 6 100.0 %
Branches: 41 56 73.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                 :            : #include "gateway.h"
      18                 :            : 
      19                 :            : #include "lib/poll-loop.h"
      20                 :            : #include "lib/simap.h"
      21                 :            : #include "lib/sset.h"
      22                 :            : #include "lib/util.h"
      23                 :            : #include "openvswitch/vlog.h"
      24                 :            : #include "ovn/lib/ovn-sb-idl.h"
      25                 :            : #include "vtep/vtep-idl.h"
      26                 :            : #include "ovn-controller-vtep.h"
      27                 :            : 
      28                 :         14 : VLOG_DEFINE_THIS_MODULE(gateway);
      29                 :            : 
      30                 :            : /*
      31                 :            :  * Registers the physical switches in vtep to ovnsb as chassis.  For each
      32                 :            :  * physical switch in the vtep database, finds all vtep logical switches that
      33                 :            :  * are associated with the physical switch, and updates the corresponding
      34                 :            :  * chassis's 'vtep_logical_switches' column.
      35                 :            :  *
      36                 :            :  */
      37                 :            : 
      38                 :            : /* Global revalidation sequence number, incremented at each call to
      39                 :            :  * 'revalidate_gateway()'. */
      40                 :            : static unsigned int gw_reval_seq;
      41                 :            : 
      42                 :            : /* Maps all chassis created by the gateway module to their own reval_seq. */
      43                 :            : static struct simap gw_chassis_map = SIMAP_INITIALIZER(&gw_chassis_map);
      44                 :            : 
      45                 :            : /* Creates and returns a new instance of 'struct sbrec_chassis'. */
      46                 :            : static const struct sbrec_chassis *
      47                 :         10 : create_chassis_rec(struct ovsdb_idl_txn *txn, const char *name,
      48                 :            :                    const char *encap_ip)
      49                 :            : {
      50                 :            :     const struct sbrec_chassis *chassis_rec;
      51                 :            :     struct sbrec_encap *encap_rec;
      52                 :            : 
      53         [ +  - ]:         10 :     VLOG_INFO("add Chassis row for VTEP physical switch (%s)", name);
      54                 :            : 
      55                 :         10 :     chassis_rec = sbrec_chassis_insert(txn);
      56                 :         10 :     sbrec_chassis_set_name(chassis_rec, name);
      57                 :         10 :     encap_rec = sbrec_encap_insert(txn);
      58                 :         10 :     sbrec_encap_set_type(encap_rec, OVN_SB_ENCAP_TYPE);
      59                 :         10 :     sbrec_encap_set_ip(encap_rec, encap_ip);
      60                 :         10 :     const struct smap options = SMAP_CONST1(&options, "csum", "false");
      61                 :         10 :     sbrec_encap_set_options(encap_rec, &options);
      62                 :         10 :     sbrec_chassis_set_encaps(chassis_rec, &encap_rec, 1);
      63                 :            : 
      64                 :         10 :     return chassis_rec;
      65                 :            : }
      66                 :            : 
      67                 :            : /* Revalidates chassis in ovnsb against vtep database.  Creates chassis for
      68                 :            :  * new vtep physical switch.  And removes chassis which no longer have
      69                 :            :  * physical switch in vtep.
      70                 :            :  *
      71                 :            :  * xxx: Support multiple tunnel encaps.
      72                 :            :  *
      73                 :            :  * */
      74                 :            : static void
      75                 :        224 : revalidate_gateway(struct controller_vtep_ctx *ctx)
      76                 :            : {
      77                 :            :     const struct vteprec_physical_switch *pswitch;
      78                 :            : 
      79                 :            :     /* Increments the global revalidation sequence number. */
      80                 :        224 :     gw_reval_seq++;
      81                 :            : 
      82                 :        224 :     ovsdb_idl_txn_add_comment(ctx->ovnsb_idl_txn,
      83                 :            :                               "ovn-controller-vtep: updating vtep chassis");
      84                 :            : 
      85         [ +  + ]:        462 :     VTEPREC_PHYSICAL_SWITCH_FOR_EACH (pswitch, ctx->vtep_idl) {
      86                 :            :         const struct sbrec_chassis *chassis_rec;
      87                 :            :         struct simap_node *gw_node;
      88                 :            :         const char *encap_ip;
      89                 :            : 
      90         [ +  + ]:        238 :         encap_ip = pswitch->n_tunnel_ips ? pswitch->tunnel_ips[0] : "";
      91                 :        238 :         gw_node = simap_find(&gw_chassis_map, pswitch->name);
      92                 :        238 :         chassis_rec = get_chassis_by_name(ctx->ovnsb_idl, pswitch->name);
      93         [ +  + ]:        238 :         if (chassis_rec) {
      94 [ -  + ][ #  # ]:        228 :             if (!gw_node &&
      95                 :          0 :                 (strcmp(chassis_rec->encaps[0]->type, OVN_SB_ENCAP_TYPE)
      96         [ #  # ]:          0 :                  || strcmp(chassis_rec->encaps[0]->ip, encap_ip))) {
      97         [ #  # ]:          0 :                 VLOG_WARN("Chassis config changing on startup, make sure "
      98                 :            :                           "multiple chassis are not configured : %s/%s->%s/%s",
      99                 :            :                           chassis_rec->encaps[0]->type,
     100                 :            :                           chassis_rec->encaps[0]->ip,
     101                 :            :                           OVN_SB_ENCAP_TYPE, encap_ip);
     102                 :            :             }
     103                 :            :             /* Updates chassis's encap if anything changed. */
     104         [ -  + ]:        228 :             if (strcmp(chassis_rec->encaps[0]->type, OVN_SB_ENCAP_TYPE)) {
     105         [ #  # ]:          0 :                 VLOG_WARN("Chassis for VTEP physical switch (%s) can only have "
     106                 :            :                           "encap type \"%s\"", pswitch->name, OVN_SB_ENCAP_TYPE);
     107                 :          0 :                 sbrec_encap_set_type(chassis_rec->encaps[0], OVN_SB_ENCAP_TYPE);
     108                 :            :             }
     109         [ +  + ]:        228 :             if (strcmp(chassis_rec->encaps[0]->ip, encap_ip)) {
     110                 :          1 :                 sbrec_encap_set_ip(chassis_rec->encaps[0], encap_ip);
     111                 :            :             }
     112         [ -  + ]:        228 :             if (smap_get_bool(&chassis_rec->encaps[0]->options, "csum", true)) {
     113                 :          0 :                 const struct smap options = SMAP_CONST1(&options, "csum",
     114                 :            :                                                                   "false");
     115                 :        228 :                 sbrec_encap_set_options(chassis_rec->encaps[0], &options);
     116                 :            :             }
     117                 :            :         } else {
     118         [ +  + ]:         10 :             if (gw_node) {
     119         [ +  - ]:          1 :                 VLOG_WARN("Chassis for VTEP physical switch (%s) disappears, "
     120                 :            :                           "maybe deleted by ovn-sbctl, adding it back",
     121                 :            :                           pswitch->name);
     122                 :            :             }
     123                 :            :             /* Creates a new chassis for the VTEP physical switch. */
     124                 :         10 :             create_chassis_rec(ctx->ovnsb_idl_txn, pswitch->name, encap_ip);
     125                 :            :         }
     126                 :            :         /* Updates or creates the simap node for 'pswitch->name'. */
     127                 :        238 :         simap_put(&gw_chassis_map, pswitch->name, gw_reval_seq);
     128                 :            :     }
     129                 :            : 
     130                 :            :     struct simap_node *iter, *next;
     131                 :            :     /* For 'gw_node' in 'gw_chassis_map' whose data is not
     132                 :            :      * 'gw_reval_seq', it means the corresponding physical switch no
     133                 :            :      * longer exist.  So, garbage collects them. */
     134 [ +  + ][ -  + ]:        464 :     SIMAP_FOR_EACH_SAFE (iter, next, &gw_chassis_map) {
                 [ +  + ]
     135         [ +  + ]:        240 :         if (iter->data != gw_reval_seq) {
     136                 :            :             const struct sbrec_chassis *chassis_rec;
     137                 :            : 
     138                 :          2 :             chassis_rec = get_chassis_by_name(ctx->ovnsb_idl, iter->name);
     139         [ +  - ]:          2 :             if (chassis_rec) {
     140                 :          2 :                 sbrec_chassis_delete(chassis_rec);
     141                 :            :             }
     142                 :          2 :             simap_delete(&gw_chassis_map, iter);
     143                 :            :         }
     144                 :            :     }
     145                 :        224 : }
     146                 :            : 
     147                 :            : /* Updates the 'vtep_logical_switches' column in the Chassis table based
     148                 :            :  * on vtep database configuration. */
     149                 :            : static void
     150                 :        224 : update_vtep_logical_switches(struct controller_vtep_ctx *ctx)
     151                 :            : {
     152                 :            :     const struct vteprec_physical_switch *pswitch;
     153                 :            : 
     154                 :        224 :     ovsdb_idl_txn_add_comment(ctx->ovnsb_idl_txn, "ovn-controller-vtep: "
     155                 :            :                               "updating chassis's vtep_logical_switches");
     156                 :            : 
     157         [ +  + ]:        462 :     VTEPREC_PHYSICAL_SWITCH_FOR_EACH (pswitch, ctx->vtep_idl) {
     158                 :        238 :         const struct sbrec_chassis *chassis_rec =
     159                 :        238 :             get_chassis_by_name(ctx->ovnsb_idl, pswitch->name);
     160                 :        238 :         struct sset lswitches = SSET_INITIALIZER(&lswitches);
     161                 :            :         size_t i;
     162                 :            : 
     163         [ +  + ]:        644 :         for (i = 0; i < pswitch->n_ports; i++) {
     164                 :        406 :             const struct vteprec_physical_port *port = pswitch->ports[i];
     165                 :            :             size_t j;
     166                 :            : 
     167         [ +  + ]:        682 :             for (j = 0; j < port->n_vlan_bindings; j++) {
     168                 :            :                 const struct vteprec_logical_switch *vtep_lswitch;
     169                 :            : 
     170                 :        276 :                 vtep_lswitch = port->value_vlan_bindings[j];
     171                 :            :                 /* If not already in 'lswitches', records it. */
     172         [ +  + ]:        276 :                 if (!sset_find(&lswitches, vtep_lswitch->name)) {
     173                 :        230 :                     sset_add(&lswitches, vtep_lswitch->name);
     174                 :            :                 }
     175                 :            :             }
     176                 :            :         }
     177                 :            : 
     178                 :        238 :         const char **ls_arr = sset_array(&lswitches);
     179                 :        238 :         sbrec_chassis_set_vtep_logical_switches(chassis_rec, ls_arr,
     180                 :            :                                                 sset_count(&lswitches));
     181                 :        238 :         free(ls_arr);
     182                 :        238 :         sset_destroy(&lswitches);
     183                 :            :     }
     184                 :        224 : }
     185                 :            : 
     186                 :            : 
     187                 :            : void
     188                 :        269 : gateway_run(struct controller_vtep_ctx *ctx)
     189                 :            : {
     190         [ +  + ]:        269 :     if (!ctx->ovnsb_idl_txn) {
     191                 :         45 :         return;
     192                 :            :     }
     193                 :            : 
     194                 :        224 :     revalidate_gateway(ctx);
     195                 :        224 :     update_vtep_logical_switches(ctx);
     196                 :            : }
     197                 :            : 
     198                 :            : /* Destroys the chassis table entries for vtep physical switches.
     199                 :            :  * Returns true when done (i.e. there is no change made to 'ctx->ovnsb_idl'),
     200                 :            :  * otherwise returns false. */
     201                 :            : bool
     202                 :         27 : gateway_cleanup(struct controller_vtep_ctx *ctx)
     203                 :            : {
     204                 :            :     static bool simap_destroyed = false;
     205                 :            :     const struct vteprec_physical_switch *pswitch;
     206                 :            : 
     207         [ +  + ]:         27 :     if (!ctx->ovnsb_idl_txn) {
     208                 :         13 :         return false;
     209                 :            :     }
     210                 :            : 
     211                 :         14 :     bool all_done = true;
     212                 :         14 :     ovsdb_idl_txn_add_comment(ctx->ovnsb_idl_txn, "ovn-controller-vtep: "
     213                 :            :                               "unregistering vtep chassis");
     214         [ +  + ]:         28 :     VTEPREC_PHYSICAL_SWITCH_FOR_EACH (pswitch, ctx->vtep_idl) {
     215                 :            :         const struct sbrec_chassis *chassis_rec;
     216                 :            : 
     217                 :         14 :         chassis_rec = get_chassis_by_name(ctx->ovnsb_idl, pswitch->name);
     218         [ +  + ]:         14 :         if (!chassis_rec) {
     219                 :          7 :             continue;
     220                 :            :         }
     221                 :          7 :         all_done = false;
     222                 :          7 :         sbrec_chassis_delete(chassis_rec);
     223                 :            :     }
     224         [ +  + ]:         14 :     if (!simap_destroyed) {
     225                 :          7 :         simap_destroy(&gw_chassis_map);
     226                 :          7 :         simap_destroyed = true;
     227                 :            :     }
     228                 :            : 
     229                 :         14 :     return all_done;
     230                 :            : }

Generated by: LCOV version 1.12