LCOV - code coverage report
Current view: top level - lib - netdev.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 554 691 80.2 %
Date: 2016-09-14 01:02:56 Functions: 97 113 85.8 %
Branches: 243 398 61.1 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2016 Nicira, Inc.
       3                 :            :  *
       4                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
       5                 :            :  * you may not use this file except in compliance with the License.
       6                 :            :  * You may obtain a copy of the License at:
       7                 :            :  *
       8                 :            :  *     http://www.apache.org/licenses/LICENSE-2.0
       9                 :            :  *
      10                 :            :  * Unless required by applicable law or agreed to in writing, software
      11                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
      12                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      13                 :            :  * See the License for the specific language governing permissions and
      14                 :            :  * limitations under the License.
      15                 :            :  */
      16                 :            : 
      17                 :            : #include <config.h>
      18                 :            : #include "netdev.h"
      19                 :            : 
      20                 :            : #include <errno.h>
      21                 :            : #include <inttypes.h>
      22                 :            : #include <netinet/in.h>
      23                 :            : #include <stdlib.h>
      24                 :            : #include <string.h>
      25                 :            : #include <unistd.h>
      26                 :            : 
      27                 :            : #ifndef _WIN32
      28                 :            : #include <ifaddrs.h>
      29                 :            : #include <net/if.h>
      30                 :            : #include <sys/ioctl.h>
      31                 :            : #include <sys/types.h>
      32                 :            : #endif
      33                 :            : 
      34                 :            : #include "cmap.h"
      35                 :            : #include "coverage.h"
      36                 :            : #include "dpif.h"
      37                 :            : #include "dp-packet.h"
      38                 :            : #include "openvswitch/dynamic-string.h"
      39                 :            : #include "fatal-signal.h"
      40                 :            : #include "hash.h"
      41                 :            : #include "openvswitch/list.h"
      42                 :            : #include "netdev-dpdk.h"
      43                 :            : #include "netdev-provider.h"
      44                 :            : #include "netdev-vport.h"
      45                 :            : #include "odp-netlink.h"
      46                 :            : #include "openflow/openflow.h"
      47                 :            : #include "packets.h"
      48                 :            : #include "poll-loop.h"
      49                 :            : #include "seq.h"
      50                 :            : #include "openvswitch/shash.h"
      51                 :            : #include "smap.h"
      52                 :            : #include "sset.h"
      53                 :            : #include "svec.h"
      54                 :            : #include "openvswitch/vlog.h"
      55                 :            : #include "flow.h"
      56                 :            : #include "util.h"
      57                 :            : 
      58                 :      20190 : VLOG_DEFINE_THIS_MODULE(netdev);
      59                 :            : 
      60                 :     153018 : COVERAGE_DEFINE(netdev_received);
      61                 :     180294 : COVERAGE_DEFINE(netdev_sent);
      62                 :      92820 : COVERAGE_DEFINE(netdev_add_router);
      63                 :     145026 : COVERAGE_DEFINE(netdev_get_stats);
      64                 :            : 
      65                 :            : struct netdev_saved_flags {
      66                 :            :     struct netdev *netdev;
      67                 :            :     struct ovs_list node;           /* In struct netdev's saved_flags_list. */
      68                 :            :     enum netdev_flags saved_flags;
      69                 :            :     enum netdev_flags saved_values;
      70                 :            : };
      71                 :            : 
      72                 :            : /* Protects 'netdev_shash' and the mutable members of struct netdev. */
      73                 :            : static struct ovs_mutex netdev_mutex = OVS_MUTEX_INITIALIZER;
      74                 :            : 
      75                 :            : /* All created network devices. */
      76                 :            : static struct shash netdev_shash OVS_GUARDED_BY(netdev_mutex)
      77                 :            :     = SHASH_INITIALIZER(&netdev_shash);
      78                 :            : 
      79                 :            : /* Mutual exclusion of */
      80                 :            : static struct ovs_mutex netdev_class_mutex OVS_ACQ_BEFORE(netdev_mutex)
      81                 :            :     = OVS_MUTEX_INITIALIZER;
      82                 :            : 
      83                 :            : /* Contains 'struct netdev_registered_class'es. */
      84                 :            : static struct cmap netdev_classes = CMAP_INITIALIZER;
      85                 :            : 
      86                 :            : struct netdev_registered_class {
      87                 :            :     struct cmap_node cmap_node; /* In 'netdev_classes', by class->type. */
      88                 :            :     const struct netdev_class *class;
      89                 :            : 
      90                 :            :     /* Number of references: one for the class itself and one for every
      91                 :            :      * instance of the class. */
      92                 :            :     struct ovs_refcount refcnt;
      93                 :            : };
      94                 :            : 
      95                 :            : /* This is set pretty low because we probably won't learn anything from the
      96                 :            :  * additional log messages. */
      97                 :            : static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 20);
      98                 :            : 
      99                 :            : static void restore_all_flags(void *aux OVS_UNUSED);
     100                 :            : void update_device_args(struct netdev *, const struct shash *args);
     101                 :            : 
     102                 :            : int
     103                 :       2562 : netdev_n_txq(const struct netdev *netdev)
     104                 :            : {
     105                 :       2562 :     return netdev->n_txq;
     106                 :            : }
     107                 :            : 
     108                 :            : int
     109                 :       2478 : netdev_n_rxq(const struct netdev *netdev)
     110                 :            : {
     111                 :       2478 :     return netdev->n_rxq;
     112                 :            : }
     113                 :            : 
     114                 :            : bool
     115                 :   27441884 : netdev_is_pmd(const struct netdev *netdev)
     116                 :            : {
     117                 :   27441884 :     return netdev->netdev_class->is_pmd;
     118                 :            : }
     119                 :            : 
     120                 :            : static void
     121                 :     273702 : netdev_initialize(void)
     122                 :            :     OVS_EXCLUDED(netdev_mutex)
     123                 :            : {
     124                 :            :     static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER;
     125                 :            : 
     126         [ +  + ]:     273702 :     if (ovsthread_once_start(&once)) {
     127                 :        686 :         fatal_signal_add_hook(restore_all_flags, NULL, NULL, true);
     128                 :            : 
     129                 :        686 :         netdev_vport_patch_register();
     130                 :            : 
     131                 :            : #ifdef __linux__
     132                 :        686 :         netdev_register_provider(&netdev_linux_class);
     133                 :        686 :         netdev_register_provider(&netdev_internal_class);
     134                 :        686 :         netdev_register_provider(&netdev_tap_class);
     135                 :        686 :         netdev_vport_tunnel_register();
     136                 :            : #endif
     137                 :            : #if defined(__FreeBSD__) || defined(__NetBSD__)
     138                 :            :         netdev_register_provider(&netdev_tap_class);
     139                 :            :         netdev_register_provider(&netdev_bsd_class);
     140                 :            : #endif
     141                 :            : #ifdef _WIN32
     142                 :            :         netdev_register_provider(&netdev_windows_class);
     143                 :            :         netdev_register_provider(&netdev_internal_class);
     144                 :            :         netdev_vport_tunnel_register();
     145                 :            : #endif
     146                 :        686 :         ovsthread_once_done(&once);
     147                 :            :     }
     148                 :     273702 : }
     149                 :            : 
     150                 :            : /* Performs periodic work needed by all the various kinds of netdevs.
     151                 :            :  *
     152                 :            :  * If your program opens any netdevs, it must call this function within its
     153                 :            :  * main poll loop. */
     154                 :            : void
     155                 :     105174 : netdev_run(void)
     156                 :            :     OVS_EXCLUDED(netdev_mutex)
     157                 :            : {
     158                 :     105174 :     netdev_initialize();
     159                 :            : 
     160                 :            :     struct netdev_registered_class *rc;
     161 [ +  + ][ +  + ]:    1444644 :     CMAP_FOR_EACH (rc, cmap_node, &netdev_classes) {
     162         [ +  - ]:    1339470 :         if (rc->class->run) {
     163                 :    1339470 :             rc->class->run(rc->class);
     164                 :            :         }
     165                 :            :     }
     166                 :     105174 : }
     167                 :            : 
     168                 :            : /* Arranges for poll_block() to wake up when netdev_run() needs to be called.
     169                 :            :  *
     170                 :            :  * If your program opens any netdevs, it must call this function within its
     171                 :            :  * main poll loop. */
     172                 :            : void
     173                 :     105174 : netdev_wait(void)
     174                 :            :     OVS_EXCLUDED(netdev_mutex)
     175                 :            : {
     176                 :     105174 :     netdev_initialize();
     177                 :            : 
     178                 :            :     struct netdev_registered_class *rc;
     179 [ +  + ][ +  + ]:    1444644 :     CMAP_FOR_EACH (rc, cmap_node, &netdev_classes) {
     180         [ +  - ]:    1339470 :         if (rc->class->wait) {
     181                 :    1339470 :             rc->class->wait(rc->class);
     182                 :            :         }
     183                 :            :     }
     184                 :     105174 : }
     185                 :            : 
     186                 :            : static struct netdev_registered_class *
     187                 :      64019 : netdev_lookup_class(const char *type)
     188                 :            : {
     189                 :            :     struct netdev_registered_class *rc;
     190         [ +  + ]:      64019 :     CMAP_FOR_EACH_WITH_HASH (rc, cmap_node, hash_string(type, 0),
     191                 :            :                              &netdev_classes) {
     192         [ +  - ]:      55344 :         if (!strcmp(type, rc->class->type)) {
     193                 :      55344 :             return rc;
     194                 :            :         }
     195                 :            :     }
     196                 :       8675 :     return NULL;
     197                 :            : }
     198                 :            : 
     199                 :            : /* Initializes and registers a new netdev provider.  After successful
     200                 :            :  * registration, new netdevs of that type can be opened using netdev_open(). */
     201                 :            : int
     202                 :       8675 : netdev_register_provider(const struct netdev_class *new_class)
     203                 :            :     OVS_EXCLUDED(netdev_class_mutex, netdev_mutex)
     204                 :            : {
     205                 :            :     int error;
     206                 :            : 
     207                 :       8675 :     ovs_mutex_lock(&netdev_class_mutex);
     208         [ -  + ]:       8675 :     if (netdev_lookup_class(new_class->type)) {
     209         [ #  # ]:          0 :         VLOG_WARN("attempted to register duplicate netdev provider: %s",
     210                 :            :                    new_class->type);
     211                 :          0 :         error = EEXIST;
     212                 :            :     } else {
     213         [ -  + ]:       8675 :         error = new_class->init ? new_class->init() : 0;
     214         [ +  - ]:       8675 :         if (!error) {
     215                 :            :             struct netdev_registered_class *rc;
     216                 :            : 
     217                 :       8675 :             rc = xmalloc(sizeof *rc);
     218                 :       8675 :             cmap_insert(&netdev_classes, &rc->cmap_node,
     219                 :            :                         hash_string(new_class->type, 0));
     220                 :       8675 :             rc->class = new_class;
     221                 :       8675 :             ovs_refcount_init(&rc->refcnt);
     222                 :            :         } else {
     223         [ #  # ]:          0 :             VLOG_ERR("failed to initialize %s network device class: %s",
     224                 :            :                      new_class->type, ovs_strerror(error));
     225                 :            :         }
     226                 :            :     }
     227                 :       8675 :     ovs_mutex_unlock(&netdev_class_mutex);
     228                 :            : 
     229                 :       8675 :     return error;
     230                 :            : }
     231                 :            : 
     232                 :            : /* Unregisters a netdev provider.  'type' must have been previously registered
     233                 :            :  * and not currently be in use by any netdevs.  After unregistration new
     234                 :            :  * netdevs of that type cannot be opened using netdev_open().  (However, the
     235                 :            :  * provider may still be accessible from other threads until the next RCU grace
     236                 :            :  * period, so the caller must not free or re-register the same netdev_class
     237                 :            :  * until that has passed.) */
     238                 :            : int
     239                 :         90 : netdev_unregister_provider(const char *type)
     240                 :            :     OVS_EXCLUDED(netdev_class_mutex, netdev_mutex)
     241                 :            : {
     242                 :            :     struct netdev_registered_class *rc;
     243                 :            :     int error;
     244                 :            : 
     245                 :         90 :     netdev_initialize();
     246                 :            : 
     247                 :         90 :     ovs_mutex_lock(&netdev_class_mutex);
     248                 :         90 :     rc = netdev_lookup_class(type);
     249         [ -  + ]:         90 :     if (!rc) {
     250         [ #  # ]:          0 :         VLOG_WARN("attempted to unregister a netdev provider that is not "
     251                 :            :                   "registered: %s", type);
     252                 :          0 :         error = EAFNOSUPPORT;
     253         [ -  + ]:         90 :     } else if (ovs_refcount_unref(&rc->refcnt) != 1) {
     254                 :          0 :         ovs_refcount_ref(&rc->refcnt);
     255         [ #  # ]:          0 :         VLOG_WARN("attempted to unregister in use netdev provider: %s",
     256                 :            :                   type);
     257                 :          0 :         error = EBUSY;
     258                 :            :     } else  {
     259                 :         90 :         cmap_remove(&netdev_classes, &rc->cmap_node,
     260                 :         90 :                     hash_string(rc->class->type, 0));
     261                 :         90 :         ovsrcu_postpone(free, rc);
     262                 :         90 :         error = 0;
     263                 :            :     }
     264                 :         90 :     ovs_mutex_unlock(&netdev_class_mutex);
     265                 :            : 
     266                 :         90 :     return error;
     267                 :            : }
     268                 :            : 
     269                 :            : /* Clears 'types' and enumerates the types of all currently registered netdev
     270                 :            :  * providers into it.  The caller must first initialize the sset. */
     271                 :            : void
     272                 :       4232 : netdev_enumerate_types(struct sset *types)
     273                 :            :     OVS_EXCLUDED(netdev_mutex)
     274                 :            : {
     275                 :       4232 :     netdev_initialize();
     276                 :       4232 :     sset_clear(types);
     277                 :            : 
     278                 :            :     struct netdev_registered_class *rc;
     279 [ +  + ][ +  + ]:      53644 :     CMAP_FOR_EACH (rc, cmap_node, &netdev_classes) {
     280                 :      49412 :         sset_add(types, rc->class->type);
     281                 :            :     }
     282                 :       4232 : }
     283                 :            : 
     284                 :            : /* Check that the network device name is not the same as any of the registered
     285                 :            :  * vport providers' dpif_port name (dpif_port is NULL if the vport provider
     286                 :            :  * does not define it) or the datapath internal port name (e.g. ovs-system).
     287                 :            :  *
     288                 :            :  * Returns true if there is a name conflict, false otherwise. */
     289                 :            : bool
     290                 :       2700 : netdev_is_reserved_name(const char *name)
     291                 :            :     OVS_EXCLUDED(netdev_mutex)
     292                 :            : {
     293                 :       2700 :     netdev_initialize();
     294                 :            : 
     295                 :            :     struct netdev_registered_class *rc;
     296 [ +  + ][ +  + ]:      36537 :     CMAP_FOR_EACH (rc, cmap_node, &netdev_classes) {
     297                 :      33845 :         const char *dpif_port = netdev_vport_class_get_dpif_port(rc->class);
     298 [ +  + ][ +  + ]:      33845 :         if (dpif_port && !strncmp(name, dpif_port, strlen(dpif_port))) {
     299                 :          8 :             return true;
     300                 :            :         }
     301                 :            :     }
     302                 :            : 
     303         [ +  + ]:       2692 :     if (!strncmp(name, "ovs-", 4)) {
     304                 :            :         struct sset types;
     305                 :            :         const char *type;
     306                 :            : 
     307                 :        229 :         sset_init(&types);
     308                 :        229 :         dp_enumerate_types(&types);
     309 [ +  - ][ +  + ]:        605 :         SSET_FOR_EACH (type, &types) {
                 [ +  + ]
     310         [ +  + ]:        378 :             if (!strcmp(name+4, type)) {
     311                 :          2 :                 sset_destroy(&types);
     312                 :          2 :                 return true;
     313                 :            :             }
     314                 :            :         }
     315                 :        227 :         sset_destroy(&types);
     316                 :            :     }
     317                 :            : 
     318                 :       2690 :     return false;
     319                 :            : }
     320                 :            : 
     321                 :            : /* Opens the network device named 'name' (e.g. "eth0") of the specified 'type'
     322                 :            :  * (e.g. "system") and returns zero if successful, otherwise a positive errno
     323                 :            :  * value.  On success, sets '*netdevp' to the new network device, otherwise to
     324                 :            :  * null.
     325                 :            :  *
     326                 :            :  * Some network devices may need to be configured (with netdev_set_config())
     327                 :            :  * before they can be used. */
     328                 :            : int
     329                 :      56332 : netdev_open(const char *name, const char *type, struct netdev **netdevp)
     330                 :            :     OVS_EXCLUDED(netdev_mutex)
     331                 :            : {
     332                 :            :     struct netdev *netdev;
     333                 :            :     int error;
     334                 :            : 
     335                 :      56332 :     netdev_initialize();
     336                 :            : 
     337                 :      56332 :     ovs_mutex_lock(&netdev_mutex);
     338                 :      56332 :     netdev = shash_find_data(&netdev_shash, name);
     339         [ +  + ]:      56332 :     if (!netdev) {
     340                 :            :         struct netdev_registered_class *rc;
     341                 :            : 
     342 [ +  + ][ +  - ]:      29084 :         rc = netdev_lookup_class(type && type[0] ? type : "system");
     343 [ +  - ][ +  - ]:      29084 :         if (rc && ovs_refcount_try_ref_rcu(&rc->refcnt)) {
     344                 :      29084 :             netdev = rc->class->alloc();
     345         [ +  - ]:      58168 :             if (netdev) {
     346                 :      29084 :                 memset(netdev, 0, sizeof *netdev);
     347                 :      29084 :                 netdev->netdev_class = rc->class;
     348                 :      29084 :                 netdev->name = xstrdup(name);
     349                 :      29084 :                 netdev->change_seq = 1;
     350                 :      29084 :                 netdev->reconfigure_seq = seq_create();
     351                 :      29084 :                 netdev->last_reconfigure_seq =
     352                 :      29084 :                     seq_read(netdev->reconfigure_seq);
     353                 :      29084 :                 netdev->node = shash_add(&netdev_shash, name, netdev);
     354                 :            : 
     355                 :            :                 /* By default enable one tx and rx queue per netdev. */
     356                 :      29084 :                 netdev->n_txq = netdev->netdev_class->send ? 1 : 0;
     357                 :      29084 :                 netdev->n_rxq = netdev->netdev_class->rxq_alloc ? 1 : 0;
     358                 :            : 
     359                 :      29084 :                 ovs_list_init(&netdev->saved_flags_list);
     360                 :            : 
     361                 :      29084 :                 error = rc->class->construct(netdev);
     362         [ +  - ]:      29084 :                 if (!error) {
     363                 :      29084 :                     netdev_change_seq_changed(netdev);
     364                 :            :                 } else {
     365                 :          0 :                     ovs_refcount_unref(&rc->refcnt);
     366                 :          0 :                     free(netdev->name);
     367         [ #  # ]:          0 :                     ovs_assert(ovs_list_is_empty(&netdev->saved_flags_list));
     368                 :          0 :                     shash_delete(&netdev_shash, netdev->node);
     369                 :      29084 :                     rc->class->dealloc(netdev);
     370                 :            :                 }
     371                 :            :             } else {
     372                 :          0 :                 error = ENOMEM;
     373                 :            :             }
     374                 :            :         } else {
     375         [ #  # ]:          0 :             VLOG_WARN("could not create netdev %s of unknown type %s",
     376                 :            :                       name, type);
     377                 :      29084 :             error = EAFNOSUPPORT;
     378                 :            :         }
     379                 :            :     } else {
     380                 :      27248 :         error = 0;
     381                 :            :     }
     382                 :            : 
     383         [ +  - ]:      56332 :     if (!error) {
     384                 :      56332 :         netdev->ref_cnt++;
     385                 :      56332 :         *netdevp = netdev;
     386                 :            :     } else {
     387                 :          0 :         *netdevp = NULL;
     388                 :            :     }
     389                 :      56332 :     ovs_mutex_unlock(&netdev_mutex);
     390                 :            : 
     391                 :      56332 :     return error;
     392                 :            : }
     393                 :            : 
     394                 :            : /* Returns a reference to 'netdev_' for the caller to own. Returns null if
     395                 :            :  * 'netdev_' is null. */
     396                 :            : struct netdev *
     397                 :     319248 : netdev_ref(const struct netdev *netdev_)
     398                 :            :     OVS_EXCLUDED(netdev_mutex)
     399                 :            : {
     400                 :     319248 :     struct netdev *netdev = CONST_CAST(struct netdev *, netdev_);
     401                 :            : 
     402         [ +  - ]:     319248 :     if (netdev) {
     403                 :     319248 :         ovs_mutex_lock(&netdev_mutex);
     404         [ -  + ]:     319248 :         ovs_assert(netdev->ref_cnt > 0);
     405                 :     319248 :         netdev->ref_cnt++;
     406                 :     319248 :         ovs_mutex_unlock(&netdev_mutex);
     407                 :            :     }
     408                 :     319248 :     return netdev;
     409                 :            : }
     410                 :            : 
     411                 :            : /* Reconfigures the device 'netdev' with 'args'.  'args' may be empty
     412                 :            :  * or NULL if none are needed. */
     413                 :            : int
     414                 :      32002 : netdev_set_config(struct netdev *netdev, const struct smap *args, char **errp)
     415                 :            :     OVS_EXCLUDED(netdev_mutex)
     416                 :            : {
     417         [ +  + ]:      32002 :     if (netdev->netdev_class->set_config) {
     418                 :      27827 :         const struct smap no_args = SMAP_INITIALIZER(&no_args);
     419                 :            :         int error;
     420                 :            : 
     421         [ -  + ]:      27827 :         error = netdev->netdev_class->set_config(netdev,
     422                 :            :                                                  args ? args : &no_args);
     423         [ -  + ]:      27827 :         if (error) {
     424 [ #  # ][ #  # ]:          0 :             VLOG_WARN_BUF(errp, "%s: could not set configuration (%s)",
     425                 :            :                           netdev_get_name(netdev), ovs_strerror(error));
     426                 :            :         }
     427                 :      27827 :         return error;
     428 [ +  - ][ -  + ]:       4175 :     } else if (args && !smap_is_empty(args)) {
     429 [ #  # ][ #  # ]:          0 :         VLOG_WARN_BUF(errp, "%s: arguments provided to device that is not configurable",
     430                 :            :                       netdev_get_name(netdev));
     431                 :            :     }
     432                 :       4175 :     return 0;
     433                 :            : }
     434                 :            : 
     435                 :            : /* Returns the current configuration for 'netdev' in 'args'.  The caller must
     436                 :            :  * have already initialized 'args' with smap_init().  Returns 0 on success, in
     437                 :            :  * which case 'args' will be filled with 'netdev''s configuration.  On failure
     438                 :            :  * returns a positive errno value, in which case 'args' will be empty.
     439                 :            :  *
     440                 :            :  * The caller owns 'args' and its contents and must eventually free them with
     441                 :            :  * smap_destroy(). */
     442                 :            : int
     443                 :        152 : netdev_get_config(const struct netdev *netdev, struct smap *args)
     444                 :            :     OVS_EXCLUDED(netdev_mutex)
     445                 :            : {
     446                 :            :     int error;
     447                 :            : 
     448                 :        152 :     smap_clear(args);
     449         [ +  - ]:        152 :     if (netdev->netdev_class->get_config) {
     450                 :        152 :         error = netdev->netdev_class->get_config(netdev, args);
     451         [ -  + ]:        152 :         if (error) {
     452                 :        152 :             smap_clear(args);
     453                 :            :         }
     454                 :            :     } else {
     455                 :          0 :         error = 0;
     456                 :            :     }
     457                 :            : 
     458                 :        152 :     return error;
     459                 :            : }
     460                 :            : 
     461                 :            : const struct netdev_tunnel_config *
     462                 :      14193 : netdev_get_tunnel_config(const struct netdev *netdev)
     463                 :            :     OVS_EXCLUDED(netdev_mutex)
     464                 :            : {
     465         [ +  + ]:      14193 :     if (netdev->netdev_class->get_tunnel_config) {
     466                 :       7822 :         return netdev->netdev_class->get_tunnel_config(netdev);
     467                 :            :     } else {
     468                 :       6371 :         return NULL;
     469                 :            :     }
     470                 :            : }
     471                 :            : 
     472                 :            : /* Returns the id of the numa node the 'netdev' is on.  If the function
     473                 :            :  * is not implemented, returns NETDEV_NUMA_UNSPEC. */
     474                 :            : int
     475                 :       2599 : netdev_get_numa_id(const struct netdev *netdev)
     476                 :            : {
     477         [ +  + ]:       2599 :     if (netdev->netdev_class->get_numa_id) {
     478                 :       2368 :         return netdev->netdev_class->get_numa_id(netdev);
     479                 :            :     } else {
     480                 :        231 :         return NETDEV_NUMA_UNSPEC;
     481                 :            :     }
     482                 :            : }
     483                 :            : 
     484                 :            : static void
     485                 :     402419 : netdev_unref(struct netdev *dev)
     486                 :            :     OVS_RELEASES(netdev_mutex)
     487                 :            : {
     488         [ -  + ]:     402419 :     ovs_assert(dev->ref_cnt);
     489         [ +  + ]:     402419 :     if (!--dev->ref_cnt) {
     490                 :      26170 :         const struct netdev_class *class = dev->netdev_class;
     491                 :            :         struct netdev_registered_class *rc;
     492                 :            : 
     493                 :      26170 :         dev->netdev_class->destruct(dev);
     494                 :            : 
     495         [ +  + ]:      26170 :         if (dev->node) {
     496                 :      25166 :             shash_delete(&netdev_shash, dev->node);
     497                 :            :         }
     498                 :      26170 :         free(dev->name);
     499                 :      26170 :         seq_destroy(dev->reconfigure_seq);
     500                 :      26170 :         dev->netdev_class->dealloc(dev);
     501                 :      26170 :         ovs_mutex_unlock(&netdev_mutex);
     502                 :            : 
     503                 :      26170 :         rc = netdev_lookup_class(class->type);
     504                 :      26170 :         ovs_refcount_unref(&rc->refcnt);
     505                 :            :     } else {
     506                 :     376249 :         ovs_mutex_unlock(&netdev_mutex);
     507                 :            :     }
     508                 :     402419 : }
     509                 :            : 
     510                 :            : /* Closes and destroys 'netdev'. */
     511                 :            : void
     512                 :     647239 : netdev_close(struct netdev *netdev)
     513                 :            :     OVS_EXCLUDED(netdev_mutex)
     514                 :            : {
     515         [ +  + ]:     647239 :     if (netdev) {
     516                 :     399429 :         ovs_mutex_lock(&netdev_mutex);
     517                 :     399430 :         netdev_unref(netdev);
     518                 :            :     }
     519                 :     647240 : }
     520                 :            : 
     521                 :            : /* Removes 'netdev' from the global shash and unrefs 'netdev'.
     522                 :            :  *
     523                 :            :  * This allows handler and revalidator threads to still retain references
     524                 :            :  * to this netdev while the main thread changes interface configuration.
     525                 :            :  *
     526                 :            :  * This function should only be called by the main thread when closing
     527                 :            :  * netdevs during user configuration changes. Otherwise, netdev_close should be
     528                 :            :  * used to close netdevs. */
     529                 :            : void
     530                 :       2689 : netdev_remove(struct netdev *netdev)
     531                 :            : {
     532         [ +  - ]:       2689 :     if (netdev) {
     533                 :       2689 :         ovs_mutex_lock(&netdev_mutex);
     534         [ +  - ]:       2689 :         if (netdev->node) {
     535                 :       2689 :             shash_delete(&netdev_shash, netdev->node);
     536                 :       2689 :             netdev->node = NULL;
     537                 :       2689 :             netdev_change_seq_changed(netdev);
     538                 :            :         }
     539                 :       2689 :         netdev_unref(netdev);
     540                 :            :     }
     541                 :       2689 : }
     542                 :            : 
     543                 :            : /* Parses 'netdev_name_', which is of the form [type@]name into its component
     544                 :            :  * pieces.  'name' and 'type' must be freed by the caller. */
     545                 :            : void
     546                 :          0 : netdev_parse_name(const char *netdev_name_, char **name, char **type)
     547                 :            : {
     548                 :          0 :     char *netdev_name = xstrdup(netdev_name_);
     549                 :            :     char *separator;
     550                 :            : 
     551                 :          0 :     separator = strchr(netdev_name, '@');
     552         [ #  # ]:          0 :     if (separator) {
     553                 :          0 :         *separator = '\0';
     554                 :          0 :         *type = netdev_name;
     555                 :          0 :         *name = xstrdup(separator + 1);
     556                 :            :     } else {
     557                 :          0 :         *name = netdev_name;
     558                 :          0 :         *type = xstrdup("system");
     559                 :            :     }
     560                 :          0 : }
     561                 :            : 
     562                 :            : /* Attempts to open a netdev_rxq handle for obtaining packets received on
     563                 :            :  * 'netdev'.  On success, returns 0 and stores a nonnull 'netdev_rxq *' into
     564                 :            :  * '*rxp'.  On failure, returns a positive errno value and stores NULL into
     565                 :            :  * '*rxp'.
     566                 :            :  *
     567                 :            :  * Some kinds of network devices might not support receiving packets.  This
     568                 :            :  * function returns EOPNOTSUPP in that case.*/
     569                 :            : int
     570                 :       2406 : netdev_rxq_open(struct netdev *netdev, struct netdev_rxq **rxp, int id)
     571                 :            :     OVS_EXCLUDED(netdev_mutex)
     572                 :            : {
     573                 :            :     int error;
     574                 :            : 
     575 [ +  - ][ +  - ]:       2406 :     if (netdev->netdev_class->rxq_alloc && id < netdev->n_rxq) {
     576                 :       2406 :         struct netdev_rxq *rx = netdev->netdev_class->rxq_alloc();
     577         [ +  - ]:       2406 :         if (rx) {
     578                 :       2406 :             rx->netdev = netdev;
     579                 :       2406 :             rx->queue_id = id;
     580                 :       2406 :             error = netdev->netdev_class->rxq_construct(rx);
     581         [ +  - ]:       2406 :             if (!error) {
     582                 :       2406 :                 netdev_ref(netdev);
     583                 :       2406 :                 *rxp = rx;
     584                 :       2406 :                 return 0;
     585                 :            :             }
     586                 :          0 :             netdev->netdev_class->rxq_dealloc(rx);
     587                 :            :         } else {
     588                 :          0 :             error = ENOMEM;
     589                 :            :         }
     590                 :            :     } else {
     591                 :          0 :         error = EOPNOTSUPP;
     592                 :            :     }
     593                 :            : 
     594                 :          0 :     *rxp = NULL;
     595                 :          0 :     return error;
     596                 :            : }
     597                 :            : 
     598                 :            : /* Closes 'rx'. */
     599                 :            : void
     600                 :        307 : netdev_rxq_close(struct netdev_rxq *rx)
     601                 :            :     OVS_EXCLUDED(netdev_mutex)
     602                 :            : {
     603         [ +  - ]:        307 :     if (rx) {
     604                 :        307 :         struct netdev *netdev = rx->netdev;
     605                 :        307 :         netdev->netdev_class->rxq_destruct(rx);
     606                 :        307 :         netdev->netdev_class->rxq_dealloc(rx);
     607                 :        307 :         netdev_close(netdev);
     608                 :            :     }
     609                 :        307 : }
     610                 :            : 
     611                 :            : /* Attempts to receive a batch of packets from 'rx'.  'batch' should point to
     612                 :            :  * the beginning of an array of NETDEV_MAX_BURST pointers to dp_packet.  If
     613                 :            :  * successful, this function stores pointers to up to NETDEV_MAX_BURST
     614                 :            :  * dp_packets into the array, transferring ownership of the packets to the
     615                 :            :  * caller, stores the number of received packets in 'batch->count', and returns
     616                 :            :  * 0.
     617                 :            :  *
     618                 :            :  * The implementation does not necessarily initialize any non-data members of
     619                 :            :  * 'batch'.  That is, the caller must initialize layer pointers and metadata
     620                 :            :  * itself, if desired, e.g. with pkt_metadata_init() and miniflow_extract().
     621                 :            :  *
     622                 :            :  * Returns EAGAIN immediately if no packet is ready to be received or another
     623                 :            :  * positive errno value if an error was encountered. */
     624                 :            : int
     625                 :   26327704 : netdev_rxq_recv(struct netdev_rxq *rx, struct dp_packet_batch *batch)
     626                 :            : {
     627                 :            :     int retval;
     628                 :            : 
     629                 :   26327704 :     retval = rx->netdev->netdev_class->rxq_recv(rx, batch);
     630         [ +  + ]:    4283598 :     if (!retval) {
     631                 :      10033 :         COVERAGE_INC(netdev_received);
     632                 :            :     } else {
     633                 :    4273565 :         batch->count = 0;
     634                 :            :     }
     635                 :    4280419 :     return retval;
     636                 :            : }
     637                 :            : 
     638                 :            : /* Arranges for poll_block() to wake up when a packet is ready to be received
     639                 :            :  * on 'rx'. */
     640                 :            : void
     641                 :     527419 : netdev_rxq_wait(struct netdev_rxq *rx)
     642                 :            : {
     643                 :     527419 :     rx->netdev->netdev_class->rxq_wait(rx);
     644                 :     527419 : }
     645                 :            : 
     646                 :            : /* Discards any packets ready to be received on 'rx'. */
     647                 :            : int
     648                 :          0 : netdev_rxq_drain(struct netdev_rxq *rx)
     649                 :            : {
     650                 :          0 :     return (rx->netdev->netdev_class->rxq_drain
     651                 :          0 :             ? rx->netdev->netdev_class->rxq_drain(rx)
     652         [ #  # ]:          0 :             : 0);
     653                 :            : }
     654                 :            : 
     655                 :            : /* Configures the number of tx queues of 'netdev'. Returns 0 if successful,
     656                 :            :  * otherwise a positive errno value.
     657                 :            :  *
     658                 :            :  * 'n_txq' specifies the exact number of transmission queues to create.
     659                 :            :  *
     660                 :            :  * The change might not effective immediately.  The caller must check if a
     661                 :            :  * reconfiguration is required with netdev_is_reconf_required() and eventually
     662                 :            :  * call netdev_reconfigure() before using the new queues.
     663                 :            :  *
     664                 :            :  * On error, the tx queue configuration is unchanged */
     665                 :            : int
     666                 :         31 : netdev_set_tx_multiq(struct netdev *netdev, unsigned int n_txq)
     667                 :            : {
     668                 :            :     int error;
     669                 :            : 
     670                 :         62 :     error = (netdev->netdev_class->set_tx_multiq
     671                 :          0 :              ? netdev->netdev_class->set_tx_multiq(netdev, MAX(n_txq, 1))
     672         [ -  + ]:         31 :              : EOPNOTSUPP);
     673                 :            : 
     674 [ +  - ][ -  + ]:         31 :     if (error && error != EOPNOTSUPP) {
     675         [ #  # ]:          0 :         VLOG_DBG_RL(&rl, "failed to set tx queue for network device %s:"
     676                 :            :                     "%s", netdev_get_name(netdev), ovs_strerror(error));
     677                 :            :     }
     678                 :            : 
     679                 :         31 :     return error;
     680                 :            : }
     681                 :            : 
     682                 :            : /* Sends 'batch' on 'netdev'.  Returns 0 if successful (for every packet),
     683                 :            :  * otherwise a positive errno value.  Returns EAGAIN without blocking if
     684                 :            :  * at least one the packets cannot be queued immediately.  Returns EMSGSIZE
     685                 :            :  * if a partial packet was transmitted or if a packet is too big or too small
     686                 :            :  * to transmit on the device.
     687                 :            :  *
     688                 :            :  * If the function returns a non-zero value, some of the packets might have
     689                 :            :  * been sent anyway.
     690                 :            :  *
     691                 :            :  * If 'may_steal' is false, the caller retains ownership of all the packets.
     692                 :            :  * If 'may_steal' is true, the caller transfers ownership of all the packets
     693                 :            :  * to the network device, regardless of success.
     694                 :            :  *
     695                 :            :  * If 'concurrent_txq' is true, the caller may perform concurrent calls
     696                 :            :  * to netdev_send() with the same 'qid'. The netdev provider is responsible
     697                 :            :  * for making sure that these concurrent calls do not create a race condition
     698                 :            :  * by using locking or other synchronization if required.
     699                 :            :  *
     700                 :            :  * The network device is expected to maintain one or more packet
     701                 :            :  * transmission queues, so that the caller does not ordinarily have to
     702                 :            :  * do additional queuing of packets.  'qid' specifies the queue to use
     703                 :            :  * and can be ignored if the implementation does not support multiple
     704                 :            :  * queues.
     705                 :            :  *
     706                 :            :  * Some network devices may not implement support for this function.  In such
     707                 :            :  * cases this function will always return EOPNOTSUPP. */
     708                 :            : int
     709                 :      14580 : netdev_send(struct netdev *netdev, int qid, struct dp_packet_batch *batch,
     710                 :            :             bool may_steal, bool concurrent_txq)
     711                 :            : {
     712         [ +  + ]:      14580 :     if (!netdev->netdev_class->send) {
     713                 :          1 :         dp_packet_delete_batch(batch, may_steal);
     714                 :          1 :         return EOPNOTSUPP;
     715                 :            :     }
     716                 :            : 
     717                 :      14579 :     int error = netdev->netdev_class->send(netdev, qid, batch, may_steal,
     718                 :            :                                            concurrent_txq);
     719         [ +  - ]:      14579 :     if (!error) {
     720                 :      14579 :         COVERAGE_INC(netdev_sent);
     721         [ +  + ]:      14579 :         if (!may_steal) {
     722                 :       5314 :             dp_packet_batch_reset_cutlen(batch);
     723                 :            :         }
     724                 :            :     }
     725                 :      14579 :     return error;
     726                 :            : }
     727                 :            : 
     728                 :            : void
     729                 :       1932 : netdev_pop_header(struct netdev *netdev, struct dp_packet_batch *batch)
     730                 :            : {
     731                 :       1932 :     int i, n_cnt = 0;
     732                 :       1932 :     struct dp_packet **buffers = batch->packets;
     733                 :            : 
     734         [ -  + ]:       1932 :     if (!netdev->netdev_class->pop_header) {
     735                 :          0 :         dp_packet_delete_batch(batch, true);
     736                 :          0 :         batch->count = 0;
     737                 :          0 :         return;
     738                 :            :     }
     739                 :            : 
     740         [ +  + ]:       3864 :     for (i = 0; i < batch->count; i++) {
     741                 :       1932 :         buffers[i] = netdev->netdev_class->pop_header(buffers[i]);
     742         [ +  + ]:       1932 :         if (buffers[i]) {
     743                 :       1930 :             buffers[n_cnt++] = buffers[i];
     744                 :            :         }
     745                 :            :     }
     746                 :       1932 :     batch->count = n_cnt;
     747                 :            : }
     748                 :            : 
     749                 :            : void
     750                 :       2407 : netdev_init_tnl_build_header_params(struct netdev_tnl_build_header_params *params,
     751                 :            :                                     const struct flow *tnl_flow,
     752                 :            :                                     const struct in6_addr *src,
     753                 :            :                                     struct eth_addr dmac,
     754                 :            :                                     struct eth_addr smac)
     755                 :            : {
     756                 :       2407 :     params->flow = tnl_flow;
     757                 :       2407 :     params->dmac = dmac;
     758                 :       2407 :     params->smac = smac;
     759                 :       2407 :     params->s_ip = src;
     760 [ +  + ][ +  - ]:       2407 :     params->is_ipv6 = !IN6_IS_ADDR_V4MAPPED(src);
                 [ +  - ]
     761                 :       2407 : }
     762                 :            : 
     763                 :       2407 : int netdev_build_header(const struct netdev *netdev,
     764                 :            :                         struct ovs_action_push_tnl *data,
     765                 :            :                         const struct netdev_tnl_build_header_params *params)
     766                 :            : {
     767         [ +  - ]:       2407 :     if (netdev->netdev_class->build_header) {
     768                 :       2407 :         return netdev->netdev_class->build_header(netdev, data, params);
     769                 :            :     }
     770                 :          0 :     return EOPNOTSUPP;
     771                 :            : }
     772                 :            : 
     773                 :            : int
     774                 :       1927 : netdev_push_header(const struct netdev *netdev,
     775                 :            :                    struct dp_packet_batch *batch,
     776                 :            :                    const struct ovs_action_push_tnl *data)
     777                 :            : {
     778                 :            :     int i;
     779                 :            : 
     780         [ -  + ]:       1927 :     if (!netdev->netdev_class->push_header) {
     781                 :          0 :         return -EINVAL;
     782                 :            :     }
     783                 :            : 
     784         [ +  + ]:       3854 :     for (i = 0; i < batch->count; i++) {
     785                 :       1927 :         netdev->netdev_class->push_header(batch->packets[i], data);
     786                 :       1927 :         pkt_metadata_init(&batch->packets[i]->md, u32_to_odp(data->out_port));
     787                 :            :     }
     788                 :            : 
     789                 :       1927 :     return 0;
     790                 :            : }
     791                 :            : 
     792                 :            : /* Registers with the poll loop to wake up from the next call to poll_block()
     793                 :            :  * when the packet transmission queue has sufficient room to transmit a packet
     794                 :            :  * with netdev_send().
     795                 :            :  *
     796                 :            :  * The network device is expected to maintain one or more packet
     797                 :            :  * transmission queues, so that the caller does not ordinarily have to
     798                 :            :  * do additional queuing of packets.  'qid' specifies the queue to use
     799                 :            :  * and can be ignored if the implementation does not support multiple
     800                 :            :  * queues. */
     801                 :            : void
     802                 :          0 : netdev_send_wait(struct netdev *netdev, int qid)
     803                 :            : {
     804         [ #  # ]:          0 :     if (netdev->netdev_class->send_wait) {
     805                 :          0 :         netdev->netdev_class->send_wait(netdev, qid);
     806                 :            :     }
     807                 :          0 : }
     808                 :            : 
     809                 :            : /* Attempts to set 'netdev''s MAC address to 'mac'.  Returns 0 if successful,
     810                 :            :  * otherwise a positive errno value. */
     811                 :            : int
     812                 :       4701 : netdev_set_etheraddr(struct netdev *netdev, const struct eth_addr mac)
     813                 :            : {
     814                 :       4701 :     return netdev->netdev_class->set_etheraddr(netdev, mac);
     815                 :            : }
     816                 :            : 
     817                 :            : /* Retrieves 'netdev''s MAC address.  If successful, returns 0 and copies the
     818                 :            :  * the MAC address into 'mac'.  On failure, returns a positive errno value and
     819                 :            :  * clears 'mac' to all-zeros. */
     820                 :            : int
     821                 :      55238 : netdev_get_etheraddr(const struct netdev *netdev, struct eth_addr *mac)
     822                 :            : {
     823                 :      55238 :     return netdev->netdev_class->get_etheraddr(netdev, mac);
     824                 :            : }
     825                 :            : 
     826                 :            : /* Returns the name of the network device that 'netdev' represents,
     827                 :            :  * e.g. "eth0".  The caller must not modify or free the returned string. */
     828                 :            : const char *
     829                 :     382772 : netdev_get_name(const struct netdev *netdev)
     830                 :            : {
     831                 :     382772 :     return netdev->name;
     832                 :            : }
     833                 :            : 
     834                 :            : /* Retrieves the MTU of 'netdev'.  The MTU is the maximum size of transmitted
     835                 :            :  * (and received) packets, in bytes, not including the hardware header; thus,
     836                 :            :  * this is typically 1500 bytes for Ethernet devices.
     837                 :            :  *
     838                 :            :  * If successful, returns 0 and stores the MTU size in '*mtup'.  Returns
     839                 :            :  * EOPNOTSUPP if 'netdev' does not have an MTU (as e.g. some tunnels do not).
     840                 :            :  * On other failure, returns a positive errno value.  On failure, sets '*mtup'
     841                 :            :  * to 0. */
     842                 :            : int
     843                 :      57351 : netdev_get_mtu(const struct netdev *netdev, int *mtup)
     844                 :            : {
     845                 :      57351 :     const struct netdev_class *class = netdev->netdev_class;
     846                 :            :     int error;
     847                 :            : 
     848         [ +  + ]:      57351 :     error = class->get_mtu ? class->get_mtu(netdev, mtup) : EOPNOTSUPP;
     849         [ +  + ]:      57351 :     if (error) {
     850                 :      29858 :         *mtup = 0;
     851         [ +  + ]:      29858 :         if (error != EOPNOTSUPP) {
     852         [ -  + ]:          5 :             VLOG_DBG_RL(&rl, "failed to retrieve MTU for network device %s: "
     853                 :            :                          "%s", netdev_get_name(netdev), ovs_strerror(error));
     854                 :            :         }
     855                 :            :     }
     856                 :      57351 :     return error;
     857                 :            : }
     858                 :            : 
     859                 :            : /* Sets the MTU of 'netdev'.  The MTU is the maximum size of transmitted
     860                 :            :  * (and received) packets, in bytes.
     861                 :            :  *
     862                 :            :  * If successful, returns 0.  Returns EOPNOTSUPP if 'netdev' does not have an
     863                 :            :  * MTU (as e.g. some tunnels do not).  On other failure, returns a positive
     864                 :            :  * errno value. */
     865                 :            : int
     866                 :        427 : netdev_set_mtu(struct netdev *netdev, int mtu)
     867                 :            : {
     868                 :        427 :     const struct netdev_class *class = netdev->netdev_class;
     869                 :            :     int error;
     870                 :            : 
     871         [ +  - ]:        427 :     error = class->set_mtu ? class->set_mtu(netdev, mtu) : EOPNOTSUPP;
     872 [ -  + ][ #  # ]:        427 :     if (error && error != EOPNOTSUPP) {
     873         [ #  # ]:          0 :         VLOG_DBG_RL(&rl, "failed to set MTU for network device %s: %s",
     874                 :            :                      netdev_get_name(netdev), ovs_strerror(error));
     875                 :            :     }
     876                 :            : 
     877                 :        427 :     return error;
     878                 :            : }
     879                 :            : 
     880                 :            : /* If 'user_config' is true, the user wants to control 'netdev''s MTU and we
     881                 :            :  * should not override it.  If 'user_config' is false, we may adjust
     882                 :            :  * 'netdev''s MTU (e.g., if 'netdev' is internal). */
     883                 :            : void
     884                 :      31998 : netdev_mtu_user_config(struct netdev *netdev, bool user_config)
     885                 :            : {
     886         [ +  + ]:      31998 :     if (netdev->mtu_user_config != user_config) {
     887                 :          4 :         netdev_change_seq_changed(netdev);
     888                 :          4 :         netdev->mtu_user_config = user_config;
     889                 :            :     }
     890                 :      31998 : }
     891                 :            : 
     892                 :            : /* Returns 'true' if the user explicitly specified an MTU value for 'netdev'.
     893                 :            :  * Otherwise, returns 'false', in which case we are allowed to adjust the
     894                 :            :  * device MTU. */
     895                 :            : bool
     896                 :       7736 : netdev_mtu_is_user_config(struct netdev *netdev)
     897                 :            : {
     898                 :       7736 :     return netdev->mtu_user_config;
     899                 :            : }
     900                 :            : 
     901                 :            : /* Returns the ifindex of 'netdev', if successful, as a positive number.  On
     902                 :            :  * failure, returns a negative errno value.
     903                 :            :  *
     904                 :            :  * The desired semantics of the ifindex value are a combination of those
     905                 :            :  * specified by POSIX for if_nametoindex() and by SNMP for ifIndex.  An ifindex
     906                 :            :  * value should be unique within a host and remain stable at least until
     907                 :            :  * reboot.  SNMP says an ifindex "ranges between 1 and the value of ifNumber"
     908                 :            :  * but many systems do not follow this rule anyhow.
     909                 :            :  *
     910                 :            :  * Some network devices may not implement support for this function.  In such
     911                 :            :  * cases this function will always return -EOPNOTSUPP.
     912                 :            :  */
     913                 :            : int
     914                 :      35088 : netdev_get_ifindex(const struct netdev *netdev)
     915                 :            : {
     916                 :            :     int (*get_ifindex)(const struct netdev *);
     917                 :            : 
     918                 :      35088 :     get_ifindex = netdev->netdev_class->get_ifindex;
     919                 :            : 
     920         [ +  + ]:      35088 :     return get_ifindex ? get_ifindex(netdev) : -EOPNOTSUPP;
     921                 :            : }
     922                 :            : 
     923                 :            : /* Stores the features supported by 'netdev' into each of '*current',
     924                 :            :  * '*advertised', '*supported', and '*peer' that are non-null.  Each value is a
     925                 :            :  * bitmap of "enum ofp_port_features" bits, in host byte order.  Returns 0 if
     926                 :            :  * successful, otherwise a positive errno value.  On failure, all of the
     927                 :            :  * passed-in values are set to 0.
     928                 :            :  *
     929                 :            :  * Some network devices may not implement support for this function.  In such
     930                 :            :  * cases this function will always return EOPNOTSUPP. */
     931                 :            : int
     932                 :      41865 : netdev_get_features(const struct netdev *netdev,
     933                 :            :                     enum netdev_features *current,
     934                 :            :                     enum netdev_features *advertised,
     935                 :            :                     enum netdev_features *supported,
     936                 :            :                     enum netdev_features *peer)
     937                 :            : {
     938                 :            :     int (*get_features)(const struct netdev *netdev,
     939                 :            :                         enum netdev_features *current,
     940                 :            :                         enum netdev_features *advertised,
     941                 :            :                         enum netdev_features *supported,
     942                 :            :                         enum netdev_features *peer);
     943                 :            :     enum netdev_features dummy[4];
     944                 :            :     int error;
     945                 :            : 
     946         [ -  + ]:      41865 :     if (!current) {
     947                 :          0 :         current = &dummy[0];
     948                 :            :     }
     949         [ +  + ]:      41865 :     if (!advertised) {
     950                 :      34169 :         advertised = &dummy[1];
     951                 :            :     }
     952         [ +  + ]:      41865 :     if (!supported) {
     953                 :      34169 :         supported = &dummy[2];
     954                 :            :     }
     955         [ +  + ]:      41865 :     if (!peer) {
     956                 :      34169 :         peer = &dummy[3];
     957                 :            :     }
     958                 :            : 
     959                 :      41865 :     get_features = netdev->netdev_class->get_features;
     960                 :      41865 :     error = get_features
     961                 :            :                     ? get_features(netdev, current, advertised, supported,
     962                 :            :                                    peer)
     963         [ +  + ]:      41865 :                     : EOPNOTSUPP;
     964         [ +  + ]:      41865 :     if (error) {
     965                 :      37910 :         *current = *advertised = *supported = *peer = 0;
     966                 :            :     }
     967                 :      41865 :     return error;
     968                 :            : }
     969                 :            : 
     970                 :            : /* Returns the maximum speed of a network connection that has the NETDEV_F_*
     971                 :            :  * bits in 'features', in bits per second.  If no bits that indicate a speed
     972                 :            :  * are set in 'features', returns 'default_bps'. */
     973                 :            : uint64_t
     974                 :      18981 : netdev_features_to_bps(enum netdev_features features,
     975                 :            :                        uint64_t default_bps)
     976                 :            : {
     977                 :            :     enum {
     978                 :            :         F_1000000MB = NETDEV_F_1TB_FD,
     979                 :            :         F_100000MB = NETDEV_F_100GB_FD,
     980                 :            :         F_40000MB = NETDEV_F_40GB_FD,
     981                 :            :         F_10000MB = NETDEV_F_10GB_FD,
     982                 :            :         F_1000MB = NETDEV_F_1GB_HD | NETDEV_F_1GB_FD,
     983                 :            :         F_100MB = NETDEV_F_100MB_HD | NETDEV_F_100MB_FD,
     984                 :            :         F_10MB = NETDEV_F_10MB_HD | NETDEV_F_10MB_FD
     985                 :            :     };
     986                 :            : 
     987                 :      18981 :     return (  features & F_1000000MB ? UINT64_C(1000000000000)
     988 [ +  - ][ +  - ]:      18981 :             : features & F_100000MB  ? UINT64_C(100000000000)
         [ +  - ][ +  + ]
         [ +  - ][ +  + ]
                 [ +  + ]
     989                 :      18981 :             : features & F_40000MB   ? UINT64_C(40000000000)
     990                 :      18981 :             : features & F_10000MB   ? UINT64_C(10000000000)
     991                 :      15806 :             : features & F_1000MB    ? UINT64_C(1000000000)
     992                 :      15806 :             : features & F_100MB     ? UINT64_C(100000000)
     993                 :      15796 :             : features & F_10MB      ? UINT64_C(10000000)
     994                 :            :                                      : default_bps);
     995                 :            : }
     996                 :            : 
     997                 :            : /* Returns true if any of the NETDEV_F_* bits that indicate a full-duplex link
     998                 :            :  * are set in 'features', otherwise false. */
     999                 :            : bool
    1000                 :       2998 : netdev_features_is_full_duplex(enum netdev_features features)
    1001                 :            : {
    1002                 :       2998 :     return (features & (NETDEV_F_10MB_FD | NETDEV_F_100MB_FD | NETDEV_F_1GB_FD
    1003                 :            :                         | NETDEV_F_10GB_FD | NETDEV_F_40GB_FD
    1004                 :            :                         | NETDEV_F_100GB_FD | NETDEV_F_1TB_FD)) != 0;
    1005                 :            : }
    1006                 :            : 
    1007                 :            : /* Set the features advertised by 'netdev' to 'advertise'.  Returns 0 if
    1008                 :            :  * successful, otherwise a positive errno value. */
    1009                 :            : int
    1010                 :          0 : netdev_set_advertisements(struct netdev *netdev,
    1011                 :            :                           enum netdev_features advertise)
    1012                 :            : {
    1013                 :          0 :     return (netdev->netdev_class->set_advertisements
    1014                 :          0 :             ? netdev->netdev_class->set_advertisements(
    1015                 :            :                     netdev, advertise)
    1016         [ #  # ]:          0 :             : EOPNOTSUPP);
    1017                 :            : }
    1018                 :            : 
    1019                 :            : /* Assigns 'addr' as 'netdev''s IPv4 address and 'mask' as its netmask.  If
    1020                 :            :  * 'addr' is INADDR_ANY, 'netdev''s IPv4 address is cleared.  Returns a
    1021                 :            :  * positive errno value. */
    1022                 :            : int
    1023                 :          0 : netdev_set_in4(struct netdev *netdev, struct in_addr addr, struct in_addr mask)
    1024                 :            : {
    1025                 :          0 :     return (netdev->netdev_class->set_in4
    1026                 :          0 :             ? netdev->netdev_class->set_in4(netdev, addr, mask)
    1027         [ #  # ]:          0 :             : EOPNOTSUPP);
    1028                 :            : }
    1029                 :            : 
    1030                 :            : /* Obtains ad IPv4 address from device name and save the address in
    1031                 :            :  * in4.  Returns 0 if successful, otherwise a positive errno value.
    1032                 :            :  */
    1033                 :            : int
    1034                 :          2 : netdev_get_in4_by_name(const char *device_name, struct in_addr *in4)
    1035                 :            : {
    1036                 :            :     struct in6_addr *mask, *addr6;
    1037                 :            :     int err, n_in6, i;
    1038                 :            :     struct netdev *dev;
    1039                 :            : 
    1040                 :          2 :     err = netdev_open(device_name, NULL, &dev);
    1041         [ -  + ]:          2 :     if (err) {
    1042                 :          0 :         return err;
    1043                 :            :     }
    1044                 :            : 
    1045                 :          2 :     err = netdev_get_addr_list(dev, &addr6, &mask, &n_in6);
    1046         [ -  + ]:          2 :     if (err) {
    1047                 :          0 :         goto out;
    1048                 :            :     }
    1049                 :            : 
    1050         [ +  - ]:          2 :     for (i = 0; i < n_in6; i++) {
    1051 [ +  - ][ +  - ]:          2 :         if (IN6_IS_ADDR_V4MAPPED(&addr6[i])) {
         [ +  - ][ +  - ]
    1052                 :          2 :             in4->s_addr = in6_addr_get_mapped_ipv4(&addr6[i]);
    1053                 :          2 :             goto out;
    1054                 :            :         }
    1055                 :            :     }
    1056                 :          0 :     err = -ENOENT;
    1057                 :            : out:
    1058                 :          2 :     free(addr6);
    1059                 :          2 :     free(mask);
    1060                 :          2 :     netdev_close(dev);
    1061                 :          2 :     return err;
    1062                 :            : 
    1063                 :            : }
    1064                 :            : 
    1065                 :            : /* Adds 'router' as a default IP gateway for the TCP/IP stack that corresponds
    1066                 :            :  * to 'netdev'. */
    1067                 :            : int
    1068                 :          0 : netdev_add_router(struct netdev *netdev, struct in_addr router)
    1069                 :            : {
    1070                 :          0 :     COVERAGE_INC(netdev_add_router);
    1071                 :          0 :     return (netdev->netdev_class->add_router
    1072                 :          0 :             ? netdev->netdev_class->add_router(netdev, router)
    1073         [ #  # ]:          0 :             : EOPNOTSUPP);
    1074                 :            : }
    1075                 :            : 
    1076                 :            : /* Looks up the next hop for 'host' for the TCP/IP stack that corresponds to
    1077                 :            :  * 'netdev'.  If a route cannot not be determined, sets '*next_hop' to 0,
    1078                 :            :  * '*netdev_name' to null, and returns a positive errno value.  Otherwise, if a
    1079                 :            :  * next hop is found, stores the next hop gateway's address (0 if 'host' is on
    1080                 :            :  * a directly connected network) in '*next_hop' and a copy of the name of the
    1081                 :            :  * device to reach 'host' in '*netdev_name', and returns 0.  The caller is
    1082                 :            :  * responsible for freeing '*netdev_name' (by calling free()). */
    1083                 :            : int
    1084                 :         12 : netdev_get_next_hop(const struct netdev *netdev,
    1085                 :            :                     const struct in_addr *host, struct in_addr *next_hop,
    1086                 :            :                     char **netdev_name)
    1087                 :            : {
    1088                 :         24 :     int error = (netdev->netdev_class->get_next_hop
    1089                 :          0 :                  ? netdev->netdev_class->get_next_hop(
    1090                 :            :                         host, next_hop, netdev_name)
    1091         [ -  + ]:         12 :                  : EOPNOTSUPP);
    1092         [ +  - ]:         12 :     if (error) {
    1093                 :         12 :         next_hop->s_addr = 0;
    1094                 :         12 :         *netdev_name = NULL;
    1095                 :            :     }
    1096                 :         12 :     return error;
    1097                 :            : }
    1098                 :            : 
    1099                 :            : /* Populates 'smap' with status information.
    1100                 :            :  *
    1101                 :            :  * Populates 'smap' with 'netdev' specific status information.  This
    1102                 :            :  * information may be used to populate the status column of the Interface table
    1103                 :            :  * as defined in ovs-vswitchd.conf.db(5). */
    1104                 :            : int
    1105                 :      34140 : netdev_get_status(const struct netdev *netdev, struct smap *smap)
    1106                 :            : {
    1107                 :      34140 :     return (netdev->netdev_class->get_status
    1108                 :      24895 :             ? netdev->netdev_class->get_status(netdev, smap)
    1109         [ +  + ]:      34140 :             : EOPNOTSUPP);
    1110                 :            : }
    1111                 :            : 
    1112                 :            : /* Returns all assigned IP address to  'netdev' and returns 0.
    1113                 :            :  * API allocates array of address and masks and set it to
    1114                 :            :  * '*addr' and '*mask'.
    1115                 :            :  * Otherwise, returns a positive errno value and sets '*addr', '*mask
    1116                 :            :  * and '*n_addr' to NULL.
    1117                 :            :  *
    1118                 :            :  * The following error values have well-defined meanings:
    1119                 :            :  *
    1120                 :            :  *   - EADDRNOTAVAIL: 'netdev' has no assigned IPv6 address.
    1121                 :            :  *
    1122                 :            :  *   - EOPNOTSUPP: No IPv6 network stack attached to 'netdev'.
    1123                 :            :  *
    1124                 :            :  * 'addr' may be null, in which case the address itself is not reported. */
    1125                 :            : int
    1126                 :      43078 : netdev_get_addr_list(const struct netdev *netdev, struct in6_addr **addr,
    1127                 :            :                      struct in6_addr **mask, int *n_addr)
    1128                 :            : {
    1129                 :            :     int error;
    1130                 :            : 
    1131                 :      86156 :     error = (netdev->netdev_class->get_addr_list
    1132         [ +  - ]:      43078 :              ? netdev->netdev_class->get_addr_list(netdev, addr, mask, n_addr): EOPNOTSUPP);
    1133 [ +  + ][ +  - ]:      43078 :     if (error && addr) {
    1134                 :        738 :         *addr = NULL;
    1135                 :        738 :         *mask = NULL;
    1136                 :        738 :         *n_addr = 0;
    1137                 :            :     }
    1138                 :            : 
    1139                 :      43078 :     return error;
    1140                 :            : }
    1141                 :            : 
    1142                 :            : /* On 'netdev', turns off the flags in 'off' and then turns on the flags in
    1143                 :            :  * 'on'.  Returns 0 if successful, otherwise a positive errno value. */
    1144                 :            : static int
    1145                 :     154215 : do_update_flags(struct netdev *netdev, enum netdev_flags off,
    1146                 :            :                 enum netdev_flags on, enum netdev_flags *old_flagsp,
    1147                 :            :                 struct netdev_saved_flags **sfp)
    1148                 :            :     OVS_EXCLUDED(netdev_mutex)
    1149                 :            : {
    1150                 :     154215 :     struct netdev_saved_flags *sf = NULL;
    1151                 :            :     enum netdev_flags old_flags;
    1152                 :            :     int error;
    1153                 :            : 
    1154                 :     154215 :     error = netdev->netdev_class->update_flags(netdev, off & ~on, on,
    1155                 :            :                                                &old_flags);
    1156         [ -  + ]:     154215 :     if (error) {
    1157 [ #  # ][ #  # ]:          0 :         VLOG_WARN_RL(&rl, "failed to %s flags for network device %s: %s",
                 [ #  # ]
    1158                 :            :                      off || on ? "set" : "get", netdev_get_name(netdev),
    1159                 :            :                      ovs_strerror(error));
    1160                 :          0 :         old_flags = 0;
    1161 [ +  + ][ +  + ]:     154215 :     } else if ((off || on) && sfp) {
                 [ +  + ]
    1162                 :       2458 :         enum netdev_flags new_flags = (old_flags & ~off) | on;
    1163                 :       2458 :         enum netdev_flags changed_flags = old_flags ^ new_flags;
    1164         [ +  + ]:       2458 :         if (changed_flags) {
    1165                 :       2373 :             ovs_mutex_lock(&netdev_mutex);
    1166                 :       2373 :             *sfp = sf = xmalloc(sizeof *sf);
    1167                 :       2373 :             sf->netdev = netdev;
    1168                 :       2373 :             ovs_list_push_front(&netdev->saved_flags_list, &sf->node);
    1169                 :       2373 :             sf->saved_flags = changed_flags;
    1170                 :       2373 :             sf->saved_values = changed_flags & new_flags;
    1171                 :            : 
    1172                 :       2373 :             netdev->ref_cnt++;
    1173                 :       2373 :             ovs_mutex_unlock(&netdev_mutex);
    1174                 :            :         }
    1175                 :            :     }
    1176                 :            : 
    1177         [ +  + ]:     154215 :     if (old_flagsp) {
    1178                 :     151739 :         *old_flagsp = old_flags;
    1179                 :            :     }
    1180         [ +  + ]:     154215 :     if (sfp) {
    1181                 :       2458 :         *sfp = sf;
    1182                 :            :     }
    1183                 :            : 
    1184                 :     154215 :     return error;
    1185                 :            : }
    1186                 :            : 
    1187                 :            : /* Obtains the current flags for 'netdev' and stores them into '*flagsp'.
    1188                 :            :  * Returns 0 if successful, otherwise a positive errno value.  On failure,
    1189                 :            :  * stores 0 into '*flagsp'. */
    1190                 :            : int
    1191                 :     151739 : netdev_get_flags(const struct netdev *netdev_, enum netdev_flags *flagsp)
    1192                 :            : {
    1193                 :     151739 :     struct netdev *netdev = CONST_CAST(struct netdev *, netdev_);
    1194                 :     151739 :     return do_update_flags(netdev, 0, 0, flagsp, NULL);
    1195                 :            : }
    1196                 :            : 
    1197                 :            : /* Sets the flags for 'netdev' to 'flags'.
    1198                 :            :  * Returns 0 if successful, otherwise a positive errno value. */
    1199                 :            : int
    1200                 :          0 : netdev_set_flags(struct netdev *netdev, enum netdev_flags flags,
    1201                 :            :                  struct netdev_saved_flags **sfp)
    1202                 :            : {
    1203                 :          0 :     return do_update_flags(netdev, -1, flags, NULL, sfp);
    1204                 :            : }
    1205                 :            : 
    1206                 :            : /* Turns on the specified 'flags' on 'netdev':
    1207                 :            :  *
    1208                 :            :  *    - On success, returns 0.  If 'sfp' is nonnull, sets '*sfp' to a newly
    1209                 :            :  *      allocated 'struct netdev_saved_flags *' that may be passed to
    1210                 :            :  *      netdev_restore_flags() to restore the original values of 'flags' on
    1211                 :            :  *      'netdev' (this will happen automatically at program termination if
    1212                 :            :  *      netdev_restore_flags() is never called) , or to NULL if no flags were
    1213                 :            :  *      actually changed.
    1214                 :            :  *
    1215                 :            :  *    - On failure, returns a positive errno value.  If 'sfp' is nonnull, sets
    1216                 :            :  *      '*sfp' to NULL. */
    1217                 :            : int
    1218                 :       2473 : netdev_turn_flags_on(struct netdev *netdev, enum netdev_flags flags,
    1219                 :            :                      struct netdev_saved_flags **sfp)
    1220                 :            : {
    1221                 :       2473 :     return do_update_flags(netdev, 0, flags, NULL, sfp);
    1222                 :            : }
    1223                 :            : 
    1224                 :            : /* Turns off the specified 'flags' on 'netdev'.  See netdev_turn_flags_on() for
    1225                 :            :  * details of the interface. */
    1226                 :            : int
    1227                 :          3 : netdev_turn_flags_off(struct netdev *netdev, enum netdev_flags flags,
    1228                 :            :                       struct netdev_saved_flags **sfp)
    1229                 :            : {
    1230                 :          3 :     return do_update_flags(netdev, flags, 0, NULL, sfp);
    1231                 :            : }
    1232                 :            : 
    1233                 :            : /* Restores the flags that were saved in 'sf', and destroys 'sf'.
    1234                 :            :  * Does nothing if 'sf' is NULL. */
    1235                 :            : void
    1236                 :        335 : netdev_restore_flags(struct netdev_saved_flags *sf)
    1237                 :            :     OVS_EXCLUDED(netdev_mutex)
    1238                 :            : {
    1239         [ +  + ]:        335 :     if (sf) {
    1240                 :        300 :         struct netdev *netdev = sf->netdev;
    1241                 :            :         enum netdev_flags old_flags;
    1242                 :            : 
    1243                 :        300 :         netdev->netdev_class->update_flags(netdev,
    1244                 :        300 :                                            sf->saved_flags & sf->saved_values,
    1245                 :        300 :                                            sf->saved_flags & ~sf->saved_values,
    1246                 :            :                                            &old_flags);
    1247                 :            : 
    1248                 :        300 :         ovs_mutex_lock(&netdev_mutex);
    1249                 :        300 :         ovs_list_remove(&sf->node);
    1250                 :        300 :         free(sf);
    1251                 :        300 :         netdev_unref(netdev);
    1252                 :            :     }
    1253                 :        335 : }
    1254                 :            : 
    1255                 :            : /* Looks up the ARP table entry for 'ip' on 'netdev'.  If one exists and can be
    1256                 :            :  * successfully retrieved, it stores the corresponding MAC address in 'mac' and
    1257                 :            :  * returns 0.  Otherwise, it returns a positive errno value; in particular,
    1258                 :            :  * ENXIO indicates that there is no ARP table entry for 'ip' on 'netdev'. */
    1259                 :            : int
    1260                 :          0 : netdev_arp_lookup(const struct netdev *netdev,
    1261                 :            :                   ovs_be32 ip, struct eth_addr *mac)
    1262                 :            : {
    1263                 :          0 :     int error = (netdev->netdev_class->arp_lookup
    1264                 :          0 :                  ? netdev->netdev_class->arp_lookup(netdev, ip, mac)
    1265         [ #  # ]:          0 :                  : EOPNOTSUPP);
    1266         [ #  # ]:          0 :     if (error) {
    1267                 :          0 :         *mac = eth_addr_zero;
    1268                 :            :     }
    1269                 :          0 :     return error;
    1270                 :            : }
    1271                 :            : 
    1272                 :            : /* Returns true if carrier is active (link light is on) on 'netdev'. */
    1273                 :            : bool
    1274                 :      92831 : netdev_get_carrier(const struct netdev *netdev)
    1275                 :            : {
    1276                 :            :     int error;
    1277                 :            :     enum netdev_flags flags;
    1278                 :            :     bool carrier;
    1279                 :            : 
    1280                 :      92831 :     netdev_get_flags(netdev, &flags);
    1281         [ +  + ]:      92831 :     if (!(flags & NETDEV_UP)) {
    1282                 :      23724 :         return false;
    1283                 :            :     }
    1284                 :            : 
    1285         [ +  + ]:      69107 :     if (!netdev->netdev_class->get_carrier) {
    1286                 :      61165 :         return true;
    1287                 :            :     }
    1288                 :            : 
    1289                 :       7942 :     error = netdev->netdev_class->get_carrier(netdev, &carrier);
    1290         [ -  + ]:       7942 :     if (error) {
    1291         [ #  # ]:          0 :         VLOG_DBG("%s: failed to get network device carrier status, assuming "
    1292                 :            :                  "down: %s", netdev_get_name(netdev), ovs_strerror(error));
    1293                 :          0 :         carrier = false;
    1294                 :            :     }
    1295                 :            : 
    1296                 :      92831 :     return carrier;
    1297                 :            : }
    1298                 :            : 
    1299                 :            : /* Returns the number of times 'netdev''s carrier has changed. */
    1300                 :            : long long int
    1301                 :      72658 : netdev_get_carrier_resets(const struct netdev *netdev)
    1302                 :            : {
    1303                 :      72658 :     return (netdev->netdev_class->get_carrier_resets
    1304                 :      11021 :             ? netdev->netdev_class->get_carrier_resets(netdev)
    1305         [ +  + ]:      72658 :             : 0);
    1306                 :            : }
    1307                 :            : 
    1308                 :            : /* Attempts to force netdev_get_carrier() to poll 'netdev''s MII registers for
    1309                 :            :  * link status instead of checking 'netdev''s carrier.  'netdev''s MII
    1310                 :            :  * registers will be polled once ever 'interval' milliseconds.  If 'netdev'
    1311                 :            :  * does not support MII, another method may be used as a fallback.  If
    1312                 :            :  * 'interval' is less than or equal to zero, reverts netdev_get_carrier() to
    1313                 :            :  * its normal behavior.
    1314                 :            :  *
    1315                 :            :  * Returns 0 if successful, otherwise a positive errno value. */
    1316                 :            : int
    1317                 :      31837 : netdev_set_miimon_interval(struct netdev *netdev, long long int interval)
    1318                 :            : {
    1319                 :      31837 :     return (netdev->netdev_class->set_miimon_interval
    1320                 :       4175 :             ? netdev->netdev_class->set_miimon_interval(netdev, interval)
    1321         [ +  + ]:      31837 :             : EOPNOTSUPP);
    1322                 :            : }
    1323                 :            : 
    1324                 :            : /* Retrieves current device stats for 'netdev'. */
    1325                 :            : int
    1326                 :       8701 : netdev_get_stats(const struct netdev *netdev, struct netdev_stats *stats)
    1327                 :            : {
    1328                 :            :     int error;
    1329                 :            : 
    1330                 :            :     /* Statistics are initialized before passing it to particular device
    1331                 :            :      * implementation so all values are filtered out by default. */
    1332                 :       8701 :     memset(stats, 0xFF, sizeof *stats);
    1333                 :            : 
    1334                 :       8701 :     COVERAGE_INC(netdev_get_stats);
    1335                 :      17402 :     error = (netdev->netdev_class->get_stats
    1336                 :       8701 :              ? netdev->netdev_class->get_stats(netdev, stats)
    1337         [ +  - ]:       8701 :              : EOPNOTSUPP);
    1338         [ -  + ]:       8701 :     if (error) {
    1339                 :            :         /* In case of error all statistics are filtered out */
    1340                 :          0 :         memset(stats, 0xff, sizeof *stats);
    1341                 :            :     }
    1342                 :       8701 :     return error;
    1343                 :            : }
    1344                 :            : 
    1345                 :            : /* Attempts to set input rate limiting (policing) policy, such that up to
    1346                 :            :  * 'kbits_rate' kbps of traffic is accepted, with a maximum accumulative burst
    1347                 :            :  * size of 'kbits' kb. */
    1348                 :            : int
    1349                 :      31837 : netdev_set_policing(struct netdev *netdev, uint32_t kbits_rate,
    1350                 :            :                     uint32_t kbits_burst)
    1351                 :            : {
    1352                 :      31837 :     return (netdev->netdev_class->set_policing
    1353                 :       4175 :             ? netdev->netdev_class->set_policing(netdev,
    1354                 :            :                     kbits_rate, kbits_burst)
    1355         [ +  + ]:      31837 :             : EOPNOTSUPP);
    1356                 :            : }
    1357                 :            : 
    1358                 :            : /* Adds to 'types' all of the forms of QoS supported by 'netdev', or leaves it
    1359                 :            :  * empty if 'netdev' does not support QoS.  Any names added to 'types' should
    1360                 :            :  * be documented as valid for the "type" column in the "QoS" table in
    1361                 :            :  * vswitchd/vswitch.xml (which is built as ovs-vswitchd.conf.db(8)).
    1362                 :            :  *
    1363                 :            :  * Every network device supports disabling QoS with a type of "", but this type
    1364                 :            :  * will not be added to 'types'.
    1365                 :            :  *
    1366                 :            :  * The caller must initialize 'types' (e.g. with sset_init()) before calling
    1367                 :            :  * this function.  The caller is responsible for destroying 'types' (e.g. with
    1368                 :            :  * sset_destroy()) when it is no longer needed.
    1369                 :            :  *
    1370                 :            :  * Returns 0 if successful, otherwise a positive errno value. */
    1371                 :            : int
    1372                 :          0 : netdev_get_qos_types(const struct netdev *netdev, struct sset *types)
    1373                 :            : {
    1374                 :          0 :     const struct netdev_class *class = netdev->netdev_class;
    1375                 :          0 :     return (class->get_qos_types
    1376                 :          0 :             ? class->get_qos_types(netdev, types)
    1377         [ #  # ]:          0 :             : 0);
    1378                 :            : }
    1379                 :            : 
    1380                 :            : /* Queries 'netdev' for its capabilities regarding the specified 'type' of QoS,
    1381                 :            :  * which should be "" or one of the types returned by netdev_get_qos_types()
    1382                 :            :  * for 'netdev'.  Returns 0 if successful, otherwise a positive errno value.
    1383                 :            :  * On success, initializes 'caps' with the QoS capabilities; on failure, clears
    1384                 :            :  * 'caps' to all zeros. */
    1385                 :            : int
    1386                 :          0 : netdev_get_qos_capabilities(const struct netdev *netdev, const char *type,
    1387                 :            :                             struct netdev_qos_capabilities *caps)
    1388                 :            : {
    1389                 :          0 :     const struct netdev_class *class = netdev->netdev_class;
    1390                 :            : 
    1391         [ #  # ]:          0 :     if (*type) {
    1392                 :          0 :         int retval = (class->get_qos_capabilities
    1393                 :          0 :                       ? class->get_qos_capabilities(netdev, type, caps)
    1394         [ #  # ]:          0 :                       : EOPNOTSUPP);
    1395         [ #  # ]:          0 :         if (retval) {
    1396                 :          0 :             memset(caps, 0, sizeof *caps);
    1397                 :            :         }
    1398                 :          0 :         return retval;
    1399                 :            :     } else {
    1400                 :            :         /* Every netdev supports turning off QoS. */
    1401                 :          0 :         memset(caps, 0, sizeof *caps);
    1402                 :          0 :         return 0;
    1403                 :            :     }
    1404                 :            : }
    1405                 :            : 
    1406                 :            : /* Obtains the number of queues supported by 'netdev' for the specified 'type'
    1407                 :            :  * of QoS.  Returns 0 if successful, otherwise a positive errno value.  Stores
    1408                 :            :  * the number of queues (zero on failure) in '*n_queuesp'.
    1409                 :            :  *
    1410                 :            :  * This is just a simple wrapper around netdev_get_qos_capabilities(). */
    1411                 :            : int
    1412                 :          0 : netdev_get_n_queues(const struct netdev *netdev,
    1413                 :            :                     const char *type, unsigned int *n_queuesp)
    1414                 :            : {
    1415                 :            :     struct netdev_qos_capabilities caps;
    1416                 :            :     int retval;
    1417                 :            : 
    1418                 :          0 :     retval = netdev_get_qos_capabilities(netdev, type, &caps);
    1419                 :          0 :     *n_queuesp = caps.n_queues;
    1420                 :          0 :     return retval;
    1421                 :            : }
    1422                 :            : 
    1423                 :            : /* Queries 'netdev' about its currently configured form of QoS.  If successful,
    1424                 :            :  * stores the name of the current form of QoS into '*typep', stores any details
    1425                 :            :  * of configuration as string key-value pairs in 'details', and returns 0.  On
    1426                 :            :  * failure, sets '*typep' to NULL and returns a positive errno value.
    1427                 :            :  *
    1428                 :            :  * A '*typep' of "" indicates that QoS is currently disabled on 'netdev'.
    1429                 :            :  *
    1430                 :            :  * The caller must initialize 'details' as an empty smap (e.g. with
    1431                 :            :  * smap_init()) before calling this function.  The caller must free 'details'
    1432                 :            :  * when it is no longer needed (e.g. with smap_destroy()).
    1433                 :            :  *
    1434                 :            :  * The caller must not modify or free '*typep'.
    1435                 :            :  *
    1436                 :            :  * '*typep' will be one of the types returned by netdev_get_qos_types() for
    1437                 :            :  * 'netdev'.  The contents of 'details' should be documented as valid for
    1438                 :            :  * '*typep' in the "other_config" column in the "QoS" table in
    1439                 :            :  * vswitchd/vswitch.xml (which is built as ovs-vswitchd.conf.db(8)). */
    1440                 :            : int
    1441                 :          0 : netdev_get_qos(const struct netdev *netdev,
    1442                 :            :                const char **typep, struct smap *details)
    1443                 :            : {
    1444                 :          0 :     const struct netdev_class *class = netdev->netdev_class;
    1445                 :            :     int retval;
    1446                 :            : 
    1447         [ #  # ]:          0 :     if (class->get_qos) {
    1448                 :          0 :         retval = class->get_qos(netdev, typep, details);
    1449         [ #  # ]:          0 :         if (retval) {
    1450                 :          0 :             *typep = NULL;
    1451                 :          0 :             smap_clear(details);
    1452                 :            :         }
    1453                 :          0 :         return retval;
    1454                 :            :     } else {
    1455                 :            :         /* 'netdev' doesn't support QoS, so report that QoS is disabled. */
    1456                 :          0 :         *typep = "";
    1457                 :          0 :         return 0;
    1458                 :            :     }
    1459                 :            : }
    1460                 :            : 
    1461                 :            : /* Attempts to reconfigure QoS on 'netdev', changing the form of QoS to 'type'
    1462                 :            :  * with details of configuration from 'details'.  Returns 0 if successful,
    1463                 :            :  * otherwise a positive errno value.  On error, the previous QoS configuration
    1464                 :            :  * is retained.
    1465                 :            :  *
    1466                 :            :  * When this function changes the type of QoS (not just 'details'), this also
    1467                 :            :  * resets all queue configuration for 'netdev' to their defaults (which depend
    1468                 :            :  * on the specific type of QoS).  Otherwise, the queue configuration for
    1469                 :            :  * 'netdev' is unchanged.
    1470                 :            :  *
    1471                 :            :  * 'type' should be "" (to disable QoS) or one of the types returned by
    1472                 :            :  * netdev_get_qos_types() for 'netdev'.  The contents of 'details' should be
    1473                 :            :  * documented as valid for the given 'type' in the "other_config" column in the
    1474                 :            :  * "QoS" table in vswitchd/vswitch.xml (which is built as
    1475                 :            :  * ovs-vswitchd.conf.db(8)).
    1476                 :            :  *
    1477                 :            :  * NULL may be specified for 'details' if there are no configuration
    1478                 :            :  * details. */
    1479                 :            : int
    1480                 :      31837 : netdev_set_qos(struct netdev *netdev,
    1481                 :            :                const char *type, const struct smap *details)
    1482                 :            : {
    1483                 :      31837 :     const struct netdev_class *class = netdev->netdev_class;
    1484                 :            : 
    1485         [ +  + ]:      31837 :     if (!type) {
    1486                 :      31836 :         type = "";
    1487                 :            :     }
    1488                 :            : 
    1489         [ +  + ]:      31837 :     if (class->set_qos) {
    1490         [ +  - ]:       4175 :         if (!details) {
    1491                 :            :             static const struct smap empty = SMAP_INITIALIZER(&empty);
    1492                 :       4175 :             details = &empty;
    1493                 :            :         }
    1494                 :       4175 :         return class->set_qos(netdev, type, details);
    1495                 :            :     } else {
    1496         [ +  + ]:      27662 :         return *type ? EOPNOTSUPP : 0;
    1497                 :            :     }
    1498                 :            : }
    1499                 :            : 
    1500                 :            : /* Queries 'netdev' for information about the queue numbered 'queue_id'.  If
    1501                 :            :  * successful, adds that information as string key-value pairs to 'details'.
    1502                 :            :  * Returns 0 if successful, otherwise a positive errno value.
    1503                 :            :  *
    1504                 :            :  * 'queue_id' must be less than the number of queues supported by 'netdev' for
    1505                 :            :  * the current form of QoS (e.g. as returned by netdev_get_n_queues(netdev)).
    1506                 :            :  *
    1507                 :            :  * The returned contents of 'details' should be documented as valid for the
    1508                 :            :  * given 'type' in the "other_config" column in the "Queue" table in
    1509                 :            :  * vswitchd/vswitch.xml (which is built as ovs-vswitchd.conf.db(8)).
    1510                 :            :  *
    1511                 :            :  * The caller must initialize 'details' (e.g. with smap_init()) before calling
    1512                 :            :  * this function.  The caller must free 'details' when it is no longer needed
    1513                 :            :  * (e.g. with smap_destroy()). */
    1514                 :            : int
    1515                 :          1 : netdev_get_queue(const struct netdev *netdev,
    1516                 :            :                  unsigned int queue_id, struct smap *details)
    1517                 :            : {
    1518                 :          1 :     const struct netdev_class *class = netdev->netdev_class;
    1519                 :            :     int retval;
    1520                 :            : 
    1521                 :          2 :     retval = (class->get_queue
    1522                 :          1 :               ? class->get_queue(netdev, queue_id, details)
    1523         [ +  - ]:          1 :               : EOPNOTSUPP);
    1524         [ +  - ]:          1 :     if (retval) {
    1525                 :          1 :         smap_clear(details);
    1526                 :            :     }
    1527                 :          1 :     return retval;
    1528                 :            : }
    1529                 :            : 
    1530                 :            : /* Configures the queue numbered 'queue_id' on 'netdev' with the key-value
    1531                 :            :  * string pairs in 'details'.  The contents of 'details' should be documented
    1532                 :            :  * as valid for the given 'type' in the "other_config" column in the "Queue"
    1533                 :            :  * table in vswitchd/vswitch.xml (which is built as ovs-vswitchd.conf.db(8)).
    1534                 :            :  * Returns 0 if successful, otherwise a positive errno value.  On failure, the
    1535                 :            :  * given queue's configuration should be unmodified.
    1536                 :            :  *
    1537                 :            :  * 'queue_id' must be less than the number of queues supported by 'netdev' for
    1538                 :            :  * the current form of QoS (e.g. as returned by netdev_get_n_queues(netdev)).
    1539                 :            :  *
    1540                 :            :  * This function does not modify 'details', and the caller retains ownership of
    1541                 :            :  * it. */
    1542                 :            : int
    1543                 :          3 : netdev_set_queue(struct netdev *netdev,
    1544                 :            :                  unsigned int queue_id, const struct smap *details)
    1545                 :            : {
    1546                 :          3 :     const struct netdev_class *class = netdev->netdev_class;
    1547                 :          3 :     return (class->set_queue
    1548                 :          0 :             ? class->set_queue(netdev, queue_id, details)
    1549         [ -  + ]:          3 :             : EOPNOTSUPP);
    1550                 :            : }
    1551                 :            : 
    1552                 :            : /* Attempts to delete the queue numbered 'queue_id' from 'netdev'.  Some kinds
    1553                 :            :  * of QoS may have a fixed set of queues, in which case attempts to delete them
    1554                 :            :  * will fail with EOPNOTSUPP.
    1555                 :            :  *
    1556                 :            :  * Returns 0 if successful, otherwise a positive errno value.  On failure, the
    1557                 :            :  * given queue will be unmodified.
    1558                 :            :  *
    1559                 :            :  * 'queue_id' must be less than the number of queues supported by 'netdev' for
    1560                 :            :  * the current form of QoS (e.g. as returned by
    1561                 :            :  * netdev_get_n_queues(netdev)). */
    1562                 :            : int
    1563                 :          1 : netdev_delete_queue(struct netdev *netdev, unsigned int queue_id)
    1564                 :            : {
    1565                 :          1 :     const struct netdev_class *class = netdev->netdev_class;
    1566                 :          1 :     return (class->delete_queue
    1567                 :          0 :             ? class->delete_queue(netdev, queue_id)
    1568         [ -  + ]:          1 :             : EOPNOTSUPP);
    1569                 :            : }
    1570                 :            : 
    1571                 :            : /* Obtains statistics about 'queue_id' on 'netdev'.  On success, returns 0 and
    1572                 :            :  * fills 'stats' with the queue's statistics; individual members of 'stats' may
    1573                 :            :  * be set to all-1-bits if the statistic is unavailable.  On failure, returns a
    1574                 :            :  * positive errno value and fills 'stats' with values indicating unsupported
    1575                 :            :  * statistics. */
    1576                 :            : int
    1577                 :         20 : netdev_get_queue_stats(const struct netdev *netdev, unsigned int queue_id,
    1578                 :            :                        struct netdev_queue_stats *stats)
    1579                 :            : {
    1580                 :         20 :     const struct netdev_class *class = netdev->netdev_class;
    1581                 :            :     int retval;
    1582                 :            : 
    1583                 :         40 :     retval = (class->get_queue_stats
    1584                 :         20 :               ? class->get_queue_stats(netdev, queue_id, stats)
    1585         [ +  - ]:         20 :               : EOPNOTSUPP);
    1586         [ +  + ]:         20 :     if (retval) {
    1587                 :         10 :         stats->tx_bytes = UINT64_MAX;
    1588                 :         10 :         stats->tx_packets = UINT64_MAX;
    1589                 :         10 :         stats->tx_errors = UINT64_MAX;
    1590                 :         10 :         stats->created = LLONG_MIN;
    1591                 :            :     }
    1592                 :         20 :     return retval;
    1593                 :            : }
    1594                 :            : 
    1595                 :            : /* Initializes 'dump' to begin dumping the queues in a netdev.
    1596                 :            :  *
    1597                 :            :  * This function provides no status indication.  An error status for the entire
    1598                 :            :  * dump operation is provided when it is completed by calling
    1599                 :            :  * netdev_queue_dump_done().
    1600                 :            :  */
    1601                 :            : void
    1602                 :         13 : netdev_queue_dump_start(struct netdev_queue_dump *dump,
    1603                 :            :                         const struct netdev *netdev)
    1604                 :            : {
    1605                 :         13 :     dump->netdev = netdev_ref(netdev);
    1606         [ +  - ]:         13 :     if (netdev->netdev_class->queue_dump_start) {
    1607                 :         13 :         dump->error = netdev->netdev_class->queue_dump_start(netdev,
    1608                 :            :                                                              &dump->state);
    1609                 :            :     } else {
    1610                 :          0 :         dump->error = EOPNOTSUPP;
    1611                 :            :     }
    1612                 :         13 : }
    1613                 :            : 
    1614                 :            : /* Attempts to retrieve another queue from 'dump', which must have been
    1615                 :            :  * initialized with netdev_queue_dump_start().  On success, stores a new queue
    1616                 :            :  * ID into '*queue_id', fills 'details' with configuration details for the
    1617                 :            :  * queue, and returns true.  On failure, returns false.
    1618                 :            :  *
    1619                 :            :  * Queues are not necessarily dumped in increasing order of queue ID (or any
    1620                 :            :  * other predictable order).
    1621                 :            :  *
    1622                 :            :  * Failure might indicate an actual error or merely that the last queue has
    1623                 :            :  * been dumped.  An error status for the entire dump operation is provided when
    1624                 :            :  * it is completed by calling netdev_queue_dump_done().
    1625                 :            :  *
    1626                 :            :  * The returned contents of 'details' should be documented as valid for the
    1627                 :            :  * given 'type' in the "other_config" column in the "Queue" table in
    1628                 :            :  * vswitchd/vswitch.xml (which is built as ovs-vswitchd.conf.db(8)).
    1629                 :            :  *
    1630                 :            :  * The caller must initialize 'details' (e.g. with smap_init()) before calling
    1631                 :            :  * this function.  This function will clear and replace its contents.  The
    1632                 :            :  * caller must free 'details' when it is no longer needed (e.g. with
    1633                 :            :  * smap_destroy()). */
    1634                 :            : bool
    1635                 :         26 : netdev_queue_dump_next(struct netdev_queue_dump *dump,
    1636                 :            :                        unsigned int *queue_id, struct smap *details)
    1637                 :            : {
    1638                 :         26 :     const struct netdev *netdev = dump->netdev;
    1639                 :            : 
    1640         [ -  + ]:         26 :     if (dump->error) {
    1641                 :          0 :         return false;
    1642                 :            :     }
    1643                 :            : 
    1644                 :         26 :     dump->error = netdev->netdev_class->queue_dump_next(netdev, dump->state,
    1645                 :            :                                                         queue_id, details);
    1646                 :            : 
    1647         [ +  + ]:         26 :     if (dump->error) {
    1648                 :         13 :         netdev->netdev_class->queue_dump_done(netdev, dump->state);
    1649                 :         13 :         return false;
    1650                 :            :     }
    1651                 :         13 :     return true;
    1652                 :            : }
    1653                 :            : 
    1654                 :            : /* Completes queue table dump operation 'dump', which must have been
    1655                 :            :  * initialized with netdev_queue_dump_start().  Returns 0 if the dump operation
    1656                 :            :  * was error-free, otherwise a positive errno value describing the problem. */
    1657                 :            : int
    1658                 :         13 : netdev_queue_dump_done(struct netdev_queue_dump *dump)
    1659                 :            : {
    1660                 :         13 :     const struct netdev *netdev = dump->netdev;
    1661 [ -  + ][ #  # ]:         13 :     if (!dump->error && netdev->netdev_class->queue_dump_done) {
    1662                 :          0 :         dump->error = netdev->netdev_class->queue_dump_done(netdev,
    1663                 :            :                                                             dump->state);
    1664                 :            :     }
    1665                 :         13 :     netdev_close(dump->netdev);
    1666         [ -  + ]:         13 :     return dump->error == EOF ? 0 : dump->error;
    1667                 :            : }
    1668                 :            : 
    1669                 :            : /* Iterates over all of 'netdev''s queues, calling 'cb' with the queue's ID,
    1670                 :            :  * its statistics, and the 'aux' specified by the caller.  The order of
    1671                 :            :  * iteration is unspecified, but (when successful) each queue is visited
    1672                 :            :  * exactly once.
    1673                 :            :  *
    1674                 :            :  * Calling this function may be more efficient than calling
    1675                 :            :  * netdev_get_queue_stats() for every queue.
    1676                 :            :  *
    1677                 :            :  * 'cb' must not modify or free the statistics passed in.
    1678                 :            :  *
    1679                 :            :  * Returns 0 if successful, otherwise a positive errno value.  On error, some
    1680                 :            :  * configured queues may not have been included in the iteration. */
    1681                 :            : int
    1682                 :         10 : netdev_dump_queue_stats(const struct netdev *netdev,
    1683                 :            :                         netdev_dump_queue_stats_cb *cb, void *aux)
    1684                 :            : {
    1685                 :         10 :     const struct netdev_class *class = netdev->netdev_class;
    1686                 :         10 :     return (class->dump_queue_stats
    1687                 :         10 :             ? class->dump_queue_stats(netdev, cb, aux)
    1688         [ +  - ]:         10 :             : EOPNOTSUPP);
    1689                 :            : }
    1690                 :            : 
    1691                 :            : 
    1692                 :            : /* Returns the class type of 'netdev'.
    1693                 :            :  *
    1694                 :            :  * The caller must not free the returned value. */
    1695                 :            : const char *
    1696                 :     125441 : netdev_get_type(const struct netdev *netdev)
    1697                 :            : {
    1698                 :     125441 :     return netdev->netdev_class->type;
    1699                 :            : }
    1700                 :            : 
    1701                 :            : /* Returns the class associated with 'netdev'. */
    1702                 :            : const struct netdev_class *
    1703                 :   57953229 : netdev_get_class(const struct netdev *netdev)
    1704                 :            : {
    1705                 :   57953229 :     return netdev->netdev_class;
    1706                 :            : }
    1707                 :            : 
    1708                 :            : /* Returns the netdev with 'name' or NULL if there is none.
    1709                 :            :  *
    1710                 :            :  * The caller must free the returned netdev with netdev_close(). */
    1711                 :            : struct netdev *
    1712                 :      32161 : netdev_from_name(const char *name)
    1713                 :            :     OVS_EXCLUDED(netdev_mutex)
    1714                 :            : {
    1715                 :            :     struct netdev *netdev;
    1716                 :            : 
    1717                 :      32161 :     ovs_mutex_lock(&netdev_mutex);
    1718                 :      32161 :     netdev = shash_find_data(&netdev_shash, name);
    1719         [ +  + ]:      32161 :     if (netdev) {
    1720                 :      30859 :         netdev->ref_cnt++;
    1721                 :            :     }
    1722                 :      32161 :     ovs_mutex_unlock(&netdev_mutex);
    1723                 :            : 
    1724                 :      32161 :     return netdev;
    1725                 :            : }
    1726                 :            : 
    1727                 :            : /* Fills 'device_list' with devices that match 'netdev_class'.
    1728                 :            :  *
    1729                 :            :  * The caller is responsible for initializing and destroying 'device_list' and
    1730                 :            :  * must close each device on the list. */
    1731                 :            : void
    1732                 :          0 : netdev_get_devices(const struct netdev_class *netdev_class,
    1733                 :            :                    struct shash *device_list)
    1734                 :            :     OVS_EXCLUDED(netdev_mutex)
    1735                 :            : {
    1736                 :            :     struct shash_node *node;
    1737                 :            : 
    1738                 :          0 :     ovs_mutex_lock(&netdev_mutex);
    1739 [ #  # ][ #  # ]:          0 :     SHASH_FOR_EACH (node, &netdev_shash) {
    1740                 :          0 :         struct netdev *dev = node->data;
    1741                 :            : 
    1742         [ #  # ]:          0 :         if (dev->netdev_class == netdev_class) {
    1743                 :          0 :             dev->ref_cnt++;
    1744                 :          0 :             shash_add(device_list, node->name, node->data);
    1745                 :            :         }
    1746                 :            :     }
    1747                 :          0 :     ovs_mutex_unlock(&netdev_mutex);
    1748                 :          0 : }
    1749                 :            : 
    1750                 :            : /* Extracts pointers to all 'netdev-vports' into an array 'vports'
    1751                 :            :  * and returns it.  Stores the size of the array into '*size'.
    1752                 :            :  *
    1753                 :            :  * The caller is responsible for freeing 'vports' and must close
    1754                 :            :  * each 'netdev-vport' in the list. */
    1755                 :            : struct netdev **
    1756                 :       2419 : netdev_get_vports(size_t *size)
    1757                 :            :     OVS_EXCLUDED(netdev_mutex)
    1758                 :            : {
    1759                 :            :     struct netdev **vports;
    1760                 :            :     struct shash_node *node;
    1761                 :       2419 :     size_t n = 0;
    1762                 :            : 
    1763         [ -  + ]:       2419 :     if (!size) {
    1764                 :          0 :         return NULL;
    1765                 :            :     }
    1766                 :            : 
    1767                 :            :     /* Explicitly allocates big enough chunk of memory. */
    1768                 :       2419 :     vports = xmalloc(shash_count(&netdev_shash) * sizeof *vports);
    1769                 :       2419 :     ovs_mutex_lock(&netdev_mutex);
    1770 [ +  + ][ -  + ]:      11016 :     SHASH_FOR_EACH (node, &netdev_shash) {
    1771                 :       8597 :         struct netdev *dev = node->data;
    1772                 :            : 
    1773         [ +  + ]:       8597 :         if (netdev_vport_is_vport_class(dev->netdev_class)) {
    1774                 :        823 :             dev->ref_cnt++;
    1775                 :        823 :             vports[n] = dev;
    1776                 :        823 :             n++;
    1777                 :            :         }
    1778                 :            :     }
    1779                 :       2419 :     ovs_mutex_unlock(&netdev_mutex);
    1780                 :       2419 :     *size = n;
    1781                 :            : 
    1782                 :       2419 :     return vports;
    1783                 :            : }
    1784                 :            : 
    1785                 :            : const char *
    1786                 :      25526 : netdev_get_type_from_name(const char *name)
    1787                 :            : {
    1788                 :      25526 :     struct netdev *dev = netdev_from_name(name);
    1789         [ +  + ]:      25526 :     const char *type = dev ? netdev_get_type(dev) : NULL;
    1790                 :      25526 :     netdev_close(dev);
    1791                 :      25526 :     return type;
    1792                 :            : }
    1793                 :            : 
    1794                 :            : struct netdev *
    1795                 :          0 : netdev_rxq_get_netdev(const struct netdev_rxq *rx)
    1796                 :            : {
    1797         [ #  # ]:          0 :     ovs_assert(rx->netdev->ref_cnt > 0);
    1798                 :          0 :     return rx->netdev;
    1799                 :            : }
    1800                 :            : 
    1801                 :            : const char *
    1802                 :          0 : netdev_rxq_get_name(const struct netdev_rxq *rx)
    1803                 :            : {
    1804                 :          0 :     return netdev_get_name(netdev_rxq_get_netdev(rx));
    1805                 :            : }
    1806                 :            : 
    1807                 :            : int
    1808                 :        118 : netdev_rxq_get_queue_id(const struct netdev_rxq *rx)
    1809                 :            : {
    1810                 :        118 :     return rx->queue_id;
    1811                 :            : }
    1812                 :            : 
    1813                 :            : static void
    1814                 :        681 : restore_all_flags(void *aux OVS_UNUSED)
    1815                 :            : {
    1816                 :            :     struct shash_node *node;
    1817                 :            : 
    1818 [ +  + ][ -  + ]:       1910 :     SHASH_FOR_EACH (node, &netdev_shash) {
    1819                 :       1229 :         struct netdev *netdev = node->data;
    1820                 :            :         const struct netdev_saved_flags *sf;
    1821                 :            :         enum netdev_flags saved_values;
    1822                 :            :         enum netdev_flags saved_flags;
    1823                 :            : 
    1824                 :       1229 :         saved_values = saved_flags = 0;
    1825         [ +  + ]:       1780 :         LIST_FOR_EACH (sf, node, &netdev->saved_flags_list) {
    1826                 :        551 :             saved_flags |= sf->saved_flags;
    1827                 :        551 :             saved_values &= ~sf->saved_flags;
    1828                 :        551 :             saved_values |= sf->saved_flags & sf->saved_values;
    1829                 :            :         }
    1830         [ +  + ]:       1229 :         if (saved_flags) {
    1831                 :            :             enum netdev_flags old_flags;
    1832                 :            : 
    1833                 :        551 :             netdev->netdev_class->update_flags(netdev,
    1834                 :        551 :                                                saved_flags & saved_values,
    1835                 :        551 :                                                saved_flags & ~saved_values,
    1836                 :            :                                                &old_flags);
    1837                 :            :         }
    1838                 :            :     }
    1839                 :        681 : }
    1840                 :            : 
    1841                 :            : uint64_t
    1842                 :     260769 : netdev_get_change_seq(const struct netdev *netdev)
    1843                 :            : {
    1844                 :     260769 :     return netdev->change_seq;
    1845                 :            : }
    1846                 :            : 
    1847                 :            : #ifndef _WIN32
    1848                 :            : /* This implementation is shared by Linux and BSD. */
    1849                 :            : 
    1850                 :            : static struct ifaddrs *if_addr_list;
    1851                 :            : static struct ovs_mutex if_addr_list_lock = OVS_MUTEX_INITIALIZER;
    1852                 :            : 
    1853                 :            : void
    1854                 :       2698 : netdev_get_addrs_list_flush(void)
    1855                 :            : {
    1856                 :       2698 :     ovs_mutex_lock(&if_addr_list_lock);
    1857         [ +  + ]:       2698 :     if (if_addr_list) {
    1858                 :       1875 :         freeifaddrs(if_addr_list);
    1859                 :       1875 :         if_addr_list = NULL;
    1860                 :            :     }
    1861                 :       2698 :     ovs_mutex_unlock(&if_addr_list_lock);
    1862                 :       2698 : }
    1863                 :            : 
    1864                 :            : int
    1865                 :      41940 : netdev_get_addrs(const char dev[], struct in6_addr **paddr,
    1866                 :            :                  struct in6_addr **pmask, int *n_in)
    1867                 :            : {
    1868                 :            :     struct in6_addr *addr_array, *mask_array;
    1869                 :            :     const struct ifaddrs *ifa;
    1870                 :      41940 :     int cnt = 0, i = 0;
    1871                 :            : 
    1872                 :      41940 :     ovs_mutex_lock(&if_addr_list_lock);
    1873         [ +  + ]:      41940 :     if (!if_addr_list) {
    1874                 :            :         int err;
    1875                 :            : 
    1876                 :       2452 :         err = getifaddrs(&if_addr_list);
    1877         [ -  + ]:       2452 :         if (err) {
    1878                 :          0 :             ovs_mutex_unlock(&if_addr_list_lock);
    1879                 :          0 :             return -err;
    1880                 :            :         }
    1881                 :            :     }
    1882                 :            : 
    1883         [ +  + ]:     630402 :     for (ifa = if_addr_list; ifa; ifa = ifa->ifa_next) {
    1884         [ +  - ]:     588462 :         if (ifa->ifa_addr != NULL) {
    1885                 :            :             int family;
    1886                 :            : 
    1887                 :     588462 :             family = ifa->ifa_addr->sa_family;
    1888 [ +  + ][ +  + ]:     588462 :             if (family == AF_INET || family == AF_INET6) {
    1889         [ +  + ]:     232754 :                 if (!strncmp(ifa->ifa_name, dev, IFNAMSIZ)) {
    1890                 :      77401 :                     cnt++;
    1891                 :            :                 }
    1892                 :            :             }
    1893                 :            :         }
    1894                 :            :     }
    1895                 :            : 
    1896         [ -  + ]:      41940 :     if (!cnt) {
    1897                 :          0 :         ovs_mutex_unlock(&if_addr_list_lock);
    1898                 :          0 :         return EADDRNOTAVAIL;
    1899                 :            :     }
    1900                 :      41940 :     addr_array = xzalloc(sizeof *addr_array * cnt);
    1901                 :      41940 :     mask_array = xzalloc(sizeof *mask_array * cnt);
    1902         [ +  + ]:     630402 :     for (ifa = if_addr_list; ifa; ifa = ifa->ifa_next) {
    1903                 :            :         int family;
    1904                 :            : 
    1905 [ +  + ][ -  + ]:     588462 :         if (strncmp(ifa->ifa_name, dev, IFNAMSIZ) || ifa->ifa_addr == NULL) {
    1906                 :     469121 :             continue;
    1907                 :            :         }
    1908                 :            : 
    1909                 :     119341 :         family = ifa->ifa_addr->sa_family;
    1910         [ +  + ]:     119341 :         if (family == AF_INET) {
    1911                 :            :             const struct sockaddr_in *sin;
    1912                 :            : 
    1913                 :      35463 :             sin = ALIGNED_CAST(const struct sockaddr_in *, ifa->ifa_addr);
    1914                 :      35463 :             in6_addr_set_mapped_ipv4(&addr_array[i], sin->sin_addr.s_addr);
    1915                 :      35463 :             sin = (struct sockaddr_in *) &ifa->ifa_netmask;
    1916                 :      35463 :             in6_addr_set_mapped_ipv4(&mask_array[i], sin->sin_addr.s_addr);
    1917                 :      35463 :             i++;
    1918         [ +  + ]:      83878 :         } else if (family == AF_INET6) {
    1919                 :            :             const struct sockaddr_in6 *sin6;
    1920                 :            : 
    1921                 :      41938 :             sin6 = ALIGNED_CAST(const struct sockaddr_in6 *, ifa->ifa_addr);
    1922                 :      41938 :             memcpy(&addr_array[i], &sin6->sin6_addr, sizeof *addr_array);
    1923                 :      41938 :             sin6 = (struct sockaddr_in6 *) &ifa->ifa_netmask;
    1924                 :      41938 :             memcpy(&mask_array[i], &sin6->sin6_addr, sizeof *mask_array);
    1925                 :      41938 :             i++;
    1926                 :            :         }
    1927                 :            :     }
    1928                 :      41940 :     ovs_mutex_unlock(&if_addr_list_lock);
    1929         [ +  - ]:      41940 :     if (paddr) {
    1930                 :      41940 :         *n_in = cnt;
    1931                 :      41940 :         *paddr = addr_array;
    1932                 :      41940 :         *pmask = mask_array;
    1933                 :            :     } else {
    1934                 :          0 :         free(addr_array);
    1935                 :          0 :         free(mask_array);
    1936                 :            :     }
    1937                 :      41940 :     return 0;
    1938                 :            : }
    1939                 :            : #endif
    1940                 :            : 
    1941                 :            : void
    1942                 :     555168 : netdev_wait_reconf_required(struct netdev *netdev)
    1943                 :            : {
    1944                 :     555168 :     seq_wait(netdev->reconfigure_seq, netdev->last_reconfigure_seq);
    1945                 :     555168 : }
    1946                 :            : 
    1947                 :            : bool
    1948                 :     565205 : netdev_is_reconf_required(struct netdev *netdev)
    1949                 :            : {
    1950                 :     565205 :     return seq_read(netdev->reconfigure_seq) != netdev->last_reconfigure_seq;
    1951                 :            : }
    1952                 :            : 
    1953                 :            : /* Give a chance to 'netdev' to reconfigure some of its parameters.
    1954                 :            :  *
    1955                 :            :  * If a module uses netdev_send() and netdev_rxq_recv(), it must call this
    1956                 :            :  * function when netdev_is_reconf_required() returns true.
    1957                 :            :  *
    1958                 :            :  * Return 0 if successful, otherwise a positive errno value.  If the
    1959                 :            :  * reconfiguration fails the netdev will not be able to send or receive
    1960                 :            :  * packets.
    1961                 :            :  *
    1962                 :            :  * When this function is called, no call to netdev_rxq_recv() or netdev_send()
    1963                 :            :  * must be issued. */
    1964                 :            : int
    1965                 :         10 : netdev_reconfigure(struct netdev *netdev)
    1966                 :            : {
    1967                 :         10 :     const struct netdev_class *class = netdev->netdev_class;
    1968                 :            : 
    1969                 :         10 :     netdev->last_reconfigure_seq = seq_read(netdev->reconfigure_seq);
    1970                 :            : 
    1971                 :         10 :     return (class->reconfigure
    1972                 :         10 :             ? class->reconfigure(netdev)
    1973         [ +  - ]:         10 :             : EOPNOTSUPP);
    1974                 :            : }

Generated by: LCOV version 1.12