LCOV - code coverage report
Current view: top level - lib - vconn.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 423 521 81.2 %
Date: 2016-09-14 01:02:56 Functions: 64 71 90.1 %
Branches: 203 327 62.1 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015 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                 :            : #include "vconn-provider.h"
      19                 :            : #include <errno.h>
      20                 :            : #include <inttypes.h>
      21                 :            : #include <netinet/in.h>
      22                 :            : #include <poll.h>
      23                 :            : #include <stdlib.h>
      24                 :            : #include <string.h>
      25                 :            : #include "coverage.h"
      26                 :            : #include "fatal-signal.h"
      27                 :            : #include "flow.h"
      28                 :            : #include "openflow/nicira-ext.h"
      29                 :            : #include "openflow/openflow.h"
      30                 :            : #include "openvswitch/dynamic-string.h"
      31                 :            : #include "openvswitch/ofp-errors.h"
      32                 :            : #include "openvswitch/ofp-msgs.h"
      33                 :            : #include "openvswitch/ofp-print.h"
      34                 :            : #include "openvswitch/ofp-util.h"
      35                 :            : #include "openvswitch/ofpbuf.h"
      36                 :            : #include "openvswitch/vlog.h"
      37                 :            : #include "packets.h"
      38                 :            : #include "poll-loop.h"
      39                 :            : #include "random.h"
      40                 :            : #include "util.h"
      41                 :            : #include "socket-util.h"
      42                 :            : 
      43                 :      19636 : VLOG_DEFINE_THIS_MODULE(vconn);
      44                 :            : 
      45                 :     133630 : COVERAGE_DEFINE(vconn_open);
      46                 :     576892 : COVERAGE_DEFINE(vconn_received);
      47                 :     431386 : COVERAGE_DEFINE(vconn_sent);
      48                 :            : 
      49                 :            : /* State of an active vconn.*/
      50                 :            : enum vconn_state {
      51                 :            :     /* This is the ordinary progression of states. */
      52                 :            :     VCS_CONNECTING,             /* Underlying vconn is not connected. */
      53                 :            :     VCS_SEND_HELLO,             /* Waiting to send OFPT_HELLO message. */
      54                 :            :     VCS_RECV_HELLO,             /* Waiting to receive OFPT_HELLO message. */
      55                 :            :     VCS_CONNECTED,              /* Connection established. */
      56                 :            : 
      57                 :            :     /* These states are entered only when something goes wrong. */
      58                 :            :     VCS_SEND_ERROR,             /* Sending OFPT_ERROR message. */
      59                 :            :     VCS_DISCONNECTED            /* Connection failed or connection closed. */
      60                 :            : };
      61                 :            : 
      62                 :            : static const struct vconn_class *vconn_classes[] = {
      63                 :            :     &tcp_vconn_class,
      64                 :            :     &unix_vconn_class,
      65                 :            : #ifdef HAVE_OPENSSL
      66                 :            :     &ssl_vconn_class,
      67                 :            : #endif
      68                 :            : };
      69                 :            : 
      70                 :            : static const struct pvconn_class *pvconn_classes[] = {
      71                 :            :     &ptcp_pvconn_class,
      72                 :            :     &punix_pvconn_class,
      73                 :            : #ifdef HAVE_OPENSSL
      74                 :            :     &pssl_pvconn_class,
      75                 :            : #endif
      76                 :            : };
      77                 :            : 
      78                 :            : /* Rate limit for individual OpenFlow messages going over the vconn, output at
      79                 :            :  * DBG level.  This is very high because, if these are enabled, it is because
      80                 :            :  * we really need to see them. */
      81                 :            : static struct vlog_rate_limit ofmsg_rl = VLOG_RATE_LIMIT_INIT(600, 600);
      82                 :            : 
      83                 :            : /* Rate limit for OpenFlow message parse errors.  These always indicate a bug
      84                 :            :  * in the peer and so there's not much point in showing a lot of them. */
      85                 :            : static struct vlog_rate_limit bad_ofmsg_rl = VLOG_RATE_LIMIT_INIT(1, 5);
      86                 :            : 
      87                 :            : static int do_recv(struct vconn *, struct ofpbuf **);
      88                 :            : static int do_send(struct vconn *, struct ofpbuf *);
      89                 :            : 
      90                 :            : /* Check the validity of the vconn class structures. */
      91                 :            : static void
      92                 :       8393 : check_vconn_classes(void)
      93                 :            : {
      94                 :            : #ifndef NDEBUG
      95                 :            :     size_t i;
      96                 :            : 
      97         [ +  + ]:      33572 :     for (i = 0; i < ARRAY_SIZE(vconn_classes); i++) {
      98                 :      25179 :         const struct vconn_class *class = vconn_classes[i];
      99         [ -  + ]:      25179 :         ovs_assert(class->name != NULL);
     100         [ -  + ]:      25179 :         ovs_assert(class->open != NULL);
     101 [ -  + ][ #  # ]:      25179 :         if (class->close || class->recv || class->send
                 [ #  # ]
     102 [ #  # ][ #  # ]:          0 :             || class->run || class->run_wait || class->wait) {
                 [ #  # ]
     103         [ -  + ]:      25179 :             ovs_assert(class->close != NULL);
     104         [ -  + ]:      25179 :             ovs_assert(class->recv != NULL);
     105         [ -  + ]:      25179 :             ovs_assert(class->send != NULL);
     106         [ -  + ]:      25179 :             ovs_assert(class->wait != NULL);
     107                 :            :         } else {
     108                 :            :             /* This class delegates to another one. */
     109                 :            :         }
     110                 :            :     }
     111                 :            : 
     112         [ +  + ]:      33572 :     for (i = 0; i < ARRAY_SIZE(pvconn_classes); i++) {
     113                 :      25179 :         const struct pvconn_class *class = pvconn_classes[i];
     114         [ -  + ]:      25179 :         ovs_assert(class->name != NULL);
     115         [ -  + ]:      25179 :         ovs_assert(class->listen != NULL);
     116 [ -  + ][ #  # ]:      25179 :         if (class->close || class->accept || class->wait) {
                 [ #  # ]
     117         [ -  + ]:      25179 :             ovs_assert(class->close != NULL);
     118         [ -  + ]:      25179 :             ovs_assert(class->accept != NULL);
     119         [ -  + ]:      25179 :             ovs_assert(class->wait != NULL);
     120                 :            :         } else {
     121                 :            :             /* This class delegates to another one. */
     122                 :            :         }
     123                 :            :     }
     124                 :            : #endif
     125                 :       8393 : }
     126                 :            : 
     127                 :            : /* Prints information on active (if 'active') and passive (if 'passive')
     128                 :            :  * connection methods supported by the vconn.  If 'bootstrap' is true, also
     129                 :            :  * advertises options to bootstrap the CA certificate. */
     130                 :            : void
     131                 :          0 : vconn_usage(bool active, bool passive, bool bootstrap OVS_UNUSED)
     132                 :            : {
     133                 :            :     /* Really this should be implemented via callbacks into the vconn
     134                 :            :      * providers, but that seems too heavy-weight to bother with at the
     135                 :            :      * moment. */
     136                 :            : 
     137                 :          0 :     printf("\n");
     138         [ #  # ]:          0 :     if (active) {
     139                 :          0 :         printf("Active OpenFlow connection methods:\n");
     140                 :          0 :         printf("  tcp:IP[:PORT]           "
     141                 :            :                "PORT (default: %d) at remote IP\n", OFP_PORT);
     142                 :            : #ifdef HAVE_OPENSSL
     143                 :          0 :         printf("  ssl:IP[:PORT]           "
     144                 :            :                "SSL PORT (default: %d) at remote IP\n", OFP_PORT);
     145                 :            : #endif
     146                 :          0 :         printf("  unix:FILE               Unix domain socket named FILE\n");
     147                 :            :     }
     148                 :            : 
     149         [ #  # ]:          0 :     if (passive) {
     150                 :          0 :         printf("Passive OpenFlow connection methods:\n");
     151                 :          0 :         printf("  ptcp:[PORT][:IP]        "
     152                 :            :                "listen to TCP PORT (default: %d) on IP\n",
     153                 :            :                OFP_PORT);
     154                 :            : #ifdef HAVE_OPENSSL
     155                 :          0 :         printf("  pssl:[PORT][:IP]        "
     156                 :            :                "listen for SSL on PORT (default: %d) on IP\n",
     157                 :            :                OFP_PORT);
     158                 :            : #endif
     159                 :          0 :         printf("  punix:FILE              "
     160                 :            :                "listen on Unix domain socket FILE\n");
     161                 :            :     }
     162                 :            : 
     163                 :            : #ifdef HAVE_OPENSSL
     164                 :          0 :     printf("PKI configuration (required to use SSL):\n"
     165                 :            :            "  -p, --private-key=FILE  file with private key\n"
     166                 :            :            "  -c, --certificate=FILE  file with certificate for private key\n"
     167                 :            :            "  -C, --ca-cert=FILE      file with peer CA certificate\n");
     168         [ #  # ]:          0 :     if (bootstrap) {
     169                 :          0 :         printf("  --bootstrap-ca-cert=FILE  file with peer CA certificate "
     170                 :            :                "to read or create\n");
     171                 :            :     }
     172                 :            : #endif
     173                 :          0 : }
     174                 :            : 
     175                 :            : /* Given 'name', a connection name in the form "TYPE:ARGS", stores the class
     176                 :            :  * named "TYPE" into '*classp' and returns 0.  Returns EAFNOSUPPORT and stores
     177                 :            :  * a null pointer into '*classp' if 'name' is in the wrong form or if no such
     178                 :            :  * class exists. */
     179                 :            : static int
     180                 :      11603 : vconn_lookup_class(const char *name, const struct vconn_class **classp)
     181                 :            : {
     182                 :            :     size_t prefix_len;
     183                 :            : 
     184                 :      11603 :     prefix_len = strcspn(name, ":");
     185         [ +  - ]:      11603 :     if (name[prefix_len] != '\0') {
     186                 :            :         size_t i;
     187                 :            : 
     188         [ +  + ]:      32602 :         for (i = 0; i < ARRAY_SIZE(vconn_classes); i++) {
     189                 :      27899 :             const struct vconn_class *class = vconn_classes[i];
     190         [ +  + ]:      27899 :             if (strlen(class->name) == prefix_len
     191         [ +  + ]:       6908 :                 && !memcmp(class->name, name, prefix_len)) {
     192                 :       6900 :                 *classp = class;
     193                 :       6900 :                 return 0;
     194                 :            :             }
     195                 :            :         }
     196                 :            :     }
     197                 :            : 
     198                 :       4703 :     *classp = NULL;
     199                 :       4703 :     return EAFNOSUPPORT;
     200                 :            : }
     201                 :            : 
     202                 :            : /* Returns 0 if 'name' is a connection name in the form "TYPE:ARGS" and TYPE is
     203                 :            :  * a supported connection type, otherwise EAFNOSUPPORT.  */
     204                 :            : int
     205                 :       4709 : vconn_verify_name(const char *name)
     206                 :            : {
     207                 :            :     const struct vconn_class *class;
     208                 :       4709 :     return vconn_lookup_class(name, &class);
     209                 :            : }
     210                 :            : 
     211                 :            : /* Attempts to connect to an OpenFlow device.  'name' is a connection name in
     212                 :            :  * the form "TYPE:ARGS", where TYPE is an active vconn class's name and ARGS
     213                 :            :  * are vconn class-specific.
     214                 :            :  *
     215                 :            :  * The vconn will automatically negotiate an OpenFlow protocol version
     216                 :            :  * acceptable to both peers on the connection.  The version negotiated will be
     217                 :            :  * one of those in the 'allowed_versions' bitmap: version 'x' is allowed if
     218                 :            :  * allowed_versions & (1 << x) is nonzero.  If 'allowed_versions' is zero, then
     219                 :            :  * OFPUTIL_DEFAULT_VERSIONS are allowed.
     220                 :            :  *
     221                 :            :  * Returns 0 if successful, otherwise a positive errno value.  If successful,
     222                 :            :  * stores a pointer to the new connection in '*vconnp', otherwise a null
     223                 :            :  * pointer.  */
     224                 :            : int
     225                 :       6894 : vconn_open(const char *name, uint32_t allowed_versions, uint8_t dscp,
     226                 :            :            struct vconn **vconnp)
     227                 :            : {
     228                 :            :     const struct vconn_class *class;
     229                 :            :     struct vconn *vconn;
     230                 :            :     char *suffix_copy;
     231                 :            :     int error;
     232                 :            : 
     233                 :       6894 :     COVERAGE_INC(vconn_open);
     234                 :       6894 :     check_vconn_classes();
     235                 :            : 
     236         [ +  + ]:       6894 :     if (!allowed_versions) {
     237                 :         24 :         allowed_versions = OFPUTIL_DEFAULT_VERSIONS;
     238                 :            :     }
     239                 :            : 
     240                 :            :     /* Look up the class. */
     241                 :       6894 :     error = vconn_lookup_class(name, &class);
     242         [ -  + ]:       6894 :     if (!class) {
     243                 :          0 :         goto error;
     244                 :            :     }
     245                 :            : 
     246                 :            :     /* Call class's "open" function. */
     247                 :       6894 :     suffix_copy = xstrdup(strchr(name, ':') + 1);
     248                 :       6894 :     error = class->open(name, allowed_versions, suffix_copy, &vconn, dscp);
     249                 :       6894 :     free(suffix_copy);
     250         [ +  + ]:       6894 :     if (error) {
     251                 :       3392 :         goto error;
     252                 :            :     }
     253                 :            : 
     254                 :            :     /* Success. */
     255 [ +  + ][ -  + ]:       3502 :     ovs_assert(vconn->state != VCS_CONNECTING || vconn->vclass->connect);
     256                 :       3502 :     *vconnp = vconn;
     257                 :       3502 :     return 0;
     258                 :            : 
     259                 :            : error:
     260                 :       3392 :     *vconnp = NULL;
     261                 :       6894 :     return error;
     262                 :            : }
     263                 :            : 
     264                 :            : /* Allows 'vconn' to perform maintenance activities, such as flushing output
     265                 :            :  * buffers. */
     266                 :            : void
     267                 :     125346 : vconn_run(struct vconn *vconn)
     268                 :            : {
     269 [ +  + ][ +  + ]:     125346 :     if (vconn->state == VCS_CONNECTING ||
     270         [ +  + ]:     121778 :         vconn->state == VCS_SEND_HELLO ||
     271                 :     121778 :         vconn->state == VCS_RECV_HELLO) {
     272                 :       7094 :         vconn_connect(vconn);
     273                 :            :     }
     274                 :            : 
     275         [ +  - ]:     125346 :     if (vconn->vclass->run) {
     276                 :     125346 :         (vconn->vclass->run)(vconn);
     277                 :            :     }
     278                 :     125346 : }
     279                 :            : 
     280                 :            : /* Arranges for the poll loop to wake up when 'vconn' needs to perform
     281                 :            :  * maintenance activities. */
     282                 :            : void
     283                 :     124578 : vconn_run_wait(struct vconn *vconn)
     284                 :            : {
     285 [ +  + ][ +  + ]:     124578 :     if (vconn->state == VCS_CONNECTING ||
     286         [ +  + ]:     121128 :         vconn->state == VCS_SEND_HELLO ||
     287                 :     121128 :         vconn->state == VCS_RECV_HELLO) {
     288                 :       6965 :         vconn_connect_wait(vconn);
     289                 :            :     }
     290                 :            : 
     291         [ +  - ]:     124578 :     if (vconn->vclass->run_wait) {
     292                 :     124578 :         (vconn->vclass->run_wait)(vconn);
     293                 :            :     }
     294                 :     124578 : }
     295                 :            : 
     296                 :            : /* Returns 0 if 'vconn' is healthy (connecting or connected), a positive errno
     297                 :            :  * value if the connection died abnormally (connection failed or aborted), or
     298                 :            :  * EOF if the connection was closed in a normal way. */
     299                 :            : int
     300                 :     110275 : vconn_get_status(const struct vconn *vconn)
     301                 :            : {
     302         [ +  + ]:     110275 :     return vconn->error == EAGAIN ? 0 : vconn->error;
     303                 :            : }
     304                 :            : 
     305                 :            : int
     306                 :          0 : vconn_open_block(const char *name, uint32_t allowed_versions, uint8_t dscp,
     307                 :            :                  struct vconn **vconnp)
     308                 :            : {
     309                 :            :     struct vconn *vconn;
     310                 :            :     int error;
     311                 :            : 
     312                 :          0 :     fatal_signal_run();
     313                 :            : 
     314                 :          0 :     error = vconn_open(name, allowed_versions, dscp, &vconn);
     315         [ #  # ]:          0 :     if (!error) {
     316                 :          0 :         error = vconn_connect_block(vconn);
     317                 :            :     }
     318                 :            : 
     319         [ #  # ]:          0 :     if (error) {
     320                 :          0 :         vconn_close(vconn);
     321                 :          0 :         *vconnp = NULL;
     322                 :            :     } else {
     323                 :          0 :         *vconnp = vconn;
     324                 :            :     }
     325                 :          0 :     return error;
     326                 :            : }
     327                 :            : 
     328                 :            : /* Closes 'vconn'. */
     329                 :            : void
     330                 :      10262 : vconn_close(struct vconn *vconn)
     331                 :            : {
     332         [ +  + ]:      10262 :     if (vconn != NULL) {
     333                 :       6870 :         char *name = vconn->name;
     334                 :       6870 :         (vconn->vclass->close)(vconn);
     335                 :       6870 :         free(name);
     336                 :            :     }
     337                 :      10262 : }
     338                 :            : 
     339                 :            : /* Returns the name of 'vconn', that is, the string passed to vconn_open(). */
     340                 :            : const char *
     341                 :      20707 : vconn_get_name(const struct vconn *vconn)
     342                 :            : {
     343                 :      20707 :     return vconn->name;
     344                 :            : }
     345                 :            : 
     346                 :            : /* Returns the allowed_versions of 'vconn', that is,
     347                 :            :  * the allowed_versions passed to vconn_open(). */
     348                 :            : uint32_t
     349                 :       3419 : vconn_get_allowed_versions(const struct vconn *vconn)
     350                 :            : {
     351                 :       3419 :     return vconn->allowed_versions;
     352                 :            : }
     353                 :            : 
     354                 :            : /* Sets the allowed_versions of 'vconn', overriding
     355                 :            :  * the allowed_versions passed to vconn_open(). */
     356                 :            : void
     357                 :          0 : vconn_set_allowed_versions(struct vconn *vconn, uint32_t allowed_versions)
     358                 :            : {
     359                 :          0 :     vconn->allowed_versions = allowed_versions;
     360                 :          0 : }
     361                 :            : 
     362                 :            : /* Returns the OpenFlow version negotiated with the peer, or -1 if version
     363                 :            :  * negotiation is not yet complete.
     364                 :            :  *
     365                 :            :  * A vconn that has successfully connected (that is, vconn_connect() or
     366                 :            :  * vconn_send() or vconn_recv() has returned 0) always negotiated a version. */
     367                 :            : int
     368                 :      22834 : vconn_get_version(const struct vconn *vconn)
     369                 :            : {
     370         [ +  + ]:      22834 :     return vconn->version ? vconn->version : -1;
     371                 :            : }
     372                 :            : 
     373                 :            : /* By default, a vconn accepts only OpenFlow messages whose version matches the
     374                 :            :  * one negotiated for the connection.  A message received with a different
     375                 :            :  * version is an error that causes the vconn to drop the connection.
     376                 :            :  *
     377                 :            :  * This functions allows 'vconn' to accept messages with any OpenFlow version.
     378                 :            :  * This is useful in the special case where 'vconn' is used as an rconn
     379                 :            :  * "monitor" connection (see rconn_add_monitor()), that is, where 'vconn' is
     380                 :            :  * used as a target for mirroring OpenFlow messages for debugging and
     381                 :            :  * troubleshooting.
     382                 :            :  *
     383                 :            :  * This function should be called after a successful vconn_open() or
     384                 :            :  * pvconn_accept() but before the connection completes, that is, before
     385                 :            :  * vconn_connect() returns success.  Otherwise, messages that arrive on 'vconn'
     386                 :            :  * beforehand with an unexpected version will the vconn to drop the
     387                 :            :  * connection. */
     388                 :            : void
     389                 :          0 : vconn_set_recv_any_version(struct vconn *vconn)
     390                 :            : {
     391                 :          0 :     vconn->recv_any_version = true;
     392                 :          0 : }
     393                 :            : 
     394                 :            : static void
     395                 :         75 : vcs_connecting(struct vconn *vconn)
     396                 :            : {
     397                 :         75 :     int retval = (vconn->vclass->connect)(vconn);
     398         [ -  + ]:         75 :     ovs_assert(retval != EINPROGRESS);
     399         [ +  + ]:         75 :     if (!retval) {
     400                 :          6 :         vconn->state = VCS_SEND_HELLO;
     401         [ +  + ]:         69 :     } else if (retval != EAGAIN) {
     402                 :          2 :         vconn->state = VCS_DISCONNECTED;
     403                 :          2 :         vconn->error = retval;
     404                 :            :     }
     405                 :         75 : }
     406                 :            : 
     407                 :            : static void
     408                 :       6915 : vcs_send_hello(struct vconn *vconn)
     409                 :            : {
     410                 :            :     struct ofpbuf *b;
     411                 :            :     int retval;
     412                 :            : 
     413                 :       6915 :     b = ofputil_encode_hello(vconn->allowed_versions);
     414                 :       6915 :     retval = do_send(vconn, b);
     415         [ +  + ]:       6915 :     if (!retval) {
     416                 :       6913 :         vconn->state = VCS_RECV_HELLO;
     417                 :            :     } else {
     418                 :          2 :         ofpbuf_delete(b);
     419         [ +  - ]:          2 :         if (retval != EAGAIN) {
     420                 :          2 :             vconn->state = VCS_DISCONNECTED;
     421                 :          2 :             vconn->error = retval;
     422                 :            :         }
     423                 :            :     }
     424                 :       6915 : }
     425                 :            : 
     426                 :            : static char *
     427                 :      13798 : version_bitmap_to_string(uint32_t bitmap)
     428                 :            : {
     429                 :            :     struct ds s;
     430                 :            : 
     431                 :      13798 :     ds_init(&s);
     432         [ -  + ]:      13798 :     if (!bitmap) {
     433                 :          0 :         ds_put_cstr(&s, "no versions");
     434         [ +  + ]:      13798 :     } else if (is_pow2(bitmap)) {
     435                 :       6895 :         ds_put_cstr(&s, "version ");
     436                 :       6895 :         ofputil_format_version(&s, leftmost_1bit_idx(bitmap));
     437         [ +  - ]:       6903 :     } else if (is_pow2((bitmap >> 1) + 1)) {
     438                 :       6903 :         ds_put_cstr(&s, "version ");
     439                 :       6903 :         ofputil_format_version(&s, leftmost_1bit_idx(bitmap));
     440                 :       6903 :         ds_put_cstr(&s, " and earlier");
     441                 :            :     } else {
     442                 :          0 :         ds_put_cstr(&s, "versions ");
     443                 :          0 :         ofputil_format_version_bitmap(&s, bitmap);
     444                 :            :     }
     445                 :      13798 :     return ds_steal_cstr(&s);
     446                 :            : }
     447                 :            : 
     448                 :            : static void
     449                 :      13960 : vcs_recv_hello(struct vconn *vconn)
     450                 :            : {
     451                 :            :     struct ofpbuf *b;
     452                 :            :     int retval;
     453                 :            : 
     454                 :      13960 :     retval = do_recv(vconn, &b);
     455         [ +  + ]:      13960 :     if (!retval) {
     456                 :            :         enum ofptype type;
     457                 :            :         enum ofperr error;
     458                 :            : 
     459                 :       6905 :         error = ofptype_decode(&type, b->data);
     460 [ +  + ][ +  + ]:       6905 :         if (!error && type == OFPTYPE_HELLO) {
     461                 :            :             char *peer_s, *local_s;
     462                 :            :             uint32_t common_versions;
     463                 :            : 
     464         [ +  + ]:       6899 :             if (!ofputil_decode_hello(b->data, &vconn->peer_versions)) {
     465                 :          3 :                 struct ds msg = DS_EMPTY_INITIALIZER;
     466                 :          3 :                 ds_put_format(&msg, "%s: unknown data in hello:\n",
     467                 :            :                               vconn->name);
     468                 :          3 :                 ds_put_hex_dump(&msg, b->data, b->size, 0, true);
     469         [ +  - ]:          3 :                 VLOG_WARN_RL(&bad_ofmsg_rl, "%s", ds_cstr(&msg));
     470                 :          3 :                 ds_destroy(&msg);
     471                 :            :             }
     472                 :            : 
     473                 :       6899 :             local_s = version_bitmap_to_string(vconn->allowed_versions);
     474                 :       6899 :             peer_s = version_bitmap_to_string(vconn->peer_versions);
     475                 :            : 
     476                 :       6899 :             common_versions = vconn->peer_versions & vconn->allowed_versions;
     477         [ -  + ]:       6899 :             if (!common_versions) {
     478                 :          0 :                 vconn->version = leftmost_1bit_idx(vconn->peer_versions);
     479         [ #  # ]:          0 :                 VLOG_WARN_RL(&bad_ofmsg_rl,
     480                 :            :                              "%s: version negotiation failed (we support "
     481                 :            :                              "%s, peer supports %s)",
     482                 :            :                              vconn->name, local_s, peer_s);
     483                 :          0 :                 vconn->state = VCS_SEND_ERROR;
     484                 :            :             } else {
     485                 :       6899 :                 vconn->version = leftmost_1bit_idx(common_versions);
     486         [ +  + ]:       6899 :                 VLOG_DBG("%s: negotiated OpenFlow version 0x%02x "
     487                 :            :                          "(we support %s, peer supports %s)", vconn->name,
     488                 :            :                          vconn->version, local_s, peer_s);
     489                 :       6899 :                 vconn->state = VCS_CONNECTED;
     490                 :            :             }
     491                 :            : 
     492                 :       6899 :             free(local_s);
     493                 :       6899 :             free(peer_s);
     494                 :            : 
     495                 :       6899 :             ofpbuf_delete(b);
     496                 :       6899 :             return;
     497                 :            :         } else {
     498                 :          6 :             char *s = ofp_to_string(b->data, b->size, 1);
     499         [ +  - ]:          6 :             VLOG_WARN_RL(&bad_ofmsg_rl,
     500                 :            :                          "%s: received message while expecting hello: %s",
     501                 :            :                          vconn->name, s);
     502                 :          6 :             free(s);
     503                 :          6 :             retval = EPROTO;
     504                 :          6 :             ofpbuf_delete(b);
     505                 :            :         }
     506                 :            :     }
     507                 :            : 
     508         [ +  + ]:       7061 :     if (retval != EAGAIN) {
     509                 :         14 :         vconn->state = VCS_DISCONNECTED;
     510         [ +  + ]:       7061 :         vconn->error = retval == EOF ? ECONNRESET : retval;
     511                 :            :     }
     512                 :            : }
     513                 :            : 
     514                 :            : static void
     515                 :          0 : vcs_send_error(struct vconn *vconn)
     516                 :            : {
     517                 :            :     struct ofpbuf *b;
     518                 :            :     char s[128];
     519                 :            :     int retval;
     520                 :            :     char *local_s, *peer_s;
     521                 :            : 
     522                 :          0 :     local_s = version_bitmap_to_string(vconn->allowed_versions);
     523                 :          0 :     peer_s = version_bitmap_to_string(vconn->peer_versions);
     524                 :          0 :     snprintf(s, sizeof s, "We support %s, you support %s, no common versions.",
     525                 :            :              local_s, peer_s);
     526                 :          0 :     free(peer_s);
     527                 :          0 :     free(local_s);
     528                 :            : 
     529                 :          0 :     b = ofperr_encode_hello(OFPERR_OFPHFC_INCOMPATIBLE, vconn->version, s);
     530                 :          0 :     retval = do_send(vconn, b);
     531         [ #  # ]:          0 :     if (retval) {
     532                 :          0 :         ofpbuf_delete(b);
     533                 :            :     }
     534         [ #  # ]:          0 :     if (retval != EAGAIN) {
     535                 :          0 :         vconn->state = VCS_DISCONNECTED;
     536         [ #  # ]:          0 :         vconn->error = retval ? retval : EPROTO;
     537                 :            :     }
     538                 :          0 : }
     539                 :            : 
     540                 :            : /* Tries to complete the connection on 'vconn'. If 'vconn''s connection is
     541                 :            :  * complete, returns 0 if the connection was successful or a positive errno
     542                 :            :  * value if it failed.  If the connection is still in progress, returns
     543                 :            :  * EAGAIN. */
     544                 :            : int
     545                 :     297027 : vconn_connect(struct vconn *vconn)
     546                 :            : {
     547                 :            :     enum vconn_state last_state;
     548                 :            : 
     549                 :            :     do {
     550                 :     310863 :         last_state = vconn->state;
     551   [ +  +  +  +  :     310863 :         switch (vconn->state) {
                -  +  - ]
     552                 :            :         case VCS_CONNECTING:
     553                 :         75 :             vcs_connecting(vconn);
     554                 :         75 :             break;
     555                 :            : 
     556                 :            :         case VCS_SEND_HELLO:
     557                 :       6915 :             vcs_send_hello(vconn);
     558                 :       6915 :             break;
     559                 :            : 
     560                 :            :         case VCS_RECV_HELLO:
     561                 :      13960 :             vcs_recv_hello(vconn);
     562                 :      13960 :             break;
     563                 :            : 
     564                 :            :         case VCS_CONNECTED:
     565                 :     289883 :             return 0;
     566                 :            : 
     567                 :            :         case VCS_SEND_ERROR:
     568                 :          0 :             vcs_send_error(vconn);
     569                 :          0 :             break;
     570                 :            : 
     571                 :            :         case VCS_DISCONNECTED:
     572                 :         30 :             return vconn->error;
     573                 :            : 
     574                 :            :         default:
     575                 :          0 :             OVS_NOT_REACHED();
     576                 :            :         }
     577         [ +  + ]:      20950 :     } while (vconn->state != last_state);
     578                 :            : 
     579                 :       7114 :     return EAGAIN;
     580                 :            : }
     581                 :            : 
     582                 :            : /* Tries to receive an OpenFlow message from 'vconn'.  If successful, stores
     583                 :            :  * the received message into '*msgp' and returns 0.  The caller is responsible
     584                 :            :  * for destroying the message with ofpbuf_delete().  On failure, returns a
     585                 :            :  * positive errno value and stores a null pointer into '*msgp'.  On normal
     586                 :            :  * connection close, returns EOF.
     587                 :            :  *
     588                 :            :  * vconn_recv will not block waiting for a packet to arrive.  If no packets
     589                 :            :  * have been received, it returns EAGAIN immediately. */
     590                 :            : int
     591                 :     199204 : vconn_recv(struct vconn *vconn, struct ofpbuf **msgp)
     592                 :            : {
     593                 :            :     struct ofpbuf *msg;
     594                 :            :     int retval;
     595                 :            : 
     596                 :     199204 :     retval = vconn_connect(vconn);
     597         [ +  + ]:     199204 :     if (!retval) {
     598                 :     196276 :         retval = do_recv(vconn, &msg);
     599                 :            :     }
     600 [ +  + ][ +  - ]:     199204 :     if (!retval && !vconn->recv_any_version) {
     601                 :      73866 :         const struct ofp_header *oh = msg->data;
     602         [ +  + ]:      73866 :         if (oh->version != vconn->version) {
     603                 :            :             enum ofptype type;
     604                 :            : 
     605         [ +  - ]:          2 :             if (ofptype_decode(&type, msg->data)
     606 [ +  - ][ +  + ]:          2 :                 || (type != OFPTYPE_HELLO &&
     607         [ +  - ]:          1 :                     type != OFPTYPE_ERROR &&
     608         [ +  - ]:          1 :                     type != OFPTYPE_ECHO_REQUEST &&
     609                 :          1 :                     type != OFPTYPE_ECHO_REPLY)) {
     610                 :            :                 struct ofpbuf *reply;
     611                 :            : 
     612         [ +  - ]:          1 :                 VLOG_ERR_RL(&bad_ofmsg_rl, "%s: received OpenFlow version "
     613                 :            :                             "0x%02"PRIx8" != expected %02x",
     614                 :            :                             vconn->name, oh->version, vconn->version);
     615                 :            : 
     616                 :            :                 /* Send a "bad version" reply, if we can. */
     617                 :          1 :                 reply = ofperr_encode_reply(OFPERR_OFPBRC_BAD_VERSION, oh);
     618                 :          1 :                 retval = vconn_send(vconn, reply);
     619         [ -  + ]:          1 :                 if (retval) {
     620         [ #  # ]:          0 :                     VLOG_INFO_RL(&bad_ofmsg_rl,
     621                 :            :                                  "%s: failed to queue error reply (%s)",
     622                 :            :                                  vconn->name, ovs_strerror(retval));
     623                 :          0 :                     ofpbuf_delete(reply);
     624                 :            :                 }
     625                 :            : 
     626                 :            :                 /* Suppress the received message, as if it had not arrived. */
     627                 :          1 :                 retval = EAGAIN;
     628                 :          2 :                 ofpbuf_delete(msg);
     629                 :            :             }
     630                 :            :         }
     631                 :            :     }
     632                 :            : 
     633         [ +  + ]:     199204 :     *msgp = retval ? NULL : msg;
     634                 :     199204 :     return retval;
     635                 :            : }
     636                 :            : 
     637                 :            : static int
     638                 :     210236 : do_recv(struct vconn *vconn, struct ofpbuf **msgp)
     639                 :            : {
     640                 :     210236 :     int retval = (vconn->vclass->recv)(vconn, msgp);
     641         [ +  + ]:     210236 :     if (!retval) {
     642                 :      80771 :         COVERAGE_INC(vconn_received);
     643         [ +  + ]:      80771 :         if (VLOG_IS_DBG_ENABLED()) {
     644                 :      55927 :             char *s = ofp_to_string((*msgp)->data, (*msgp)->size, 1);
     645         [ +  - ]:      55927 :             VLOG_DBG_RL(&ofmsg_rl, "%s: received: %s", vconn->name, s);
     646                 :      55927 :             free(s);
     647                 :            :         }
     648                 :            :     }
     649                 :     210236 :     return retval;
     650                 :            : }
     651                 :            : 
     652                 :            : /* Tries to queue 'msg' for transmission on 'vconn'.  If successful, returns 0,
     653                 :            :  * in which case ownership of 'msg' is transferred to the vconn.  Success does
     654                 :            :  * not guarantee that 'msg' has been or ever will be delivered to the peer,
     655                 :            :  * only that it has been queued for transmission.
     656                 :            :  *
     657                 :            :  * Returns a positive errno value on failure, in which case the caller
     658                 :            :  * retains ownership of 'msg'.
     659                 :            :  *
     660                 :            :  * vconn_send will not block.  If 'msg' cannot be immediately accepted for
     661                 :            :  * transmission, it returns EAGAIN immediately. */
     662                 :            : int
     663                 :      86613 : vconn_send(struct vconn *vconn, struct ofpbuf *msg)
     664                 :            : {
     665                 :      86613 :     int retval = vconn_connect(vconn);
     666         [ +  - ]:      86613 :     if (!retval) {
     667                 :      86613 :         retval = do_send(vconn, msg);
     668                 :            :     }
     669                 :      86613 :     return retval;
     670                 :            : }
     671                 :            : 
     672                 :            : static int
     673                 :      93528 : do_send(struct vconn *vconn, struct ofpbuf *msg)
     674                 :            : {
     675                 :            :     int retval;
     676                 :            : 
     677         [ -  + ]:      93528 :     ovs_assert(msg->size >= sizeof(struct ofp_header));
     678                 :            : 
     679                 :      93528 :     ofpmsg_update_length(msg);
     680         [ +  + ]:      93528 :     if (!VLOG_IS_DBG_ENABLED()) {
     681                 :      56520 :         COVERAGE_INC(vconn_sent);
     682                 :      56520 :         retval = (vconn->vclass->send)(vconn, msg);
     683                 :            :     } else {
     684                 :      37008 :         char *s = ofp_to_string(msg->data, msg->size, 1);
     685                 :      37008 :         retval = (vconn->vclass->send)(vconn, msg);
     686         [ +  + ]:      37008 :         if (retval != EAGAIN) {
     687         [ +  - ]:      24447 :             VLOG_DBG_RL(&ofmsg_rl, "%s: sent (%s): %s",
     688                 :            :                         vconn->name, ovs_strerror(retval), s);
     689                 :            :         }
     690                 :      37008 :         free(s);
     691                 :            :     }
     692                 :      93528 :     return retval;
     693                 :            : }
     694                 :            : 
     695                 :            : /* Same as vconn_connect(), except that it waits until the connection on
     696                 :            :  * 'vconn' completes or fails.  Thus, it will never return EAGAIN. */
     697                 :            : int
     698                 :       3391 : vconn_connect_block(struct vconn *vconn)
     699                 :            : {
     700                 :            :     int error;
     701                 :            : 
     702         [ +  + ]:       3875 :     while ((error = vconn_connect(vconn)) == EAGAIN) {
     703                 :        484 :         vconn_run(vconn);
     704                 :        484 :         vconn_run_wait(vconn);
     705                 :        484 :         vconn_connect_wait(vconn);
     706                 :        484 :         poll_block();
     707                 :            :     }
     708         [ -  + ]:       3391 :     ovs_assert(error != EINPROGRESS);
     709                 :            : 
     710                 :       3391 :     return error;
     711                 :            : }
     712                 :            : 
     713                 :            : /* Same as vconn_send, except that it waits until 'msg' can be transmitted. */
     714                 :            : int
     715                 :      29493 : vconn_send_block(struct vconn *vconn, struct ofpbuf *msg)
     716                 :            : {
     717                 :            :     int retval;
     718                 :            : 
     719                 :      29493 :     fatal_signal_run();
     720                 :            : 
     721         [ -  + ]:      29493 :     while ((retval = vconn_send(vconn, msg)) == EAGAIN) {
     722                 :          0 :         vconn_run(vconn);
     723                 :          0 :         vconn_run_wait(vconn);
     724                 :          0 :         vconn_send_wait(vconn);
     725                 :          0 :         poll_block();
     726                 :            :     }
     727                 :      29493 :     return retval;
     728                 :            : }
     729                 :            : 
     730                 :            : /* Same as vconn_recv, except that it waits until a message is received. */
     731                 :            : int
     732                 :      14879 : vconn_recv_block(struct vconn *vconn, struct ofpbuf **msgp)
     733                 :            : {
     734                 :            :     int retval;
     735                 :            : 
     736                 :      14879 :     fatal_signal_run();
     737                 :            : 
     738         [ +  + ]:      27590 :     while ((retval = vconn_recv(vconn, msgp)) == EAGAIN) {
     739                 :      12711 :         vconn_run(vconn);
     740                 :      12711 :         vconn_run_wait(vconn);
     741                 :      12711 :         vconn_recv_wait(vconn);
     742                 :      12711 :         poll_block();
     743                 :            :     }
     744                 :      14879 :     return retval;
     745                 :            : }
     746                 :            : 
     747                 :            : static void
     748                 :         13 : vconn_add_bundle_error(const struct ofp_header *oh, struct ovs_list *errors)
     749                 :            : {
     750         [ +  - ]:         13 :     if (errors) {
     751                 :         13 :         struct vconn_bundle_error *err = xmalloc(sizeof *err);
     752                 :         13 :         size_t len = ntohs(oh->length);
     753                 :            : 
     754                 :         13 :         memcpy(err->ofp_msg_data, oh, MIN(len, sizeof err->ofp_msg_data));
     755                 :         13 :         ovs_list_push_back(errors, &err->list_node);
     756                 :            :     }
     757                 :         13 : }
     758                 :            : 
     759                 :            : static int
     760                 :        676 : vconn_recv_xid__(struct vconn *vconn, ovs_be32 xid, struct ofpbuf **replyp,
     761                 :            :                  struct ovs_list *errors)
     762                 :            : {
     763                 :            :     for (;;) {
     764                 :            :         ovs_be32 recv_xid;
     765                 :            :         struct ofpbuf *reply;
     766                 :            :         const struct ofp_header *oh;
     767                 :            :         enum ofptype type;
     768                 :            :         int error;
     769                 :            : 
     770                 :        682 :         error = vconn_recv_block(vconn, &reply);
     771         [ -  + ]:        682 :         if (error) {
     772                 :          0 :             *replyp = NULL;
     773                 :        676 :             return error;
     774                 :            :         }
     775                 :        682 :         oh = reply->data;
     776                 :        682 :         recv_xid = oh->xid;
     777         [ +  + ]:        682 :         if (xid == recv_xid) {
     778                 :        676 :             *replyp = reply;
     779                 :        676 :             return 0;
     780                 :            :         }
     781                 :            : 
     782                 :          6 :         error = ofptype_decode(&type, oh);
     783 [ +  - ][ +  - ]:          6 :         if (!error && type == OFPTYPE_ERROR) {
     784                 :          6 :             vconn_add_bundle_error(oh, errors);
     785                 :            :         } else {
     786         [ #  # ]:          0 :             VLOG_DBG_RL(&bad_ofmsg_rl, "%s: received reply with xid %08"PRIx32
     787                 :            :                         " != expected %08"PRIx32,
     788                 :            :                         vconn->name, ntohl(recv_xid), ntohl(xid));
     789                 :            :         }
     790                 :          6 :         ofpbuf_delete(reply);
     791                 :          6 :     }
     792                 :            : }
     793                 :            : 
     794                 :            : /* Waits until a message with a transaction ID matching 'xid' is received on
     795                 :            :  * 'vconn'.  Returns 0 if successful, in which case the reply is stored in
     796                 :            :  * '*replyp' for the caller to examine and free.  Otherwise returns a positive
     797                 :            :  * errno value, or EOF, and sets '*replyp' to null.
     798                 :            :  *
     799                 :            :  * 'request' is always destroyed, regardless of the return value. */
     800                 :            : int
     801                 :          0 : vconn_recv_xid(struct vconn *vconn, ovs_be32 xid, struct ofpbuf **replyp)
     802                 :            : {
     803                 :          0 :     return vconn_recv_xid__(vconn, xid, replyp, NULL);
     804                 :            : }
     805                 :            : 
     806                 :            : static int
     807                 :        557 : vconn_transact__(struct vconn *vconn, struct ofpbuf *request,
     808                 :            :                  struct ofpbuf **replyp, struct ovs_list *errors)
     809                 :            : {
     810                 :        557 :     ovs_be32 send_xid = ((struct ofp_header *) request->data)->xid;
     811                 :            :     int error;
     812                 :            : 
     813                 :        557 :     *replyp = NULL;
     814                 :        557 :     error = vconn_send_block(vconn, request);
     815         [ -  + ]:        557 :     if (error) {
     816                 :          0 :         ofpbuf_delete(request);
     817                 :            :     }
     818         [ +  - ]:        557 :     return error ? error : vconn_recv_xid__(vconn, send_xid, replyp, errors);
     819                 :            : }
     820                 :            : 
     821                 :            : /* Sends 'request' to 'vconn' and blocks until it receives a reply with a
     822                 :            :  * matching transaction ID.  Returns 0 if successful, in which case the reply
     823                 :            :  * is stored in '*replyp' for the caller to examine and free.  Otherwise
     824                 :            :  * returns a positive errno value, or EOF, and sets '*replyp' to null.
     825                 :            :  *
     826                 :            :  * 'request' should be an OpenFlow request that requires a reply.  Otherwise,
     827                 :            :  * if there is no reply, this function can end up blocking forever (or until
     828                 :            :  * the peer drops the connection).
     829                 :            :  *
     830                 :            :  * 'request' is always destroyed, regardless of the return value. */
     831                 :            : int
     832                 :        319 : vconn_transact(struct vconn *vconn, struct ofpbuf *request,
     833                 :            :                struct ofpbuf **replyp)
     834                 :            : {
     835                 :        319 :     return vconn_transact__(vconn, request, replyp, NULL);
     836                 :            : }
     837                 :            : 
     838                 :            : static int
     839                 :      13662 : vconn_send_barrier(struct vconn *vconn, ovs_be32 *barrier_xid)
     840                 :            : {
     841                 :            :     struct ofpbuf *barrier;
     842                 :            :     int error;
     843                 :            : 
     844                 :            :     /* Send barrier. */
     845                 :      13662 :     barrier = ofputil_encode_barrier_request(vconn_get_version(vconn));
     846                 :      13662 :     *barrier_xid = ((struct ofp_header *) barrier->data)->xid;
     847                 :      13662 :     error = vconn_send_block(vconn, barrier);
     848         [ -  + ]:      13662 :     if (error) {
     849                 :          0 :         ofpbuf_delete(barrier);
     850                 :            :     }
     851                 :      13662 :     return error;
     852                 :            : }
     853                 :            : 
     854                 :            : /* Sends 'request' followed by a barrier request to 'vconn', then blocks until
     855                 :            :  * it receives a reply to the barrier.  If successful, stores the reply to
     856                 :            :  * 'request' in '*replyp', if one was received, and otherwise NULL, then
     857                 :            :  * returns 0.  Otherwise returns a positive errno value, or EOF, and sets
     858                 :            :  * '*replyp' to null.
     859                 :            :  *
     860                 :            :  * This function is useful for sending an OpenFlow request that doesn't
     861                 :            :  * ordinarily include a reply but might report an error in special
     862                 :            :  * circumstances.
     863                 :            :  *
     864                 :            :  * 'request' is always destroyed, regardless of the return value. */
     865                 :            : int
     866                 :      13543 : vconn_transact_noreply(struct vconn *vconn, struct ofpbuf *request,
     867                 :            :                        struct ofpbuf **replyp)
     868                 :            : {
     869                 :            :     ovs_be32 request_xid;
     870                 :            :     ovs_be32 barrier_xid;
     871                 :            :     int error;
     872                 :            : 
     873                 :      13543 :     *replyp = NULL;
     874                 :            : 
     875                 :            :     /* Send request. */
     876                 :      13543 :     request_xid = ((struct ofp_header *) request->data)->xid;
     877                 :      13543 :     error = vconn_send_block(vconn, request);
     878         [ -  + ]:      13543 :     if (error) {
     879                 :          0 :         ofpbuf_delete(request);
     880                 :          0 :         return error;
     881                 :            :     }
     882                 :            : 
     883                 :            :     /* Send barrier. */
     884                 :      13543 :     error = vconn_send_barrier(vconn, &barrier_xid);
     885         [ -  + ]:      13543 :     if (error) {
     886                 :          0 :         return error;
     887                 :            :     }
     888                 :            : 
     889                 :            :     for (;;) {
     890                 :            :         struct ofpbuf *msg;
     891                 :            :         ovs_be32 msg_xid;
     892                 :            :         int error;
     893                 :            : 
     894                 :      13556 :         error = vconn_recv_block(vconn, &msg);
     895         [ -  + ]:      13556 :         if (error) {
     896                 :          0 :             ofpbuf_delete(*replyp);
     897                 :          0 :             *replyp = NULL;
     898                 :      13543 :             return error;
     899                 :            :         }
     900                 :            : 
     901                 :      13556 :         msg_xid = ((struct ofp_header *) msg->data)->xid;
     902         [ +  + ]:      13556 :         if (msg_xid == request_xid) {
     903         [ -  + ]:         13 :             if (*replyp) {
     904         [ #  # ]:          0 :                 VLOG_WARN_RL(&bad_ofmsg_rl, "%s: duplicate replies with "
     905                 :            :                              "xid %08"PRIx32, vconn->name, ntohl(msg_xid));
     906                 :          0 :                 ofpbuf_delete(*replyp);
     907                 :            :             }
     908                 :         13 :             *replyp = msg;
     909                 :            :         } else {
     910                 :      13543 :             ofpbuf_delete(msg);
     911         [ +  - ]:      13543 :             if (msg_xid == barrier_xid) {
     912                 :      13543 :                 return 0;
     913                 :            :             } else {
     914         [ #  # ]:          0 :                 VLOG_DBG_RL(&bad_ofmsg_rl, "%s: reply with xid %08"PRIx32
     915                 :            :                             " != expected %08"PRIx32" or %08"PRIx32,
     916                 :            :                             vconn->name, ntohl(msg_xid),
     917                 :            :                             ntohl(request_xid), ntohl(barrier_xid));
     918                 :            :             }
     919                 :            :         }
     920                 :         13 :     }
     921                 :            : }
     922                 :            : 
     923                 :            : /* vconn_transact_noreply() for a list of "struct ofpbuf"s, sent one by one.
     924                 :            :  * All of the requests on 'requests' are always destroyed, regardless of the
     925                 :            :  * return value. */
     926                 :            : int
     927                 :      13028 : vconn_transact_multiple_noreply(struct vconn *vconn, struct ovs_list *requests,
     928                 :            :                                 struct ofpbuf **replyp)
     929                 :            : {
     930                 :            :     struct ofpbuf *request;
     931                 :            : 
     932         [ +  + ]:      26058 :     LIST_FOR_EACH_POP (request, list_node, requests) {
     933                 :            :         int error;
     934                 :            : 
     935                 :      13043 :         error = vconn_transact_noreply(vconn, request, replyp);
     936 [ +  - ][ +  + ]:      13043 :         if (error || *replyp) {
     937                 :         13 :             ofpbuf_list_delete(requests);
     938                 :         13 :             return error;
     939                 :            :         }
     940                 :            :     }
     941                 :            : 
     942                 :      13015 :     *replyp = NULL;
     943                 :      13015 :     return 0;
     944                 :            : }
     945                 :            : 
     946                 :            : static enum ofperr
     947                 :        238 : vconn_bundle_reply_validate(struct ofpbuf *reply,
     948                 :            :                             struct ofputil_bundle_ctrl_msg *request,
     949                 :            :                             struct ovs_list *errors)
     950                 :            : {
     951                 :            :     const struct ofp_header *oh;
     952                 :            :     enum ofptype type;
     953                 :            :     enum ofperr error;
     954                 :            :     struct ofputil_bundle_ctrl_msg rbc;
     955                 :            : 
     956                 :        238 :     oh = reply->data;
     957                 :        238 :     error = ofptype_decode(&type, oh);
     958         [ -  + ]:        238 :     if (error) {
     959                 :          0 :         return error;
     960                 :            :     }
     961                 :            : 
     962         [ +  + ]:        238 :     if (type == OFPTYPE_ERROR) {
     963                 :          5 :         vconn_add_bundle_error(oh, errors);
     964                 :          5 :         return ofperr_decode_msg(oh, NULL);
     965                 :            :     }
     966         [ -  + ]:        233 :     if (type != OFPTYPE_BUNDLE_CONTROL) {
     967                 :          0 :         return OFPERR_OFPBRC_BAD_TYPE;
     968                 :            :     }
     969                 :            : 
     970                 :        233 :     error = ofputil_decode_bundle_ctrl(oh, &rbc);
     971         [ -  + ]:        233 :     if (error) {
     972                 :          0 :         return error;
     973                 :            :     }
     974                 :            : 
     975         [ -  + ]:        233 :     if (rbc.bundle_id != request->bundle_id) {
     976                 :          0 :         return OFPERR_OFPBFC_BAD_ID;
     977                 :            :     }
     978                 :            : 
     979         [ -  + ]:        233 :     if (rbc.type != request->type + 1) {
     980                 :          0 :         return OFPERR_OFPBFC_BAD_TYPE;
     981                 :            :     }
     982                 :            : 
     983                 :        238 :     return 0;
     984                 :            : }
     985                 :            : 
     986                 :            : /* Send bundle control message 'bc' of 'type' via 'vconn', and wait for either
     987                 :            :  * an error or the corresponding bundle control message response.
     988                 :            :  *
     989                 :            :  * 'errors' is a list to which any OpenFlow errors relating to bundle
     990                 :            :  * processing are appended.  Caller is responsible for releasing the memory of
     991                 :            :  * each node in the list on return.
     992                 :            :  *
     993                 :            :  * Returns errno value, or 0 when successful. */
     994                 :            : static int
     995                 :        238 : vconn_bundle_control_transact(struct vconn *vconn,
     996                 :            :                               struct ofputil_bundle_ctrl_msg *bc,
     997                 :            :                               uint16_t type, struct ovs_list *errors)
     998                 :            : {
     999                 :            :     struct ofpbuf *request, *reply;
    1000                 :            :     int error;
    1001                 :            :     enum ofperr ofperr;
    1002                 :            : 
    1003                 :        238 :     bc->type = type;
    1004                 :        238 :     request = ofputil_encode_bundle_ctrl_request(vconn->version, bc);
    1005                 :        238 :     ofpmsg_update_length(request);
    1006                 :        238 :     error = vconn_transact__(vconn, request, &reply, errors);
    1007         [ -  + ]:        238 :     if (error) {
    1008                 :          0 :         return error;
    1009                 :            :     }
    1010                 :            : 
    1011                 :        238 :     ofperr = vconn_bundle_reply_validate(reply, bc, errors);
    1012                 :        238 :     ofpbuf_delete(reply);
    1013                 :            : 
    1014         [ +  + ]:        238 :     return ofperr ? EPROTO : 0;
    1015                 :            : }
    1016                 :            : 
    1017                 :            : /* Checks if error responses can be received on 'vconn'. */
    1018                 :            : static void
    1019                 :        735 : vconn_recv_error(struct vconn *vconn, struct ovs_list *errors)
    1020                 :            : {
    1021                 :            :     int error;
    1022                 :            : 
    1023                 :            :     do {
    1024                 :            :         struct ofpbuf *reply;
    1025                 :            : 
    1026                 :        737 :         error = vconn_recv(vconn, &reply);
    1027         [ +  + ]:        737 :         if (!error) {
    1028                 :            :             const struct ofp_header *oh;
    1029                 :            :             enum ofptype type;
    1030                 :            :             enum ofperr ofperr;
    1031                 :            : 
    1032                 :          2 :             oh = reply->data;
    1033                 :          2 :             ofperr = ofptype_decode(&type, oh);
    1034 [ +  - ][ +  - ]:          2 :             if (!ofperr && type == OFPTYPE_ERROR) {
    1035                 :          2 :                 vconn_add_bundle_error(oh, errors);
    1036                 :            :             } else {
    1037         [ #  # ]:          0 :                 VLOG_DBG_RL(&bad_ofmsg_rl,
    1038                 :            :                             "%s: received unexpected reply with xid %08"PRIx32,
    1039                 :            :                             vconn->name, ntohl(oh->xid));
    1040                 :            :             }
    1041                 :          2 :             ofpbuf_delete(reply);
    1042                 :            :         }
    1043         [ +  + ]:        737 :     } while (!error);
    1044                 :        735 : }
    1045                 :            : 
    1046                 :            : /* Sends a barrier and waits for the barrier response and stores any errors
    1047                 :            :  * that are received before the barrier response. */
    1048                 :            : static int
    1049                 :        119 : vconn_bundle_barrier_transact(struct vconn *vconn, struct ovs_list *errors)
    1050                 :            : {
    1051                 :            :     struct ofpbuf *reply;
    1052                 :            :     ovs_be32 barrier_xid;
    1053                 :            :     int error;
    1054                 :            : 
    1055                 :        119 :     error = vconn_send_barrier(vconn, &barrier_xid);
    1056         [ -  + ]:        119 :     if (error) {
    1057                 :          0 :         return error;
    1058                 :            :     }
    1059                 :            : 
    1060                 :        119 :     error = vconn_recv_xid__(vconn, barrier_xid, &reply, errors);
    1061         [ -  + ]:        119 :     if (error) {
    1062                 :          0 :         return error;
    1063                 :            :     }
    1064                 :        119 :     ofpbuf_delete(reply);
    1065                 :        119 :     return 0;
    1066                 :            : }
    1067                 :            : 
    1068                 :            : static int
    1069                 :        735 : vconn_bundle_add_msg(struct vconn *vconn, struct ofputil_bundle_ctrl_msg *bc,
    1070                 :            :                      struct ofpbuf *msg,
    1071                 :            :                      struct ovs_list *errors)
    1072                 :            : {
    1073                 :            :     struct ofputil_bundle_add_msg bam;
    1074                 :            :     struct ofpbuf *request;
    1075                 :            :     int error;
    1076                 :            : 
    1077                 :        735 :     ofpmsg_update_length(msg);
    1078                 :            : 
    1079                 :        735 :     bam.bundle_id = bc->bundle_id;
    1080                 :        735 :     bam.flags = bc->flags;
    1081                 :        735 :     bam.msg = msg->data;
    1082                 :            : 
    1083                 :        735 :     request = ofputil_encode_bundle_add(vconn->version, &bam);
    1084                 :            : 
    1085                 :        735 :     error = vconn_send_block(vconn, request);
    1086         [ +  - ]:        735 :     if (!error) {
    1087                 :            :         /* Check for an error return, so that the socket buffer does not become
    1088                 :            :          * full of errors. */
    1089                 :        735 :         vconn_recv_error(vconn, errors);
    1090                 :            :     }
    1091                 :        735 :     return error;
    1092                 :            : }
    1093                 :            : 
    1094                 :            : int
    1095                 :        119 : vconn_bundle_transact(struct vconn *vconn, struct ovs_list *requests,
    1096                 :            :                       uint16_t flags, struct ovs_list *errors)
    1097                 :            : {
    1098                 :            :     struct ofputil_bundle_ctrl_msg bc;
    1099                 :            :     struct ofpbuf *request;
    1100                 :            :     int error;
    1101                 :            : 
    1102                 :        119 :     ovs_list_init(errors);
    1103                 :            : 
    1104                 :        119 :     memset(&bc, 0, sizeof bc);
    1105                 :        119 :     bc.flags = flags;
    1106                 :        119 :     error = vconn_bundle_control_transact(vconn, &bc, OFPBCT_OPEN_REQUEST,
    1107                 :            :                                           errors);
    1108         [ -  + ]:        119 :     if (error) {
    1109                 :          0 :         return error;
    1110                 :            :     }
    1111                 :            : 
    1112         [ +  + ]:        854 :     LIST_FOR_EACH (request, list_node, requests) {
    1113                 :        735 :         error = vconn_bundle_add_msg(vconn, &bc, request, errors);
    1114         [ -  + ]:        735 :         if (error) {
    1115                 :          0 :             break;
    1116                 :            :         }
    1117                 :            :     }
    1118                 :            : 
    1119         [ +  - ]:        119 :     if (!error) {
    1120                 :            :         /* A failing message does not invalidate the bundle, but the message is
    1121                 :            :          * simply not added to the bundle.  Since we do not want to commit if
    1122                 :            :          * any of the messages failed, we need to explicitly sync with barrier
    1123                 :            :          * before we issue the commit message. */
    1124                 :        119 :         error = vconn_bundle_barrier_transact(vconn, errors);
    1125                 :            :     }
    1126 [ +  - ][ +  + ]:        119 :     if (!error && !ovs_list_is_empty(errors)) {
    1127                 :          3 :         error = EPROTO;
    1128                 :            :     }
    1129                 :            : 
    1130                 :            :     /* Commit only if no errors are received. */
    1131         [ +  + ]:        119 :     if (!error) {
    1132                 :        116 :         error = vconn_bundle_control_transact(vconn, &bc,
    1133                 :            :                                               OFPBCT_COMMIT_REQUEST,
    1134                 :            :                                               errors);
    1135                 :            :     } else {
    1136                 :          3 :         vconn_bundle_control_transact(vconn, &bc, OFPBCT_DISCARD_REQUEST,
    1137                 :            :                                       errors);
    1138                 :            :     }
    1139                 :        119 :     return error;
    1140                 :            : }
    1141                 :            : 
    1142                 :            : void
    1143                 :     144192 : vconn_wait(struct vconn *vconn, enum vconn_wait_type wait)
    1144                 :            : {
    1145 [ +  + ][ +  + ]:     144192 :     ovs_assert(wait == WAIT_CONNECT || wait == WAIT_RECV || wait == WAIT_SEND);
         [ +  + ][ -  + ]
    1146                 :            : 
    1147   [ +  +  +  +  :     144192 :     switch (vconn->state) {
                   -  - ]
    1148                 :            :     case VCS_CONNECTING:
    1149                 :         62 :         wait = WAIT_CONNECT;
    1150                 :         62 :         break;
    1151                 :            : 
    1152                 :            :     case VCS_SEND_HELLO:
    1153                 :            :     case VCS_SEND_ERROR:
    1154                 :       6838 :         wait = WAIT_SEND;
    1155                 :       6838 :         break;
    1156                 :            : 
    1157                 :            :     case VCS_RECV_HELLO:
    1158                 :       7030 :         wait = WAIT_RECV;
    1159                 :       7030 :         break;
    1160                 :            : 
    1161                 :            :     case VCS_CONNECTED:
    1162                 :     130262 :         break;
    1163                 :            : 
    1164                 :            :     case VCS_DISCONNECTED:
    1165                 :          0 :         poll_immediate_wake();
    1166                 :          0 :         return;
    1167                 :            :     }
    1168                 :     144192 :     (vconn->vclass->wait)(vconn, wait);
    1169                 :            : }
    1170                 :            : 
    1171                 :            : void
    1172                 :       7456 : vconn_connect_wait(struct vconn *vconn)
    1173                 :            : {
    1174                 :       7456 :     vconn_wait(vconn, WAIT_CONNECT);
    1175                 :       7456 : }
    1176                 :            : 
    1177                 :            : void
    1178                 :      14536 : vconn_recv_wait(struct vconn *vconn)
    1179                 :            : {
    1180                 :      14536 :     vconn_wait(vconn, WAIT_RECV);
    1181                 :      14536 : }
    1182                 :            : 
    1183                 :            : void
    1184                 :          0 : vconn_send_wait(struct vconn *vconn)
    1185                 :            : {
    1186                 :          0 :     vconn_wait(vconn, WAIT_SEND);
    1187                 :          0 : }
    1188                 :            : 
    1189                 :            : /* Given 'name', a connection name in the form "TYPE:ARGS", stores the class
    1190                 :            :  * named "TYPE" into '*classp' and returns 0.  Returns EAFNOSUPPORT and stores
    1191                 :            :  * a null pointer into '*classp' if 'name' is in the wrong form or if no such
    1192                 :            :  * class exists. */
    1193                 :            : static int
    1194                 :       6202 : pvconn_lookup_class(const char *name, const struct pvconn_class **classp)
    1195                 :            : {
    1196                 :            :     size_t prefix_len;
    1197                 :            : 
    1198                 :       6202 :     prefix_len = strcspn(name, ":");
    1199         [ +  - ]:       6202 :     if (name[prefix_len] != '\0') {
    1200                 :            :         size_t i;
    1201                 :            : 
    1202         [ +  - ]:      12404 :         for (i = 0; i < ARRAY_SIZE(pvconn_classes); i++) {
    1203                 :      12404 :             const struct pvconn_class *class = pvconn_classes[i];
    1204         [ +  + ]:      12404 :             if (strlen(class->name) == prefix_len
    1205         [ +  - ]:       6202 :                 && !memcmp(class->name, name, prefix_len)) {
    1206                 :       6202 :                 *classp = class;
    1207                 :       6202 :                 return 0;
    1208                 :            :             }
    1209                 :            :         }
    1210                 :            :     }
    1211                 :            : 
    1212                 :          0 :     *classp = NULL;
    1213                 :          0 :     return EAFNOSUPPORT;
    1214                 :            : }
    1215                 :            : 
    1216                 :            : /* Returns 0 if 'name' is a connection name in the form "TYPE:ARGS" and TYPE is
    1217                 :            :  * a supported connection type, otherwise EAFNOSUPPORT.  */
    1218                 :            : int
    1219                 :       4703 : pvconn_verify_name(const char *name)
    1220                 :            : {
    1221                 :            :     const struct pvconn_class *class;
    1222                 :       4703 :     return pvconn_lookup_class(name, &class);
    1223                 :            : }
    1224                 :            : 
    1225                 :            : /* Attempts to start listening for OpenFlow connections.  'name' is a
    1226                 :            :  * connection name in the form "TYPE:ARGS", where TYPE is an passive vconn
    1227                 :            :  * class's name and ARGS are vconn class-specific.
    1228                 :            :  *
    1229                 :            :  * vconns accepted by the pvconn will automatically negotiate an OpenFlow
    1230                 :            :  * protocol version acceptable to both peers on the connection.  The version
    1231                 :            :  * negotiated will be one of those in the 'allowed_versions' bitmap: version
    1232                 :            :  * 'x' is allowed if allowed_versions & (1 << x) is nonzero.  If
    1233                 :            :  * 'allowed_versions' is zero, then OFPUTIL_DEFAULT_VERSIONS are allowed.
    1234                 :            :  *
    1235                 :            :  * Returns 0 if successful, otherwise a positive errno value.  If successful,
    1236                 :            :  * stores a pointer to the new connection in '*pvconnp', otherwise a null
    1237                 :            :  * pointer.  */
    1238                 :            : int
    1239                 :       1499 : pvconn_open(const char *name, uint32_t allowed_versions, uint8_t dscp,
    1240                 :            :             struct pvconn **pvconnp)
    1241                 :            : {
    1242                 :            :     const struct pvconn_class *class;
    1243                 :            :     struct pvconn *pvconn;
    1244                 :            :     char *suffix_copy;
    1245                 :            :     int error;
    1246                 :            : 
    1247                 :       1499 :     check_vconn_classes();
    1248                 :            : 
    1249         [ +  + ]:       1499 :     if (!allowed_versions) {
    1250                 :        937 :         allowed_versions = OFPUTIL_DEFAULT_VERSIONS;
    1251                 :            :     }
    1252                 :            : 
    1253                 :            :     /* Look up the class. */
    1254                 :       1499 :     error = pvconn_lookup_class(name, &class);
    1255         [ -  + ]:       1499 :     if (!class) {
    1256                 :          0 :         goto error;
    1257                 :            :     }
    1258                 :            : 
    1259                 :            :     /* Call class's "open" function. */
    1260                 :       1499 :     suffix_copy = xstrdup(strchr(name, ':') + 1);
    1261                 :       1499 :     error = class->listen(name, allowed_versions, suffix_copy, &pvconn, dscp);
    1262                 :       1499 :     free(suffix_copy);
    1263         [ -  + ]:       1499 :     if (error) {
    1264                 :          0 :         goto error;
    1265                 :            :     }
    1266                 :            : 
    1267                 :            :     /* Success. */
    1268                 :       1499 :     *pvconnp = pvconn;
    1269                 :       1499 :     return 0;
    1270                 :            : 
    1271                 :            : error:
    1272                 :          0 :     *pvconnp = NULL;
    1273                 :       1499 :     return error;
    1274                 :            : }
    1275                 :            : 
    1276                 :            : /* Returns the name that was used to open 'pvconn'.  The caller must not
    1277                 :            :  * modify or free the name. */
    1278                 :            : const char *
    1279                 :       8653 : pvconn_get_name(const struct pvconn *pvconn)
    1280                 :            : {
    1281                 :       8653 :     return pvconn->name;
    1282                 :            : }
    1283                 :            : 
    1284                 :            : /* Closes 'pvconn'. */
    1285                 :            : void
    1286                 :       1499 : pvconn_close(struct pvconn *pvconn)
    1287                 :            : {
    1288         [ +  - ]:       1499 :     if (pvconn != NULL) {
    1289                 :       1499 :         char *name = pvconn->name;
    1290                 :       1499 :         (pvconn->pvclass->close)(pvconn);
    1291                 :       1499 :         free(name);
    1292                 :            :     }
    1293                 :       1499 : }
    1294                 :            : 
    1295                 :            : /* Tries to accept a new connection on 'pvconn'.  If successful, stores the new
    1296                 :            :  * connection in '*new_vconn' and returns 0.  Otherwise, returns a positive
    1297                 :            :  * errno value.
    1298                 :            :  *
    1299                 :            :  * The new vconn will automatically negotiate an OpenFlow protocol version
    1300                 :            :  * acceptable to both peers on the connection.  The version negotiated will be
    1301                 :            :  * no lower than 'min_version' and no higher than 'max_version'.
    1302                 :            :  *
    1303                 :            :  * pvconn_accept() will not block waiting for a connection.  If no connection
    1304                 :            :  * is ready to be accepted, it returns EAGAIN immediately. */
    1305                 :            : int
    1306                 :     315213 : pvconn_accept(struct pvconn *pvconn, struct vconn **new_vconn)
    1307                 :            : {
    1308                 :     315213 :     int retval = (pvconn->pvclass->accept)(pvconn, new_vconn);
    1309         [ +  + ]:     315213 :     if (retval) {
    1310                 :     311794 :         *new_vconn = NULL;
    1311                 :            :     } else {
    1312 [ -  + ][ #  # ]:       3419 :         ovs_assert((*new_vconn)->state != VCS_CONNECTING
    1313                 :            :                    || (*new_vconn)->vclass->connect);
    1314                 :            :     }
    1315                 :     315213 :     return retval;
    1316                 :            : }
    1317                 :            : 
    1318                 :            : void
    1319                 :     307292 : pvconn_wait(struct pvconn *pvconn)
    1320                 :            : {
    1321                 :     307292 :     (pvconn->pvclass->wait)(pvconn);
    1322                 :     307292 : }
    1323                 :            : 
    1324                 :            : /* Initializes 'vconn' as a new vconn named 'name', implemented via 'class'.
    1325                 :            :  * The initial connection status, supplied as 'connect_status', is interpreted
    1326                 :            :  * as follows:
    1327                 :            :  *
    1328                 :            :  *      - 0: 'vconn' is connected.  Its 'send' and 'recv' functions may be
    1329                 :            :  *        called in the normal fashion.
    1330                 :            :  *
    1331                 :            :  *      - EAGAIN: 'vconn' is trying to complete a connection.  Its 'connect'
    1332                 :            :  *        function should be called to complete the connection.
    1333                 :            :  *
    1334                 :            :  *      - Other positive errno values indicate that the connection failed with
    1335                 :            :  *        the specified error.
    1336                 :            :  *
    1337                 :            :  * After calling this function, vconn_close() must be used to destroy 'vconn',
    1338                 :            :  * otherwise resources will be leaked.
    1339                 :            :  *
    1340                 :            :  * The caller retains ownership of 'name'. */
    1341                 :            : void
    1342                 :       6921 : vconn_init(struct vconn *vconn, const struct vconn_class *class,
    1343                 :            :            int connect_status, const char *name, uint32_t allowed_versions)
    1344                 :            : {
    1345                 :       6921 :     memset(vconn, 0, sizeof *vconn);
    1346                 :       6921 :     vconn->vclass = class;
    1347                 :       6921 :     vconn->state = (connect_status == EAGAIN ? VCS_CONNECTING
    1348         [ +  + ]:      13830 :                     : !connect_status ? VCS_SEND_HELLO
    1349         [ +  - ]:       6909 :                     : VCS_DISCONNECTED);
    1350                 :       6921 :     vconn->error = connect_status;
    1351                 :       6921 :     vconn->allowed_versions = allowed_versions;
    1352                 :       6921 :     vconn->name = xstrdup(name);
    1353 [ +  + ][ -  + ]:       6921 :     ovs_assert(vconn->state != VCS_CONNECTING || class->connect);
    1354                 :       6921 : }
    1355                 :            : 
    1356                 :            : void
    1357                 :       1499 : pvconn_init(struct pvconn *pvconn, const struct pvconn_class *class,
    1358                 :            :             const char *name, uint32_t allowed_versions)
    1359                 :            : {
    1360                 :       1499 :     pvconn->pvclass = class;
    1361                 :       1499 :     pvconn->name = xstrdup(name);
    1362                 :       1499 :     pvconn->allowed_versions = allowed_versions;
    1363                 :       1499 : }

Generated by: LCOV version 1.12