LCOV - code coverage report
Current view: top level - ovn/utilities - ovn-sbctl.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 287 390 73.6 %
Date: 2016-09-14 01:02:56 Functions: 24 27 88.9 %
Branches: 109 208 52.4 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright (c) 2015, 2016 Nicira, Inc.
       3                 :            :  *
       4                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
       5                 :            :  * you may not use this file except in compliance with the License.
       6                 :            :  * You may obtain a copy of the License at:
       7                 :            :  *
       8                 :            :  *     http://www.apache.org/licenses/LICENSE-2.0
       9                 :            :  *
      10                 :            :  * Unless required by applicable law or agreed to in writing, software
      11                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
      12                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      13                 :            :  * See the License for the specific language governing permissions and
      14                 :            :  * limitations under the License.
      15                 :            :  */
      16                 :            : 
      17                 :            : #include <config.h>
      18                 :            : 
      19                 :            : #include <ctype.h>
      20                 :            : #include <errno.h>
      21                 :            : #include <float.h>
      22                 :            : #include <getopt.h>
      23                 :            : #include <inttypes.h>
      24                 :            : #include <signal.h>
      25                 :            : #include <stdarg.h>
      26                 :            : #include <stdlib.h>
      27                 :            : #include <string.h>
      28                 :            : #include <unistd.h>
      29                 :            : 
      30                 :            : #include "command-line.h"
      31                 :            : #include "compiler.h"
      32                 :            : #include "db-ctl-base.h"
      33                 :            : #include "dirs.h"
      34                 :            : #include "fatal-signal.h"
      35                 :            : #include "openvswitch/dynamic-string.h"
      36                 :            : #include "openvswitch/json.h"
      37                 :            : #include "openvswitch/shash.h"
      38                 :            : #include "openvswitch/vlog.h"
      39                 :            : #include "ovn/lib/ovn-sb-idl.h"
      40                 :            : #include "ovn/lib/ovn-util.h"
      41                 :            : #include "ovsdb-data.h"
      42                 :            : #include "ovsdb-idl.h"
      43                 :            : #include "poll-loop.h"
      44                 :            : #include "process.h"
      45                 :            : #include "sset.h"
      46                 :            : #include "stream-ssl.h"
      47                 :            : #include "stream.h"
      48                 :            : #include "table.h"
      49                 :            : #include "timeval.h"
      50                 :            : #include "util.h"
      51                 :            : 
      52                 :        362 : VLOG_DEFINE_THIS_MODULE(sbctl);
      53                 :            : 
      54                 :            : struct sbctl_context;
      55                 :            : 
      56                 :            : /* --db: The database server to contact. */
      57                 :            : static const char *db;
      58                 :            : 
      59                 :            : /* --oneline: Write each command's output as a single line? */
      60                 :            : static bool oneline;
      61                 :            : 
      62                 :            : /* --dry-run: Do not commit any changes. */
      63                 :            : static bool dry_run;
      64                 :            : 
      65                 :            : /* --timeout: Time to wait for a connection to 'db'. */
      66                 :            : static int timeout;
      67                 :            : 
      68                 :            : /* Format for table output. */
      69                 :            : static struct table_style table_style = TABLE_STYLE_DEFAULT;
      70                 :            : 
      71                 :            : /* The IDL we're using and the current transaction, if any.
      72                 :            :  * This is for use by sbctl_exit() only, to allow it to clean up.
      73                 :            :  * Other code should use its context arguments. */
      74                 :            : static struct ovsdb_idl *the_idl;
      75                 :            : static struct ovsdb_idl_txn *the_idl_txn;
      76                 :            : OVS_NO_RETURN static void sbctl_exit(int status);
      77                 :            : 
      78                 :            : static void sbctl_cmd_init(void);
      79                 :            : OVS_NO_RETURN static void usage(void);
      80                 :            : static void parse_options(int argc, char *argv[], struct shash *local_options);
      81                 :            : static void run_prerequisites(struct ctl_command[], size_t n_commands,
      82                 :            :                               struct ovsdb_idl *);
      83                 :            : static bool do_sbctl(const char *args, struct ctl_command *, size_t n,
      84                 :            :                      struct ovsdb_idl *);
      85                 :            : 
      86                 :            : int
      87                 :        181 : main(int argc, char *argv[])
      88                 :            : {
      89                 :            :     struct ovsdb_idl *idl;
      90                 :            :     struct ctl_command *commands;
      91                 :            :     struct shash local_options;
      92                 :            :     unsigned int seqno;
      93                 :            :     size_t n_commands;
      94                 :            :     char *args;
      95                 :            : 
      96                 :        181 :     set_program_name(argv[0]);
      97                 :        181 :     fatal_ignore_sigpipe();
      98                 :        181 :     vlog_set_levels(NULL, VLF_CONSOLE, VLL_WARN);
      99                 :        181 :     vlog_set_levels_from_string_assert("reconnect:warn");
     100                 :        181 :     sbrec_init();
     101                 :            : 
     102                 :        181 :     sbctl_cmd_init();
     103                 :            : 
     104                 :            :     /* Log our arguments.  This is often valuable for debugging systems. */
     105                 :        181 :     args = process_escape_args(argv);
     106 [ +  + ][ +  + ]:        181 :     VLOG(ctl_might_write_to_db(argv) ? VLL_INFO : VLL_DBG, "Called as %s", args);
     107                 :            : 
     108                 :            :     /* Parse command line. */
     109                 :        181 :     shash_init(&local_options);
     110                 :        181 :     parse_options(argc, argv, &local_options);
     111                 :        181 :     commands = ctl_parse_commands(argc - optind, argv + optind, &local_options,
     112                 :            :                                   &n_commands);
     113                 :            : 
     114         [ -  + ]:        181 :     if (timeout) {
     115                 :          0 :         time_alarm(timeout);
     116                 :            :     }
     117                 :            : 
     118                 :            :     /* Initialize IDL. */
     119                 :        181 :     idl = the_idl = ovsdb_idl_create(db, &sbrec_idl_class, false, false);
     120                 :        181 :     run_prerequisites(commands, n_commands, idl);
     121                 :            : 
     122                 :            :     /* Execute the commands.
     123                 :            :      *
     124                 :            :      * 'seqno' is the database sequence number for which we last tried to
     125                 :            :      * execute our transaction.  There's no point in trying to commit more than
     126                 :            :      * once for any given sequence number, because if the transaction fails
     127                 :            :      * it's because the database changed and we need to obtain an up-to-date
     128                 :            :      * view of the database before we try the transaction again. */
     129                 :        181 :     seqno = ovsdb_idl_get_seqno(idl);
     130                 :            :     for (;;) {
     131                 :        482 :         ovsdb_idl_run(idl);
     132         [ -  + ]:        482 :         if (!ovsdb_idl_is_alive(idl)) {
     133                 :          0 :             int retval = ovsdb_idl_get_last_error(idl);
     134                 :          0 :             ctl_fatal("%s: database connection failed (%s)",
     135                 :            :                         db, ovs_retval_to_string(retval));
     136                 :            :         }
     137                 :            : 
     138         [ +  + ]:        482 :         if (seqno != ovsdb_idl_get_seqno(idl)) {
     139                 :        181 :             seqno = ovsdb_idl_get_seqno(idl);
     140         [ +  - ]:        181 :             if (do_sbctl(args, commands, n_commands, idl)) {
     141                 :        181 :                 free(args);
     142                 :        181 :                 exit(EXIT_SUCCESS);
     143                 :            :             }
     144                 :            :         }
     145                 :            : 
     146         [ +  - ]:        301 :         if (seqno == ovsdb_idl_get_seqno(idl)) {
     147                 :        301 :             ovsdb_idl_wait(idl);
     148                 :        301 :             poll_block();
     149                 :            :         }
     150                 :        301 :     }
     151                 :            : }
     152                 :            : 
     153                 :            : static void
     154                 :        181 : parse_options(int argc, char *argv[], struct shash *local_options)
     155                 :            : {
     156                 :            :     enum {
     157                 :            :         OPT_DB = UCHAR_MAX + 1,
     158                 :            :         OPT_ONELINE,
     159                 :            :         OPT_NO_SYSLOG,
     160                 :            :         OPT_DRY_RUN,
     161                 :            :         OPT_LOCAL,
     162                 :            :         OPT_COMMANDS,
     163                 :            :         OPT_OPTIONS,
     164                 :            :         VLOG_OPTION_ENUMS,
     165                 :            :         TABLE_OPTION_ENUMS
     166                 :            :     };
     167                 :            :     static const struct option global_long_options[] = {
     168                 :            :         {"db", required_argument, NULL, OPT_DB},
     169                 :            :         {"no-syslog", no_argument, NULL, OPT_NO_SYSLOG},
     170                 :            :         {"dry-run", no_argument, NULL, OPT_DRY_RUN},
     171                 :            :         {"oneline", no_argument, NULL, OPT_ONELINE},
     172                 :            :         {"timeout", required_argument, NULL, 't'},
     173                 :            :         {"help", no_argument, NULL, 'h'},
     174                 :            :         {"commands", no_argument, NULL, OPT_COMMANDS},
     175                 :            :         {"options", no_argument, NULL, OPT_OPTIONS},
     176                 :            :         {"version", no_argument, NULL, 'V'},
     177                 :            :         VLOG_LONG_OPTIONS,
     178                 :            :         STREAM_SSL_LONG_OPTIONS,
     179                 :            :         TABLE_LONG_OPTIONS,
     180                 :            :         {NULL, 0, NULL, 0},
     181                 :            :     };
     182                 :        181 :     const int n_global_long_options = ARRAY_SIZE(global_long_options) - 1;
     183                 :            :     char *tmp, *short_options;
     184                 :            : 
     185                 :            :     struct option *options;
     186                 :            :     size_t allocated_options;
     187                 :            :     size_t n_options;
     188                 :            :     size_t i;
     189                 :            : 
     190                 :        181 :     tmp = ovs_cmdl_long_options_to_short_options(global_long_options);
     191                 :        181 :     short_options = xasprintf("+%s", tmp);
     192                 :        181 :     free(tmp);
     193                 :            : 
     194                 :            :     /* We want to parse both global and command-specific options here, but
     195                 :            :      * getopt_long() isn't too convenient for the job.  We copy our global
     196                 :            :      * options into a dynamic array, then append all of the command-specific
     197                 :            :      * options. */
     198                 :        181 :     options = xmemdup(global_long_options, sizeof global_long_options);
     199                 :        181 :     allocated_options = ARRAY_SIZE(global_long_options);
     200                 :        181 :     n_options = n_global_long_options;
     201                 :        181 :     ctl_add_cmd_options(&options, &n_options, &allocated_options, OPT_LOCAL);
     202                 :        181 :     table_style.format = TF_LIST;
     203                 :            : 
     204                 :            :     for (;;) {
     205                 :            :         int idx;
     206                 :            :         int c;
     207                 :            : 
     208                 :        244 :         c = getopt_long(argc, argv, short_options, options, &idx);
     209         [ +  + ]:        244 :         if (c == -1) {
     210                 :        181 :             break;
     211                 :            :         }
     212                 :            : 
     213   [ -  -  -  -  :         63 :         switch (c) {
          +  -  -  -  -  
          -  -  -  -  -  
          +  +  +  -  -  
             -  -  -  -  
                      - ]
     214                 :            :         case OPT_DB:
     215                 :          0 :             db = optarg;
     216                 :          0 :             break;
     217                 :            : 
     218                 :            :         case OPT_ONELINE:
     219                 :          0 :             oneline = true;
     220                 :          0 :             break;
     221                 :            : 
     222                 :            :         case OPT_NO_SYSLOG:
     223                 :          0 :             vlog_set_levels(&this_module, VLF_SYSLOG, VLL_WARN);
     224                 :          0 :             break;
     225                 :            : 
     226                 :            :         case OPT_DRY_RUN:
     227                 :          0 :             dry_run = true;
     228                 :          0 :             break;
     229                 :            : 
     230                 :            :         case OPT_LOCAL:
     231         [ -  + ]:         33 :             if (shash_find(local_options, options[idx].name)) {
     232                 :          0 :                 ctl_fatal("'%s' option specified multiple times",
     233                 :          0 :                             options[idx].name);
     234                 :            :             }
     235                 :         33 :             shash_add_nocopy(local_options,
     236                 :         33 :                              xasprintf("--%s", options[idx].name),
     237                 :         33 :                              nullable_xstrdup(optarg));
     238                 :         33 :             break;
     239                 :            : 
     240                 :            :         case 'h':
     241                 :          0 :             usage();
     242                 :            : 
     243                 :            :         case OPT_COMMANDS:
     244                 :          0 :             ctl_print_commands();
     245                 :            : 
     246                 :            :         case OPT_OPTIONS:
     247                 :          0 :             ctl_print_options(global_long_options);
     248                 :            : 
     249                 :            :         case 'V':
     250                 :          0 :             ovs_print_version(0, 0);
     251                 :          0 :             printf("DB Schema %s\n", sbrec_get_db_version());
     252                 :          0 :             exit(EXIT_SUCCESS);
     253                 :            : 
     254                 :            :         case 't':
     255                 :          0 :             timeout = strtoul(optarg, NULL, 10);
     256         [ #  # ]:          0 :             if (timeout < 0) {
     257                 :          0 :                 ctl_fatal("value %s on -t or --timeout is invalid", optarg);
     258                 :            :             }
     259                 :          0 :             break;
     260                 :            : 
     261                 :          0 :         VLOG_OPTION_HANDLERS
     262                 :         30 :         TABLE_OPTION_HANDLERS(&table_style)
     263                 :          0 :         STREAM_SSL_OPTION_HANDLERS
     264                 :            : 
     265                 :            :         case '?':
     266                 :          0 :             exit(EXIT_FAILURE);
     267                 :            : 
     268                 :            :         default:
     269                 :          0 :             abort();
     270                 :            :         }
     271                 :         63 :     }
     272                 :        181 :     free(short_options);
     273                 :            : 
     274         [ +  - ]:        181 :     if (!db) {
     275                 :        181 :         db = default_sb_db();
     276                 :            :     }
     277                 :            : 
     278         [ +  + ]:       1086 :     for (i = n_global_long_options; options[i].name; i++) {
     279                 :        905 :         free(CONST_CAST(char *, options[i].name));
     280                 :            :     }
     281                 :        181 :     free(options);
     282                 :        181 : }
     283                 :            : 
     284                 :            : static void
     285                 :          0 : usage(void)
     286                 :            : {
     287                 :          0 :     printf("\
     288                 :            : %s: OVN southbound DB management utility\n\
     289                 :            : \n\
     290                 :            : For debugging and testing only, not for use in production.\n\
     291                 :            : \n\
     292                 :            : usage: %s [OPTIONS] COMMAND [ARG...]\n\
     293                 :            : \n\
     294                 :            : General commands:\n\
     295                 :            :   show                        print overview of database contents\n\
     296                 :            : \n\
     297                 :            : Chassis commands:\n\
     298                 :            :   chassis-add CHASSIS ENCAP-TYPE ENCAP-IP  create a new chassis named\n\
     299                 :            :                                            CHASSIS with ENCAP-TYPE tunnels\n\
     300                 :            :                                            and ENCAP-IP\n\
     301                 :            :   chassis-del CHASSIS         delete CHASSIS and all of its encaps\n\
     302                 :            :                               and gateway_ports\n\
     303                 :            : \n\
     304                 :            : Port binding commands:\n\
     305                 :            :   lsp-bind PORT CHASSIS       bind logical port PORT to CHASSIS\n\
     306                 :            :   lsp-unbind PORT             reset the port binding of logical port PORT\n\
     307                 :            : \n\
     308                 :            : Logical flow commands:\n\
     309                 :            :   lflow-list [DATAPATH]       List logical flows for all or a single datapath\n\
     310                 :            :   dump-flows [DATAPATH]       Alias for lflow-list\n\
     311                 :            : \n\
     312                 :            : %s\
     313                 :            : \n\
     314                 :            : Options:\n\
     315                 :            :   --db=DATABASE               connect to DATABASE\n\
     316                 :            :                               (default: %s)\n\
     317                 :            :   -t, --timeout=SECS          wait at most SECS seconds\n\
     318                 :            :   --dry-run                   do not commit changes to database\n\
     319                 :            :   --oneline                   print exactly one line of output per command\n",
     320                 :            :            program_name, program_name, ctl_get_db_cmd_usage(),
     321                 :            :            default_sb_db());
     322                 :          0 :     vlog_usage();
     323                 :          0 :     printf("\
     324                 :            :   --no-syslog             equivalent to --verbose=sbctl:syslog:warn\n");
     325                 :          0 :     printf("\n\
     326                 :            : Other options:\n\
     327                 :            :   -h, --help                  display this help message\n\
     328                 :            :   -V, --version               display version information\n");
     329                 :          0 :     stream_usage("database", true, true, false);
     330                 :          0 :     exit(EXIT_SUCCESS);
     331                 :            : }
     332                 :            : 
     333                 :            : 
     334                 :            : /* ovs-sbctl specific context.  Inherits the 'struct ctl_context' as base. */
     335                 :            : struct sbctl_context {
     336                 :            :     struct ctl_context base;
     337                 :            : 
     338                 :            :     /* A cache of the contents of the database.
     339                 :            :      *
     340                 :            :      * A command that needs to use any of this information must first call
     341                 :            :      * sbctl_context_populate_cache().  A command that changes anything that
     342                 :            :      * could invalidate the cache must either call
     343                 :            :      * sbctl_context_invalidate_cache() or manually update the cache to
     344                 :            :      * maintain its correctness. */
     345                 :            :     bool cache_valid;
     346                 :            :     /* Maps from chassis name to struct sbctl_chassis. */
     347                 :            :     struct shash chassis;
     348                 :            :     /* Maps from lport name to struct sbctl_port_binding. */
     349                 :            :     struct shash port_bindings;
     350                 :            : };
     351                 :            : 
     352                 :            : /* Casts 'base' into 'struct sbctl_context'. */
     353                 :            : static struct sbctl_context *
     354                 :        420 : sbctl_context_cast(struct ctl_context *base)
     355                 :            : {
     356                 :        420 :     return CONTAINER_OF(base, struct sbctl_context, base);
     357                 :            : }
     358                 :            : 
     359                 :            : struct sbctl_chassis {
     360                 :            :     const struct sbrec_chassis *ch_cfg;
     361                 :            : };
     362                 :            : 
     363                 :            : struct sbctl_port_binding {
     364                 :            :     const struct sbrec_port_binding *bd_cfg;
     365                 :            : };
     366                 :            : 
     367                 :            : static void
     368                 :        378 : sbctl_context_invalidate_cache(struct ctl_context *ctx)
     369                 :            : {
     370                 :        378 :     struct sbctl_context *sbctl_ctx = sbctl_context_cast(ctx);
     371                 :            : 
     372         [ +  + ]:        378 :     if (!sbctl_ctx->cache_valid) {
     373                 :        357 :         return;
     374                 :            :     }
     375                 :         21 :     sbctl_ctx->cache_valid = false;
     376                 :         21 :     shash_destroy_free_data(&sbctl_ctx->chassis);
     377                 :         21 :     shash_destroy_free_data(&sbctl_ctx->port_bindings);
     378                 :            : }
     379                 :            : 
     380                 :            : static void
     381                 :         21 : sbctl_context_populate_cache(struct ctl_context *ctx)
     382                 :            : {
     383                 :         21 :     struct sbctl_context *sbctl_ctx = sbctl_context_cast(ctx);
     384                 :            :     const struct sbrec_chassis *chassis_rec;
     385                 :            :     const struct sbrec_port_binding *port_binding_rec;
     386                 :            :     struct sset chassis, port_bindings;
     387                 :            : 
     388         [ -  + ]:         21 :     if (sbctl_ctx->cache_valid) {
     389                 :            :         /* Cache is already populated. */
     390                 :          0 :         return;
     391                 :            :     }
     392                 :         21 :     sbctl_ctx->cache_valid = true;
     393                 :         21 :     shash_init(&sbctl_ctx->chassis);
     394                 :         21 :     shash_init(&sbctl_ctx->port_bindings);
     395                 :         21 :     sset_init(&chassis);
     396         [ +  + ]:         49 :     SBREC_CHASSIS_FOR_EACH(chassis_rec, ctx->idl) {
     397                 :            :         struct sbctl_chassis *ch;
     398                 :            : 
     399         [ -  + ]:         28 :         if (!sset_add(&chassis, chassis_rec->name)) {
     400         [ #  # ]:          0 :             VLOG_WARN("database contains duplicate chassis name (%s)",
     401                 :            :                       chassis_rec->name);
     402                 :          0 :             continue;
     403                 :            :         }
     404                 :            : 
     405                 :         28 :         ch = xmalloc(sizeof *ch);
     406                 :         28 :         ch->ch_cfg = chassis_rec;
     407                 :         28 :         shash_add(&sbctl_ctx->chassis, chassis_rec->name, ch);
     408                 :            :     }
     409                 :         21 :     sset_destroy(&chassis);
     410                 :            : 
     411                 :         21 :     sset_init(&port_bindings);
     412         [ +  + ]:         49 :     SBREC_PORT_BINDING_FOR_EACH(port_binding_rec, ctx->idl) {
     413                 :            :         struct sbctl_port_binding *bd;
     414                 :            : 
     415         [ -  + ]:         28 :         if (!sset_add(&port_bindings, port_binding_rec->logical_port)) {
     416         [ #  # ]:          0 :             VLOG_WARN("database contains duplicate port binding for logical "
     417                 :            :                       "port (%s)",
     418                 :            :                       port_binding_rec->logical_port);
     419                 :          0 :             continue;
     420                 :            :         }
     421                 :            : 
     422                 :         28 :         bd = xmalloc(sizeof *bd);
     423                 :         28 :         bd->bd_cfg = port_binding_rec;
     424                 :         28 :         shash_add(&sbctl_ctx->port_bindings, port_binding_rec->logical_port,
     425                 :            :                   bd);
     426                 :            :     }
     427                 :         21 :     sset_destroy(&port_bindings);
     428                 :            : }
     429                 :            : 
     430                 :            : static void
     431                 :          9 : check_conflicts(struct sbctl_context *sbctl_ctx, const char *name,
     432                 :            :                 char *msg)
     433                 :            : {
     434         [ -  + ]:          9 :     if (shash_find(&sbctl_ctx->chassis, name)) {
     435                 :          0 :         ctl_fatal("%s because a chassis named %s already exists",
     436                 :            :                     msg, name);
     437                 :            :     }
     438                 :          9 :     free(msg);
     439                 :          9 : }
     440                 :            : 
     441                 :            : static struct sbctl_chassis *
     442                 :         12 : find_chassis(struct sbctl_context *sbctl_ctx, const char *name,
     443                 :            :              bool must_exist)
     444                 :            : {
     445                 :            :     struct sbctl_chassis *sbctl_ch;
     446                 :            : 
     447         [ -  + ]:         12 :     ovs_assert(sbctl_ctx->cache_valid);
     448                 :            : 
     449                 :         12 :     sbctl_ch = shash_find_data(&sbctl_ctx->chassis, name);
     450 [ +  - ][ -  + ]:         12 :     if (must_exist && !sbctl_ch) {
     451                 :          0 :         ctl_fatal("no chassis named %s", name);
     452                 :            :     }
     453                 :            : 
     454                 :         12 :     return sbctl_ch;
     455                 :            : }
     456                 :            : 
     457                 :            : static struct sbctl_port_binding *
     458                 :         10 : find_port_binding(struct sbctl_context *sbctl_ctx, const char *name,
     459                 :            :                   bool must_exist)
     460                 :            : {
     461                 :            :     struct sbctl_port_binding *bd;
     462                 :            : 
     463         [ -  + ]:         10 :     ovs_assert(sbctl_ctx->cache_valid);
     464                 :            : 
     465                 :         10 :     bd = shash_find_data(&sbctl_ctx->port_bindings, name);
     466 [ +  - ][ -  + ]:         10 :     if (must_exist && !bd) {
     467                 :          0 :         ctl_fatal("no port named %s", name);
     468                 :            :     }
     469                 :            : 
     470                 :         10 :     return bd;
     471                 :            : }
     472                 :            : 
     473                 :            : static void
     474                 :         30 : pre_get_info(struct ctl_context *ctx)
     475                 :            : {
     476                 :         30 :     ovsdb_idl_add_column(ctx->idl, &sbrec_chassis_col_name);
     477                 :         30 :     ovsdb_idl_add_column(ctx->idl, &sbrec_chassis_col_encaps);
     478                 :            : 
     479                 :         30 :     ovsdb_idl_add_column(ctx->idl, &sbrec_encap_col_type);
     480                 :         30 :     ovsdb_idl_add_column(ctx->idl, &sbrec_encap_col_ip);
     481                 :            : 
     482                 :         30 :     ovsdb_idl_add_column(ctx->idl, &sbrec_port_binding_col_logical_port);
     483                 :         30 :     ovsdb_idl_add_column(ctx->idl, &sbrec_port_binding_col_chassis);
     484                 :            : 
     485                 :         30 :     ovsdb_idl_add_column(ctx->idl, &sbrec_logical_flow_col_logical_datapath);
     486                 :         30 :     ovsdb_idl_add_column(ctx->idl, &sbrec_logical_flow_col_pipeline);
     487                 :         30 :     ovsdb_idl_add_column(ctx->idl, &sbrec_logical_flow_col_actions);
     488                 :         30 :     ovsdb_idl_add_column(ctx->idl, &sbrec_logical_flow_col_priority);
     489                 :         30 :     ovsdb_idl_add_column(ctx->idl, &sbrec_logical_flow_col_table_id);
     490                 :         30 :     ovsdb_idl_add_column(ctx->idl, &sbrec_logical_flow_col_match);
     491                 :         30 :     ovsdb_idl_add_column(ctx->idl, &sbrec_logical_flow_col_external_ids);
     492                 :            : 
     493                 :         30 :     ovsdb_idl_add_column(ctx->idl, &sbrec_datapath_binding_col_external_ids);
     494                 :         30 : }
     495                 :            : 
     496                 :            : static struct cmd_show_table cmd_show_tables[] = {
     497                 :            :     {&sbrec_table_chassis,
     498                 :            :      &sbrec_chassis_col_name,
     499                 :            :      {&sbrec_chassis_col_hostname,
     500                 :            :       &sbrec_chassis_col_encaps,
     501                 :            :       NULL},
     502                 :            :      {&sbrec_table_port_binding,
     503                 :            :       &sbrec_port_binding_col_logical_port,
     504                 :            :       &sbrec_port_binding_col_chassis}},
     505                 :            : 
     506                 :            :     {&sbrec_table_encap,
     507                 :            :      &sbrec_encap_col_type,
     508                 :            :      {&sbrec_encap_col_ip,
     509                 :            :       &sbrec_encap_col_options,
     510                 :            :       NULL},
     511                 :            :      {NULL, NULL, NULL}},
     512                 :            : 
     513                 :            :     {NULL, NULL, {NULL, NULL, NULL}, {NULL, NULL, NULL}},
     514                 :            : };
     515                 :            : 
     516                 :            : static void
     517                 :         33 : sbctl_init(struct ctl_context *ctx OVS_UNUSED)
     518                 :            : {
     519                 :         33 : }
     520                 :            : 
     521                 :            : static void
     522                 :          9 : cmd_chassis_add(struct ctl_context *ctx)
     523                 :            : {
     524                 :          9 :     struct sbctl_context *sbctl_ctx = sbctl_context_cast(ctx);
     525                 :          9 :     bool may_exist = shash_find(&ctx->options, "--may-exist") != NULL;
     526                 :            :     const char *ch_name, *encap_types, *encap_ip;
     527                 :            : 
     528                 :          9 :     ch_name = ctx->argv[1];
     529                 :          9 :     encap_types = ctx->argv[2];
     530                 :          9 :     encap_ip = ctx->argv[3];
     531                 :            : 
     532                 :          9 :     sbctl_context_populate_cache(ctx);
     533         [ -  + ]:          9 :     if (may_exist) {
     534                 :            :         struct sbctl_chassis *sbctl_ch;
     535                 :            : 
     536                 :          0 :         sbctl_ch = find_chassis(sbctl_ctx, ch_name, false);
     537         [ #  # ]:          0 :         if (sbctl_ch) {
     538                 :          0 :             return;
     539                 :            :         }
     540                 :            :     }
     541                 :          9 :     check_conflicts(sbctl_ctx, ch_name,
     542                 :            :                     xasprintf("cannot create a chassis named %s", ch_name));
     543                 :            : 
     544                 :            :     struct sset encap_set;
     545                 :          9 :     sset_from_delimited_string(&encap_set, encap_types, ",");
     546                 :            : 
     547                 :          9 :     size_t n_encaps = sset_count(&encap_set);
     548                 :          9 :     struct sbrec_encap **encaps = xmalloc(n_encaps * sizeof *encaps);
     549                 :          9 :     const struct smap options = SMAP_CONST1(&options, "csum", "true");
     550                 :            :     const char *encap_type;
     551                 :          9 :     int i = 0;
     552 [ +  - ][ +  + ]:         20 :     SSET_FOR_EACH (encap_type, &encap_set){
                 [ +  + ]
     553                 :         11 :         encaps[i] = sbrec_encap_insert(ctx->txn);
     554                 :            : 
     555                 :         11 :         sbrec_encap_set_type(encaps[i], encap_type);
     556                 :         11 :         sbrec_encap_set_ip(encaps[i], encap_ip);
     557                 :         11 :         sbrec_encap_set_options(encaps[i], &options);
     558                 :         11 :         i++;
     559                 :            :     }
     560                 :          9 :     sset_destroy(&encap_set);
     561                 :            : 
     562                 :          9 :     struct sbrec_chassis *ch = sbrec_chassis_insert(ctx->txn);
     563                 :          9 :     sbrec_chassis_set_name(ch, ch_name);
     564                 :          9 :     sbrec_chassis_set_encaps(ch, encaps, n_encaps);
     565                 :          9 :     free(encaps);
     566                 :            : 
     567                 :          9 :     sbctl_context_invalidate_cache(ctx);
     568                 :            : }
     569                 :            : 
     570                 :            : static void
     571                 :          2 : cmd_chassis_del(struct ctl_context *ctx)
     572                 :            : {
     573                 :          2 :     struct sbctl_context *sbctl_ctx = sbctl_context_cast(ctx);
     574                 :          2 :     bool must_exist = !shash_find(&ctx->options, "--if-exists");
     575                 :            :     struct sbctl_chassis *sbctl_ch;
     576                 :            : 
     577                 :          2 :     sbctl_context_populate_cache(ctx);
     578                 :          2 :     sbctl_ch = find_chassis(sbctl_ctx, ctx->argv[1], must_exist);
     579         [ +  - ]:          2 :     if (sbctl_ch) {
     580         [ +  - ]:          2 :         if (sbctl_ch->ch_cfg) {
     581                 :            :             size_t i;
     582                 :            : 
     583         [ +  + ]:          4 :             for (i = 0; i < sbctl_ch->ch_cfg->n_encaps; i++) {
     584                 :          2 :                 sbrec_encap_delete(sbctl_ch->ch_cfg->encaps[i]);
     585                 :            :             }
     586                 :          2 :             sbrec_chassis_delete(sbctl_ch->ch_cfg);
     587                 :            :         }
     588                 :          2 :         shash_find_and_delete(&sbctl_ctx->chassis, ctx->argv[1]);
     589                 :          2 :         free(sbctl_ch);
     590                 :            :     }
     591                 :          2 : }
     592                 :            : 
     593                 :            : static void
     594                 :         10 : cmd_lsp_bind(struct ctl_context *ctx)
     595                 :            : {
     596                 :         10 :     struct sbctl_context *sbctl_ctx = sbctl_context_cast(ctx);
     597                 :         10 :     bool may_exist = shash_find(&ctx->options, "--may-exist") != NULL;
     598                 :            :     struct sbctl_chassis *sbctl_ch;
     599                 :            :     struct sbctl_port_binding *sbctl_bd;
     600                 :            :     char *lport_name, *ch_name;
     601                 :            : 
     602                 :            :     /* port_binding must exist, chassis must exist! */
     603                 :         10 :     lport_name = ctx->argv[1];
     604                 :         10 :     ch_name = ctx->argv[2];
     605                 :            : 
     606                 :         10 :     sbctl_context_populate_cache(ctx);
     607                 :         10 :     sbctl_bd = find_port_binding(sbctl_ctx, lport_name, true);
     608                 :         10 :     sbctl_ch = find_chassis(sbctl_ctx, ch_name, true);
     609                 :            : 
     610         [ -  + ]:         10 :     if (sbctl_bd->bd_cfg->chassis) {
     611 [ #  # ][ #  # ]:          0 :         if (may_exist && sbctl_bd->bd_cfg->chassis == sbctl_ch->ch_cfg) {
     612                 :          0 :             return;
     613                 :            :         } else {
     614                 :          0 :             ctl_fatal("lport (%s) has already been binded to chassis (%s)",
     615                 :          0 :                       lport_name, sbctl_bd->bd_cfg->chassis->name);
     616                 :            :         }
     617                 :            :     }
     618                 :         10 :     sbrec_port_binding_set_chassis(sbctl_bd->bd_cfg, sbctl_ch->ch_cfg);
     619                 :         10 :     sbctl_context_invalidate_cache(ctx);
     620                 :            : }
     621                 :            : 
     622                 :            : static void
     623                 :          0 : cmd_lsp_unbind(struct ctl_context *ctx)
     624                 :            : {
     625                 :          0 :     struct sbctl_context *sbctl_ctx = sbctl_context_cast(ctx);
     626                 :          0 :     bool must_exist = !shash_find(&ctx->options, "--if-exists");
     627                 :            :     struct sbctl_port_binding *sbctl_bd;
     628                 :            :     char *lport_name;
     629                 :            : 
     630                 :          0 :     lport_name = ctx->argv[1];
     631                 :          0 :     sbctl_context_populate_cache(ctx);
     632                 :          0 :     sbctl_bd = find_port_binding(sbctl_ctx, lport_name, must_exist);
     633         [ #  # ]:          0 :     if (sbctl_bd) {
     634                 :          0 :         sbrec_port_binding_set_chassis(sbctl_bd->bd_cfg, NULL);
     635                 :            :     }
     636                 :          0 : }
     637                 :            : 
     638                 :            : enum {
     639                 :            :     PL_INGRESS,
     640                 :            :     PL_EGRESS,
     641                 :            : };
     642                 :            : 
     643                 :            : /* Help ensure we catch any future pipeline values */
     644                 :            : static int
     645                 :      18812 : pipeline_encode(const char *pl)
     646                 :            : {
     647         [ +  + ]:      18812 :     if (!strcmp(pl, "ingress")) {
     648                 :      14506 :         return PL_INGRESS;
     649         [ +  - ]:       4306 :     } else if (!strcmp(pl, "egress")) {
     650                 :       4306 :         return PL_EGRESS;
     651                 :            :     }
     652                 :            : 
     653                 :          0 :     OVS_NOT_REACHED();
     654                 :            : }
     655                 :            : 
     656                 :            : static int
     657                 :       9406 : lflow_cmp(const void *lf1_, const void *lf2_)
     658                 :            : {
     659                 :       9406 :     const struct sbrec_logical_flow *const *lf1p = lf1_;
     660                 :       9406 :     const struct sbrec_logical_flow *const *lf2p = lf2_;
     661                 :       9406 :     const struct sbrec_logical_flow *lf1 = *lf1p;
     662                 :       9406 :     const struct sbrec_logical_flow *lf2 = *lf2p;
     663                 :            : 
     664                 :       9406 :     int pl1 = pipeline_encode(lf1->pipeline);
     665                 :       9406 :     int pl2 = pipeline_encode(lf2->pipeline);
     666                 :            : 
     667                 :            : #define CMP(expr) \
     668                 :            :     do { \
     669                 :            :         int res; \
     670                 :            :         res = (expr); \
     671                 :            :         if (res) { \
     672                 :            :             return res; \
     673                 :            :         } \
     674                 :            :     } while (0)
     675                 :            : 
     676         [ +  + ]:       9406 :     CMP(uuid_compare_3way(&lf1->logical_datapath->header_.uuid,
     677                 :            :                           &lf2->logical_datapath->header_.uuid));
     678         [ +  + ]:       7131 :     CMP(pl1 - pl2);
     679 [ +  + ][ +  + ]:       6144 :     CMP(lf1->table_id > lf2->table_id ? 1 :
                 [ +  + ]
     680                 :            :             (lf1->table_id < lf2->table_id ? -1 : 0));
     681 [ +  + ][ +  + ]:       2776 :     CMP(lf1->priority > lf2->priority ? -1 :
     682                 :            :             (lf1->priority < lf2->priority ? 1 : 0));
     683         [ +  - ]:       1772 :     CMP(strcmp(lf1->match, lf2->match));
     684                 :            : 
     685                 :            : #undef CMP
     686                 :            : 
     687                 :          0 :     return 0;
     688                 :            : }
     689                 :            : 
     690                 :            : static void
     691                 :          9 : cmd_lflow_list(struct ctl_context *ctx)
     692                 :            : {
     693         [ -  + ]:          9 :     const char *datapath = ctx->argc == 2 ? ctx->argv[1] : NULL;
     694                 :          9 :     struct uuid datapath_uuid = { .parts = { 0, }};
     695                 :            :     const struct sbrec_logical_flow **lflows;
     696                 :            :     const struct sbrec_logical_flow *lflow;
     697                 :          9 :     size_t n_flows = 0, n_capacity = 64;
     698                 :            : 
     699 [ -  + ][ #  # ]:          9 :     if (datapath && !uuid_from_string(&datapath_uuid, datapath)) {
     700         [ #  # ]:          0 :         VLOG_ERR("Invalid format of datapath UUID");
     701                 :          0 :         return;
     702                 :            :     }
     703                 :            : 
     704                 :          9 :     lflows = xmalloc(sizeof *lflows * n_capacity);
     705         [ +  + ]:       1479 :     SBREC_LOGICAL_FLOW_FOR_EACH (lflow, ctx->idl) {
     706         [ +  + ]:       1470 :         if (n_flows == n_capacity) {
     707                 :         13 :             lflows = x2nrealloc(lflows, &n_capacity, sizeof *lflows);
     708                 :            :         }
     709                 :       1470 :         lflows[n_flows] = lflow;
     710                 :       1470 :         n_flows++;
     711                 :            :     }
     712                 :            : 
     713                 :          9 :     qsort(lflows, n_flows, sizeof *lflows, lflow_cmp);
     714                 :            : 
     715                 :          9 :     const char *cur_pipeline = "";
     716                 :            :     size_t i;
     717         [ +  + ]:       1479 :     for (i = 0; i < n_flows; i++) {
     718                 :       1470 :         lflow = lflows[i];
     719 [ -  + ][ #  # ]:       1470 :         if (datapath && !uuid_equals(&datapath_uuid,
     720                 :          0 :                                      &lflow->logical_datapath->header_.uuid)) {
     721                 :          0 :             continue;
     722                 :            :         }
     723         [ +  + ]:       1470 :         if (strcmp(cur_pipeline, lflow->pipeline)) {
     724                 :         52 :             printf("Datapath: \"%s\" ("UUID_FMT")  Pipeline: %s\n",
     725                 :         52 :                    smap_get_def(&lflow->logical_datapath->external_ids,
     726                 :            :                                 "name", ""),
     727                 :        156 :                    UUID_ARGS(&lflow->logical_datapath->header_.uuid),
     728                 :            :                    lflow->pipeline);
     729                 :         52 :             cur_pipeline = lflow->pipeline;
     730                 :            :         }
     731                 :            : 
     732                 :       1470 :         printf("  table=%-2" PRId64 "(%-19s), priority=%-5" PRId64
     733                 :            :                ", match=(%s), action=(%s)\n",
     734                 :            :                lflow->table_id,
     735                 :            :                smap_get_def(&lflow->external_ids, "stage-name", ""),
     736                 :            :                lflow->priority, lflow->match, lflow->actions);
     737                 :            :     }
     738                 :            : 
     739                 :          9 :     free(lflows);
     740                 :            : }
     741                 :            : 
     742                 :            : 
     743                 :            : static const struct ctl_table_class tables[] = {
     744                 :            :     {&sbrec_table_sb_global,
     745                 :            :      {{&sbrec_table_sb_global, NULL, NULL},
     746                 :            :       {NULL, NULL, NULL}}},
     747                 :            : 
     748                 :            :     {&sbrec_table_chassis,
     749                 :            :      {{&sbrec_table_chassis, &sbrec_chassis_col_name, NULL},
     750                 :            :       {NULL, NULL, NULL}}},
     751                 :            : 
     752                 :            :     {&sbrec_table_encap,
     753                 :            :      {{NULL, NULL, NULL},
     754                 :            :       {NULL, NULL, NULL}}},
     755                 :            : 
     756                 :            :     {&sbrec_table_logical_flow,
     757                 :            :      {{&sbrec_table_logical_flow, NULL,
     758                 :            :        &sbrec_logical_flow_col_logical_datapath},
     759                 :            :       {NULL, NULL, NULL}}},
     760                 :            : 
     761                 :            :     {&sbrec_table_multicast_group,
     762                 :            :      {{NULL, NULL, NULL},
     763                 :            :       {NULL, NULL, NULL}}},
     764                 :            : 
     765                 :            :     {&sbrec_table_datapath_binding,
     766                 :            :      {{NULL, NULL, NULL},
     767                 :            :       {NULL, NULL, NULL}}},
     768                 :            : 
     769                 :            :     {&sbrec_table_port_binding,
     770                 :            :      {{&sbrec_table_port_binding, &sbrec_port_binding_col_logical_port, NULL},
     771                 :            :       {NULL, NULL, NULL}}},
     772                 :            : 
     773                 :            :     {&sbrec_table_mac_binding,
     774                 :            :      {{&sbrec_table_mac_binding, &sbrec_mac_binding_col_logical_port, NULL},
     775                 :            :       {NULL, NULL, NULL}}},
     776                 :            : 
     777                 :            :     {&sbrec_table_address_set,
     778                 :            :      {{&sbrec_table_address_set, &sbrec_address_set_col_name, NULL},
     779                 :            :       {NULL, NULL, NULL}}},
     780                 :            : 
     781                 :            :     {NULL, {{NULL, NULL, NULL}, {NULL, NULL, NULL}}}
     782                 :            : };
     783                 :            : 
     784                 :            : 
     785                 :            : static void
     786                 :        192 : sbctl_context_init_command(struct sbctl_context *sbctl_ctx,
     787                 :            :                            struct ctl_command *command)
     788                 :            : {
     789                 :        192 :     ctl_context_init_command(&sbctl_ctx->base, command);
     790                 :        192 : }
     791                 :            : 
     792                 :            : static void
     793                 :        352 : sbctl_context_init(struct sbctl_context *sbctl_ctx,
     794                 :            :                    struct ctl_command *command, struct ovsdb_idl *idl,
     795                 :            :                    struct ovsdb_idl_txn *txn,
     796                 :            :                    struct ovsdb_symbol_table *symtab)
     797                 :            : {
     798                 :        352 :     ctl_context_init(&sbctl_ctx->base, command, idl, txn, symtab,
     799                 :            :                      sbctl_context_invalidate_cache);
     800                 :        352 :     sbctl_ctx->cache_valid = false;
     801                 :        352 : }
     802                 :            : 
     803                 :            : static void
     804                 :        192 : sbctl_context_done_command(struct sbctl_context *sbctl_ctx,
     805                 :            :                            struct ctl_command *command)
     806                 :            : {
     807                 :        192 :     ctl_context_done_command(&sbctl_ctx->base, command);
     808                 :        192 : }
     809                 :            : 
     810                 :            : static void
     811                 :        352 : sbctl_context_done(struct sbctl_context *sbctl_ctx,
     812                 :            :                    struct ctl_command *command)
     813                 :            : {
     814                 :        352 :     ctl_context_done(&sbctl_ctx->base, command);
     815                 :        352 : }
     816                 :            : 
     817                 :            : static void
     818                 :        181 : run_prerequisites(struct ctl_command *commands, size_t n_commands,
     819                 :            :                   struct ovsdb_idl *idl)
     820                 :            : {
     821                 :        181 :     ovsdb_idl_add_table(idl, &sbrec_table_sb_global);
     822                 :            : 
     823         [ +  + ]:        373 :     for (struct ctl_command *c = commands; c < &commands[n_commands]; c++) {
     824         [ +  + ]:        192 :         if (c->syntax->prerequisites) {
     825                 :            :             struct sbctl_context sbctl_ctx;
     826                 :            : 
     827                 :        159 :             ds_init(&c->output);
     828                 :        159 :             c->table = NULL;
     829                 :            : 
     830                 :        159 :             sbctl_context_init(&sbctl_ctx, c, idl, NULL, NULL);
     831                 :        159 :             (c->syntax->prerequisites)(&sbctl_ctx.base);
     832                 :        159 :             sbctl_context_done(&sbctl_ctx, c);
     833                 :            : 
     834         [ -  + ]:        159 :             ovs_assert(!c->output.string);
     835         [ -  + ]:        159 :             ovs_assert(!c->table);
     836                 :            :         }
     837                 :            :     }
     838                 :        181 : }
     839                 :            : 
     840                 :            : static bool
     841                 :        181 : do_sbctl(const char *args, struct ctl_command *commands, size_t n_commands,
     842                 :            :          struct ovsdb_idl *idl)
     843                 :            : {
     844                 :            :     struct ovsdb_idl_txn *txn;
     845                 :            :     enum ovsdb_idl_txn_status status;
     846                 :            :     struct ovsdb_symbol_table *symtab;
     847                 :            :     struct sbctl_context sbctl_ctx;
     848                 :            :     struct ctl_command *c;
     849                 :            :     struct shash_node *node;
     850                 :        181 :     char *error = NULL;
     851                 :            : 
     852                 :        181 :     txn = the_idl_txn = ovsdb_idl_txn_create(idl);
     853         [ -  + ]:        181 :     if (dry_run) {
     854                 :          0 :         ovsdb_idl_txn_set_dry_run(txn);
     855                 :            :     }
     856                 :            : 
     857                 :        181 :     ovsdb_idl_txn_add_comment(txn, "ovs-sbctl: %s", args);
     858                 :            : 
     859                 :        181 :     const struct sbrec_sb_global *sb = sbrec_sb_global_first(idl);
     860         [ +  + ]:        181 :     if (!sb) {
     861                 :            :         /* XXX add verification that table is empty */
     862                 :         44 :         sb = sbrec_sb_global_insert(txn);
     863                 :            :     }
     864                 :            : 
     865                 :        181 :     symtab = ovsdb_symbol_table_create();
     866         [ +  + ]:        373 :     for (c = commands; c < &commands[n_commands]; c++) {
     867                 :        192 :         ds_init(&c->output);
     868                 :        192 :         c->table = NULL;
     869                 :            :     }
     870                 :        181 :     sbctl_context_init(&sbctl_ctx, NULL, idl, txn, symtab);
     871         [ +  + ]:        373 :     for (c = commands; c < &commands[n_commands]; c++) {
     872                 :        192 :         sbctl_context_init_command(&sbctl_ctx, c);
     873         [ +  - ]:        192 :         if (c->syntax->run) {
     874                 :        192 :             (c->syntax->run)(&sbctl_ctx.base);
     875                 :            :         }
     876                 :        192 :         sbctl_context_done_command(&sbctl_ctx, c);
     877                 :            : 
     878         [ -  + ]:        192 :         if (sbctl_ctx.base.try_again) {
     879                 :          0 :             sbctl_context_done(&sbctl_ctx, NULL);
     880                 :          0 :             goto try_again;
     881                 :            :         }
     882                 :            :     }
     883                 :        181 :     sbctl_context_done(&sbctl_ctx, NULL);
     884                 :            : 
     885 [ +  + ][ -  + ]:        186 :     SHASH_FOR_EACH (node, &symtab->sh) {
     886                 :          5 :         struct ovsdb_symbol *symbol = node->data;
     887         [ -  + ]:          5 :         if (!symbol->created) {
     888                 :          0 :             ctl_fatal("row id \"%s\" is referenced but never created (e.g. "
     889                 :            :                       "with \"-- --id=%s create ...\")",
     890                 :            :                       node->name, node->name);
     891                 :            :         }
     892         [ -  + ]:          5 :         if (!symbol->strong_ref) {
     893         [ #  # ]:          0 :             if (!symbol->weak_ref) {
     894         [ #  # ]:          0 :                 VLOG_WARN("row id \"%s\" was created but no reference to it "
     895                 :            :                           "was inserted, so it will not actually appear in "
     896                 :            :                           "the database", node->name);
     897                 :            :             } else {
     898         [ #  # ]:          0 :                 VLOG_WARN("row id \"%s\" was created but only a weak "
     899                 :            :                           "reference to it was inserted, so it will not "
     900                 :            :                           "actually appear in the database", node->name);
     901                 :            :             }
     902                 :            :         }
     903                 :            :     }
     904                 :            : 
     905                 :        181 :     status = ovsdb_idl_txn_commit_block(txn);
     906 [ +  + ][ +  - ]:        181 :     if (status == TXN_UNCHANGED || status == TXN_SUCCESS) {
     907         [ +  + ]:        373 :         for (c = commands; c < &commands[n_commands]; c++) {
     908         [ +  + ]:        192 :             if (c->syntax->postprocess) {
     909                 :         12 :                 sbctl_context_init(&sbctl_ctx, c, idl, txn, symtab);
     910                 :         12 :                 (c->syntax->postprocess)(&sbctl_ctx.base);
     911                 :         12 :                 sbctl_context_done(&sbctl_ctx, c);
     912                 :            :             }
     913                 :            :         }
     914                 :            :     }
     915                 :        181 :     error = xstrdup(ovsdb_idl_txn_get_error(txn));
     916                 :            : 
     917   [ -  -  +  -  :        181 :     switch (status) {
                -  -  - ]
     918                 :            :     case TXN_UNCOMMITTED:
     919                 :            :     case TXN_INCOMPLETE:
     920                 :          0 :         OVS_NOT_REACHED();
     921                 :            : 
     922                 :            :     case TXN_ABORTED:
     923                 :            :         /* Should not happen--we never call ovsdb_idl_txn_abort(). */
     924                 :          0 :         ctl_fatal("transaction aborted");
     925                 :            : 
     926                 :            :     case TXN_UNCHANGED:
     927                 :            :     case TXN_SUCCESS:
     928                 :        181 :         break;
     929                 :            : 
     930                 :            :     case TXN_TRY_AGAIN:
     931                 :          0 :         goto try_again;
     932                 :            : 
     933                 :            :     case TXN_ERROR:
     934                 :          0 :         ctl_fatal("transaction error: %s", error);
     935                 :            : 
     936                 :            :     case TXN_NOT_LOCKED:
     937                 :            :         /* Should not happen--we never call ovsdb_idl_set_lock(). */
     938                 :          0 :         ctl_fatal("database not locked");
     939                 :            : 
     940                 :            :     default:
     941                 :          0 :         OVS_NOT_REACHED();
     942                 :            :     }
     943                 :        181 :     free(error);
     944                 :            : 
     945                 :        181 :     ovsdb_symbol_table_destroy(symtab);
     946                 :            : 
     947         [ +  + ]:        373 :     for (c = commands; c < &commands[n_commands]; c++) {
     948                 :        192 :         struct ds *ds = &c->output;
     949                 :            : 
     950         [ +  + ]:        192 :         if (c->table) {
     951                 :         92 :             table_print(c->table, &table_style);
     952         [ -  + ]:        100 :         } else if (oneline) {
     953                 :            :             size_t j;
     954                 :            : 
     955                 :          0 :             ds_chomp(ds, '\n');
     956         [ #  # ]:          0 :             for (j = 0; j < ds->length; j++) {
     957                 :          0 :                 int ch = ds->string[j];
     958      [ #  #  # ]:          0 :                 switch (ch) {
     959                 :            :                 case '\n':
     960                 :          0 :                     fputs("\\n", stdout);
     961                 :          0 :                     break;
     962                 :            : 
     963                 :            :                 case '\\':
     964                 :          0 :                     fputs("\\\\", stdout);
     965                 :          0 :                     break;
     966                 :            : 
     967                 :            :                 default:
     968                 :          0 :                     putchar(ch);
     969                 :            :                 }
     970                 :            :             }
     971                 :          0 :             putchar('\n');
     972                 :            :         } else {
     973                 :        100 :             fputs(ds_cstr(ds), stdout);
     974                 :            :         }
     975                 :        192 :         ds_destroy(&c->output);
     976                 :        192 :         table_destroy(c->table);
     977                 :        192 :         free(c->table);
     978                 :            : 
     979                 :        192 :         shash_destroy_free_data(&c->options);
     980                 :            :     }
     981                 :        181 :     free(commands);
     982                 :        181 :     ovsdb_idl_txn_destroy(txn);
     983                 :        181 :     ovsdb_idl_destroy(idl);
     984                 :            : 
     985                 :        181 :     return true;
     986                 :            : 
     987                 :            : try_again:
     988                 :            :     /* Our transaction needs to be rerun, or a prerequisite was not met.  Free
     989                 :            :      * resources and return so that the caller can try again. */
     990         [ #  # ]:          0 :     if (txn) {
     991                 :          0 :         ovsdb_idl_txn_abort(txn);
     992                 :          0 :         ovsdb_idl_txn_destroy(txn);
     993                 :          0 :         the_idl_txn = NULL;
     994                 :            :     }
     995                 :          0 :     ovsdb_symbol_table_destroy(symtab);
     996         [ #  # ]:          0 :     for (c = commands; c < &commands[n_commands]; c++) {
     997                 :          0 :         ds_destroy(&c->output);
     998                 :          0 :         table_destroy(c->table);
     999                 :          0 :         free(c->table);
    1000                 :            :     }
    1001                 :          0 :     free(error);
    1002                 :        181 :     return false;
    1003                 :            : }
    1004                 :            : 
    1005                 :            : /* Frees the current transaction and the underlying IDL and then calls
    1006                 :            :  * exit(status).
    1007                 :            :  *
    1008                 :            :  * Freeing the transaction and the IDL is not strictly necessary, but it makes
    1009                 :            :  * for a clean memory leak report from valgrind in the normal case.  That makes
    1010                 :            :  * it easier to notice real memory leaks. */
    1011                 :            : static void
    1012                 :          0 : sbctl_exit(int status)
    1013                 :            : {
    1014         [ #  # ]:          0 :     if (the_idl_txn) {
    1015                 :          0 :         ovsdb_idl_txn_abort(the_idl_txn);
    1016                 :          0 :         ovsdb_idl_txn_destroy(the_idl_txn);
    1017                 :            :     }
    1018                 :          0 :     ovsdb_idl_destroy(the_idl);
    1019                 :          0 :     exit(status);
    1020                 :            : }
    1021                 :            : 
    1022                 :            : static const struct ctl_command_syntax sbctl_commands[] = {
    1023                 :            :     { "init", 0, 0, "", NULL, sbctl_init, NULL, "", RW },
    1024                 :            : 
    1025                 :            :     /* Chassis commands. */
    1026                 :            :     {"chassis-add", 3, 3, "CHASSIS ENCAP-TYPE ENCAP-IP", pre_get_info,
    1027                 :            :      cmd_chassis_add, NULL, "--may-exist", RW},
    1028                 :            :     {"chassis-del", 1, 1, "CHASSIS", pre_get_info, cmd_chassis_del, NULL,
    1029                 :            :      "--if-exists", RW},
    1030                 :            : 
    1031                 :            :     /* Port binding commands. */
    1032                 :            :     {"lsp-bind", 2, 2, "PORT CHASSIS", pre_get_info, cmd_lsp_bind, NULL,
    1033                 :            :      "--may-exist", RW},
    1034                 :            :     {"lsp-unbind", 1, 1, "PORT", pre_get_info, cmd_lsp_unbind, NULL,
    1035                 :            :      "--if-exists", RW},
    1036                 :            : 
    1037                 :            :     /* Logical flow commands */
    1038                 :            :     {"lflow-list", 0, 1, "[DATAPATH]", pre_get_info, cmd_lflow_list, NULL,
    1039                 :            :      "", RO},
    1040                 :            :     {"dump-flows", 0, 1, "[DATAPATH]", pre_get_info, cmd_lflow_list, NULL,
    1041                 :            :      "", RO}, /* Friendly alias for lflow-list */
    1042                 :            : 
    1043                 :            :     /* SSL commands (To Be Added). */
    1044                 :            : 
    1045                 :            :     {NULL, 0, 0, NULL, NULL, NULL, NULL, NULL, RO},
    1046                 :            : };
    1047                 :            : 
    1048                 :            : /* Registers sbctl and common db commands. */
    1049                 :            : static void
    1050                 :        181 : sbctl_cmd_init(void)
    1051                 :            : {
    1052                 :        181 :     ctl_init(tables, cmd_show_tables, sbctl_exit);
    1053                 :        181 :     ctl_register_commands(sbctl_commands);
    1054                 :        181 : }

Generated by: LCOV version 1.12