LCOV - code coverage report
Current view: top level - lib - dpif-netdev.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 1855 2018 91.9 %
Date: 2016-09-14 01:02:56 Functions: 186 187 99.5 %
Branches: 736 982 74.9 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2016 Nicira, Inc.
       3                 :            :  *
       4                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
       5                 :            :  * you may not use this file except in compliance with the License.
       6                 :            :  * You may obtain a copy of the License at:
       7                 :            :  *
       8                 :            :  *     http://www.apache.org/licenses/LICENSE-2.0
       9                 :            :  *
      10                 :            :  * Unless required by applicable law or agreed to in writing, software
      11                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
      12                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      13                 :            :  * See the License for the specific language governing permissions and
      14                 :            :  * limitations under the License.
      15                 :            :  */
      16                 :            : 
      17                 :            : #include <config.h>
      18                 :            : #include "dpif-netdev.h"
      19                 :            : 
      20                 :            : #include <ctype.h>
      21                 :            : #include <errno.h>
      22                 :            : #include <fcntl.h>
      23                 :            : #include <inttypes.h>
      24                 :            : #include <net/if.h>
      25                 :            : #include <netinet/in.h>
      26                 :            : #include <stdint.h>
      27                 :            : #include <stdlib.h>
      28                 :            : #include <string.h>
      29                 :            : #include <sys/ioctl.h>
      30                 :            : #include <sys/socket.h>
      31                 :            : #include <sys/stat.h>
      32                 :            : #include <unistd.h>
      33                 :            : 
      34                 :            : #include "bitmap.h"
      35                 :            : #include "cmap.h"
      36                 :            : #include "conntrack.h"
      37                 :            : #include "coverage.h"
      38                 :            : #include "ct-dpif.h"
      39                 :            : #include "csum.h"
      40                 :            : #include "dp-packet.h"
      41                 :            : #include "dpif.h"
      42                 :            : #include "dpif-provider.h"
      43                 :            : #include "dummy.h"
      44                 :            : #include "fat-rwlock.h"
      45                 :            : #include "flow.h"
      46                 :            : #include "hmapx.h"
      47                 :            : #include "latch.h"
      48                 :            : #include "netdev.h"
      49                 :            : #include "netdev-dpdk.h"
      50                 :            : #include "netdev-vport.h"
      51                 :            : #include "netlink.h"
      52                 :            : #include "odp-execute.h"
      53                 :            : #include "odp-util.h"
      54                 :            : #include "openvswitch/dynamic-string.h"
      55                 :            : #include "openvswitch/list.h"
      56                 :            : #include "openvswitch/match.h"
      57                 :            : #include "openvswitch/ofp-print.h"
      58                 :            : #include "openvswitch/ofp-util.h"
      59                 :            : #include "openvswitch/ofpbuf.h"
      60                 :            : #include "openvswitch/shash.h"
      61                 :            : #include "openvswitch/vlog.h"
      62                 :            : #include "ovs-numa.h"
      63                 :            : #include "ovs-rcu.h"
      64                 :            : #include "packets.h"
      65                 :            : #include "poll-loop.h"
      66                 :            : #include "pvector.h"
      67                 :            : #include "random.h"
      68                 :            : #include "seq.h"
      69                 :            : #include "smap.h"
      70                 :            : #include "sset.h"
      71                 :            : #include "timeval.h"
      72                 :            : #include "tnl-neigh-cache.h"
      73                 :            : #include "tnl-ports.h"
      74                 :            : #include "unixctl.h"
      75                 :            : #include "util.h"
      76                 :            : 
      77                 :      20190 : VLOG_DEFINE_THIS_MODULE(dpif_netdev);
      78                 :            : 
      79                 :            : #define FLOW_DUMP_MAX_BATCH 50
      80                 :            : /* Use per thread recirc_depth to prevent recirculation loop. */
      81                 :            : #define MAX_RECIRC_DEPTH 5
      82                 :     153974 : DEFINE_STATIC_PER_THREAD_DATA(uint32_t, recirc_depth, 0)
      83                 :            : 
      84                 :            : /* Configuration parameters. */
      85                 :            : enum { MAX_FLOWS = 65536 };     /* Maximum number of flows in flow table. */
      86                 :            : 
      87                 :            : /* Protects against changes to 'dp_netdevs'. */
      88                 :            : static struct ovs_mutex dp_netdev_mutex = OVS_MUTEX_INITIALIZER;
      89                 :            : 
      90                 :            : /* Contains all 'struct dp_netdev's. */
      91                 :            : static struct shash dp_netdevs OVS_GUARDED_BY(dp_netdev_mutex)
      92                 :            :     = SHASH_INITIALIZER(&dp_netdevs);
      93                 :            : 
      94                 :            : static struct vlog_rate_limit upcall_rl = VLOG_RATE_LIMIT_INIT(600, 600);
      95                 :            : 
      96                 :            : #define DP_NETDEV_CS_SUPPORTED_MASK (CS_NEW | CS_ESTABLISHED | CS_RELATED \
      97                 :            :                                      | CS_INVALID | CS_REPLY_DIR | CS_TRACKED)
      98                 :            : #define DP_NETDEV_CS_UNSUPPORTED_MASK (~(uint32_t)DP_NETDEV_CS_SUPPORTED_MASK)
      99                 :            : 
     100                 :            : static struct odp_support dp_netdev_support = {
     101                 :            :     .max_mpls_depth = SIZE_MAX,
     102                 :            :     .recirc = true,
     103                 :            :     .ct_state = true,
     104                 :            :     .ct_zone = true,
     105                 :            :     .ct_mark = true,
     106                 :            :     .ct_label = true,
     107                 :            : };
     108                 :            : 
     109                 :            : /* Stores a miniflow with inline values */
     110                 :            : 
     111                 :            : struct netdev_flow_key {
     112                 :            :     uint32_t hash;       /* Hash function differs for different users. */
     113                 :            :     uint32_t len;        /* Length of the following miniflow (incl. map). */
     114                 :            :     struct miniflow mf;
     115                 :            :     uint64_t buf[FLOW_MAX_PACKET_U64S];
     116                 :            : };
     117                 :            : 
     118                 :            : /* Exact match cache for frequently used flows
     119                 :            :  *
     120                 :            :  * The cache uses a 32-bit hash of the packet (which can be the RSS hash) to
     121                 :            :  * search its entries for a miniflow that matches exactly the miniflow of the
     122                 :            :  * packet. It stores the 'dpcls_rule' (rule) that matches the miniflow.
     123                 :            :  *
     124                 :            :  * A cache entry holds a reference to its 'dp_netdev_flow'.
     125                 :            :  *
     126                 :            :  * A miniflow with a given hash can be in one of EM_FLOW_HASH_SEGS different
     127                 :            :  * entries. The 32-bit hash is split into EM_FLOW_HASH_SEGS values (each of
     128                 :            :  * them is EM_FLOW_HASH_SHIFT bits wide and the remainder is thrown away). Each
     129                 :            :  * value is the index of a cache entry where the miniflow could be.
     130                 :            :  *
     131                 :            :  *
     132                 :            :  * Thread-safety
     133                 :            :  * =============
     134                 :            :  *
     135                 :            :  * Each pmd_thread has its own private exact match cache.
     136                 :            :  * If dp_netdev_input is not called from a pmd thread, a mutex is used.
     137                 :            :  */
     138                 :            : 
     139                 :            : #define EM_FLOW_HASH_SHIFT 13
     140                 :            : #define EM_FLOW_HASH_ENTRIES (1u << EM_FLOW_HASH_SHIFT)
     141                 :            : #define EM_FLOW_HASH_MASK (EM_FLOW_HASH_ENTRIES - 1)
     142                 :            : #define EM_FLOW_HASH_SEGS 2
     143                 :            : 
     144                 :            : struct emc_entry {
     145                 :            :     struct dp_netdev_flow *flow;
     146                 :            :     struct netdev_flow_key key;   /* key.hash used for emc hash value. */
     147                 :            : };
     148                 :            : 
     149                 :            : struct emc_cache {
     150                 :            :     struct emc_entry entries[EM_FLOW_HASH_ENTRIES];
     151                 :            :     int sweep_idx;                /* For emc_cache_slow_sweep(). */
     152                 :            : };
     153                 :            : 
     154                 :            : /* Iterate in the exact match cache through every entry that might contain a
     155                 :            :  * miniflow with hash 'HASH'. */
     156                 :            : #define EMC_FOR_EACH_POS_WITH_HASH(EMC, CURRENT_ENTRY, HASH)                 \
     157                 :            :     for (uint32_t i__ = 0, srch_hash__ = (HASH);                             \
     158                 :            :          (CURRENT_ENTRY) = &(EMC)->entries[srch_hash__ & EM_FLOW_HASH_MASK], \
     159                 :            :          i__ < EM_FLOW_HASH_SEGS;                                            \
     160                 :            :          i__++, srch_hash__ >>= EM_FLOW_HASH_SHIFT)
     161                 :            : 
     162                 :            : /* Simple non-wildcarding single-priority classifier. */
     163                 :            : 
     164                 :            : /* Time in ms between successive optimizations of the dpcls subtable vector */
     165                 :            : #define DPCLS_OPTIMIZATION_INTERVAL 1000
     166                 :            : 
     167                 :            : struct dpcls {
     168                 :            :     struct cmap_node node;      /* Within dp_netdev_pmd_thread.classifiers */
     169                 :            :     odp_port_t in_port;
     170                 :            :     struct cmap subtables_map;
     171                 :            :     struct pvector subtables;
     172                 :            : };
     173                 :            : 
     174                 :            : /* A rule to be inserted to the classifier. */
     175                 :            : struct dpcls_rule {
     176                 :            :     struct cmap_node cmap_node;   /* Within struct dpcls_subtable 'rules'. */
     177                 :            :     struct netdev_flow_key *mask; /* Subtable's mask. */
     178                 :            :     struct netdev_flow_key flow;  /* Matching key. */
     179                 :            :     /* 'flow' must be the last field, additional space is allocated here. */
     180                 :            : };
     181                 :            : 
     182                 :            : static void dpcls_init(struct dpcls *);
     183                 :            : static void dpcls_destroy(struct dpcls *);
     184                 :            : static void dpcls_sort_subtable_vector(struct dpcls *);
     185                 :            : static void dpcls_insert(struct dpcls *, struct dpcls_rule *,
     186                 :            :                          const struct netdev_flow_key *mask);
     187                 :            : static void dpcls_remove(struct dpcls *, struct dpcls_rule *);
     188                 :            : static bool dpcls_lookup(struct dpcls *cls,
     189                 :            :                          const struct netdev_flow_key keys[],
     190                 :            :                          struct dpcls_rule **rules, size_t cnt,
     191                 :            :                          int *num_lookups_p);
     192                 :            : 
     193                 :            : /* Datapath based on the network device interface from netdev.h.
     194                 :            :  *
     195                 :            :  *
     196                 :            :  * Thread-safety
     197                 :            :  * =============
     198                 :            :  *
     199                 :            :  * Some members, marked 'const', are immutable.  Accessing other members
     200                 :            :  * requires synchronization, as noted in more detail below.
     201                 :            :  *
     202                 :            :  * Acquisition order is, from outermost to innermost:
     203                 :            :  *
     204                 :            :  *    dp_netdev_mutex (global)
     205                 :            :  *    port_mutex
     206                 :            :  *    non_pmd_mutex
     207                 :            :  */
     208                 :            : struct dp_netdev {
     209                 :            :     const struct dpif_class *const class;
     210                 :            :     const char *const name;
     211                 :            :     struct dpif *dpif;
     212                 :            :     struct ovs_refcount ref_cnt;
     213                 :            :     atomic_flag destroyed;
     214                 :            : 
     215                 :            :     /* Ports.
     216                 :            :      *
     217                 :            :      * Any lookup into 'ports' or any access to the dp_netdev_ports found
     218                 :            :      * through 'ports' requires taking 'port_mutex'. */
     219                 :            :     struct ovs_mutex port_mutex;
     220                 :            :     struct hmap ports;
     221                 :            :     struct seq *port_seq;       /* Incremented whenever a port changes. */
     222                 :            : 
     223                 :            :     /* Protects access to ofproto-dpif-upcall interface during revalidator
     224                 :            :      * thread synchronization. */
     225                 :            :     struct fat_rwlock upcall_rwlock;
     226                 :            :     upcall_callback *upcall_cb;  /* Callback function for executing upcalls. */
     227                 :            :     void *upcall_aux;
     228                 :            : 
     229                 :            :     /* Callback function for notifying the purging of dp flows (during
     230                 :            :      * reseting pmd deletion). */
     231                 :            :     dp_purge_callback *dp_purge_cb;
     232                 :            :     void *dp_purge_aux;
     233                 :            : 
     234                 :            :     /* Stores all 'struct dp_netdev_pmd_thread's. */
     235                 :            :     struct cmap poll_threads;
     236                 :            : 
     237                 :            :     /* Protects the access of the 'struct dp_netdev_pmd_thread'
     238                 :            :      * instance for non-pmd thread. */
     239                 :            :     struct ovs_mutex non_pmd_mutex;
     240                 :            : 
     241                 :            :     /* Each pmd thread will store its pointer to
     242                 :            :      * 'struct dp_netdev_pmd_thread' in 'per_pmd_key'. */
     243                 :            :     ovsthread_key_t per_pmd_key;
     244                 :            : 
     245                 :            :     struct seq *reconfigure_seq;
     246                 :            :     uint64_t last_reconfigure_seq;
     247                 :            : 
     248                 :            :     /* Cpu mask for pin of pmd threads. */
     249                 :            :     char *pmd_cmask;
     250                 :            : 
     251                 :            :     uint64_t last_tnl_conf_seq;
     252                 :            : 
     253                 :            :     struct conntrack conntrack;
     254                 :            : };
     255                 :            : 
     256                 :            : static struct dp_netdev_port *dp_netdev_lookup_port(const struct dp_netdev *dp,
     257                 :            :                                                     odp_port_t)
     258                 :            :     OVS_REQUIRES(dp->port_mutex);
     259                 :            : 
     260                 :            : enum dp_stat_type {
     261                 :            :     DP_STAT_EXACT_HIT,          /* Packets that had an exact match (emc). */
     262                 :            :     DP_STAT_MASKED_HIT,         /* Packets that matched in the flow table. */
     263                 :            :     DP_STAT_MISS,               /* Packets that did not match. */
     264                 :            :     DP_STAT_LOST,               /* Packets not passed up to the client. */
     265                 :            :     DP_STAT_LOOKUP_HIT,         /* Number of subtable lookups for flow table
     266                 :            :                                    hits */
     267                 :            :     DP_N_STATS
     268                 :            : };
     269                 :            : 
     270                 :            : enum pmd_cycles_counter_type {
     271                 :            :     PMD_CYCLES_POLLING,         /* Cycles spent polling NICs. */
     272                 :            :     PMD_CYCLES_PROCESSING,      /* Cycles spent processing packets */
     273                 :            :     PMD_N_CYCLES
     274                 :            : };
     275                 :            : 
     276                 :            : #define XPS_TIMEOUT_MS 500LL
     277                 :            : 
     278                 :            : /* Contained by struct dp_netdev_port's 'rxqs' member.  */
     279                 :            : struct dp_netdev_rxq {
     280                 :            :     struct netdev_rxq *rxq;
     281                 :            :     unsigned core_id;           /* Сore to which this queue is pinned. */
     282                 :            : };
     283                 :            : 
     284                 :            : /* A port in a netdev-based datapath. */
     285                 :            : struct dp_netdev_port {
     286                 :            :     odp_port_t port_no;
     287                 :            :     struct netdev *netdev;
     288                 :            :     struct hmap_node node;      /* Node in dp_netdev's 'ports'. */
     289                 :            :     struct netdev_saved_flags *sf;
     290                 :            :     unsigned n_rxq;             /* Number of elements in 'rxq' */
     291                 :            :     struct dp_netdev_rxq *rxqs;
     292                 :            :     bool dynamic_txqs;          /* If true XPS will be used. */
     293                 :            :     unsigned *txq_used;         /* Number of threads that uses each tx queue. */
     294                 :            :     struct ovs_mutex txq_used_mutex;
     295                 :            :     char *type;                 /* Port type as requested by user. */
     296                 :            :     char *rxq_affinity_list;    /* Requested affinity of rx queues. */
     297                 :            : };
     298                 :            : 
     299                 :            : /* Contained by struct dp_netdev_flow's 'stats' member.  */
     300                 :            : struct dp_netdev_flow_stats {
     301                 :            :     atomic_llong used;             /* Last used time, in monotonic msecs. */
     302                 :            :     atomic_ullong packet_count;    /* Number of packets matched. */
     303                 :            :     atomic_ullong byte_count;      /* Number of bytes matched. */
     304                 :            :     atomic_uint16_t tcp_flags;     /* Bitwise-OR of seen tcp_flags values. */
     305                 :            : };
     306                 :            : 
     307                 :            : /* A flow in 'dp_netdev_pmd_thread's 'flow_table'.
     308                 :            :  *
     309                 :            :  *
     310                 :            :  * Thread-safety
     311                 :            :  * =============
     312                 :            :  *
     313                 :            :  * Except near the beginning or ending of its lifespan, rule 'rule' belongs to
     314                 :            :  * its pmd thread's classifier.  The text below calls this classifier 'cls'.
     315                 :            :  *
     316                 :            :  * Motivation
     317                 :            :  * ----------
     318                 :            :  *
     319                 :            :  * The thread safety rules described here for "struct dp_netdev_flow" are
     320                 :            :  * motivated by two goals:
     321                 :            :  *
     322                 :            :  *    - Prevent threads that read members of "struct dp_netdev_flow" from
     323                 :            :  *      reading bad data due to changes by some thread concurrently modifying
     324                 :            :  *      those members.
     325                 :            :  *
     326                 :            :  *    - Prevent two threads making changes to members of a given "struct
     327                 :            :  *      dp_netdev_flow" from interfering with each other.
     328                 :            :  *
     329                 :            :  *
     330                 :            :  * Rules
     331                 :            :  * -----
     332                 :            :  *
     333                 :            :  * A flow 'flow' may be accessed without a risk of being freed during an RCU
     334                 :            :  * grace period.  Code that needs to hold onto a flow for a while
     335                 :            :  * should try incrementing 'flow->ref_cnt' with dp_netdev_flow_ref().
     336                 :            :  *
     337                 :            :  * 'flow->ref_cnt' protects 'flow' from being freed.  It doesn't protect the
     338                 :            :  * flow from being deleted from 'cls' and it doesn't protect members of 'flow'
     339                 :            :  * from modification.
     340                 :            :  *
     341                 :            :  * Some members, marked 'const', are immutable.  Accessing other members
     342                 :            :  * requires synchronization, as noted in more detail below.
     343                 :            :  */
     344                 :            : struct dp_netdev_flow {
     345                 :            :     const struct flow flow;      /* Unmasked flow that created this entry. */
     346                 :            :     /* Hash table index by unmasked flow. */
     347                 :            :     const struct cmap_node node; /* In owning dp_netdev_pmd_thread's */
     348                 :            :                                  /* 'flow_table'. */
     349                 :            :     const ovs_u128 ufid;         /* Unique flow identifier. */
     350                 :            :     const unsigned pmd_id;       /* The 'core_id' of pmd thread owning this */
     351                 :            :                                  /* flow. */
     352                 :            : 
     353                 :            :     /* Number of references.
     354                 :            :      * The classifier owns one reference.
     355                 :            :      * Any thread trying to keep a rule from being freed should hold its own
     356                 :            :      * reference. */
     357                 :            :     struct ovs_refcount ref_cnt;
     358                 :            : 
     359                 :            :     bool dead;
     360                 :            : 
     361                 :            :     /* Statistics. */
     362                 :            :     struct dp_netdev_flow_stats stats;
     363                 :            : 
     364                 :            :     /* Actions. */
     365                 :            :     OVSRCU_TYPE(struct dp_netdev_actions *) actions;
     366                 :            : 
     367                 :            :     /* While processing a group of input packets, the datapath uses the next
     368                 :            :      * member to store a pointer to the output batch for the flow.  It is
     369                 :            :      * reset after the batch has been sent out (See dp_netdev_queue_batches(),
     370                 :            :      * packet_batch_per_flow_init() and packet_batch_per_flow_execute()). */
     371                 :            :     struct packet_batch_per_flow *batch;
     372                 :            : 
     373                 :            :     /* Packet classification. */
     374                 :            :     struct dpcls_rule cr;        /* In owning dp_netdev's 'cls'. */
     375                 :            :     /* 'cr' must be the last member. */
     376                 :            : };
     377                 :            : 
     378                 :            : static void dp_netdev_flow_unref(struct dp_netdev_flow *);
     379                 :            : static bool dp_netdev_flow_ref(struct dp_netdev_flow *);
     380                 :            : static int dpif_netdev_flow_from_nlattrs(const struct nlattr *, uint32_t,
     381                 :            :                                          struct flow *);
     382                 :            : 
     383                 :            : /* A set of datapath actions within a "struct dp_netdev_flow".
     384                 :            :  *
     385                 :            :  *
     386                 :            :  * Thread-safety
     387                 :            :  * =============
     388                 :            :  *
     389                 :            :  * A struct dp_netdev_actions 'actions' is protected with RCU. */
     390                 :            : struct dp_netdev_actions {
     391                 :            :     /* These members are immutable: they do not change during the struct's
     392                 :            :      * lifetime.  */
     393                 :            :     unsigned int size;          /* Size of 'actions', in bytes. */
     394                 :            :     struct nlattr actions[];    /* Sequence of OVS_ACTION_ATTR_* attributes. */
     395                 :            : };
     396                 :            : 
     397                 :            : struct dp_netdev_actions *dp_netdev_actions_create(const struct nlattr *,
     398                 :            :                                                    size_t);
     399                 :            : struct dp_netdev_actions *dp_netdev_flow_get_actions(
     400                 :            :     const struct dp_netdev_flow *);
     401                 :            : static void dp_netdev_actions_free(struct dp_netdev_actions *);
     402                 :            : 
     403                 :            : /* Contained by struct dp_netdev_pmd_thread's 'stats' member.  */
     404                 :            : struct dp_netdev_pmd_stats {
     405                 :            :     /* Indexed by DP_STAT_*. */
     406                 :            :     atomic_ullong n[DP_N_STATS];
     407                 :            : };
     408                 :            : 
     409                 :            : /* Contained by struct dp_netdev_pmd_thread's 'cycle' member.  */
     410                 :            : struct dp_netdev_pmd_cycles {
     411                 :            :     /* Indexed by PMD_CYCLES_*. */
     412                 :            :     atomic_ullong n[PMD_N_CYCLES];
     413                 :            : };
     414                 :            : 
     415                 :            : /* Contained by struct dp_netdev_pmd_thread's 'poll_list' member. */
     416                 :            : struct rxq_poll {
     417                 :            :     struct dp_netdev_port *port;
     418                 :            :     struct netdev_rxq *rx;
     419                 :            :     struct ovs_list node;
     420                 :            : };
     421                 :            : 
     422                 :            : /* Contained by struct dp_netdev_pmd_thread's 'port_cache' or 'tx_ports'. */
     423                 :            : struct tx_port {
     424                 :            :     struct dp_netdev_port *port;
     425                 :            :     int qid;
     426                 :            :     long long last_used;
     427                 :            :     struct hmap_node node;
     428                 :            : };
     429                 :            : 
     430                 :            : /* PMD: Poll modes drivers.  PMD accesses devices via polling to eliminate
     431                 :            :  * the performance overhead of interrupt processing.  Therefore netdev can
     432                 :            :  * not implement rx-wait for these devices.  dpif-netdev needs to poll
     433                 :            :  * these device to check for recv buffer.  pmd-thread does polling for
     434                 :            :  * devices assigned to itself.
     435                 :            :  *
     436                 :            :  * DPDK used PMD for accessing NIC.
     437                 :            :  *
     438                 :            :  * Note, instance with cpu core id NON_PMD_CORE_ID will be reserved for
     439                 :            :  * I/O of all non-pmd threads.  There will be no actual thread created
     440                 :            :  * for the instance.
     441                 :            :  *
     442                 :            :  * Each struct has its own flow table and classifier.  Packets received
     443                 :            :  * from managed ports are looked up in the corresponding pmd thread's
     444                 :            :  * flow table, and are executed with the found actions.
     445                 :            :  * */
     446                 :            : struct dp_netdev_pmd_thread {
     447                 :            :     struct dp_netdev *dp;
     448                 :            :     struct ovs_refcount ref_cnt;    /* Every reference must be refcount'ed. */
     449                 :            :     struct cmap_node node;          /* In 'dp->poll_threads'. */
     450                 :            : 
     451                 :            :     pthread_cond_t cond;            /* For synchronizing pmd thread reload. */
     452                 :            :     struct ovs_mutex cond_mutex;    /* Mutex for condition variable. */
     453                 :            : 
     454                 :            :     /* Per thread exact-match cache.  Note, the instance for cpu core
     455                 :            :      * NON_PMD_CORE_ID can be accessed by multiple threads, and thusly
     456                 :            :      * need to be protected by 'non_pmd_mutex'.  Every other instance
     457                 :            :      * will only be accessed by its own pmd thread. */
     458                 :            :     struct emc_cache flow_cache;
     459                 :            : 
     460                 :            :     /* Flow-Table and classifiers
     461                 :            :      *
     462                 :            :      * Writers of 'flow_table' must take the 'flow_mutex'.  Corresponding
     463                 :            :      * changes to 'classifiers' must be made while still holding the
     464                 :            :      * 'flow_mutex'.
     465                 :            :      */
     466                 :            :     struct ovs_mutex flow_mutex;
     467                 :            :     struct cmap flow_table OVS_GUARDED; /* Flow table. */
     468                 :            : 
     469                 :            :     /* One classifier per in_port polled by the pmd */
     470                 :            :     struct cmap classifiers;
     471                 :            :     /* Periodically sort subtable vectors according to hit frequencies */
     472                 :            :     long long int next_optimization;
     473                 :            : 
     474                 :            :     /* Statistics. */
     475                 :            :     struct dp_netdev_pmd_stats stats;
     476                 :            : 
     477                 :            :     /* Cycles counters */
     478                 :            :     struct dp_netdev_pmd_cycles cycles;
     479                 :            : 
     480                 :            :     /* Used to count cicles. See 'cycles_counter_end()' */
     481                 :            :     unsigned long long last_cycles;
     482                 :            : 
     483                 :            :     struct latch exit_latch;        /* For terminating the pmd thread. */
     484                 :            :     atomic_uint change_seq;         /* For reloading pmd ports. */
     485                 :            :     pthread_t thread;
     486                 :            :     unsigned core_id;               /* CPU core id of this pmd thread. */
     487                 :            :     int numa_id;                    /* numa node id of this pmd thread. */
     488                 :            :     bool isolated;
     489                 :            : 
     490                 :            :     /* Queue id used by this pmd thread to send packets on all netdevs if
     491                 :            :      * XPS disabled for this netdev. All static_tx_qid's are unique and less
     492                 :            :      * than 'ovs_numa_get_n_cores() + 1'. */
     493                 :            :     atomic_int static_tx_qid;
     494                 :            : 
     495                 :            :     struct ovs_mutex port_mutex;    /* Mutex for 'poll_list' and 'tx_ports'. */
     496                 :            :     /* List of rx queues to poll. */
     497                 :            :     struct ovs_list poll_list OVS_GUARDED;
     498                 :            :     /* Number of elements in 'poll_list' */
     499                 :            :     int poll_cnt;
     500                 :            :     /* Map of 'tx_port's used for transmission.  Written by the main thread,
     501                 :            :      * read by the pmd thread. */
     502                 :            :     struct hmap tx_ports OVS_GUARDED;
     503                 :            : 
     504                 :            :     /* Map of 'tx_port' used in the fast path. This is a thread-local copy of
     505                 :            :      * 'tx_ports'. The instance for cpu core NON_PMD_CORE_ID can be accessed
     506                 :            :      * by multiple threads, and thusly need to be protected by 'non_pmd_mutex'.
     507                 :            :      * Every other instance will only be accessed by its own pmd thread. */
     508                 :            :     struct hmap port_cache;
     509                 :            : 
     510                 :            :     /* Only a pmd thread can write on its own 'cycles' and 'stats'.
     511                 :            :      * The main thread keeps 'stats_zero' and 'cycles_zero' as base
     512                 :            :      * values and subtracts them from 'stats' and 'cycles' before
     513                 :            :      * reporting to the user */
     514                 :            :     unsigned long long stats_zero[DP_N_STATS];
     515                 :            :     uint64_t cycles_zero[PMD_N_CYCLES];
     516                 :            : };
     517                 :            : 
     518                 :            : #define PMD_INITIAL_SEQ 1
     519                 :            : 
     520                 :            : /* Interface to netdev-based datapath. */
     521                 :            : struct dpif_netdev {
     522                 :            :     struct dpif dpif;
     523                 :            :     struct dp_netdev *dp;
     524                 :            :     uint64_t last_port_seq;
     525                 :            : };
     526                 :            : 
     527                 :            : static int get_port_by_number(struct dp_netdev *dp, odp_port_t port_no,
     528                 :            :                               struct dp_netdev_port **portp)
     529                 :            :     OVS_REQUIRES(dp->port_mutex);
     530                 :            : static int get_port_by_name(struct dp_netdev *dp, const char *devname,
     531                 :            :                             struct dp_netdev_port **portp)
     532                 :            :     OVS_REQUIRES(dp->port_mutex);
     533                 :            : static void dp_netdev_free(struct dp_netdev *)
     534                 :            :     OVS_REQUIRES(dp_netdev_mutex);
     535                 :            : static int do_add_port(struct dp_netdev *dp, const char *devname,
     536                 :            :                        const char *type, odp_port_t port_no)
     537                 :            :     OVS_REQUIRES(dp->port_mutex);
     538                 :            : static void do_del_port(struct dp_netdev *dp, struct dp_netdev_port *)
     539                 :            :     OVS_REQUIRES(dp->port_mutex);
     540                 :            : static int dpif_netdev_open(const struct dpif_class *, const char *name,
     541                 :            :                             bool create, struct dpif **);
     542                 :            : static void dp_netdev_execute_actions(struct dp_netdev_pmd_thread *pmd,
     543                 :            :                                       struct dp_packet_batch *,
     544                 :            :                                       bool may_steal, const struct flow *flow,
     545                 :            :                                       const struct nlattr *actions,
     546                 :            :                                       size_t actions_len,
     547                 :            :                                       long long now);
     548                 :            : static void dp_netdev_input(struct dp_netdev_pmd_thread *,
     549                 :            :                             struct dp_packet_batch *, odp_port_t port_no);
     550                 :            : static void dp_netdev_recirculate(struct dp_netdev_pmd_thread *,
     551                 :            :                                   struct dp_packet_batch *);
     552                 :            : 
     553                 :            : static void dp_netdev_disable_upcall(struct dp_netdev *);
     554                 :            : static void dp_netdev_pmd_reload_done(struct dp_netdev_pmd_thread *pmd);
     555                 :            : static void dp_netdev_configure_pmd(struct dp_netdev_pmd_thread *pmd,
     556                 :            :                                     struct dp_netdev *dp, unsigned core_id,
     557                 :            :                                     int numa_id);
     558                 :            : static void dp_netdev_destroy_pmd(struct dp_netdev_pmd_thread *pmd);
     559                 :            : static void dp_netdev_set_nonpmd(struct dp_netdev *dp)
     560                 :            :     OVS_REQUIRES(dp->port_mutex);
     561                 :            : 
     562                 :            : static struct dp_netdev_pmd_thread *dp_netdev_get_pmd(struct dp_netdev *dp,
     563                 :            :                                                       unsigned core_id);
     564                 :            : static struct dp_netdev_pmd_thread *
     565                 :            : dp_netdev_pmd_get_next(struct dp_netdev *dp, struct cmap_position *pos);
     566                 :            : static void dp_netdev_destroy_all_pmds(struct dp_netdev *dp);
     567                 :            : static void dp_netdev_del_pmds_on_numa(struct dp_netdev *dp, int numa_id);
     568                 :            : static void dp_netdev_set_pmds_on_numa(struct dp_netdev *dp, int numa_id)
     569                 :            :     OVS_REQUIRES(dp->port_mutex);
     570                 :            : static void dp_netdev_pmd_clear_ports(struct dp_netdev_pmd_thread *pmd);
     571                 :            : static void dp_netdev_del_port_from_all_pmds(struct dp_netdev *dp,
     572                 :            :                                              struct dp_netdev_port *port);
     573                 :            : static void dp_netdev_add_port_to_pmds(struct dp_netdev *dp,
     574                 :            :                                        struct dp_netdev_port *port);
     575                 :            : static void dp_netdev_add_port_tx_to_pmd(struct dp_netdev_pmd_thread *pmd,
     576                 :            :                                          struct dp_netdev_port *port);
     577                 :            : static void dp_netdev_add_rxq_to_pmd(struct dp_netdev_pmd_thread *pmd,
     578                 :            :                                      struct dp_netdev_port *port,
     579                 :            :                                      struct netdev_rxq *rx);
     580                 :            : static struct dp_netdev_pmd_thread *
     581                 :            : dp_netdev_less_loaded_pmd_on_numa(struct dp_netdev *dp, int numa_id);
     582                 :            : static void dp_netdev_reset_pmd_threads(struct dp_netdev *dp)
     583                 :            :     OVS_REQUIRES(dp->port_mutex);
     584                 :            : static void reconfigure_pmd_threads(struct dp_netdev *dp)
     585                 :            :     OVS_REQUIRES(dp->port_mutex);
     586                 :            : static bool dp_netdev_pmd_try_ref(struct dp_netdev_pmd_thread *pmd);
     587                 :            : static void dp_netdev_pmd_unref(struct dp_netdev_pmd_thread *pmd);
     588                 :            : static void dp_netdev_pmd_flow_flush(struct dp_netdev_pmd_thread *pmd);
     589                 :            : static void pmd_load_cached_ports(struct dp_netdev_pmd_thread *pmd)
     590                 :            :     OVS_REQUIRES(pmd->port_mutex);
     591                 :            : static inline void
     592                 :            : dp_netdev_pmd_try_optimize(struct dp_netdev_pmd_thread *pmd);
     593                 :            : 
     594                 :            : static void
     595                 :            : dpif_netdev_xps_revalidate_pmd(const struct dp_netdev_pmd_thread *pmd,
     596                 :            :                                long long now, bool purge);
     597                 :            : static int dpif_netdev_xps_get_tx_qid(const struct dp_netdev_pmd_thread *pmd,
     598                 :            :                                       struct tx_port *tx, long long now);
     599                 :            : 
     600                 :            : static inline bool emc_entry_alive(struct emc_entry *ce);
     601                 :            : static void emc_clear_entry(struct emc_entry *ce);
     602                 :            : 
     603                 :            : static void
     604                 :        690 : emc_cache_init(struct emc_cache *flow_cache)
     605                 :            : {
     606                 :            :     int i;
     607                 :            : 
     608                 :        690 :     flow_cache->sweep_idx = 0;
     609         [ +  + ]:    5653170 :     for (i = 0; i < ARRAY_SIZE(flow_cache->entries); i++) {
     610                 :    5652480 :         flow_cache->entries[i].flow = NULL;
     611                 :    5652480 :         flow_cache->entries[i].key.hash = 0;
     612                 :    5652480 :         flow_cache->entries[i].key.len = sizeof(struct miniflow);
     613                 :    5652480 :         flowmap_init(&flow_cache->entries[i].key.mf.map);
     614                 :            :     }
     615                 :        690 : }
     616                 :            : 
     617                 :            : static void
     618                 :        117 : emc_cache_uninit(struct emc_cache *flow_cache)
     619                 :            : {
     620                 :            :     int i;
     621                 :            : 
     622         [ +  + ]:     958581 :     for (i = 0; i < ARRAY_SIZE(flow_cache->entries); i++) {
     623                 :     958464 :         emc_clear_entry(&flow_cache->entries[i]);
     624                 :            :     }
     625                 :        117 : }
     626                 :            : 
     627                 :            : /* Check and clear dead flow references slowly (one entry at each
     628                 :            :  * invocation).  */
     629                 :            : static void
     630                 :     218750 : emc_cache_slow_sweep(struct emc_cache *flow_cache)
     631                 :            : {
     632                 :     218750 :     struct emc_entry *entry = &flow_cache->entries[flow_cache->sweep_idx];
     633                 :            : 
     634         [ +  + ]:     218750 :     if (!emc_entry_alive(entry)) {
     635                 :     220144 :         emc_clear_entry(entry);
     636                 :            :     }
     637                 :     220145 :     flow_cache->sweep_idx = (flow_cache->sweep_idx + 1) & EM_FLOW_HASH_MASK;
     638                 :     220145 : }
     639                 :            : 
     640                 :            : /* Returns true if 'dpif' is a netdev or dummy dpif, false otherwise. */
     641                 :            : bool
     642                 :     693011 : dpif_is_netdev(const struct dpif *dpif)
     643                 :            : {
     644                 :     693011 :     return dpif->dpif_class->open == dpif_netdev_open;
     645                 :            : }
     646                 :            : 
     647                 :            : static struct dpif_netdev *
     648                 :     692397 : dpif_netdev_cast(const struct dpif *dpif)
     649                 :            : {
     650         [ -  + ]:     692397 :     ovs_assert(dpif_is_netdev(dpif));
     651                 :     692397 :     return CONTAINER_OF(dpif, struct dpif_netdev, dpif);
     652                 :            : }
     653                 :            : 
     654                 :            : static struct dp_netdev *
     655                 :     413907 : get_dp_netdev(const struct dpif *dpif)
     656                 :            : {
     657                 :     413907 :     return dpif_netdev_cast(dpif)->dp;
     658                 :            : }
     659                 :            : 
     660                 :            : enum pmd_info_type {
     661                 :            :     PMD_INFO_SHOW_STATS,  /* Show how cpu cycles are spent. */
     662                 :            :     PMD_INFO_CLEAR_STATS, /* Set the cycles count to 0. */
     663                 :            :     PMD_INFO_SHOW_RXQ     /* Show poll-lists of pmd threads. */
     664                 :            : };
     665                 :            : 
     666                 :            : static void
     667                 :          4 : pmd_info_show_stats(struct ds *reply,
     668                 :            :                     struct dp_netdev_pmd_thread *pmd,
     669                 :            :                     unsigned long long stats[DP_N_STATS],
     670                 :            :                     uint64_t cycles[PMD_N_CYCLES])
     671                 :            : {
     672                 :          4 :     unsigned long long total_packets = 0;
     673                 :          4 :     uint64_t total_cycles = 0;
     674                 :            :     int i;
     675                 :            : 
     676                 :            :     /* These loops subtracts reference values ('*_zero') from the counters.
     677                 :            :      * Since loads and stores are relaxed, it might be possible for a '*_zero'
     678                 :            :      * value to be more recent than the current value we're reading from the
     679                 :            :      * counter.  This is not a big problem, since these numbers are not
     680                 :            :      * supposed to be too accurate, but we should at least make sure that
     681                 :            :      * the result is not negative. */
     682         [ +  + ]:         24 :     for (i = 0; i < DP_N_STATS; i++) {
     683         [ +  + ]:         20 :         if (stats[i] > pmd->stats_zero[i]) {
     684                 :          2 :             stats[i] -= pmd->stats_zero[i];
     685                 :            :         } else {
     686                 :         18 :             stats[i] = 0;
     687                 :            :         }
     688                 :            : 
     689         [ +  + ]:         20 :         if (i != DP_STAT_LOST) {
     690                 :            :             /* Lost packets are already included in DP_STAT_MISS */
     691                 :         16 :             total_packets += stats[i];
     692                 :            :         }
     693                 :            :     }
     694                 :            : 
     695         [ +  + ]:         12 :     for (i = 0; i < PMD_N_CYCLES; i++) {
     696         [ -  + ]:          8 :         if (cycles[i] > pmd->cycles_zero[i]) {
     697                 :          0 :            cycles[i] -= pmd->cycles_zero[i];
     698                 :            :         } else {
     699                 :          8 :             cycles[i] = 0;
     700                 :            :         }
     701                 :            : 
     702                 :          8 :         total_cycles += cycles[i];
     703                 :            :     }
     704                 :            : 
     705         [ +  + ]:          4 :     ds_put_cstr(reply, (pmd->core_id == NON_PMD_CORE_ID)
     706                 :            :                         ? "main thread" : "pmd thread");
     707                 :            : 
     708         [ +  + ]:          4 :     if (pmd->numa_id != OVS_NUMA_UNSPEC) {
     709                 :          2 :         ds_put_format(reply, " numa_id %d", pmd->numa_id);
     710                 :            :     }
     711 [ +  - ][ +  + ]:          4 :     if (pmd->core_id != OVS_CORE_UNSPEC && pmd->core_id != NON_PMD_CORE_ID) {
     712                 :          2 :         ds_put_format(reply, " core_id %u", pmd->core_id);
     713                 :            :     }
     714                 :          4 :     ds_put_cstr(reply, ":\n");
     715                 :            : 
     716         [ -  + ]:          4 :     ds_put_format(reply,
     717                 :            :                   "\temc hits:%llu\n\tmegaflow hits:%llu\n"
     718                 :            :                   "\tavg. subtable lookups per hit:%.2f\n"
     719                 :            :                   "\tmiss:%llu\n\tlost:%llu\n",
     720                 :          4 :                   stats[DP_STAT_EXACT_HIT], stats[DP_STAT_MASKED_HIT],
     721                 :          4 :                   stats[DP_STAT_MASKED_HIT] > 0
     722                 :          0 :                   ? (1.0*stats[DP_STAT_LOOKUP_HIT])/stats[DP_STAT_MASKED_HIT]
     723                 :            :                   : 0,
     724                 :          8 :                   stats[DP_STAT_MISS], stats[DP_STAT_LOST]);
     725                 :            : 
     726         [ +  - ]:          4 :     if (total_cycles == 0) {
     727                 :          4 :         return;
     728                 :            :     }
     729                 :            : 
     730                 :          0 :     ds_put_format(reply,
     731                 :            :                   "\tpolling cycles:%"PRIu64" (%.02f%%)\n"
     732                 :            :                   "\tprocessing cycles:%"PRIu64" (%.02f%%)\n",
     733                 :            :                   cycles[PMD_CYCLES_POLLING],
     734                 :          0 :                   cycles[PMD_CYCLES_POLLING] / (double)total_cycles * 100,
     735                 :          0 :                   cycles[PMD_CYCLES_PROCESSING],
     736                 :          0 :                   cycles[PMD_CYCLES_PROCESSING] / (double)total_cycles * 100);
     737                 :            : 
     738         [ #  # ]:          0 :     if (total_packets == 0) {
     739                 :          0 :         return;
     740                 :            :     }
     741                 :            : 
     742                 :          0 :     ds_put_format(reply,
     743                 :            :                   "\tavg cycles per packet: %.02f (%"PRIu64"/%llu)\n",
     744                 :          0 :                   total_cycles / (double)total_packets,
     745                 :            :                   total_cycles, total_packets);
     746                 :            : 
     747                 :          0 :     ds_put_format(reply,
     748                 :            :                   "\tavg processing cycles per packet: "
     749                 :            :                   "%.02f (%"PRIu64"/%llu)\n",
     750                 :          0 :                   cycles[PMD_CYCLES_PROCESSING] / (double)total_packets,
     751                 :          0 :                   cycles[PMD_CYCLES_PROCESSING], total_packets);
     752                 :            : }
     753                 :            : 
     754                 :            : static void
     755                 :          0 : pmd_info_clear_stats(struct ds *reply OVS_UNUSED,
     756                 :            :                     struct dp_netdev_pmd_thread *pmd,
     757                 :            :                     unsigned long long stats[DP_N_STATS],
     758                 :            :                     uint64_t cycles[PMD_N_CYCLES])
     759                 :            : {
     760                 :            :     int i;
     761                 :            : 
     762                 :            :     /* We cannot write 'stats' and 'cycles' (because they're written by other
     763                 :            :      * threads) and we shouldn't change 'stats' (because they're used to count
     764                 :            :      * datapath stats, which must not be cleared here).  Instead, we save the
     765                 :            :      * current values and subtract them from the values to be displayed in the
     766                 :            :      * future */
     767         [ #  # ]:          0 :     for (i = 0; i < DP_N_STATS; i++) {
     768                 :          0 :         pmd->stats_zero[i] = stats[i];
     769                 :            :     }
     770         [ #  # ]:          0 :     for (i = 0; i < PMD_N_CYCLES; i++) {
     771                 :          0 :         pmd->cycles_zero[i] = cycles[i];
     772                 :            :     }
     773                 :          0 : }
     774                 :            : 
     775                 :            : static void
     776                 :         47 : pmd_info_show_rxq(struct ds *reply, struct dp_netdev_pmd_thread *pmd)
     777                 :            : {
     778         [ +  + ]:         47 :     if (pmd->core_id != NON_PMD_CORE_ID) {
     779                 :            :         struct rxq_poll *poll;
     780                 :         30 :         const char *prev_name = NULL;
     781                 :            : 
     782         [ +  + ]:         30 :         ds_put_format(reply,
     783                 :            :                       "pmd thread numa_id %d core_id %u:\n\tisolated : %s\n",
     784                 :         30 :                       pmd->numa_id, pmd->core_id, (pmd->isolated)
     785                 :            :                                                   ? "true" : "false");
     786                 :            : 
     787                 :         30 :         ovs_mutex_lock(&pmd->port_mutex);
     788         [ +  + ]:         97 :         LIST_FOR_EACH (poll, node, &pmd->poll_list) {
     789                 :         67 :             const char *name = netdev_get_name(poll->port->netdev);
     790                 :            : 
     791 [ +  + ][ +  + ]:         67 :             if (!prev_name || strcmp(name, prev_name)) {
     792         [ +  + ]:         28 :                 if (prev_name) {
     793                 :          3 :                     ds_put_cstr(reply, "\n");
     794                 :            :                 }
     795                 :         28 :                 ds_put_format(reply, "\tport: %s\tqueue-id:",
     796                 :         28 :                               netdev_get_name(poll->port->netdev));
     797                 :            :             }
     798                 :         67 :             ds_put_format(reply, " %d", netdev_rxq_get_queue_id(poll->rx));
     799                 :         67 :             prev_name = name;
     800                 :            :         }
     801                 :         30 :         ovs_mutex_unlock(&pmd->port_mutex);
     802                 :         30 :         ds_put_cstr(reply, "\n");
     803                 :            :     }
     804                 :         47 : }
     805                 :            : 
     806                 :            : static void
     807                 :         19 : dpif_netdev_pmd_info(struct unixctl_conn *conn, int argc, const char *argv[],
     808                 :            :                      void *aux)
     809                 :            : {
     810                 :         19 :     struct ds reply = DS_EMPTY_INITIALIZER;
     811                 :            :     struct dp_netdev_pmd_thread *pmd;
     812                 :         19 :     struct dp_netdev *dp = NULL;
     813                 :         19 :     enum pmd_info_type type = *(enum pmd_info_type *) aux;
     814                 :            : 
     815                 :         19 :     ovs_mutex_lock(&dp_netdev_mutex);
     816                 :            : 
     817         [ -  + ]:         19 :     if (argc == 2) {
     818                 :          0 :         dp = shash_find_data(&dp_netdevs, argv[1]);
     819         [ +  - ]:         19 :     } else if (shash_count(&dp_netdevs) == 1) {
     820                 :            :         /* There's only one datapath */
     821                 :         19 :         dp = shash_first(&dp_netdevs)->data;
     822                 :            :     }
     823                 :            : 
     824         [ -  + ]:         19 :     if (!dp) {
     825                 :          0 :         ovs_mutex_unlock(&dp_netdev_mutex);
     826                 :          0 :         unixctl_command_reply_error(conn,
     827                 :            :                                     "please specify an existing datapath");
     828                 :          0 :         return;
     829                 :            :     }
     830                 :            : 
     831 [ +  + ][ +  + ]:         70 :     CMAP_FOR_EACH (pmd, node, &dp->poll_threads) {
     832         [ +  + ]:         51 :         if (type == PMD_INFO_SHOW_RXQ) {
     833                 :         47 :             pmd_info_show_rxq(&reply, pmd);
     834                 :            :         } else {
     835                 :            :             unsigned long long stats[DP_N_STATS];
     836                 :            :             uint64_t cycles[PMD_N_CYCLES];
     837                 :            :             int i;
     838                 :            : 
     839                 :            :             /* Read current stats and cycle counters */
     840         [ +  + ]:         24 :             for (i = 0; i < ARRAY_SIZE(stats); i++) {
     841                 :         20 :                 atomic_read_relaxed(&pmd->stats.n[i], &stats[i]);
     842                 :            :             }
     843         [ +  + ]:         12 :             for (i = 0; i < ARRAY_SIZE(cycles); i++) {
     844                 :          8 :                 atomic_read_relaxed(&pmd->cycles.n[i], &cycles[i]);
     845                 :            :             }
     846                 :            : 
     847         [ -  + ]:          4 :             if (type == PMD_INFO_CLEAR_STATS) {
     848                 :          0 :                 pmd_info_clear_stats(&reply, pmd, stats, cycles);
     849         [ +  - ]:          4 :             } else if (type == PMD_INFO_SHOW_STATS) {
     850                 :          4 :                 pmd_info_show_stats(&reply, pmd, stats, cycles);
     851                 :            :             }
     852                 :            :         }
     853                 :            :     }
     854                 :            : 
     855                 :         19 :     ovs_mutex_unlock(&dp_netdev_mutex);
     856                 :            : 
     857                 :         19 :     unixctl_command_reply(conn, ds_cstr(&reply));
     858                 :         19 :     ds_destroy(&reply);
     859                 :            : }
     860                 :            : 
     861                 :            : static int
     862                 :       1310 : dpif_netdev_init(void)
     863                 :            : {
     864                 :            :     static enum pmd_info_type show_aux = PMD_INFO_SHOW_STATS,
     865                 :            :                               clear_aux = PMD_INFO_CLEAR_STATS,
     866                 :            :                               poll_aux = PMD_INFO_SHOW_RXQ;
     867                 :            : 
     868                 :       1310 :     unixctl_command_register("dpif-netdev/pmd-stats-show", "[dp]",
     869                 :            :                              0, 1, dpif_netdev_pmd_info,
     870                 :            :                              (void *)&show_aux);
     871                 :       1310 :     unixctl_command_register("dpif-netdev/pmd-stats-clear", "[dp]",
     872                 :            :                              0, 1, dpif_netdev_pmd_info,
     873                 :            :                              (void *)&clear_aux);
     874                 :       1310 :     unixctl_command_register("dpif-netdev/pmd-rxq-show", "[dp]",
     875                 :            :                              0, 1, dpif_netdev_pmd_info,
     876                 :            :                              (void *)&poll_aux);
     877                 :       1310 :     return 0;
     878                 :            : }
     879                 :            : 
     880                 :            : static int
     881                 :        676 : dpif_netdev_enumerate(struct sset *all_dps,
     882                 :            :                       const struct dpif_class *dpif_class)
     883                 :            : {
     884                 :            :     struct shash_node *node;
     885                 :            : 
     886                 :        676 :     ovs_mutex_lock(&dp_netdev_mutex);
     887 [ +  + ][ -  + ]:        742 :     SHASH_FOR_EACH(node, &dp_netdevs) {
     888                 :         66 :         struct dp_netdev *dp = node->data;
     889         [ +  + ]:         66 :         if (dpif_class != dp->class) {
     890                 :            :             /* 'dp_netdevs' contains both "netdev" and "dummy" dpifs.
     891                 :            :              * If the class doesn't match, skip this dpif. */
     892                 :         24 :              continue;
     893                 :            :         }
     894                 :         42 :         sset_add(all_dps, node->name);
     895                 :            :     }
     896                 :        676 :     ovs_mutex_unlock(&dp_netdev_mutex);
     897                 :            : 
     898                 :        676 :     return 0;
     899                 :            : }
     900                 :            : 
     901                 :            : static bool
     902                 :      29862 : dpif_netdev_class_is_dummy(const struct dpif_class *class)
     903                 :            : {
     904                 :      29862 :     return class != &dpif_netdev_class;
     905                 :            : }
     906                 :            : 
     907                 :            : static const char *
     908                 :      58462 : dpif_netdev_port_open_type(const struct dpif_class *class, const char *type)
     909                 :            : {
     910                 :      58462 :     return strcmp(type, "internal") ? type
     911         [ +  + ]:      88323 :                   : dpif_netdev_class_is_dummy(class) ? "dummy-internal"
     912         [ +  + ]:      29861 :                   : "tap";
     913                 :            : }
     914                 :            : 
     915                 :            : static struct dpif *
     916                 :        612 : create_dpif_netdev(struct dp_netdev *dp)
     917                 :            : {
     918                 :        612 :     uint16_t netflow_id = hash_string(dp->name, 0);
     919                 :            :     struct dpif_netdev *dpif;
     920                 :            : 
     921                 :        612 :     ovs_refcount_ref(&dp->ref_cnt);
     922                 :            : 
     923                 :        612 :     dpif = xmalloc(sizeof *dpif);
     924                 :        612 :     dpif_init(&dpif->dpif, dp->class, dp->name, netflow_id >> 8, netflow_id);
     925                 :        612 :     dpif->dp = dp;
     926                 :        612 :     dpif->last_port_seq = seq_read(dp->port_seq);
     927                 :            : 
     928                 :        612 :     return &dpif->dpif;
     929                 :            : }
     930                 :            : 
     931                 :            : /* Choose an unused, non-zero port number and return it on success.
     932                 :            :  * Return ODPP_NONE on failure. */
     933                 :            : static odp_port_t
     934                 :       1905 : choose_port(struct dp_netdev *dp, const char *name)
     935                 :            :     OVS_REQUIRES(dp->port_mutex)
     936                 :            : {
     937                 :            :     uint32_t port_no;
     938                 :            : 
     939         [ +  + ]:       1905 :     if (dp->class != &dpif_netdev_class) {
     940                 :            :         const char *p;
     941                 :       1785 :         int start_no = 0;
     942                 :            : 
     943                 :            :         /* If the port name begins with "br", start the number search at
     944                 :            :          * 100 to make writing tests easier. */
     945         [ +  + ]:       1785 :         if (!strncmp(name, "br", 2)) {
     946                 :        646 :             start_no = 100;
     947                 :            :         }
     948                 :            : 
     949                 :            :         /* If the port name contains a number, try to assign that port number.
     950                 :            :          * This can make writing unit tests easier because port numbers are
     951                 :            :          * predictable. */
     952         [ +  + ]:       6226 :         for (p = name; *p != '\0'; p++) {
     953         [ +  + ]:       6051 :             if (isdigit((unsigned char) *p)) {
     954                 :       1610 :                 port_no = start_no + strtol(p, NULL, 10);
     955 [ +  + ][ +  - ]:       1610 :                 if (port_no > 0 && port_no != odp_to_u32(ODPP_NONE)
     956         [ +  + ]:       1589 :                     && !dp_netdev_lookup_port(dp, u32_to_odp(port_no))) {
     957                 :       1469 :                     return u32_to_odp(port_no);
     958                 :            :                 }
     959                 :        141 :                 break;
     960                 :            :             }
     961                 :            :         }
     962                 :            :     }
     963                 :            : 
     964         [ +  - ]:        998 :     for (port_no = 1; port_no <= UINT16_MAX; port_no++) {
     965         [ +  + ]:        998 :         if (!dp_netdev_lookup_port(dp, u32_to_odp(port_no))) {
     966                 :        436 :             return u32_to_odp(port_no);
     967                 :            :         }
     968                 :            :     }
     969                 :            : 
     970                 :          0 :     return ODPP_NONE;
     971                 :            : }
     972                 :            : 
     973                 :            : static int
     974                 :        553 : create_dp_netdev(const char *name, const struct dpif_class *class,
     975                 :            :                  struct dp_netdev **dpp)
     976                 :            :     OVS_REQUIRES(dp_netdev_mutex)
     977                 :            : {
     978                 :            :     struct dp_netdev *dp;
     979                 :            :     int error;
     980                 :            : 
     981                 :        553 :     dp = xzalloc(sizeof *dp);
     982                 :        553 :     shash_add(&dp_netdevs, name, dp);
     983                 :            : 
     984                 :        553 :     *CONST_CAST(const struct dpif_class **, &dp->class) = class;
     985                 :        553 :     *CONST_CAST(const char **, &dp->name) = xstrdup(name);
     986                 :        553 :     ovs_refcount_init(&dp->ref_cnt);
     987                 :        553 :     atomic_flag_clear(&dp->destroyed);
     988                 :            : 
     989                 :        553 :     ovs_mutex_init(&dp->port_mutex);
     990                 :        553 :     hmap_init(&dp->ports);
     991                 :        553 :     dp->port_seq = seq_create();
     992                 :        553 :     fat_rwlock_init(&dp->upcall_rwlock);
     993                 :            : 
     994                 :        553 :     dp->reconfigure_seq = seq_create();
     995                 :        553 :     dp->last_reconfigure_seq = seq_read(dp->reconfigure_seq);
     996                 :            : 
     997                 :            :     /* Disable upcalls by default. */
     998                 :        553 :     dp_netdev_disable_upcall(dp);
     999                 :        553 :     dp->upcall_aux = NULL;
    1000                 :        553 :     dp->upcall_cb = NULL;
    1001                 :            : 
    1002                 :        553 :     conntrack_init(&dp->conntrack);
    1003                 :            : 
    1004                 :        553 :     cmap_init(&dp->poll_threads);
    1005                 :        553 :     ovs_mutex_init_recursive(&dp->non_pmd_mutex);
    1006                 :        553 :     ovsthread_key_create(&dp->per_pmd_key, NULL);
    1007                 :            : 
    1008                 :        553 :     ovs_mutex_lock(&dp->port_mutex);
    1009                 :        553 :     dp_netdev_set_nonpmd(dp);
    1010                 :            : 
    1011                 :        553 :     error = do_add_port(dp, name, dpif_netdev_port_open_type(dp->class,
    1012                 :            :                                                              "internal"),
    1013                 :            :                         ODPP_LOCAL);
    1014                 :        553 :     ovs_mutex_unlock(&dp->port_mutex);
    1015         [ -  + ]:        553 :     if (error) {
    1016                 :          0 :         dp_netdev_free(dp);
    1017                 :          0 :         return error;
    1018                 :            :     }
    1019                 :            : 
    1020                 :        553 :     dp->last_tnl_conf_seq = seq_read(tnl_conf_seq);
    1021                 :        553 :     *dpp = dp;
    1022                 :        553 :     return 0;
    1023                 :            : }
    1024                 :            : 
    1025                 :            : static void
    1026                 :         11 : dp_netdev_request_reconfigure(struct dp_netdev *dp)
    1027                 :            : {
    1028                 :         11 :     seq_change(dp->reconfigure_seq);
    1029                 :         11 : }
    1030                 :            : 
    1031                 :            : static bool
    1032                 :      99708 : dp_netdev_is_reconf_required(struct dp_netdev *dp)
    1033                 :            : {
    1034                 :      99708 :     return seq_read(dp->reconfigure_seq) != dp->last_reconfigure_seq;
    1035                 :            : }
    1036                 :            : 
    1037                 :            : static int
    1038                 :        615 : dpif_netdev_open(const struct dpif_class *class, const char *name,
    1039                 :            :                  bool create, struct dpif **dpifp)
    1040                 :            : {
    1041                 :            :     struct dp_netdev *dp;
    1042                 :            :     int error;
    1043                 :            : 
    1044                 :        615 :     ovs_mutex_lock(&dp_netdev_mutex);
    1045                 :        615 :     dp = shash_find_data(&dp_netdevs, name);
    1046         [ +  + ]:        615 :     if (!dp) {
    1047         [ +  + ]:        555 :         error = create ? create_dp_netdev(name, class, &dp) : ENODEV;
    1048                 :            :     } else {
    1049                 :         60 :         error = (dp->class != class ? EINVAL
    1050         [ +  - ]:        120 :                  : create ? EEXIST
    1051         [ +  + ]:         60 :                  : 0);
    1052                 :            :     }
    1053         [ +  + ]:        615 :     if (!error) {
    1054                 :        612 :         *dpifp = create_dpif_netdev(dp);
    1055                 :        612 :         dp->dpif = *dpifp;
    1056                 :            :     }
    1057                 :        615 :     ovs_mutex_unlock(&dp_netdev_mutex);
    1058                 :            : 
    1059                 :        615 :     return error;
    1060                 :            : }
    1061                 :            : 
    1062                 :            : static void
    1063                 :          2 : dp_netdev_destroy_upcall_lock(struct dp_netdev *dp)
    1064                 :            :     OVS_NO_THREAD_SAFETY_ANALYSIS
    1065                 :            : {
    1066                 :            :     /* Check that upcalls are disabled, i.e. that the rwlock is taken */
    1067         [ -  + ]:          2 :     ovs_assert(fat_rwlock_tryrdlock(&dp->upcall_rwlock));
    1068                 :            : 
    1069                 :            :     /* Before freeing a lock we should release it */
    1070                 :          2 :     fat_rwlock_unlock(&dp->upcall_rwlock);
    1071                 :          2 :     fat_rwlock_destroy(&dp->upcall_rwlock);
    1072                 :          2 : }
    1073                 :            : 
    1074                 :            : /* Requires dp_netdev_mutex so that we can't get a new reference to 'dp'
    1075                 :            :  * through the 'dp_netdevs' shash while freeing 'dp'. */
    1076                 :            : static void
    1077                 :          2 : dp_netdev_free(struct dp_netdev *dp)
    1078                 :            :     OVS_REQUIRES(dp_netdev_mutex)
    1079                 :            : {
    1080                 :            :     struct dp_netdev_port *port, *next;
    1081                 :            : 
    1082                 :          2 :     shash_find_and_delete(&dp_netdevs, dp->name);
    1083                 :            : 
    1084                 :          2 :     dp_netdev_destroy_all_pmds(dp);
    1085                 :          2 :     ovs_mutex_destroy(&dp->non_pmd_mutex);
    1086                 :          2 :     ovsthread_key_delete(dp->per_pmd_key);
    1087                 :            : 
    1088                 :          2 :     conntrack_destroy(&dp->conntrack);
    1089                 :            : 
    1090                 :          2 :     ovs_mutex_lock(&dp->port_mutex);
    1091 [ +  + ][ -  + ]:          4 :     HMAP_FOR_EACH_SAFE (port, next, node, &dp->ports) {
                 [ +  + ]
    1092                 :          2 :         do_del_port(dp, port);
    1093                 :            :     }
    1094                 :          2 :     ovs_mutex_unlock(&dp->port_mutex);
    1095                 :          2 :     cmap_destroy(&dp->poll_threads);
    1096                 :            : 
    1097                 :          2 :     seq_destroy(dp->reconfigure_seq);
    1098                 :            : 
    1099                 :          2 :     seq_destroy(dp->port_seq);
    1100                 :          2 :     hmap_destroy(&dp->ports);
    1101                 :          2 :     ovs_mutex_destroy(&dp->port_mutex);
    1102                 :            : 
    1103                 :            :     /* Upcalls must be disabled at this point */
    1104                 :          2 :     dp_netdev_destroy_upcall_lock(dp);
    1105                 :            : 
    1106                 :          2 :     free(dp->pmd_cmask);
    1107                 :          2 :     free(CONST_CAST(char *, dp->name));
    1108                 :          2 :     free(dp);
    1109                 :          2 : }
    1110                 :            : 
    1111                 :            : static void
    1112                 :        613 : dp_netdev_unref(struct dp_netdev *dp)
    1113                 :            : {
    1114         [ +  - ]:        613 :     if (dp) {
    1115                 :            :         /* Take dp_netdev_mutex so that, if dp->ref_cnt falls to zero, we can't
    1116                 :            :          * get a new reference to 'dp' through the 'dp_netdevs' shash. */
    1117                 :        613 :         ovs_mutex_lock(&dp_netdev_mutex);
    1118         [ +  + ]:        613 :         if (ovs_refcount_unref_relaxed(&dp->ref_cnt) == 1) {
    1119                 :          2 :             dp_netdev_free(dp);
    1120                 :            :         }
    1121                 :        613 :         ovs_mutex_unlock(&dp_netdev_mutex);
    1122                 :            :     }
    1123                 :        613 : }
    1124                 :            : 
    1125                 :            : static void
    1126                 :        612 : dpif_netdev_close(struct dpif *dpif)
    1127                 :            : {
    1128                 :        612 :     struct dp_netdev *dp = get_dp_netdev(dpif);
    1129                 :            : 
    1130                 :        612 :     dp_netdev_unref(dp);
    1131                 :        612 :     free(dpif);
    1132                 :        612 : }
    1133                 :            : 
    1134                 :            : static int
    1135                 :          2 : dpif_netdev_destroy(struct dpif *dpif)
    1136                 :            : {
    1137                 :          2 :     struct dp_netdev *dp = get_dp_netdev(dpif);
    1138                 :            : 
    1139         [ +  - ]:          2 :     if (!atomic_flag_test_and_set(&dp->destroyed)) {
    1140         [ -  + ]:          2 :         if (ovs_refcount_unref_relaxed(&dp->ref_cnt) == 1) {
    1141                 :            :             /* Can't happen: 'dpif' still owns a reference to 'dp'. */
    1142                 :          0 :             OVS_NOT_REACHED();
    1143                 :            :         }
    1144                 :            :     }
    1145                 :            : 
    1146                 :          2 :     return 0;
    1147                 :            : }
    1148                 :            : 
    1149                 :            : /* Add 'n' to the atomic variable 'var' non-atomically and using relaxed
    1150                 :            :  * load/store semantics.  While the increment is not atomic, the load and
    1151                 :            :  * store operations are, making it impossible to read inconsistent values.
    1152                 :            :  *
    1153                 :            :  * This is used to update thread local stats counters. */
    1154                 :            : static void
    1155                 :   26478856 : non_atomic_ullong_add(atomic_ullong *var, unsigned long long n)
    1156                 :            : {
    1157                 :            :     unsigned long long tmp;
    1158                 :            : 
    1159                 :   26478856 :     atomic_read_relaxed(var, &tmp);
    1160                 :   26478856 :     tmp += n;
    1161                 :   26478856 :     atomic_store_relaxed(var, tmp);
    1162                 :   26478856 : }
    1163                 :            : 
    1164                 :            : static int
    1165                 :      11274 : dpif_netdev_get_stats(const struct dpif *dpif, struct dpif_dp_stats *stats)
    1166                 :            : {
    1167                 :      11274 :     struct dp_netdev *dp = get_dp_netdev(dpif);
    1168                 :            :     struct dp_netdev_pmd_thread *pmd;
    1169                 :            : 
    1170                 :      11274 :     stats->n_flows = stats->n_hit = stats->n_missed = stats->n_lost = 0;
    1171 [ +  + ][ +  + ]:      22743 :     CMAP_FOR_EACH (pmd, node, &dp->poll_threads) {
    1172                 :            :         unsigned long long n;
    1173                 :      11469 :         stats->n_flows += cmap_count(&pmd->flow_table);
    1174                 :            : 
    1175                 :      11469 :         atomic_read_relaxed(&pmd->stats.n[DP_STAT_MASKED_HIT], &n);
    1176                 :      11469 :         stats->n_hit += n;
    1177                 :      11469 :         atomic_read_relaxed(&pmd->stats.n[DP_STAT_EXACT_HIT], &n);
    1178                 :      11469 :         stats->n_hit += n;
    1179                 :      11469 :         atomic_read_relaxed(&pmd->stats.n[DP_STAT_MISS], &n);
    1180                 :      11469 :         stats->n_missed += n;
    1181                 :      11469 :         atomic_read_relaxed(&pmd->stats.n[DP_STAT_LOST], &n);
    1182                 :      11469 :         stats->n_lost += n;
    1183                 :            :     }
    1184                 :      11274 :     stats->n_masks = UINT32_MAX;
    1185                 :      11274 :     stats->n_mask_hit = UINT64_MAX;
    1186                 :            : 
    1187                 :      11274 :     return 0;
    1188                 :            : }
    1189                 :            : 
    1190                 :            : static void
    1191                 :       3461 : dp_netdev_reload_pmd__(struct dp_netdev_pmd_thread *pmd)
    1192                 :            : {
    1193                 :            :     int old_seq;
    1194                 :            : 
    1195         [ +  + ]:       3461 :     if (pmd->core_id == NON_PMD_CORE_ID) {
    1196                 :       3360 :         ovs_mutex_lock(&pmd->dp->non_pmd_mutex);
    1197                 :       3360 :         ovs_mutex_lock(&pmd->port_mutex);
    1198                 :       3360 :         pmd_load_cached_ports(pmd);
    1199                 :       3360 :         ovs_mutex_unlock(&pmd->port_mutex);
    1200                 :       3360 :         ovs_mutex_unlock(&pmd->dp->non_pmd_mutex);
    1201                 :       3360 :         return;
    1202                 :            :     }
    1203                 :            : 
    1204                 :        101 :     ovs_mutex_lock(&pmd->cond_mutex);
    1205                 :        101 :     atomic_add_relaxed(&pmd->change_seq, 1, &old_seq);
    1206                 :        101 :     ovs_mutex_cond_wait(&pmd->cond, &pmd->cond_mutex);
    1207                 :        101 :     ovs_mutex_unlock(&pmd->cond_mutex);
    1208                 :            : }
    1209                 :            : 
    1210                 :            : static uint32_t
    1211                 :     101479 : hash_port_no(odp_port_t port_no)
    1212                 :            : {
    1213                 :     101479 :     return hash_int(odp_to_u32(port_no), 0);
    1214                 :            : }
    1215                 :            : 
    1216                 :            : static int
    1217                 :       2458 : port_create(const char *devname, const char *type,
    1218                 :            :             odp_port_t port_no, struct dp_netdev_port **portp)
    1219                 :            : {
    1220                 :            :     struct netdev_saved_flags *sf;
    1221                 :            :     struct dp_netdev_port *port;
    1222                 :            :     enum netdev_flags flags;
    1223                 :            :     struct netdev *netdev;
    1224                 :       2458 :     int n_open_rxqs = 0;
    1225                 :       2458 :     int n_cores = 0;
    1226                 :            :     int i, error;
    1227                 :       2458 :     bool dynamic_txqs = false;
    1228                 :            : 
    1229                 :       2458 :     *portp = NULL;
    1230                 :            : 
    1231                 :            :     /* Open and validate network device. */
    1232                 :       2458 :     error = netdev_open(devname, type, &netdev);
    1233         [ -  + ]:       2458 :     if (error) {
    1234                 :          0 :         return error;
    1235                 :            :     }
    1236                 :            :     /* XXX reject non-Ethernet devices */
    1237                 :            : 
    1238                 :       2458 :     netdev_get_flags(netdev, &flags);
    1239         [ -  + ]:       2458 :     if (flags & NETDEV_LOOPBACK) {
    1240         [ #  # ]:          0 :         VLOG_ERR("%s: cannot add a loopback device", devname);
    1241                 :          0 :         error = EINVAL;
    1242                 :          0 :         goto out;
    1243                 :            :     }
    1244                 :            : 
    1245         [ +  + ]:       2458 :     if (netdev_is_pmd(netdev)) {
    1246                 :         31 :         n_cores = ovs_numa_get_n_cores();
    1247                 :            : 
    1248         [ -  + ]:         31 :         if (n_cores == OVS_CORE_UNSPEC) {
    1249         [ #  # ]:          0 :             VLOG_ERR("%s, cannot get cpu core info", devname);
    1250                 :          0 :             error = ENOENT;
    1251                 :          0 :             goto out;
    1252                 :            :         }
    1253                 :            :         /* There can only be ovs_numa_get_n_cores() pmd threads,
    1254                 :            :          * so creates a txq for each, and one extra for the non
    1255                 :            :          * pmd threads. */
    1256                 :         31 :         error = netdev_set_tx_multiq(netdev, n_cores + 1);
    1257 [ +  - ][ -  + ]:         31 :         if (error && (error != EOPNOTSUPP)) {
    1258         [ #  # ]:          0 :             VLOG_ERR("%s, cannot set multiq", devname);
    1259                 :          0 :             goto out;
    1260                 :            :         }
    1261                 :            :     }
    1262                 :            : 
    1263         [ +  + ]:       2458 :     if (netdev_is_reconf_required(netdev)) {
    1264                 :          7 :         error = netdev_reconfigure(netdev);
    1265         [ -  + ]:          7 :         if (error) {
    1266                 :          0 :             goto out;
    1267                 :            :         }
    1268                 :            :     }
    1269                 :            : 
    1270         [ +  + ]:       2458 :     if (netdev_is_pmd(netdev)) {
    1271         [ +  - ]:         31 :         if (netdev_n_txq(netdev) < n_cores + 1) {
    1272                 :         31 :             dynamic_txqs = true;
    1273                 :            :         }
    1274                 :            :     }
    1275                 :            : 
    1276                 :       2458 :     port = xzalloc(sizeof *port);
    1277                 :       2458 :     port->port_no = port_no;
    1278                 :       2458 :     port->netdev = netdev;
    1279                 :       2458 :     port->n_rxq = netdev_n_rxq(netdev);
    1280                 :       2458 :     port->rxqs = xcalloc(port->n_rxq, sizeof *port->rxqs);
    1281                 :       2458 :     port->txq_used = xcalloc(netdev_n_txq(netdev), sizeof *port->txq_used);
    1282                 :       2458 :     port->type = xstrdup(type);
    1283                 :       2458 :     ovs_mutex_init(&port->txq_used_mutex);
    1284                 :       2458 :     port->dynamic_txqs = dynamic_txqs;
    1285                 :            : 
    1286         [ +  + ]:       4850 :     for (i = 0; i < port->n_rxq; i++) {
    1287                 :       2392 :         error = netdev_rxq_open(netdev, &port->rxqs[i].rxq, i);
    1288         [ -  + ]:       2392 :         if (error) {
    1289         [ #  # ]:          0 :             VLOG_ERR("%s: cannot receive packets on this network device (%s)",
    1290                 :            :                      devname, ovs_strerror(errno));
    1291                 :          0 :             goto out_rxq_close;
    1292                 :            :         }
    1293                 :       2392 :         port->rxqs[i].core_id = -1;
    1294                 :       2392 :         n_open_rxqs++;
    1295                 :            :     }
    1296                 :            : 
    1297                 :       2458 :     error = netdev_turn_flags_on(netdev, NETDEV_PROMISC, &sf);
    1298         [ -  + ]:       2458 :     if (error) {
    1299                 :          0 :         goto out_rxq_close;
    1300                 :            :     }
    1301                 :       2458 :     port->sf = sf;
    1302                 :            : 
    1303                 :       2458 :     *portp = port;
    1304                 :            : 
    1305                 :       2458 :     return 0;
    1306                 :            : 
    1307                 :            : out_rxq_close:
    1308         [ #  # ]:          0 :     for (i = 0; i < n_open_rxqs; i++) {
    1309                 :          0 :         netdev_rxq_close(port->rxqs[i].rxq);
    1310                 :            :     }
    1311                 :          0 :     ovs_mutex_destroy(&port->txq_used_mutex);
    1312                 :          0 :     free(port->type);
    1313                 :          0 :     free(port->txq_used);
    1314                 :          0 :     free(port->rxqs);
    1315                 :          0 :     free(port);
    1316                 :            : 
    1317                 :            : out:
    1318                 :          0 :     netdev_close(netdev);
    1319                 :       2458 :     return error;
    1320                 :            : }
    1321                 :            : 
    1322                 :            : static int
    1323                 :       2459 : do_add_port(struct dp_netdev *dp, const char *devname, const char *type,
    1324                 :            :             odp_port_t port_no)
    1325                 :            :     OVS_REQUIRES(dp->port_mutex)
    1326                 :            : {
    1327                 :            :     struct dp_netdev_port *port;
    1328                 :            :     int error;
    1329                 :            : 
    1330                 :            :     /* Reject devices already in 'dp'. */
    1331         [ +  + ]:       2459 :     if (!get_port_by_name(dp, devname, &port)) {
    1332                 :          1 :         return EEXIST;
    1333                 :            :     }
    1334                 :            : 
    1335                 :       2458 :     error = port_create(devname, type, port_no, &port);
    1336         [ -  + ]:       2458 :     if (error) {
    1337                 :          0 :         return error;
    1338                 :            :     }
    1339                 :            : 
    1340         [ +  + ]:       2458 :     if (netdev_is_pmd(port->netdev)) {
    1341                 :         31 :         int numa_id = netdev_get_numa_id(port->netdev);
    1342                 :            : 
    1343         [ -  + ]:         31 :         ovs_assert(ovs_numa_numa_id_is_valid(numa_id));
    1344                 :         31 :         dp_netdev_set_pmds_on_numa(dp, numa_id);
    1345                 :            :     }
    1346                 :            : 
    1347                 :       2458 :     dp_netdev_add_port_to_pmds(dp, port);
    1348                 :            : 
    1349                 :       2458 :     hmap_insert(&dp->ports, &port->node, hash_port_no(port_no));
    1350                 :       2458 :     seq_change(dp->port_seq);
    1351                 :            : 
    1352                 :       2459 :     return 0;
    1353                 :            : }
    1354                 :            : 
    1355                 :            : static int
    1356                 :       1906 : dpif_netdev_port_add(struct dpif *dpif, struct netdev *netdev,
    1357                 :            :                      odp_port_t *port_nop)
    1358                 :            : {
    1359                 :       1906 :     struct dp_netdev *dp = get_dp_netdev(dpif);
    1360                 :            :     char namebuf[NETDEV_VPORT_NAME_BUFSIZE];
    1361                 :            :     const char *dpif_port;
    1362                 :            :     odp_port_t port_no;
    1363                 :            :     int error;
    1364                 :            : 
    1365                 :       1906 :     ovs_mutex_lock(&dp->port_mutex);
    1366                 :       1906 :     dpif_port = netdev_vport_get_dpif_port(netdev, namebuf, sizeof namebuf);
    1367         [ +  + ]:       1906 :     if (*port_nop != ODPP_NONE) {
    1368                 :          1 :         port_no = *port_nop;
    1369         [ -  + ]:          1 :         error = dp_netdev_lookup_port(dp, *port_nop) ? EBUSY : 0;
    1370                 :            :     } else {
    1371                 :       1905 :         port_no = choose_port(dp, dpif_port);
    1372         [ -  + ]:       1905 :         error = port_no == ODPP_NONE ? EFBIG : 0;
    1373                 :            :     }
    1374         [ +  - ]:       1906 :     if (!error) {
    1375                 :       1906 :         *port_nop = port_no;
    1376                 :       1906 :         error = do_add_port(dp, dpif_port, netdev_get_type(netdev), port_no);
    1377                 :            :     }
    1378                 :       1906 :     ovs_mutex_unlock(&dp->port_mutex);
    1379                 :            : 
    1380                 :       1906 :     return error;
    1381                 :            : }
    1382                 :            : 
    1383                 :            : static int
    1384                 :        334 : dpif_netdev_port_del(struct dpif *dpif, odp_port_t port_no)
    1385                 :            : {
    1386                 :        334 :     struct dp_netdev *dp = get_dp_netdev(dpif);
    1387                 :            :     int error;
    1388                 :            : 
    1389                 :        334 :     ovs_mutex_lock(&dp->port_mutex);
    1390         [ +  + ]:        334 :     if (port_no == ODPP_LOCAL) {
    1391                 :          1 :         error = EINVAL;
    1392                 :            :     } else {
    1393                 :            :         struct dp_netdev_port *port;
    1394                 :            : 
    1395                 :        333 :         error = get_port_by_number(dp, port_no, &port);
    1396         [ +  - ]:        333 :         if (!error) {
    1397                 :        333 :             do_del_port(dp, port);
    1398                 :            :         }
    1399                 :            :     }
    1400                 :        334 :     ovs_mutex_unlock(&dp->port_mutex);
    1401                 :            : 
    1402                 :        334 :     return error;
    1403                 :            : }
    1404                 :            : 
    1405                 :            : static bool
    1406                 :      21695 : is_valid_port_number(odp_port_t port_no)
    1407                 :            : {
    1408                 :      21695 :     return port_no != ODPP_NONE;
    1409                 :            : }
    1410                 :            : 
    1411                 :            : static struct dp_netdev_port *
    1412                 :       9596 : dp_netdev_lookup_port(const struct dp_netdev *dp, odp_port_t port_no)
    1413                 :            :     OVS_REQUIRES(dp->port_mutex)
    1414                 :            : {
    1415                 :            :     struct dp_netdev_port *port;
    1416                 :            : 
    1417 [ +  + ][ -  + ]:       9596 :     HMAP_FOR_EACH_WITH_HASH (port, node, hash_port_no(port_no), &dp->ports) {
    1418         [ +  - ]:       7689 :         if (port->port_no == port_no) {
    1419                 :       7689 :             return port;
    1420                 :            :         }
    1421                 :            :     }
    1422                 :       1907 :     return NULL;
    1423                 :            : }
    1424                 :            : 
    1425                 :            : static int
    1426                 :       7007 : get_port_by_number(struct dp_netdev *dp,
    1427                 :            :                    odp_port_t port_no, struct dp_netdev_port **portp)
    1428                 :            :     OVS_REQUIRES(dp->port_mutex)
    1429                 :            : {
    1430         [ -  + ]:       7007 :     if (!is_valid_port_number(port_no)) {
    1431                 :          0 :         *portp = NULL;
    1432                 :          0 :         return EINVAL;
    1433                 :            :     } else {
    1434                 :       7007 :         *portp = dp_netdev_lookup_port(dp, port_no);
    1435         [ +  - ]:       7007 :         return *portp ? 0 : ENOENT;
    1436                 :            :     }
    1437                 :            : }
    1438                 :            : 
    1439                 :            : static void
    1440                 :        335 : port_destroy(struct dp_netdev_port *port)
    1441                 :            : {
    1442         [ -  + ]:        335 :     if (!port) {
    1443                 :          0 :         return;
    1444                 :            :     }
    1445                 :            : 
    1446                 :        335 :     netdev_close(port->netdev);
    1447                 :        335 :     netdev_restore_flags(port->sf);
    1448                 :            : 
    1449         [ +  + ]:        637 :     for (unsigned i = 0; i < port->n_rxq; i++) {
    1450                 :        302 :         netdev_rxq_close(port->rxqs[i].rxq);
    1451                 :            :     }
    1452                 :        335 :     ovs_mutex_destroy(&port->txq_used_mutex);
    1453                 :        335 :     free(port->rxq_affinity_list);
    1454                 :        335 :     free(port->txq_used);
    1455                 :        335 :     free(port->rxqs);
    1456                 :        335 :     free(port->type);
    1457                 :        335 :     free(port);
    1458                 :            : }
    1459                 :            : 
    1460                 :            : static int
    1461                 :      25486 : get_port_by_name(struct dp_netdev *dp,
    1462                 :            :                  const char *devname, struct dp_netdev_port **portp)
    1463                 :            :     OVS_REQUIRES(dp->port_mutex)
    1464                 :            : {
    1465                 :            :     struct dp_netdev_port *port;
    1466                 :            : 
    1467 [ +  + ][ -  + ]:      93384 :     HMAP_FOR_EACH (port, node, &dp->ports) {
    1468         [ +  + ]:      87203 :         if (!strcmp(netdev_get_name(port->netdev), devname)) {
    1469                 :      19305 :             *portp = port;
    1470                 :      19305 :             return 0;
    1471                 :            :         }
    1472                 :            :     }
    1473                 :       6181 :     return ENOENT;
    1474                 :            : }
    1475                 :            : 
    1476                 :            : static int
    1477                 :         54 : get_n_pmd_threads(struct dp_netdev *dp)
    1478                 :            : {
    1479                 :            :     /* There is one non pmd thread in dp->poll_threads */
    1480                 :         54 :     return cmap_count(&dp->poll_threads) - 1;
    1481                 :            : }
    1482                 :            : 
    1483                 :            : static int
    1484                 :         48 : get_n_pmd_threads_on_numa(struct dp_netdev *dp, int numa_id)
    1485                 :            : {
    1486                 :            :     struct dp_netdev_pmd_thread *pmd;
    1487                 :         48 :     int n_pmds = 0;
    1488                 :            : 
    1489 [ +  + ][ +  + ]:        111 :     CMAP_FOR_EACH (pmd, node, &dp->poll_threads) {
    1490         [ +  + ]:         63 :         if (pmd->numa_id == numa_id) {
    1491                 :         14 :             n_pmds++;
    1492                 :            :         }
    1493                 :            :     }
    1494                 :            : 
    1495                 :         48 :     return n_pmds;
    1496                 :            : }
    1497                 :            : 
    1498                 :            : /* Returns 'true' if there is a port with pmd netdev and the netdev
    1499                 :            :  * is on numa node 'numa_id'. */
    1500                 :            : static bool
    1501                 :          1 : has_pmd_port_for_numa(struct dp_netdev *dp, int numa_id)
    1502                 :            :     OVS_REQUIRES(dp->port_mutex)
    1503                 :            : {
    1504                 :            :     struct dp_netdev_port *port;
    1505                 :            : 
    1506 [ +  + ][ -  + ]:          3 :     HMAP_FOR_EACH (port, node, &dp->ports) {
    1507         [ -  + ]:          2 :         if (netdev_is_pmd(port->netdev)
    1508         [ #  # ]:          0 :             && netdev_get_numa_id(port->netdev) == numa_id) {
    1509                 :          0 :             return true;
    1510                 :            :         }
    1511                 :            :     }
    1512                 :            : 
    1513                 :          1 :     return false;
    1514                 :            : }
    1515                 :            : 
    1516                 :            : 
    1517                 :            : static void
    1518                 :        335 : do_del_port(struct dp_netdev *dp, struct dp_netdev_port *port)
    1519                 :            :     OVS_REQUIRES(dp->port_mutex)
    1520                 :            : {
    1521                 :        335 :     hmap_remove(&dp->ports, &port->node);
    1522                 :        335 :     seq_change(dp->port_seq);
    1523                 :            : 
    1524                 :        335 :     dp_netdev_del_port_from_all_pmds(dp, port);
    1525                 :            : 
    1526         [ +  + ]:        335 :     if (netdev_is_pmd(port->netdev)) {
    1527                 :          1 :         int numa_id = netdev_get_numa_id(port->netdev);
    1528                 :            : 
    1529                 :            :         /* PMD threads can not be on invalid numa node. */
    1530         [ -  + ]:          1 :         ovs_assert(ovs_numa_numa_id_is_valid(numa_id));
    1531                 :            :         /* If there is no netdev on the numa node, deletes the pmd threads
    1532                 :            :          * for that numa. */
    1533         [ +  - ]:          1 :         if (!has_pmd_port_for_numa(dp, numa_id)) {
    1534                 :          1 :             dp_netdev_del_pmds_on_numa(dp, numa_id);
    1535                 :            :         }
    1536                 :            :     }
    1537                 :            : 
    1538                 :        335 :     port_destroy(port);
    1539                 :        335 : }
    1540                 :            : 
    1541                 :            : static void
    1542                 :      19013 : answer_port_query(const struct dp_netdev_port *port,
    1543                 :            :                   struct dpif_port *dpif_port)
    1544                 :            : {
    1545                 :      19013 :     dpif_port->name = xstrdup(netdev_get_name(port->netdev));
    1546                 :      19013 :     dpif_port->type = xstrdup(port->type);
    1547                 :      19013 :     dpif_port->port_no = port->port_no;
    1548                 :      19013 : }
    1549                 :            : 
    1550                 :            : static int
    1551                 :          5 : dpif_netdev_port_query_by_number(const struct dpif *dpif, odp_port_t port_no,
    1552                 :            :                                  struct dpif_port *dpif_port)
    1553                 :            : {
    1554                 :          5 :     struct dp_netdev *dp = get_dp_netdev(dpif);
    1555                 :            :     struct dp_netdev_port *port;
    1556                 :            :     int error;
    1557                 :            : 
    1558                 :          5 :     ovs_mutex_lock(&dp->port_mutex);
    1559                 :          5 :     error = get_port_by_number(dp, port_no, &port);
    1560 [ +  - ][ +  - ]:          5 :     if (!error && dpif_port) {
    1561                 :          5 :         answer_port_query(port, dpif_port);
    1562                 :            :     }
    1563                 :          5 :     ovs_mutex_unlock(&dp->port_mutex);
    1564                 :            : 
    1565                 :          5 :     return error;
    1566                 :            : }
    1567                 :            : 
    1568                 :            : static int
    1569                 :      23026 : dpif_netdev_port_query_by_name(const struct dpif *dpif, const char *devname,
    1570                 :            :                                struct dpif_port *dpif_port)
    1571                 :            : {
    1572                 :      23026 :     struct dp_netdev *dp = get_dp_netdev(dpif);
    1573                 :            :     struct dp_netdev_port *port;
    1574                 :            :     int error;
    1575                 :            : 
    1576                 :      23026 :     ovs_mutex_lock(&dp->port_mutex);
    1577                 :      23026 :     error = get_port_by_name(dp, devname, &port);
    1578 [ +  + ][ +  + ]:      23026 :     if (!error && dpif_port) {
    1579                 :      19008 :         answer_port_query(port, dpif_port);
    1580                 :            :     }
    1581                 :      23026 :     ovs_mutex_unlock(&dp->port_mutex);
    1582                 :            : 
    1583                 :      23026 :     return error;
    1584                 :            : }
    1585                 :            : 
    1586                 :            : static void
    1587                 :       6805 : dp_netdev_flow_free(struct dp_netdev_flow *flow)
    1588                 :            : {
    1589                 :       6805 :     dp_netdev_actions_free(dp_netdev_flow_get_actions(flow));
    1590                 :       6805 :     free(flow);
    1591                 :       6805 : }
    1592                 :            : 
    1593                 :      12596 : static void dp_netdev_flow_unref(struct dp_netdev_flow *flow)
    1594                 :            : {
    1595         [ +  + ]:      12596 :     if (ovs_refcount_unref_relaxed(&flow->ref_cnt) == 1) {
    1596                 :       6805 :         ovsrcu_postpone(dp_netdev_flow_free, flow);
    1597                 :            :     }
    1598                 :      12596 : }
    1599                 :            : 
    1600                 :            : static uint32_t
    1601                 :      35955 : dp_netdev_flow_hash(const ovs_u128 *ufid)
    1602                 :            : {
    1603                 :      35955 :     return ufid->u32[0];
    1604                 :            : }
    1605                 :            : 
    1606                 :            : static inline struct dpcls *
    1607                 :      47632 : dp_netdev_pmd_lookup_dpcls(struct dp_netdev_pmd_thread *pmd,
    1608                 :            :                            odp_port_t in_port)
    1609                 :            : {
    1610                 :            :     struct dpcls *cls;
    1611                 :      47632 :     uint32_t hash = hash_port_no(in_port);
    1612         [ +  + ]:      47632 :     CMAP_FOR_EACH_WITH_HASH (cls, node, hash, &pmd->classifiers) {
    1613         [ +  - ]:      44710 :         if (cls->in_port == in_port) {
    1614                 :            :             /* Port classifier exists already */
    1615                 :      44710 :             return cls;
    1616                 :            :         }
    1617                 :            :     }
    1618                 :       2922 :     return NULL;
    1619                 :            : }
    1620                 :            : 
    1621                 :            : static inline struct dpcls *
    1622                 :      10331 : dp_netdev_pmd_find_dpcls(struct dp_netdev_pmd_thread *pmd,
    1623                 :            :                          odp_port_t in_port)
    1624                 :            :     OVS_REQUIRES(pmd->flow_mutex)
    1625                 :            : {
    1626                 :      10331 :     struct dpcls *cls = dp_netdev_pmd_lookup_dpcls(pmd, in_port);
    1627                 :      10331 :     uint32_t hash = hash_port_no(in_port);
    1628                 :            : 
    1629         [ +  + ]:      10331 :     if (!cls) {
    1630                 :            :         /* Create new classifier for in_port */
    1631                 :        996 :         cls = xmalloc(sizeof(*cls));
    1632                 :        996 :         dpcls_init(cls);
    1633                 :        996 :         cls->in_port = in_port;
    1634                 :        996 :         cmap_insert(&pmd->classifiers, &cls->node, hash);
    1635         [ +  + ]:        996 :         VLOG_DBG("Creating dpcls %p for in_port %d", cls, in_port);
    1636                 :            :     }
    1637                 :      10331 :     return cls;
    1638                 :            : }
    1639                 :            : 
    1640                 :            : static void
    1641                 :      10331 : dp_netdev_pmd_remove_flow(struct dp_netdev_pmd_thread *pmd,
    1642                 :            :                           struct dp_netdev_flow *flow)
    1643                 :            :     OVS_REQUIRES(pmd->flow_mutex)
    1644                 :            : {
    1645                 :      10331 :     struct cmap_node *node = CONST_CAST(struct cmap_node *, &flow->node);
    1646                 :            :     struct dpcls *cls;
    1647                 :      10331 :     odp_port_t in_port = flow->flow.in_port.odp_port;
    1648                 :            : 
    1649                 :      10331 :     cls = dp_netdev_pmd_lookup_dpcls(pmd, in_port);
    1650         [ -  + ]:      10331 :     ovs_assert(cls != NULL);
    1651                 :      10331 :     dpcls_remove(cls, &flow->cr);
    1652                 :      10331 :     cmap_remove(&pmd->flow_table, node, dp_netdev_flow_hash(&flow->ufid));
    1653                 :      10331 :     flow->dead = true;
    1654                 :            : 
    1655                 :      10331 :     dp_netdev_flow_unref(flow);
    1656                 :      10331 : }
    1657                 :            : 
    1658                 :            : static void
    1659                 :       1456 : dp_netdev_pmd_flow_flush(struct dp_netdev_pmd_thread *pmd)
    1660                 :            : {
    1661                 :            :     struct dp_netdev_flow *netdev_flow;
    1662                 :            : 
    1663                 :       1456 :     ovs_mutex_lock(&pmd->flow_mutex);
    1664 [ -  + ][ -  + ]:       1456 :     CMAP_FOR_EACH (netdev_flow, node, &pmd->flow_table) {
    1665                 :          0 :         dp_netdev_pmd_remove_flow(pmd, netdev_flow);
    1666                 :            :     }
    1667                 :       1456 :     ovs_mutex_unlock(&pmd->flow_mutex);
    1668                 :       1456 : }
    1669                 :            : 
    1670                 :            : static int
    1671                 :       1380 : dpif_netdev_flow_flush(struct dpif *dpif)
    1672                 :            : {
    1673                 :       1380 :     struct dp_netdev *dp = get_dp_netdev(dpif);
    1674                 :            :     struct dp_netdev_pmd_thread *pmd;
    1675                 :            : 
    1676 [ +  + ][ +  + ]:       2789 :     CMAP_FOR_EACH (pmd, node, &dp->poll_threads) {
    1677                 :       1409 :         dp_netdev_pmd_flow_flush(pmd);
    1678                 :            :     }
    1679                 :            : 
    1680                 :       1380 :     return 0;
    1681                 :            : }
    1682                 :            : 
    1683                 :            : struct dp_netdev_port_state {
    1684                 :            :     struct hmap_position position;
    1685                 :            :     char *name;
    1686                 :            : };
    1687                 :            : 
    1688                 :            : static int
    1689                 :       2235 : dpif_netdev_port_dump_start(const struct dpif *dpif OVS_UNUSED, void **statep)
    1690                 :            : {
    1691                 :       2235 :     *statep = xzalloc(sizeof(struct dp_netdev_port_state));
    1692                 :       2235 :     return 0;
    1693                 :            : }
    1694                 :            : 
    1695                 :            : static int
    1696                 :      10240 : dpif_netdev_port_dump_next(const struct dpif *dpif, void *state_,
    1697                 :            :                            struct dpif_port *dpif_port)
    1698                 :            : {
    1699                 :      10240 :     struct dp_netdev_port_state *state = state_;
    1700                 :      10240 :     struct dp_netdev *dp = get_dp_netdev(dpif);
    1701                 :            :     struct hmap_node *node;
    1702                 :            :     int retval;
    1703                 :            : 
    1704                 :      10240 :     ovs_mutex_lock(&dp->port_mutex);
    1705                 :      10240 :     node = hmap_at_position(&dp->ports, &state->position);
    1706         [ +  + ]:      10240 :     if (node) {
    1707                 :            :         struct dp_netdev_port *port;
    1708                 :            : 
    1709                 :       8005 :         port = CONTAINER_OF(node, struct dp_netdev_port, node);
    1710                 :            : 
    1711                 :       8005 :         free(state->name);
    1712                 :       8005 :         state->name = xstrdup(netdev_get_name(port->netdev));
    1713                 :       8005 :         dpif_port->name = state->name;
    1714                 :       8005 :         dpif_port->type = port->type;
    1715                 :       8005 :         dpif_port->port_no = port->port_no;
    1716                 :            : 
    1717                 :       8005 :         retval = 0;
    1718                 :            :     } else {
    1719                 :       2235 :         retval = EOF;
    1720                 :            :     }
    1721                 :      10240 :     ovs_mutex_unlock(&dp->port_mutex);
    1722                 :            : 
    1723                 :      10240 :     return retval;
    1724                 :            : }
    1725                 :            : 
    1726                 :            : static int
    1727                 :       2235 : dpif_netdev_port_dump_done(const struct dpif *dpif OVS_UNUSED, void *state_)
    1728                 :            : {
    1729                 :       2235 :     struct dp_netdev_port_state *state = state_;
    1730                 :       2235 :     free(state->name);
    1731                 :       2235 :     free(state);
    1732                 :       2235 :     return 0;
    1733                 :            : }
    1734                 :            : 
    1735                 :            : static int
    1736                 :     101030 : dpif_netdev_port_poll(const struct dpif *dpif_, char **devnamep OVS_UNUSED)
    1737                 :            : {
    1738                 :     101030 :     struct dpif_netdev *dpif = dpif_netdev_cast(dpif_);
    1739                 :            :     uint64_t new_port_seq;
    1740                 :            :     int error;
    1741                 :            : 
    1742                 :     101030 :     new_port_seq = seq_read(dpif->dp->port_seq);
    1743         [ +  + ]:     101030 :     if (dpif->last_port_seq != new_port_seq) {
    1744                 :       1322 :         dpif->last_port_seq = new_port_seq;
    1745                 :       1322 :         error = ENOBUFS;
    1746                 :            :     } else {
    1747                 :      99708 :         error = EAGAIN;
    1748                 :            :     }
    1749                 :            : 
    1750                 :     101030 :     return error;
    1751                 :            : }
    1752                 :            : 
    1753                 :            : static void
    1754                 :     147289 : dpif_netdev_port_poll_wait(const struct dpif *dpif_)
    1755                 :            : {
    1756                 :     147289 :     struct dpif_netdev *dpif = dpif_netdev_cast(dpif_);
    1757                 :            : 
    1758                 :     147289 :     seq_wait(dpif->dp->port_seq, dpif->last_port_seq);
    1759                 :     147289 : }
    1760                 :            : 
    1761                 :            : static struct dp_netdev_flow *
    1762                 :      20137 : dp_netdev_flow_cast(const struct dpcls_rule *cr)
    1763                 :            : {
    1764         [ +  + ]:      20137 :     return cr ? CONTAINER_OF(cr, struct dp_netdev_flow, cr) : NULL;
    1765                 :            : }
    1766                 :            : 
    1767                 :      10720 : static bool dp_netdev_flow_ref(struct dp_netdev_flow *flow)
    1768                 :            : {
    1769                 :      10720 :     return ovs_refcount_try_ref_rcu(&flow->ref_cnt);
    1770                 :            : }
    1771                 :            : 
    1772                 :            : /* netdev_flow_key utilities.
    1773                 :            :  *
    1774                 :            :  * netdev_flow_key is basically a miniflow.  We use these functions
    1775                 :            :  * (netdev_flow_key_clone, netdev_flow_key_equal, ...) instead of the miniflow
    1776                 :            :  * functions (miniflow_clone_inline, miniflow_equal, ...), because:
    1777                 :            :  *
    1778                 :            :  * - Since we are dealing exclusively with miniflows created by
    1779                 :            :  *   miniflow_extract(), if the map is different the miniflow is different.
    1780                 :            :  *   Therefore we can be faster by comparing the map and the miniflow in a
    1781                 :            :  *   single memcmp().
    1782                 :            :  * - These functions can be inlined by the compiler. */
    1783                 :            : 
    1784                 :            : /* Given the number of bits set in miniflow's maps, returns the size of the
    1785                 :            :  * 'netdev_flow_key.mf' */
    1786                 :            : static inline size_t
    1787                 :      26557 : netdev_flow_key_size(size_t flow_u64s)
    1788                 :            : {
    1789                 :      26557 :     return sizeof(struct miniflow) + MINIFLOW_VALUES_SIZE(flow_u64s);
    1790                 :            : }
    1791                 :            : 
    1792                 :            : static inline bool
    1793                 :      25759 : netdev_flow_key_equal(const struct netdev_flow_key *a,
    1794                 :            :                       const struct netdev_flow_key *b)
    1795                 :            : {
    1796                 :            :     /* 'b->len' may be not set yet. */
    1797 [ +  + ][ +  + ]:      25759 :     return a->hash == b->hash && !memcmp(&a->mf, &b->mf, a->len);
    1798                 :            : }
    1799                 :            : 
    1800                 :            : /* Used to compare 'netdev_flow_key' in the exact match cache to a miniflow.
    1801                 :            :  * The maps are compared bitwise, so both 'key->mf' and 'mf' must have been
    1802                 :            :  * generated by miniflow_extract. */
    1803                 :            : static inline bool
    1804                 :       9185 : netdev_flow_key_equal_mf(const struct netdev_flow_key *key,
    1805                 :            :                          const struct miniflow *mf)
    1806                 :            : {
    1807                 :       9185 :     return !memcmp(&key->mf, mf, key->len);
    1808                 :            : }
    1809                 :            : 
    1810                 :            : static inline void
    1811                 :      16793 : netdev_flow_key_clone(struct netdev_flow_key *dst,
    1812                 :            :                       const struct netdev_flow_key *src)
    1813                 :            : {
    1814                 :      16793 :     memcpy(dst, src,
    1815                 :      16793 :            offsetof(struct netdev_flow_key, mf) + src->len);
    1816                 :      16793 : }
    1817                 :            : 
    1818                 :            : /* Slow. */
    1819                 :            : static void
    1820                 :       5321 : netdev_flow_key_from_flow(struct netdev_flow_key *dst,
    1821                 :            :                           const struct flow *src)
    1822                 :            : {
    1823                 :            :     struct dp_packet packet;
    1824                 :            :     uint64_t buf_stub[512 / 8];
    1825                 :            : 
    1826                 :       5321 :     dp_packet_use_stub(&packet, buf_stub, sizeof buf_stub);
    1827                 :       5321 :     pkt_metadata_from_flow(&packet.md, src);
    1828                 :       5321 :     flow_compose(&packet, src);
    1829                 :       5321 :     miniflow_extract(&packet, &dst->mf);
    1830                 :       5321 :     dp_packet_uninit(&packet);
    1831                 :            : 
    1832                 :       5321 :     dst->len = netdev_flow_key_size(miniflow_n_values(&dst->mf));
    1833                 :       5321 :     dst->hash = 0; /* Not computed yet. */
    1834                 :       5321 : }
    1835                 :            : 
    1836                 :            : /* Initialize a netdev_flow_key 'mask' from 'match'. */
    1837                 :            : static inline void
    1838                 :      10331 : netdev_flow_mask_init(struct netdev_flow_key *mask,
    1839                 :            :                       const struct match *match)
    1840                 :            : {
    1841                 :      10331 :     uint64_t *dst = miniflow_values(&mask->mf);
    1842                 :            :     struct flowmap fmap;
    1843                 :      10331 :     uint32_t hash = 0;
    1844                 :            :     size_t idx;
    1845                 :            : 
    1846                 :            :     /* Only check masks that make sense for the flow. */
    1847                 :      10331 :     flow_wc_map(&match->flow, &fmap);
    1848                 :      10331 :     flowmap_init(&mask->mf.map);
    1849                 :            : 
    1850         [ +  + ]:     123834 :     FLOWMAP_FOR_EACH_INDEX(idx, fmap) {
    1851                 :     113503 :         uint64_t mask_u64 = flow_u64_value(&match->wc.masks, idx);
    1852                 :            : 
    1853         [ +  + ]:     113503 :         if (mask_u64) {
    1854                 :      80885 :             flowmap_set(&mask->mf.map, idx, 1);
    1855                 :      80885 :             *dst++ = mask_u64;
    1856                 :      80885 :             hash = hash_add64(hash, mask_u64);
    1857                 :            :         }
    1858                 :            :     }
    1859                 :            : 
    1860                 :            :     map_t map;
    1861                 :            : 
    1862         [ +  + ]:      30993 :     FLOWMAP_FOR_EACH_MAP (map, mask->mf.map) {
    1863                 :      20662 :         hash = hash_add64(hash, map);
    1864                 :            :     }
    1865                 :            : 
    1866                 :      10331 :     size_t n = dst - miniflow_get_values(&mask->mf);
    1867                 :            : 
    1868                 :      10331 :     mask->hash = hash_finish(hash, n * 8);
    1869                 :      10331 :     mask->len = netdev_flow_key_size(n);
    1870                 :      10331 : }
    1871                 :            : 
    1872                 :            : /* Initializes 'dst' as a copy of 'flow' masked with 'mask'. */
    1873                 :            : static inline void
    1874                 :      10331 : netdev_flow_key_init_masked(struct netdev_flow_key *dst,
    1875                 :            :                             const struct flow *flow,
    1876                 :            :                             const struct netdev_flow_key *mask)
    1877                 :            : {
    1878                 :      10331 :     uint64_t *dst_u64 = miniflow_values(&dst->mf);
    1879                 :      10331 :     const uint64_t *mask_u64 = miniflow_get_values(&mask->mf);
    1880                 :      10331 :     uint32_t hash = 0;
    1881                 :            :     uint64_t value;
    1882                 :            : 
    1883                 :      10331 :     dst->len = mask->len;
    1884                 :      10331 :     dst->mf = mask->mf;   /* Copy maps. */
    1885                 :            : 
    1886         [ +  + ]:      91216 :     FLOW_FOR_EACH_IN_MAPS(value, flow, mask->mf.map) {
    1887                 :      80885 :         *dst_u64 = value & *mask_u64++;
    1888                 :      80885 :         hash = hash_add64(hash, *dst_u64++);
    1889                 :            :     }
    1890                 :      10331 :     dst->hash = hash_finish(hash,
    1891                 :      10331 :                             (dst_u64 - miniflow_get_values(&dst->mf)) * 8);
    1892                 :      10331 : }
    1893                 :            : 
    1894                 :            : /* Iterate through netdev_flow_key TNL u64 values specified by 'FLOWMAP'. */
    1895                 :            : #define NETDEV_FLOW_KEY_FOR_EACH_IN_FLOWMAP(VALUE, KEY, FLOWMAP)   \
    1896                 :            :     MINIFLOW_FOR_EACH_IN_FLOWMAP(VALUE, &(KEY)->mf, FLOWMAP)
    1897                 :            : 
    1898                 :            : /* Returns a hash value for the bits of 'key' where there are 1-bits in
    1899                 :            :  * 'mask'. */
    1900                 :            : static inline uint32_t
    1901                 :      38063 : netdev_flow_key_hash_in_mask(const struct netdev_flow_key *key,
    1902                 :            :                              const struct netdev_flow_key *mask)
    1903                 :            : {
    1904                 :      38063 :     const uint64_t *p = miniflow_get_values(&mask->mf);
    1905                 :      38063 :     uint32_t hash = 0;
    1906                 :            :     uint64_t value;
    1907                 :            : 
    1908         [ +  + ]:     291783 :     NETDEV_FLOW_KEY_FOR_EACH_IN_FLOWMAP(value, key, mask->mf.map) {
    1909                 :     253720 :         hash = hash_add64(hash, value & *p++);
    1910                 :            :     }
    1911                 :            : 
    1912                 :      38063 :     return hash_finish(hash, (p - miniflow_get_values(&mask->mf)) * 8);
    1913                 :            : }
    1914                 :            : 
    1915                 :            : static inline bool
    1916                 :     243461 : emc_entry_alive(struct emc_entry *ce)
    1917                 :            : {
    1918    [ +  + ][ + ]:     243461 :     return ce->flow && !ce->flow->dead;
    1919                 :            : }
    1920                 :            : 
    1921                 :            : static void
    1922                 :    1178358 : emc_clear_entry(struct emc_entry *ce)
    1923                 :            : {
    1924         [ +  + ]:    1178358 :     if (ce->flow) {
    1925                 :          6 :         dp_netdev_flow_unref(ce->flow);
    1926                 :          6 :         ce->flow = NULL;
    1927                 :            :     }
    1928                 :    1178358 : }
    1929                 :            : 
    1930                 :            : static inline void
    1931                 :      10905 : emc_change_entry(struct emc_entry *ce, struct dp_netdev_flow *flow,
    1932                 :            :                  const struct netdev_flow_key *key)
    1933                 :            : {
    1934         [ +  + ]:      10905 :     if (ce->flow != flow) {
    1935         [ +  + ]:      10720 :         if (ce->flow) {
    1936                 :       2259 :             dp_netdev_flow_unref(ce->flow);
    1937                 :            :         }
    1938                 :            : 
    1939         [ +  - ]:      10720 :         if (dp_netdev_flow_ref(flow)) {
    1940                 :      10720 :             ce->flow = flow;
    1941                 :            :         } else {
    1942                 :          0 :             ce->flow = NULL;
    1943                 :            :         }
    1944                 :            :     }
    1945         [ +  + ]:      10905 :     if (key) {
    1946                 :      10634 :         netdev_flow_key_clone(&ce->key, key);
    1947                 :            :     }
    1948                 :      10905 : }
    1949                 :            : 
    1950                 :            : static inline void
    1951                 :      10905 : emc_insert(struct emc_cache *cache, const struct netdev_flow_key *key,
    1952                 :            :            struct dp_netdev_flow *flow)
    1953                 :            : {
    1954                 :      10905 :     struct emc_entry *to_be_replaced = NULL;
    1955                 :            :     struct emc_entry *current_entry;
    1956                 :            : 
    1957         [ +  + ]:      32221 :     EMC_FOR_EACH_POS_WITH_HASH(cache, current_entry, key->hash) {
    1958         [ +  + ]:      21587 :         if (netdev_flow_key_equal(&current_entry->key, key)) {
    1959                 :            :             /* We found the entry with the 'mf' miniflow */
    1960                 :        271 :             emc_change_entry(current_entry, flow, NULL);
    1961                 :        271 :             return;
    1962                 :            :         }
    1963                 :            : 
    1964                 :            :         /* Replacement policy: put the flow in an empty (not alive) entry, or
    1965                 :            :          * in the first entry where it can be */
    1966         [ +  + ]:      21316 :         if (!to_be_replaced
    1967         [ +  + ]:      10634 :             || (emc_entry_alive(to_be_replaced)
    1968         [ +  + ]:       3059 :                 && !emc_entry_alive(current_entry))
    1969         [ +  + ]:       9513 :             || current_entry->key.hash < to_be_replaced->key.hash) {
    1970                 :      12171 :             to_be_replaced = current_entry;
    1971                 :            :         }
    1972                 :            :     }
    1973                 :            :     /* We didn't find the miniflow in the cache.
    1974                 :            :      * The 'to_be_replaced' entry is where the new flow will be stored */
    1975                 :            : 
    1976                 :      10634 :     emc_change_entry(to_be_replaced, flow, key);
    1977                 :            : }
    1978                 :            : 
    1979                 :            : static inline struct dp_netdev_flow *
    1980                 :      14617 : emc_lookup(struct emc_cache *cache, const struct netdev_flow_key *key)
    1981                 :            : {
    1982                 :            :     struct emc_entry *current_entry;
    1983                 :            : 
    1984         [ +  + ]:      37181 :     EMC_FOR_EACH_POS_WITH_HASH(cache, current_entry, key->hash) {
    1985         [ +  + ]:      26276 :         if (current_entry->key.hash == key->hash
    1986         [ +  + ]:       9623 :             && emc_entry_alive(current_entry)
    1987         [ +  + ]:       9185 :             && netdev_flow_key_equal_mf(&current_entry->key, &key->mf)) {
    1988                 :            : 
    1989                 :            :             /* We found the entry with the 'key->mf' miniflow */
    1990                 :       3712 :             return current_entry->flow;
    1991                 :            :         }
    1992                 :            :     }
    1993                 :            : 
    1994                 :      10905 :     return NULL;
    1995                 :            : }
    1996                 :            : 
    1997                 :            : static struct dp_netdev_flow *
    1998                 :      16065 : dp_netdev_pmd_lookup_flow(struct dp_netdev_pmd_thread *pmd,
    1999                 :            :                           const struct netdev_flow_key *key,
    2000                 :            :                           int *lookup_num_p)
    2001                 :            : {
    2002                 :            :     struct dpcls *cls;
    2003                 :            :     struct dpcls_rule *rule;
    2004         [ +  - ]:      16065 :     odp_port_t in_port = u32_to_odp(MINIFLOW_GET_U32(&key->mf, in_port));
    2005                 :      16065 :     struct dp_netdev_flow *netdev_flow = NULL;
    2006                 :            : 
    2007                 :      16065 :     cls = dp_netdev_pmd_lookup_dpcls(pmd, in_port);
    2008         [ +  + ]:      16065 :     if (OVS_LIKELY(cls)) {
    2009                 :      14604 :         dpcls_lookup(cls, key, &rule, 1, lookup_num_p);
    2010                 :      14604 :         netdev_flow = dp_netdev_flow_cast(rule);
    2011                 :            :     }
    2012                 :      16065 :     return netdev_flow;
    2013                 :            : }
    2014                 :            : 
    2015                 :            : static struct dp_netdev_flow *
    2016                 :      15293 : dp_netdev_pmd_find_flow(const struct dp_netdev_pmd_thread *pmd,
    2017                 :            :                         const ovs_u128 *ufidp, const struct nlattr *key,
    2018                 :            :                         size_t key_len)
    2019                 :            : {
    2020                 :            :     struct dp_netdev_flow *netdev_flow;
    2021                 :            :     struct flow flow;
    2022                 :            :     ovs_u128 ufid;
    2023                 :            : 
    2024                 :            :     /* If a UFID is not provided, determine one based on the key. */
    2025 [ +  + ][ +  - ]:      15293 :     if (!ufidp && key && key_len
                 [ +  - ]
    2026         [ +  - ]:       8816 :         && !dpif_netdev_flow_from_nlattrs(key, key_len, &flow)) {
    2027                 :       8816 :         dpif_flow_hash(pmd->dp->dpif, &flow, sizeof flow, &ufid);
    2028                 :       8816 :         ufidp = &ufid;
    2029                 :            :     }
    2030                 :            : 
    2031         [ +  - ]:      15293 :     if (ufidp) {
    2032         [ +  + ]:      15293 :         CMAP_FOR_EACH_WITH_HASH (netdev_flow, node, dp_netdev_flow_hash(ufidp),
    2033                 :            :                                  &pmd->flow_table) {
    2034         [ +  - ]:      15292 :             if (ovs_u128_equals(netdev_flow->ufid, *ufidp)) {
    2035                 :      15292 :                 return netdev_flow;
    2036                 :            :             }
    2037                 :            :         }
    2038                 :            :     }
    2039                 :            : 
    2040                 :      15293 :     return NULL;
    2041                 :            : }
    2042                 :            : 
    2043                 :            : static void
    2044                 :     178065 : get_dpif_flow_stats(const struct dp_netdev_flow *netdev_flow_,
    2045                 :            :                     struct dpif_flow_stats *stats)
    2046                 :            : {
    2047                 :            :     struct dp_netdev_flow *netdev_flow;
    2048                 :            :     unsigned long long n;
    2049                 :            :     long long used;
    2050                 :            :     uint16_t flags;
    2051                 :            : 
    2052                 :     178065 :     netdev_flow = CONST_CAST(struct dp_netdev_flow *, netdev_flow_);
    2053                 :            : 
    2054                 :     178065 :     atomic_read_relaxed(&netdev_flow->stats.packet_count, &n);
    2055                 :     178065 :     stats->n_packets = n;
    2056                 :     178065 :     atomic_read_relaxed(&netdev_flow->stats.byte_count, &n);
    2057                 :     178065 :     stats->n_bytes = n;
    2058                 :     178065 :     atomic_read_relaxed(&netdev_flow->stats.used, &used);
    2059                 :     178065 :     stats->used = used;
    2060                 :     178065 :     atomic_read_relaxed(&netdev_flow->stats.tcp_flags, &flags);
    2061                 :     178065 :     stats->tcp_flags = flags;
    2062                 :     178065 : }
    2063                 :            : 
    2064                 :            : /* Converts to the dpif_flow format, using 'key_buf' and 'mask_buf' for
    2065                 :            :  * storing the netlink-formatted key/mask. 'key_buf' may be the same as
    2066                 :            :  * 'mask_buf'. Actions will be returned without copying, by relying on RCU to
    2067                 :            :  * protect them. */
    2068                 :            : static void
    2069                 :     172693 : dp_netdev_flow_to_dpif_flow(const struct dp_netdev_flow *netdev_flow,
    2070                 :            :                             struct ofpbuf *key_buf, struct ofpbuf *mask_buf,
    2071                 :            :                             struct dpif_flow *flow, bool terse)
    2072                 :            : {
    2073         [ +  + ]:     172693 :     if (terse) {
    2074                 :     165685 :         memset(flow, 0, sizeof *flow);
    2075                 :            :     } else {
    2076                 :            :         struct flow_wildcards wc;
    2077                 :            :         struct dp_netdev_actions *actions;
    2078                 :            :         size_t offset;
    2079                 :      14016 :         struct odp_flow_key_parms odp_parms = {
    2080                 :       7008 :             .flow = &netdev_flow->flow,
    2081                 :            :             .mask = &wc.masks,
    2082                 :            :             .support = dp_netdev_support,
    2083                 :            :         };
    2084                 :            : 
    2085                 :       7008 :         miniflow_expand(&netdev_flow->cr.mask->mf, &wc.masks);
    2086                 :            : 
    2087                 :            :         /* Key */
    2088                 :       7008 :         offset = key_buf->size;
    2089                 :       7008 :         flow->key = ofpbuf_tail(key_buf);
    2090                 :       7008 :         odp_flow_key_from_flow(&odp_parms, key_buf);
    2091                 :       7008 :         flow->key_len = key_buf->size - offset;
    2092                 :            : 
    2093                 :            :         /* Mask */
    2094                 :       7008 :         offset = mask_buf->size;
    2095                 :       7008 :         flow->mask = ofpbuf_tail(mask_buf);
    2096                 :       7008 :         odp_parms.key_buf = key_buf;
    2097                 :       7008 :         odp_flow_key_from_mask(&odp_parms, mask_buf);
    2098                 :       7008 :         flow->mask_len = mask_buf->size - offset;
    2099                 :            : 
    2100                 :            :         /* Actions */
    2101                 :       7008 :         actions = dp_netdev_flow_get_actions(netdev_flow);
    2102                 :       7008 :         flow->actions = actions->actions;
    2103                 :       7008 :         flow->actions_len = actions->size;
    2104                 :            :     }
    2105                 :            : 
    2106                 :     172693 :     flow->ufid = netdev_flow->ufid;
    2107                 :     172693 :     flow->ufid_present = true;
    2108                 :     172693 :     flow->pmd_id = netdev_flow->pmd_id;
    2109                 :     172693 :     get_dpif_flow_stats(netdev_flow, &flow->stats);
    2110                 :     172693 : }
    2111                 :            : 
    2112                 :            : static int
    2113                 :       5321 : dpif_netdev_mask_from_nlattrs(const struct nlattr *key, uint32_t key_len,
    2114                 :            :                               const struct nlattr *mask_key,
    2115                 :            :                               uint32_t mask_key_len, const struct flow *flow,
    2116                 :            :                               struct flow_wildcards *wc)
    2117                 :            : {
    2118                 :            :     enum odp_key_fitness fitness;
    2119                 :            : 
    2120                 :       5321 :     fitness = odp_flow_key_to_mask_udpif(mask_key, mask_key_len, key,
    2121                 :            :                                          key_len, wc, flow);
    2122         [ -  + ]:       5321 :     if (fitness) {
    2123                 :            :         /* This should not happen: it indicates that
    2124                 :            :          * odp_flow_key_from_mask() and odp_flow_key_to_mask()
    2125                 :            :          * disagree on the acceptable form of a mask.  Log the problem
    2126                 :            :          * as an error, with enough details to enable debugging. */
    2127                 :            :         static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
    2128                 :            : 
    2129         [ #  # ]:          0 :         if (!VLOG_DROP_ERR(&rl)) {
    2130                 :            :             struct ds s;
    2131                 :            : 
    2132                 :          0 :             ds_init(&s);
    2133                 :          0 :             odp_flow_format(key, key_len, mask_key, mask_key_len, NULL, &s,
    2134                 :            :                             true);
    2135         [ #  # ]:          0 :             VLOG_ERR("internal error parsing flow mask %s (%s)",
    2136                 :            :                      ds_cstr(&s), odp_key_fitness_to_string(fitness));
    2137                 :          0 :             ds_destroy(&s);
    2138                 :            :         }
    2139                 :            : 
    2140                 :          0 :         return EINVAL;
    2141                 :            :     }
    2142                 :            : 
    2143                 :       5321 :     return 0;
    2144                 :            : }
    2145                 :            : 
    2146                 :            : static int
    2147                 :      14688 : dpif_netdev_flow_from_nlattrs(const struct nlattr *key, uint32_t key_len,
    2148                 :            :                               struct flow *flow)
    2149                 :            : {
    2150                 :            :     odp_port_t in_port;
    2151                 :            : 
    2152         [ -  + ]:      14688 :     if (odp_flow_key_to_flow_udpif(key, key_len, flow)) {
    2153                 :            :         /* This should not happen: it indicates that odp_flow_key_from_flow()
    2154                 :            :          * and odp_flow_key_to_flow() disagree on the acceptable form of a
    2155                 :            :          * flow.  Log the problem as an error, with enough details to enable
    2156                 :            :          * debugging. */
    2157                 :            :         static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
    2158                 :            : 
    2159         [ #  # ]:          0 :         if (!VLOG_DROP_ERR(&rl)) {
    2160                 :            :             struct ds s;
    2161                 :            : 
    2162                 :          0 :             ds_init(&s);
    2163                 :          0 :             odp_flow_format(key, key_len, NULL, 0, NULL, &s, true);
    2164         [ #  # ]:          0 :             VLOG_ERR("internal error parsing flow key %s", ds_cstr(&s));
    2165                 :          0 :             ds_destroy(&s);
    2166                 :            :         }
    2167                 :            : 
    2168                 :          0 :         return EINVAL;
    2169                 :            :     }
    2170                 :            : 
    2171                 :      14688 :     in_port = flow->in_port.odp_port;
    2172 [ -  + ][ #  # ]:      14688 :     if (!is_valid_port_number(in_port) && in_port != ODPP_NONE) {
    2173                 :          0 :         return EINVAL;
    2174                 :            :     }
    2175                 :            : 
    2176         [ +  + ]:      14688 :     if (flow->ct_state & DP_NETDEV_CS_UNSUPPORTED_MASK) {
    2177                 :        551 :         return EINVAL;
    2178                 :            :     }
    2179                 :            : 
    2180                 :      14137 :     return 0;
    2181                 :            : }
    2182                 :            : 
    2183                 :            : static int
    2184                 :       4961 : dpif_netdev_flow_get(const struct dpif *dpif, const struct dpif_flow_get *get)
    2185                 :            : {
    2186                 :       4961 :     struct dp_netdev *dp = get_dp_netdev(dpif);
    2187                 :            :     struct dp_netdev_flow *netdev_flow;
    2188                 :            :     struct dp_netdev_pmd_thread *pmd;
    2189                 :       4961 :     struct hmapx to_find = HMAPX_INITIALIZER(&to_find);
    2190                 :            :     struct hmapx_node *node;
    2191                 :       4961 :     int error = EINVAL;
    2192                 :            : 
    2193         [ +  - ]:       4961 :     if (get->pmd_id == PMD_ID_NULL) {
    2194 [ +  + ][ +  + ]:       9923 :         CMAP_FOR_EACH (pmd, node, &dp->poll_threads) {
    2195 [ +  - ][ -  + ]:       4962 :             if (dp_netdev_pmd_try_ref(pmd) && !hmapx_add(&to_find, pmd)) {
    2196                 :          0 :                 dp_netdev_pmd_unref(pmd);
    2197                 :            :             }
    2198                 :            :         }
    2199                 :            :     } else {
    2200                 :          0 :         pmd = dp_netdev_get_pmd(dp, get->pmd_id);
    2201         [ #  # ]:          0 :         if (!pmd) {
    2202                 :          0 :             goto out;
    2203                 :            :         }
    2204                 :          0 :         hmapx_add(&to_find, pmd);
    2205                 :            :     }
    2206                 :            : 
    2207         [ -  + ]:       4961 :     if (!hmapx_count(&to_find)) {
    2208                 :          0 :         goto out;
    2209                 :            :     }
    2210                 :            : 
    2211 [ +  - ][ #  # ]:       4962 :     HMAPX_FOR_EACH (node, &to_find) {
    2212                 :       4962 :         pmd = (struct dp_netdev_pmd_thread *) node->data;
    2213                 :       4962 :         netdev_flow = dp_netdev_pmd_find_flow(pmd, get->ufid, get->key,
    2214                 :            :                                               get->key_len);
    2215         [ +  + ]:       4962 :         if (netdev_flow) {
    2216                 :       4961 :             dp_netdev_flow_to_dpif_flow(netdev_flow, get->buffer, get->buffer,
    2217                 :            :                                         get->flow, false);
    2218                 :       4961 :             error = 0;
    2219                 :       4961 :             break;
    2220                 :            :         } else {
    2221                 :          1 :             error = ENOENT;
    2222                 :            :         }
    2223                 :            :     }
    2224                 :            : 
    2225 [ +  + ][ -  + ]:       9923 :     HMAPX_FOR_EACH (node, &to_find) {
    2226                 :       4962 :         pmd = (struct dp_netdev_pmd_thread *) node->data;
    2227                 :       4962 :         dp_netdev_pmd_unref(pmd);
    2228                 :            :     }
    2229                 :            : out:
    2230                 :       4961 :     hmapx_destroy(&to_find);
    2231                 :       4961 :     return error;
    2232                 :            : }
    2233                 :            : 
    2234                 :            : static struct dp_netdev_flow *
    2235                 :      10331 : dp_netdev_flow_add(struct dp_netdev_pmd_thread *pmd,
    2236                 :            :                    struct match *match, const ovs_u128 *ufid,
    2237                 :            :                    const struct nlattr *actions, size_t actions_len)
    2238                 :            :     OVS_REQUIRES(pmd->flow_mutex)
    2239                 :            : {
    2240                 :            :     struct dp_netdev_flow *flow;
    2241                 :            :     struct netdev_flow_key mask;
    2242                 :            :     struct dpcls *cls;
    2243                 :      10331 :     odp_port_t in_port = match->flow.in_port.odp_port;
    2244                 :            : 
    2245                 :      10331 :     netdev_flow_mask_init(&mask, match);
    2246                 :            :     /* Make sure wc does not have metadata. */
    2247 [ +  - ][ -  + ]:      10331 :     ovs_assert(!FLOWMAP_HAS_FIELD(&mask.mf.map, metadata)
    2248                 :            :                && !FLOWMAP_HAS_FIELD(&mask.mf.map, regs));
    2249                 :            : 
    2250                 :            :     /* Do not allocate extra space. */
    2251                 :      10331 :     flow = xmalloc(sizeof *flow - sizeof flow->cr.flow.mf + mask.len);
    2252                 :      10331 :     memset(&flow->stats, 0, sizeof flow->stats);
    2253                 :      10331 :     flow->dead = false;
    2254                 :      10331 :     flow->batch = NULL;
    2255                 :      10331 :     *CONST_CAST(unsigned *, &flow->pmd_id) = pmd->core_id;
    2256                 :      10331 :     *CONST_CAST(struct flow *, &flow->flow) = match->flow;
    2257                 :      10331 :     *CONST_CAST(ovs_u128 *, &flow->ufid) = *ufid;
    2258                 :      10331 :     ovs_refcount_init(&flow->ref_cnt);
    2259                 :      10331 :     ovsrcu_set(&flow->actions, dp_netdev_actions_create(actions, actions_len));
    2260                 :            : 
    2261                 :      10331 :     netdev_flow_key_init_masked(&flow->cr.flow, &match->flow, &mask);
    2262                 :            : 
    2263                 :            :     /* Select dpcls for in_port. Relies on in_port to be exact match */
    2264         [ -  + ]:      10331 :     ovs_assert(match->wc.masks.in_port.odp_port == ODP_PORT_C(UINT32_MAX));
    2265                 :      10331 :     cls = dp_netdev_pmd_find_dpcls(pmd, in_port);
    2266                 :      10331 :     dpcls_insert(cls, &flow->cr, &mask);
    2267                 :            : 
    2268                 :      10331 :     cmap_insert(&pmd->flow_table, CONST_CAST(struct cmap_node *, &flow->node),
    2269                 :            :                 dp_netdev_flow_hash(&flow->ufid));
    2270                 :            : 
    2271         [ +  + ]:      10331 :     if (OVS_UNLIKELY(VLOG_IS_DBG_ENABLED())) {
    2272                 :        197 :         struct ds ds = DS_EMPTY_INITIALIZER;
    2273                 :            :         struct ofpbuf key_buf, mask_buf;
    2274                 :        591 :         struct odp_flow_key_parms odp_parms = {
    2275                 :        197 :             .flow = &match->flow,
    2276                 :        197 :             .mask = &match->wc.masks,
    2277                 :            :             .support = dp_netdev_support,
    2278                 :            :         };
    2279                 :            : 
    2280                 :        197 :         ofpbuf_init(&key_buf, 0);
    2281                 :        197 :         ofpbuf_init(&mask_buf, 0);
    2282                 :            : 
    2283                 :        197 :         odp_flow_key_from_flow(&odp_parms, &key_buf);
    2284                 :        197 :         odp_parms.key_buf = &key_buf;
    2285                 :        197 :         odp_flow_key_from_mask(&odp_parms, &mask_buf);
    2286                 :            : 
    2287                 :        197 :         ds_put_cstr(&ds, "flow_add: ");
    2288                 :        197 :         odp_format_ufid(ufid, &ds);
    2289                 :        197 :         ds_put_cstr(&ds, " ");
    2290                 :        197 :         odp_flow_format(key_buf.data, key_buf.size,
    2291                 :        394 :                         mask_buf.data, mask_buf.size,
    2292                 :            :                         NULL, &ds, false);
    2293                 :        197 :         ds_put_cstr(&ds, ", actions:");
    2294                 :        197 :         format_odp_actions(&ds, actions, actions_len);
    2295                 :            : 
    2296         [ +  - ]:        197 :         VLOG_DBG_RL(&upcall_rl, "%s", ds_cstr(&ds));
    2297                 :            : 
    2298                 :        197 :         ofpbuf_uninit(&key_buf);
    2299                 :        197 :         ofpbuf_uninit(&mask_buf);
    2300                 :        197 :         ds_destroy(&ds);
    2301                 :            :     }
    2302                 :            : 
    2303                 :      10331 :     return flow;
    2304                 :            : }
    2305                 :            : 
    2306                 :            : static int
    2307                 :       5872 : dpif_netdev_flow_put(struct dpif *dpif, const struct dpif_flow_put *put)
    2308                 :            : {
    2309                 :       5872 :     struct dp_netdev *dp = get_dp_netdev(dpif);
    2310                 :            :     struct dp_netdev_flow *netdev_flow;
    2311                 :            :     struct netdev_flow_key key;
    2312                 :            :     struct dp_netdev_pmd_thread *pmd;
    2313                 :            :     struct match match;
    2314                 :            :     ovs_u128 ufid;
    2315                 :      11744 :     unsigned pmd_id = put->pmd_id == PMD_ID_NULL
    2316         [ +  + ]:       5872 :                       ? NON_PMD_CORE_ID : put->pmd_id;
    2317                 :            :     int error;
    2318                 :            : 
    2319                 :       5872 :     error = dpif_netdev_flow_from_nlattrs(put->key, put->key_len, &match.flow);
    2320         [ +  + ]:       5872 :     if (error) {
    2321                 :        551 :         return error;
    2322                 :            :     }
    2323                 :       5321 :     error = dpif_netdev_mask_from_nlattrs(put->key, put->key_len,
    2324                 :       5321 :                                           put->mask, put->mask_len,
    2325                 :            :                                           &match.flow, &match.wc);
    2326         [ -  + ]:       5321 :     if (error) {
    2327                 :          0 :         return error;
    2328                 :            :     }
    2329                 :            : 
    2330                 :       5321 :     pmd = dp_netdev_get_pmd(dp, pmd_id);
    2331         [ -  + ]:       5321 :     if (!pmd) {
    2332                 :          0 :         return EINVAL;
    2333                 :            :     }
    2334                 :            : 
    2335                 :            :     /* Must produce a netdev_flow_key for lookup.
    2336                 :            :      * This interface is no longer performance critical, since it is not used
    2337                 :            :      * for upcall processing any more. */
    2338                 :       5321 :     netdev_flow_key_from_flow(&key, &match.flow);
    2339                 :            : 
    2340         [ +  + ]:       5321 :     if (put->ufid) {
    2341                 :        913 :         ufid = *put->ufid;
    2342                 :            :     } else {
    2343                 :       4408 :         dpif_flow_hash(dpif, &match.flow, sizeof match.flow, &ufid);
    2344                 :            :     }
    2345                 :            : 
    2346                 :       5321 :     ovs_mutex_lock(&pmd->flow_mutex);
    2347                 :       5321 :     netdev_flow = dp_netdev_pmd_lookup_flow(pmd, &key, NULL);
    2348         [ +  + ]:       5321 :     if (!netdev_flow) {
    2349         [ +  - ]:       4959 :         if (put->flags & DPIF_FP_CREATE) {
    2350         [ +  - ]:       4959 :             if (cmap_count(&pmd->flow_table) < MAX_FLOWS) {
    2351         [ -  + ]:       4959 :                 if (put->stats) {
    2352                 :          0 :                     memset(put->stats, 0, sizeof *put->stats);
    2353                 :            :                 }
    2354                 :       4959 :                 dp_netdev_flow_add(pmd, &match, &ufid, put->actions,
    2355                 :            :                                    put->actions_len);
    2356                 :       4959 :                 error = 0;
    2357                 :            :             } else {
    2358                 :       4959 :                 error = EFBIG;
    2359                 :            :             }
    2360                 :            :         } else {
    2361                 :       4959 :             error = ENOENT;
    2362                 :            :         }
    2363                 :            :     } else {
    2364         [ +  - ]:        362 :         if (put->flags & DPIF_FP_MODIFY
    2365         [ +  + ]:        719 :             && flow_equal(&match.flow, &netdev_flow->flow)) {
    2366                 :            :             struct dp_netdev_actions *new_actions;
    2367                 :            :             struct dp_netdev_actions *old_actions;
    2368                 :            : 
    2369                 :        357 :             new_actions = dp_netdev_actions_create(put->actions,
    2370                 :            :                                                    put->actions_len);
    2371                 :            : 
    2372                 :        357 :             old_actions = dp_netdev_flow_get_actions(netdev_flow);
    2373                 :        357 :             ovsrcu_set(&netdev_flow->actions, new_actions);
    2374                 :            : 
    2375         [ -  + ]:        357 :             if (put->stats) {
    2376                 :          0 :                 get_dpif_flow_stats(netdev_flow, put->stats);
    2377                 :            :             }
    2378         [ -  + ]:        357 :             if (put->flags & DPIF_FP_ZERO_STATS) {
    2379                 :            :                 /* XXX: The userspace datapath uses thread local statistics
    2380                 :            :                  * (for flows), which should be updated only by the owning
    2381                 :            :                  * thread.  Since we cannot write on stats memory here,
    2382                 :            :                  * we choose not to support this flag.  Please note:
    2383                 :            :                  * - This feature is currently used only by dpctl commands with
    2384                 :            :                  *   option --clear.
    2385                 :            :                  * - Should the need arise, this operation can be implemented
    2386                 :            :                  *   by keeping a base value (to be update here) for each
    2387                 :            :                  *   counter, and subtracting it before outputting the stats */
    2388                 :          0 :                 error = EOPNOTSUPP;
    2389                 :            :             }
    2390                 :            : 
    2391                 :        357 :             ovsrcu_postpone(dp_netdev_actions_free, old_actions);
    2392         [ -  + ]:          5 :         } else if (put->flags & DPIF_FP_CREATE) {
    2393                 :          0 :             error = EEXIST;
    2394                 :            :         } else {
    2395                 :            :             /* Overlapping flow. */
    2396                 :          5 :             error = EINVAL;
    2397                 :            :         }
    2398                 :            :     }
    2399                 :       5321 :     ovs_mutex_unlock(&pmd->flow_mutex);
    2400                 :       5321 :     dp_netdev_pmd_unref(pmd);
    2401                 :            : 
    2402                 :       5872 :     return error;
    2403                 :            : }
    2404                 :            : 
    2405                 :            : static int
    2406                 :      10331 : dpif_netdev_flow_del(struct dpif *dpif, const struct dpif_flow_del *del)
    2407                 :            : {
    2408                 :      10331 :     struct dp_netdev *dp = get_dp_netdev(dpif);
    2409                 :            :     struct dp_netdev_flow *netdev_flow;
    2410                 :            :     struct dp_netdev_pmd_thread *pmd;
    2411                 :      20662 :     unsigned pmd_id = del->pmd_id == PMD_ID_NULL
    2412         [ +  + ]:      10331 :                       ? NON_PMD_CORE_ID : del->pmd_id;
    2413                 :      10331 :     int error = 0;
    2414                 :            : 
    2415                 :      10331 :     pmd = dp_netdev_get_pmd(dp, pmd_id);
    2416         [ -  + ]:      10331 :     if (!pmd) {
    2417                 :          0 :         return EINVAL;
    2418                 :            :     }
    2419                 :            : 
    2420                 :      10331 :     ovs_mutex_lock(&pmd->flow_mutex);
    2421                 :      10331 :     netdev_flow = dp_netdev_pmd_find_flow(pmd, del->ufid, del->key,
    2422                 :            :                                           del->key_len);
    2423         [ +  - ]:      10331 :     if (netdev_flow) {
    2424         [ +  + ]:      10331 :         if (del->stats) {
    2425                 :       5372 :             get_dpif_flow_stats(netdev_flow, del->stats);
    2426                 :            :         }
    2427                 :      10331 :         dp_netdev_pmd_remove_flow(pmd, netdev_flow);
    2428                 :            :     } else {
    2429                 :          0 :         error = ENOENT;
    2430                 :            :     }
    2431                 :      10331 :     ovs_mutex_unlock(&pmd->flow_mutex);
    2432                 :      10331 :     dp_netdev_pmd_unref(pmd);
    2433                 :            : 
    2434                 :      10331 :     return error;
    2435                 :            : }
    2436                 :            : 
    2437                 :            : struct dpif_netdev_flow_dump {
    2438                 :            :     struct dpif_flow_dump up;
    2439                 :            :     struct cmap_position poll_thread_pos;
    2440                 :            :     struct cmap_position flow_pos;
    2441                 :            :     struct dp_netdev_pmd_thread *cur_pmd;
    2442                 :            :     int status;
    2443                 :            :     struct ovs_mutex mutex;
    2444                 :            : };
    2445                 :            : 
    2446                 :            : static struct dpif_netdev_flow_dump *
    2447                 :      51985 : dpif_netdev_flow_dump_cast(struct dpif_flow_dump *dump)
    2448                 :            : {
    2449                 :      51985 :     return CONTAINER_OF(dump, struct dpif_netdev_flow_dump, up);
    2450                 :            : }
    2451                 :            : 
    2452                 :            : static struct dpif_flow_dump *
    2453                 :      25991 : dpif_netdev_flow_dump_create(const struct dpif *dpif_, bool terse)
    2454                 :            : {
    2455                 :            :     struct dpif_netdev_flow_dump *dump;
    2456                 :            : 
    2457                 :      25991 :     dump = xzalloc(sizeof *dump);
    2458                 :      25991 :     dpif_flow_dump_init(&dump->up, dpif_);
    2459                 :      25991 :     dump->up.terse = terse;
    2460                 :      25991 :     ovs_mutex_init(&dump->mutex);
    2461                 :            : 
    2462                 :      25991 :     return &dump->up;
    2463                 :            : }
    2464                 :            : 
    2465                 :            : static int
    2466                 :      25991 : dpif_netdev_flow_dump_destroy(struct dpif_flow_dump *dump_)
    2467                 :            : {
    2468                 :      25991 :     struct dpif_netdev_flow_dump *dump = dpif_netdev_flow_dump_cast(dump_);
    2469                 :            : 
    2470                 :      25991 :     ovs_mutex_destroy(&dump->mutex);
    2471                 :      25991 :     free(dump);
    2472                 :      25991 :     return 0;
    2473                 :            : }
    2474                 :            : 
    2475                 :            : struct dpif_netdev_flow_dump_thread {
    2476                 :            :     struct dpif_flow_dump_thread up;
    2477                 :            :     struct dpif_netdev_flow_dump *dump;
    2478                 :            :     struct odputil_keybuf keybuf[FLOW_DUMP_MAX_BATCH];
    2479                 :            :     struct odputil_keybuf maskbuf[FLOW_DUMP_MAX_BATCH];
    2480                 :            : };
    2481                 :            : 
    2482                 :            : static struct dpif_netdev_flow_dump_thread *
    2483                 :      60888 : dpif_netdev_flow_dump_thread_cast(struct dpif_flow_dump_thread *thread)
    2484                 :            : {
    2485                 :      60888 :     return CONTAINER_OF(thread, struct dpif_netdev_flow_dump_thread, up);
    2486                 :            : }
    2487                 :            : 
    2488                 :            : static struct dpif_flow_dump_thread *
    2489                 :      25994 : dpif_netdev_flow_dump_thread_create(struct dpif_flow_dump *dump_)
    2490                 :            : {
    2491                 :      25994 :     struct dpif_netdev_flow_dump *dump = dpif_netdev_flow_dump_cast(dump_);
    2492                 :            :     struct dpif_netdev_flow_dump_thread *thread;
    2493                 :            : 
    2494                 :      25994 :     thread = xmalloc(sizeof *thread);
    2495                 :      25994 :     dpif_flow_dump_thread_init(&thread->up, &dump->up);
    2496                 :      25994 :     thread->dump = dump;
    2497                 :      25994 :     return &thread->up;
    2498                 :            : }
    2499                 :            : 
    2500                 :            : static void
    2501                 :      25994 : dpif_netdev_flow_dump_thread_destroy(struct dpif_flow_dump_thread *thread_)
    2502                 :            : {
    2503                 :      25994 :     struct dpif_netdev_flow_dump_thread *thread
    2504                 :            :         = dpif_netdev_flow_dump_thread_cast(thread_);
    2505                 :            : 
    2506                 :      25994 :     free(thread);
    2507                 :      25994 : }
    2508                 :            : 
    2509                 :            : static int
    2510                 :      34894 : dpif_netdev_flow_dump_next(struct dpif_flow_dump_thread *thread_,
    2511                 :            :                            struct dpif_flow *flows, int max_flows)
    2512                 :            : {
    2513                 :      34894 :     struct dpif_netdev_flow_dump_thread *thread
    2514                 :            :         = dpif_netdev_flow_dump_thread_cast(thread_);
    2515                 :      34894 :     struct dpif_netdev_flow_dump *dump = thread->dump;
    2516                 :            :     struct dp_netdev_flow *netdev_flows[FLOW_DUMP_MAX_BATCH];
    2517                 :      34894 :     int n_flows = 0;
    2518                 :            :     int i;
    2519                 :            : 
    2520                 :      34894 :     ovs_mutex_lock(&dump->mutex);
    2521         [ +  + ]:      34894 :     if (!dump->status) {
    2522                 :      30171 :         struct dpif_netdev *dpif = dpif_netdev_cast(thread->up.dpif);
    2523                 :      30171 :         struct dp_netdev *dp = get_dp_netdev(&dpif->dpif);
    2524                 :      30171 :         struct dp_netdev_pmd_thread *pmd = dump->cur_pmd;
    2525                 :      30171 :         int flow_limit = MIN(max_flows, FLOW_DUMP_MAX_BATCH);
    2526                 :            : 
    2527                 :            :         /* First call to dump_next(), extracts the first pmd thread.
    2528                 :            :          * If there is no pmd thread, returns immediately. */
    2529         [ +  + ]:      30171 :         if (!pmd) {
    2530                 :      25991 :             pmd = dp_netdev_pmd_get_next(dp, &dump->poll_thread_pos);
    2531         [ +  + ]:      25991 :             if (!pmd) {
    2532                 :         12 :                 ovs_mutex_unlock(&dump->mutex);
    2533                 :         12 :                 return n_flows;
    2534                 :            : 
    2535                 :            :             }
    2536                 :            :         }
    2537                 :            : 
    2538                 :            :         do {
    2539         [ +  + ]:     198181 :             for (n_flows = 0; n_flows < flow_limit; n_flows++) {
    2540                 :            :                 struct cmap_node *node;
    2541                 :            : 
    2542                 :     194014 :                 node = cmap_next_position(&pmd->flow_table, &dump->flow_pos);
    2543         [ +  + ]:     194014 :                 if (!node) {
    2544                 :      26282 :                     break;
    2545                 :            :                 }
    2546                 :     167732 :                 netdev_flows[n_flows] = CONTAINER_OF(node,
    2547                 :            :                                                      struct dp_netdev_flow,
    2548                 :            :                                                      node);
    2549                 :            :             }
    2550                 :            :             /* When finishing dumping the current pmd thread, moves to
    2551                 :            :              * the next. */
    2552         [ +  + ]:      30449 :             if (n_flows < flow_limit) {
    2553                 :      26282 :                 memset(&dump->flow_pos, 0, sizeof dump->flow_pos);
    2554                 :      26282 :                 dp_netdev_pmd_unref(pmd);
    2555                 :      26282 :                 pmd = dp_netdev_pmd_get_next(dp, &dump->poll_thread_pos);
    2556         [ +  + ]:      26282 :                 if (!pmd) {
    2557                 :      25979 :                     dump->status = EOF;
    2558                 :      25979 :                     break;
    2559                 :            :                 }
    2560                 :            :             }
    2561                 :            :             /* Keeps the reference to next caller. */
    2562                 :       4470 :             dump->cur_pmd = pmd;
    2563                 :            : 
    2564                 :            :             /* If the current dump is empty, do not exit the loop, since the
    2565                 :            :              * remaining pmds could have flows to be dumped.  Just dumps again
    2566                 :            :              * on the new 'pmd'. */
    2567         [ +  + ]:       4470 :         } while (!n_flows);
    2568                 :            :     }
    2569                 :      34882 :     ovs_mutex_unlock(&dump->mutex);
    2570                 :            : 
    2571         [ +  + ]:     202614 :     for (i = 0; i < n_flows; i++) {
    2572                 :     167732 :         struct odputil_keybuf *maskbuf = &thread->maskbuf[i];
    2573                 :     167732 :         struct odputil_keybuf *keybuf = &thread->keybuf[i];
    2574                 :     167732 :         struct dp_netdev_flow *netdev_flow = netdev_flows[i];
    2575                 :     167732 :         struct dpif_flow *f = &flows[i];
    2576                 :            :         struct ofpbuf key, mask;
    2577                 :            : 
    2578                 :     167732 :         ofpbuf_use_stack(&key, keybuf, sizeof *keybuf);
    2579                 :     167732 :         ofpbuf_use_stack(&mask, maskbuf, sizeof *maskbuf);
    2580                 :     167732 :         dp_netdev_flow_to_dpif_flow(netdev_flow, &key, &mask, f,
    2581                 :     167732 :                                     dump->up.terse);
    2582                 :            :     }
    2583                 :            : 
    2584                 :      34894 :     return n_flows;
    2585                 :            : }
    2586                 :            : 
    2587                 :            : static int
    2588                 :       3624 : dpif_netdev_execute(struct dpif *dpif, struct dpif_execute *execute)
    2589                 :            :     OVS_NO_THREAD_SAFETY_ANALYSIS
    2590                 :            : {
    2591                 :       3624 :     struct dp_netdev *dp = get_dp_netdev(dpif);
    2592                 :            :     struct dp_netdev_pmd_thread *pmd;
    2593                 :            :     struct dp_packet_batch pp;
    2594                 :            : 
    2595   [ +  -  -  + ]:       7248 :     if (dp_packet_size(execute->packet) < ETH_HEADER_LEN ||
    2596                 :       3624 :         dp_packet_size(execute->packet) > UINT16_MAX) {
    2597                 :          0 :         return EINVAL;
    2598                 :            :     }
    2599                 :            : 
    2600                 :            :     /* Tries finding the 'pmd'.  If NULL is returned, that means
    2601                 :            :      * the current thread is a non-pmd thread and should use
    2602                 :            :      * dp_netdev_get_pmd(dp, NON_PMD_CORE_ID). */
    2603                 :       3624 :     pmd = ovsthread_getspecific(dp->per_pmd_key);
    2604         [ +  - ]:       3624 :     if (!pmd) {
    2605                 :       3624 :         pmd = dp_netdev_get_pmd(dp, NON_PMD_CORE_ID);
    2606                 :            :     }
    2607                 :            : 
    2608                 :            :     /* If the current thread is non-pmd thread, acquires
    2609                 :            :      * the 'non_pmd_mutex'. */
    2610         [ +  - ]:       3624 :     if (pmd->core_id == NON_PMD_CORE_ID) {
    2611                 :       3624 :         ovs_mutex_lock(&dp->non_pmd_mutex);
    2612                 :            :     }
    2613                 :            : 
    2614                 :            :     /* The action processing expects the RSS hash to be valid, because
    2615                 :            :      * it's always initialized at the beginning of datapath processing.
    2616                 :            :      * In this case, though, 'execute->packet' may not have gone through
    2617                 :            :      * the datapath at all, it may have been generated by the upper layer
    2618                 :            :      * (OpenFlow packet-out, BFD frame, ...). */
    2619         [ +  + ]:       3624 :     if (!dp_packet_rss_valid(execute->packet)) {
    2620                 :       2567 :         dp_packet_set_rss_hash(execute->packet,
    2621                 :            :                                flow_hash_5tuple(execute->flow, 0));
    2622                 :            :     }
    2623                 :            : 
    2624                 :       3624 :     packet_batch_init_packet(&pp, execute->packet);
    2625                 :       3624 :     dp_netdev_execute_actions(pmd, &pp, false, execute->flow,
    2626                 :            :                               execute->actions, execute->actions_len,
    2627                 :            :                               time_msec());
    2628                 :            : 
    2629         [ +  - ]:       3624 :     if (pmd->core_id == NON_PMD_CORE_ID) {
    2630                 :       3624 :         ovs_mutex_unlock(&dp->non_pmd_mutex);
    2631                 :       3624 :         dp_netdev_pmd_unref(pmd);
    2632                 :            :     }
    2633                 :            : 
    2634                 :       3624 :     return 0;
    2635                 :            : }
    2636                 :            : 
    2637                 :            : static void
    2638                 :      22263 : dpif_netdev_operate(struct dpif *dpif, struct dpif_op **ops, size_t n_ops)
    2639                 :            : {
    2640                 :            :     size_t i;
    2641                 :            : 
    2642         [ +  + ]:      47051 :     for (i = 0; i < n_ops; i++) {
    2643                 :      24788 :         struct dpif_op *op = ops[i];
    2644                 :            : 
    2645   [ +  +  +  +  :      24788 :         switch (op->type) {
                      - ]
    2646                 :            :         case DPIF_OP_FLOW_PUT:
    2647                 :       5872 :             op->error = dpif_netdev_flow_put(dpif, &op->u.flow_put);
    2648                 :       5872 :             break;
    2649                 :            : 
    2650                 :            :         case DPIF_OP_FLOW_DEL:
    2651                 :      10331 :             op->error = dpif_netdev_flow_del(dpif, &op->u.flow_del);
    2652                 :      10331 :             break;
    2653                 :            : 
    2654                 :            :         case DPIF_OP_EXECUTE:
    2655                 :       3624 :             op->error = dpif_netdev_execute(dpif, &op->u.execute);
    2656                 :       3624 :             break;
    2657                 :            : 
    2658                 :            :         case DPIF_OP_FLOW_GET:
    2659                 :       4961 :             op->error = dpif_netdev_flow_get(dpif, &op->u.flow_get);
    2660                 :       4961 :             break;
    2661                 :            :         }
    2662                 :            :     }
    2663                 :      22263 : }
    2664                 :            : 
    2665                 :            : /* Changes the number or the affinity of pmd threads.  The changes are actually
    2666                 :            :  * applied in dpif_netdev_run(). */
    2667                 :            : static int
    2668                 :      99708 : dpif_netdev_pmd_set(struct dpif *dpif, const char *cmask)
    2669                 :            : {
    2670                 :      99708 :     struct dp_netdev *dp = get_dp_netdev(dpif);
    2671                 :            : 
    2672         [ +  + ]:      99708 :     if (!nullable_string_is_equal(dp->pmd_cmask, cmask)) {
    2673                 :          8 :         free(dp->pmd_cmask);
    2674                 :          8 :         dp->pmd_cmask = nullable_xstrdup(cmask);
    2675                 :          8 :         dp_netdev_request_reconfigure(dp);
    2676                 :            :     }
    2677                 :            : 
    2678                 :      99708 :     return 0;
    2679                 :            : }
    2680                 :            : 
    2681                 :            : /* Parses affinity list and returns result in 'core_ids'. */
    2682                 :            : static int
    2683                 :          6 : parse_affinity_list(const char *affinity_list, unsigned *core_ids, int n_rxq)
    2684                 :            : {
    2685                 :            :     unsigned i;
    2686                 :            :     char *list, *copy, *key, *value;
    2687                 :          6 :     int error = 0;
    2688                 :            : 
    2689         [ +  + ]:         32 :     for (i = 0; i < n_rxq; i++) {
    2690                 :         26 :         core_ids[i] = -1;
    2691                 :            :     }
    2692                 :            : 
    2693         [ +  + ]:          6 :     if (!affinity_list) {
    2694                 :          4 :         return 0;
    2695                 :            :     }
    2696                 :            : 
    2697                 :          2 :     list = copy = xstrdup(affinity_list);
    2698                 :            : 
    2699         [ +  + ]:          7 :     while (ofputil_parse_key_value(&list, &key, &value)) {
    2700                 :            :         int rxq_id, core_id;
    2701                 :            : 
    2702 [ +  - ][ +  - ]:          5 :         if (!str_to_int(key, 0, &rxq_id) || rxq_id < 0
    2703 [ +  - ][ -  + ]:          5 :             || !str_to_int(value, 0, &core_id) || core_id < 0) {
    2704                 :          0 :             error = EINVAL;
    2705                 :          0 :             break;
    2706                 :            :         }
    2707                 :            : 
    2708         [ +  - ]:          5 :         if (rxq_id < n_rxq) {
    2709                 :          5 :             core_ids[rxq_id] = core_id;
    2710                 :            :         }
    2711                 :            :     }
    2712                 :            : 
    2713                 :          2 :     free(copy);
    2714                 :          6 :     return error;
    2715                 :            : }
    2716                 :            : 
    2717                 :            : /* Parses 'affinity_list' and applies configuration if it is valid. */
    2718                 :            : static int
    2719                 :          6 : dpif_netdev_port_set_rxq_affinity(struct dp_netdev_port *port,
    2720                 :            :                                   const char *affinity_list)
    2721                 :            : {
    2722                 :            :     unsigned *core_ids, i;
    2723                 :          6 :     int error = 0;
    2724                 :            : 
    2725                 :          6 :     core_ids = xmalloc(port->n_rxq * sizeof *core_ids);
    2726         [ -  + ]:          6 :     if (parse_affinity_list(affinity_list, core_ids, port->n_rxq)) {
    2727                 :          0 :         error = EINVAL;
    2728                 :          0 :         goto exit;
    2729                 :            :     }
    2730                 :            : 
    2731         [ +  + ]:         32 :     for (i = 0; i < port->n_rxq; i++) {
    2732                 :         26 :         port->rxqs[i].core_id = core_ids[i];
    2733                 :            :     }
    2734                 :            : 
    2735                 :            : exit:
    2736                 :          6 :     free(core_ids);
    2737                 :          6 :     return error;
    2738                 :            : }
    2739                 :            : 
    2740                 :            : /* Changes the affinity of port's rx queues.  The changes are actually applied
    2741                 :            :  * in dpif_netdev_run(). */
    2742                 :            : static int
    2743                 :       6669 : dpif_netdev_port_set_config(struct dpif *dpif, odp_port_t port_no,
    2744                 :            :                             const struct smap *cfg)
    2745                 :            : {
    2746                 :       6669 :     struct dp_netdev *dp = get_dp_netdev(dpif);
    2747                 :            :     struct dp_netdev_port *port;
    2748                 :       6669 :     int error = 0;
    2749                 :       6669 :     const char *affinity_list = smap_get(cfg, "pmd-rxq-affinity");
    2750                 :            : 
    2751                 :       6669 :     ovs_mutex_lock(&dp->port_mutex);
    2752                 :       6669 :     error = get_port_by_number(dp, port_no, &port);
    2753 [ +  - ][ +  + ]:       6669 :     if (error || !netdev_is_pmd(port->netdev)
    2754         [ +  + ]:         45 :         || nullable_string_is_equal(affinity_list, port->rxq_affinity_list)) {
    2755                 :            :         goto unlock;
    2756                 :            :     }
    2757                 :            : 
    2758                 :          3 :     error = dpif_netdev_port_set_rxq_affinity(port, affinity_list);
    2759         [ -  + ]:          3 :     if (error) {
    2760                 :          0 :         goto unlock;
    2761                 :            :     }
    2762                 :          3 :     free(port->rxq_affinity_list);
    2763                 :          3 :     port->rxq_affinity_list = nullable_xstrdup(affinity_list);
    2764                 :            : 
    2765                 :          3 :     dp_netdev_request_reconfigure(dp);
    2766                 :            : unlock:
    2767                 :       6669 :     ovs_mutex_unlock(&dp->port_mutex);
    2768                 :       6669 :     return error;
    2769                 :            : }
    2770                 :            : 
    2771                 :            : static int
    2772                 :         14 : dpif_netdev_queue_to_priority(const struct dpif *dpif OVS_UNUSED,
    2773                 :            :                               uint32_t queue_id, uint32_t *priority)
    2774                 :            : {
    2775                 :         14 :     *priority = queue_id;
    2776                 :         14 :     return 0;
    2777                 :            : }
    2778                 :            : 
    2779                 :            : 
    2780                 :            : /* Creates and returns a new 'struct dp_netdev_actions', whose actions are
    2781                 :            :  * a copy of the 'ofpacts_len' bytes of 'ofpacts'. */
    2782                 :            : struct dp_netdev_actions *
    2783                 :      10688 : dp_netdev_actions_create(const struct nlattr *actions, size_t size)
    2784                 :            : {
    2785                 :            :     struct dp_netdev_actions *netdev_actions;
    2786                 :            : 
    2787                 :      10688 :     netdev_actions = xmalloc(sizeof *netdev_actions + size);
    2788                 :      10688 :     memcpy(netdev_actions->actions, actions, size);
    2789                 :      10688 :     netdev_actions->size = size;
    2790                 :            : 
    2791                 :      10688 :     return netdev_actions;
    2792                 :            : }
    2793                 :            : 
    2794                 :            : struct dp_netdev_actions *
    2795                 :      23415 : dp_netdev_flow_get_actions(const struct dp_netdev_flow *flow)
    2796                 :            : {
    2797                 :      23415 :     return ovsrcu_get(struct dp_netdev_actions *, &flow->actions);
    2798                 :            : }
    2799                 :            : 
    2800                 :            : static void
    2801                 :       7162 : dp_netdev_actions_free(struct dp_netdev_actions *actions)
    2802                 :            : {
    2803                 :       7162 :     free(actions);
    2804                 :       7162 : }
    2805                 :            : 
    2806                 :            : static inline unsigned long long
    2807                 :   52770593 : cycles_counter(void)
    2808                 :            : {
    2809                 :            : #ifdef DPDK_NETDEV
    2810                 :            :     return rte_get_tsc_cycles();
    2811                 :            : #else
    2812                 :   52770593 :     return 0;
    2813                 :            : #endif
    2814                 :            : }
    2815                 :            : 
    2816                 :            : /* Fake mutex to make sure that the calls to cycles_count_* are balanced */
    2817                 :            : extern struct ovs_mutex cycles_counter_fake_mutex;
    2818                 :            : 
    2819                 :            : /* Start counting cycles.  Must be followed by 'cycles_count_end()' */
    2820                 :            : static inline void
    2821                 :   26386925 : cycles_count_start(struct dp_netdev_pmd_thread *pmd)
    2822                 :            :     OVS_ACQUIRES(&cycles_counter_fake_mutex)
    2823                 :            :     OVS_NO_THREAD_SAFETY_ANALYSIS
    2824                 :            : {
    2825                 :   26386925 :     pmd->last_cycles = cycles_counter();
    2826                 :   26386986 : }
    2827                 :            : 
    2828                 :            : /* Stop counting cycles and add them to the counter 'type' */
    2829                 :            : static inline void
    2830                 :   26398875 : cycles_count_end(struct dp_netdev_pmd_thread *pmd,
    2831                 :            :                  enum pmd_cycles_counter_type type)
    2832                 :            :     OVS_RELEASES(&cycles_counter_fake_mutex)
    2833                 :            :     OVS_NO_THREAD_SAFETY_ANALYSIS
    2834                 :            : {
    2835                 :   26398875 :     unsigned long long interval = cycles_counter() - pmd->last_cycles;
    2836                 :            : 
    2837                 :   26396959 :     non_atomic_ullong_add(&pmd->cycles.n[type], interval);
    2838                 :   26390170 : }
    2839                 :            : 
    2840                 :            : static void
    2841                 :    4286363 : dp_netdev_process_rxq_port(struct dp_netdev_pmd_thread *pmd,
    2842                 :            :                            struct dp_netdev_port *port,
    2843                 :            :                            struct netdev_rxq *rxq)
    2844                 :            : {
    2845                 :            :     struct dp_packet_batch batch;
    2846                 :            :     int error;
    2847                 :            : 
    2848                 :    4286363 :     dp_packet_batch_init(&batch);
    2849                 :   26377372 :     cycles_count_start(pmd);
    2850                 :   26375485 :     error = netdev_rxq_recv(rxq, &batch);
    2851                 :   26388974 :     cycles_count_end(pmd, PMD_CYCLES_POLLING);
    2852         [ +  + ]:    4289538 :     if (!error) {
    2853                 :      10033 :         *recirc_depth_get() = 0;
    2854                 :            : 
    2855                 :      10033 :         cycles_count_start(pmd);
    2856                 :      10033 :         dp_netdev_input(pmd, &batch, port->port_no);
    2857                 :      10033 :         cycles_count_end(pmd, PMD_CYCLES_PROCESSING);
    2858 [ -  + ][ #  # ]:    4279505 :     } else if (error != EAGAIN && error != EOPNOTSUPP) {
    2859                 :            :         static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
    2860                 :            : 
    2861         [ #  # ]:          0 :         VLOG_ERR_RL(&rl, "error receiving data from %s: %s",
    2862                 :            :                     netdev_get_name(port->netdev), ovs_strerror(error));
    2863                 :            :     }
    2864                 :    4289538 : }
    2865                 :            : 
    2866                 :            : static int
    2867                 :         46 : port_reconfigure(struct dp_netdev_port *port)
    2868                 :            : {
    2869                 :         46 :     struct netdev *netdev = port->netdev;
    2870                 :            :     int i, err;
    2871                 :            : 
    2872         [ +  + ]:         46 :     if (!netdev_is_reconf_required(netdev)) {
    2873                 :         43 :         return 0;
    2874                 :            :     }
    2875                 :            : 
    2876                 :            :     /* Closes the existing 'rxq's. */
    2877         [ +  + ]:          8 :     for (i = 0; i < port->n_rxq; i++) {
    2878                 :          5 :         netdev_rxq_close(port->rxqs[i].rxq);
    2879                 :          5 :         port->rxqs[i].rxq = NULL;
    2880                 :            :     }
    2881                 :          3 :     port->n_rxq = 0;
    2882                 :            : 
    2883                 :            :     /* Allows 'netdev' to apply the pending configuration changes. */
    2884                 :          3 :     err = netdev_reconfigure(netdev);
    2885 [ -  + ][ #  # ]:          3 :     if (err && (err != EOPNOTSUPP)) {
    2886         [ #  # ]:          0 :         VLOG_ERR("Failed to set interface %s new configuration",
    2887                 :            :                  netdev_get_name(netdev));
    2888                 :          0 :         return err;
    2889                 :            :     }
    2890                 :            :     /* If the netdev_reconfigure() above succeeds, reopens the 'rxq's. */
    2891                 :          3 :     port->rxqs = xrealloc(port->rxqs,
    2892                 :          3 :                           sizeof *port->rxqs * netdev_n_rxq(netdev));
    2893                 :            :     /* Realloc 'used' counters for tx queues. */
    2894                 :          3 :     free(port->txq_used);
    2895                 :          3 :     port->txq_used = xcalloc(netdev_n_txq(netdev), sizeof *port->txq_used);
    2896                 :            : 
    2897         [ +  + ]:         17 :     for (i = 0; i < netdev_n_rxq(netdev); i++) {
    2898                 :         14 :         err = netdev_rxq_open(netdev, &port->rxqs[i].rxq, i);
    2899         [ -  + ]:         14 :         if (err) {
    2900                 :          0 :             return err;
    2901                 :            :         }
    2902                 :         14 :         port->n_rxq++;
    2903                 :            :     }
    2904                 :            : 
    2905                 :            :     /* Parse affinity list to apply configuration for new queues. */
    2906                 :          3 :     dpif_netdev_port_set_rxq_affinity(port, port->rxq_affinity_list);
    2907                 :            : 
    2908                 :          3 :     return 0;
    2909                 :            : }
    2910                 :            : 
    2911                 :            : static void
    2912                 :         14 : reconfigure_pmd_threads(struct dp_netdev *dp)
    2913                 :            :     OVS_REQUIRES(dp->port_mutex)
    2914                 :            : {
    2915                 :            :     struct dp_netdev_port *port, *next;
    2916                 :            :     int n_cores;
    2917                 :            : 
    2918                 :         14 :     dp->last_reconfigure_seq = seq_read(dp->reconfigure_seq);
    2919                 :            : 
    2920                 :         14 :     dp_netdev_destroy_all_pmds(dp);
    2921                 :            : 
    2922                 :            :     /* Reconfigures the cpu mask. */
    2923                 :         14 :     ovs_numa_set_cpu_mask(dp->pmd_cmask);
    2924                 :            : 
    2925                 :         14 :     n_cores = ovs_numa_get_n_cores();
    2926         [ -  + ]:         14 :     if (n_cores == OVS_CORE_UNSPEC) {
    2927         [ #  # ]:          0 :         VLOG_ERR("Cannot get cpu core info");
    2928                 :          0 :         return;
    2929                 :            :     }
    2930                 :            : 
    2931 [ +  + ][ -  + ]:         60 :     HMAP_FOR_EACH_SAFE (port, next, node, &dp->ports) {
                 [ +  + ]
    2932                 :            :         int err;
    2933                 :            : 
    2934                 :         46 :         err = port_reconfigure(port);
    2935         [ -  + ]:         46 :         if (err) {
    2936                 :          0 :             hmap_remove(&dp->ports, &port->node);
    2937                 :          0 :             seq_change(dp->port_seq);
    2938                 :          0 :             port_destroy(port);
    2939                 :            :         } else {
    2940                 :         46 :             port->dynamic_txqs = netdev_n_txq(port->netdev) < n_cores + 1;
    2941                 :            :         }
    2942                 :            :     }
    2943                 :            :     /* Restores the non-pmd. */
    2944                 :         14 :     dp_netdev_set_nonpmd(dp);
    2945                 :            :     /* Restores all pmd threads. */
    2946                 :         14 :     dp_netdev_reset_pmd_threads(dp);
    2947                 :            : }
    2948                 :            : 
    2949                 :            : /* Returns true if one of the netdevs in 'dp' requires a reconfiguration */
    2950                 :            : static bool
    2951                 :      99697 : ports_require_restart(const struct dp_netdev *dp)
    2952                 :            :     OVS_REQUIRES(dp->port_mutex)
    2953                 :            : {
    2954                 :            :     struct dp_netdev_port *port;
    2955                 :            : 
    2956 [ +  + ][ -  + ]:     662395 :     HMAP_FOR_EACH (port, node, &dp->ports) {
    2957         [ +  + ]:     562701 :         if (netdev_is_reconf_required(port->netdev)) {
    2958                 :          3 :             return true;
    2959                 :            :         }
    2960                 :            :     }
    2961                 :            : 
    2962                 :      99694 :     return false;
    2963                 :            : }
    2964                 :            : 
    2965                 :            : /* Return true if needs to revalidate datapath flows. */
    2966                 :            : static bool
    2967                 :      99708 : dpif_netdev_run(struct dpif *dpif)
    2968                 :            : {
    2969                 :            :     struct dp_netdev_port *port;
    2970                 :      99708 :     struct dp_netdev *dp = get_dp_netdev(dpif);
    2971                 :      99708 :     struct dp_netdev_pmd_thread *non_pmd = dp_netdev_get_pmd(dp,
    2972                 :            :                                                              NON_PMD_CORE_ID);
    2973                 :            :     uint64_t new_tnl_seq;
    2974                 :            : 
    2975                 :      99708 :     ovs_mutex_lock(&dp->port_mutex);
    2976                 :      99708 :     ovs_mutex_lock(&dp->non_pmd_mutex);
    2977 [ +  + ][ -  + ]:     662448 :     HMAP_FOR_EACH (port, node, &dp->ports) {
    2978         [ +  + ]:     562740 :         if (!netdev_is_pmd(port->netdev)) {
    2979                 :            :             int i;
    2980                 :            : 
    2981         [ +  + ]:    1096211 :             for (i = 0; i < port->n_rxq; i++) {
    2982                 :     534506 :                 dp_netdev_process_rxq_port(non_pmd, port, port->rxqs[i].rxq);
    2983                 :            :             }
    2984                 :            :         }
    2985                 :            :     }
    2986                 :      99708 :     dpif_netdev_xps_revalidate_pmd(non_pmd, time_msec(), false);
    2987                 :      99708 :     ovs_mutex_unlock(&dp->non_pmd_mutex);
    2988                 :            : 
    2989                 :      99708 :     dp_netdev_pmd_unref(non_pmd);
    2990                 :            : 
    2991 [ +  + ][ +  + ]:      99708 :     if (dp_netdev_is_reconf_required(dp) || ports_require_restart(dp)) {
    2992                 :         14 :         reconfigure_pmd_threads(dp);
    2993                 :            :     }
    2994                 :      99708 :     ovs_mutex_unlock(&dp->port_mutex);
    2995                 :            : 
    2996                 :      99708 :     tnl_neigh_cache_run();
    2997                 :      99708 :     tnl_port_map_run();
    2998                 :      99708 :     new_tnl_seq = seq_read(tnl_conf_seq);
    2999                 :            : 
    3000         [ +  + ]:      99708 :     if (dp->last_tnl_conf_seq != new_tnl_seq) {
    3001                 :        715 :         dp->last_tnl_conf_seq = new_tnl_seq;
    3002                 :        715 :         return true;
    3003                 :            :     }
    3004                 :      98993 :     return false;
    3005                 :            : }
    3006                 :            : 
    3007                 :            : static void
    3008                 :      97752 : dpif_netdev_wait(struct dpif *dpif)
    3009                 :            : {
    3010                 :            :     struct dp_netdev_port *port;
    3011                 :      97752 :     struct dp_netdev *dp = get_dp_netdev(dpif);
    3012                 :            : 
    3013                 :      97752 :     ovs_mutex_lock(&dp_netdev_mutex);
    3014                 :      97752 :     ovs_mutex_lock(&dp->port_mutex);
    3015 [ +  + ][ -  + ]:     652920 :     HMAP_FOR_EACH (port, node, &dp->ports) {
    3016                 :     555168 :         netdev_wait_reconf_required(port->netdev);
    3017         [ +  + ]:     555168 :         if (!netdev_is_pmd(port->netdev)) {
    3018                 :            :             int i;
    3019                 :            : 
    3020         [ +  + ]:    1081567 :             for (i = 0; i < port->n_rxq; i++) {
    3021                 :     527419 :                 netdev_rxq_wait(port->rxqs[i].rxq);
    3022                 :            :             }
    3023                 :            :         }
    3024                 :            :     }
    3025                 :      97752 :     ovs_mutex_unlock(&dp->port_mutex);
    3026                 :      97752 :     ovs_mutex_unlock(&dp_netdev_mutex);
    3027                 :      97752 :     seq_wait(tnl_conf_seq, dp->last_tnl_conf_seq);
    3028                 :      97752 : }
    3029                 :            : 
    3030                 :            : static void
    3031                 :       3561 : pmd_free_cached_ports(struct dp_netdev_pmd_thread *pmd)
    3032                 :            : {
    3033                 :            :     struct tx_port *tx_port_cached;
    3034                 :            : 
    3035                 :            :     /* Free all used tx queue ids. */
    3036                 :       3561 :     dpif_netdev_xps_revalidate_pmd(pmd, 0, true);
    3037                 :            : 
    3038 [ +  + ][ -  + ]:      10799 :     HMAP_FOR_EACH_POP (tx_port_cached, node, &pmd->port_cache) {
                 [ +  + ]
    3039                 :       7238 :         free(tx_port_cached);
    3040                 :            :     }
    3041                 :       3561 : }
    3042                 :            : 
    3043                 :            : /* Copies ports from 'pmd->tx_ports' (shared with the main thread) to
    3044                 :            :  * 'pmd->port_cache' (thread local) */
    3045                 :            : static void
    3046                 :       3514 : pmd_load_cached_ports(struct dp_netdev_pmd_thread *pmd)
    3047                 :            :     OVS_REQUIRES(pmd->port_mutex)
    3048                 :            : {
    3049                 :            :     struct tx_port *tx_port, *tx_port_cached;
    3050                 :            : 
    3051                 :       3514 :     pmd_free_cached_ports(pmd);
    3052                 :       3514 :     hmap_shrink(&pmd->port_cache);
    3053                 :            : 
    3054 [ +  + ][ -  + ]:      12961 :     HMAP_FOR_EACH (tx_port, node, &pmd->tx_ports) {
    3055                 :       9447 :         tx_port_cached = xmemdup(tx_port, sizeof *tx_port_cached);
    3056                 :       9447 :         hmap_insert(&pmd->port_cache, &tx_port_cached->node,
    3057                 :            :                     hash_port_no(tx_port_cached->port->port_no));
    3058                 :            :     }
    3059                 :       3514 : }
    3060                 :            : 
    3061                 :            : static int
    3062                 :        154 : pmd_load_queues_and_ports(struct dp_netdev_pmd_thread *pmd,
    3063                 :            :                           struct rxq_poll **ppoll_list)
    3064                 :            : {
    3065                 :        154 :     struct rxq_poll *poll_list = *ppoll_list;
    3066                 :            :     struct rxq_poll *poll;
    3067                 :            :     int i;
    3068                 :            : 
    3069                 :        154 :     ovs_mutex_lock(&pmd->port_mutex);
    3070                 :        154 :     poll_list = xrealloc(poll_list, pmd->poll_cnt * sizeof *poll_list);
    3071                 :            : 
    3072                 :        154 :     i = 0;
    3073         [ +  + ]:        401 :     LIST_FOR_EACH (poll, node, &pmd->poll_list) {
    3074                 :        247 :         poll_list[i++] = *poll;
    3075                 :            :     }
    3076                 :            : 
    3077                 :        154 :     pmd_load_cached_ports(pmd);
    3078                 :            : 
    3079                 :        154 :     ovs_mutex_unlock(&pmd->port_mutex);
    3080                 :            : 
    3081                 :        154 :     *ppoll_list = poll_list;
    3082                 :        154 :     return i;
    3083                 :            : }
    3084                 :            : 
    3085                 :            : static void *
    3086                 :         53 : pmd_thread_main(void *f_)
    3087                 :            : {
    3088                 :         53 :     struct dp_netdev_pmd_thread *pmd = f_;
    3089                 :         53 :     unsigned int lc = 0;
    3090                 :            :     struct rxq_poll *poll_list;
    3091                 :         53 :     unsigned int port_seq = PMD_INITIAL_SEQ;
    3092                 :            :     bool exiting;
    3093                 :            :     int poll_cnt;
    3094                 :            :     int i;
    3095                 :            : 
    3096                 :         53 :     poll_list = NULL;
    3097                 :            : 
    3098                 :            :     /* Stores the pmd thread's 'pmd' to 'per_pmd_key'. */
    3099                 :         53 :     ovsthread_setspecific(pmd->dp->per_pmd_key, pmd);
    3100                 :         53 :     ovs_numa_thread_setaffinity_core(pmd->core_id);
    3101                 :         53 :     dpdk_set_lcore_id(pmd->core_id);
    3102                 :         53 :     poll_cnt = pmd_load_queues_and_ports(pmd, &poll_list);
    3103                 :            : reload:
    3104                 :        123 :     emc_cache_init(&pmd->flow_cache);
    3105                 :            : 
    3106                 :            :     /* List port/core affinity */
    3107            [ + ]:          0 :     for (i = 0; i < poll_cnt; i++) {
    3108         [ +  + ]:        202 :        VLOG_DBG("Core %d processing port \'%s\' with queue-id %d\n",
    3109                 :            :                 pmd->core_id, netdev_get_name(poll_list[i].port->netdev),
    3110                 :            :                 netdev_rxq_get_queue_id(poll_list[i].rx));
    3111                 :            :     }
    3112                 :            : 
    3113                 :            :     for (;;) {
    3114         [ +  + ]:  267098573 :         for (i = 0; i < poll_cnt; i++) {
    3115                 :   25846388 :             dp_netdev_process_rxq_port(pmd, poll_list[i].port, poll_list[i].rx);
    3116                 :            :         }
    3117                 :            : 
    3118         [ +  + ]:  241252185 :         if (lc++ > 1024) {
    3119                 :            :             unsigned int seq;
    3120                 :            : 
    3121                 :     256850 :             lc = 0;
    3122                 :            : 
    3123                 :     256850 :             coverage_try_clear();
    3124                 :     260282 :             dp_netdev_pmd_try_optimize(pmd);
    3125         [ +  + ]:     260281 :             if (!ovsrcu_try_quiesce()) {
    3126                 :     220145 :                 emc_cache_slow_sweep(&pmd->flow_cache);
    3127                 :            :             }
    3128                 :            : 
    3129                 :     260280 :             atomic_read_relaxed(&pmd->change_seq, &seq);
    3130         [ +  + ]:     260280 :             if (seq != port_seq) {
    3131                 :        101 :                 port_seq = seq;
    3132                 :        101 :                 break;
    3133                 :            :             }
    3134                 :            :         }
    3135                 :  241255514 :     }
    3136                 :            : 
    3137                 :        101 :     poll_cnt = pmd_load_queues_and_ports(pmd, &poll_list);
    3138                 :        101 :     exiting = latch_is_set(&pmd->exit_latch);
    3139                 :            :     /* Signal here to make sure the pmd finishes
    3140                 :            :      * reloading the updated configuration. */
    3141                 :        101 :     dp_netdev_pmd_reload_done(pmd);
    3142                 :            : 
    3143                 :        101 :     emc_cache_uninit(&pmd->flow_cache);
    3144                 :            : 
    3145         [ +  + ]:     260280 :     if (!exiting) {
    3146                 :         70 :         goto reload;
    3147                 :            :     }
    3148                 :            : 
    3149                 :         31 :     free(poll_list);
    3150                 :         31 :     pmd_free_cached_ports(pmd);
    3151                 :         31 :     return NULL;
    3152                 :            : }
    3153                 :            : 
    3154                 :            : static void
    3155                 :       2608 : dp_netdev_disable_upcall(struct dp_netdev *dp)
    3156                 :            :     OVS_ACQUIRES(dp->upcall_rwlock)
    3157                 :            : {
    3158                 :       2608 :     fat_rwlock_wrlock(&dp->upcall_rwlock);
    3159                 :       2608 : }
    3160                 :            : 
    3161                 :            : static void
    3162                 :       2055 : dpif_netdev_disable_upcall(struct dpif *dpif)
    3163                 :            :     OVS_NO_THREAD_SAFETY_ANALYSIS
    3164                 :            : {
    3165                 :       2055 :     struct dp_netdev *dp = get_dp_netdev(dpif);
    3166                 :       2055 :     dp_netdev_disable_upcall(dp);
    3167                 :       2055 : }
    3168                 :            : 
    3169                 :            : static void
    3170                 :       2055 : dp_netdev_enable_upcall(struct dp_netdev *dp)
    3171                 :            :     OVS_RELEASES(dp->upcall_rwlock)
    3172                 :            : {
    3173                 :       2055 :     fat_rwlock_unlock(&dp->upcall_rwlock);
    3174                 :       2055 : }
    3175                 :            : 
    3176                 :            : static void
    3177                 :       2055 : dpif_netdev_enable_upcall(struct dpif *dpif)
    3178                 :            :     OVS_NO_THREAD_SAFETY_ANALYSIS
    3179                 :            : {
    3180                 :       2055 :     struct dp_netdev *dp = get_dp_netdev(dpif);
    3181                 :       2055 :     dp_netdev_enable_upcall(dp);
    3182                 :       2055 : }
    3183                 :            : 
    3184                 :            : static void
    3185                 :        101 : dp_netdev_pmd_reload_done(struct dp_netdev_pmd_thread *pmd)
    3186                 :            : {
    3187                 :        101 :     ovs_mutex_lock(&pmd->cond_mutex);
    3188                 :        101 :     xpthread_cond_signal(&pmd->cond);
    3189                 :        101 :     ovs_mutex_unlock(&pmd->cond_mutex);
    3190                 :        101 : }
    3191                 :            : 
    3192                 :            : /* Finds and refs the dp_netdev_pmd_thread on core 'core_id'.  Returns
    3193                 :            :  * the pointer if succeeds, otherwise, NULL.
    3194                 :            :  *
    3195                 :            :  * Caller must unrefs the returned reference.  */
    3196                 :            : static struct dp_netdev_pmd_thread *
    3197                 :     118993 : dp_netdev_get_pmd(struct dp_netdev *dp, unsigned core_id)
    3198                 :            : {
    3199                 :            :     struct dp_netdev_pmd_thread *pmd;
    3200                 :            :     const struct cmap_node *pnode;
    3201                 :            : 
    3202                 :     118993 :     pnode = cmap_find(&dp->poll_threads, hash_int(core_id, 0));
    3203         [ +  + ]:     118993 :     if (!pnode) {
    3204                 :          3 :         return NULL;
    3205                 :            :     }
    3206                 :     118990 :     pmd = CONTAINER_OF(pnode, struct dp_netdev_pmd_thread, node);
    3207                 :            : 
    3208         [ +  - ]:     118990 :     return dp_netdev_pmd_try_ref(pmd) ? pmd : NULL;
    3209                 :            : }
    3210                 :            : 
    3211                 :            : /* Sets the 'struct dp_netdev_pmd_thread' for non-pmd threads. */
    3212                 :            : static void
    3213                 :        567 : dp_netdev_set_nonpmd(struct dp_netdev *dp)
    3214                 :            :     OVS_REQUIRES(dp->port_mutex)
    3215                 :            : {
    3216                 :            :     struct dp_netdev_pmd_thread *non_pmd;
    3217                 :            :     struct dp_netdev_port *port;
    3218                 :            : 
    3219                 :        567 :     non_pmd = xzalloc(sizeof *non_pmd);
    3220                 :        567 :     dp_netdev_configure_pmd(non_pmd, dp, NON_PMD_CORE_ID, OVS_NUMA_UNSPEC);
    3221                 :            : 
    3222 [ +  + ][ -  + ]:        613 :     HMAP_FOR_EACH (port, node, &dp->ports) {
    3223                 :         46 :         dp_netdev_add_port_tx_to_pmd(non_pmd, port);
    3224                 :            :     }
    3225                 :            : 
    3226                 :        567 :     dp_netdev_reload_pmd__(non_pmd);
    3227                 :        567 : }
    3228                 :            : 
    3229                 :            : /* Caller must have valid pointer to 'pmd'. */
    3230                 :            : static bool
    3231                 :     150234 : dp_netdev_pmd_try_ref(struct dp_netdev_pmd_thread *pmd)
    3232                 :            : {
    3233                 :     150234 :     return ovs_refcount_try_ref_rcu(&pmd->ref_cnt);
    3234                 :            : }
    3235                 :            : 
    3236                 :            : static void
    3237                 :     150281 : dp_netdev_pmd_unref(struct dp_netdev_pmd_thread *pmd)
    3238                 :            : {
    3239 [ +  - ][ +  + ]:     150281 :     if (pmd && ovs_refcount_unref(&pmd->ref_cnt) == 1) {
    3240                 :         47 :         ovsrcu_postpone(dp_netdev_destroy_pmd, pmd);
    3241                 :            :     }
    3242                 :     150281 : }
    3243                 :            : 
    3244                 :            : /* Given cmap position 'pos', tries to ref the next node.  If try_ref()
    3245                 :            :  * fails, keeps checking for next node until reaching the end of cmap.
    3246                 :            :  *
    3247                 :            :  * Caller must unrefs the returned reference. */
    3248                 :            : static struct dp_netdev_pmd_thread *
    3249                 :      52273 : dp_netdev_pmd_get_next(struct dp_netdev *dp, struct cmap_position *pos)
    3250                 :            : {
    3251                 :            :     struct dp_netdev_pmd_thread *next;
    3252                 :            : 
    3253                 :            :     do {
    3254                 :            :         struct cmap_node *node;
    3255                 :            : 
    3256                 :      52273 :         node = cmap_next_position(&dp->poll_threads, pos);
    3257                 :      52273 :         next = node ? CONTAINER_OF(node, struct dp_netdev_pmd_thread, node)
    3258         [ +  + ]:      52273 :             : NULL;
    3259 [ +  + ][ -  + ]:      52273 :     } while (next && !dp_netdev_pmd_try_ref(next));
    3260                 :            : 
    3261                 :      52273 :     return next;
    3262                 :            : }
    3263                 :            : 
    3264                 :            : /* Configures the 'pmd' based on the input argument. */
    3265                 :            : static void
    3266                 :        620 : dp_netdev_configure_pmd(struct dp_netdev_pmd_thread *pmd, struct dp_netdev *dp,
    3267                 :            :                         unsigned core_id, int numa_id)
    3268                 :            : {
    3269                 :        620 :     pmd->dp = dp;
    3270                 :        620 :     pmd->core_id = core_id;
    3271                 :        620 :     pmd->numa_id = numa_id;
    3272                 :        620 :     pmd->poll_cnt = 0;
    3273                 :            : 
    3274         [ +  + ]:        620 :     atomic_init(&pmd->static_tx_qid,
    3275                 :            :                 (core_id == NON_PMD_CORE_ID)
    3276                 :            :                 ? ovs_numa_get_n_cores()
    3277                 :            :                 : get_n_pmd_threads(dp));
    3278                 :            : 
    3279                 :        620 :     ovs_refcount_init(&pmd->ref_cnt);
    3280                 :        620 :     latch_init(&pmd->exit_latch);
    3281                 :        620 :     atomic_init(&pmd->change_seq, PMD_INITIAL_SEQ);
    3282                 :        620 :     xpthread_cond_init(&pmd->cond, NULL);
    3283                 :        620 :     ovs_mutex_init(&pmd->cond_mutex);
    3284                 :        620 :     ovs_mutex_init(&pmd->flow_mutex);
    3285                 :        620 :     ovs_mutex_init(&pmd->port_mutex);
    3286                 :        620 :     cmap_init(&pmd->flow_table);
    3287                 :        620 :     cmap_init(&pmd->classifiers);
    3288                 :        620 :     pmd->next_optimization = time_msec() + DPCLS_OPTIMIZATION_INTERVAL;
    3289                 :        620 :     ovs_list_init(&pmd->poll_list);
    3290                 :        620 :     hmap_init(&pmd->tx_ports);
    3291                 :        620 :     hmap_init(&pmd->port_cache);
    3292                 :            :     /* init the 'flow_cache' since there is no
    3293                 :            :      * actual thread created for NON_PMD_CORE_ID. */
    3294         [ +  + ]:        620 :     if (core_id == NON_PMD_CORE_ID) {
    3295                 :        567 :         emc_cache_init(&pmd->flow_cache);
    3296                 :            :     }
    3297                 :        620 :     cmap_insert(&dp->poll_threads, CONST_CAST(struct cmap_node *, &pmd->node),
    3298                 :            :                 hash_int(core_id, 0));
    3299                 :        620 : }
    3300                 :            : 
    3301                 :            : static void
    3302                 :         47 : dp_netdev_destroy_pmd(struct dp_netdev_pmd_thread *pmd)
    3303                 :            : {
    3304                 :            :     struct dpcls *cls;
    3305                 :            : 
    3306                 :         47 :     dp_netdev_pmd_flow_flush(pmd);
    3307                 :         47 :     hmap_destroy(&pmd->port_cache);
    3308                 :         47 :     hmap_destroy(&pmd->tx_ports);
    3309                 :            :     /* All flows (including their dpcls_rules) have been deleted already */
    3310 [ +  + ][ +  + ]:         60 :     CMAP_FOR_EACH (cls, node, &pmd->classifiers) {
    3311                 :         13 :         dpcls_destroy(cls);
    3312                 :            :     }
    3313                 :         47 :     cmap_destroy(&pmd->classifiers);
    3314                 :         47 :     cmap_destroy(&pmd->flow_table);
    3315                 :         47 :     ovs_mutex_destroy(&pmd->flow_mutex);
    3316                 :         47 :     latch_destroy(&pmd->exit_latch);
    3317                 :         47 :     xpthread_cond_destroy(&pmd->cond);
    3318                 :         47 :     ovs_mutex_destroy(&pmd->cond_mutex);
    3319                 :         47 :     ovs_mutex_destroy(&pmd->port_mutex);
    3320                 :         47 :     free(pmd);
    3321                 :         47 : }
    3322                 :            : 
    3323                 :            : /* Stops the pmd thread, removes it from the 'dp->poll_threads',
    3324                 :            :  * and unrefs the struct. */
    3325                 :            : static void
    3326                 :         47 : dp_netdev_del_pmd(struct dp_netdev *dp, struct dp_netdev_pmd_thread *pmd)
    3327                 :            : {
    3328                 :            :     /* NON_PMD_CORE_ID doesn't have a thread, so we don't have to synchronize,
    3329                 :            :      * but extra cleanup is necessary */
    3330         [ +  + ]:         47 :     if (pmd->core_id == NON_PMD_CORE_ID) {
    3331                 :         16 :         emc_cache_uninit(&pmd->flow_cache);
    3332                 :         16 :         pmd_free_cached_ports(pmd);
    3333                 :            :     } else {
    3334                 :         31 :         latch_set(&pmd->exit_latch);
    3335                 :         31 :         dp_netdev_reload_pmd__(pmd);
    3336                 :         31 :         ovs_numa_unpin_core(pmd->core_id);
    3337                 :         31 :         xpthread_join(pmd->thread, NULL);
    3338                 :            :     }
    3339                 :            : 
    3340                 :         47 :     dp_netdev_pmd_clear_ports(pmd);
    3341                 :            : 
    3342                 :            :     /* Purges the 'pmd''s flows after stopping the thread, but before
    3343                 :            :      * destroying the flows, so that the flow stats can be collected. */
    3344         [ +  + ]:         47 :     if (dp->dp_purge_cb) {
    3345                 :         45 :         dp->dp_purge_cb(dp->dp_purge_aux, pmd->core_id);
    3346                 :            :     }
    3347                 :         47 :     cmap_remove(&pmd->dp->poll_threads, &pmd->node, hash_int(pmd->core_id, 0));
    3348                 :         47 :     dp_netdev_pmd_unref(pmd);
    3349                 :         47 : }
    3350                 :            : 
    3351                 :            : /* Destroys all pmd threads. */
    3352                 :            : static void
    3353                 :         16 : dp_netdev_destroy_all_pmds(struct dp_netdev *dp)
    3354                 :            : {
    3355                 :            :     struct dp_netdev_pmd_thread *pmd;
    3356                 :            :     struct dp_netdev_pmd_thread **pmd_list;
    3357                 :         16 :     size_t k = 0, n_pmds;
    3358                 :            : 
    3359                 :         16 :     n_pmds = cmap_count(&dp->poll_threads);
    3360                 :         16 :     pmd_list = xcalloc(n_pmds, sizeof *pmd_list);
    3361                 :            : 
    3362 [ +  + ][ +  + ]:         62 :     CMAP_FOR_EACH (pmd, node, &dp->poll_threads) {
    3363                 :            :         /* We cannot call dp_netdev_del_pmd(), since it alters
    3364                 :            :          * 'dp->poll_threads' (while we're iterating it) and it
    3365                 :            :          * might quiesce. */
    3366         [ -  + ]:         46 :         ovs_assert(k < n_pmds);
    3367                 :         46 :         pmd_list[k++] = pmd;
    3368                 :            :     }
    3369                 :            : 
    3370         [ +  + ]:         62 :     for (size_t i = 0; i < k; i++) {
    3371                 :         46 :         dp_netdev_del_pmd(dp, pmd_list[i]);
    3372                 :            :     }
    3373                 :         16 :     free(pmd_list);
    3374                 :         16 : }
    3375                 :            : 
    3376                 :            : /* Deletes all pmd threads on numa node 'numa_id' and
    3377                 :            :  * fixes static_tx_qids of other threads to keep them sequential. */
    3378                 :            : static void
    3379                 :          1 : dp_netdev_del_pmds_on_numa(struct dp_netdev *dp, int numa_id)
    3380                 :            : {
    3381                 :            :     struct dp_netdev_pmd_thread *pmd;
    3382                 :            :     int n_pmds_on_numa, n_pmds;
    3383                 :          1 :     int *free_idx, k = 0;
    3384                 :            :     struct dp_netdev_pmd_thread **pmd_list;
    3385                 :            : 
    3386                 :          1 :     n_pmds_on_numa = get_n_pmd_threads_on_numa(dp, numa_id);
    3387                 :          1 :     free_idx = xcalloc(n_pmds_on_numa, sizeof *free_idx);
    3388                 :          1 :     pmd_list = xcalloc(n_pmds_on_numa, sizeof *pmd_list);
    3389                 :            : 
    3390 [ +  + ][ +  + ]:          3 :     CMAP_FOR_EACH (pmd, node, &dp->poll_threads) {
    3391                 :            :         /* We cannot call dp_netdev_del_pmd(), since it alters
    3392                 :            :          * 'dp->poll_threads' (while we're iterating it) and it
    3393                 :            :          * might quiesce. */
    3394         [ +  + ]:          2 :         if (pmd->numa_id == numa_id) {
    3395                 :          1 :             atomic_read_relaxed(&pmd->static_tx_qid, &free_idx[k]);
    3396                 :          1 :             pmd_list[k] = pmd;
    3397         [ -  + ]:          1 :             ovs_assert(k < n_pmds_on_numa);
    3398                 :          1 :             k++;
    3399                 :            :         }
    3400                 :            :     }
    3401                 :            : 
    3402         [ +  + ]:          2 :     for (int i = 0; i < k; i++) {
    3403                 :          1 :         dp_netdev_del_pmd(dp, pmd_list[i]);
    3404                 :            :     }
    3405                 :            : 
    3406                 :          1 :     n_pmds = get_n_pmd_threads(dp);
    3407 [ +  + ][ +  + ]:          2 :     CMAP_FOR_EACH (pmd, node, &dp->poll_threads) {
    3408                 :            :         int old_tx_qid;
    3409                 :            : 
    3410                 :          1 :         atomic_read_relaxed(&pmd->static_tx_qid, &old_tx_qid);
    3411                 :            : 
    3412         [ +  - ]:          1 :         if (old_tx_qid >= n_pmds) {
    3413                 :          1 :             int new_tx_qid = free_idx[--k];
    3414                 :            : 
    3415                 :          1 :             atomic_store_relaxed(&pmd->static_tx_qid, new_tx_qid);
    3416                 :            :         }
    3417                 :            :     }
    3418                 :            : 
    3419                 :          1 :     free(pmd_list);
    3420                 :          1 :     free(free_idx);
    3421                 :          1 : }
    3422                 :            : 
    3423                 :            : /* Deletes all rx queues from pmd->poll_list and all the ports from
    3424                 :            :  * pmd->tx_ports. */
    3425                 :            : static void
    3426                 :         47 : dp_netdev_pmd_clear_ports(struct dp_netdev_pmd_thread *pmd)
    3427                 :            : {
    3428                 :            :     struct rxq_poll *poll;
    3429                 :            :     struct tx_port *port;
    3430                 :            : 
    3431                 :         47 :     ovs_mutex_lock(&pmd->port_mutex);
    3432         [ +  + ]:         92 :     LIST_FOR_EACH_POP (poll, node, &pmd->poll_list) {
    3433                 :         45 :         free(poll);
    3434                 :            :     }
    3435                 :         47 :     pmd->poll_cnt = 0;
    3436 [ +  + ][ -  + ]:        192 :     HMAP_FOR_EACH_POP (port, node, &pmd->tx_ports) {
                 [ +  + ]
    3437                 :        145 :         free(port);
    3438                 :            :     }
    3439                 :         47 :     ovs_mutex_unlock(&pmd->port_mutex);
    3440                 :         47 : }
    3441                 :            : 
    3442                 :            : static struct tx_port *
    3443                 :      19325 : tx_port_lookup(const struct hmap *hmap, odp_port_t port_no)
    3444                 :            : {
    3445                 :            :     struct tx_port *tx;
    3446                 :            : 
    3447 [ +  + ][ -  + ]:      29435 :     HMAP_FOR_EACH_IN_BUCKET (tx, node, hash_port_no(port_no), hmap) {
    3448         [ +  + ]:      28884 :         if (tx->port->port_no == port_no) {
    3449                 :      18774 :             return tx;
    3450                 :            :         }
    3451                 :            :     }
    3452                 :            : 
    3453                 :        551 :     return NULL;
    3454                 :            : }
    3455                 :            : 
    3456                 :            : /* Deletes all rx queues of 'port' from 'poll_list', and the 'port' from
    3457                 :            :  * 'tx_ports' of 'pmd' thread.  Returns true if 'port' was found in 'pmd'
    3458                 :            :  * (therefore a restart is required). */
    3459                 :            : static bool
    3460                 :        335 : dp_netdev_del_port_from_pmd__(struct dp_netdev_port *port,
    3461                 :            :                               struct dp_netdev_pmd_thread *pmd)
    3462                 :            : {
    3463                 :            :     struct rxq_poll *poll, *next;
    3464                 :            :     struct tx_port *tx;
    3465                 :        335 :     bool found = false;
    3466                 :            : 
    3467                 :        335 :     ovs_mutex_lock(&pmd->port_mutex);
    3468 [ +  + ][ +  + ]:        336 :     LIST_FOR_EACH_SAFE (poll, next, node, &pmd->poll_list) {
    3469         [ +  - ]:          1 :         if (poll->port == port) {
    3470                 :          1 :             found = true;
    3471                 :          1 :             ovs_list_remove(&poll->node);
    3472                 :          1 :             pmd->poll_cnt--;
    3473                 :          1 :             free(poll);
    3474                 :            :         }
    3475                 :            :     }
    3476                 :            : 
    3477                 :        335 :     tx = tx_port_lookup(&pmd->tx_ports, port->port_no);
    3478         [ +  - ]:        335 :     if (tx) {
    3479                 :        335 :         hmap_remove(&pmd->tx_ports, &tx->node);
    3480                 :        335 :         free(tx);
    3481                 :        335 :         found = true;
    3482                 :            :     }
    3483                 :        335 :     ovs_mutex_unlock(&pmd->port_mutex);
    3484                 :            : 
    3485                 :        335 :     return found;
    3486                 :            : }
    3487                 :            : 
    3488                 :            : /* Deletes 'port' from the 'poll_list' and from the 'tx_ports' of all the pmd
    3489                 :            :  * threads.  The pmd threads that need to be restarted are inserted in
    3490                 :            :  * 'to_reload'. */
    3491                 :            : static void
    3492                 :        336 : dp_netdev_del_port_from_all_pmds__(struct dp_netdev *dp,
    3493                 :            :                                    struct dp_netdev_port *port,
    3494                 :            :                                    struct hmapx *to_reload)
    3495                 :            : {
    3496                 :            :     struct dp_netdev_pmd_thread *pmd;
    3497                 :            : 
    3498 [ +  + ][ +  + ]:        671 :     CMAP_FOR_EACH (pmd, node, &dp->poll_threads) {
    3499                 :            :         bool found;
    3500                 :            : 
    3501                 :        335 :         found = dp_netdev_del_port_from_pmd__(port, pmd);
    3502                 :            : 
    3503         [ +  - ]:        335 :         if (found) {
    3504                 :        335 :             hmapx_add(to_reload, pmd);
    3505                 :            :         }
    3506                 :            :     }
    3507                 :        336 : }
    3508                 :            : 
    3509                 :            : /* Deletes 'port' from the 'poll_list' and from the 'tx_ports' of all the pmd
    3510                 :            :  * threads. Reloads the threads if needed. */
    3511                 :            : static void
    3512                 :        336 : dp_netdev_del_port_from_all_pmds(struct dp_netdev *dp,
    3513                 :            :                                  struct dp_netdev_port *port)
    3514                 :            : {
    3515                 :            :     struct dp_netdev_pmd_thread *pmd;
    3516                 :        336 :     struct hmapx to_reload = HMAPX_INITIALIZER(&to_reload);
    3517                 :            :     struct hmapx_node *node;
    3518                 :            : 
    3519                 :        336 :     dp_netdev_del_port_from_all_pmds__(dp, port, &to_reload);
    3520                 :            : 
    3521 [ +  + ][ -  + ]:        671 :     HMAPX_FOR_EACH (node, &to_reload) {
    3522                 :        335 :         pmd = (struct dp_netdev_pmd_thread *) node->data;
    3523                 :        335 :         dp_netdev_reload_pmd__(pmd);
    3524                 :            :     }
    3525                 :            : 
    3526                 :        336 :     hmapx_destroy(&to_reload);
    3527                 :        336 : }
    3528                 :            : 
    3529                 :            : 
    3530                 :            : /* Returns non-isolated PMD thread from this numa node with fewer
    3531                 :            :  * rx queues to poll. Returns NULL if there is no non-isolated  PMD threads
    3532                 :            :  * on this numa node. Can be called safely only by main thread. */
    3533                 :            : static struct dp_netdev_pmd_thread *
    3534                 :         96 : dp_netdev_less_loaded_pmd_on_numa(struct dp_netdev *dp, int numa_id)
    3535                 :            : {
    3536                 :         96 :     int min_cnt = -1;
    3537                 :         96 :     struct dp_netdev_pmd_thread *pmd, *res = NULL;
    3538                 :            : 
    3539 [ +  + ][ +  + ]:        337 :     CMAP_FOR_EACH (pmd, node, &dp->poll_threads) {
    3540 [ +  + ][ +  + ]:        241 :         if (!pmd->isolated && pmd->numa_id == numa_id
    3541 [ +  + ][ +  + ]:        138 :             && (min_cnt > pmd->poll_cnt || res == NULL)) {
    3542                 :        106 :             min_cnt = pmd->poll_cnt;
    3543                 :        106 :             res = pmd;
    3544                 :            :         }
    3545                 :            :     }
    3546                 :            : 
    3547                 :         96 :     return res;
    3548                 :            : }
    3549                 :            : 
    3550                 :            : /* Adds rx queue to poll_list of PMD thread. */
    3551                 :            : static void
    3552                 :        102 : dp_netdev_add_rxq_to_pmd(struct dp_netdev_pmd_thread *pmd,
    3553                 :            :                          struct dp_netdev_port *port, struct netdev_rxq *rx)
    3554                 :            :     OVS_REQUIRES(pmd->port_mutex)
    3555                 :            : {
    3556                 :        102 :     struct rxq_poll *poll = xmalloc(sizeof *poll);
    3557                 :            : 
    3558                 :        102 :     poll->port = port;
    3559                 :        102 :     poll->rx = rx;
    3560                 :            : 
    3561                 :        102 :     ovs_list_push_back(&pmd->poll_list, &poll->node);
    3562                 :        102 :     pmd->poll_cnt++;
    3563                 :        102 : }
    3564                 :            : 
    3565                 :            : /* Add 'port' to the tx port cache of 'pmd', which must be reloaded for the
    3566                 :            :  * changes to take effect. */
    3567                 :            : static void
    3568                 :       2689 : dp_netdev_add_port_tx_to_pmd(struct dp_netdev_pmd_thread *pmd,
    3569                 :            :                              struct dp_netdev_port *port)
    3570                 :            : {
    3571                 :       2689 :     struct tx_port *tx = xzalloc(sizeof *tx);
    3572                 :            : 
    3573                 :       2689 :     tx->port = port;
    3574                 :       2689 :     tx->qid = -1;
    3575                 :            : 
    3576                 :       2689 :     ovs_mutex_lock(&pmd->port_mutex);
    3577                 :       2689 :     hmap_insert(&pmd->tx_ports, &tx->node, hash_port_no(tx->port->port_no));
    3578                 :       2689 :     ovs_mutex_unlock(&pmd->port_mutex);
    3579                 :       2689 : }
    3580                 :            : 
    3581                 :            : /* Distribute all {pinned|non-pinned} rx queues of 'port' between PMD
    3582                 :            :  * threads in 'dp'. The pmd threads that need to be restarted are inserted
    3583                 :            :  * in 'to_reload'. PMD threads with pinned queues marked as isolated. */
    3584                 :            : static void
    3585                 :       2551 : dp_netdev_add_port_rx_to_pmds(struct dp_netdev *dp,
    3586                 :            :                               struct dp_netdev_port *port,
    3587                 :            :                               struct hmapx *to_reload, bool pinned)
    3588                 :            : {
    3589                 :       2551 :     int numa_id = netdev_get_numa_id(port->netdev);
    3590                 :            :     struct dp_netdev_pmd_thread *pmd;
    3591                 :            :     int i;
    3592                 :            : 
    3593         [ +  + ]:       2551 :     if (!netdev_is_pmd(port->netdev)) {
    3594                 :       2488 :         return;
    3595                 :            :     }
    3596                 :            : 
    3597         [ +  + ]:        225 :     for (i = 0; i < port->n_rxq; i++) {
    3598         [ +  + ]:        162 :         if (pinned) {
    3599         [ +  + ]:         57 :             if (port->rxqs[i].core_id == -1) {
    3600                 :         48 :                 continue;
    3601                 :            :             }
    3602                 :          9 :             pmd = dp_netdev_get_pmd(dp, port->rxqs[i].core_id);
    3603         [ +  + ]:          9 :             if (!pmd) {
    3604         [ +  - ]:          3 :                 VLOG_WARN("There is no PMD thread on core %d. "
    3605                 :            :                           "Queue %d on port \'%s\' will not be polled.",
    3606                 :            :                           port->rxqs[i].core_id, i,
    3607                 :            :                           netdev_get_name(port->netdev));
    3608                 :          3 :                 continue;
    3609                 :            :             }
    3610                 :          6 :             pmd->isolated = true;
    3611                 :          6 :             dp_netdev_pmd_unref(pmd);
    3612                 :            :         } else {
    3613         [ +  + ]:        105 :             if (port->rxqs[i].core_id != -1) {
    3614                 :          9 :                 continue;
    3615                 :            :             }
    3616                 :         96 :             pmd = dp_netdev_less_loaded_pmd_on_numa(dp, numa_id);
    3617         [ -  + ]:         96 :             if (!pmd) {
    3618         [ #  # ]:          0 :                 VLOG_WARN("There's no available pmd thread on numa node %d",
    3619                 :            :                           numa_id);
    3620                 :          0 :                 break;
    3621                 :            :             }
    3622                 :            :         }
    3623                 :            : 
    3624                 :        102 :         ovs_mutex_lock(&pmd->port_mutex);
    3625                 :        102 :         dp_netdev_add_rxq_to_pmd(pmd, port, port->rxqs[i].rxq);
    3626                 :        102 :         ovs_mutex_unlock(&pmd->port_mutex);
    3627                 :            : 
    3628                 :        102 :         hmapx_add(to_reload, pmd);
    3629                 :            :     }
    3630                 :            : }
    3631                 :            : 
    3632                 :            : /* Distributes all non-pinned rx queues of 'port' between all PMD threads
    3633                 :            :  * in 'dp' and inserts 'port' in the PMD threads 'tx_ports'. The pmd threads
    3634                 :            :  * that need to be restarted are inserted in 'to_reload'. */
    3635                 :            : static void
    3636                 :       2459 : dp_netdev_add_port_to_pmds__(struct dp_netdev *dp, struct dp_netdev_port *port,
    3637                 :            :                              struct hmapx *to_reload)
    3638                 :            : {
    3639                 :            :     struct dp_netdev_pmd_thread *pmd;
    3640                 :            : 
    3641                 :       2459 :     dp_netdev_add_port_rx_to_pmds(dp, port, to_reload, false);
    3642                 :            : 
    3643 [ +  + ][ +  + ]:       4966 :     CMAP_FOR_EACH (pmd, node, &dp->poll_threads) {
    3644                 :       2507 :         dp_netdev_add_port_tx_to_pmd(pmd, port);
    3645                 :       2507 :         hmapx_add(to_reload, pmd);
    3646                 :            :     }
    3647                 :       2459 : }
    3648                 :            : 
    3649                 :            : /* Distributes all non-pinned rx queues of 'port' between all PMD threads
    3650                 :            :  * in 'dp', inserts 'port' in the PMD threads 'tx_ports' and reloads them,
    3651                 :            :  * if needed. */
    3652                 :            : static void
    3653                 :       2459 : dp_netdev_add_port_to_pmds(struct dp_netdev *dp, struct dp_netdev_port *port)
    3654                 :            : {
    3655                 :            :     struct dp_netdev_pmd_thread *pmd;
    3656                 :       2459 :     struct hmapx to_reload = HMAPX_INITIALIZER(&to_reload);
    3657                 :            :     struct hmapx_node *node;
    3658                 :            : 
    3659                 :       2459 :     dp_netdev_add_port_to_pmds__(dp, port, &to_reload);
    3660                 :            : 
    3661 [ +  + ][ -  + ]:       4966 :     HMAPX_FOR_EACH (node, &to_reload) {
    3662                 :       2507 :         pmd = (struct dp_netdev_pmd_thread *) node->data;
    3663                 :       2507 :         dp_netdev_reload_pmd__(pmd);
    3664                 :            :     }
    3665                 :            : 
    3666                 :       2459 :     hmapx_destroy(&to_reload);
    3667                 :       2459 : }
    3668                 :            : 
    3669                 :            : /* Starts pmd threads for the numa node 'numa_id', if not already started.
    3670                 :            :  * The function takes care of filling the threads tx port cache. */
    3671                 :            : static void
    3672                 :         47 : dp_netdev_set_pmds_on_numa(struct dp_netdev *dp, int numa_id)
    3673                 :            :     OVS_REQUIRES(dp->port_mutex)
    3674                 :            : {
    3675                 :            :     int n_pmds;
    3676                 :            : 
    3677         [ -  + ]:         47 :     if (!ovs_numa_numa_id_is_valid(numa_id)) {
    3678         [ #  # ]:          0 :         VLOG_WARN("Cannot create pmd threads due to numa id (%d) invalid",
    3679                 :            :                   numa_id);
    3680                 :          0 :         return;
    3681                 :            :     }
    3682                 :            : 
    3683                 :         47 :     n_pmds = get_n_pmd_threads_on_numa(dp, numa_id);
    3684                 :            : 
    3685                 :            :     /* If there are already pmd threads created for the numa node
    3686                 :            :      * in which 'netdev' is on, do nothing.  Else, creates the
    3687                 :            :      * pmd threads for the numa node. */
    3688         [ +  + ]:         47 :     if (!n_pmds) {
    3689                 :            :         int can_have, n_unpinned, i;
    3690                 :            : 
    3691                 :         34 :         n_unpinned = ovs_numa_get_n_unpinned_cores_on_numa(numa_id);
    3692         [ -  + ]:         34 :         if (!n_unpinned) {
    3693         [ #  # ]:          0 :             VLOG_WARN("Cannot create pmd threads due to out of unpinned "
    3694                 :            :                       "cores on numa node %d", numa_id);
    3695                 :          0 :             return;
    3696                 :            :         }
    3697                 :            : 
    3698                 :            :         /* If cpu mask is specified, uses all unpinned cores, otherwise
    3699                 :            :          * tries creating NR_PMD_THREADS pmd threads. */
    3700         [ +  + ]:         34 :         can_have = dp->pmd_cmask ? n_unpinned : MIN(n_unpinned, NR_PMD_THREADS);
    3701         [ +  + ]:         87 :         for (i = 0; i < can_have; i++) {
    3702                 :         53 :             unsigned core_id = ovs_numa_get_unpinned_core_on_numa(numa_id);
    3703                 :         53 :             struct dp_netdev_pmd_thread *pmd = xzalloc(sizeof *pmd);
    3704                 :            :             struct dp_netdev_port *port;
    3705                 :            : 
    3706                 :         53 :             dp_netdev_configure_pmd(pmd, dp, core_id, numa_id);
    3707                 :            : 
    3708 [ +  + ][ -  + ]:        189 :             HMAP_FOR_EACH (port, node, &dp->ports) {
    3709                 :        136 :                 dp_netdev_add_port_tx_to_pmd(pmd, port);
    3710                 :            :             }
    3711                 :            : 
    3712                 :         53 :             pmd->thread = ovs_thread_create("pmd", pmd_thread_main, pmd);
    3713                 :            :         }
    3714         [ +  - ]:         34 :         VLOG_INFO("Created %d pmd threads on numa node %d", can_have, numa_id);
    3715                 :            :     }
    3716                 :            : }
    3717                 :            : 
    3718                 :            : 
    3719                 :            : /* Called after pmd threads config change.  Restarts pmd threads with
    3720                 :            :  * new configuration. */
    3721                 :            : static void
    3722                 :         14 : dp_netdev_reset_pmd_threads(struct dp_netdev *dp)
    3723                 :            :     OVS_REQUIRES(dp->port_mutex)
    3724                 :            : {
    3725                 :         14 :     struct hmapx to_reload = HMAPX_INITIALIZER(&to_reload);
    3726                 :            :     struct dp_netdev_pmd_thread *pmd;
    3727                 :            :     struct dp_netdev_port *port;
    3728                 :            :     struct hmapx_node *node;
    3729                 :            : 
    3730 [ +  + ][ -  + ]:         60 :     HMAP_FOR_EACH (port, node, &dp->ports) {
    3731         [ +  + ]:         46 :         if (netdev_is_pmd(port->netdev)) {
    3732                 :         16 :             int numa_id = netdev_get_numa_id(port->netdev);
    3733                 :            : 
    3734                 :         16 :             dp_netdev_set_pmds_on_numa(dp, numa_id);
    3735                 :            :         }
    3736                 :            :         /* Distribute only pinned rx queues first to mark threads as isolated */
    3737                 :         46 :         dp_netdev_add_port_rx_to_pmds(dp, port, &to_reload, true);
    3738                 :            :     }
    3739                 :            : 
    3740                 :            :     /* Distribute remaining non-pinned rx queues to non-isolated PMD threads. */
    3741 [ +  + ][ -  + ]:         60 :     HMAP_FOR_EACH (port, node, &dp->ports) {
    3742                 :         46 :         dp_netdev_add_port_rx_to_pmds(dp, port, &to_reload, false);
    3743                 :            :     }
    3744                 :            : 
    3745 [ +  + ][ -  + ]:         35 :     HMAPX_FOR_EACH (node, &to_reload) {
    3746                 :         21 :         pmd = (struct dp_netdev_pmd_thread *) node->data;
    3747                 :         21 :         dp_netdev_reload_pmd__(pmd);
    3748                 :            :     }
    3749                 :            : 
    3750                 :         14 :     hmapx_destroy(&to_reload);
    3751                 :         14 : }
    3752                 :            : 
    3753                 :            : static char *
    3754                 :        551 : dpif_netdev_get_datapath_version(void)
    3755                 :            : {
    3756                 :        551 :      return xstrdup("<built-in>");
    3757                 :            : }
    3758                 :            : 
    3759                 :            : static void
    3760                 :       9245 : dp_netdev_flow_used(struct dp_netdev_flow *netdev_flow, int cnt, int size,
    3761                 :            :                     uint16_t tcp_flags, long long now)
    3762                 :            : {
    3763                 :            :     uint16_t flags;
    3764                 :            : 
    3765                 :       9245 :     atomic_store_relaxed(&netdev_flow->stats.used, now);
    3766                 :       9245 :     non_atomic_ullong_add(&netdev_flow->stats.packet_count, cnt);
    3767                 :       9245 :     non_atomic_ullong_add(&netdev_flow->stats.byte_count, size);
    3768                 :       9245 :     atomic_read_relaxed(&netdev_flow->stats.tcp_flags, &flags);
    3769                 :       9245 :     flags |= tcp_flags;
    3770                 :       9245 :     atomic_store_relaxed(&netdev_flow->stats.tcp_flags, flags);
    3771                 :       9245 : }
    3772                 :            : 
    3773                 :            : static void
    3774                 :      63609 : dp_netdev_count_packet(struct dp_netdev_pmd_thread *pmd,
    3775                 :            :                        enum dp_stat_type type, int cnt)
    3776                 :            : {
    3777                 :      63609 :     non_atomic_ullong_add(&pmd->stats.n[type], cnt);
    3778                 :      63609 : }
    3779                 :            : 
    3780                 :            : static int
    3781                 :       6182 : dp_netdev_upcall(struct dp_netdev_pmd_thread *pmd, struct dp_packet *packet_,
    3782                 :            :                  struct flow *flow, struct flow_wildcards *wc, ovs_u128 *ufid,
    3783                 :            :                  enum dpif_upcall_type type, const struct nlattr *userdata,
    3784                 :            :                  struct ofpbuf *actions, struct ofpbuf *put_actions)
    3785                 :            : {
    3786                 :       6182 :     struct dp_netdev *dp = pmd->dp;
    3787                 :            :     struct flow_tnl orig_tunnel;
    3788                 :            :     int err;
    3789                 :            : 
    3790         [ -  + ]:       6182 :     if (OVS_UNLIKELY(!dp->upcall_cb)) {
    3791                 :          0 :         return ENODEV;
    3792                 :            :     }
    3793                 :            : 
    3794                 :            :     /* Upcall processing expects the Geneve options to be in the translated
    3795                 :            :      * format but we need to retain the raw format for datapath use. */
    3796                 :       6182 :     orig_tunnel.flags = flow->tunnel.flags;
    3797         [ +  + ]:       6182 :     if (flow->tunnel.flags & FLOW_TNL_F_UDPIF) {
    3798                 :        798 :         orig_tunnel.metadata.present.len = flow->tunnel.metadata.present.len;
    3799                 :        798 :         memcpy(orig_tunnel.metadata.opts.gnv, flow->tunnel.metadata.opts.gnv,
    3800                 :        798 :                flow->tunnel.metadata.present.len);
    3801                 :        798 :         err = tun_metadata_from_geneve_udpif(&orig_tunnel, &orig_tunnel,
    3802                 :            :                                              &flow->tunnel);
    3803         [ -  + ]:        798 :         if (err) {
    3804                 :          0 :             return err;
    3805                 :            :         }
    3806                 :            :     }
    3807                 :            : 
    3808         [ +  + ]:       6182 :     if (OVS_UNLIKELY(!VLOG_DROP_DBG(&upcall_rl))) {
    3809                 :        204 :         struct ds ds = DS_EMPTY_INITIALIZER;
    3810                 :            :         char *packet_str;
    3811                 :            :         struct ofpbuf key;
    3812                 :        408 :         struct odp_flow_key_parms odp_parms = {
    3813                 :            :             .flow = flow,
    3814                 :        204 :             .mask = &wc->masks,
    3815                 :            :             .support = dp_netdev_support,
    3816                 :            :         };
    3817                 :            : 
    3818                 :        204 :         ofpbuf_init(&key, 0);
    3819                 :        204 :         odp_flow_key_from_flow(&odp_parms, &key);
    3820                 :        204 :         packet_str = ofp_packet_to_string(dp_packet_data(packet_),
    3821                 :        204 :                                           dp_packet_size(packet_));
    3822                 :            : 
    3823                 :        204 :         odp_flow_key_format(key.data, key.size, &ds);
    3824                 :            : 
    3825         [ +  - ]:        204 :         VLOG_DBG("%s: %s upcall:\n%s\n%s", dp->name,
    3826                 :            :                  dpif_upcall_type_to_string(type), ds_cstr(&ds), packet_str);
    3827                 :            : 
    3828                 :        204 :         ofpbuf_uninit(&key);
    3829                 :        204 :         free(packet_str);
    3830                 :            : 
    3831                 :        204 :         ds_destroy(&ds);
    3832                 :            :     }
    3833                 :            : 
    3834                 :       6182 :     err = dp->upcall_cb(packet_, flow, ufid, pmd->core_id, type, userdata,
    3835                 :            :                         actions, wc, put_actions, dp->upcall_aux);
    3836 [ +  + ][ +  + ]:       6182 :     if (err && err != ENOSPC) {
    3837                 :        610 :         return err;
    3838                 :            :     }
    3839                 :            : 
    3840                 :            :     /* Translate tunnel metadata masks to datapath format. */
    3841         [ +  + ]:       5572 :     if (wc) {
    3842         [ +  + ]:       5372 :         if (wc->masks.tunnel.metadata.present.map) {
    3843                 :            :             struct geneve_opt opts[TLV_TOT_OPT_SIZE /
    3844                 :            :                                    sizeof(struct geneve_opt)];
    3845                 :            : 
    3846         [ +  + ]:       1849 :             if (orig_tunnel.flags & FLOW_TNL_F_UDPIF) {
    3847                 :        798 :                 tun_metadata_to_geneve_udpif_mask(&flow->tunnel,
    3848                 :        798 :                                                   &wc->masks.tunnel,
    3849                 :            :                                                   orig_tunnel.metadata.opts.gnv,
    3850                 :        798 :                                                   orig_tunnel.metadata.present.len,
    3851                 :            :                                                   opts);
    3852                 :            :             } else {
    3853                 :       1051 :                 orig_tunnel.metadata.present.len = 0;
    3854                 :            :             }
    3855                 :            : 
    3856                 :       1849 :             memset(&wc->masks.tunnel.metadata, 0,
    3857                 :            :                    sizeof wc->masks.tunnel.metadata);
    3858                 :       1849 :             memcpy(&wc->masks.tunnel.metadata.opts.gnv, opts,
    3859                 :       1849 :                    orig_tunnel.metadata.present.len);
    3860                 :            :         }
    3861                 :       5372 :         wc->masks.tunnel.metadata.present.len = 0xff;
    3862                 :            :     }
    3863                 :            : 
    3864                 :            :     /* Restore tunnel metadata. We need to use the saved options to ensure
    3865                 :            :      * that any unknown options are not lost. The generated mask will have
    3866                 :            :      * the same structure, matching on types and lengths but wildcarding
    3867                 :            :      * option data we don't care about. */
    3868         [ +  + ]:       5572 :     if (orig_tunnel.flags & FLOW_TNL_F_UDPIF) {
    3869                 :        798 :         memcpy(&flow->tunnel.metadata.opts.gnv, orig_tunnel.metadata.opts.gnv,
    3870                 :        798 :                orig_tunnel.metadata.present.len);
    3871                 :        798 :         flow->tunnel.metadata.present.len = orig_tunnel.metadata.present.len;
    3872                 :        798 :         flow->tunnel.flags |= FLOW_TNL_F_UDPIF;
    3873                 :            :     }
    3874                 :            : 
    3875                 :       6182 :     return err;
    3876                 :            : }
    3877                 :            : 
    3878                 :            : static inline uint32_t
    3879                 :      14617 : dpif_netdev_packet_get_rss_hash(struct dp_packet *packet,
    3880                 :            :                                 const struct miniflow *mf)
    3881                 :            : {
    3882                 :            :     uint32_t hash, recirc_depth;
    3883                 :            : 
    3884         [ +  + ]:      14617 :     if (OVS_LIKELY(dp_packet_rss_valid(packet))) {
    3885                 :       4584 :         hash = dp_packet_get_rss_hash(packet);
    3886                 :            :     } else {
    3887                 :      10033 :         hash = miniflow_hash_5tuple(mf, 0);
    3888                 :      10033 :         dp_packet_set_rss_hash(packet, hash);
    3889                 :            :     }
    3890                 :            : 
    3891                 :            :     /* The RSS hash must account for the recirculation depth to avoid
    3892                 :            :      * collisions in the exact match cache */
    3893                 :      14617 :     recirc_depth = *recirc_depth_get_unsafe();
    3894         [ +  + ]:      14617 :     if (OVS_UNLIKELY(recirc_depth)) {
    3895                 :       4584 :         hash = hash_finish(hash, recirc_depth);
    3896                 :       4584 :         dp_packet_set_rss_hash(packet, hash);
    3897                 :            :     }
    3898                 :      14617 :     return hash;
    3899                 :            : }
    3900                 :            : 
    3901                 :            : struct packet_batch_per_flow {
    3902                 :            :     unsigned int byte_count;
    3903                 :            :     uint16_t tcp_flags;
    3904                 :            :     struct dp_netdev_flow *flow;
    3905                 :            : 
    3906                 :            :     struct dp_packet_batch array;
    3907                 :            : };
    3908                 :            : 
    3909                 :            : static inline void
    3910                 :       9245 : packet_batch_per_flow_update(struct packet_batch_per_flow *batch,
    3911                 :            :                              struct dp_packet *packet,
    3912                 :            :                              const struct miniflow *mf)
    3913                 :            : {
    3914                 :       9245 :     batch->byte_count += dp_packet_size(packet);
    3915                 :       9245 :     batch->tcp_flags |= miniflow_get_tcp_flags(mf);
    3916                 :       9245 :     batch->array.packets[batch->array.count++] = packet;
    3917                 :       9245 : }
    3918                 :            : 
    3919                 :            : static inline void
    3920                 :       9245 : packet_batch_per_flow_init(struct packet_batch_per_flow *batch,
    3921                 :            :                            struct dp_netdev_flow *flow)
    3922                 :            : {
    3923                 :       9245 :     flow->batch = batch;
    3924                 :            : 
    3925                 :       9245 :     batch->flow = flow;
    3926                 :       9245 :     dp_packet_batch_init(&batch->array);
    3927                 :       9245 :     batch->byte_count = 0;
    3928                 :       9245 :     batch->tcp_flags = 0;
    3929                 :       9245 : }
    3930                 :            : 
    3931                 :            : static inline void
    3932                 :       9245 : packet_batch_per_flow_execute(struct packet_batch_per_flow *batch,
    3933                 :            :                               struct dp_netdev_pmd_thread *pmd,
    3934                 :            :                               long long now)
    3935                 :            : {
    3936                 :            :     struct dp_netdev_actions *actions;
    3937                 :       9245 :     struct dp_netdev_flow *flow = batch->flow;
    3938                 :            : 
    3939                 :       9245 :     dp_netdev_flow_used(flow, batch->array.count, batch->byte_count,
    3940                 :       9245 :                         batch->tcp_flags, now);
    3941                 :            : 
    3942                 :       9245 :     actions = dp_netdev_flow_get_actions(flow);
    3943                 :            : 
    3944                 :       9245 :     dp_netdev_execute_actions(pmd, &batch->array, true, &flow->flow,
    3945                 :      18490 :                               actions->actions, actions->size, now);
    3946                 :       9245 : }
    3947                 :            : 
    3948                 :            : static inline void
    3949                 :       9245 : dp_netdev_queue_batches(struct dp_packet *pkt,
    3950                 :            :                         struct dp_netdev_flow *flow, const struct miniflow *mf,
    3951                 :            :                         struct packet_batch_per_flow *batches, size_t *n_batches)
    3952                 :            : {
    3953                 :       9245 :     struct packet_batch_per_flow *batch = flow->batch;
    3954                 :            : 
    3955         [ +  - ]:       9245 :     if (OVS_UNLIKELY(!batch)) {
    3956                 :       9245 :         batch = &batches[(*n_batches)++];
    3957                 :       9245 :         packet_batch_per_flow_init(batch, flow);
    3958                 :            :     }
    3959                 :            : 
    3960                 :       9245 :     packet_batch_per_flow_update(batch, pkt, mf);
    3961                 :       9245 : }
    3962                 :            : 
    3963                 :            : /* Try to process all ('cnt') the 'packets' using only the exact match cache
    3964                 :            :  * 'pmd->flow_cache'. If a flow is not found for a packet 'packets[i]', the
    3965                 :            :  * miniflow is copied into 'keys' and the packet pointer is moved at the
    3966                 :            :  * beginning of the 'packets' array.
    3967                 :            :  *
    3968                 :            :  * The function returns the number of packets that needs to be processed in the
    3969                 :            :  * 'packets' array (they have been moved to the beginning of the vector).
    3970                 :            :  *
    3971                 :            :  * If 'md_is_valid' is false, the metadata in 'packets' is not valid and must be
    3972                 :            :  * initialized by this function using 'port_no'.
    3973                 :            :  */
    3974                 :            : static inline size_t
    3975                 :      14617 : emc_processing(struct dp_netdev_pmd_thread *pmd, struct dp_packet_batch *packets_,
    3976                 :            :                struct netdev_flow_key *keys,
    3977                 :            :                struct packet_batch_per_flow batches[], size_t *n_batches,
    3978                 :            :                bool md_is_valid, odp_port_t port_no)
    3979                 :            : {
    3980                 :      14617 :     struct emc_cache *flow_cache = &pmd->flow_cache;
    3981                 :      14617 :     struct netdev_flow_key *key = &keys[0];
    3982                 :      14617 :     size_t i, n_missed = 0, n_dropped = 0;
    3983                 :      14617 :     struct dp_packet **packets = packets_->packets;
    3984                 :      14617 :     int cnt = packets_->count;
    3985                 :            : 
    3986         [ +  + ]:      29234 :     for (i = 0; i < cnt; i++) {
    3987                 :            :         struct dp_netdev_flow *flow;
    3988                 :      14617 :         struct dp_packet *packet = packets[i];
    3989                 :            : 
    3990         [ -  + ]:      14617 :         if (OVS_UNLIKELY(dp_packet_size(packet) < ETH_HEADER_LEN)) {
    3991                 :          0 :             dp_packet_delete(packet);
    3992                 :          0 :             n_dropped++;
    3993                 :          0 :             continue;
    3994                 :            :         }
    3995                 :            : 
    3996         [ -  + ]:      14617 :         if (i != cnt - 1) {
    3997                 :            :             /* Prefetch next packet data and metadata. */
    3998                 :          0 :             OVS_PREFETCH(dp_packet_data(packets[i+1]));
    3999                 :          0 :             pkt_metadata_prefetch_init(&packets[i+1]->md);
    4000                 :            :         }
    4001                 :            : 
    4002         [ +  + ]:      14617 :         if (!md_is_valid) {
    4003                 :      10033 :             pkt_metadata_init(&packet->md, port_no);
    4004                 :            :         }
    4005                 :      14617 :         miniflow_extract(packet, &key->mf);
    4006                 :      14617 :         key->len = 0; /* Not computed yet. */
    4007                 :      14617 :         key->hash = dpif_netdev_packet_get_rss_hash(packet, &key->mf);
    4008                 :            : 
    4009                 :      14617 :         flow = emc_lookup(flow_cache, key);
    4010         [ +  + ]:      14617 :         if (OVS_LIKELY(flow)) {
    4011                 :       3712 :             dp_netdev_queue_batches(packet, flow, &key->mf, batches,
    4012                 :            :                                     n_batches);
    4013                 :            :         } else {
    4014                 :            :             /* Exact match cache missed. Group missed packets together at
    4015                 :            :              * the beginning of the 'packets' array.  */
    4016                 :      10905 :             packets[n_missed] = packet;
    4017                 :            :             /* 'key[n_missed]' contains the key of the current packet and it
    4018                 :            :              * must be returned to the caller. The next key should be extracted
    4019                 :            :              * to 'keys[n_missed + 1]'. */
    4020                 :      10905 :             key = &keys[++n_missed];
    4021                 :            :         }
    4022                 :            :     }
    4023                 :            : 
    4024                 :      14617 :     dp_netdev_count_packet(pmd, DP_STAT_EXACT_HIT, cnt - n_dropped - n_missed);
    4025                 :            : 
    4026                 :      14617 :     return n_missed;
    4027                 :            : }
    4028                 :            : 
    4029                 :            : static inline void
    4030                 :       5372 : handle_packet_upcall(struct dp_netdev_pmd_thread *pmd, struct dp_packet *packet,
    4031                 :            :                      const struct netdev_flow_key *key,
    4032                 :            :                      struct ofpbuf *actions, struct ofpbuf *put_actions,
    4033                 :            :                      int *lost_cnt, long long now)
    4034                 :            : {
    4035                 :            :     struct ofpbuf *add_actions;
    4036                 :            :     struct dp_packet_batch b;
    4037                 :            :     struct match match;
    4038                 :            :     ovs_u128 ufid;
    4039                 :            :     int error;
    4040                 :            : 
    4041                 :       5372 :     match.tun_md.valid = false;
    4042                 :       5372 :     miniflow_expand(&key->mf, &match.flow);
    4043                 :            : 
    4044                 :       5372 :     ofpbuf_clear(actions);
    4045                 :       5372 :     ofpbuf_clear(put_actions);
    4046                 :            : 
    4047                 :       5372 :     dpif_flow_hash(pmd->dp->dpif, &match.flow, sizeof match.flow, &ufid);
    4048                 :       5372 :     error = dp_netdev_upcall(pmd, packet, &match.flow, &match.wc,
    4049                 :            :                              &ufid, DPIF_UC_MISS, NULL, actions,
    4050                 :            :                              put_actions);
    4051 [ -  + ][ #  # ]:       5372 :     if (OVS_UNLIKELY(error && error != ENOSPC)) {
    4052                 :          0 :         dp_packet_delete(packet);
    4053                 :          0 :         (*lost_cnt)++;
    4054                 :          0 :         return;
    4055                 :            :     }
    4056                 :            : 
    4057                 :            :     /* The Netlink encoding of datapath flow keys cannot express
    4058                 :            :      * wildcarding the presence of a VLAN tag. Instead, a missing VLAN
    4059                 :            :      * tag is interpreted as exact match on the fact that there is no
    4060                 :            :      * VLAN.  Unless we refactor a lot of code that translates between
    4061                 :            :      * Netlink and struct flow representations, we have to do the same
    4062                 :            :      * here. */
    4063         [ +  + ]:       5372 :     if (!match.wc.masks.vlan_tci) {
    4064                 :       1424 :         match.wc.masks.vlan_tci = htons(0xffff);
    4065                 :            :     }
    4066                 :            : 
    4067                 :            :     /* We can't allow the packet batching in the next loop to execute
    4068                 :            :      * the actions.  Otherwise, if there are any slow path actions,
    4069                 :            :      * we'll send the packet up twice. */
    4070                 :       5372 :     packet_batch_init_packet(&b, packet);
    4071                 :       5372 :     dp_netdev_execute_actions(pmd, &b, true, &match.flow,
    4072                 :      10744 :                               actions->data, actions->size, now);
    4073                 :            : 
    4074         [ +  + ]:       5372 :     add_actions = put_actions->size ? put_actions : actions;
    4075         [ +  - ]:       5372 :     if (OVS_LIKELY(error != ENOSPC)) {
    4076                 :            :         struct dp_netdev_flow *netdev_flow;
    4077                 :            : 
    4078                 :            :         /* XXX: There's a race window where a flow covering this packet
    4079                 :            :          * could have already been installed since we last did the flow
    4080                 :            :          * lookup before upcall.  This could be solved by moving the
    4081                 :            :          * mutex lock outside the loop, but that's an awful long time
    4082                 :            :          * to be locking everyone out of making flow installs.  If we
    4083                 :            :          * move to a per-core classifier, it would be reasonable. */
    4084                 :       5372 :         ovs_mutex_lock(&pmd->flow_mutex);
    4085                 :       5372 :         netdev_flow = dp_netdev_pmd_lookup_flow(pmd, key, NULL);
    4086         [ +  - ]:       5372 :         if (OVS_LIKELY(!netdev_flow)) {
    4087                 :       5372 :             netdev_flow = dp_netdev_flow_add(pmd, &match, &ufid,
    4088                 :       5372 :                                              add_actions->data,
    4089                 :       5372 :                                              add_actions->size);
    4090                 :            :         }
    4091                 :       5372 :         ovs_mutex_unlock(&pmd->flow_mutex);
    4092                 :            : 
    4093                 :       5372 :         emc_insert(&pmd->flow_cache, key, netdev_flow);
    4094                 :            :     }
    4095                 :            : }
    4096                 :            : 
    4097                 :            : static inline void
    4098                 :      10905 : fast_path_processing(struct dp_netdev_pmd_thread *pmd,
    4099                 :            :                      struct dp_packet_batch *packets_,
    4100                 :            :                      struct netdev_flow_key *keys,
    4101                 :            :                      struct packet_batch_per_flow batches[], size_t *n_batches,
    4102                 :            :                      odp_port_t in_port,
    4103                 :            :                      long long now)
    4104                 :      10905 : {
    4105                 :      10905 :     int cnt = packets_->count;
    4106                 :            : #if !defined(__CHECKER__) && !defined(_WIN32)
    4107                 :      10905 :     const size_t PKT_ARRAY_SIZE = cnt;
    4108                 :            : #else
    4109                 :            :     /* Sparse or MSVC doesn't like variable length array. */
    4110                 :            :     enum { PKT_ARRAY_SIZE = NETDEV_MAX_BURST };
    4111                 :            : #endif
    4112                 :      10905 :     struct dp_packet **packets = packets_->packets;
    4113                 :            :     struct dpcls *cls;
    4114                 :      10905 :     struct dpcls_rule *rules[PKT_ARRAY_SIZE];
    4115                 :      10905 :     struct dp_netdev *dp = pmd->dp;
    4116                 :      10905 :     struct emc_cache *flow_cache = &pmd->flow_cache;
    4117                 :      10905 :     int miss_cnt = 0, lost_cnt = 0;
    4118                 :      10905 :     int lookup_cnt = 0, add_lookup_cnt;
    4119                 :            :     bool any_miss;
    4120                 :            :     size_t i;
    4121                 :            : 
    4122         [ +  + ]:      21810 :     for (i = 0; i < cnt; i++) {
    4123                 :            :         /* Key length is needed in all the cases, hash computed on demand. */
    4124                 :      10905 :         keys[i].len = netdev_flow_key_size(miniflow_n_values(&keys[i].mf));
    4125                 :            :     }
    4126                 :            :     /* Get the classifier for the in_port */
    4127                 :      10905 :     cls = dp_netdev_pmd_lookup_dpcls(pmd, in_port);
    4128         [ +  + ]:      10905 :     if (OVS_LIKELY(cls)) {
    4129                 :      10440 :         any_miss = !dpcls_lookup(cls, keys, rules, cnt, &lookup_cnt);
    4130                 :            :     } else {
    4131                 :        465 :         any_miss = true;
    4132                 :        465 :         memset(rules, 0, sizeof(rules));
    4133                 :            :     }
    4134 [ +  + ][ +  - ]:      16277 :     if (OVS_UNLIKELY(any_miss) && !fat_rwlock_tryrdlock(&dp->upcall_rwlock)) {
    4135                 :            :         uint64_t actions_stub[512 / 8], slow_stub[512 / 8];
    4136                 :            :         struct ofpbuf actions, put_actions;
    4137                 :            : 
    4138                 :       5372 :         ofpbuf_use_stub(&actions, actions_stub, sizeof actions_stub);
    4139                 :       5372 :         ofpbuf_use_stub(&put_actions, slow_stub, sizeof slow_stub);
    4140                 :            : 
    4141         [ +  + ]:      10744 :         for (i = 0; i < cnt; i++) {
    4142                 :            :             struct dp_netdev_flow *netdev_flow;
    4143                 :            : 
    4144         [ -  + ]:       5372 :             if (OVS_LIKELY(rules[i])) {
    4145                 :          0 :                 continue;
    4146                 :            :             }
    4147                 :            : 
    4148                 :            :             /* It's possible that an earlier slow path execution installed
    4149                 :            :              * a rule covering this flow.  In this case, it's a lot cheaper
    4150                 :            :              * to catch it here than execute a miss. */
    4151                 :       5372 :             netdev_flow = dp_netdev_pmd_lookup_flow(pmd, &keys[i],
    4152                 :            :                                                     &add_lookup_cnt);
    4153         [ -  + ]:       5372 :             if (netdev_flow) {
    4154                 :          0 :                 lookup_cnt += add_lookup_cnt;
    4155                 :          0 :                 rules[i] = &netdev_flow->cr;
    4156                 :          0 :                 continue;
    4157                 :            :             }
    4158                 :            : 
    4159                 :       5372 :             miss_cnt++;
    4160                 :       5372 :             handle_packet_upcall(pmd, packets[i], &keys[i], &actions,
    4161                 :            :                                  &put_actions, &lost_cnt, now);
    4162                 :            :         }
    4163                 :            : 
    4164                 :       5372 :         ofpbuf_uninit(&actions);
    4165                 :       5372 :         ofpbuf_uninit(&put_actions);
    4166                 :       5372 :         fat_rwlock_unlock(&dp->upcall_rwlock);
    4167                 :       5372 :         dp_netdev_count_packet(pmd, DP_STAT_LOST, lost_cnt);
    4168         [ -  + ]:       5533 :     } else if (OVS_UNLIKELY(any_miss)) {
    4169         [ #  # ]:          0 :         for (i = 0; i < cnt; i++) {
    4170         [ #  # ]:          0 :             if (OVS_UNLIKELY(!rules[i])) {
    4171                 :          0 :                 dp_packet_delete(packets[i]);
    4172                 :          0 :                 lost_cnt++;
    4173                 :          0 :                 miss_cnt++;
    4174                 :            :             }
    4175                 :            :         }
    4176                 :            :     }
    4177                 :            : 
    4178         [ +  + ]:      21810 :     for (i = 0; i < cnt; i++) {
    4179                 :      10905 :         struct dp_packet *packet = packets[i];
    4180                 :            :         struct dp_netdev_flow *flow;
    4181                 :            : 
    4182         [ +  + ]:      10905 :         if (OVS_UNLIKELY(!rules[i])) {
    4183                 :       5372 :             continue;
    4184                 :            :         }
    4185                 :            : 
    4186                 :       5533 :         flow = dp_netdev_flow_cast(rules[i]);
    4187                 :            : 
    4188                 :       5533 :         emc_insert(flow_cache, &keys[i], flow);
    4189                 :       5533 :         dp_netdev_queue_batches(packet, flow, &keys[i].mf, batches, n_batches);
    4190                 :            :     }
    4191                 :            : 
    4192                 :      10905 :     dp_netdev_count_packet(pmd, DP_STAT_MASKED_HIT, cnt - miss_cnt);
    4193                 :      10905 :     dp_netdev_count_packet(pmd, DP_STAT_LOOKUP_HIT, lookup_cnt);
    4194                 :      10905 :     dp_netdev_count_packet(pmd, DP_STAT_MISS, miss_cnt);
    4195                 :      10905 :     dp_netdev_count_packet(pmd, DP_STAT_LOST, lost_cnt);
    4196                 :      10905 : }
    4197                 :            : 
    4198                 :            : /* Packets enter the datapath from a port (or from recirculation) here.
    4199                 :            :  *
    4200                 :            :  * For performance reasons a caller may choose not to initialize the metadata
    4201                 :            :  * in 'packets': in this case 'mdinit' is false and this function needs to
    4202                 :            :  * initialize it using 'port_no'.  If the metadata in 'packets' is already
    4203                 :            :  * valid, 'md_is_valid' must be true and 'port_no' will be ignored. */
    4204                 :            : static void
    4205                 :      14617 : dp_netdev_input__(struct dp_netdev_pmd_thread *pmd,
    4206                 :            :                   struct dp_packet_batch *packets,
    4207                 :            :                   bool md_is_valid, odp_port_t port_no)
    4208                 :      14617 : {
    4209                 :      14617 :     int cnt = packets->count;
    4210                 :            : #if !defined(__CHECKER__) && !defined(_WIN32)
    4211                 :      14617 :     const size_t PKT_ARRAY_SIZE = cnt;
    4212                 :            : #else
    4213                 :            :     /* Sparse or MSVC doesn't like variable length array. */
    4214                 :            :     enum { PKT_ARRAY_SIZE = NETDEV_MAX_BURST };
    4215                 :            : #endif
    4216                 :      14617 :     struct netdev_flow_key keys[PKT_ARRAY_SIZE];
    4217                 :      14617 :     struct packet_batch_per_flow batches[PKT_ARRAY_SIZE];
    4218                 :      14617 :     long long now = time_msec();
    4219                 :            :     size_t newcnt, n_batches, i;
    4220                 :            :     odp_port_t in_port;
    4221                 :            : 
    4222                 :      14617 :     n_batches = 0;
    4223                 :      14617 :     newcnt = emc_processing(pmd, packets, keys, batches, &n_batches,
    4224                 :            :                             md_is_valid, port_no);
    4225         [ +  + ]:      14617 :     if (OVS_UNLIKELY(newcnt)) {
    4226                 :      10905 :         packets->count = newcnt;
    4227                 :            :         /* Get ingress port from first packet's metadata. */
    4228                 :      10905 :         in_port = packets->packets[0]->md.in_port.odp_port;
    4229                 :      10905 :         fast_path_processing(pmd, packets, keys, batches, &n_batches, in_port, now);
    4230                 :            :     }
    4231                 :            : 
    4232         [ +  + ]:      23862 :     for (i = 0; i < n_batches; i++) {
    4233                 :       9245 :         batches[i].flow->batch = NULL;
    4234                 :            :     }
    4235                 :            : 
    4236         [ +  + ]:      23862 :     for (i = 0; i < n_batches; i++) {
    4237                 :       9245 :         packet_batch_per_flow_execute(&batches[i], pmd, now);
    4238                 :            :     }
    4239                 :      14617 : }
    4240                 :            : 
    4241                 :            : static void
    4242                 :      10033 : dp_netdev_input(struct dp_netdev_pmd_thread *pmd,
    4243                 :            :                 struct dp_packet_batch *packets,
    4244                 :            :                 odp_port_t port_no)
    4245                 :            : {
    4246                 :      10033 :     dp_netdev_input__(pmd, packets, false, port_no);
    4247                 :      10033 : }
    4248                 :            : 
    4249                 :            : static void
    4250                 :       4584 : dp_netdev_recirculate(struct dp_netdev_pmd_thread *pmd,
    4251                 :            :                       struct dp_packet_batch *packets)
    4252                 :            : {
    4253                 :       4584 :     dp_netdev_input__(pmd, packets, true, 0);
    4254                 :       4584 : }
    4255                 :            : 
    4256                 :            : struct dp_netdev_execute_aux {
    4257                 :            :     struct dp_netdev_pmd_thread *pmd;
    4258                 :            :     long long now;
    4259                 :            :     const struct flow *flow;
    4260                 :            : };
    4261                 :            : 
    4262                 :            : static void
    4263                 :       1102 : dpif_netdev_register_dp_purge_cb(struct dpif *dpif, dp_purge_callback *cb,
    4264                 :            :                                  void *aux)
    4265                 :            : {
    4266                 :       1102 :     struct dp_netdev *dp = get_dp_netdev(dpif);
    4267                 :       1102 :     dp->dp_purge_aux = aux;
    4268                 :       1102 :     dp->dp_purge_cb = cb;
    4269                 :       1102 : }
    4270                 :            : 
    4271                 :            : static void
    4272                 :       1102 : dpif_netdev_register_upcall_cb(struct dpif *dpif, upcall_callback *cb,
    4273                 :            :                                void *aux)
    4274                 :            : {
    4275                 :       1102 :     struct dp_netdev *dp = get_dp_netdev(dpif);
    4276                 :       1102 :     dp->upcall_aux = aux;
    4277                 :       1102 :     dp->upcall_cb = cb;
    4278                 :       1102 : }
    4279                 :            : 
    4280                 :            : static void
    4281                 :     103281 : dpif_netdev_xps_revalidate_pmd(const struct dp_netdev_pmd_thread *pmd,
    4282                 :            :                                long long now, bool purge)
    4283                 :            : {
    4284                 :            :     struct tx_port *tx;
    4285                 :            :     struct dp_netdev_port *port;
    4286                 :            :     long long interval;
    4287                 :            : 
    4288 [ +  + ][ -  + ]:     673320 :     HMAP_FOR_EACH (tx, node, &pmd->port_cache) {
    4289         [ +  + ]:     570039 :         if (!tx->port->dynamic_txqs) {
    4290                 :     568130 :             continue;
    4291                 :            :         }
    4292                 :       1909 :         interval = now - tx->last_used;
    4293 [ +  + ][ +  + ]:       1909 :         if (tx->qid >= 0 && (purge || interval >= XPS_TIMEOUT_MS)) {
                 [ +  + ]
    4294                 :          3 :             port = tx->port;
    4295                 :          3 :             ovs_mutex_lock(&port->txq_used_mutex);
    4296                 :          3 :             port->txq_used[tx->qid]--;
    4297                 :          3 :             ovs_mutex_unlock(&port->txq_used_mutex);
    4298                 :          3 :             tx->qid = -1;
    4299                 :            :         }
    4300                 :            :     }
    4301                 :     103281 : }
    4302                 :            : 
    4303                 :            : static int
    4304                 :         16 : dpif_netdev_xps_get_tx_qid(const struct dp_netdev_pmd_thread *pmd,
    4305                 :            :                            struct tx_port *tx, long long now)
    4306                 :            : {
    4307                 :            :     struct dp_netdev_port *port;
    4308                 :            :     long long interval;
    4309                 :            :     int i, min_cnt, min_qid;
    4310                 :            : 
    4311         [ -  + ]:         16 :     if (OVS_UNLIKELY(!now)) {
    4312                 :          0 :         now = time_msec();
    4313                 :            :     }
    4314                 :            : 
    4315                 :         16 :     interval = now - tx->last_used;
    4316                 :         16 :     tx->last_used = now;
    4317                 :            : 
    4318 [ +  + ][ +  + ]:         16 :     if (OVS_LIKELY(tx->qid >= 0 && interval < XPS_TIMEOUT_MS)) {
    4319                 :          4 :         return tx->qid;
    4320                 :            :     }
    4321                 :            : 
    4322                 :         12 :     port = tx->port;
    4323                 :            : 
    4324                 :         12 :     ovs_mutex_lock(&port->txq_used_mutex);
    4325         [ +  + ]:         12 :     if (tx->qid >= 0) {
    4326                 :          1 :         port->txq_used[tx->qid]--;
    4327                 :          1 :         tx->qid = -1;
    4328                 :            :     }
    4329                 :            : 
    4330                 :         12 :     min_cnt = -1;
    4331                 :         12 :     min_qid = 0;
    4332         [ +  + ]:         24 :     for (i = 0; i < netdev_n_txq(port->netdev); i++) {
    4333 [ -  + ][ #  # ]:         12 :         if (port->txq_used[i] < min_cnt || min_cnt == -1) {
    4334                 :         12 :             min_cnt = port->txq_used[i];
    4335                 :         12 :             min_qid = i;
    4336                 :            :         }
    4337                 :            :     }
    4338                 :            : 
    4339                 :         12 :     port->txq_used[min_qid]++;
    4340                 :         12 :     tx->qid = min_qid;
    4341                 :            : 
    4342                 :         12 :     ovs_mutex_unlock(&port->txq_used_mutex);
    4343                 :            : 
    4344                 :         12 :     dpif_netdev_xps_revalidate_pmd(pmd, now, false);
    4345                 :            : 
    4346         [ +  - ]:         12 :     VLOG_DBG("Core %d: New TX queue ID %d for port \'%s\'.",
    4347                 :            :              pmd->core_id, tx->qid, netdev_get_name(tx->port->netdev));
    4348                 :         12 :     return min_qid;
    4349                 :            : }
    4350                 :            : 
    4351                 :            : static struct tx_port *
    4352                 :      18990 : pmd_tx_port_cache_lookup(const struct dp_netdev_pmd_thread *pmd,
    4353                 :            :                          odp_port_t port_no)
    4354                 :            : {
    4355                 :      18990 :     return tx_port_lookup(&pmd->port_cache, port_no);
    4356                 :            : }
    4357                 :            : 
    4358                 :            : static int
    4359                 :       1927 : push_tnl_action(const struct dp_netdev_pmd_thread *pmd,
    4360                 :            :                 const struct nlattr *attr,
    4361                 :            :                 struct dp_packet_batch *batch)
    4362                 :            : {
    4363                 :            :     struct tx_port *tun_port;
    4364                 :            :     const struct ovs_action_push_tnl *data;
    4365                 :            :     int err;
    4366                 :            : 
    4367                 :       1927 :     data = nl_attr_get(attr);
    4368                 :            : 
    4369                 :       1927 :     tun_port = pmd_tx_port_cache_lookup(pmd, u32_to_odp(data->tnl_port));
    4370         [ -  + ]:       1927 :     if (!tun_port) {
    4371                 :          0 :         err = -EINVAL;
    4372                 :          0 :         goto error;
    4373                 :            :     }
    4374                 :       1927 :     err = netdev_push_header(tun_port->port->netdev, batch, data);
    4375         [ +  - ]:       1927 :     if (!err) {
    4376                 :       1927 :         return 0;
    4377                 :            :     }
    4378                 :            : error:
    4379                 :          0 :     dp_packet_delete_batch(batch, true);
    4380                 :          0 :     return err;
    4381                 :            : }
    4382                 :            : 
    4383                 :            : static void
    4384                 :        810 : dp_execute_userspace_action(struct dp_netdev_pmd_thread *pmd,
    4385                 :            :                             struct dp_packet *packet, bool may_steal,
    4386                 :            :                             struct flow *flow, ovs_u128 *ufid,
    4387                 :            :                             struct ofpbuf *actions,
    4388                 :            :                             const struct nlattr *userdata, long long now)
    4389                 :            : {
    4390                 :            :     struct dp_packet_batch b;
    4391                 :            :     int error;
    4392                 :            : 
    4393                 :        810 :     ofpbuf_clear(actions);
    4394                 :            : 
    4395                 :        810 :     error = dp_netdev_upcall(pmd, packet, flow, NULL, ufid,
    4396                 :            :                              DPIF_UC_ACTION, userdata, actions,
    4397                 :            :                              NULL);
    4398 [ +  - ][ +  + ]:        810 :     if (!error || error == ENOSPC) {
    4399                 :        200 :         packet_batch_init_packet(&b, packet);
    4400                 :        200 :         dp_netdev_execute_actions(pmd, &b, may_steal, flow,
    4401                 :        400 :                                   actions->data, actions->size, now);
    4402         [ +  + ]:        610 :     } else if (may_steal) {
    4403                 :         23 :         dp_packet_delete(packet);
    4404                 :            :     }
    4405                 :        810 : }
    4406                 :            : 
    4407                 :            : static void
    4408                 :      21152 : dp_execute_cb(void *aux_, struct dp_packet_batch *packets_,
    4409                 :            :               const struct nlattr *a, bool may_steal)
    4410                 :            : {
    4411                 :      21152 :     struct dp_netdev_execute_aux *aux = aux_;
    4412                 :      21152 :     uint32_t *depth = recirc_depth_get();
    4413                 :      21152 :     struct dp_netdev_pmd_thread *pmd = aux->pmd;
    4414                 :      21152 :     struct dp_netdev *dp = pmd->dp;
    4415                 :      21152 :     int type = nl_attr_type(a);
    4416                 :      21152 :     long long now = aux->now;
    4417                 :            :     struct tx_port *p;
    4418                 :            : 
    4419   [ +  +  +  +  :      21152 :     switch ((enum ovs_action_attr)type) {
             +  +  -  - ]
    4420                 :            :     case OVS_ACTION_ATTR_OUTPUT:
    4421                 :      15131 :         p = pmd_tx_port_cache_lookup(pmd, u32_to_odp(nl_attr_get_u32(a)));
    4422         [ +  + ]:      15131 :         if (OVS_LIKELY(p)) {
    4423                 :            :             int tx_qid;
    4424                 :            :             bool dynamic_txqs;
    4425                 :            : 
    4426                 :      14580 :             dynamic_txqs = p->port->dynamic_txqs;
    4427         [ +  + ]:      14580 :             if (dynamic_txqs) {
    4428                 :         16 :                 tx_qid = dpif_netdev_xps_get_tx_qid(pmd, p, now);
    4429                 :            :             } else {
    4430                 :      14564 :                 atomic_read_relaxed(&pmd->static_tx_qid, &tx_qid);
    4431                 :            :             }
    4432                 :            : 
    4433                 :      14580 :             netdev_send(p->port->netdev, tx_qid, packets_, may_steal,
    4434                 :            :                         dynamic_txqs);
    4435                 :      14580 :             return;
    4436                 :            :         }
    4437                 :        551 :         break;
    4438                 :            : 
    4439                 :            :     case OVS_ACTION_ATTR_TUNNEL_PUSH:
    4440         [ +  - ]:       1927 :         if (*depth < MAX_RECIRC_DEPTH) {
    4441                 :            :             struct dp_packet_batch tnl_pkt;
    4442                 :       1927 :             struct dp_packet_batch *orig_packets_ = packets_;
    4443                 :            :             int err;
    4444                 :            : 
    4445         [ +  + ]:       1927 :             if (!may_steal) {
    4446                 :        966 :                 dp_packet_batch_clone(&tnl_pkt, packets_);
    4447                 :        966 :                 packets_ = &tnl_pkt;
    4448                 :        966 :                 dp_packet_batch_reset_cutlen(orig_packets_);
    4449                 :            :             }
    4450                 :            : 
    4451                 :       1927 :             dp_packet_batch_apply_cutlen(packets_);
    4452                 :            : 
    4453                 :       1927 :             err = push_tnl_action(pmd, a, packets_);
    4454         [ +  - ]:       1927 :             if (!err) {
    4455                 :       1927 :                 (*depth)++;
    4456                 :       1927 :                 dp_netdev_recirculate(pmd, packets_);
    4457                 :       1927 :                 (*depth)--;
    4458                 :            :             }
    4459                 :       1927 :             return;
    4460                 :            :         }
    4461                 :          0 :         break;
    4462                 :            : 
    4463                 :            :     case OVS_ACTION_ATTR_TUNNEL_POP:
    4464         [ +  - ]:       1932 :         if (*depth < MAX_RECIRC_DEPTH) {
    4465                 :       1932 :             struct dp_packet_batch *orig_packets_ = packets_;
    4466                 :       1932 :             odp_port_t portno = u32_to_odp(nl_attr_get_u32(a));
    4467                 :            : 
    4468                 :       1932 :             p = pmd_tx_port_cache_lookup(pmd, portno);
    4469         [ +  - ]:       1932 :             if (p) {
    4470                 :            :                 struct dp_packet_batch tnl_pkt;
    4471                 :            :                 int i;
    4472                 :            : 
    4473         [ -  + ]:       1932 :                 if (!may_steal) {
    4474                 :          0 :                     dp_packet_batch_clone(&tnl_pkt, packets_);
    4475                 :          0 :                     packets_ = &tnl_pkt;
    4476                 :          0 :                     dp_packet_batch_reset_cutlen(orig_packets_);
    4477                 :            :                 }
    4478                 :            : 
    4479                 :       1932 :                 dp_packet_batch_apply_cutlen(packets_);
    4480                 :            : 
    4481                 :       1932 :                 netdev_pop_header(p->port->netdev, packets_);
    4482         [ +  + ]:       1932 :                 if (!packets_->count) {
    4483                 :          2 :                     return;
    4484                 :            :                 }
    4485                 :            : 
    4486         [ +  + ]:       3860 :                 for (i = 0; i < packets_->count; i++) {
    4487                 :       1930 :                     packets_->packets[i]->md.in_port.odp_port = portno;
    4488                 :            :                 }
    4489                 :            : 
    4490                 :       1930 :                 (*depth)++;
    4491                 :       1930 :                 dp_netdev_recirculate(pmd, packets_);
    4492                 :       1930 :                 (*depth)--;
    4493                 :       1932 :                 return;
    4494                 :            :             }
    4495                 :            :         }
    4496                 :          0 :         break;
    4497                 :            : 
    4498                 :            :     case OVS_ACTION_ATTR_USERSPACE:
    4499         [ +  + ]:        811 :         if (!fat_rwlock_tryrdlock(&dp->upcall_rwlock)) {
    4500                 :        810 :             struct dp_packet_batch *orig_packets_ = packets_;
    4501                 :        810 :             struct dp_packet **packets = packets_->packets;
    4502                 :            :             const struct nlattr *userdata;
    4503                 :            :             struct dp_packet_batch usr_pkt;
    4504                 :            :             struct ofpbuf actions;
    4505                 :            :             struct flow flow;
    4506                 :            :             ovs_u128 ufid;
    4507                 :        810 :             bool clone = false;
    4508                 :            :             int i;
    4509                 :            : 
    4510                 :        810 :             userdata = nl_attr_find_nested(a, OVS_USERSPACE_ATTR_USERDATA);
    4511                 :        810 :             ofpbuf_init(&actions, 0);
    4512                 :            : 
    4513         [ -  + ]:        810 :             if (packets_->trunc) {
    4514         [ #  # ]:          0 :                 if (!may_steal) {
    4515                 :          0 :                     dp_packet_batch_clone(&usr_pkt, packets_);
    4516                 :          0 :                     packets_ = &usr_pkt;
    4517                 :          0 :                     packets = packets_->packets;
    4518                 :          0 :                     clone = true;
    4519                 :          0 :                     dp_packet_batch_reset_cutlen(orig_packets_);
    4520                 :            :                 }
    4521                 :            : 
    4522                 :          0 :                 dp_packet_batch_apply_cutlen(packets_);
    4523                 :            :             }
    4524                 :            : 
    4525         [ +  + ]:       1620 :             for (i = 0; i < packets_->count; i++) {
    4526                 :        810 :                 flow_extract(packets[i], &flow);
    4527                 :        810 :                 dpif_flow_hash(dp->dpif, &flow, sizeof flow, &ufid);
    4528                 :        810 :                 dp_execute_userspace_action(pmd, packets[i], may_steal, &flow,
    4529                 :            :                                             &ufid, &actions, userdata, now);
    4530                 :            :             }
    4531                 :            : 
    4532         [ -  + ]:        810 :             if (clone) {
    4533                 :          0 :                 dp_packet_delete_batch(packets_, true);
    4534                 :            :             }
    4535                 :            : 
    4536                 :        810 :             ofpbuf_uninit(&actions);
    4537                 :        810 :             fat_rwlock_unlock(&dp->upcall_rwlock);
    4538                 :            : 
    4539                 :        810 :             return;
    4540                 :            :         }
    4541                 :          1 :         break;
    4542                 :            : 
    4543                 :            :     case OVS_ACTION_ATTR_RECIRC:
    4544         [ +  - ]:        727 :         if (*depth < MAX_RECIRC_DEPTH) {
    4545                 :            :             struct dp_packet_batch recirc_pkts;
    4546                 :            :             int i;
    4547                 :            : 
    4548         [ +  + ]:        727 :             if (!may_steal) {
    4549                 :        266 :                dp_packet_batch_clone(&recirc_pkts, packets_);
    4550                 :        266 :                packets_ = &recirc_pkts;
    4551                 :            :             }
    4552                 :            : 
    4553         [ +  + ]:       1454 :             for (i = 0; i < packets_->count; i++) {
    4554                 :        727 :                 packets_->packets[i]->md.recirc_id = nl_attr_get_u32(a);
    4555                 :            :             }
    4556                 :            : 
    4557                 :        727 :             (*depth)++;
    4558                 :        727 :             dp_netdev_recirculate(pmd, packets_);
    4559                 :        727 :             (*depth)--;
    4560                 :            : 
    4561                 :        727 :             return;
    4562                 :            :         }
    4563                 :            : 
    4564         [ #  # ]:          0 :         VLOG_WARN("Packet dropped. Max recirculation depth exceeded.");
    4565                 :          0 :         break;
    4566                 :            : 
    4567                 :            :     case OVS_ACTION_ATTR_CT: {
    4568                 :            :         const struct nlattr *b;
    4569                 :        624 :         bool commit = false;
    4570                 :            :         unsigned int left;
    4571                 :        624 :         uint16_t zone = 0;
    4572                 :        624 :         const char *helper = NULL;
    4573                 :        624 :         const uint32_t *setmark = NULL;
    4574                 :        624 :         const struct ovs_key_ct_labels *setlabel = NULL;
    4575                 :            : 
    4576         [ +  + ]:       1627 :         NL_ATTR_FOR_EACH_UNSAFE (b, left, nl_attr_get(a),
    4577                 :            :                                  nl_attr_get_size(a)) {
    4578                 :       1003 :             enum ovs_ct_attr sub_type = nl_attr_type(b);
    4579                 :            : 
    4580   [ +  +  -  +  :       1003 :             switch(sub_type) {
                +  -  - ]
    4581                 :            :             case OVS_CT_ATTR_COMMIT:
    4582                 :        285 :                 commit = true;
    4583                 :        285 :                 break;
    4584                 :            :             case OVS_CT_ATTR_ZONE:
    4585                 :        624 :                 zone = nl_attr_get_u16(b);
    4586                 :        624 :                 break;
    4587                 :            :             case OVS_CT_ATTR_HELPER:
    4588                 :          0 :                 helper = nl_attr_get_string(b);
    4589                 :          0 :                 break;
    4590                 :            :             case OVS_CT_ATTR_MARK:
    4591                 :         50 :                 setmark = nl_attr_get(b);
    4592                 :         50 :                 break;
    4593                 :            :             case OVS_CT_ATTR_LABELS:
    4594                 :         44 :                 setlabel = nl_attr_get(b);
    4595                 :         44 :                 break;
    4596                 :            :             case OVS_CT_ATTR_NAT:
    4597                 :            :             case OVS_CT_ATTR_UNSPEC:
    4598                 :            :             case __OVS_CT_ATTR_MAX:
    4599                 :          0 :                 OVS_NOT_REACHED();
    4600                 :            :             }
    4601                 :            :         }
    4602                 :            : 
    4603                 :        624 :         conntrack_execute(&dp->conntrack, packets_, aux->flow->dl_type, commit,
    4604                 :            :                           zone, setmark, setlabel, helper);
    4605                 :        624 :         break;
    4606                 :            :     }
    4607                 :            : 
    4608                 :            :     case OVS_ACTION_ATTR_PUSH_VLAN:
    4609                 :            :     case OVS_ACTION_ATTR_POP_VLAN:
    4610                 :            :     case OVS_ACTION_ATTR_PUSH_MPLS:
    4611                 :            :     case OVS_ACTION_ATTR_POP_MPLS:
    4612                 :            :     case OVS_ACTION_ATTR_SET:
    4613                 :            :     case OVS_ACTION_ATTR_SET_MASKED:
    4614                 :            :     case OVS_ACTION_ATTR_SAMPLE:
    4615                 :            :     case OVS_ACTION_ATTR_HASH:
    4616                 :            :     case OVS_ACTION_ATTR_UNSPEC:
    4617                 :            :     case OVS_ACTION_ATTR_TRUNC:
    4618                 :            :     case __OVS_ACTION_ATTR_MAX:
    4619                 :          0 :         OVS_NOT_REACHED();
    4620                 :            :     }
    4621                 :            : 
    4622                 :       1176 :     dp_packet_delete_batch(packets_, may_steal);
    4623                 :            : }
    4624                 :            : 
    4625                 :            : static void
    4626                 :      18441 : dp_netdev_execute_actions(struct dp_netdev_pmd_thread *pmd,
    4627                 :            :                           struct dp_packet_batch *packets,
    4628                 :            :                           bool may_steal, const struct flow *flow,
    4629                 :            :                           const struct nlattr *actions, size_t actions_len,
    4630                 :            :                           long long now)
    4631                 :            : {
    4632                 :      18441 :     struct dp_netdev_execute_aux aux = { pmd, now, flow };
    4633                 :            : 
    4634                 :      18441 :     odp_execute_actions(&aux, packets, may_steal, actions,
    4635                 :            :                         actions_len, dp_execute_cb);
    4636                 :      18441 : }
    4637                 :            : 
    4638                 :            : struct dp_netdev_ct_dump {
    4639                 :            :     struct ct_dpif_dump_state up;
    4640                 :            :     struct conntrack_dump dump;
    4641                 :            :     struct conntrack *ct;
    4642                 :            :     struct dp_netdev *dp;
    4643                 :            : };
    4644                 :            : 
    4645                 :            : static int
    4646                 :         16 : dpif_netdev_ct_dump_start(struct dpif *dpif, struct ct_dpif_dump_state **dump_,
    4647                 :            :                           const uint16_t *pzone)
    4648                 :            : {
    4649                 :         16 :     struct dp_netdev *dp = get_dp_netdev(dpif);
    4650                 :            :     struct dp_netdev_ct_dump *dump;
    4651                 :            : 
    4652                 :         16 :     dump = xzalloc(sizeof *dump);
    4653                 :         16 :     dump->dp = dp;
    4654                 :         16 :     dump->ct = &dp->conntrack;
    4655                 :            : 
    4656                 :         16 :     conntrack_dump_start(&dp->conntrack, &dump->dump, pzone);
    4657                 :            : 
    4658                 :         16 :     *dump_ = &dump->up;
    4659                 :            : 
    4660                 :         16 :     return 0;
    4661                 :            : }
    4662                 :            : 
    4663                 :            : static int
    4664                 :         64 : dpif_netdev_ct_dump_next(struct dpif *dpif OVS_UNUSED,
    4665                 :            :                          struct ct_dpif_dump_state *dump_,
    4666                 :            :                          struct ct_dpif_entry *entry)
    4667                 :            : {
    4668                 :            :     struct dp_netdev_ct_dump *dump;
    4669                 :            : 
    4670                 :         64 :     INIT_CONTAINER(dump, dump_, up);
    4671                 :            : 
    4672                 :         64 :     return conntrack_dump_next(&dump->dump, entry);
    4673                 :            : }
    4674                 :            : 
    4675                 :            : static int
    4676                 :         16 : dpif_netdev_ct_dump_done(struct dpif *dpif OVS_UNUSED,
    4677                 :            :                          struct ct_dpif_dump_state *dump_)
    4678                 :            : {
    4679                 :            :     struct dp_netdev_ct_dump *dump;
    4680                 :            :     int err;
    4681                 :            : 
    4682                 :         16 :     INIT_CONTAINER(dump, dump_, up);
    4683                 :            : 
    4684                 :         16 :     err = conntrack_dump_done(&dump->dump);
    4685                 :            : 
    4686                 :         16 :     free(dump);
    4687                 :            : 
    4688                 :         16 :     return err;
    4689                 :            : }
    4690                 :            : 
    4691                 :            : static int
    4692                 :          2 : dpif_netdev_ct_flush(struct dpif *dpif, const uint16_t *zone)
    4693                 :            : {
    4694                 :          2 :     struct dp_netdev *dp = get_dp_netdev(dpif);
    4695                 :            : 
    4696                 :          2 :     return conntrack_flush(&dp->conntrack, zone);
    4697                 :            : }
    4698                 :            : 
    4699                 :            : const struct dpif_class dpif_netdev_class = {
    4700                 :            :     "netdev",
    4701                 :            :     dpif_netdev_init,
    4702                 :            :     dpif_netdev_enumerate,
    4703                 :            :     dpif_netdev_port_open_type,
    4704                 :            :     dpif_netdev_open,
    4705                 :            :     dpif_netdev_close,
    4706                 :            :     dpif_netdev_destroy,
    4707                 :            :     dpif_netdev_run,
    4708                 :            :     dpif_netdev_wait,
    4709                 :            :     dpif_netdev_get_stats,
    4710                 :            :     dpif_netdev_port_add,
    4711                 :            :     dpif_netdev_port_del,
    4712                 :            :     dpif_netdev_port_set_config,
    4713                 :            :     dpif_netdev_port_query_by_number,
    4714                 :            :     dpif_netdev_port_query_by_name,
    4715                 :            :     NULL,                       /* port_get_pid */
    4716                 :            :     dpif_netdev_port_dump_start,
    4717                 :            :     dpif_netdev_port_dump_next,
    4718                 :            :     dpif_netdev_port_dump_done,
    4719                 :            :     dpif_netdev_port_poll,
    4720                 :            :     dpif_netdev_port_poll_wait,
    4721                 :            :     dpif_netdev_flow_flush,
    4722                 :            :     dpif_netdev_flow_dump_create,
    4723                 :            :     dpif_netdev_flow_dump_destroy,
    4724                 :            :     dpif_netdev_flow_dump_thread_create,
    4725                 :            :     dpif_netdev_flow_dump_thread_destroy,
    4726                 :            :     dpif_netdev_flow_dump_next,
    4727                 :            :     dpif_netdev_operate,
    4728                 :            :     NULL,                       /* recv_set */
    4729                 :            :     NULL,                       /* handlers_set */
    4730                 :            :     dpif_netdev_pmd_set,
    4731                 :            :     dpif_netdev_queue_to_priority,
    4732                 :            :     NULL,                       /* recv */
    4733                 :            :     NULL,                       /* recv_wait */
    4734                 :            :     NULL,                       /* recv_purge */
    4735                 :            :     dpif_netdev_register_dp_purge_cb,
    4736                 :            :     dpif_netdev_register_upcall_cb,
    4737                 :            :     dpif_netdev_enable_upcall,
    4738                 :            :     dpif_netdev_disable_upcall,
    4739                 :            :     dpif_netdev_get_datapath_version,
    4740                 :            :     dpif_netdev_ct_dump_start,
    4741                 :            :     dpif_netdev_ct_dump_next,
    4742                 :            :     dpif_netdev_ct_dump_done,
    4743                 :            :     dpif_netdev_ct_flush,
    4744                 :            : };
    4745                 :            : 
    4746                 :            : static void
    4747                 :          1 : dpif_dummy_change_port_number(struct unixctl_conn *conn, int argc OVS_UNUSED,
    4748                 :            :                               const char *argv[], void *aux OVS_UNUSED)
    4749                 :            : {
    4750                 :            :     struct dp_netdev_port *port;
    4751                 :            :     struct dp_netdev *dp;
    4752                 :            :     odp_port_t port_no;
    4753                 :            : 
    4754                 :          1 :     ovs_mutex_lock(&dp_netdev_mutex);
    4755                 :          1 :     dp = shash_find_data(&dp_netdevs, argv[1]);
    4756 [ +  - ][ -  + ]:          1 :     if (!dp || !dpif_netdev_class_is_dummy(dp->class)) {
    4757                 :          0 :         ovs_mutex_unlock(&dp_netdev_mutex);
    4758                 :          0 :         unixctl_command_reply_error(conn, "unknown datapath or not a dummy");
    4759                 :          0 :         return;
    4760                 :            :     }
    4761                 :          1 :     ovs_refcount_ref(&dp->ref_cnt);
    4762                 :          1 :     ovs_mutex_unlock(&dp_netdev_mutex);
    4763                 :            : 
    4764                 :          1 :     ovs_mutex_lock(&dp->port_mutex);
    4765         [ -  + ]:          1 :     if (get_port_by_name(dp, argv[2], &port)) {
    4766                 :          0 :         unixctl_command_reply_error(conn, "unknown port");
    4767                 :          0 :         goto exit;
    4768                 :            :     }
    4769                 :            : 
    4770                 :          1 :     port_no = u32_to_odp(atoi(argv[3]));
    4771 [ +  - ][ -  + ]:          1 :     if (!port_no || port_no == ODPP_NONE) {
    4772                 :          0 :         unixctl_command_reply_error(conn, "bad port number");
    4773                 :          0 :         goto exit;
    4774                 :            :     }
    4775         [ -  + ]:          1 :     if (dp_netdev_lookup_port(dp, port_no)) {
    4776                 :          0 :         unixctl_command_reply_error(conn, "port number already in use");
    4777                 :          0 :         goto exit;
    4778                 :            :     }
    4779                 :            : 
    4780                 :            :     /* Remove port. */
    4781                 :          1 :     hmap_remove(&dp->ports, &port->node);
    4782                 :          1 :     dp_netdev_del_port_from_all_pmds(dp, port);
    4783                 :            : 
    4784                 :            :     /* Reinsert with new port number. */
    4785                 :          1 :     port->port_no = port_no;
    4786                 :          1 :     hmap_insert(&dp->ports, &port->node, hash_port_no(port_no));
    4787                 :          1 :     dp_netdev_add_port_to_pmds(dp, port);
    4788                 :            : 
    4789                 :          1 :     seq_change(dp->port_seq);
    4790                 :          1 :     unixctl_command_reply(conn, NULL);
    4791                 :            : 
    4792                 :            : exit:
    4793                 :          1 :     ovs_mutex_unlock(&dp->port_mutex);
    4794                 :          1 :     dp_netdev_unref(dp);
    4795                 :            : }
    4796                 :            : 
    4797                 :            : static void
    4798                 :        626 : dpif_dummy_register__(const char *type)
    4799                 :            : {
    4800                 :            :     struct dpif_class *class;
    4801                 :            : 
    4802                 :        626 :     class = xmalloc(sizeof *class);
    4803                 :        626 :     *class = dpif_netdev_class;
    4804                 :        626 :     class->type = xstrdup(type);
    4805                 :        626 :     dp_register_provider(class);
    4806                 :        626 : }
    4807                 :            : 
    4808                 :            : static void
    4809                 :         83 : dpif_dummy_override(const char *type)
    4810                 :            : {
    4811                 :            :     int error;
    4812                 :            : 
    4813                 :            :     /*
    4814                 :            :      * Ignore EAFNOSUPPORT to allow --enable-dummy=system with
    4815                 :            :      * a userland-only build.  It's useful for testsuite.
    4816                 :            :      */
    4817                 :         83 :     error = dp_unregister_provider(type);
    4818 [ -  + ][ #  # ]:         83 :     if (error == 0 || error == EAFNOSUPPORT) {
    4819                 :         83 :         dpif_dummy_register__(type);
    4820                 :            :     }
    4821                 :         83 : }
    4822                 :            : 
    4823                 :            : void
    4824                 :        543 : dpif_dummy_register(enum dummy_level level)
    4825                 :            : {
    4826         [ +  + ]:        543 :     if (level == DUMMY_OVERRIDE_ALL) {
    4827                 :            :         struct sset types;
    4828                 :            :         const char *type;
    4829                 :            : 
    4830                 :          1 :         sset_init(&types);
    4831                 :          1 :         dp_enumerate_types(&types);
    4832 [ +  - ][ +  + ]:          3 :         SSET_FOR_EACH (type, &types) {
                 [ +  + ]
    4833                 :          2 :             dpif_dummy_override(type);
    4834                 :            :         }
    4835                 :          1 :         sset_destroy(&types);
    4836         [ +  + ]:        542 :     } else if (level == DUMMY_OVERRIDE_SYSTEM) {
    4837                 :         81 :         dpif_dummy_override("system");
    4838                 :            :     }
    4839                 :            : 
    4840                 :        543 :     dpif_dummy_register__("dummy");
    4841                 :            : 
    4842                 :        543 :     unixctl_command_register("dpif-dummy/change-port-number",
    4843                 :            :                              "dp port new-number",
    4844                 :            :                              3, 3, dpif_dummy_change_port_number, NULL);
    4845                 :        543 : }
    4846                 :            : 
    4847                 :            : /* Datapath Classifier. */
    4848                 :            : 
    4849                 :            : /* A set of rules that all have the same fields wildcarded. */
    4850                 :            : struct dpcls_subtable {
    4851                 :            :     /* The fields are only used by writers. */
    4852                 :            :     struct cmap_node cmap_node OVS_GUARDED; /* Within dpcls 'subtables_map'. */
    4853                 :            : 
    4854                 :            :     /* These fields are accessed by readers. */
    4855                 :            :     struct cmap rules;           /* Contains "struct dpcls_rule"s. */
    4856                 :            :     uint32_t hit_cnt;            /* Number of match hits in subtable in current
    4857                 :            :                                     optimization interval. */
    4858                 :            :     struct netdev_flow_key mask; /* Wildcards for fields (const). */
    4859                 :            :     /* 'mask' must be the last field, additional space is allocated here. */
    4860                 :            : };
    4861                 :            : 
    4862                 :            : /* Initializes 'cls' as a classifier that initially contains no classification
    4863                 :            :  * rules. */
    4864                 :            : static void
    4865                 :        996 : dpcls_init(struct dpcls *cls)
    4866                 :            : {
    4867                 :        996 :     cmap_init(&cls->subtables_map);
    4868                 :        996 :     pvector_init(&cls->subtables);
    4869                 :        996 : }
    4870                 :            : 
    4871                 :            : static void
    4872                 :       6159 : dpcls_destroy_subtable(struct dpcls *cls, struct dpcls_subtable *subtable)
    4873                 :            : {
    4874         [ +  + ]:       6159 :     VLOG_DBG("Destroying subtable %p for in_port %d", subtable, cls->in_port);
    4875                 :       6159 :     pvector_remove(&cls->subtables, subtable);
    4876                 :       6159 :     cmap_remove(&cls->subtables_map, &subtable->cmap_node,
    4877                 :            :                 subtable->mask.hash);
    4878                 :       6159 :     cmap_destroy(&subtable->rules);
    4879                 :       6159 :     ovsrcu_postpone(free, subtable);
    4880                 :       6159 : }
    4881                 :            : 
    4882                 :            : /* Destroys 'cls'.  Rules within 'cls', if any, are not freed; this is the
    4883                 :            :  * caller's responsibility.
    4884                 :            :  * May only be called after all the readers have been terminated. */
    4885                 :            : static void
    4886                 :         13 : dpcls_destroy(struct dpcls *cls)
    4887                 :            : {
    4888         [ +  - ]:         13 :     if (cls) {
    4889                 :            :         struct dpcls_subtable *subtable;
    4890                 :            : 
    4891 [ -  + ][ -  + ]:         13 :         CMAP_FOR_EACH (subtable, cmap_node, &cls->subtables_map) {
    4892         [ #  # ]:          0 :             ovs_assert(cmap_count(&subtable->rules) == 0);
    4893                 :          0 :             dpcls_destroy_subtable(cls, subtable);
    4894                 :            :         }
    4895                 :         13 :         cmap_destroy(&cls->subtables_map);
    4896                 :         13 :         pvector_destroy(&cls->subtables);
    4897                 :            :     }
    4898                 :         13 : }
    4899                 :            : 
    4900                 :            : static struct dpcls_subtable *
    4901                 :       6159 : dpcls_create_subtable(struct dpcls *cls, const struct netdev_flow_key *mask)
    4902                 :            : {
    4903                 :            :     struct dpcls_subtable *subtable;
    4904                 :            : 
    4905                 :            :     /* Need to add one. */
    4906                 :       6159 :     subtable = xmalloc(sizeof *subtable
    4907                 :       6159 :                        - sizeof subtable->mask.mf + mask->len);
    4908                 :       6159 :     cmap_init(&subtable->rules);
    4909                 :       6159 :     subtable->hit_cnt = 0;
    4910                 :       6159 :     netdev_flow_key_clone(&subtable->mask, mask);
    4911                 :       6159 :     cmap_insert(&cls->subtables_map, &subtable->cmap_node, mask->hash);
    4912                 :            :     /* Add the new subtable at the end of the pvector (with no hits yet) */
    4913                 :       6159 :     pvector_insert(&cls->subtables, subtable, 0);
    4914         [ +  + ]:       6159 :     VLOG_DBG("Creating %"PRIuSIZE". subtable %p for in_port %d",
    4915                 :            :              cmap_count(&cls->subtables_map), subtable, cls->in_port);
    4916                 :       6159 :     pvector_publish(&cls->subtables);
    4917                 :            : 
    4918                 :       6159 :     return subtable;
    4919                 :            : }
    4920                 :            : 
    4921                 :            : static inline struct dpcls_subtable *
    4922                 :      10331 : dpcls_find_subtable(struct dpcls *cls, const struct netdev_flow_key *mask)
    4923                 :            : {
    4924                 :            :     struct dpcls_subtable *subtable;
    4925                 :            : 
    4926         [ +  + ]:      10331 :     CMAP_FOR_EACH_WITH_HASH (subtable, cmap_node, mask->hash,
    4927                 :            :                              &cls->subtables_map) {
    4928         [ +  - ]:       4172 :         if (netdev_flow_key_equal(&subtable->mask, mask)) {
    4929                 :       4172 :             return subtable;
    4930                 :            :         }
    4931                 :            :     }
    4932                 :       6159 :     return dpcls_create_subtable(cls, mask);
    4933                 :            : }
    4934                 :            : 
    4935                 :            : 
    4936                 :            : /* Periodically sort the dpcls subtable vectors according to hit counts */
    4937                 :            : static void
    4938                 :         24 : dpcls_sort_subtable_vector(struct dpcls *cls)
    4939                 :            : {
    4940                 :         24 :     struct pvector *pvec = &cls->subtables;
    4941                 :            :     struct dpcls_subtable *subtable;
    4942                 :            : 
    4943         [ +  + ]:         46 :     PVECTOR_FOR_EACH (subtable, pvec) {
    4944                 :         22 :         pvector_change_priority(pvec, subtable, subtable->hit_cnt);
    4945                 :         22 :         subtable->hit_cnt = 0;
    4946                 :            :     }
    4947                 :         24 :     pvector_publish(pvec);
    4948                 :         24 : }
    4949                 :            : 
    4950                 :            : static inline void
    4951                 :     260282 : dp_netdev_pmd_try_optimize(struct dp_netdev_pmd_thread *pmd)
    4952                 :            : {
    4953                 :            :     struct dpcls *cls;
    4954                 :     260282 :     long long int now = time_msec();
    4955                 :            : 
    4956         [ +  + ]:     260281 :     if (now > pmd->next_optimization) {
    4957                 :            :         /* Try to obtain the flow lock to block out revalidator threads.
    4958                 :            :          * If not possible, just try next time. */
    4959         [ +  - ]:         37 :         if (!ovs_mutex_trylock(&pmd->flow_mutex)) {
    4960                 :            :             /* Optimize each classifier */
    4961 [ +  + ][ +  + ]:         61 :             CMAP_FOR_EACH (cls, node, &pmd->classifiers) {
    4962                 :         24 :                 dpcls_sort_subtable_vector(cls);
    4963                 :            :             }
    4964                 :         37 :             ovs_mutex_unlock(&pmd->flow_mutex);
    4965                 :            :             /* Start new measuring interval */
    4966                 :         37 :             pmd->next_optimization = now + DPCLS_OPTIMIZATION_INTERVAL;
    4967                 :            :         }
    4968                 :            :     }
    4969                 :     260281 : }
    4970                 :            : 
    4971                 :            : /* Insert 'rule' into 'cls'. */
    4972                 :            : static void
    4973                 :      10331 : dpcls_insert(struct dpcls *cls, struct dpcls_rule *rule,
    4974                 :            :              const struct netdev_flow_key *mask)
    4975                 :            : {
    4976                 :      10331 :     struct dpcls_subtable *subtable = dpcls_find_subtable(cls, mask);
    4977                 :            : 
    4978                 :            :     /* Refer to subtable's mask, also for later removal. */
    4979                 :      10331 :     rule->mask = &subtable->mask;
    4980                 :      10331 :     cmap_insert(&subtable->rules, &rule->cmap_node, rule->flow.hash);
    4981                 :      10331 : }
    4982                 :            : 
    4983                 :            : /* Removes 'rule' from 'cls', also destructing the 'rule'. */
    4984                 :            : static void
    4985                 :      10331 : dpcls_remove(struct dpcls *cls, struct dpcls_rule *rule)
    4986                 :            : {
    4987                 :            :     struct dpcls_subtable *subtable;
    4988                 :            : 
    4989         [ -  + ]:      10331 :     ovs_assert(rule->mask);
    4990                 :            : 
    4991                 :            :     /* Get subtable from reference in rule->mask. */
    4992                 :      10331 :     INIT_CONTAINER(subtable, rule->mask, mask);
    4993         [ +  + ]:      10331 :     if (cmap_remove(&subtable->rules, &rule->cmap_node, rule->flow.hash)
    4994                 :            :         == 0) {
    4995                 :            :         /* Delete empty subtable. */
    4996                 :       6159 :         dpcls_destroy_subtable(cls, subtable);
    4997                 :       6159 :         pvector_publish(&cls->subtables);
    4998                 :            :     }
    4999                 :      10331 : }
    5000                 :            : 
    5001                 :            : /* Returns true if 'target' satisfies 'key' in 'mask', that is, if each 1-bit
    5002                 :            :  * in 'mask' the values in 'key' and 'target' are the same. */
    5003                 :            : static inline bool
    5004                 :       5895 : dpcls_rule_matches_key(const struct dpcls_rule *rule,
    5005                 :            :                        const struct netdev_flow_key *target)
    5006                 :            : {
    5007                 :       5895 :     const uint64_t *keyp = miniflow_get_values(&rule->flow.mf);
    5008                 :       5895 :     const uint64_t *maskp = miniflow_get_values(&rule->mask->mf);
    5009                 :            :     uint64_t value;
    5010                 :            : 
    5011         [ +  + ]:      43444 :     NETDEV_FLOW_KEY_FOR_EACH_IN_FLOWMAP(value, target, rule->flow.mf.map) {
    5012         [ -  + ]:      37549 :         if (OVS_UNLIKELY((value & *maskp++) != *keyp++)) {
    5013                 :          0 :             return false;
    5014                 :            :         }
    5015                 :            :     }
    5016                 :       5895 :     return true;
    5017                 :            : }
    5018                 :            : 
    5019                 :            : /* For each miniflow in 'keys' performs a classifier lookup writing the result
    5020                 :            :  * into the corresponding slot in 'rules'.  If a particular entry in 'keys' is
    5021                 :            :  * NULL it is skipped.
    5022                 :            :  *
    5023                 :            :  * This function is optimized for use in the userspace datapath and therefore
    5024                 :            :  * does not implement a lot of features available in the standard
    5025                 :            :  * classifier_lookup() function.  Specifically, it does not implement
    5026                 :            :  * priorities, instead returning any rule which matches the flow.
    5027                 :            :  *
    5028                 :            :  * Returns true if all miniflows found a corresponding rule. */
    5029                 :            : static bool
    5030                 :      25044 : dpcls_lookup(struct dpcls *cls, const struct netdev_flow_key keys[],
    5031                 :            :              struct dpcls_rule **rules, const size_t cnt,
    5032                 :            :              int *num_lookups_p)
    5033                 :      25044 : {
    5034                 :            :     /* The received 'cnt' miniflows are the search-keys that will be processed
    5035                 :            :      * in batches of 16 elements.  N_MAPS will contain the number of these
    5036                 :            :      * 16-elements batches.  i.e. for 'cnt' = 32, N_MAPS will be 2.  The batch
    5037                 :            :      * size 16 was experimentally found faster than 8 or 32. */
    5038                 :            :     typedef uint16_t map_type;
    5039                 :            : #define MAP_BITS (sizeof(map_type) * CHAR_BIT)
    5040                 :            : 
    5041                 :            : #if !defined(__CHECKER__) && !defined(_WIN32)
    5042                 :      25044 :     const int N_MAPS = DIV_ROUND_UP(cnt, MAP_BITS);
    5043                 :            : #else
    5044                 :            :     enum { N_MAPS = DIV_ROUND_UP(NETDEV_MAX_BURST, MAP_BITS) };
    5045                 :            : #endif
    5046                 :      25044 :     map_type maps[N_MAPS];
    5047                 :            :     struct dpcls_subtable *subtable;
    5048                 :            : 
    5049                 :      25044 :     memset(maps, 0xff, sizeof maps);
    5050         [ +  - ]:      25044 :     if (cnt % MAP_BITS) {
    5051                 :      25044 :         maps[N_MAPS - 1] >>= MAP_BITS - cnt % MAP_BITS; /* Clear extra bits. */
    5052                 :            :     }
    5053                 :      25044 :     memset(rules, 0, cnt * sizeof *rules);
    5054                 :            : 
    5055                 :      25044 :     int lookups_match = 0, subtable_pos = 1;
    5056                 :            : 
    5057                 :            :     /* The Datapath classifier - aka dpcls - is composed of subtables.
    5058                 :            :      * Subtables are dynamically created as needed when new rules are inserted.
    5059                 :            :      * Each subtable collects rules with matches on a specific subset of packet
    5060                 :            :      * fields as defined by the subtable's mask.  We proceed to process every
    5061                 :            :      * search-key against each subtable, but when a match is found for a
    5062                 :            :      * search-key, the search for that key can stop because the rules are
    5063                 :            :      * non-overlapping. */
    5064         [ +  + ]:      57212 :     PVECTOR_FOR_EACH (subtable, &cls->subtables) {
    5065                 :      38063 :         const struct netdev_flow_key *mkeys = keys;
    5066                 :      38063 :         struct dpcls_rule **mrules = rules;
    5067                 :      38063 :         map_type remains = 0;
    5068                 :            :         int m;
    5069                 :            : 
    5070                 :            :         BUILD_ASSERT_DECL(sizeof remains == sizeof *maps);
    5071                 :            : 
    5072                 :            :         /* Loops on each batch of 16 search-keys. */
    5073         [ +  + ]:      76126 :         for (m = 0; m < N_MAPS; m++, mkeys += MAP_BITS, mrules += MAP_BITS) {
    5074                 :            :             uint32_t hashes[MAP_BITS];
    5075                 :            :             const struct cmap_node *nodes[MAP_BITS];
    5076                 :      38063 :             unsigned long map = maps[m];
    5077                 :            :             int i;
    5078                 :            : 
    5079         [ -  + ]:      38063 :             if (!map) {
    5080                 :          0 :                 continue; /* Skip empty maps. */
    5081                 :            :             }
    5082                 :            : 
    5083                 :            :             /* Compute hashes for the remaining keys.  Each search-key is
    5084                 :            :              * masked with the subtable's mask to avoid hashing the wildcarded
    5085                 :            :              * bits. */
    5086         [ +  + ]:      76126 :             ULLONG_FOR_EACH_1(i, map) {
    5087                 :      38063 :                 hashes[i] = netdev_flow_key_hash_in_mask(&mkeys[i],
    5088                 :      38063 :                                                          &subtable->mask);
    5089                 :            :             }
    5090                 :            :             /* Lookup. */
    5091                 :      38063 :             map = cmap_find_batch(&subtable->rules, map, hashes, nodes);
    5092                 :            :             /* Check results.  When the i-th bit of map is set, it means that a
    5093                 :            :              * set of nodes with a matching hash value was found for the i-th
    5094                 :            :              * search-key.  Due to possible hash collisions we need to check
    5095                 :            :              * which of the found rules, if any, really matches our masked
    5096                 :            :              * search-key. */
    5097         [ +  + ]:      43958 :             ULLONG_FOR_EACH_1(i, map) {
    5098                 :            :                 struct dpcls_rule *rule;
    5099                 :            : 
    5100         [ +  - ]:       5895 :                 CMAP_NODE_FOR_EACH (rule, cmap_node, nodes[i]) {
    5101         [ +  - ]:       5895 :                     if (OVS_LIKELY(dpcls_rule_matches_key(rule, &mkeys[i]))) {
    5102                 :       5895 :                         mrules[i] = rule;
    5103                 :            :                         /* Even at 20 Mpps the 32-bit hit_cnt cannot wrap
    5104                 :            :                          * within one second optimization interval  */
    5105                 :       5895 :                         subtable->hit_cnt++;
    5106                 :       5895 :                         lookups_match += subtable_pos;
    5107                 :       5895 :                         goto next;
    5108                 :            :                     }
    5109                 :            :                 }
    5110                 :            :                 /* None of the found rules was a match. Reset the i-th bit to
    5111                 :            :                  * keep searching in the next subtable. */
    5112                 :          0 :                 ULLONG_SET0(map, i);  /* Did not match. */
    5113                 :            :             next:
    5114                 :            :                 ;                     /* Keep Sparse happy. */
    5115                 :            :             }
    5116                 :      38063 :             maps[m] &= ~map;          /* Clear the found rules. */
    5117                 :      38063 :             remains |= maps[m];
    5118                 :            :         }
    5119         [ +  + ]:      38063 :         if (!remains) {
    5120         [ +  + ]:       5895 :             if (num_lookups_p) {
    5121                 :       5533 :                 *num_lookups_p = lookups_match;
    5122                 :            :             }
    5123                 :       5895 :             return true;              /* All found. */
    5124                 :            :         }
    5125                 :      32168 :         subtable_pos++;
    5126                 :            :     }
    5127         [ +  + ]:      19149 :     if (num_lookups_p) {
    5128                 :       9814 :         *num_lookups_p = lookups_match;
    5129                 :            :     }
    5130                 :      25044 :     return false;                     /* Some misses. */
    5131                 :            : }

Generated by: LCOV version 1.12