LCOV - code coverage report
Current view: top level - ovn/controller - binding.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 96 113 85.0 %
Date: 2016-09-14 01:02:56 Functions: 8 8 100.0 %
Branches: 56 90 62.2 %

           Branch data     Line data    Source code
       1                 :            : /* Copyright (c) 2015, 2016 Nicira, Inc.
       2                 :            :  *
       3                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
       4                 :            :  * you may not use this file except in compliance with the License.
       5                 :            :  * You may obtain a copy of the License at:
       6                 :            :  *
       7                 :            :  *     http://www.apache.org/licenses/LICENSE-2.0
       8                 :            :  *
       9                 :            :  * Unless required by applicable law or agreed to in writing, software
      10                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
      11                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      12                 :            :  * See the License for the specific language governing permissions and
      13                 :            :  * limitations under the License.
      14                 :            :  */
      15                 :            : 
      16                 :            : #include <config.h>
      17                 :            : #include "binding.h"
      18                 :            : #include "lflow.h"
      19                 :            : #include "lport.h"
      20                 :            : 
      21                 :            : #include "lib/bitmap.h"
      22                 :            : #include "lib/poll-loop.h"
      23                 :            : #include "lib/sset.h"
      24                 :            : #include "lib/util.h"
      25                 :            : #include "lib/vswitch-idl.h"
      26                 :            : #include "openvswitch/hmap.h"
      27                 :            : #include "openvswitch/vlog.h"
      28                 :            : #include "ovn/lib/ovn-sb-idl.h"
      29                 :            : #include "ovn-controller.h"
      30                 :            : 
      31                 :         94 : VLOG_DEFINE_THIS_MODULE(binding);
      32                 :            : 
      33                 :            : void
      34                 :         44 : binding_register_ovs_idl(struct ovsdb_idl *ovs_idl)
      35                 :            : {
      36                 :         44 :     ovsdb_idl_add_table(ovs_idl, &ovsrec_table_open_vswitch);
      37                 :         44 :     ovsdb_idl_add_column(ovs_idl, &ovsrec_open_vswitch_col_bridges);
      38                 :            : 
      39                 :         44 :     ovsdb_idl_add_table(ovs_idl, &ovsrec_table_bridge);
      40                 :         44 :     ovsdb_idl_add_column(ovs_idl, &ovsrec_bridge_col_name);
      41                 :         44 :     ovsdb_idl_add_column(ovs_idl, &ovsrec_bridge_col_ports);
      42                 :            : 
      43                 :         44 :     ovsdb_idl_add_table(ovs_idl, &ovsrec_table_port);
      44                 :         44 :     ovsdb_idl_add_column(ovs_idl, &ovsrec_port_col_name);
      45                 :         44 :     ovsdb_idl_add_column(ovs_idl, &ovsrec_port_col_interfaces);
      46                 :            : 
      47                 :         44 :     ovsdb_idl_add_table(ovs_idl, &ovsrec_table_interface);
      48                 :         44 :     ovsdb_idl_add_column(ovs_idl, &ovsrec_interface_col_name);
      49                 :         44 :     ovsdb_idl_add_column(ovs_idl, &ovsrec_interface_col_external_ids);
      50                 :         44 :     ovsdb_idl_add_column(ovs_idl, &ovsrec_interface_col_ingress_policing_rate);
      51                 :         44 :     ovsdb_idl_add_column(ovs_idl,
      52                 :            :                          &ovsrec_interface_col_ingress_policing_burst);
      53                 :         44 : }
      54                 :            : 
      55                 :            : static void
      56                 :       3163 : get_local_iface_ids(const struct ovsrec_bridge *br_int,
      57                 :            :                     struct shash *lport_to_iface,
      58                 :            :                     struct sset *all_lports)
      59                 :            : {
      60                 :            :     int i;
      61                 :            : 
      62         [ +  + ]:      47426 :     for (i = 0; i < br_int->n_ports; i++) {
      63                 :      44263 :         const struct ovsrec_port *port_rec = br_int->ports[i];
      64                 :            :         const char *iface_id;
      65                 :            :         int j;
      66                 :            : 
      67         [ +  + ]:      44263 :         if (!strcmp(port_rec->name, br_int->name)) {
      68                 :       3163 :             continue;
      69                 :            :         }
      70                 :            : 
      71         [ +  + ]:      82200 :         for (j = 0; j < port_rec->n_interfaces; j++) {
      72                 :            :             const struct ovsrec_interface *iface_rec;
      73                 :            : 
      74                 :      41100 :             iface_rec = port_rec->interfaces[j];
      75                 :      41100 :             iface_id = smap_get(&iface_rec->external_ids, "iface-id");
      76         [ +  + ]:      41100 :             if (!iface_id) {
      77                 :      28216 :                 continue;
      78                 :            :             }
      79                 :      12884 :             shash_add(lport_to_iface, iface_id, iface_rec);
      80                 :      12884 :             sset_add(all_lports, iface_id);
      81                 :            :         }
      82                 :            :     }
      83                 :       3163 : }
      84                 :            : 
      85                 :            : static void
      86                 :      13085 : add_local_datapath(struct hmap *local_datapaths,
      87                 :            :         const struct sbrec_port_binding *binding_rec)
      88                 :            : {
      89         [ +  + ]:      13085 :     if (get_local_datapath(local_datapaths,
      90                 :      13085 :                            binding_rec->datapath->tunnel_key)) {
      91                 :       7907 :         return;
      92                 :            :     }
      93                 :            : 
      94                 :       5178 :     struct local_datapath *ld = xzalloc(sizeof *ld);
      95                 :       5178 :     ld->logical_port = xstrdup(binding_rec->logical_port);
      96                 :       5178 :     memcpy(&ld->uuid, &binding_rec->header_.uuid, sizeof ld->uuid);
      97                 :       5178 :     hmap_insert(local_datapaths, &ld->hmap_node,
      98                 :            :                 binding_rec->datapath->tunnel_key);
      99                 :            : }
     100                 :            : 
     101                 :            : static void
     102                 :      12255 : update_qos(const struct ovsrec_interface *iface_rec,
     103                 :            :            const struct sbrec_port_binding *pb)
     104                 :            : {
     105                 :      12255 :     int rate = smap_get_int(&pb->options, "policing_rate", 0);
     106                 :      12255 :     int burst = smap_get_int(&pb->options, "policing_burst", 0);
     107                 :            : 
     108                 :      12255 :     ovsrec_interface_set_ingress_policing_rate(iface_rec, MAX(0, rate));
     109                 :      12255 :     ovsrec_interface_set_ingress_policing_burst(iface_rec, MAX(0, burst));
     110                 :      12255 : }
     111                 :            : 
     112                 :            : static void
     113                 :      62676 : consider_local_datapath(struct controller_ctx *ctx,
     114                 :            :                         const struct sbrec_chassis *chassis_rec,
     115                 :            :                         const struct sbrec_port_binding *binding_rec,
     116                 :            :                         struct hmap *local_datapaths,
     117                 :            :                         struct shash *lport_to_iface,
     118                 :            :                         struct sset *all_lports)
     119                 :            : {
     120                 :      62676 :     const struct ovsrec_interface *iface_rec
     121                 :      62676 :         = shash_find_data(lport_to_iface, binding_rec->logical_port);
     122                 :            : 
     123         [ +  + ]:      62676 :     if (iface_rec
     124         [ +  + ]:      50241 :         || (binding_rec->parent_port && binding_rec->parent_port[0] &&
           [ -  +  #  # ]
     125                 :          0 :             sset_contains(all_lports, binding_rec->parent_port))) {
     126 [ -  + ][ #  # ]:      12435 :         if (binding_rec->parent_port && binding_rec->parent_port[0]) {
     127                 :            :             /* Add child logical port to the set of all local ports. */
     128                 :          0 :             sset_add(all_lports, binding_rec->logical_port);
     129                 :            :         }
     130                 :      12435 :         add_local_datapath(local_datapaths, binding_rec);
     131 [ +  - ][ +  + ]:      12435 :         if (iface_rec && ctx->ovs_idl_txn) {
     132                 :      12255 :             update_qos(iface_rec, binding_rec);
     133                 :            :         }
     134         [ +  + ]:      12435 :         if (binding_rec->chassis == chassis_rec) {
     135                 :      12295 :             return;
     136                 :            :         }
     137         [ +  + ]:        252 :         if (ctx->ovnsb_idl_txn) {
     138         [ -  + ]:        112 :             if (binding_rec->chassis) {
     139         [ #  # ]:          0 :                 VLOG_INFO("Changing chassis for lport %s from %s to %s.",
     140                 :            :                           binding_rec->logical_port,
     141                 :            :                           binding_rec->chassis->name,
     142                 :            :                           chassis_rec->name);
     143                 :            :             } else {
     144         [ +  - ]:        112 :                 VLOG_INFO("Claiming lport %s for this chassis.",
     145                 :            :                           binding_rec->logical_port);
     146                 :            :             }
     147                 :        112 :             sbrec_port_binding_set_chassis(binding_rec, chassis_rec);
     148                 :            :         }
     149         [ -  + ]:      50241 :     } else if (!strcmp(binding_rec->type, "l2gateway")) {
     150                 :          0 :         const char *chassis_id = smap_get(&binding_rec->options,
     151                 :            :                                           "l2gateway-chassis");
     152 [ #  # ][ #  # ]:          0 :         if (!chassis_id || strcmp(chassis_id, chassis_rec->name)) {
     153 [ #  # ][ #  # ]:          0 :             if (binding_rec->chassis == chassis_rec && ctx->ovnsb_idl_txn) {
     154         [ #  # ]:          0 :                 VLOG_INFO("Releasing l2gateway port %s from this chassis.",
     155                 :            :                           binding_rec->logical_port);
     156                 :          0 :                 sbrec_port_binding_set_chassis(binding_rec, NULL);
     157                 :            :             }
     158                 :          0 :             return;
     159                 :            :         }
     160                 :            : 
     161                 :          0 :         sset_add(all_lports, binding_rec->logical_port);
     162                 :          0 :         add_local_datapath(local_datapaths, binding_rec);
     163         [ #  # ]:          0 :         if (binding_rec->chassis == chassis_rec) {
     164                 :          0 :             return;
     165                 :            :         }
     166                 :            : 
     167 [ #  # ][ #  # ]:          0 :         if (!strcmp(chassis_id, chassis_rec->name) && ctx->ovnsb_idl_txn) {
     168         [ #  # ]:          0 :             VLOG_INFO("Claiming l2gateway port %s for this chassis.",
     169                 :            :                       binding_rec->logical_port);
     170                 :          0 :             sbrec_port_binding_set_chassis(binding_rec, chassis_rec);
     171                 :            :         }
     172         [ +  + ]:      50241 :     } else if (!strcmp(binding_rec->type, "l3gateway")) {
     173                 :        928 :         const char *chassis = smap_get(&binding_rec->options,
     174                 :            :                                        "l3gateway-chassis");
     175 [ +  + ][ +  + ]:        928 :         if (!strcmp(chassis, chassis_rec->name) && ctx->ovnsb_idl_txn) {
     176                 :        928 :             add_local_datapath(local_datapaths, binding_rec);
     177                 :            :         }
     178 [ +  - ][ +  + ]:      49313 :     } else if (chassis_rec && binding_rec->chassis == chassis_rec) {
     179         [ +  + ]:         10 :         if (ctx->ovnsb_idl_txn) {
     180         [ +  - ]:          4 :             VLOG_INFO("Releasing lport %s from this chassis.",
     181                 :            :                       binding_rec->logical_port);
     182                 :          4 :             sbrec_port_binding_set_chassis(binding_rec, NULL);
     183                 :          4 :             sset_find_and_delete(all_lports, binding_rec->logical_port);
     184                 :            :         }
     185         [ +  + ]:      49307 :     } else if (!binding_rec->chassis
     186         [ +  + ]:      29650 :                && !strcmp(binding_rec->type, "localnet")) {
     187                 :            :         /* Add all localnet ports to all_lports so that we allocate ct zones
     188                 :            :          * for them. */
     189                 :        716 :         sset_add(all_lports, binding_rec->logical_port);
     190                 :            :     }
     191                 :            : }
     192                 :            : 
     193                 :            : void
     194                 :       3167 : binding_run(struct controller_ctx *ctx, const struct ovsrec_bridge *br_int,
     195                 :            :             const char *chassis_id, struct hmap *local_datapaths,
     196                 :            :             struct sset *all_lports)
     197                 :            : {
     198                 :            :     const struct sbrec_chassis *chassis_rec;
     199                 :            :     const struct sbrec_port_binding *binding_rec;
     200                 :       3167 :     struct shash lport_to_iface = SHASH_INITIALIZER(&lport_to_iface);
     201                 :            : 
     202                 :       3167 :     chassis_rec = get_chassis(ctx->ovnsb_idl, chassis_id);
     203         [ +  + ]:       3167 :     if (!chassis_rec) {
     204                 :          4 :         return;
     205                 :            :     }
     206                 :            : 
     207         [ +  - ]:       3163 :     if (br_int) {
     208                 :       3163 :         get_local_iface_ids(br_int, &lport_to_iface, all_lports);
     209                 :            :     }
     210                 :            : 
     211                 :            :     /* Run through each binding record to see if it is resident on this
     212                 :            :      * chassis and update the binding accordingly.  This includes both
     213                 :            :      * directly connected logical ports and children of those ports. */
     214         [ +  + ]:      65839 :     SBREC_PORT_BINDING_FOR_EACH(binding_rec, ctx->ovnsb_idl) {
     215                 :      62676 :         consider_local_datapath(ctx, chassis_rec, binding_rec,
     216                 :            :                                 local_datapaths, &lport_to_iface,
     217                 :            :                                 all_lports);
     218                 :            :     }
     219                 :            : 
     220                 :       3163 :     shash_destroy(&lport_to_iface);
     221                 :            : }
     222                 :            : 
     223                 :            : /* Returns true if the database is all cleaned up, false if more work is
     224                 :            :  * required. */
     225                 :            : bool
     226                 :        138 : binding_cleanup(struct controller_ctx *ctx, const char *chassis_id)
     227                 :            : {
     228         [ +  + ]:        138 :     if (!ctx->ovnsb_idl_txn) {
     229                 :         44 :         return false;
     230                 :            :     }
     231                 :            : 
     232         [ -  + ]:         94 :     if (!chassis_id) {
     233                 :          0 :         return true;
     234                 :            :     }
     235                 :            : 
     236                 :         94 :     const struct sbrec_chassis *chassis_rec
     237                 :         94 :         = get_chassis(ctx->ovnsb_idl, chassis_id);
     238         [ +  + ]:         94 :     if (!chassis_rec) {
     239                 :         50 :         return true;
     240                 :            :     }
     241                 :            : 
     242                 :         44 :     ovsdb_idl_txn_add_comment(
     243                 :            :         ctx->ovnsb_idl_txn,
     244                 :            :         "ovn-controller: removing all port bindings for '%s'", chassis_id);
     245                 :            : 
     246                 :            :     const struct sbrec_port_binding *binding_rec;
     247                 :         44 :     bool any_changes = false;
     248         [ +  + ]:        458 :     SBREC_PORT_BINDING_FOR_EACH(binding_rec, ctx->ovnsb_idl) {
     249         [ +  + ]:        414 :         if (binding_rec->chassis == chassis_rec) {
     250                 :        128 :             sbrec_port_binding_set_chassis(binding_rec, NULL);
     251                 :        128 :             any_changes = true;
     252                 :            :         }
     253                 :            :     }
     254                 :         44 :     return !any_changes;
     255                 :            : }

Generated by: LCOV version 1.12