LCOV - code coverage report
Current view: top level - lib - dpif-netlink.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 929 1143 81.3 %
Date: 2016-09-14 01:02:56 Functions: 82 94 87.2 %
Branches: 333 571 58.3 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Nicira, Inc.
       3                 :            :  *
       4                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
       5                 :            :  * you may not use this file except in compliance with the License.
       6                 :            :  * You may obtain a copy of the License at:
       7                 :            :  *
       8                 :            :  *     http://www.apache.org/licenses/LICENSE-2.0
       9                 :            :  *
      10                 :            :  * Unless required by applicable law or agreed to in writing, software
      11                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
      12                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      13                 :            :  * See the License for the specific language governing permissions and
      14                 :            :  * limitations under the License.
      15                 :            :  */
      16                 :            : 
      17                 :            : #include <config.h>
      18                 :            : 
      19                 :            : #include "dpif-netlink.h"
      20                 :            : 
      21                 :            : #include <ctype.h>
      22                 :            : #include <errno.h>
      23                 :            : #include <fcntl.h>
      24                 :            : #include <inttypes.h>
      25                 :            : #include <net/if.h>
      26                 :            : #include <linux/types.h>
      27                 :            : #include <linux/pkt_sched.h>
      28                 :            : #include <poll.h>
      29                 :            : #include <stdlib.h>
      30                 :            : #include <strings.h>
      31                 :            : #include <sys/epoll.h>
      32                 :            : #include <sys/stat.h>
      33                 :            : #include <unistd.h>
      34                 :            : 
      35                 :            : #include "bitmap.h"
      36                 :            : #include "dpif-provider.h"
      37                 :            : #include "openvswitch/dynamic-string.h"
      38                 :            : #include "flow.h"
      39                 :            : #include "fat-rwlock.h"
      40                 :            : #include "netdev.h"
      41                 :            : #include "netdev-linux.h"
      42                 :            : #include "netdev-vport.h"
      43                 :            : #include "netlink-conntrack.h"
      44                 :            : #include "netlink-notifier.h"
      45                 :            : #include "netlink-socket.h"
      46                 :            : #include "netlink.h"
      47                 :            : #include "odp-util.h"
      48                 :            : #include "openvswitch/ofpbuf.h"
      49                 :            : #include "packets.h"
      50                 :            : #include "poll-loop.h"
      51                 :            : #include "random.h"
      52                 :            : #include "openvswitch/shash.h"
      53                 :            : #include "sset.h"
      54                 :            : #include "timeval.h"
      55                 :            : #include "unaligned.h"
      56                 :            : #include "util.h"
      57                 :            : #include "openvswitch/vlog.h"
      58                 :            : 
      59                 :      20190 : VLOG_DEFINE_THIS_MODULE(dpif_netlink);
      60                 :            : #ifdef _WIN32
      61                 :            : enum { WINDOWS = 1 };
      62                 :            : #else
      63                 :            : enum { WINDOWS = 0 };
      64                 :            : #endif
      65                 :            : enum { MAX_PORTS = USHRT_MAX };
      66                 :            : 
      67                 :            : /* This ethtool flag was introduced in Linux 2.6.24, so it might be
      68                 :            :  * missing if we have old headers. */
      69                 :            : #define ETH_FLAG_LRO      (1 << 15)    /* LRO is enabled */
      70                 :            : 
      71                 :            : struct dpif_netlink_dp {
      72                 :            :     /* Generic Netlink header. */
      73                 :            :     uint8_t cmd;
      74                 :            : 
      75                 :            :     /* struct ovs_header. */
      76                 :            :     int dp_ifindex;
      77                 :            : 
      78                 :            :     /* Attributes. */
      79                 :            :     const char *name;                  /* OVS_DP_ATTR_NAME. */
      80                 :            :     const uint32_t *upcall_pid;        /* OVS_DP_ATTR_UPCALL_PID. */
      81                 :            :     uint32_t user_features;            /* OVS_DP_ATTR_USER_FEATURES */
      82                 :            :     const struct ovs_dp_stats *stats;  /* OVS_DP_ATTR_STATS. */
      83                 :            :     const struct ovs_dp_megaflow_stats *megaflow_stats;
      84                 :            :                                        /* OVS_DP_ATTR_MEGAFLOW_STATS.*/
      85                 :            : };
      86                 :            : 
      87                 :            : static void dpif_netlink_dp_init(struct dpif_netlink_dp *);
      88                 :            : static int dpif_netlink_dp_from_ofpbuf(struct dpif_netlink_dp *,
      89                 :            :                                        const struct ofpbuf *);
      90                 :            : static void dpif_netlink_dp_dump_start(struct nl_dump *);
      91                 :            : static int dpif_netlink_dp_transact(const struct dpif_netlink_dp *request,
      92                 :            :                                     struct dpif_netlink_dp *reply,
      93                 :            :                                     struct ofpbuf **bufp);
      94                 :            : static int dpif_netlink_dp_get(const struct dpif *,
      95                 :            :                                struct dpif_netlink_dp *reply,
      96                 :            :                                struct ofpbuf **bufp);
      97                 :            : 
      98                 :            : struct dpif_netlink_flow {
      99                 :            :     /* Generic Netlink header. */
     100                 :            :     uint8_t cmd;
     101                 :            : 
     102                 :            :     /* struct ovs_header. */
     103                 :            :     unsigned int nlmsg_flags;
     104                 :            :     int dp_ifindex;
     105                 :            : 
     106                 :            :     /* Attributes.
     107                 :            :      *
     108                 :            :      * The 'stats' member points to 64-bit data that might only be aligned on
     109                 :            :      * 32-bit boundaries, so get_unaligned_u64() should be used to access its
     110                 :            :      * values.
     111                 :            :      *
     112                 :            :      * If 'actions' is nonnull then OVS_FLOW_ATTR_ACTIONS will be included in
     113                 :            :      * the Netlink version of the command, even if actions_len is zero. */
     114                 :            :     const struct nlattr *key;           /* OVS_FLOW_ATTR_KEY. */
     115                 :            :     size_t key_len;
     116                 :            :     const struct nlattr *mask;          /* OVS_FLOW_ATTR_MASK. */
     117                 :            :     size_t mask_len;
     118                 :            :     const struct nlattr *actions;       /* OVS_FLOW_ATTR_ACTIONS. */
     119                 :            :     size_t actions_len;
     120                 :            :     ovs_u128 ufid;                      /* OVS_FLOW_ATTR_FLOW_ID. */
     121                 :            :     bool ufid_present;                  /* Is there a UFID? */
     122                 :            :     bool ufid_terse;                    /* Skip serializing key/mask/acts? */
     123                 :            :     const struct ovs_flow_stats *stats; /* OVS_FLOW_ATTR_STATS. */
     124                 :            :     const uint8_t *tcp_flags;           /* OVS_FLOW_ATTR_TCP_FLAGS. */
     125                 :            :     const ovs_32aligned_u64 *used;      /* OVS_FLOW_ATTR_USED. */
     126                 :            :     bool clear;                         /* OVS_FLOW_ATTR_CLEAR. */
     127                 :            :     bool probe;                         /* OVS_FLOW_ATTR_PROBE. */
     128                 :            : };
     129                 :            : 
     130                 :            : static void dpif_netlink_flow_init(struct dpif_netlink_flow *);
     131                 :            : static int dpif_netlink_flow_from_ofpbuf(struct dpif_netlink_flow *,
     132                 :            :                                          const struct ofpbuf *);
     133                 :            : static void dpif_netlink_flow_to_ofpbuf(const struct dpif_netlink_flow *,
     134                 :            :                                         struct ofpbuf *);
     135                 :            : static int dpif_netlink_flow_transact(struct dpif_netlink_flow *request,
     136                 :            :                                       struct dpif_netlink_flow *reply,
     137                 :            :                                       struct ofpbuf **bufp);
     138                 :            : static void dpif_netlink_flow_get_stats(const struct dpif_netlink_flow *,
     139                 :            :                                         struct dpif_flow_stats *);
     140                 :            : static void dpif_netlink_flow_to_dpif_flow(struct dpif *, struct dpif_flow *,
     141                 :            :                                            const struct dpif_netlink_flow *);
     142                 :            : 
     143                 :            : /* One of the dpif channels between the kernel and userspace. */
     144                 :            : struct dpif_channel {
     145                 :            :     struct nl_sock *sock;       /* Netlink socket. */
     146                 :            :     long long int last_poll;    /* Last time this channel was polled. */
     147                 :            : };
     148                 :            : 
     149                 :            : #ifdef _WIN32
     150                 :            : #define VPORT_SOCK_POOL_SIZE 1
     151                 :            : /* On Windows, there is no native support for epoll.  There are equivalent
     152                 :            :  * interfaces though, that are not used currently.  For simpicity, a pool of
     153                 :            :  * netlink sockets is used.  Each socket is represented by 'struct
     154                 :            :  * dpif_windows_vport_sock'.  Since it is a pool, multiple OVS ports may be
     155                 :            :  * sharing the same socket.  In the future, we can add a reference count and
     156                 :            :  * such fields. */
     157                 :            : struct dpif_windows_vport_sock {
     158                 :            :     struct nl_sock *nl_sock;    /* netlink socket. */
     159                 :            : };
     160                 :            : #endif
     161                 :            : 
     162                 :            : struct dpif_handler {
     163                 :            :     struct dpif_channel *channels;/* Array of channels for each handler. */
     164                 :            :     struct epoll_event *epoll_events;
     165                 :            :     int epoll_fd;                 /* epoll fd that includes channel socks. */
     166                 :            :     int n_events;                 /* Num events returned by epoll_wait(). */
     167                 :            :     int event_offset;             /* Offset into 'epoll_events'. */
     168                 :            : 
     169                 :            : #ifdef _WIN32
     170                 :            :     /* Pool of sockets. */
     171                 :            :     struct dpif_windows_vport_sock *vport_sock_pool;
     172                 :            :     size_t last_used_pool_idx; /* Index to aid in allocating a
     173                 :            :                                   socket in the pool to a port. */
     174                 :            : #endif
     175                 :            : };
     176                 :            : 
     177                 :            : /* Datapath interface for the openvswitch Linux kernel module. */
     178                 :            : struct dpif_netlink {
     179                 :            :     struct dpif dpif;
     180                 :            :     int dp_ifindex;
     181                 :            : 
     182                 :            :     /* Upcall messages. */
     183                 :            :     struct fat_rwlock upcall_lock;
     184                 :            :     struct dpif_handler *handlers;
     185                 :            :     uint32_t n_handlers;           /* Num of upcall handlers. */
     186                 :            :     int uc_array_size;             /* Size of 'handler->channels' and */
     187                 :            :                                    /* 'handler->epoll_events'. */
     188                 :            : 
     189                 :            :     /* Change notification. */
     190                 :            :     struct nl_sock *port_notifier; /* vport multicast group subscriber. */
     191                 :            :     bool refresh_channels;
     192                 :            : };
     193                 :            : 
     194                 :            : static void report_loss(struct dpif_netlink *, struct dpif_channel *,
     195                 :            :                         uint32_t ch_idx, uint32_t handler_id);
     196                 :            : 
     197                 :            : static struct vlog_rate_limit error_rl = VLOG_RATE_LIMIT_INIT(9999, 5);
     198                 :            : 
     199                 :            : /* Generic Netlink family numbers for OVS.
     200                 :            :  *
     201                 :            :  * Initialized by dpif_netlink_init(). */
     202                 :            : static int ovs_datapath_family;
     203                 :            : static int ovs_vport_family;
     204                 :            : static int ovs_flow_family;
     205                 :            : static int ovs_packet_family;
     206                 :            : 
     207                 :            : /* Generic Netlink multicast groups for OVS.
     208                 :            :  *
     209                 :            :  * Initialized by dpif_netlink_init(). */
     210                 :            : static unsigned int ovs_vport_mcgroup;
     211                 :            : 
     212                 :            : static int dpif_netlink_init(void);
     213                 :            : static int open_dpif(const struct dpif_netlink_dp *, struct dpif **);
     214                 :            : static uint32_t dpif_netlink_port_get_pid(const struct dpif *,
     215                 :            :                                           odp_port_t port_no, uint32_t hash);
     216                 :            : static void dpif_netlink_handler_uninit(struct dpif_handler *handler);
     217                 :            : static int dpif_netlink_refresh_channels(struct dpif_netlink *,
     218                 :            :                                          uint32_t n_handlers);
     219                 :            : static void dpif_netlink_vport_to_ofpbuf(const struct dpif_netlink_vport *,
     220                 :            :                                          struct ofpbuf *);
     221                 :            : static int dpif_netlink_vport_from_ofpbuf(struct dpif_netlink_vport *,
     222                 :            :                                           const struct ofpbuf *);
     223                 :            : 
     224                 :            : static struct dpif_netlink *
     225                 :      39865 : dpif_netlink_cast(const struct dpif *dpif)
     226                 :            : {
     227                 :      39865 :     dpif_assert_class(dpif, &dpif_netlink_class);
     228                 :      39864 :     return CONTAINER_OF(dpif, struct dpif_netlink, dpif);
     229                 :            : }
     230                 :            : 
     231                 :            : static int
     232                 :        122 : dpif_netlink_enumerate(struct sset *all_dps,
     233                 :            :                        const struct dpif_class *dpif_class OVS_UNUSED)
     234                 :            : {
     235                 :            :     struct nl_dump dump;
     236                 :            :     uint64_t reply_stub[NL_DUMP_BUFSIZE / 8];
     237                 :            :     struct ofpbuf msg, buf;
     238                 :            :     int error;
     239                 :            : 
     240                 :        122 :     error = dpif_netlink_init();
     241         [ -  + ]:        122 :     if (error) {
     242                 :          0 :         return error;
     243                 :            :     }
     244                 :            : 
     245                 :        122 :     ofpbuf_use_stub(&buf, reply_stub, sizeof reply_stub);
     246                 :        122 :     dpif_netlink_dp_dump_start(&dump);
     247         [ +  + ]:        181 :     while (nl_dump_next(&dump, &msg, &buf)) {
     248                 :            :         struct dpif_netlink_dp dp;
     249                 :            : 
     250         [ +  - ]:         59 :         if (!dpif_netlink_dp_from_ofpbuf(&dp, &msg)) {
     251                 :         59 :             sset_add(all_dps, dp.name);
     252                 :            :         }
     253                 :            :     }
     254                 :        122 :     ofpbuf_uninit(&buf);
     255                 :        122 :     return nl_dump_done(&dump);
     256                 :            : }
     257                 :            : 
     258                 :            : static int
     259                 :        186 : dpif_netlink_open(const struct dpif_class *class OVS_UNUSED, const char *name,
     260                 :            :                   bool create, struct dpif **dpifp)
     261                 :            : {
     262                 :            :     struct dpif_netlink_dp dp_request, dp;
     263                 :            :     struct ofpbuf *buf;
     264                 :            :     uint32_t upcall_pid;
     265                 :            :     int error;
     266                 :            : 
     267                 :        186 :     error = dpif_netlink_init();
     268         [ -  + ]:        186 :     if (error) {
     269                 :          0 :         return error;
     270                 :            :     }
     271                 :            : 
     272                 :            :     /* Create or look up datapath. */
     273                 :        186 :     dpif_netlink_dp_init(&dp_request);
     274         [ +  + ]:        186 :     if (create) {
     275                 :         63 :         dp_request.cmd = OVS_DP_CMD_NEW;
     276                 :         63 :         upcall_pid = 0;
     277                 :         63 :         dp_request.upcall_pid = &upcall_pid;
     278                 :            :     } else {
     279                 :            :         /* Use OVS_DP_CMD_SET to report user features */
     280                 :        123 :         dp_request.cmd = OVS_DP_CMD_SET;
     281                 :            :     }
     282                 :        186 :     dp_request.name = name;
     283                 :        186 :     dp_request.user_features |= OVS_DP_F_UNALIGNED;
     284                 :        186 :     dp_request.user_features |= OVS_DP_F_VPORT_PIDS;
     285                 :        186 :     error = dpif_netlink_dp_transact(&dp_request, &dp, &buf);
     286         [ -  + ]:        186 :     if (error) {
     287                 :          0 :         return error;
     288                 :            :     }
     289                 :            : 
     290                 :        186 :     error = open_dpif(&dp, dpifp);
     291                 :        186 :     ofpbuf_delete(buf);
     292                 :        186 :     return error;
     293                 :            : }
     294                 :            : 
     295                 :            : static int
     296                 :        186 : open_dpif(const struct dpif_netlink_dp *dp, struct dpif **dpifp)
     297                 :            : {
     298                 :            :     struct dpif_netlink *dpif;
     299                 :            : 
     300                 :        186 :     dpif = xzalloc(sizeof *dpif);
     301                 :        186 :     dpif->port_notifier = NULL;
     302                 :        186 :     fat_rwlock_init(&dpif->upcall_lock);
     303                 :            : 
     304                 :        186 :     dpif_init(&dpif->dpif, &dpif_netlink_class, dp->name,
     305                 :        372 :               dp->dp_ifindex, dp->dp_ifindex);
     306                 :            : 
     307                 :        186 :     dpif->dp_ifindex = dp->dp_ifindex;
     308                 :        186 :     *dpifp = &dpif->dpif;
     309                 :            : 
     310                 :        186 :     return 0;
     311                 :            : }
     312                 :            : 
     313                 :            : /* Destroys the netlink sockets pointed by the elements in 'socksp'
     314                 :            :  * and frees the 'socksp'.  */
     315                 :            : static void
     316                 :          0 : vport_del_socksp__(struct nl_sock **socksp, uint32_t n_socks)
     317                 :            : {
     318                 :            :     size_t i;
     319                 :            : 
     320         [ #  # ]:          0 :     for (i = 0; i < n_socks; i++) {
     321                 :          0 :         nl_sock_destroy(socksp[i]);
     322                 :            :     }
     323                 :            : 
     324                 :          0 :     free(socksp);
     325                 :          0 : }
     326                 :            : 
     327                 :            : /* Creates an array of netlink sockets.  Returns an array of the
     328                 :            :  * corresponding pointers.  Records the error in 'error'. */
     329                 :            : static struct nl_sock **
     330                 :        295 : vport_create_socksp__(uint32_t n_socks, int *error)
     331                 :            : {
     332                 :        295 :     struct nl_sock **socksp = xzalloc(n_socks * sizeof *socksp);
     333                 :            :     size_t i;
     334                 :            : 
     335         [ +  + ]:        590 :     for (i = 0; i < n_socks; i++) {
     336                 :        295 :         *error = nl_sock_create(NETLINK_GENERIC, &socksp[i]);
     337         [ -  + ]:        295 :         if (*error) {
     338                 :          0 :             goto error;
     339                 :            :         }
     340                 :            :     }
     341                 :            : 
     342                 :        295 :     return socksp;
     343                 :            : 
     344                 :            : error:
     345                 :          0 :     vport_del_socksp__(socksp, n_socks);
     346                 :            : 
     347                 :          0 :     return NULL;
     348                 :            : }
     349                 :            : 
     350                 :            : #ifdef _WIN32
     351                 :            : static void
     352                 :            : vport_delete_sock_pool(struct dpif_handler *handler)
     353                 :            :     OVS_REQ_WRLOCK(dpif->upcall_lock)
     354                 :            : {
     355                 :            :     if (handler->vport_sock_pool) {
     356                 :            :         uint32_t i;
     357                 :            :         struct dpif_windows_vport_sock *sock_pool =
     358                 :            :             handler->vport_sock_pool;
     359                 :            : 
     360                 :            :         for (i = 0; i < VPORT_SOCK_POOL_SIZE; i++) {
     361                 :            :             if (sock_pool[i].nl_sock) {
     362                 :            :                 nl_sock_unsubscribe_packets(sock_pool[i].nl_sock);
     363                 :            :                 nl_sock_destroy(sock_pool[i].nl_sock);
     364                 :            :                 sock_pool[i].nl_sock = NULL;
     365                 :            :             }
     366                 :            :         }
     367                 :            : 
     368                 :            :         free(handler->vport_sock_pool);
     369                 :            :         handler->vport_sock_pool = NULL;
     370                 :            :     }
     371                 :            : }
     372                 :            : 
     373                 :            : static int
     374                 :            : vport_create_sock_pool(struct dpif_handler *handler)
     375                 :            :     OVS_REQ_WRLOCK(dpif->upcall_lock)
     376                 :            : {
     377                 :            :     struct dpif_windows_vport_sock *sock_pool;
     378                 :            :     size_t i;
     379                 :            :     int error = 0;
     380                 :            : 
     381                 :            :     sock_pool = xzalloc(VPORT_SOCK_POOL_SIZE * sizeof *sock_pool);
     382                 :            :     for (i = 0; i < VPORT_SOCK_POOL_SIZE; i++) {
     383                 :            :         error = nl_sock_create(NETLINK_GENERIC, &sock_pool[i].nl_sock);
     384                 :            :         if (error) {
     385                 :            :             goto error;
     386                 :            :         }
     387                 :            : 
     388                 :            :         /* Enable the netlink socket to receive packets.  This is equivalent to
     389                 :            :          * calling nl_sock_join_mcgroup() to receive events. */
     390                 :            :         error = nl_sock_subscribe_packets(sock_pool[i].nl_sock);
     391                 :            :         if (error) {
     392                 :            :            goto error;
     393                 :            :         }
     394                 :            :     }
     395                 :            : 
     396                 :            :     handler->vport_sock_pool = sock_pool;
     397                 :            :     handler->last_used_pool_idx = 0;
     398                 :            :     return 0;
     399                 :            : 
     400                 :            : error:
     401                 :            :     vport_delete_sock_pool(handler);
     402                 :            :     return error;
     403                 :            : }
     404                 :            : 
     405                 :            : /* Returns an array pointers to netlink sockets.  The sockets are picked from a
     406                 :            :  * pool. Records the error in 'error'. */
     407                 :            : static struct nl_sock **
     408                 :            : vport_create_socksp_windows(struct dpif_netlink *dpif, int *error)
     409                 :            :     OVS_REQ_WRLOCK(dpif->upcall_lock)
     410                 :            : {
     411                 :            :     uint32_t n_socks = dpif->n_handlers;
     412                 :            :     struct nl_sock **socksp;
     413                 :            :     size_t i;
     414                 :            : 
     415                 :            :     ovs_assert(n_socks <= 1);
     416                 :            :     socksp = xzalloc(n_socks * sizeof *socksp);
     417                 :            : 
     418                 :            :     /* Pick netlink sockets to use in a round-robin fashion from each
     419                 :            :      * handler's pool of sockets. */
     420                 :            :     for (i = 0; i < n_socks; i++) {
     421                 :            :         struct dpif_handler *handler = &dpif->handlers[i];
     422                 :            :         struct dpif_windows_vport_sock *sock_pool = handler->vport_sock_pool;
     423                 :            :         size_t index = handler->last_used_pool_idx;
     424                 :            : 
     425                 :            :         /* A pool of sockets is allocated when the handler is initialized. */
     426                 :            :         if (sock_pool == NULL) {
     427                 :            :             free(socksp);
     428                 :            :             *error = EINVAL;
     429                 :            :             return NULL;
     430                 :            :         }
     431                 :            : 
     432                 :            :         ovs_assert(index < VPORT_SOCK_POOL_SIZE);
     433                 :            :         socksp[i] = sock_pool[index].nl_sock;
     434                 :            :         socksp[i] = sock_pool[index].nl_sock;
     435                 :            :         ovs_assert(socksp[i]);
     436                 :            :         index = (index == VPORT_SOCK_POOL_SIZE - 1) ? 0 : index + 1;
     437                 :            :         handler->last_used_pool_idx = index;
     438                 :            :     }
     439                 :            : 
     440                 :            :     return socksp;
     441                 :            : }
     442                 :            : 
     443                 :            : static void
     444                 :            : vport_del_socksp_windows(struct dpif_netlink *dpif, struct nl_sock **socksp)
     445                 :            : {
     446                 :            :     free(socksp);
     447                 :            : }
     448                 :            : #endif /* _WIN32 */
     449                 :            : 
     450                 :            : static struct nl_sock **
     451                 :        295 : vport_create_socksp(struct dpif_netlink *dpif, int *error)
     452                 :            : {
     453                 :            : #ifdef _WIN32
     454                 :            :     return vport_create_socksp_windows(dpif, error);
     455                 :            : #else
     456                 :        295 :     return vport_create_socksp__(dpif->n_handlers, error);
     457                 :            : #endif
     458                 :            : }
     459                 :            : 
     460                 :            : static void
     461                 :          0 : vport_del_socksp(struct dpif_netlink *dpif, struct nl_sock **socksp)
     462                 :            : {
     463                 :            : #ifdef _WIN32
     464                 :            :     vport_del_socksp_windows(dpif, socksp);
     465                 :            : #else
     466                 :          0 :     vport_del_socksp__(socksp, dpif->n_handlers);
     467                 :            : #endif
     468                 :          0 : }
     469                 :            : 
     470                 :            : /* Given the array of pointers to netlink sockets 'socksp', returns
     471                 :            :  * the array of corresponding pids. If the 'socksp' is NULL, returns
     472                 :            :  * a single-element array of value 0. */
     473                 :            : static uint32_t *
     474                 :        295 : vport_socksp_to_pids(struct nl_sock **socksp, uint32_t n_socks)
     475                 :            : {
     476                 :            :     uint32_t *pids;
     477                 :            : 
     478         [ -  + ]:        295 :     if (!socksp) {
     479                 :          0 :         pids = xzalloc(sizeof *pids);
     480                 :            :     } else {
     481                 :            :         size_t i;
     482                 :            : 
     483                 :        295 :         pids = xzalloc(n_socks * sizeof *pids);
     484         [ +  + ]:        590 :         for (i = 0; i < n_socks; i++) {
     485                 :        295 :             pids[i] = nl_sock_pid(socksp[i]);
     486                 :            :         }
     487                 :            :     }
     488                 :            : 
     489                 :        295 :     return pids;
     490                 :            : }
     491                 :            : 
     492                 :            : /* Given the port number 'port_idx', extracts the pids of netlink sockets
     493                 :            :  * associated to the port and assigns it to 'upcall_pids'. */
     494                 :            : static bool
     495                 :         63 : vport_get_pids(struct dpif_netlink *dpif, uint32_t port_idx,
     496                 :            :                uint32_t **upcall_pids)
     497                 :            : {
     498                 :            :     uint32_t *pids;
     499                 :            :     size_t i;
     500                 :            : 
     501                 :            :     /* Since the nl_sock can only be assigned in either all
     502                 :            :      * or none "dpif->handlers" channels, the following check
     503                 :            :      * would suffice. */
     504         [ -  + ]:         63 :     if (!dpif->handlers[0].channels[port_idx].sock) {
     505                 :          0 :         return false;
     506                 :            :     }
     507                 :            :     ovs_assert(!WINDOWS || dpif->n_handlers <= 1);
     508                 :            : 
     509                 :         63 :     pids = xzalloc(dpif->n_handlers * sizeof *pids);
     510                 :            : 
     511         [ +  + ]:        126 :     for (i = 0; i < dpif->n_handlers; i++) {
     512                 :         63 :         pids[i] = nl_sock_pid(dpif->handlers[i].channels[port_idx].sock);
     513                 :            :     }
     514                 :            : 
     515                 :         63 :     *upcall_pids = pids;
     516                 :            : 
     517                 :         63 :     return true;
     518                 :            : }
     519                 :            : 
     520                 :            : static int
     521                 :        295 : vport_add_channels(struct dpif_netlink *dpif, odp_port_t port_no,
     522                 :            :                    struct nl_sock **socksp)
     523                 :            : {
     524                 :            :     struct epoll_event event;
     525                 :        295 :     uint32_t port_idx = odp_to_u32(port_no);
     526                 :            :     size_t i, j;
     527                 :            :     int error;
     528                 :            : 
     529         [ -  + ]:        295 :     if (dpif->handlers == NULL) {
     530                 :          0 :         return 0;
     531                 :            :     }
     532                 :            : 
     533                 :            :     /* We assume that the datapath densely chooses port numbers, which can
     534                 :            :      * therefore be used as an index into 'channels' and 'epoll_events' of
     535                 :            :      * 'dpif->handler'. */
     536         [ +  - ]:        295 :     if (port_idx >= dpif->uc_array_size) {
     537                 :        295 :         uint32_t new_size = port_idx + 1;
     538                 :            : 
     539         [ -  + ]:        295 :         if (new_size > MAX_PORTS) {
     540         [ #  # ]:          0 :             VLOG_WARN_RL(&error_rl, "%s: datapath port %"PRIu32" too big",
     541                 :            :                          dpif_name(&dpif->dpif), port_no);
     542                 :          0 :             return EFBIG;
     543                 :            :         }
     544                 :            : 
     545         [ +  + ]:        590 :         for (i = 0; i < dpif->n_handlers; i++) {
     546                 :        295 :             struct dpif_handler *handler = &dpif->handlers[i];
     547                 :            : 
     548                 :        295 :             handler->channels = xrealloc(handler->channels,
     549                 :            :                                          new_size * sizeof *handler->channels);
     550                 :            : 
     551         [ +  + ]:        590 :             for (j = dpif->uc_array_size; j < new_size; j++) {
     552                 :        295 :                 handler->channels[j].sock = NULL;
     553                 :            :             }
     554                 :            : 
     555                 :        295 :             handler->epoll_events = xrealloc(handler->epoll_events,
     556                 :            :                 new_size * sizeof *handler->epoll_events);
     557                 :            : 
     558                 :            :         }
     559                 :        295 :         dpif->uc_array_size = new_size;
     560                 :            :     }
     561                 :            : 
     562                 :        295 :     memset(&event, 0, sizeof event);
     563                 :        295 :     event.events = EPOLLIN;
     564                 :        295 :     event.data.u32 = port_idx;
     565                 :            : 
     566         [ +  + ]:        590 :     for (i = 0; i < dpif->n_handlers; i++) {
     567                 :        295 :         struct dpif_handler *handler = &dpif->handlers[i];
     568                 :            : 
     569                 :            : #ifndef _WIN32
     570         [ -  + ]:        295 :         if (epoll_ctl(handler->epoll_fd, EPOLL_CTL_ADD, nl_sock_fd(socksp[i]),
     571                 :            :                       &event) < 0) {
     572                 :          0 :             error = errno;
     573                 :          0 :             goto error;
     574                 :            :         }
     575                 :            : #endif
     576                 :        295 :         dpif->handlers[i].channels[port_idx].sock = socksp[i];
     577                 :        295 :         dpif->handlers[i].channels[port_idx].last_poll = LLONG_MIN;
     578                 :            :     }
     579                 :            : 
     580                 :        295 :     return 0;
     581                 :            : 
     582                 :            : error:
     583         [ #  # ]:          0 :     for (j = 0; j < i; j++) {
     584                 :            : #ifndef _WIN32
     585                 :          0 :         epoll_ctl(dpif->handlers[j].epoll_fd, EPOLL_CTL_DEL,
     586                 :          0 :                   nl_sock_fd(socksp[j]), NULL);
     587                 :            : #endif
     588                 :          0 :         dpif->handlers[j].channels[port_idx].sock = NULL;
     589                 :            :     }
     590                 :            : 
     591                 :        295 :     return error;
     592                 :            : }
     593                 :            : 
     594                 :            : static void
     595                 :        295 : vport_del_channels(struct dpif_netlink *dpif, odp_port_t port_no)
     596                 :            : {
     597                 :        295 :     uint32_t port_idx = odp_to_u32(port_no);
     598                 :            :     size_t i;
     599                 :            : 
     600 [ +  - ][ -  + ]:        295 :     if (!dpif->handlers || port_idx >= dpif->uc_array_size) {
     601                 :          0 :         return;
     602                 :            :     }
     603                 :            : 
     604                 :            :     /* Since the sock can only be assigned in either all or none
     605                 :            :      * of "dpif->handlers" channels, the following check would
     606                 :            :      * suffice. */
     607         [ -  + ]:        295 :     if (!dpif->handlers[0].channels[port_idx].sock) {
     608                 :          0 :         return;
     609                 :            :     }
     610                 :            : 
     611         [ +  + ]:        590 :     for (i = 0; i < dpif->n_handlers; i++) {
     612                 :        295 :         struct dpif_handler *handler = &dpif->handlers[i];
     613                 :            : #ifndef _WIN32
     614                 :        295 :         epoll_ctl(handler->epoll_fd, EPOLL_CTL_DEL,
     615                 :        295 :                   nl_sock_fd(handler->channels[port_idx].sock), NULL);
     616                 :        295 :         nl_sock_destroy(handler->channels[port_idx].sock);
     617                 :            : #endif
     618                 :        295 :         handler->channels[port_idx].sock = NULL;
     619                 :        295 :         handler->event_offset = handler->n_events = 0;
     620                 :            :     }
     621                 :            : }
     622                 :            : 
     623                 :            : static void
     624                 :        249 : destroy_all_channels(struct dpif_netlink *dpif)
     625                 :            :     OVS_REQ_WRLOCK(dpif->upcall_lock)
     626                 :            : {
     627                 :            :     unsigned int i;
     628                 :            : 
     629         [ +  + ]:        249 :     if (!dpif->handlers) {
     630                 :        186 :         return;
     631                 :            :     }
     632                 :            : 
     633         [ +  + ]:        358 :     for (i = 0; i < dpif->uc_array_size; i++ ) {
     634                 :            :         struct dpif_netlink_vport vport_request;
     635                 :        295 :         uint32_t upcall_pids = 0;
     636                 :            : 
     637                 :            :         /* Since the sock can only be assigned in either all or none
     638                 :            :          * of "dpif->handlers" channels, the following check would
     639                 :            :          * suffice. */
     640         [ -  + ]:        295 :         if (!dpif->handlers[0].channels[i].sock) {
     641                 :          0 :             continue;
     642                 :            :         }
     643                 :            : 
     644                 :            :         /* Turn off upcalls. */
     645                 :        295 :         dpif_netlink_vport_init(&vport_request);
     646                 :        295 :         vport_request.cmd = OVS_VPORT_CMD_SET;
     647                 :        295 :         vport_request.dp_ifindex = dpif->dp_ifindex;
     648                 :        295 :         vport_request.port_no = u32_to_odp(i);
     649                 :        295 :         vport_request.n_upcall_pids = 1;
     650                 :        295 :         vport_request.upcall_pids = &upcall_pids;
     651                 :        295 :         dpif_netlink_vport_transact(&vport_request, NULL, NULL);
     652                 :            : 
     653                 :        295 :         vport_del_channels(dpif, u32_to_odp(i));
     654                 :            :     }
     655                 :            : 
     656         [ +  + ]:        126 :     for (i = 0; i < dpif->n_handlers; i++) {
     657                 :         63 :         struct dpif_handler *handler = &dpif->handlers[i];
     658                 :            : 
     659                 :         63 :         dpif_netlink_handler_uninit(handler);
     660                 :         63 :         free(handler->epoll_events);
     661                 :         63 :         free(handler->channels);
     662                 :            :     }
     663                 :            : 
     664                 :         63 :     free(dpif->handlers);
     665                 :         63 :     dpif->handlers = NULL;
     666                 :         63 :     dpif->n_handlers = 0;
     667                 :         63 :     dpif->uc_array_size = 0;
     668                 :            : }
     669                 :            : 
     670                 :            : static void
     671                 :        186 : dpif_netlink_close(struct dpif *dpif_)
     672                 :            : {
     673                 :        186 :     struct dpif_netlink *dpif = dpif_netlink_cast(dpif_);
     674                 :            : 
     675                 :        186 :     nl_sock_destroy(dpif->port_notifier);
     676                 :            : 
     677                 :        186 :     fat_rwlock_wrlock(&dpif->upcall_lock);
     678                 :        186 :     destroy_all_channels(dpif);
     679                 :        186 :     fat_rwlock_unlock(&dpif->upcall_lock);
     680                 :            : 
     681                 :        186 :     fat_rwlock_destroy(&dpif->upcall_lock);
     682                 :        186 :     free(dpif);
     683                 :        186 : }
     684                 :            : 
     685                 :            : static int
     686                 :         64 : dpif_netlink_destroy(struct dpif *dpif_)
     687                 :            : {
     688                 :         64 :     struct dpif_netlink *dpif = dpif_netlink_cast(dpif_);
     689                 :            :     struct dpif_netlink_dp dp;
     690                 :            : 
     691                 :         64 :     dpif_netlink_dp_init(&dp);
     692                 :         64 :     dp.cmd = OVS_DP_CMD_DEL;
     693                 :         64 :     dp.dp_ifindex = dpif->dp_ifindex;
     694                 :         64 :     return dpif_netlink_dp_transact(&dp, NULL, NULL);
     695                 :            : }
     696                 :            : 
     697                 :            : static bool
     698                 :       5991 : dpif_netlink_run(struct dpif *dpif_)
     699                 :            : {
     700                 :       5991 :     struct dpif_netlink *dpif = dpif_netlink_cast(dpif_);
     701                 :            : 
     702         [ -  + ]:       5991 :     if (dpif->refresh_channels) {
     703                 :          0 :         dpif->refresh_channels = false;
     704                 :          0 :         fat_rwlock_wrlock(&dpif->upcall_lock);
     705                 :          0 :         dpif_netlink_refresh_channels(dpif, dpif->n_handlers);
     706                 :          0 :         fat_rwlock_unlock(&dpif->upcall_lock);
     707                 :            :     }
     708                 :       5991 :     return false;
     709                 :            : }
     710                 :            : 
     711                 :            : static int
     712                 :       1060 : dpif_netlink_get_stats(const struct dpif *dpif_, struct dpif_dp_stats *stats)
     713                 :            : {
     714                 :            :     struct dpif_netlink_dp dp;
     715                 :            :     struct ofpbuf *buf;
     716                 :            :     int error;
     717                 :            : 
     718                 :       1060 :     error = dpif_netlink_dp_get(dpif_, &dp, &buf);
     719         [ +  - ]:       1060 :     if (!error) {
     720                 :       1060 :         memset(stats, 0, sizeof *stats);
     721                 :            : 
     722         [ +  - ]:       1060 :         if (dp.stats) {
     723                 :       1060 :             stats->n_hit    = get_32aligned_u64(&dp.stats->n_hit);
     724                 :       1060 :             stats->n_missed = get_32aligned_u64(&dp.stats->n_missed);
     725                 :       1060 :             stats->n_lost   = get_32aligned_u64(&dp.stats->n_lost);
     726                 :       1060 :             stats->n_flows  = get_32aligned_u64(&dp.stats->n_flows);
     727                 :            :         }
     728                 :            : 
     729         [ +  - ]:       1060 :         if (dp.megaflow_stats) {
     730                 :       1060 :             stats->n_masks = dp.megaflow_stats->n_masks;
     731                 :       1060 :             stats->n_mask_hit = get_32aligned_u64(
     732                 :       1060 :                 &dp.megaflow_stats->n_mask_hit);
     733                 :            :         } else {
     734                 :          0 :             stats->n_masks = UINT32_MAX;
     735                 :          0 :             stats->n_mask_hit = UINT64_MAX;
     736                 :            :         }
     737                 :       1060 :         ofpbuf_delete(buf);
     738                 :            :     }
     739                 :       1060 :     return error;
     740                 :            : }
     741                 :            : 
     742                 :            : static const char *
     743                 :       4054 : get_vport_type(const struct dpif_netlink_vport *vport)
     744                 :            : {
     745                 :            :     static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 20);
     746                 :            : 
     747   [ +  +  -  +  :       4054 :     switch (vport->type) {
             +  -  -  -  
                      - ]
     748                 :            :     case OVS_VPORT_TYPE_NETDEV: {
     749                 :       2160 :         const char *type = netdev_get_type_from_name(vport->name);
     750                 :            : 
     751         [ +  - ]:       2160 :         return type ? type : "system";
     752                 :            :     }
     753                 :            : 
     754                 :            :     case OVS_VPORT_TYPE_INTERNAL:
     755                 :       1889 :         return "internal";
     756                 :            : 
     757                 :            :     case OVS_VPORT_TYPE_GENEVE:
     758                 :          0 :         return "geneve";
     759                 :            : 
     760                 :            :     case OVS_VPORT_TYPE_GRE:
     761                 :          2 :         return "gre";
     762                 :            : 
     763                 :            :     case OVS_VPORT_TYPE_VXLAN:
     764                 :          3 :         return "vxlan";
     765                 :            : 
     766                 :            :     case OVS_VPORT_TYPE_LISP:
     767                 :          0 :         return "lisp";
     768                 :            : 
     769                 :            :     case OVS_VPORT_TYPE_STT:
     770                 :          0 :         return "stt";
     771                 :            : 
     772                 :            :     case OVS_VPORT_TYPE_UNSPEC:
     773                 :            :     case __OVS_VPORT_TYPE_MAX:
     774                 :          0 :         break;
     775                 :            :     }
     776                 :            : 
     777         [ #  # ]:          0 :     VLOG_WARN_RL(&rl, "dp%d: port `%s' has unsupported type %u",
     778                 :            :                  vport->dp_ifindex, vport->name, (unsigned int) vport->type);
     779                 :          0 :     return "unknown";
     780                 :            : }
     781                 :            : 
     782                 :            : static enum ovs_vport_type
     783                 :        232 : netdev_to_ovs_vport_type(const struct netdev *netdev)
     784                 :            : {
     785                 :        232 :     const char *type = netdev_get_type(netdev);
     786                 :            : 
     787 [ +  - ][ +  + ]:        232 :     if (!strcmp(type, "tap") || !strcmp(type, "system")) {
     788                 :        151 :         return OVS_VPORT_TYPE_NETDEV;
     789         [ +  + ]:         81 :     } else if (!strcmp(type, "internal")) {
     790                 :         76 :         return OVS_VPORT_TYPE_INTERNAL;
     791         [ -  + ]:          5 :     } else if (strstr(type, "stt")) {
     792                 :          0 :         return OVS_VPORT_TYPE_STT;
     793         [ -  + ]:          5 :     } else if (!strcmp(type, "geneve")) {
     794                 :          0 :         return OVS_VPORT_TYPE_GENEVE;
     795         [ +  + ]:          5 :     } else if (strstr(type, "gre")) {
     796                 :          2 :         return OVS_VPORT_TYPE_GRE;
     797         [ +  - ]:          3 :     } else if (!strcmp(type, "vxlan")) {
     798                 :          3 :         return OVS_VPORT_TYPE_VXLAN;
     799         [ #  # ]:          0 :     } else if (!strcmp(type, "lisp")) {
     800                 :          0 :         return OVS_VPORT_TYPE_LISP;
     801                 :            :     } else {
     802                 :          0 :         return OVS_VPORT_TYPE_UNSPEC;
     803                 :            :     }
     804                 :            : }
     805                 :            : 
     806                 :            : static int
     807                 :        232 : dpif_netlink_port_add__(struct dpif_netlink *dpif, struct netdev *netdev,
     808                 :            :                         odp_port_t *port_nop)
     809                 :            :     OVS_REQ_WRLOCK(dpif->upcall_lock)
     810                 :            : {
     811                 :            :     const struct netdev_tunnel_config *tnl_cfg;
     812                 :            :     char namebuf[NETDEV_VPORT_NAME_BUFSIZE];
     813                 :        232 :     const char *name = netdev_vport_get_dpif_port(netdev,
     814                 :            :                                                   namebuf, sizeof namebuf);
     815                 :        232 :     const char *type = netdev_get_type(netdev);
     816                 :            :     struct dpif_netlink_vport request, reply;
     817                 :            :     struct ofpbuf *buf;
     818                 :            :     uint64_t options_stub[64 / 8];
     819                 :            :     struct ofpbuf options;
     820                 :        232 :     struct nl_sock **socksp = NULL;
     821                 :            :     uint32_t *upcall_pids;
     822                 :        232 :     int error = 0;
     823                 :            : 
     824         [ +  - ]:        232 :     if (dpif->handlers) {
     825                 :        232 :         socksp = vport_create_socksp(dpif, &error);
     826         [ -  + ]:        232 :         if (!socksp) {
     827                 :          0 :             return error;
     828                 :            :         }
     829                 :            :     }
     830                 :            : 
     831                 :        232 :     dpif_netlink_vport_init(&request);
     832                 :        232 :     request.cmd = OVS_VPORT_CMD_NEW;
     833                 :        232 :     request.dp_ifindex = dpif->dp_ifindex;
     834                 :        232 :     request.type = netdev_to_ovs_vport_type(netdev);
     835         [ -  + ]:        232 :     if (request.type == OVS_VPORT_TYPE_UNSPEC) {
     836         [ #  # ]:          0 :         VLOG_WARN_RL(&error_rl, "%s: cannot create port `%s' because it has "
     837                 :            :                      "unsupported type `%s'",
     838                 :            :                      dpif_name(&dpif->dpif), name, type);
     839                 :          0 :         vport_del_socksp(dpif, socksp);
     840                 :          0 :         return EINVAL;
     841                 :            :     }
     842                 :        232 :     request.name = name;
     843                 :            : 
     844         [ +  + ]:        232 :     if (request.type == OVS_VPORT_TYPE_NETDEV) {
     845                 :            : #ifdef _WIN32
     846                 :            :         /* XXX : Map appropiate Windows handle */
     847                 :            : #else
     848                 :        151 :         netdev_linux_ethtool_set_flag(netdev, ETH_FLAG_LRO, "LRO", false);
     849                 :            : #endif
     850                 :            :     }
     851                 :            : 
     852                 :        232 :     tnl_cfg = netdev_get_tunnel_config(netdev);
     853 [ +  + ][ +  + ]:        232 :     if (tnl_cfg && (tnl_cfg->dst_port != 0 || tnl_cfg->exts)) {
                 [ -  + ]
     854                 :          3 :         ofpbuf_use_stack(&options, options_stub, sizeof options_stub);
     855         [ +  - ]:          3 :         if (tnl_cfg->dst_port) {
     856                 :          3 :             nl_msg_put_u16(&options, OVS_TUNNEL_ATTR_DST_PORT,
     857                 :          3 :                            ntohs(tnl_cfg->dst_port));
     858                 :            :         }
     859         [ -  + ]:          3 :         if (tnl_cfg->exts) {
     860                 :            :             size_t ext_ofs;
     861                 :            :             int i;
     862                 :            : 
     863                 :          0 :             ext_ofs = nl_msg_start_nested(&options, OVS_TUNNEL_ATTR_EXTENSION);
     864         [ #  # ]:          0 :             for (i = 0; i < 32; i++) {
     865         [ #  # ]:          0 :                 if (tnl_cfg->exts & (1 << i)) {
     866                 :          0 :                     nl_msg_put_flag(&options, i);
     867                 :            :                 }
     868                 :            :             }
     869                 :          0 :             nl_msg_end_nested(&options, ext_ofs);
     870                 :            :         }
     871                 :          3 :         request.options = options.data;
     872                 :          3 :         request.options_len = options.size;
     873                 :            :     }
     874                 :            : 
     875                 :        232 :     request.port_no = *port_nop;
     876                 :        232 :     upcall_pids = vport_socksp_to_pids(socksp, dpif->n_handlers);
     877         [ +  - ]:        232 :     request.n_upcall_pids = socksp ? dpif->n_handlers : 1;
     878                 :        232 :     request.upcall_pids = upcall_pids;
     879                 :            : 
     880                 :        232 :     error = dpif_netlink_vport_transact(&request, &reply, &buf);
     881         [ +  - ]:        232 :     if (!error) {
     882                 :        232 :         *port_nop = reply.port_no;
     883                 :            :     } else {
     884 [ #  # ][ #  # ]:          0 :         if (error == EBUSY && *port_nop != ODPP_NONE) {
     885         [ #  # ]:          0 :             VLOG_INFO("%s: requested port %"PRIu32" is in use",
     886                 :            :                       dpif_name(&dpif->dpif), *port_nop);
     887                 :            :         }
     888                 :            : 
     889                 :          0 :         vport_del_socksp(dpif, socksp);
     890                 :          0 :         goto exit;
     891                 :            :     }
     892                 :            : 
     893         [ +  - ]:        232 :     if (socksp) {
     894                 :        232 :         error = vport_add_channels(dpif, *port_nop, socksp);
     895         [ -  + ]:        232 :         if (error) {
     896         [ #  # ]:          0 :             VLOG_INFO("%s: could not add channel for port %s",
     897                 :            :                       dpif_name(&dpif->dpif), name);
     898                 :            : 
     899                 :            :             /* Delete the port. */
     900                 :          0 :             dpif_netlink_vport_init(&request);
     901                 :          0 :             request.cmd = OVS_VPORT_CMD_DEL;
     902                 :          0 :             request.dp_ifindex = dpif->dp_ifindex;
     903                 :          0 :             request.port_no = *port_nop;
     904                 :          0 :             dpif_netlink_vport_transact(&request, NULL, NULL);
     905                 :          0 :             vport_del_socksp(dpif, socksp);
     906                 :          0 :             goto exit;
     907                 :            :         }
     908                 :            :     }
     909                 :        232 :     free(socksp);
     910                 :            : 
     911                 :            : exit:
     912                 :        232 :     ofpbuf_delete(buf);
     913                 :        232 :     free(upcall_pids);
     914                 :            : 
     915                 :        232 :     return error;
     916                 :            : }
     917                 :            : 
     918                 :            : static int
     919                 :        232 : dpif_netlink_port_add(struct dpif *dpif_, struct netdev *netdev,
     920                 :            :                       odp_port_t *port_nop)
     921                 :            : {
     922                 :        232 :     struct dpif_netlink *dpif = dpif_netlink_cast(dpif_);
     923                 :            :     int error;
     924                 :            : 
     925                 :        232 :     fat_rwlock_wrlock(&dpif->upcall_lock);
     926                 :        232 :     error = dpif_netlink_port_add__(dpif, netdev, port_nop);
     927                 :        232 :     fat_rwlock_unlock(&dpif->upcall_lock);
     928                 :            : 
     929                 :        232 :     return error;
     930                 :            : }
     931                 :            : 
     932                 :            : static int
     933                 :          0 : dpif_netlink_port_del__(struct dpif_netlink *dpif, odp_port_t port_no)
     934                 :            :     OVS_REQ_WRLOCK(dpif->upcall_lock)
     935                 :            : {
     936                 :            :     struct dpif_netlink_vport vport;
     937                 :            :     int error;
     938                 :            : 
     939                 :          0 :     dpif_netlink_vport_init(&vport);
     940                 :          0 :     vport.cmd = OVS_VPORT_CMD_DEL;
     941                 :          0 :     vport.dp_ifindex = dpif->dp_ifindex;
     942                 :          0 :     vport.port_no = port_no;
     943                 :          0 :     error = dpif_netlink_vport_transact(&vport, NULL, NULL);
     944                 :            : 
     945                 :          0 :     vport_del_channels(dpif, port_no);
     946                 :            : 
     947                 :          0 :     return error;
     948                 :            : }
     949                 :            : 
     950                 :            : static int
     951                 :          0 : dpif_netlink_port_del(struct dpif *dpif_, odp_port_t port_no)
     952                 :            : {
     953                 :          0 :     struct dpif_netlink *dpif = dpif_netlink_cast(dpif_);
     954                 :            :     int error;
     955                 :            : 
     956                 :          0 :     fat_rwlock_wrlock(&dpif->upcall_lock);
     957                 :          0 :     error = dpif_netlink_port_del__(dpif, port_no);
     958                 :          0 :     fat_rwlock_unlock(&dpif->upcall_lock);
     959                 :            : 
     960                 :          0 :     return error;
     961                 :            : }
     962                 :            : 
     963                 :            : static int
     964                 :       4097 : dpif_netlink_port_query__(const struct dpif_netlink *dpif, odp_port_t port_no,
     965                 :            :                           const char *port_name, struct dpif_port *dpif_port)
     966                 :            : {
     967                 :            :     struct dpif_netlink_vport request;
     968                 :            :     struct dpif_netlink_vport reply;
     969                 :            :     struct ofpbuf *buf;
     970                 :            :     int error;
     971                 :            : 
     972                 :       4097 :     dpif_netlink_vport_init(&request);
     973                 :       4097 :     request.cmd = OVS_VPORT_CMD_GET;
     974                 :       4097 :     request.dp_ifindex = dpif->dp_ifindex;
     975                 :       4097 :     request.port_no = port_no;
     976                 :       4097 :     request.name = port_name;
     977                 :            : 
     978                 :       4097 :     error = dpif_netlink_vport_transact(&request, &reply, &buf);
     979         [ +  + ]:       4097 :     if (!error) {
     980         [ -  + ]:       3851 :         if (reply.dp_ifindex != request.dp_ifindex) {
     981                 :            :             /* A query by name reported that 'port_name' is in some datapath
     982                 :            :              * other than 'dpif', but the caller wants to know about 'dpif'. */
     983                 :          0 :             error = ENODEV;
     984         [ +  - ]:       3851 :         } else if (dpif_port) {
     985                 :       3851 :             dpif_port->name = xstrdup(reply.name);
     986                 :       3851 :             dpif_port->type = xstrdup(get_vport_type(&reply));
     987                 :       3851 :             dpif_port->port_no = reply.port_no;
     988                 :            :         }
     989                 :       3851 :         ofpbuf_delete(buf);
     990                 :            :     }
     991                 :       4097 :     return error;
     992                 :            : }
     993                 :            : 
     994                 :            : static int
     995                 :          0 : dpif_netlink_port_query_by_number(const struct dpif *dpif_, odp_port_t port_no,
     996                 :            :                                   struct dpif_port *dpif_port)
     997                 :            : {
     998                 :          0 :     struct dpif_netlink *dpif = dpif_netlink_cast(dpif_);
     999                 :            : 
    1000                 :          0 :     return dpif_netlink_port_query__(dpif, port_no, NULL, dpif_port);
    1001                 :            : }
    1002                 :            : 
    1003                 :            : static int
    1004                 :       4097 : dpif_netlink_port_query_by_name(const struct dpif *dpif_, const char *devname,
    1005                 :            :                               struct dpif_port *dpif_port)
    1006                 :            : {
    1007                 :       4097 :     struct dpif_netlink *dpif = dpif_netlink_cast(dpif_);
    1008                 :            : 
    1009                 :       4097 :     return dpif_netlink_port_query__(dpif, 0, devname, dpif_port);
    1010                 :            : }
    1011                 :            : 
    1012                 :            : static uint32_t
    1013                 :        242 : dpif_netlink_port_get_pid__(const struct dpif_netlink *dpif,
    1014                 :            :                             odp_port_t port_no, uint32_t hash)
    1015                 :            :     OVS_REQ_RDLOCK(dpif->upcall_lock)
    1016                 :            : {
    1017                 :        242 :     uint32_t port_idx = odp_to_u32(port_no);
    1018                 :        242 :     uint32_t pid = 0;
    1019                 :            : 
    1020 [ +  - ][ +  - ]:        242 :     if (dpif->handlers && dpif->uc_array_size > 0) {
    1021                 :            :         /* The ODPP_NONE "reserved" port number uses the "ovs-system"'s
    1022                 :            :          * channel, since it is not heavily loaded. */
    1023         [ +  + ]:        242 :         uint32_t idx = port_idx >= dpif->uc_array_size ? 0 : port_idx;
    1024                 :        242 :         struct dpif_handler *h = &dpif->handlers[hash % dpif->n_handlers];
    1025                 :            : 
    1026                 :            :         /* Needs to check in case the socket pointer is changed in between
    1027                 :            :          * the holding of upcall_lock.  A known case happens when the main
    1028                 :            :          * thread deletes the vport while the handler thread is handling
    1029                 :            :          * the upcall from that port. */
    1030         [ +  - ]:        242 :         if (h->channels[idx].sock) {
    1031                 :        242 :             pid = nl_sock_pid(h->channels[idx].sock);
    1032                 :            :         }
    1033                 :            :     }
    1034                 :            : 
    1035                 :        242 :     return pid;
    1036                 :            : }
    1037                 :            : 
    1038                 :            : static uint32_t
    1039                 :        242 : dpif_netlink_port_get_pid(const struct dpif *dpif_, odp_port_t port_no,
    1040                 :            :                           uint32_t hash)
    1041                 :            : {
    1042                 :        242 :     const struct dpif_netlink *dpif = dpif_netlink_cast(dpif_);
    1043                 :            :     uint32_t ret;
    1044                 :            : 
    1045                 :        242 :     fat_rwlock_rdlock(&dpif->upcall_lock);
    1046                 :        242 :     ret = dpif_netlink_port_get_pid__(dpif, port_no, hash);
    1047                 :        242 :     fat_rwlock_unlock(&dpif->upcall_lock);
    1048                 :            : 
    1049                 :        242 :     return ret;
    1050                 :            : }
    1051                 :            : 
    1052                 :            : static int
    1053                 :        137 : dpif_netlink_flow_flush(struct dpif *dpif_)
    1054                 :            : {
    1055                 :        137 :     const struct dpif_netlink *dpif = dpif_netlink_cast(dpif_);
    1056                 :            :     struct dpif_netlink_flow flow;
    1057                 :            : 
    1058                 :        137 :     dpif_netlink_flow_init(&flow);
    1059                 :        137 :     flow.cmd = OVS_FLOW_CMD_DEL;
    1060                 :        137 :     flow.dp_ifindex = dpif->dp_ifindex;
    1061                 :        137 :     return dpif_netlink_flow_transact(&flow, NULL, NULL);
    1062                 :            : }
    1063                 :            : 
    1064                 :            : struct dpif_netlink_port_state {
    1065                 :            :     struct nl_dump dump;
    1066                 :            :     struct ofpbuf buf;
    1067                 :            : };
    1068                 :            : 
    1069                 :            : static void
    1070                 :        254 : dpif_netlink_port_dump_start__(const struct dpif_netlink *dpif,
    1071                 :            :                                struct nl_dump *dump)
    1072                 :            : {
    1073                 :            :     struct dpif_netlink_vport request;
    1074                 :            :     struct ofpbuf *buf;
    1075                 :            : 
    1076                 :        254 :     dpif_netlink_vport_init(&request);
    1077                 :        254 :     request.cmd = OVS_VPORT_CMD_GET;
    1078                 :        254 :     request.dp_ifindex = dpif->dp_ifindex;
    1079                 :            : 
    1080                 :        254 :     buf = ofpbuf_new(1024);
    1081                 :        254 :     dpif_netlink_vport_to_ofpbuf(&request, buf);
    1082                 :        254 :     nl_dump_start(dump, NETLINK_GENERIC, buf);
    1083                 :        254 :     ofpbuf_delete(buf);
    1084                 :        254 : }
    1085                 :            : 
    1086                 :            : static int
    1087                 :        128 : dpif_netlink_port_dump_start(const struct dpif *dpif_, void **statep)
    1088                 :            : {
    1089                 :        128 :     struct dpif_netlink *dpif = dpif_netlink_cast(dpif_);
    1090                 :            :     struct dpif_netlink_port_state *state;
    1091                 :            : 
    1092                 :        128 :     *statep = state = xmalloc(sizeof *state);
    1093                 :        128 :     dpif_netlink_port_dump_start__(dpif, &state->dump);
    1094                 :            : 
    1095                 :        128 :     ofpbuf_init(&state->buf, NL_DUMP_BUFSIZE);
    1096                 :        128 :     return 0;
    1097                 :            : }
    1098                 :            : 
    1099                 :            : static int
    1100                 :        583 : dpif_netlink_port_dump_next__(const struct dpif_netlink *dpif,
    1101                 :            :                               struct nl_dump *dump,
    1102                 :            :                               struct dpif_netlink_vport *vport,
    1103                 :            :                               struct ofpbuf *buffer)
    1104                 :            : {
    1105                 :            :     struct ofpbuf buf;
    1106                 :            :     int error;
    1107                 :            : 
    1108         [ +  + ]:        583 :     if (!nl_dump_next(dump, &buf, buffer)) {
    1109                 :        254 :         return EOF;
    1110                 :            :     }
    1111                 :            : 
    1112                 :        329 :     error = dpif_netlink_vport_from_ofpbuf(vport, &buf);
    1113         [ -  + ]:        329 :     if (error) {
    1114         [ #  # ]:          0 :         VLOG_WARN_RL(&error_rl, "%s: failed to parse vport record (%s)",
    1115                 :            :                      dpif_name(&dpif->dpif), ovs_strerror(error));
    1116                 :            :     }
    1117                 :        583 :     return error;
    1118                 :            : }
    1119                 :            : 
    1120                 :            : static int
    1121                 :        331 : dpif_netlink_port_dump_next(const struct dpif *dpif_, void *state_,
    1122                 :            :                             struct dpif_port *dpif_port)
    1123                 :            : {
    1124                 :        331 :     struct dpif_netlink *dpif = dpif_netlink_cast(dpif_);
    1125                 :        331 :     struct dpif_netlink_port_state *state = state_;
    1126                 :            :     struct dpif_netlink_vport vport;
    1127                 :            :     int error;
    1128                 :            : 
    1129                 :        331 :     error = dpif_netlink_port_dump_next__(dpif, &state->dump, &vport,
    1130                 :            :                                           &state->buf);
    1131         [ +  + ]:        331 :     if (error) {
    1132                 :        128 :         return error;
    1133                 :            :     }
    1134                 :        203 :     dpif_port->name = CONST_CAST(char *, vport.name);
    1135                 :        203 :     dpif_port->type = CONST_CAST(char *, get_vport_type(&vport));
    1136                 :        203 :     dpif_port->port_no = vport.port_no;
    1137                 :        331 :     return 0;
    1138                 :            : }
    1139                 :            : 
    1140                 :            : static int
    1141                 :        128 : dpif_netlink_port_dump_done(const struct dpif *dpif_ OVS_UNUSED, void *state_)
    1142                 :            : {
    1143                 :        128 :     struct dpif_netlink_port_state *state = state_;
    1144                 :        128 :     int error = nl_dump_done(&state->dump);
    1145                 :            : 
    1146                 :        128 :     ofpbuf_uninit(&state->buf);
    1147                 :        128 :     free(state);
    1148                 :        128 :     return error;
    1149                 :            : }
    1150                 :            : 
    1151                 :            : static int
    1152                 :       6222 : dpif_netlink_port_poll(const struct dpif *dpif_, char **devnamep)
    1153                 :            : {
    1154                 :       6222 :     struct dpif_netlink *dpif = dpif_netlink_cast(dpif_);
    1155                 :            : 
    1156                 :            :     /* Lazily create the Netlink socket to listen for notifications. */
    1157         [ +  + ]:       6222 :     if (!dpif->port_notifier) {
    1158                 :            :         struct nl_sock *sock;
    1159                 :            :         int error;
    1160                 :            : 
    1161                 :         63 :         error = nl_sock_create(NETLINK_GENERIC, &sock);
    1162         [ -  + ]:         63 :         if (error) {
    1163                 :          0 :             return error;
    1164                 :            :         }
    1165                 :            : 
    1166                 :         63 :         error = nl_sock_join_mcgroup(sock, ovs_vport_mcgroup);
    1167         [ -  + ]:         63 :         if (error) {
    1168                 :          0 :             nl_sock_destroy(sock);
    1169                 :          0 :             return error;
    1170                 :            :         }
    1171                 :         63 :         dpif->port_notifier = sock;
    1172                 :            : 
    1173                 :            :         /* We have no idea of the current state so report that everything
    1174                 :            :          * changed. */
    1175                 :         63 :         return ENOBUFS;
    1176                 :            :     }
    1177                 :            : 
    1178                 :            :     for (;;) {
    1179                 :            :         static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
    1180                 :            :         uint64_t buf_stub[4096 / 8];
    1181                 :            :         struct ofpbuf buf;
    1182                 :            :         int error;
    1183                 :            : 
    1184                 :       6159 :         ofpbuf_use_stub(&buf, buf_stub, sizeof buf_stub);
    1185                 :       6159 :         error = nl_sock_recv(dpif->port_notifier, &buf, false);
    1186         [ +  + ]:       6159 :         if (!error) {
    1187                 :            :             struct dpif_netlink_vport vport;
    1188                 :            : 
    1189                 :        168 :             error = dpif_netlink_vport_from_ofpbuf(&vport, &buf);
    1190         [ +  - ]:        168 :             if (!error) {
    1191         [ +  - ]:        168 :                 if (vport.dp_ifindex == dpif->dp_ifindex
    1192         [ -  + ]:        168 :                     && (vport.cmd == OVS_VPORT_CMD_NEW
    1193         [ #  # ]:          0 :                         || vport.cmd == OVS_VPORT_CMD_DEL
    1194         [ #  # ]:          0 :                         || vport.cmd == OVS_VPORT_CMD_SET)) {
    1195         [ -  + ]:        168 :                     VLOG_DBG("port_changed: dpif:%s vport:%s cmd:%"PRIu8,
    1196                 :            :                              dpif->dpif.full_name, vport.name, vport.cmd);
    1197 [ -  + ][ #  # ]:        168 :                     if (vport.cmd == OVS_VPORT_CMD_DEL && dpif->handlers) {
    1198                 :          0 :                         dpif->refresh_channels = true;
    1199                 :            :                     }
    1200                 :        168 :                     *devnamep = xstrdup(vport.name);
    1201                 :        168 :                     ofpbuf_uninit(&buf);
    1202                 :        168 :                     return 0;
    1203                 :            :                 }
    1204                 :            :             }
    1205         [ -  + ]:       5991 :         } else if (error != EAGAIN) {
    1206         [ #  # ]:          0 :             VLOG_WARN_RL(&rl, "error reading or parsing netlink (%s)",
    1207                 :            :                          ovs_strerror(error));
    1208                 :          0 :             nl_sock_drain(dpif->port_notifier);
    1209                 :          0 :             error = ENOBUFS;
    1210                 :            :         }
    1211                 :            : 
    1212                 :       5991 :         ofpbuf_uninit(&buf);
    1213         [ +  - ]:       5991 :         if (error) {
    1214                 :       5991 :             return error;
    1215                 :            :         }
    1216                 :       6159 :     }
    1217                 :            : }
    1218                 :            : 
    1219                 :            : static void
    1220                 :       6356 : dpif_netlink_port_poll_wait(const struct dpif *dpif_)
    1221                 :            : {
    1222                 :       6356 :     const struct dpif_netlink *dpif = dpif_netlink_cast(dpif_);
    1223                 :            : 
    1224         [ +  - ]:       6356 :     if (dpif->port_notifier) {
    1225                 :       6356 :         nl_sock_wait(dpif->port_notifier, POLLIN);
    1226                 :            :     } else {
    1227                 :          0 :         poll_immediate_wake();
    1228                 :            :     }
    1229                 :       6356 : }
    1230                 :            : 
    1231                 :            : static void
    1232                 :       4371 : dpif_netlink_flow_init_ufid(struct dpif_netlink_flow *request,
    1233                 :            :                             const ovs_u128 *ufid, bool terse)
    1234                 :            : {
    1235         [ +  + ]:       4371 :     if (ufid) {
    1236                 :       2985 :         request->ufid = *ufid;
    1237                 :       2985 :         request->ufid_present = true;
    1238                 :            :     } else {
    1239                 :       1386 :         request->ufid_present = false;
    1240                 :            :     }
    1241                 :       4371 :     request->ufid_terse = terse;
    1242                 :       4371 : }
    1243                 :            : 
    1244                 :            : static void
    1245                 :        567 : dpif_netlink_init_flow_get__(const struct dpif_netlink *dpif,
    1246                 :            :                              const struct nlattr *key, size_t key_len,
    1247                 :            :                              const ovs_u128 *ufid, bool terse,
    1248                 :            :                              struct dpif_netlink_flow *request)
    1249                 :            : {
    1250                 :        567 :     dpif_netlink_flow_init(request);
    1251                 :        567 :     request->cmd = OVS_FLOW_CMD_GET;
    1252                 :        567 :     request->dp_ifindex = dpif->dp_ifindex;
    1253                 :        567 :     request->key = key;
    1254                 :        567 :     request->key_len = key_len;
    1255                 :        567 :     dpif_netlink_flow_init_ufid(request, ufid, terse);
    1256                 :        567 : }
    1257                 :            : 
    1258                 :            : static void
    1259                 :        567 : dpif_netlink_init_flow_get(const struct dpif_netlink *dpif,
    1260                 :            :                            const struct dpif_flow_get *get,
    1261                 :            :                            struct dpif_netlink_flow *request)
    1262                 :            : {
    1263                 :        567 :     dpif_netlink_init_flow_get__(dpif, get->key, get->key_len, get->ufid,
    1264                 :            :                                  false, request);
    1265                 :        567 : }
    1266                 :            : 
    1267                 :            : static int
    1268                 :          0 : dpif_netlink_flow_get__(const struct dpif_netlink *dpif,
    1269                 :            :                         const struct nlattr *key, size_t key_len,
    1270                 :            :                         const ovs_u128 *ufid, bool terse,
    1271                 :            :                         struct dpif_netlink_flow *reply, struct ofpbuf **bufp)
    1272                 :            : {
    1273                 :            :     struct dpif_netlink_flow request;
    1274                 :            : 
    1275                 :          0 :     dpif_netlink_init_flow_get__(dpif, key, key_len, ufid, terse, &request);
    1276                 :          0 :     return dpif_netlink_flow_transact(&request, reply, bufp);
    1277                 :            : }
    1278                 :            : 
    1279                 :            : static int
    1280                 :          0 : dpif_netlink_flow_get(const struct dpif_netlink *dpif,
    1281                 :            :                       const struct dpif_netlink_flow *flow,
    1282                 :            :                       struct dpif_netlink_flow *reply, struct ofpbuf **bufp)
    1283                 :            : {
    1284         [ #  # ]:          0 :     return dpif_netlink_flow_get__(dpif, flow->key, flow->key_len,
    1285                 :          0 :                                    flow->ufid_present ? &flow->ufid : NULL,
    1286                 :            :                                    false, reply, bufp);
    1287                 :            : }
    1288                 :            : 
    1289                 :            : static void
    1290                 :       1981 : dpif_netlink_init_flow_put(struct dpif_netlink *dpif,
    1291                 :            :                            const struct dpif_flow_put *put,
    1292                 :            :                            struct dpif_netlink_flow *request)
    1293                 :            : {
    1294                 :            :     static const struct nlattr dummy_action;
    1295                 :            : 
    1296                 :       1981 :     dpif_netlink_flow_init(request);
    1297         [ +  + ]:       1981 :     request->cmd = (put->flags & DPIF_FP_CREATE
    1298                 :            :                     ? OVS_FLOW_CMD_NEW : OVS_FLOW_CMD_SET);
    1299                 :       1981 :     request->dp_ifindex = dpif->dp_ifindex;
    1300                 :       1981 :     request->key = put->key;
    1301                 :       1981 :     request->key_len = put->key_len;
    1302                 :       1981 :     request->mask = put->mask;
    1303                 :       1981 :     request->mask_len = put->mask_len;
    1304                 :       1981 :     dpif_netlink_flow_init_ufid(request, put->ufid, false);
    1305                 :            : 
    1306                 :            :     /* Ensure that OVS_FLOW_ATTR_ACTIONS will always be included. */
    1307                 :       3962 :     request->actions = (put->actions
    1308                 :            :                         ? put->actions
    1309         [ +  + ]:       1981 :                         : CONST_CAST(struct nlattr *, &dummy_action));
    1310                 :       1981 :     request->actions_len = put->actions_len;
    1311         [ -  + ]:       1981 :     if (put->flags & DPIF_FP_ZERO_STATS) {
    1312                 :          0 :         request->clear = true;
    1313                 :            :     }
    1314         [ +  + ]:       1981 :     if (put->flags & DPIF_FP_PROBE) {
    1315                 :        567 :         request->probe = true;
    1316                 :            :     }
    1317         [ +  + ]:       1981 :     request->nlmsg_flags = put->flags & DPIF_FP_MODIFY ? 0 : NLM_F_CREATE;
    1318                 :       1981 : }
    1319                 :            : 
    1320                 :            : static void
    1321                 :       1823 : dpif_netlink_init_flow_del__(struct dpif_netlink *dpif,
    1322                 :            :                              const struct nlattr *key, size_t key_len,
    1323                 :            :                              const ovs_u128 *ufid, bool terse,
    1324                 :            :                              struct dpif_netlink_flow *request)
    1325                 :            : {
    1326                 :       1823 :     dpif_netlink_flow_init(request);
    1327                 :       1823 :     request->cmd = OVS_FLOW_CMD_DEL;
    1328                 :       1823 :     request->dp_ifindex = dpif->dp_ifindex;
    1329                 :       1823 :     request->key = key;
    1330                 :       1823 :     request->key_len = key_len;
    1331                 :       1823 :     dpif_netlink_flow_init_ufid(request, ufid, terse);
    1332                 :       1823 : }
    1333                 :            : 
    1334                 :            : static void
    1335                 :       1823 : dpif_netlink_init_flow_del(struct dpif_netlink *dpif,
    1336                 :            :                            const struct dpif_flow_del *del,
    1337                 :            :                            struct dpif_netlink_flow *request)
    1338                 :            : {
    1339                 :       1823 :     dpif_netlink_init_flow_del__(dpif, del->key, del->key_len,
    1340                 :       1823 :                                  del->ufid, del->terse, request);
    1341                 :       1823 : }
    1342                 :            : 
    1343                 :            : struct dpif_netlink_flow_dump {
    1344                 :            :     struct dpif_flow_dump up;
    1345                 :            :     struct nl_dump nl_dump;
    1346                 :            :     atomic_int status;
    1347                 :            : };
    1348                 :            : 
    1349                 :            : static struct dpif_netlink_flow_dump *
    1350                 :       4410 : dpif_netlink_flow_dump_cast(struct dpif_flow_dump *dump)
    1351                 :            : {
    1352                 :       4410 :     return CONTAINER_OF(dump, struct dpif_netlink_flow_dump, up);
    1353                 :            : }
    1354                 :            : 
    1355                 :            : static struct dpif_flow_dump *
    1356                 :       2205 : dpif_netlink_flow_dump_create(const struct dpif *dpif_, bool terse)
    1357                 :            : {
    1358                 :       2205 :     const struct dpif_netlink *dpif = dpif_netlink_cast(dpif_);
    1359                 :            :     struct dpif_netlink_flow_dump *dump;
    1360                 :            :     struct dpif_netlink_flow request;
    1361                 :            :     struct ofpbuf *buf;
    1362                 :            : 
    1363                 :       2205 :     dump = xmalloc(sizeof *dump);
    1364                 :       2205 :     dpif_flow_dump_init(&dump->up, dpif_);
    1365                 :            : 
    1366                 :       2205 :     dpif_netlink_flow_init(&request);
    1367                 :       2205 :     request.cmd = OVS_FLOW_CMD_GET;
    1368                 :       2205 :     request.dp_ifindex = dpif->dp_ifindex;
    1369                 :       2205 :     request.ufid_present = false;
    1370                 :       2205 :     request.ufid_terse = terse;
    1371                 :            : 
    1372                 :       2205 :     buf = ofpbuf_new(1024);
    1373                 :       2205 :     dpif_netlink_flow_to_ofpbuf(&request, buf);
    1374                 :       2205 :     nl_dump_start(&dump->nl_dump, NETLINK_GENERIC, buf);
    1375                 :       2205 :     ofpbuf_delete(buf);
    1376                 :       2205 :     atomic_init(&dump->status, 0);
    1377                 :       2205 :     dump->up.terse = terse;
    1378                 :            : 
    1379                 :       2205 :     return &dump->up;
    1380                 :            : }
    1381                 :            : 
    1382                 :            : static int
    1383                 :       2205 : dpif_netlink_flow_dump_destroy(struct dpif_flow_dump *dump_)
    1384                 :            : {
    1385                 :       2205 :     struct dpif_netlink_flow_dump *dump = dpif_netlink_flow_dump_cast(dump_);
    1386                 :       2205 :     unsigned int nl_status = nl_dump_done(&dump->nl_dump);
    1387                 :            :     int dump_status;
    1388                 :            : 
    1389                 :            :     /* No other thread has access to 'dump' at this point. */
    1390                 :       2205 :     atomic_read_relaxed(&dump->status, &dump_status);
    1391                 :       2205 :     free(dump);
    1392         [ -  + ]:       2205 :     return dump_status ? dump_status : nl_status;
    1393                 :            : }
    1394                 :            : 
    1395                 :            : struct dpif_netlink_flow_dump_thread {
    1396                 :            :     struct dpif_flow_dump_thread up;
    1397                 :            :     struct dpif_netlink_flow_dump *dump;
    1398                 :            :     struct dpif_netlink_flow flow;
    1399                 :            :     struct dpif_flow_stats stats;
    1400                 :            :     struct ofpbuf nl_flows;     /* Always used to store flows. */
    1401                 :            :     struct ofpbuf *nl_actions;  /* Used if kernel does not supply actions. */
    1402                 :            : };
    1403                 :            : 
    1404                 :            : static struct dpif_netlink_flow_dump_thread *
    1405                 :       5973 : dpif_netlink_flow_dump_thread_cast(struct dpif_flow_dump_thread *thread)
    1406                 :            : {
    1407                 :       5973 :     return CONTAINER_OF(thread, struct dpif_netlink_flow_dump_thread, up);
    1408                 :            : }
    1409                 :            : 
    1410                 :            : static struct dpif_flow_dump_thread *
    1411                 :       2205 : dpif_netlink_flow_dump_thread_create(struct dpif_flow_dump *dump_)
    1412                 :            : {
    1413                 :       2205 :     struct dpif_netlink_flow_dump *dump = dpif_netlink_flow_dump_cast(dump_);
    1414                 :            :     struct dpif_netlink_flow_dump_thread *thread;
    1415                 :            : 
    1416                 :       2205 :     thread = xmalloc(sizeof *thread);
    1417                 :       2205 :     dpif_flow_dump_thread_init(&thread->up, &dump->up);
    1418                 :       2205 :     thread->dump = dump;
    1419                 :       2205 :     ofpbuf_init(&thread->nl_flows, NL_DUMP_BUFSIZE);
    1420                 :       2205 :     thread->nl_actions = NULL;
    1421                 :            : 
    1422                 :       2205 :     return &thread->up;
    1423                 :            : }
    1424                 :            : 
    1425                 :            : static void
    1426                 :       2205 : dpif_netlink_flow_dump_thread_destroy(struct dpif_flow_dump_thread *thread_)
    1427                 :            : {
    1428                 :       2205 :     struct dpif_netlink_flow_dump_thread *thread
    1429                 :            :         = dpif_netlink_flow_dump_thread_cast(thread_);
    1430                 :            : 
    1431                 :       2205 :     ofpbuf_uninit(&thread->nl_flows);
    1432                 :       2205 :     ofpbuf_delete(thread->nl_actions);
    1433                 :       2205 :     free(thread);
    1434                 :       2205 : }
    1435                 :            : 
    1436                 :            : static void
    1437                 :       8422 : dpif_netlink_flow_to_dpif_flow(struct dpif *dpif, struct dpif_flow *dpif_flow,
    1438                 :            :                                const struct dpif_netlink_flow *datapath_flow)
    1439                 :            : {
    1440                 :       8422 :     dpif_flow->key = datapath_flow->key;
    1441                 :       8422 :     dpif_flow->key_len = datapath_flow->key_len;
    1442                 :       8422 :     dpif_flow->mask = datapath_flow->mask;
    1443                 :       8422 :     dpif_flow->mask_len = datapath_flow->mask_len;
    1444                 :       8422 :     dpif_flow->actions = datapath_flow->actions;
    1445                 :       8422 :     dpif_flow->actions_len = datapath_flow->actions_len;
    1446                 :       8422 :     dpif_flow->ufid_present = datapath_flow->ufid_present;
    1447                 :       8422 :     dpif_flow->pmd_id = PMD_ID_NULL;
    1448         [ +  + ]:       8422 :     if (datapath_flow->ufid_present) {
    1449                 :       7981 :         dpif_flow->ufid = datapath_flow->ufid;
    1450                 :            :     } else {
    1451 [ +  - ][ -  + ]:        441 :         ovs_assert(datapath_flow->key && datapath_flow->key_len);
    1452                 :        441 :         dpif_flow_hash(dpif, datapath_flow->key, datapath_flow->key_len,
    1453                 :            :                        &dpif_flow->ufid);
    1454                 :            :     }
    1455                 :       8422 :     dpif_netlink_flow_get_stats(datapath_flow, &dpif_flow->stats);
    1456                 :       8422 : }
    1457                 :            : 
    1458                 :            : static int
    1459                 :       3768 : dpif_netlink_flow_dump_next(struct dpif_flow_dump_thread *thread_,
    1460                 :            :                             struct dpif_flow *flows, int max_flows)
    1461                 :            : {
    1462                 :       3768 :     struct dpif_netlink_flow_dump_thread *thread
    1463                 :            :         = dpif_netlink_flow_dump_thread_cast(thread_);
    1464                 :       3768 :     struct dpif_netlink_flow_dump *dump = thread->dump;
    1465                 :       3768 :     struct dpif_netlink *dpif = dpif_netlink_cast(thread->up.dpif);
    1466                 :            :     int n_flows;
    1467                 :            : 
    1468                 :       3768 :     ofpbuf_delete(thread->nl_actions);
    1469                 :       3768 :     thread->nl_actions = NULL;
    1470                 :            : 
    1471                 :       3768 :     n_flows = 0;
    1472         [ +  + ]:      11623 :     while (!n_flows
    1473 [ +  + ][ +  + ]:       7855 :            || (n_flows < max_flows && thread->nl_flows.size)) {
    1474                 :            :         struct dpif_netlink_flow datapath_flow;
    1475                 :            :         struct ofpbuf nl_flow;
    1476                 :            :         int error;
    1477                 :            : 
    1478                 :            :         /* Try to grab another flow. */
    1479         [ +  + ]:      10060 :         if (!nl_dump_next(&dump->nl_dump, &nl_flow, &thread->nl_flows)) {
    1480                 :       2205 :             break;
    1481                 :            :         }
    1482                 :            : 
    1483                 :            :         /* Convert the flow to our output format. */
    1484                 :       7855 :         error = dpif_netlink_flow_from_ofpbuf(&datapath_flow, &nl_flow);
    1485         [ -  + ]:       7855 :         if (error) {
    1486                 :          0 :             atomic_store_relaxed(&dump->status, error);
    1487                 :          0 :             break;
    1488                 :            :         }
    1489                 :            : 
    1490 [ +  + ][ +  - ]:       7855 :         if (dump->up.terse || datapath_flow.actions) {
    1491                 :            :             /* Common case: we don't want actions, or the flow includes
    1492                 :            :              * actions. */
    1493                 :       7855 :             dpif_netlink_flow_to_dpif_flow(&dpif->dpif, &flows[n_flows++],
    1494                 :            :                                            &datapath_flow);
    1495                 :            :         } else {
    1496                 :            :             /* Rare case: the flow does not include actions.  Retrieve this
    1497                 :            :              * individual flow again to get the actions. */
    1498                 :          0 :             error = dpif_netlink_flow_get(dpif, &datapath_flow,
    1499                 :            :                                           &datapath_flow, &thread->nl_actions);
    1500         [ #  # ]:          0 :             if (error == ENOENT) {
    1501         [ #  # ]:          0 :                 VLOG_DBG("dumped flow disappeared on get");
    1502                 :          0 :                 continue;
    1503         [ #  # ]:          0 :             } else if (error) {
    1504         [ #  # ]:          0 :                 VLOG_WARN("error fetching dumped flow: %s",
    1505                 :            :                           ovs_strerror(error));
    1506                 :          0 :                 atomic_store_relaxed(&dump->status, error);
    1507                 :          0 :                 break;
    1508                 :            :             }
    1509                 :            : 
    1510                 :            :             /* Save this flow.  Then exit, because we only have one buffer to
    1511                 :            :              * handle this case. */
    1512                 :          0 :             dpif_netlink_flow_to_dpif_flow(&dpif->dpif, &flows[n_flows++],
    1513                 :            :                                            &datapath_flow);
    1514                 :          0 :             break;
    1515                 :            :         }
    1516                 :            :     }
    1517                 :       3768 :     return n_flows;
    1518                 :            : }
    1519                 :            : 
    1520                 :            : static void
    1521                 :       1217 : dpif_netlink_encode_execute(int dp_ifindex, const struct dpif_execute *d_exec,
    1522                 :            :                             struct ofpbuf *buf)
    1523                 :            : {
    1524                 :            :     struct ovs_header *k_exec;
    1525                 :            :     size_t key_ofs;
    1526                 :            : 
    1527                 :       1217 :     ofpbuf_prealloc_tailroom(buf, (64
    1528                 :       1217 :                                    + dp_packet_size(d_exec->packet)
    1529                 :       1217 :                                    + ODP_KEY_METADATA_SIZE
    1530                 :       1217 :                                    + d_exec->actions_len));
    1531                 :            : 
    1532                 :       1217 :     nl_msg_put_genlmsghdr(buf, 0, ovs_packet_family, NLM_F_REQUEST,
    1533                 :            :                           OVS_PACKET_CMD_EXECUTE, OVS_PACKET_VERSION);
    1534                 :            : 
    1535                 :       1217 :     k_exec = ofpbuf_put_uninit(buf, sizeof *k_exec);
    1536                 :       1217 :     k_exec->dp_ifindex = dp_ifindex;
    1537                 :            : 
    1538                 :       1217 :     nl_msg_put_unspec(buf, OVS_PACKET_ATTR_PACKET,
    1539                 :       1217 :                       dp_packet_data(d_exec->packet),
    1540                 :       1217 :                       dp_packet_size(d_exec->packet));
    1541                 :            : 
    1542                 :       1217 :     key_ofs = nl_msg_start_nested(buf, OVS_PACKET_ATTR_KEY);
    1543                 :       1217 :     odp_key_from_pkt_metadata(buf, &d_exec->packet->md);
    1544                 :       1217 :     nl_msg_end_nested(buf, key_ofs);
    1545                 :            : 
    1546                 :       1217 :     nl_msg_put_unspec(buf, OVS_PACKET_ATTR_ACTIONS,
    1547                 :       1217 :                       d_exec->actions, d_exec->actions_len);
    1548         [ +  + ]:       1217 :     if (d_exec->probe) {
    1549                 :        189 :         nl_msg_put_flag(buf, OVS_PACKET_ATTR_PROBE);
    1550                 :            :     }
    1551         [ +  + ]:       1217 :     if (d_exec->mtu) {
    1552                 :          6 :         nl_msg_put_u16(buf, OVS_PACKET_ATTR_MRU, d_exec->mtu);
    1553                 :            :     }
    1554                 :       1217 : }
    1555                 :            : 
    1556                 :            : /* Executes, against 'dpif', up to the first 'n_ops' operations in 'ops'.
    1557                 :            :  * Returns the number actually executed (at least 1, if 'n_ops' is
    1558                 :            :  * positive). */
    1559                 :            : static size_t
    1560                 :       4386 : dpif_netlink_operate__(struct dpif_netlink *dpif,
    1561                 :            :                        struct dpif_op **ops, size_t n_ops)
    1562                 :            : {
    1563                 :            :     enum { MAX_OPS = 50 };
    1564                 :            : 
    1565                 :            :     struct op_auxdata {
    1566                 :            :         struct nl_transaction txn;
    1567                 :            : 
    1568                 :            :         struct ofpbuf request;
    1569                 :            :         uint64_t request_stub[1024 / 8];
    1570                 :            : 
    1571                 :            :         struct ofpbuf reply;
    1572                 :            :         uint64_t reply_stub[1024 / 8];
    1573                 :            :     } auxes[MAX_OPS];
    1574                 :            : 
    1575                 :            :     struct nl_transaction *txnsp[MAX_OPS];
    1576                 :            :     size_t i;
    1577                 :            : 
    1578                 :       4386 :     n_ops = MIN(n_ops, MAX_OPS);
    1579         [ +  + ]:       9974 :     for (i = 0; i < n_ops; i++) {
    1580                 :       5588 :         struct op_auxdata *aux = &auxes[i];
    1581                 :       5588 :         struct dpif_op *op = ops[i];
    1582                 :            :         struct dpif_flow_put *put;
    1583                 :            :         struct dpif_flow_del *del;
    1584                 :            :         struct dpif_flow_get *get;
    1585                 :            :         struct dpif_netlink_flow flow;
    1586                 :            : 
    1587                 :       5588 :         ofpbuf_use_stub(&aux->request,
    1588                 :       5588 :                         aux->request_stub, sizeof aux->request_stub);
    1589                 :       5588 :         aux->txn.request = &aux->request;
    1590                 :            : 
    1591                 :       5588 :         ofpbuf_use_stub(&aux->reply, aux->reply_stub, sizeof aux->reply_stub);
    1592                 :       5588 :         aux->txn.reply = NULL;
    1593                 :            : 
    1594   [ +  +  +  +  :       5588 :         switch (op->type) {
                      - ]
    1595                 :            :         case DPIF_OP_FLOW_PUT:
    1596                 :       1981 :             put = &op->u.flow_put;
    1597                 :       1981 :             dpif_netlink_init_flow_put(dpif, put, &flow);
    1598         [ -  + ]:       1981 :             if (put->stats) {
    1599                 :          0 :                 flow.nlmsg_flags |= NLM_F_ECHO;
    1600                 :          0 :                 aux->txn.reply = &aux->reply;
    1601                 :            :             }
    1602                 :       1981 :             dpif_netlink_flow_to_ofpbuf(&flow, &aux->request);
    1603                 :       1981 :             break;
    1604                 :            : 
    1605                 :            :         case DPIF_OP_FLOW_DEL:
    1606                 :       1823 :             del = &op->u.flow_del;
    1607                 :       1823 :             dpif_netlink_init_flow_del(dpif, del, &flow);
    1608         [ +  + ]:       1823 :             if (del->stats) {
    1609                 :       1319 :                 flow.nlmsg_flags |= NLM_F_ECHO;
    1610                 :       1319 :                 aux->txn.reply = &aux->reply;
    1611                 :            :             }
    1612                 :       1823 :             dpif_netlink_flow_to_ofpbuf(&flow, &aux->request);
    1613                 :       1823 :             break;
    1614                 :            : 
    1615                 :            :         case DPIF_OP_EXECUTE:
    1616                 :            :             /* Can't execute a packet that won't fit in a Netlink attribute. */
    1617         [ -  + ]:       1217 :             if (OVS_UNLIKELY(nl_attr_oversized(
    1618                 :            :                                  dp_packet_size(op->u.execute.packet)))) {
    1619                 :            :                 /* Report an error immediately if this is the first operation.
    1620                 :            :                  * Otherwise the easiest thing to do is to postpone to the next
    1621                 :            :                  * call (when this will be the first operation). */
    1622         [ #  # ]:          0 :                 if (i == 0) {
    1623         [ #  # ]:          0 :                     VLOG_ERR_RL(&error_rl,
    1624                 :            :                                 "dropping oversized %"PRIu32"-byte packet",
    1625                 :            :                                 dp_packet_size(op->u.execute.packet));
    1626                 :          0 :                     op->error = ENOBUFS;
    1627                 :          0 :                     return 1;
    1628                 :            :                 }
    1629                 :          0 :                 n_ops = i;
    1630                 :            :             } else {
    1631                 :       1217 :                 dpif_netlink_encode_execute(dpif->dp_ifindex, &op->u.execute,
    1632                 :            :                                             &aux->request);
    1633                 :            :             }
    1634                 :       1217 :             break;
    1635                 :            : 
    1636                 :            :         case DPIF_OP_FLOW_GET:
    1637                 :        567 :             get = &op->u.flow_get;
    1638                 :        567 :             dpif_netlink_init_flow_get(dpif, get, &flow);
    1639                 :        567 :             aux->txn.reply = get->buffer;
    1640                 :        567 :             dpif_netlink_flow_to_ofpbuf(&flow, &aux->request);
    1641                 :        567 :             break;
    1642                 :            : 
    1643                 :            :         default:
    1644                 :          0 :             OVS_NOT_REACHED();
    1645                 :            :         }
    1646                 :            :     }
    1647                 :            : 
    1648         [ +  + ]:       9974 :     for (i = 0; i < n_ops; i++) {
    1649                 :       5588 :         txnsp[i] = &auxes[i].txn;
    1650                 :            :     }
    1651                 :       4386 :     nl_transact_multiple(NETLINK_GENERIC, txnsp, n_ops);
    1652                 :            : 
    1653         [ +  + ]:       9974 :     for (i = 0; i < n_ops; i++) {
    1654                 :       5588 :         struct op_auxdata *aux = &auxes[i];
    1655                 :       5588 :         struct nl_transaction *txn = &auxes[i].txn;
    1656                 :       5588 :         struct dpif_op *op = ops[i];
    1657                 :            :         struct dpif_flow_put *put;
    1658                 :            :         struct dpif_flow_del *del;
    1659                 :            :         struct dpif_flow_get *get;
    1660                 :            : 
    1661                 :       5588 :         op->error = txn->error;
    1662                 :            : 
    1663   [ +  +  +  +  :       5588 :         switch (op->type) {
                      - ]
    1664                 :            :         case DPIF_OP_FLOW_PUT:
    1665                 :       1981 :             put = &op->u.flow_put;
    1666         [ -  + ]:       1981 :             if (put->stats) {
    1667         [ #  # ]:          0 :                 if (!op->error) {
    1668                 :            :                     struct dpif_netlink_flow reply;
    1669                 :            : 
    1670                 :          0 :                     op->error = dpif_netlink_flow_from_ofpbuf(&reply,
    1671                 :          0 :                                                               txn->reply);
    1672         [ #  # ]:          0 :                     if (!op->error) {
    1673                 :          0 :                         dpif_netlink_flow_get_stats(&reply, put->stats);
    1674                 :            :                     }
    1675                 :            :                 }
    1676                 :            :             }
    1677                 :       1981 :             break;
    1678                 :            : 
    1679                 :            :         case DPIF_OP_FLOW_DEL:
    1680                 :       1823 :             del = &op->u.flow_del;
    1681         [ +  + ]:       1823 :             if (del->stats) {
    1682         [ +  - ]:       1319 :                 if (!op->error) {
    1683                 :            :                     struct dpif_netlink_flow reply;
    1684                 :            : 
    1685                 :       1319 :                     op->error = dpif_netlink_flow_from_ofpbuf(&reply,
    1686                 :       1319 :                                                               txn->reply);
    1687         [ +  - ]:       1319 :                     if (!op->error) {
    1688                 :       1319 :                         dpif_netlink_flow_get_stats(&reply, del->stats);
    1689                 :            :                     }
    1690                 :            :                 }
    1691                 :            :             }
    1692                 :       1823 :             break;
    1693                 :            : 
    1694                 :            :         case DPIF_OP_EXECUTE:
    1695                 :       1217 :             break;
    1696                 :            : 
    1697                 :            :         case DPIF_OP_FLOW_GET:
    1698                 :        567 :             get = &op->u.flow_get;
    1699         [ +  - ]:        567 :             if (!op->error) {
    1700                 :            :                 struct dpif_netlink_flow reply;
    1701                 :            : 
    1702                 :        567 :                 op->error = dpif_netlink_flow_from_ofpbuf(&reply, txn->reply);
    1703         [ +  - ]:        567 :                 if (!op->error) {
    1704                 :        567 :                     dpif_netlink_flow_to_dpif_flow(&dpif->dpif, get->flow,
    1705                 :            :                                                    &reply);
    1706                 :            :                 }
    1707                 :            :             }
    1708                 :        567 :             break;
    1709                 :            : 
    1710                 :            :         default:
    1711                 :          0 :             OVS_NOT_REACHED();
    1712                 :            :         }
    1713                 :            : 
    1714                 :       5588 :         ofpbuf_uninit(&aux->request);
    1715                 :       5588 :         ofpbuf_uninit(&aux->reply);
    1716                 :            :     }
    1717                 :            : 
    1718                 :       4386 :     return n_ops;
    1719                 :            : }
    1720                 :            : 
    1721                 :            : static void
    1722                 :       4386 : dpif_netlink_operate(struct dpif *dpif_, struct dpif_op **ops, size_t n_ops)
    1723                 :            : {
    1724                 :       4386 :     struct dpif_netlink *dpif = dpif_netlink_cast(dpif_);
    1725                 :            : 
    1726         [ +  + ]:       8772 :     while (n_ops > 0) {
    1727                 :       4386 :         size_t chunk = dpif_netlink_operate__(dpif, ops, n_ops);
    1728                 :       4386 :         ops += chunk;
    1729                 :       4386 :         n_ops -= chunk;
    1730                 :            :     }
    1731                 :       4386 : }
    1732                 :            : 
    1733                 :            : #if _WIN32
    1734                 :            : static void
    1735                 :            : dpif_netlink_handler_uninit(struct dpif_handler *handler)
    1736                 :            : {
    1737                 :            :     vport_delete_sock_pool(handler);
    1738                 :            : }
    1739                 :            : 
    1740                 :            : static int
    1741                 :            : dpif_netlink_handler_init(struct dpif_handler *handler)
    1742                 :            : {
    1743                 :            :     return vport_create_sock_pool(handler);
    1744                 :            : }
    1745                 :            : #else
    1746                 :            : 
    1747                 :            : static int
    1748                 :         63 : dpif_netlink_handler_init(struct dpif_handler *handler)
    1749                 :            : {
    1750                 :         63 :     handler->epoll_fd = epoll_create(10);
    1751         [ -  + ]:         63 :     return handler->epoll_fd < 0 ? errno : 0;
    1752                 :            : }
    1753                 :            : 
    1754                 :            : static void
    1755                 :         63 : dpif_netlink_handler_uninit(struct dpif_handler *handler)
    1756                 :            : {
    1757                 :         63 :     close(handler->epoll_fd);
    1758                 :         63 : }
    1759                 :            : #endif
    1760                 :            : 
    1761                 :            : /* Synchronizes 'channels' in 'dpif->handlers'  with the set of vports
    1762                 :            :  * currently in 'dpif' in the kernel, by adding a new set of channels for
    1763                 :            :  * any kernel vport that lacks one and deleting any channels that have no
    1764                 :            :  * backing kernel vports. */
    1765                 :            : static int
    1766                 :        126 : dpif_netlink_refresh_channels(struct dpif_netlink *dpif, uint32_t n_handlers)
    1767                 :            :     OVS_REQ_WRLOCK(dpif->upcall_lock)
    1768                 :            : {
    1769                 :            :     unsigned long int *keep_channels;
    1770                 :            :     struct dpif_netlink_vport vport;
    1771                 :            :     size_t keep_channels_nbits;
    1772                 :            :     struct nl_dump dump;
    1773                 :            :     uint64_t reply_stub[NL_DUMP_BUFSIZE / 8];
    1774                 :            :     struct ofpbuf buf;
    1775                 :        126 :     int retval = 0;
    1776                 :            :     size_t i;
    1777                 :            : 
    1778                 :            :     ovs_assert(!WINDOWS || n_handlers <= 1);
    1779                 :            :     ovs_assert(!WINDOWS || dpif->n_handlers <= 1);
    1780                 :            : 
    1781         [ +  + ]:        126 :     if (dpif->n_handlers != n_handlers) {
    1782                 :         63 :         destroy_all_channels(dpif);
    1783                 :         63 :         dpif->handlers = xzalloc(n_handlers * sizeof *dpif->handlers);
    1784         [ +  + ]:        126 :         for (i = 0; i < n_handlers; i++) {
    1785                 :            :             int error;
    1786                 :         63 :             struct dpif_handler *handler = &dpif->handlers[i];
    1787                 :            : 
    1788                 :         63 :             error = dpif_netlink_handler_init(handler);
    1789         [ -  + ]:         63 :             if (error) {
    1790                 :            :                 size_t j;
    1791                 :          0 :                 struct dpif_handler *tmp = &dpif->handlers[i];
    1792                 :            : 
    1793                 :            : 
    1794         [ #  # ]:          0 :                 for (j = 0; j < i; j++) {
    1795                 :          0 :                     dpif_netlink_handler_uninit(tmp);
    1796                 :            :                 }
    1797                 :          0 :                 free(dpif->handlers);
    1798                 :          0 :                 dpif->handlers = NULL;
    1799                 :            : 
    1800                 :          0 :                 return error;
    1801                 :            :             }
    1802                 :            :         }
    1803                 :         63 :         dpif->n_handlers = n_handlers;
    1804                 :            :     }
    1805                 :            : 
    1806         [ +  + ]:        252 :     for (i = 0; i < n_handlers; i++) {
    1807                 :        126 :         struct dpif_handler *handler = &dpif->handlers[i];
    1808                 :            : 
    1809                 :        126 :         handler->event_offset = handler->n_events = 0;
    1810                 :            :     }
    1811                 :            : 
    1812                 :        126 :     keep_channels_nbits = dpif->uc_array_size;
    1813                 :        126 :     keep_channels = bitmap_allocate(keep_channels_nbits);
    1814                 :            : 
    1815                 :        126 :     ofpbuf_use_stub(&buf, reply_stub, sizeof reply_stub);
    1816                 :        126 :     dpif_netlink_port_dump_start__(dpif, &dump);
    1817         [ +  + ]:        252 :     while (!dpif_netlink_port_dump_next__(dpif, &dump, &vport, &buf)) {
    1818                 :        126 :         uint32_t port_no = odp_to_u32(vport.port_no);
    1819                 :        126 :         uint32_t *upcall_pids = NULL;
    1820                 :            :         int error;
    1821                 :            : 
    1822         [ +  + ]:        126 :         if (port_no >= dpif->uc_array_size
    1823         [ -  + ]:         63 :             || !vport_get_pids(dpif, port_no, &upcall_pids)) {
    1824                 :         63 :             struct nl_sock **socksp = vport_create_socksp(dpif, &error);
    1825                 :            : 
    1826         [ -  + ]:         63 :             if (!socksp) {
    1827                 :          0 :                 goto error;
    1828                 :            :             }
    1829                 :            : 
    1830                 :         63 :             error = vport_add_channels(dpif, vport.port_no, socksp);
    1831         [ -  + ]:         63 :             if (error) {
    1832         [ #  # ]:          0 :                 VLOG_INFO("%s: could not add channels for port %s",
    1833                 :            :                           dpif_name(&dpif->dpif), vport.name);
    1834                 :          0 :                 vport_del_socksp(dpif, socksp);
    1835                 :          0 :                 retval = error;
    1836                 :          0 :                 goto error;
    1837                 :            :             }
    1838                 :         63 :             upcall_pids = vport_socksp_to_pids(socksp, dpif->n_handlers);
    1839                 :         63 :             free(socksp);
    1840                 :            :         }
    1841                 :            : 
    1842                 :            :         /* Configure the vport to deliver misses to 'sock'. */
    1843         [ +  + ]:        126 :         if (vport.upcall_pids[0] == 0
    1844         [ +  - ]:         63 :             || vport.n_upcall_pids != dpif->n_handlers
    1845         [ -  + ]:         63 :             || memcmp(upcall_pids, vport.upcall_pids, n_handlers * sizeof
    1846                 :            :                       *upcall_pids)) {
    1847                 :            :             struct dpif_netlink_vport vport_request;
    1848                 :            : 
    1849                 :         63 :             dpif_netlink_vport_init(&vport_request);
    1850                 :         63 :             vport_request.cmd = OVS_VPORT_CMD_SET;
    1851                 :         63 :             vport_request.dp_ifindex = dpif->dp_ifindex;
    1852                 :         63 :             vport_request.port_no = vport.port_no;
    1853                 :         63 :             vport_request.n_upcall_pids = dpif->n_handlers;
    1854                 :         63 :             vport_request.upcall_pids = upcall_pids;
    1855                 :         63 :             error = dpif_netlink_vport_transact(&vport_request, NULL, NULL);
    1856         [ -  + ]:         63 :             if (error) {
    1857         [ #  # ]:          0 :                 VLOG_WARN_RL(&error_rl,
    1858                 :            :                              "%s: failed to set upcall pid on port: %s",
    1859                 :            :                              dpif_name(&dpif->dpif), ovs_strerror(error));
    1860                 :            : 
    1861 [ #  # ][ #  # ]:          0 :                 if (error != ENODEV && error != ENOENT) {
    1862                 :          0 :                     retval = error;
    1863                 :            :                 } else {
    1864                 :            :                     /* The vport isn't really there, even though the dump says
    1865                 :            :                      * it is.  Probably we just hit a race after a port
    1866                 :            :                      * disappeared. */
    1867                 :            :                 }
    1868                 :         63 :                 goto error;
    1869                 :            :             }
    1870                 :            :         }
    1871                 :            : 
    1872         [ +  + ]:        126 :         if (port_no < keep_channels_nbits) {
    1873                 :         63 :             bitmap_set1(keep_channels, port_no);
    1874                 :            :         }
    1875                 :        126 :         free(upcall_pids);
    1876                 :        126 :         continue;
    1877                 :            : 
    1878                 :            :     error:
    1879                 :          0 :         free(upcall_pids);
    1880                 :          0 :         vport_del_channels(dpif, vport.port_no);
    1881                 :            :     }
    1882                 :        126 :     nl_dump_done(&dump);
    1883                 :        126 :     ofpbuf_uninit(&buf);
    1884                 :            : 
    1885                 :            :     /* Discard any saved channels that we didn't reuse. */
    1886         [ +  + ]:        189 :     for (i = 0; i < keep_channels_nbits; i++) {
    1887         [ -  + ]:         63 :         if (!bitmap_is_set(keep_channels, i)) {
    1888                 :          0 :             vport_del_channels(dpif, u32_to_odp(i));
    1889                 :            :         }
    1890                 :            :     }
    1891                 :        126 :     free(keep_channels);
    1892                 :            : 
    1893                 :        126 :     return retval;
    1894                 :            : }
    1895                 :            : 
    1896                 :            : static int
    1897                 :         63 : dpif_netlink_recv_set__(struct dpif_netlink *dpif, bool enable)
    1898                 :            :     OVS_REQ_WRLOCK(dpif->upcall_lock)
    1899                 :            : {
    1900         [ -  + ]:         63 :     if ((dpif->handlers != NULL) == enable) {
    1901                 :          0 :         return 0;
    1902         [ -  + ]:         63 :     } else if (!enable) {
    1903                 :          0 :         destroy_all_channels(dpif);
    1904                 :          0 :         return 0;
    1905                 :            :     } else {
    1906                 :         63 :         return dpif_netlink_refresh_channels(dpif, 1);
    1907                 :            :     }
    1908                 :            : }
    1909                 :            : 
    1910                 :            : static int
    1911                 :         63 : dpif_netlink_recv_set(struct dpif *dpif_, bool enable)
    1912                 :            : {
    1913                 :         63 :     struct dpif_netlink *dpif = dpif_netlink_cast(dpif_);
    1914                 :            :     int error;
    1915                 :            : 
    1916                 :         63 :     fat_rwlock_wrlock(&dpif->upcall_lock);
    1917                 :         63 :     error = dpif_netlink_recv_set__(dpif, enable);
    1918                 :         63 :     fat_rwlock_unlock(&dpif->upcall_lock);
    1919                 :            : 
    1920                 :         63 :     return error;
    1921                 :            : }
    1922                 :            : 
    1923                 :            : static int
    1924                 :         63 : dpif_netlink_handlers_set(struct dpif *dpif_, uint32_t n_handlers)
    1925                 :            : {
    1926                 :         63 :     struct dpif_netlink *dpif = dpif_netlink_cast(dpif_);
    1927                 :         63 :     int error = 0;
    1928                 :            : 
    1929                 :            : #ifdef _WIN32
    1930                 :            :     /* Multiple upcall handlers will be supported once kernel datapath supports
    1931                 :            :      * it. */
    1932                 :            :     if (n_handlers > 1) {
    1933                 :            :         return error;
    1934                 :            :     }
    1935                 :            : #endif
    1936                 :            : 
    1937                 :         63 :     fat_rwlock_wrlock(&dpif->upcall_lock);
    1938         [ +  - ]:         63 :     if (dpif->handlers) {
    1939                 :         63 :         error = dpif_netlink_refresh_channels(dpif, n_handlers);
    1940                 :            :     }
    1941                 :         63 :     fat_rwlock_unlock(&dpif->upcall_lock);
    1942                 :            : 
    1943                 :         63 :     return error;
    1944                 :            : }
    1945                 :            : 
    1946                 :            : static int
    1947                 :          0 : dpif_netlink_queue_to_priority(const struct dpif *dpif OVS_UNUSED,
    1948                 :            :                              uint32_t queue_id, uint32_t *priority)
    1949                 :            : {
    1950         [ #  # ]:          0 :     if (queue_id < 0xf000) {
    1951                 :          0 :         *priority = TC_H_MAKE(1 << 16, queue_id + 1);
    1952                 :          0 :         return 0;
    1953                 :            :     } else {
    1954                 :          0 :         return EINVAL;
    1955                 :            :     }
    1956                 :            : }
    1957                 :            : 
    1958                 :            : static int
    1959                 :       1374 : parse_odp_packet(const struct dpif_netlink *dpif, struct ofpbuf *buf,
    1960                 :            :                  struct dpif_upcall *upcall, int *dp_ifindex)
    1961                 :            : {
    1962                 :            :     static const struct nl_policy ovs_packet_policy[] = {
    1963                 :            :         /* Always present. */
    1964                 :            :         [OVS_PACKET_ATTR_PACKET] = { .type = NL_A_UNSPEC,
    1965                 :            :                                      .min_len = ETH_HEADER_LEN },
    1966                 :            :         [OVS_PACKET_ATTR_KEY] = { .type = NL_A_NESTED },
    1967                 :            : 
    1968                 :            :         /* OVS_PACKET_CMD_ACTION only. */
    1969                 :            :         [OVS_PACKET_ATTR_USERDATA] = { .type = NL_A_UNSPEC, .optional = true },
    1970                 :            :         [OVS_PACKET_ATTR_EGRESS_TUN_KEY] = { .type = NL_A_NESTED, .optional = true },
    1971                 :            :         [OVS_PACKET_ATTR_ACTIONS] = { .type = NL_A_NESTED, .optional = true },
    1972                 :            :         [OVS_PACKET_ATTR_MRU] = { .type = NL_A_U16, .optional = true }
    1973                 :            :     };
    1974                 :            : 
    1975                 :       1374 :     struct ofpbuf b = ofpbuf_const_initializer(buf->data, buf->size);
    1976                 :       1374 :     struct nlmsghdr *nlmsg = ofpbuf_try_pull(&b, sizeof *nlmsg);
    1977                 :       1374 :     struct genlmsghdr *genl = ofpbuf_try_pull(&b, sizeof *genl);
    1978                 :       1374 :     struct ovs_header *ovs_header = ofpbuf_try_pull(&b, sizeof *ovs_header);
    1979                 :            : 
    1980                 :            :     struct nlattr *a[ARRAY_SIZE(ovs_packet_policy)];
    1981 [ +  - ][ +  - ]:       1374 :     if (!nlmsg || !genl || !ovs_header
                 [ +  - ]
    1982         [ +  - ]:       1374 :         || nlmsg->nlmsg_type != ovs_packet_family
    1983         [ -  + ]:       1374 :         || !nl_policy_parse(&b, 0, ovs_packet_policy, a,
    1984                 :            :                             ARRAY_SIZE(ovs_packet_policy))) {
    1985                 :          0 :         return EINVAL;
    1986                 :            :     }
    1987                 :            : 
    1988                 :       2748 :     int type = (genl->cmd == OVS_PACKET_CMD_MISS ? DPIF_UC_MISS
    1989         [ +  + ]:       1439 :                 : genl->cmd == OVS_PACKET_CMD_ACTION ? DPIF_UC_ACTION
    1990         [ +  - ]:         65 :                 : -1);
    1991         [ -  + ]:       1374 :     if (type < 0) {
    1992                 :          0 :         return EINVAL;
    1993                 :            :     }
    1994                 :            : 
    1995                 :            :     /* (Re)set ALL fields of '*upcall' on successful return. */
    1996                 :       1374 :     upcall->type = type;
    1997                 :       1374 :     upcall->key = CONST_CAST(struct nlattr *,
    1998                 :            :                              nl_attr_get(a[OVS_PACKET_ATTR_KEY]));
    1999                 :       1374 :     upcall->key_len = nl_attr_get_size(a[OVS_PACKET_ATTR_KEY]);
    2000                 :       1374 :     dpif_flow_hash(&dpif->dpif, upcall->key, upcall->key_len, &upcall->ufid);
    2001                 :       1374 :     upcall->userdata = a[OVS_PACKET_ATTR_USERDATA];
    2002                 :       1374 :     upcall->out_tun_key = a[OVS_PACKET_ATTR_EGRESS_TUN_KEY];
    2003                 :       1374 :     upcall->actions = a[OVS_PACKET_ATTR_ACTIONS];
    2004                 :       1374 :     upcall->mru = a[OVS_PACKET_ATTR_MRU];
    2005                 :            : 
    2006                 :            :     /* Allow overwriting the netlink attribute header without reallocating. */
    2007                 :       1374 :     dp_packet_use_stub(&upcall->packet,
    2008                 :       1374 :                     CONST_CAST(struct nlattr *,
    2009                 :            :                                nl_attr_get(a[OVS_PACKET_ATTR_PACKET])) - 1,
    2010                 :       1374 :                     nl_attr_get_size(a[OVS_PACKET_ATTR_PACKET]) +
    2011                 :            :                     sizeof(struct nlattr));
    2012                 :       1374 :     dp_packet_set_data(&upcall->packet,
    2013                 :       1374 :                     (char *)dp_packet_data(&upcall->packet) + sizeof(struct nlattr));
    2014                 :       1374 :     dp_packet_set_size(&upcall->packet, nl_attr_get_size(a[OVS_PACKET_ATTR_PACKET]));
    2015                 :            : 
    2016                 :       1374 :     *dp_ifindex = ovs_header->dp_ifindex;
    2017                 :            : 
    2018                 :       1374 :     return 0;
    2019                 :            : }
    2020                 :            : 
    2021                 :            : #ifdef _WIN32
    2022                 :            : #define PACKET_RECV_BATCH_SIZE 50
    2023                 :            : static int
    2024                 :            : dpif_netlink_recv_windows(struct dpif_netlink *dpif, uint32_t handler_id,
    2025                 :            :                           struct dpif_upcall *upcall, struct ofpbuf *buf)
    2026                 :            :     OVS_REQ_RDLOCK(dpif->upcall_lock)
    2027                 :            : {
    2028                 :            :     struct dpif_handler *handler;
    2029                 :            :     int read_tries = 0;
    2030                 :            :     struct dpif_windows_vport_sock *sock_pool;
    2031                 :            :     uint32_t i;
    2032                 :            : 
    2033                 :            :     if (!dpif->handlers) {
    2034                 :            :         return EAGAIN;
    2035                 :            :     }
    2036                 :            : 
    2037                 :            :     /* Only one handler is supported currently. */
    2038                 :            :     if (handler_id >= 1) {
    2039                 :            :         return EAGAIN;
    2040                 :            :     }
    2041                 :            : 
    2042                 :            :     if (handler_id >= dpif->n_handlers) {
    2043                 :            :         return EAGAIN;
    2044                 :            :     }
    2045                 :            : 
    2046                 :            :     handler = &dpif->handlers[handler_id];
    2047                 :            :     sock_pool = handler->vport_sock_pool;
    2048                 :            : 
    2049                 :            :     for (i = 0; i < VPORT_SOCK_POOL_SIZE; i++) {
    2050                 :            :         for (;;) {
    2051                 :            :             int dp_ifindex;
    2052                 :            :             int error;
    2053                 :            : 
    2054                 :            :             if (++read_tries > PACKET_RECV_BATCH_SIZE) {
    2055                 :            :                 return EAGAIN;
    2056                 :            :             }
    2057                 :            : 
    2058                 :            :             error = nl_sock_recv(sock_pool[i].nl_sock, buf, false);
    2059                 :            :             if (error == ENOBUFS) {
    2060                 :            :                 /* ENOBUFS typically means that we've received so many
    2061                 :            :                  * packets that the buffer overflowed.  Try again
    2062                 :            :                  * immediately because there's almost certainly a packet
    2063                 :            :                  * waiting for us. */
    2064                 :            :                 /* XXX: report_loss(dpif, ch, idx, handler_id); */
    2065                 :            :                 continue;
    2066                 :            :             }
    2067                 :            : 
    2068                 :            :             /* XXX: ch->last_poll = time_msec(); */
    2069                 :            :             if (error) {
    2070                 :            :                 if (error == EAGAIN) {
    2071                 :            :                     break;
    2072                 :            :                 }
    2073                 :            :                 return error;
    2074                 :            :             }
    2075                 :            : 
    2076                 :            :             error = parse_odp_packet(dpif, buf, upcall, &dp_ifindex);
    2077                 :            :             if (!error && dp_ifindex == dpif->dp_ifindex) {
    2078                 :            :                 return 0;
    2079                 :            :             } else if (error) {
    2080                 :            :                 return error;
    2081                 :            :             }
    2082                 :            :         }
    2083                 :            :     }
    2084                 :            : 
    2085                 :            :     return EAGAIN;
    2086                 :            : }
    2087                 :            : #else
    2088                 :            : static int
    2089                 :       3449 : dpif_netlink_recv__(struct dpif_netlink *dpif, uint32_t handler_id,
    2090                 :            :                     struct dpif_upcall *upcall, struct ofpbuf *buf)
    2091                 :            :     OVS_REQ_RDLOCK(dpif->upcall_lock)
    2092                 :            : {
    2093                 :            :     struct dpif_handler *handler;
    2094                 :       3449 :     int read_tries = 0;
    2095                 :            : 
    2096 [ +  - ][ -  + ]:       3449 :     if (!dpif->handlers || handler_id >= dpif->n_handlers) {
    2097                 :          0 :         return EAGAIN;
    2098                 :            :     }
    2099                 :            : 
    2100                 :       3449 :     handler = &dpif->handlers[handler_id];
    2101         [ +  + ]:       3449 :     if (handler->event_offset >= handler->n_events) {
    2102                 :            :         int retval;
    2103                 :            : 
    2104                 :       3438 :         handler->event_offset = handler->n_events = 0;
    2105                 :            : 
    2106                 :            :         do {
    2107                 :       3438 :             retval = epoll_wait(handler->epoll_fd, handler->epoll_events,
    2108                 :            :                                 dpif->uc_array_size, 0);
    2109 [ -  + ][ #  # ]:       3438 :         } while (retval < 0 && errno == EINTR);
    2110                 :            : 
    2111         [ -  + ]:       3438 :         if (retval < 0) {
    2112                 :            :             static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
    2113         [ #  # ]:          0 :             VLOG_WARN_RL(&rl, "epoll_wait failed (%s)", ovs_strerror(errno));
    2114         [ +  + ]:       3438 :         } else if (retval > 0) {
    2115                 :       1363 :             handler->n_events = retval;
    2116                 :            :         }
    2117                 :            :     }
    2118                 :            : 
    2119         [ +  + ]:       3449 :     while (handler->event_offset < handler->n_events) {
    2120                 :       1374 :         int idx = handler->epoll_events[handler->event_offset].data.u32;
    2121                 :       1374 :         struct dpif_channel *ch = &dpif->handlers[handler_id].channels[idx];
    2122                 :            : 
    2123                 :       1374 :         handler->event_offset++;
    2124                 :            : 
    2125                 :            :         for (;;) {
    2126                 :            :             int dp_ifindex;
    2127                 :            :             int error;
    2128                 :            : 
    2129         [ -  + ]:       1374 :             if (++read_tries > 50) {
    2130                 :       1374 :                 return EAGAIN;
    2131                 :            :             }
    2132                 :            : 
    2133                 :       1374 :             error = nl_sock_recv(ch->sock, buf, false);
    2134         [ -  + ]:       1374 :             if (error == ENOBUFS) {
    2135                 :            :                 /* ENOBUFS typically means that we've received so many
    2136                 :            :                  * packets that the buffer overflowed.  Try again
    2137                 :            :                  * immediately because there's almost certainly a packet
    2138                 :            :                  * waiting for us. */
    2139                 :          0 :                 report_loss(dpif, ch, idx, handler_id);
    2140                 :          0 :                 continue;
    2141                 :            :             }
    2142                 :            : 
    2143                 :       1374 :             ch->last_poll = time_msec();
    2144         [ -  + ]:       1374 :             if (error) {
    2145         [ #  # ]:          0 :                 if (error == EAGAIN) {
    2146                 :          0 :                     break;
    2147                 :            :                 }
    2148                 :          0 :                 return error;
    2149                 :            :             }
    2150                 :            : 
    2151                 :       1374 :             error = parse_odp_packet(dpif, buf, upcall, &dp_ifindex);
    2152 [ +  - ][ +  - ]:       1374 :             if (!error && dp_ifindex == dpif->dp_ifindex) {
    2153                 :       1374 :                 return 0;
    2154         [ #  # ]:          0 :             } else if (error) {
    2155                 :          0 :                 return error;
    2156                 :            :             }
    2157                 :          0 :         }
    2158                 :            :     }
    2159                 :            : 
    2160                 :       2075 :     return EAGAIN;
    2161                 :            : }
    2162                 :            : #endif
    2163                 :            : 
    2164                 :            : static int
    2165                 :       3449 : dpif_netlink_recv(struct dpif *dpif_, uint32_t handler_id,
    2166                 :            :                   struct dpif_upcall *upcall, struct ofpbuf *buf)
    2167                 :            : {
    2168                 :       3449 :     struct dpif_netlink *dpif = dpif_netlink_cast(dpif_);
    2169                 :            :     int error;
    2170                 :            : 
    2171                 :       3449 :     fat_rwlock_rdlock(&dpif->upcall_lock);
    2172                 :            : #ifdef _WIN32
    2173                 :            :     error = dpif_netlink_recv_windows(dpif, handler_id, upcall, buf);
    2174                 :            : #else
    2175                 :       3449 :     error = dpif_netlink_recv__(dpif, handler_id, upcall, buf);
    2176                 :            : #endif
    2177                 :       3449 :     fat_rwlock_unlock(&dpif->upcall_lock);
    2178                 :            : 
    2179                 :       3449 :     return error;
    2180                 :            : }
    2181                 :            : 
    2182                 :            : static void
    2183                 :        885 : dpif_netlink_recv_wait__(struct dpif_netlink *dpif, uint32_t handler_id)
    2184                 :            :     OVS_REQ_RDLOCK(dpif->upcall_lock)
    2185                 :            : {
    2186                 :            : #ifdef _WIN32
    2187                 :            :     uint32_t i;
    2188                 :            :     struct dpif_windows_vport_sock *sock_pool =
    2189                 :            :         dpif->handlers[handler_id].vport_sock_pool;
    2190                 :            : 
    2191                 :            :     /* Only one handler is supported currently. */
    2192                 :            :     if (handler_id >= 1) {
    2193                 :            :         return;
    2194                 :            :     }
    2195                 :            : 
    2196                 :            :     for (i = 0; i < VPORT_SOCK_POOL_SIZE; i++) {
    2197                 :            :         nl_sock_wait(sock_pool[i].nl_sock, POLLIN);
    2198                 :            :     }
    2199                 :            : #else
    2200 [ +  - ][ +  - ]:        885 :     if (dpif->handlers && handler_id < dpif->n_handlers) {
    2201                 :        885 :         struct dpif_handler *handler = &dpif->handlers[handler_id];
    2202                 :            : 
    2203                 :        885 :         poll_fd_wait(handler->epoll_fd, POLLIN);
    2204                 :            :     }
    2205                 :            : #endif
    2206                 :        885 : }
    2207                 :            : 
    2208                 :            : static void
    2209                 :        885 : dpif_netlink_recv_wait(struct dpif *dpif_, uint32_t handler_id)
    2210                 :            : {
    2211                 :        885 :     struct dpif_netlink *dpif = dpif_netlink_cast(dpif_);
    2212                 :            : 
    2213                 :        885 :     fat_rwlock_rdlock(&dpif->upcall_lock);
    2214                 :        885 :     dpif_netlink_recv_wait__(dpif, handler_id);
    2215                 :        885 :     fat_rwlock_unlock(&dpif->upcall_lock);
    2216                 :        885 : }
    2217                 :            : 
    2218                 :            : static void
    2219                 :          0 : dpif_netlink_recv_purge__(struct dpif_netlink *dpif)
    2220                 :            :     OVS_REQ_WRLOCK(dpif->upcall_lock)
    2221                 :            : {
    2222         [ #  # ]:          0 :     if (dpif->handlers) {
    2223                 :            :         size_t i, j;
    2224                 :            : 
    2225         [ #  # ]:          0 :         for (i = 0; i < dpif->uc_array_size; i++ ) {
    2226         [ #  # ]:          0 :             if (!dpif->handlers[0].channels[i].sock) {
    2227                 :          0 :                 continue;
    2228                 :            :             }
    2229                 :            : 
    2230         [ #  # ]:          0 :             for (j = 0; j < dpif->n_handlers; j++) {
    2231                 :          0 :                 nl_sock_drain(dpif->handlers[j].channels[i].sock);
    2232                 :            :             }
    2233                 :            :         }
    2234                 :            :     }
    2235                 :          0 : }
    2236                 :            : 
    2237                 :            : static void
    2238                 :          0 : dpif_netlink_recv_purge(struct dpif *dpif_)
    2239                 :            : {
    2240                 :          0 :     struct dpif_netlink *dpif = dpif_netlink_cast(dpif_);
    2241                 :            : 
    2242                 :          0 :     fat_rwlock_wrlock(&dpif->upcall_lock);
    2243                 :          0 :     dpif_netlink_recv_purge__(dpif);
    2244                 :          0 :     fat_rwlock_unlock(&dpif->upcall_lock);
    2245                 :          0 : }
    2246                 :            : 
    2247                 :            : static char *
    2248                 :         63 : dpif_netlink_get_datapath_version(void)
    2249                 :            : {
    2250                 :         63 :     char *version_str = NULL;
    2251                 :            : 
    2252                 :            : #ifdef __linux__
    2253                 :            : 
    2254                 :            : #define MAX_VERSION_STR_SIZE 80
    2255                 :            : #define LINUX_DATAPATH_VERSION_FILE  "/sys/module/openvswitch/version"
    2256                 :            :     FILE *f;
    2257                 :            : 
    2258                 :         63 :     f = fopen(LINUX_DATAPATH_VERSION_FILE, "r");
    2259         [ +  - ]:         63 :     if (f) {
    2260                 :            :         char *newline;
    2261                 :            :         char version[MAX_VERSION_STR_SIZE];
    2262                 :            : 
    2263         [ +  - ]:         63 :         if (fgets(version, MAX_VERSION_STR_SIZE, f)) {
    2264                 :         63 :             newline = strchr(version, '\n');
    2265         [ +  - ]:         63 :             if (newline) {
    2266                 :         63 :                 *newline = '\0';
    2267                 :            :             }
    2268                 :         63 :             version_str = xstrdup(version);
    2269                 :            :         }
    2270                 :         63 :         fclose(f);
    2271                 :            :     }
    2272                 :            : #endif
    2273                 :            : 
    2274                 :         63 :     return version_str;
    2275                 :            : }
    2276                 :            : 
    2277                 :            : struct dpif_netlink_ct_dump_state {
    2278                 :            :     struct ct_dpif_dump_state up;
    2279                 :            :     struct nl_ct_dump_state *nl_ct_dump;
    2280                 :            : };
    2281                 :            : 
    2282                 :            : static int
    2283                 :         53 : dpif_netlink_ct_dump_start(struct dpif *dpif OVS_UNUSED,
    2284                 :            :                            struct ct_dpif_dump_state **dump_,
    2285                 :            :                            const uint16_t *zone)
    2286                 :            : {
    2287                 :            :     struct dpif_netlink_ct_dump_state *dump;
    2288                 :            :     int err;
    2289                 :            : 
    2290                 :         53 :     dump = xzalloc(sizeof *dump);
    2291                 :         53 :     err = nl_ct_dump_start(&dump->nl_ct_dump, zone);
    2292         [ -  + ]:         53 :     if (err) {
    2293                 :          0 :         free(dump);
    2294                 :          0 :         return err;
    2295                 :            :     }
    2296                 :            : 
    2297                 :         53 :     *dump_ = &dump->up;
    2298                 :            : 
    2299                 :         53 :     return 0;
    2300                 :            : }
    2301                 :            : 
    2302                 :            : static int
    2303                 :        439 : dpif_netlink_ct_dump_next(struct dpif *dpif OVS_UNUSED,
    2304                 :            :                           struct ct_dpif_dump_state *dump_,
    2305                 :            :                           struct ct_dpif_entry *entry)
    2306                 :            : {
    2307                 :            :     struct dpif_netlink_ct_dump_state *dump;
    2308                 :            : 
    2309                 :        439 :     INIT_CONTAINER(dump, dump_, up);
    2310                 :            : 
    2311                 :        439 :     return nl_ct_dump_next(dump->nl_ct_dump, entry);
    2312                 :            : }
    2313                 :            : 
    2314                 :            : static int
    2315                 :         53 : dpif_netlink_ct_dump_done(struct dpif *dpif OVS_UNUSED,
    2316                 :            :                           struct ct_dpif_dump_state *dump_)
    2317                 :            : {
    2318                 :            :     struct dpif_netlink_ct_dump_state *dump;
    2319                 :            :     int err;
    2320                 :            : 
    2321                 :         53 :     INIT_CONTAINER(dump, dump_, up);
    2322                 :            : 
    2323                 :         53 :     err = nl_ct_dump_done(dump->nl_ct_dump);
    2324                 :         53 :     free(dump);
    2325                 :         53 :     return err;
    2326                 :            : }
    2327                 :            : 
    2328                 :            : static int
    2329                 :          6 : dpif_netlink_ct_flush(struct dpif *dpif OVS_UNUSED, const uint16_t *zone)
    2330                 :            : {
    2331         [ -  + ]:          6 :     if (zone) {
    2332                 :          0 :         return nl_ct_flush_zone(*zone);
    2333                 :            :     } else {
    2334                 :          6 :         return nl_ct_flush();
    2335                 :            :     }
    2336                 :            : }
    2337                 :            : 
    2338                 :            : const struct dpif_class dpif_netlink_class = {
    2339                 :            :     "system",
    2340                 :            :     NULL,                       /* init */
    2341                 :            :     dpif_netlink_enumerate,
    2342                 :            :     NULL,
    2343                 :            :     dpif_netlink_open,
    2344                 :            :     dpif_netlink_close,
    2345                 :            :     dpif_netlink_destroy,
    2346                 :            :     dpif_netlink_run,
    2347                 :            :     NULL,                       /* wait */
    2348                 :            :     dpif_netlink_get_stats,
    2349                 :            :     dpif_netlink_port_add,
    2350                 :            :     dpif_netlink_port_del,
    2351                 :            :     NULL,                       /* port_set_config */
    2352                 :            :     dpif_netlink_port_query_by_number,
    2353                 :            :     dpif_netlink_port_query_by_name,
    2354                 :            :     dpif_netlink_port_get_pid,
    2355                 :            :     dpif_netlink_port_dump_start,
    2356                 :            :     dpif_netlink_port_dump_next,
    2357                 :            :     dpif_netlink_port_dump_done,
    2358                 :            :     dpif_netlink_port_poll,
    2359                 :            :     dpif_netlink_port_poll_wait,
    2360                 :            :     dpif_netlink_flow_flush,
    2361                 :            :     dpif_netlink_flow_dump_create,
    2362                 :            :     dpif_netlink_flow_dump_destroy,
    2363                 :            :     dpif_netlink_flow_dump_thread_create,
    2364                 :            :     dpif_netlink_flow_dump_thread_destroy,
    2365                 :            :     dpif_netlink_flow_dump_next,
    2366                 :            :     dpif_netlink_operate,
    2367                 :            :     dpif_netlink_recv_set,
    2368                 :            :     dpif_netlink_handlers_set,
    2369                 :            :     NULL,                       /* poll_thread_set */
    2370                 :            :     dpif_netlink_queue_to_priority,
    2371                 :            :     dpif_netlink_recv,
    2372                 :            :     dpif_netlink_recv_wait,
    2373                 :            :     dpif_netlink_recv_purge,
    2374                 :            :     NULL,                       /* register_dp_purge_cb */
    2375                 :            :     NULL,                       /* register_upcall_cb */
    2376                 :            :     NULL,                       /* enable_upcall */
    2377                 :            :     NULL,                       /* disable_upcall */
    2378                 :            :     dpif_netlink_get_datapath_version, /* get_datapath_version */
    2379                 :            :     dpif_netlink_ct_dump_start,
    2380                 :            :     dpif_netlink_ct_dump_next,
    2381                 :            :     dpif_netlink_ct_dump_done,
    2382                 :            :     dpif_netlink_ct_flush
    2383                 :            : };
    2384                 :            : 
    2385                 :            : static int
    2386                 :       5496 : dpif_netlink_init(void)
    2387                 :            : {
    2388                 :            :     static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER;
    2389                 :            :     static int error;
    2390                 :            : 
    2391         [ +  + ]:       5496 :     if (ovsthread_once_start(&once)) {
    2392                 :        158 :         error = nl_lookup_genl_family(OVS_DATAPATH_FAMILY,
    2393                 :            :                                       &ovs_datapath_family);
    2394         [ +  + ]:        158 :         if (error) {
    2395         [ +  - ]:         31 :             VLOG_WARN("Generic Netlink family '%s' does not exist. "
    2396                 :            :                       "The Open vSwitch kernel module is probably not loaded.",
    2397                 :            :                       OVS_DATAPATH_FAMILY);
    2398                 :            :         }
    2399         [ +  + ]:        158 :         if (!error) {
    2400                 :        127 :             error = nl_lookup_genl_family(OVS_VPORT_FAMILY, &ovs_vport_family);
    2401                 :            :         }
    2402         [ +  + ]:        158 :         if (!error) {
    2403                 :        127 :             error = nl_lookup_genl_family(OVS_FLOW_FAMILY, &ovs_flow_family);
    2404                 :            :         }
    2405         [ +  + ]:        158 :         if (!error) {
    2406                 :        127 :             error = nl_lookup_genl_family(OVS_PACKET_FAMILY,
    2407                 :            :                                           &ovs_packet_family);
    2408                 :            :         }
    2409         [ +  + ]:        158 :         if (!error) {
    2410                 :        127 :             error = nl_lookup_genl_mcgroup(OVS_VPORT_FAMILY, OVS_VPORT_MCGROUP,
    2411                 :            :                                            &ovs_vport_mcgroup);
    2412                 :            :         }
    2413                 :            : 
    2414                 :        158 :         ovsthread_once_done(&once);
    2415                 :            :     }
    2416                 :            : 
    2417                 :       5496 :     return error;
    2418                 :            : }
    2419                 :            : 
    2420                 :            : bool
    2421                 :          0 : dpif_netlink_is_internal_device(const char *name)
    2422                 :            : {
    2423                 :            :     struct dpif_netlink_vport reply;
    2424                 :            :     struct ofpbuf *buf;
    2425                 :            :     int error;
    2426                 :            : 
    2427                 :          0 :     error = dpif_netlink_vport_get(name, &reply, &buf);
    2428         [ #  # ]:          0 :     if (!error) {
    2429                 :          0 :         ofpbuf_delete(buf);
    2430 [ #  # ][ #  # ]:          0 :     } else if (error != ENODEV && error != ENOENT) {
    2431         [ #  # ]:          0 :         VLOG_WARN_RL(&error_rl, "%s: vport query failed (%s)",
    2432                 :            :                      name, ovs_strerror(error));
    2433                 :            :     }
    2434                 :            : 
    2435                 :          0 :     return reply.type == OVS_VPORT_TYPE_INTERNAL;
    2436                 :            : }
    2437                 :            : 
    2438                 :            : /* Parses the contents of 'buf', which contains a "struct ovs_header" followed
    2439                 :            :  * by Netlink attributes, into 'vport'.  Returns 0 if successful, otherwise a
    2440                 :            :  * positive errno value.
    2441                 :            :  *
    2442                 :            :  * 'vport' will contain pointers into 'buf', so the caller should not free
    2443                 :            :  * 'buf' while 'vport' is still in use. */
    2444                 :            : static int
    2445                 :       4915 : dpif_netlink_vport_from_ofpbuf(struct dpif_netlink_vport *vport,
    2446                 :            :                              const struct ofpbuf *buf)
    2447                 :            : {
    2448                 :            :     static const struct nl_policy ovs_vport_policy[] = {
    2449                 :            :         [OVS_VPORT_ATTR_PORT_NO] = { .type = NL_A_U32 },
    2450                 :            :         [OVS_VPORT_ATTR_TYPE] = { .type = NL_A_U32 },
    2451                 :            :         [OVS_VPORT_ATTR_NAME] = { .type = NL_A_STRING, .max_len = IFNAMSIZ },
    2452                 :            :         [OVS_VPORT_ATTR_UPCALL_PID] = { .type = NL_A_UNSPEC },
    2453                 :            :         [OVS_VPORT_ATTR_STATS] = { NL_POLICY_FOR(struct ovs_vport_stats),
    2454                 :            :                                    .optional = true },
    2455                 :            :         [OVS_VPORT_ATTR_OPTIONS] = { .type = NL_A_NESTED, .optional = true },
    2456                 :            :     };
    2457                 :            : 
    2458                 :       4915 :     dpif_netlink_vport_init(vport);
    2459                 :            : 
    2460                 :       4915 :     struct ofpbuf b = ofpbuf_const_initializer(buf->data, buf->size);
    2461                 :       4915 :     struct nlmsghdr *nlmsg = ofpbuf_try_pull(&b, sizeof *nlmsg);
    2462                 :       4915 :     struct genlmsghdr *genl = ofpbuf_try_pull(&b, sizeof *genl);
    2463                 :       4915 :     struct ovs_header *ovs_header = ofpbuf_try_pull(&b, sizeof *ovs_header);
    2464                 :            : 
    2465                 :            :     struct nlattr *a[ARRAY_SIZE(ovs_vport_policy)];
    2466 [ +  - ][ +  - ]:       4915 :     if (!nlmsg || !genl || !ovs_header
                 [ +  - ]
    2467         [ +  - ]:       4915 :         || nlmsg->nlmsg_type != ovs_vport_family
    2468         [ -  + ]:       4915 :         || !nl_policy_parse(&b, 0, ovs_vport_policy, a,
    2469                 :            :                             ARRAY_SIZE(ovs_vport_policy))) {
    2470                 :          0 :         return EINVAL;
    2471                 :            :     }
    2472                 :            : 
    2473                 :       4915 :     vport->cmd = genl->cmd;
    2474                 :       4915 :     vport->dp_ifindex = ovs_header->dp_ifindex;
    2475                 :       4915 :     vport->port_no = nl_attr_get_odp_port(a[OVS_VPORT_ATTR_PORT_NO]);
    2476                 :       4915 :     vport->type = nl_attr_get_u32(a[OVS_VPORT_ATTR_TYPE]);
    2477                 :       4915 :     vport->name = nl_attr_get_string(a[OVS_VPORT_ATTR_NAME]);
    2478         [ +  - ]:       4915 :     if (a[OVS_VPORT_ATTR_UPCALL_PID]) {
    2479                 :       4915 :         vport->n_upcall_pids = nl_attr_get_size(a[OVS_VPORT_ATTR_UPCALL_PID])
    2480                 :       4915 :                                / (sizeof *vport->upcall_pids);
    2481                 :       4915 :         vport->upcall_pids = nl_attr_get(a[OVS_VPORT_ATTR_UPCALL_PID]);
    2482                 :            : 
    2483                 :            :     }
    2484         [ +  - ]:       4915 :     if (a[OVS_VPORT_ATTR_STATS]) {
    2485                 :       4915 :         vport->stats = nl_attr_get(a[OVS_VPORT_ATTR_STATS]);
    2486                 :            :     }
    2487         [ +  + ]:       4915 :     if (a[OVS_VPORT_ATTR_OPTIONS]) {
    2488                 :          9 :         vport->options = nl_attr_get(a[OVS_VPORT_ATTR_OPTIONS]);
    2489                 :          9 :         vport->options_len = nl_attr_get_size(a[OVS_VPORT_ATTR_OPTIONS]);
    2490                 :            :     }
    2491                 :       4915 :     return 0;
    2492                 :            : }
    2493                 :            : 
    2494                 :            : /* Appends to 'buf' (which must initially be empty) a "struct ovs_header"
    2495                 :            :  * followed by Netlink attributes corresponding to 'vport'. */
    2496                 :            : static void
    2497                 :       5276 : dpif_netlink_vport_to_ofpbuf(const struct dpif_netlink_vport *vport,
    2498                 :            :                              struct ofpbuf *buf)
    2499                 :            : {
    2500                 :            :     struct ovs_header *ovs_header;
    2501                 :            : 
    2502                 :       5276 :     nl_msg_put_genlmsghdr(buf, 0, ovs_vport_family, NLM_F_REQUEST | NLM_F_ECHO,
    2503                 :       5276 :                           vport->cmd, OVS_VPORT_VERSION);
    2504                 :            : 
    2505                 :       5276 :     ovs_header = ofpbuf_put_uninit(buf, sizeof *ovs_header);
    2506                 :       5276 :     ovs_header->dp_ifindex = vport->dp_ifindex;
    2507                 :            : 
    2508         [ +  + ]:       5276 :     if (vport->port_no != ODPP_NONE) {
    2509                 :       4455 :         nl_msg_put_odp_port(buf, OVS_VPORT_ATTR_PORT_NO, vport->port_no);
    2510                 :            :     }
    2511                 :            : 
    2512         [ +  + ]:       5276 :     if (vport->type != OVS_VPORT_TYPE_UNSPEC) {
    2513                 :        232 :         nl_msg_put_u32(buf, OVS_VPORT_ATTR_TYPE, vport->type);
    2514                 :            :     }
    2515                 :            : 
    2516         [ +  + ]:       5276 :     if (vport->name) {
    2517                 :       4664 :         nl_msg_put_string(buf, OVS_VPORT_ATTR_NAME, vport->name);
    2518                 :            :     }
    2519                 :            : 
    2520         [ +  + ]:       5276 :     if (vport->upcall_pids) {
    2521                 :        590 :         nl_msg_put_unspec(buf, OVS_VPORT_ATTR_UPCALL_PID,
    2522                 :        590 :                           vport->upcall_pids,
    2523                 :        590 :                           vport->n_upcall_pids * sizeof *vport->upcall_pids);
    2524                 :            :     }
    2525                 :            : 
    2526         [ -  + ]:       5276 :     if (vport->stats) {
    2527                 :          0 :         nl_msg_put_unspec(buf, OVS_VPORT_ATTR_STATS,
    2528                 :          0 :                           vport->stats, sizeof *vport->stats);
    2529                 :            :     }
    2530                 :            : 
    2531         [ +  + ]:       5276 :     if (vport->options) {
    2532                 :          3 :         nl_msg_put_nested(buf, OVS_VPORT_ATTR_OPTIONS,
    2533                 :          3 :                           vport->options, vport->options_len);
    2534                 :            :     }
    2535                 :       5276 : }
    2536                 :            : 
    2537                 :            : /* Clears 'vport' to "empty" values. */
    2538                 :            : void
    2539                 :      10769 : dpif_netlink_vport_init(struct dpif_netlink_vport *vport)
    2540                 :            : {
    2541                 :      10769 :     memset(vport, 0, sizeof *vport);
    2542                 :      10769 :     vport->port_no = ODPP_NONE;
    2543                 :      10769 : }
    2544                 :            : 
    2545                 :            : /* Executes 'request' in the kernel datapath.  If the command fails, returns a
    2546                 :            :  * positive errno value.  Otherwise, if 'reply' and 'bufp' are null, returns 0
    2547                 :            :  * without doing anything else.  If 'reply' and 'bufp' are nonnull, then the
    2548                 :            :  * result of the command is expected to be an ovs_vport also, which is decoded
    2549                 :            :  * and stored in '*reply' and '*bufp'.  The caller must free '*bufp' when the
    2550                 :            :  * reply is no longer needed ('reply' will contain pointers into '*bufp'). */
    2551                 :            : int
    2552                 :       5188 : dpif_netlink_vport_transact(const struct dpif_netlink_vport *request,
    2553                 :            :                             struct dpif_netlink_vport *reply,
    2554                 :            :                             struct ofpbuf **bufp)
    2555                 :            : {
    2556                 :            :     struct ofpbuf *request_buf;
    2557                 :            :     int error;
    2558                 :            : 
    2559         [ -  + ]:       5188 :     ovs_assert((reply != NULL) == (bufp != NULL));
    2560                 :            : 
    2561                 :       5188 :     error = dpif_netlink_init();
    2562         [ +  + ]:       5188 :     if (error) {
    2563         [ +  - ]:        166 :         if (reply) {
    2564                 :        166 :             *bufp = NULL;
    2565                 :        166 :             dpif_netlink_vport_init(reply);
    2566                 :            :         }
    2567                 :        166 :         return error;
    2568                 :            :     }
    2569                 :            : 
    2570                 :       5022 :     request_buf = ofpbuf_new(1024);
    2571                 :       5022 :     dpif_netlink_vport_to_ofpbuf(request, request_buf);
    2572                 :       5022 :     error = nl_transact(NETLINK_GENERIC, request_buf, bufp);
    2573                 :       5022 :     ofpbuf_delete(request_buf);
    2574                 :            : 
    2575         [ +  + ]:       5022 :     if (reply) {
    2576         [ +  + ]:       4664 :         if (!error) {
    2577                 :       4418 :             error = dpif_netlink_vport_from_ofpbuf(reply, *bufp);
    2578                 :            :         }
    2579         [ +  + ]:       4664 :         if (error) {
    2580                 :        246 :             dpif_netlink_vport_init(reply);
    2581                 :        246 :             ofpbuf_delete(*bufp);
    2582                 :        246 :             *bufp = NULL;
    2583                 :            :         }
    2584                 :            :     }
    2585                 :       5022 :     return error;
    2586                 :            : }
    2587                 :            : 
    2588                 :            : /* Obtains information about the kernel vport named 'name' and stores it into
    2589                 :            :  * '*reply' and '*bufp'.  The caller must free '*bufp' when the reply is no
    2590                 :            :  * longer needed ('reply' will contain pointers into '*bufp').  */
    2591                 :            : int
    2592                 :        501 : dpif_netlink_vport_get(const char *name, struct dpif_netlink_vport *reply,
    2593                 :            :                        struct ofpbuf **bufp)
    2594                 :            : {
    2595                 :            :     struct dpif_netlink_vport request;
    2596                 :            : 
    2597                 :        501 :     dpif_netlink_vport_init(&request);
    2598                 :        501 :     request.cmd = OVS_VPORT_CMD_GET;
    2599                 :        501 :     request.name = name;
    2600                 :            : 
    2601                 :        501 :     return dpif_netlink_vport_transact(&request, reply, bufp);
    2602                 :            : }
    2603                 :            : 
    2604                 :            : /* Parses the contents of 'buf', which contains a "struct ovs_header" followed
    2605                 :            :  * by Netlink attributes, into 'dp'.  Returns 0 if successful, otherwise a
    2606                 :            :  * positive errno value.
    2607                 :            :  *
    2608                 :            :  * 'dp' will contain pointers into 'buf', so the caller should not free 'buf'
    2609                 :            :  * while 'dp' is still in use. */
    2610                 :            : static int
    2611                 :       1305 : dpif_netlink_dp_from_ofpbuf(struct dpif_netlink_dp *dp, const struct ofpbuf *buf)
    2612                 :            : {
    2613                 :            :     static const struct nl_policy ovs_datapath_policy[] = {
    2614                 :            :         [OVS_DP_ATTR_NAME] = { .type = NL_A_STRING, .max_len = IFNAMSIZ },
    2615                 :            :         [OVS_DP_ATTR_STATS] = { NL_POLICY_FOR(struct ovs_dp_stats),
    2616                 :            :                                 .optional = true },
    2617                 :            :         [OVS_DP_ATTR_MEGAFLOW_STATS] = {
    2618                 :            :                         NL_POLICY_FOR(struct ovs_dp_megaflow_stats),
    2619                 :            :                         .optional = true },
    2620                 :            :     };
    2621                 :            : 
    2622                 :       1305 :     dpif_netlink_dp_init(dp);
    2623                 :            : 
    2624                 :       1305 :     struct ofpbuf b = ofpbuf_const_initializer(buf->data, buf->size);
    2625                 :       1305 :     struct nlmsghdr *nlmsg = ofpbuf_try_pull(&b, sizeof *nlmsg);
    2626                 :       1305 :     struct genlmsghdr *genl = ofpbuf_try_pull(&b, sizeof *genl);
    2627                 :       1305 :     struct ovs_header *ovs_header = ofpbuf_try_pull(&b, sizeof *ovs_header);
    2628                 :            : 
    2629                 :            :     struct nlattr *a[ARRAY_SIZE(ovs_datapath_policy)];
    2630 [ +  - ][ +  - ]:       1305 :     if (!nlmsg || !genl || !ovs_header
                 [ +  - ]
    2631         [ +  - ]:       1305 :         || nlmsg->nlmsg_type != ovs_datapath_family
    2632         [ -  + ]:       1305 :         || !nl_policy_parse(&b, 0, ovs_datapath_policy, a,
    2633                 :            :                             ARRAY_SIZE(ovs_datapath_policy))) {
    2634                 :          0 :         return EINVAL;
    2635                 :            :     }
    2636                 :            : 
    2637                 :       1305 :     dp->cmd = genl->cmd;
    2638                 :       1305 :     dp->dp_ifindex = ovs_header->dp_ifindex;
    2639                 :       1305 :     dp->name = nl_attr_get_string(a[OVS_DP_ATTR_NAME]);
    2640         [ +  - ]:       1305 :     if (a[OVS_DP_ATTR_STATS]) {
    2641                 :       1305 :         dp->stats = nl_attr_get(a[OVS_DP_ATTR_STATS]);
    2642                 :            :     }
    2643                 :            : 
    2644         [ +  - ]:       1305 :     if (a[OVS_DP_ATTR_MEGAFLOW_STATS]) {
    2645                 :       1305 :         dp->megaflow_stats = nl_attr_get(a[OVS_DP_ATTR_MEGAFLOW_STATS]);
    2646                 :            :     }
    2647                 :            : 
    2648                 :       1305 :     return 0;
    2649                 :            : }
    2650                 :            : 
    2651                 :            : /* Appends to 'buf' the Generic Netlink message described by 'dp'. */
    2652                 :            : static void
    2653                 :       1432 : dpif_netlink_dp_to_ofpbuf(const struct dpif_netlink_dp *dp, struct ofpbuf *buf)
    2654                 :            : {
    2655                 :            :     struct ovs_header *ovs_header;
    2656                 :            : 
    2657                 :       1432 :     nl_msg_put_genlmsghdr(buf, 0, ovs_datapath_family,
    2658                 :       1432 :                           NLM_F_REQUEST | NLM_F_ECHO, dp->cmd,
    2659                 :            :                           OVS_DATAPATH_VERSION);
    2660                 :            : 
    2661                 :       1432 :     ovs_header = ofpbuf_put_uninit(buf, sizeof *ovs_header);
    2662                 :       1432 :     ovs_header->dp_ifindex = dp->dp_ifindex;
    2663                 :            : 
    2664         [ +  + ]:       1432 :     if (dp->name) {
    2665                 :        186 :         nl_msg_put_string(buf, OVS_DP_ATTR_NAME, dp->name);
    2666                 :            :     }
    2667                 :            : 
    2668         [ +  + ]:       1432 :     if (dp->upcall_pid) {
    2669                 :         63 :         nl_msg_put_u32(buf, OVS_DP_ATTR_UPCALL_PID, *dp->upcall_pid);
    2670                 :            :     }
    2671                 :            : 
    2672         [ +  + ]:       1432 :     if (dp->user_features) {
    2673                 :        186 :         nl_msg_put_u32(buf, OVS_DP_ATTR_USER_FEATURES, dp->user_features);
    2674                 :            :     }
    2675                 :            : 
    2676                 :            :     /* Skip OVS_DP_ATTR_STATS since we never have a reason to serialize it. */
    2677                 :       1432 : }
    2678                 :            : 
    2679                 :            : /* Clears 'dp' to "empty" values. */
    2680                 :            : static void
    2681                 :       3983 : dpif_netlink_dp_init(struct dpif_netlink_dp *dp)
    2682                 :            : {
    2683                 :       3983 :     memset(dp, 0, sizeof *dp);
    2684                 :       3983 : }
    2685                 :            : 
    2686                 :            : static void
    2687                 :        122 : dpif_netlink_dp_dump_start(struct nl_dump *dump)
    2688                 :            : {
    2689                 :            :     struct dpif_netlink_dp request;
    2690                 :            :     struct ofpbuf *buf;
    2691                 :            : 
    2692                 :        122 :     dpif_netlink_dp_init(&request);
    2693                 :        122 :     request.cmd = OVS_DP_CMD_GET;
    2694                 :            : 
    2695                 :        122 :     buf = ofpbuf_new(1024);
    2696                 :        122 :     dpif_netlink_dp_to_ofpbuf(&request, buf);
    2697                 :        122 :     nl_dump_start(dump, NETLINK_GENERIC, buf);
    2698                 :        122 :     ofpbuf_delete(buf);
    2699                 :        122 : }
    2700                 :            : 
    2701                 :            : /* Executes 'request' in the kernel datapath.  If the command fails, returns a
    2702                 :            :  * positive errno value.  Otherwise, if 'reply' and 'bufp' are null, returns 0
    2703                 :            :  * without doing anything else.  If 'reply' and 'bufp' are nonnull, then the
    2704                 :            :  * result of the command is expected to be of the same form, which is decoded
    2705                 :            :  * and stored in '*reply' and '*bufp'.  The caller must free '*bufp' when the
    2706                 :            :  * reply is no longer needed ('reply' will contain pointers into '*bufp'). */
    2707                 :            : static int
    2708                 :       1310 : dpif_netlink_dp_transact(const struct dpif_netlink_dp *request,
    2709                 :            :                          struct dpif_netlink_dp *reply, struct ofpbuf **bufp)
    2710                 :            : {
    2711                 :            :     struct ofpbuf *request_buf;
    2712                 :            :     int error;
    2713                 :            : 
    2714         [ -  + ]:       1310 :     ovs_assert((reply != NULL) == (bufp != NULL));
    2715                 :            : 
    2716                 :       1310 :     request_buf = ofpbuf_new(1024);
    2717                 :       1310 :     dpif_netlink_dp_to_ofpbuf(request, request_buf);
    2718                 :       1310 :     error = nl_transact(NETLINK_GENERIC, request_buf, bufp);
    2719                 :       1310 :     ofpbuf_delete(request_buf);
    2720                 :            : 
    2721         [ +  + ]:       1310 :     if (reply) {
    2722                 :       1246 :         dpif_netlink_dp_init(reply);
    2723         [ +  - ]:       1246 :         if (!error) {
    2724                 :       1246 :             error = dpif_netlink_dp_from_ofpbuf(reply, *bufp);
    2725                 :            :         }
    2726         [ -  + ]:       1246 :         if (error) {
    2727                 :          0 :             ofpbuf_delete(*bufp);
    2728                 :          0 :             *bufp = NULL;
    2729                 :            :         }
    2730                 :            :     }
    2731                 :       1310 :     return error;
    2732                 :            : }
    2733                 :            : 
    2734                 :            : /* Obtains information about 'dpif_' and stores it into '*reply' and '*bufp'.
    2735                 :            :  * The caller must free '*bufp' when the reply is no longer needed ('reply'
    2736                 :            :  * will contain pointers into '*bufp').  */
    2737                 :            : static int
    2738                 :       1060 : dpif_netlink_dp_get(const struct dpif *dpif_, struct dpif_netlink_dp *reply,
    2739                 :            :                     struct ofpbuf **bufp)
    2740                 :            : {
    2741                 :       1060 :     struct dpif_netlink *dpif = dpif_netlink_cast(dpif_);
    2742                 :            :     struct dpif_netlink_dp request;
    2743                 :            : 
    2744                 :       1060 :     dpif_netlink_dp_init(&request);
    2745                 :       1060 :     request.cmd = OVS_DP_CMD_GET;
    2746                 :       1060 :     request.dp_ifindex = dpif->dp_ifindex;
    2747                 :            : 
    2748                 :       1060 :     return dpif_netlink_dp_transact(&request, reply, bufp);
    2749                 :            : }
    2750                 :            : 
    2751                 :            : /* Parses the contents of 'buf', which contains a "struct ovs_header" followed
    2752                 :            :  * by Netlink attributes, into 'flow'.  Returns 0 if successful, otherwise a
    2753                 :            :  * positive errno value.
    2754                 :            :  *
    2755                 :            :  * 'flow' will contain pointers into 'buf', so the caller should not free 'buf'
    2756                 :            :  * while 'flow' is still in use. */
    2757                 :            : static int
    2758                 :       9741 : dpif_netlink_flow_from_ofpbuf(struct dpif_netlink_flow *flow,
    2759                 :            :                               const struct ofpbuf *buf)
    2760                 :            : {
    2761                 :            :     static const struct nl_policy ovs_flow_policy[__OVS_FLOW_ATTR_MAX] = {
    2762                 :            :         [OVS_FLOW_ATTR_KEY] = { .type = NL_A_NESTED, .optional = true },
    2763                 :            :         [OVS_FLOW_ATTR_MASK] = { .type = NL_A_NESTED, .optional = true },
    2764                 :            :         [OVS_FLOW_ATTR_ACTIONS] = { .type = NL_A_NESTED, .optional = true },
    2765                 :            :         [OVS_FLOW_ATTR_STATS] = { NL_POLICY_FOR(struct ovs_flow_stats),
    2766                 :            :                                   .optional = true },
    2767                 :            :         [OVS_FLOW_ATTR_TCP_FLAGS] = { .type = NL_A_U8, .optional = true },
    2768                 :            :         [OVS_FLOW_ATTR_USED] = { .type = NL_A_U64, .optional = true },
    2769                 :            :         [OVS_FLOW_ATTR_UFID] = { .type = NL_A_UNSPEC, .optional = true,
    2770                 :            :                                  .min_len = sizeof(ovs_u128) },
    2771                 :            :         /* The kernel never uses OVS_FLOW_ATTR_CLEAR. */
    2772                 :            :         /* The kernel never uses OVS_FLOW_ATTR_PROBE. */
    2773                 :            :         /* The kernel never uses OVS_FLOW_ATTR_UFID_FLAGS. */
    2774                 :            :     };
    2775                 :            : 
    2776                 :       9741 :     dpif_netlink_flow_init(flow);
    2777                 :            : 
    2778                 :       9741 :     struct ofpbuf b = ofpbuf_const_initializer(buf->data, buf->size);
    2779                 :       9741 :     struct nlmsghdr *nlmsg = ofpbuf_try_pull(&b, sizeof *nlmsg);
    2780                 :       9741 :     struct genlmsghdr *genl = ofpbuf_try_pull(&b, sizeof *genl);
    2781                 :       9741 :     struct ovs_header *ovs_header = ofpbuf_try_pull(&b, sizeof *ovs_header);
    2782                 :            : 
    2783                 :            :     struct nlattr *a[ARRAY_SIZE(ovs_flow_policy)];
    2784 [ +  - ][ +  - ]:       9741 :     if (!nlmsg || !genl || !ovs_header
                 [ +  - ]
    2785         [ +  - ]:       9741 :         || nlmsg->nlmsg_type != ovs_flow_family
    2786         [ -  + ]:       9741 :         || !nl_policy_parse(&b, 0, ovs_flow_policy, a,
    2787                 :            :                             ARRAY_SIZE(ovs_flow_policy))) {
    2788                 :          0 :         return EINVAL;
    2789                 :            :     }
    2790 [ +  + ][ -  + ]:       9741 :     if (!a[OVS_FLOW_ATTR_KEY] && !a[OVS_FLOW_ATTR_UFID]) {
    2791                 :          0 :         return EINVAL;
    2792                 :            :     }
    2793                 :            : 
    2794                 :       9741 :     flow->nlmsg_flags = nlmsg->nlmsg_flags;
    2795                 :       9741 :     flow->dp_ifindex = ovs_header->dp_ifindex;
    2796         [ +  + ]:       9741 :     if (a[OVS_FLOW_ATTR_KEY]) {
    2797                 :        652 :         flow->key = nl_attr_get(a[OVS_FLOW_ATTR_KEY]);
    2798                 :        652 :         flow->key_len = nl_attr_get_size(a[OVS_FLOW_ATTR_KEY]);
    2799                 :            :     }
    2800                 :            : 
    2801         [ +  + ]:       9741 :     if (a[OVS_FLOW_ATTR_UFID]) {
    2802                 :            :         const ovs_u128 *ufid;
    2803                 :            : 
    2804                 :       9300 :         ufid = nl_attr_get_unspec(a[OVS_FLOW_ATTR_UFID],
    2805                 :       9300 :                                   nl_attr_get_size(a[OVS_FLOW_ATTR_UFID]));
    2806                 :       9300 :         flow->ufid = *ufid;
    2807                 :       9300 :         flow->ufid_present = true;
    2808                 :            :     }
    2809         [ +  + ]:       9741 :     if (a[OVS_FLOW_ATTR_MASK]) {
    2810                 :        652 :         flow->mask = nl_attr_get(a[OVS_FLOW_ATTR_MASK]);
    2811                 :        652 :         flow->mask_len = nl_attr_get_size(a[OVS_FLOW_ATTR_MASK]);
    2812                 :            :     }
    2813         [ +  + ]:       9741 :     if (a[OVS_FLOW_ATTR_ACTIONS]) {
    2814                 :        652 :         flow->actions = nl_attr_get(a[OVS_FLOW_ATTR_ACTIONS]);
    2815                 :        652 :         flow->actions_len = nl_attr_get_size(a[OVS_FLOW_ATTR_ACTIONS]);
    2816                 :            :     }
    2817         [ +  + ]:       9741 :     if (a[OVS_FLOW_ATTR_STATS]) {
    2818                 :       4228 :         flow->stats = nl_attr_get(a[OVS_FLOW_ATTR_STATS]);
    2819                 :            :     }
    2820         [ +  + ]:       9741 :     if (a[OVS_FLOW_ATTR_TCP_FLAGS]) {
    2821                 :       1523 :         flow->tcp_flags = nl_attr_get(a[OVS_FLOW_ATTR_TCP_FLAGS]);
    2822                 :            :     }
    2823         [ +  + ]:       9741 :     if (a[OVS_FLOW_ATTR_USED]) {
    2824                 :       4228 :         flow->used = nl_attr_get(a[OVS_FLOW_ATTR_USED]);
    2825                 :            :     }
    2826                 :       9741 :     return 0;
    2827                 :            : }
    2828                 :            : 
    2829                 :            : /* Appends to 'buf' (which must initially be empty) a "struct ovs_header"
    2830                 :            :  * followed by Netlink attributes corresponding to 'flow'. */
    2831                 :            : static void
    2832                 :       6713 : dpif_netlink_flow_to_ofpbuf(const struct dpif_netlink_flow *flow,
    2833                 :            :                             struct ofpbuf *buf)
    2834                 :            : {
    2835                 :            :     struct ovs_header *ovs_header;
    2836                 :            : 
    2837                 :       6713 :     nl_msg_put_genlmsghdr(buf, 0, ovs_flow_family,
    2838                 :       6713 :                           NLM_F_REQUEST | flow->nlmsg_flags,
    2839                 :       6713 :                           flow->cmd, OVS_FLOW_VERSION);
    2840                 :            : 
    2841                 :       6713 :     ovs_header = ofpbuf_put_uninit(buf, sizeof *ovs_header);
    2842                 :       6713 :     ovs_header->dp_ifindex = flow->dp_ifindex;
    2843                 :            : 
    2844         [ +  + ]:       6713 :     if (flow->ufid_present) {
    2845                 :       2985 :         nl_msg_put_unspec(buf, OVS_FLOW_ATTR_UFID, &flow->ufid,
    2846                 :            :                           sizeof flow->ufid);
    2847                 :            :     }
    2848         [ +  + ]:       6713 :     if (flow->ufid_terse) {
    2849                 :       3522 :         nl_msg_put_u32(buf, OVS_FLOW_ATTR_UFID_FLAGS,
    2850                 :            :                        OVS_UFID_F_OMIT_KEY | OVS_UFID_F_OMIT_MASK
    2851                 :            :                        | OVS_UFID_F_OMIT_ACTIONS);
    2852                 :            :     }
    2853 [ +  + ][ +  + ]:       6713 :     if (!flow->ufid_terse || !flow->ufid_present) {
    2854         [ +  + ]:       5394 :         if (flow->key_len) {
    2855                 :       2989 :             nl_msg_put_unspec(buf, OVS_FLOW_ATTR_KEY,
    2856                 :       2989 :                               flow->key, flow->key_len);
    2857                 :            :         }
    2858                 :            : 
    2859         [ +  + ]:       5394 :         if (flow->mask_len) {
    2860                 :       1351 :             nl_msg_put_unspec(buf, OVS_FLOW_ATTR_MASK,
    2861                 :       1351 :                               flow->mask, flow->mask_len);
    2862                 :            :         }
    2863 [ +  + ][ -  + ]:       5394 :         if (flow->actions || flow->actions_len) {
    2864                 :       1981 :             nl_msg_put_unspec(buf, OVS_FLOW_ATTR_ACTIONS,
    2865                 :       1981 :                               flow->actions, flow->actions_len);
    2866                 :            :         }
    2867                 :            :     }
    2868                 :            : 
    2869                 :            :     /* We never need to send these to the kernel. */
    2870         [ -  + ]:       6713 :     ovs_assert(!flow->stats);
    2871         [ -  + ]:       6713 :     ovs_assert(!flow->tcp_flags);
    2872         [ -  + ]:       6713 :     ovs_assert(!flow->used);
    2873                 :            : 
    2874         [ -  + ]:       6713 :     if (flow->clear) {
    2875                 :          0 :         nl_msg_put_flag(buf, OVS_FLOW_ATTR_CLEAR);
    2876                 :            :     }
    2877         [ +  + ]:       6713 :     if (flow->probe) {
    2878                 :        567 :         nl_msg_put_flag(buf, OVS_FLOW_ATTR_PROBE);
    2879                 :            :     }
    2880                 :       6713 : }
    2881                 :            : 
    2882                 :            : /* Clears 'flow' to "empty" values. */
    2883                 :            : static void
    2884                 :      16454 : dpif_netlink_flow_init(struct dpif_netlink_flow *flow)
    2885                 :            : {
    2886                 :      16454 :     memset(flow, 0, sizeof *flow);
    2887                 :      16454 : }
    2888                 :            : 
    2889                 :            : /* Executes 'request' in the kernel datapath.  If the command fails, returns a
    2890                 :            :  * positive errno value.  Otherwise, if 'reply' and 'bufp' are null, returns 0
    2891                 :            :  * without doing anything else.  If 'reply' and 'bufp' are nonnull, then the
    2892                 :            :  * result of the command is expected to be a flow also, which is decoded and
    2893                 :            :  * stored in '*reply' and '*bufp'.  The caller must free '*bufp' when the reply
    2894                 :            :  * is no longer needed ('reply' will contain pointers into '*bufp'). */
    2895                 :            : static int
    2896                 :        137 : dpif_netlink_flow_transact(struct dpif_netlink_flow *request,
    2897                 :            :                            struct dpif_netlink_flow *reply,
    2898                 :            :                            struct ofpbuf **bufp)
    2899                 :            : {
    2900                 :            :     struct ofpbuf *request_buf;
    2901                 :            :     int error;
    2902                 :            : 
    2903         [ -  + ]:        137 :     ovs_assert((reply != NULL) == (bufp != NULL));
    2904                 :            : 
    2905         [ -  + ]:        137 :     if (reply) {
    2906                 :          0 :         request->nlmsg_flags |= NLM_F_ECHO;
    2907                 :            :     }
    2908                 :            : 
    2909                 :        137 :     request_buf = ofpbuf_new(1024);
    2910                 :        137 :     dpif_netlink_flow_to_ofpbuf(request, request_buf);
    2911                 :        137 :     error = nl_transact(NETLINK_GENERIC, request_buf, bufp);
    2912                 :        137 :     ofpbuf_delete(request_buf);
    2913                 :            : 
    2914         [ -  + ]:        137 :     if (reply) {
    2915         [ #  # ]:          0 :         if (!error) {
    2916                 :          0 :             error = dpif_netlink_flow_from_ofpbuf(reply, *bufp);
    2917                 :            :         }
    2918         [ #  # ]:          0 :         if (error) {
    2919                 :          0 :             dpif_netlink_flow_init(reply);
    2920                 :          0 :             ofpbuf_delete(*bufp);
    2921                 :          0 :             *bufp = NULL;
    2922                 :            :         }
    2923                 :            :     }
    2924                 :        137 :     return error;
    2925                 :            : }
    2926                 :            : 
    2927                 :            : static void
    2928                 :       9741 : dpif_netlink_flow_get_stats(const struct dpif_netlink_flow *flow,
    2929                 :            :                             struct dpif_flow_stats *stats)
    2930                 :            : {
    2931         [ +  + ]:       9741 :     if (flow->stats) {
    2932                 :       4228 :         stats->n_packets = get_32aligned_u64(&flow->stats->n_packets);
    2933                 :       4228 :         stats->n_bytes = get_32aligned_u64(&flow->stats->n_bytes);
    2934                 :            :     } else {
    2935                 :       5513 :         stats->n_packets = 0;
    2936                 :       5513 :         stats->n_bytes = 0;
    2937                 :            :     }
    2938         [ +  + ]:       9741 :     stats->used = flow->used ? get_32aligned_u64(flow->used) : 0;
    2939         [ +  + ]:       9741 :     stats->tcp_flags = flow->tcp_flags ? *flow->tcp_flags : 0;
    2940                 :       9741 : }
    2941                 :            : 
    2942                 :            : /* Logs information about a packet that was recently lost in 'ch' (in
    2943                 :            :  * 'dpif_'). */
    2944                 :            : static void
    2945                 :          0 : report_loss(struct dpif_netlink *dpif, struct dpif_channel *ch, uint32_t ch_idx,
    2946                 :            :             uint32_t handler_id)
    2947                 :            : {
    2948                 :            :     static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 5);
    2949                 :            :     struct ds s;
    2950                 :            : 
    2951         [ #  # ]:          0 :     if (VLOG_DROP_WARN(&rl)) {
    2952                 :          0 :         return;
    2953                 :            :     }
    2954                 :            : 
    2955                 :          0 :     ds_init(&s);
    2956         [ #  # ]:          0 :     if (ch->last_poll != LLONG_MIN) {
    2957                 :          0 :         ds_put_format(&s, " (last polled %lld ms ago)",
    2958                 :          0 :                       time_msec() - ch->last_poll);
    2959                 :            :     }
    2960                 :            : 
    2961         [ #  # ]:          0 :     VLOG_WARN("%s: lost packet on port channel %u of handler %u",
    2962                 :            :               dpif_name(&dpif->dpif), ch_idx, handler_id);
    2963                 :          0 :     ds_destroy(&s);
    2964                 :            : }

Generated by: LCOV version 1.12