Coverage Report

Created: 2026-07-16 06:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openvswitch/lib/dpif-netdev.c
Line
Count
Source
1
/*
2
 * Copyright (c) 2009-2014, 2016-2018 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 <sys/types.h>
26
#include <netinet/in.h>
27
#include <stdint.h>
28
#include <stdlib.h>
29
#include <string.h>
30
#include <sys/ioctl.h>
31
#include <sys/socket.h>
32
#include <sys/stat.h>
33
#include <unistd.h>
34
35
#include "bitmap.h"
36
#include "ccmap.h"
37
#include "cmap.h"
38
#include "conntrack.h"
39
#include "conntrack-tp.h"
40
#include "coverage.h"
41
#include "ct-dpif.h"
42
#include "csum.h"
43
#include "dp-packet.h"
44
#include "dpif.h"
45
#include "dpif-netdev-dfc.h"
46
#include "dpif-netdev-dpcls.h"
47
#include "dpif-netdev-flow.h"
48
#include "dpif-netdev-perf.h"
49
#include "dpif-netdev-thread.h"
50
#include "dpif-offload.h"
51
#include "dpif-provider.h"
52
#include "dummy.h"
53
#include "fat-rwlock.h"
54
#include "flow.h"
55
#include "hmapx.h"
56
#include "id-fpool.h"
57
#include "id-pool.h"
58
#include "ipf.h"
59
#include "mov-avg.h"
60
#include "mpsc-queue.h"
61
#include "netdev.h"
62
#include "netdev-provider.h"
63
#include "netdev-vport.h"
64
#include "netlink.h"
65
#include "odp-execute.h"
66
#include "odp-util.h"
67
#include "openvswitch/dynamic-string.h"
68
#include "openvswitch/list.h"
69
#include "openvswitch/match.h"
70
#include "openvswitch/ofp-parse.h"
71
#include "openvswitch/ofp-print.h"
72
#include "openvswitch/ofpbuf.h"
73
#include "openvswitch/shash.h"
74
#include "openvswitch/vlog.h"
75
#include "ovs-numa.h"
76
#include "ovs-rcu.h"
77
#include "packets.h"
78
#include "openvswitch/poll-loop.h"
79
#include "pvector.h"
80
#include "random.h"
81
#include "seq.h"
82
#include "smap.h"
83
#include "sset.h"
84
#include "timeval.h"
85
#include "tnl-neigh-cache.h"
86
#include "tnl-ports.h"
87
#include "unixctl.h"
88
#include "util.h"
89
#include "uuid.h"
90
91
VLOG_DEFINE_THIS_MODULE(dpif_netdev);
92
93
/* Auto Load Balancing Defaults */
94
0
#define ALB_IMPROVEMENT_THRESHOLD    25
95
0
#define ALB_LOAD_THRESHOLD           95
96
0
#define ALB_REBALANCE_INTERVAL       1     /* 1 Min */
97
0
#define MAX_ALB_REBALANCE_INTERVAL   20000 /* 20000 Min */
98
0
#define MIN_TO_MSEC                  60000
99
100
#define FLOW_DUMP_MAX_BATCH 50
101
/* Use per thread recirc_depth to prevent recirculation loop. */
102
0
#define MAX_RECIRC_DEPTH 8
103
DEFINE_STATIC_PER_THREAD_DATA(uint32_t, recirc_depth, 0)
104
105
/* Use instant packet send by default. */
106
0
#define DEFAULT_TX_FLUSH_INTERVAL 0
107
108
/* Configuration parameters. */
109
enum { MAX_METERS = 1 << 18 };  /* Maximum number of meters. */
110
enum { MAX_BANDS = 8 };         /* Maximum number of bands / meter. */
111
112
COVERAGE_DEFINE(datapath_drop_meter);
113
COVERAGE_DEFINE(datapath_drop_upcall_error);
114
COVERAGE_DEFINE(datapath_drop_lock_error);
115
COVERAGE_DEFINE(datapath_drop_userspace_action_error);
116
COVERAGE_DEFINE(datapath_drop_tunnel_push_error);
117
COVERAGE_DEFINE(datapath_drop_tunnel_pop_error);
118
COVERAGE_DEFINE(datapath_drop_recirc_error);
119
COVERAGE_DEFINE(datapath_drop_invalid_port);
120
COVERAGE_DEFINE(datapath_drop_invalid_bond);
121
COVERAGE_DEFINE(datapath_drop_invalid_tnl_port);
122
COVERAGE_DEFINE(datapath_drop_rx_invalid_packet);
123
COVERAGE_DEFINE(datapath_drop_hw_post_process);
124
COVERAGE_DEFINE(datapath_drop_hw_post_process_consumed);
125
126
COVERAGE_DEFINE(dpif_netdev_output_grow_queues);
127
COVERAGE_DEFINE(dpif_netdev_recirc_big_batch);
128
129
/* Protects against changes to 'dp_netdevs'. */
130
static struct ovs_mutex dp_netdev_mutex = OVS_MUTEX_INITIALIZER;
131
132
/* Contains all 'struct dp_netdev's. */
133
static struct shash dp_netdevs OVS_GUARDED_BY(dp_netdev_mutex)
134
    = SHASH_INITIALIZER(&dp_netdevs);
135
136
static struct vlog_rate_limit upcall_rl = VLOG_RATE_LIMIT_INIT(600, 600);
137
138
0
#define DP_NETDEV_CS_SUPPORTED_MASK (CS_NEW | CS_ESTABLISHED | CS_RELATED \
139
0
                                     | CS_INVALID | CS_REPLY_DIR | CS_TRACKED \
140
0
                                     | CS_SRC_NAT | CS_DST_NAT)
141
0
#define DP_NETDEV_CS_UNSUPPORTED_MASK (~(uint32_t)DP_NETDEV_CS_SUPPORTED_MASK)
142
143
static struct odp_support dp_netdev_support = {
144
    .max_vlan_headers = SIZE_MAX,
145
    .max_mpls_depth = SIZE_MAX,
146
    .recirc = true,
147
    .ct_state = true,
148
    .ct_zone = true,
149
    .ct_mark = true,
150
    .ct_label = true,
151
    .ct_state_nat = true,
152
    .ct_orig_tuple = true,
153
    .ct_orig_tuple6 = true,
154
};
155
156

157
/* Simple non-wildcarding single-priority classifier. */
158
159
/* Time in microseconds between successive optimizations of the dpcls
160
 * subtable vector */
161
0
#define DPCLS_OPTIMIZATION_INTERVAL 1000000LL
162
163
/* Time in microseconds of the interval in which rxq processing cycles used
164
 * in rxq to pmd assignments is measured and stored. */
165
0
#define PMD_INTERVAL_LEN 5000000LL
166
/* For converting PMD_INTERVAL_LEN to secs. */
167
0
#define INTERVAL_USEC_TO_SEC 1000000LL
168
169
/* Number of intervals for which cycles are stored
170
 * and used during rxq to pmd assignment. */
171
0
#define PMD_INTERVAL_MAX 12
172
173
/* Time in microseconds to try RCU quiescing. */
174
0
#define PMD_RCU_QUIESCE_INTERVAL 10000LL
175
176
/* Timer resolution for PMD threads in nanoseconds. */
177
0
#define PMD_TIMER_RES_NS 1000
178
179
/* Number of pkts Rx on an interface that will stop pmd thread sleeping. */
180
0
#define PMD_SLEEP_THRESH (NETDEV_MAX_BURST / 2)
181
/* Time in uS to increment a pmd thread sleep time. */
182
0
#define PMD_SLEEP_INC_US 1
183
184
struct pmd_sleep {
185
    unsigned core_id;
186
    uint64_t max_sleep;
187
};
188
189
struct dpcls {
190
    struct cmap_node node;      /* Within dp_netdev_pmd_thread.classifiers */
191
    odp_port_t in_port;
192
    struct cmap subtables_map;
193
    struct pvector subtables;
194
};
195
196
/* Data structure to keep packet order till fastpath processing. */
197
struct dp_packet_flow_map {
198
    struct dp_packet *packet;
199
    struct dp_netdev_flow *flow;
200
    uint16_t tcp_flags;
201
};
202
203
static void dpcls_init(struct dpcls *);
204
static void dpcls_destroy(struct dpcls *);
205
static void dpcls_sort_subtable_vector(struct dpcls *);
206
static void dpcls_insert(struct dpcls *, struct dpcls_rule *,
207
                         const struct netdev_flow_key *mask);
208
static void dpcls_remove(struct dpcls *, struct dpcls_rule *);
209
210
/* Set of supported meter flags */
211
#define DP_SUPPORTED_METER_FLAGS_MASK \
212
0
    (OFPMF13_STATS | OFPMF13_PKTPS | OFPMF13_KBPS | OFPMF13_BURST)
213
214
/* Set of supported meter band types */
215
#define DP_SUPPORTED_METER_BAND_TYPES           \
216
0
    ( 1 << OFPMBT13_DROP )
217
218
struct dp_meter_band {
219
    uint32_t rate;
220
    uint32_t burst_size;
221
    atomic_uint64_t bucket;          /* In 1/1000 packets for PKTPS,
222
                                      * or in bits for KBPS. */
223
    atomic_uint64_t packet_count;
224
    atomic_uint64_t byte_count;
225
};
226
227
struct dp_meter {
228
    struct cmap_node node;
229
    uint32_t id;
230
    uint16_t flags;
231
    uint16_t n_bands;
232
    uint32_t max_delta_t;
233
    atomic_uint64_t used;  /* Time of a last use in milliseconds. */
234
    atomic_uint64_t packet_count;
235
    atomic_uint64_t byte_count;
236
    struct dp_meter_band bands[];
237
};
238
239
struct pmd_auto_lb {
240
    bool do_dry_run;
241
    bool recheck_config;
242
    bool is_enabled;            /* Current status of Auto load balancing. */
243
    uint64_t rebalance_intvl;
244
    uint64_t rebalance_poll_timer;
245
    uint8_t rebalance_improve_thresh;
246
    atomic_uint8_t rebalance_load_thresh;
247
};
248
249
enum sched_assignment_type {
250
    SCHED_ROUNDROBIN,
251
    SCHED_CYCLES, /* Default.*/
252
    SCHED_GROUP
253
};
254
255
/* Datapath based on the network device interface from netdev.h.
256
 *
257
 *
258
 * Thread-safety
259
 * =============
260
 *
261
 * Some members, marked 'const', are immutable.  Accessing other members
262
 * requires synchronization, as noted in more detail below.
263
 *
264
 * Acquisition order is, from outermost to innermost:
265
 *
266
 *    dp_netdev_mutex (global)
267
 *    port_rwlock
268
 *    bond_mutex
269
 *    non_pmd_mutex
270
 */
271
struct dp_netdev {
272
    const struct dpif_class *const class;
273
    const char *const name;
274
    const char *const full_name;
275
    struct ovs_refcount ref_cnt;
276
    atomic_flag destroyed;
277
278
    /* Ports.
279
     *
280
     * Any lookup into 'ports' or any access to the dp_netdev_ports found
281
     * through 'ports' requires taking 'port_rwlock'. */
282
    struct ovs_rwlock port_rwlock;
283
    struct hmap ports;
284
    struct seq *port_seq;       /* Incremented whenever a port changes. */
285
286
    /* The time that a packet can wait in output batch for sending. */
287
    atomic_uint32_t tx_flush_interval;
288
289
    /* Meters. */
290
    struct ovs_mutex meters_lock;
291
    struct cmap meters;
292
293
    /* Probability of EMC insertions is a factor of 'emc_insert_min'.*/
294
    atomic_uint32_t emc_insert_min;
295
    /* Enable collection of PMD performance metrics. */
296
    atomic_bool pmd_perf_metrics;
297
    /* Default max load based sleep request. */
298
    uint64_t pmd_max_sleep_default;
299
    /* Enable the SMC cache from ovsdb config */
300
    atomic_bool smc_enable_db;
301
302
    /* Protects access to ofproto-dpif-upcall interface during revalidator
303
     * thread synchronization. */
304
    struct fat_rwlock upcall_rwlock;
305
    upcall_callback *upcall_cb;  /* Callback function for executing upcalls. */
306
    void *upcall_aux;
307
308
    /* Callback function for notifying the purging of dp flows (during
309
     * reseting pmd deletion). */
310
    dp_purge_callback *dp_purge_cb;
311
    void *dp_purge_aux;
312
313
    /* Stores all 'struct dp_netdev_pmd_thread's. */
314
    struct cmap poll_threads;
315
    /* id pool for per thread static_tx_qid. */
316
    struct id_pool *tx_qid_pool;
317
    struct ovs_mutex tx_qid_pool_mutex;
318
    /* Rxq to pmd assignment type. */
319
    enum sched_assignment_type pmd_rxq_assign_type;
320
    bool pmd_iso;
321
322
    /* Protects the access of the 'struct dp_netdev_pmd_thread'
323
     * instance for non-pmd thread. */
324
    struct ovs_mutex non_pmd_mutex;
325
326
    /* Each pmd thread will store its pointer to
327
     * 'struct dp_netdev_pmd_thread' in 'per_pmd_key'. */
328
    ovsthread_key_t per_pmd_key;
329
330
    struct seq *reconfigure_seq;
331
    uint64_t last_reconfigure_seq;
332
    struct ovsthread_once once_set_config;
333
334
    /* Cpu mask for pin of pmd threads. */
335
    char *pmd_cmask;
336
337
    /* PMD max load based sleep request user string. */
338
    char *max_sleep_list;
339
340
    uint64_t last_tnl_conf_seq;
341
342
    struct conntrack *conntrack;
343
    struct pmd_auto_lb pmd_alb;
344
345
    /* Bonds. */
346
    struct ovs_mutex bond_mutex; /* Protects updates of 'tx_bonds'. */
347
    struct cmap tx_bonds; /* Contains 'struct tx_bond'. */
348
};
349
350
static struct dp_netdev_port *dp_netdev_lookup_port(const struct dp_netdev *dp,
351
                                                    odp_port_t)
352
    OVS_REQ_RDLOCK(dp->port_rwlock);
353
354
enum rxq_cycles_counter_type {
355
    RXQ_CYCLES_PROC_CURR,       /* Cycles spent successfully polling and
356
                                   processing packets during the current
357
                                   interval. */
358
    RXQ_CYCLES_PROC_HIST,       /* Total cycles of all intervals that are used
359
                                   during rxq to pmd assignment. */
360
    RXQ_N_CYCLES
361
};
362
363
0
#define XPS_TIMEOUT 500000LL    /* In microseconds. */
364
365
/* Contained by struct dp_netdev_port's 'rxqs' member.  */
366
struct dp_netdev_rxq {
367
    struct dp_netdev_port *port;
368
    struct netdev_rxq *rx;
369
    unsigned core_id;                  /* Core to which this queue should be
370
                                          pinned. OVS_CORE_UNSPEC if the
371
                                          queue doesn't need to be pinned to a
372
                                          particular core. */
373
    atomic_count intrvl_idx;           /* Write index for 'cycles_intrvl'. */
374
    struct dp_netdev_pmd_thread *pmd;  /* pmd thread that polls this queue. */
375
    bool is_vhost;                     /* Is rxq of a vhost port. */
376
377
    /* Counters of cycles spent successfully polling and processing pkts. */
378
    atomic_ullong cycles[RXQ_N_CYCLES];
379
    /* We store PMD_INTERVAL_MAX intervals of data for an rxq and then
380
       sum them to yield the cycles used for an rxq. */
381
    atomic_ullong cycles_intrvl[PMD_INTERVAL_MAX];
382
};
383
384
enum txq_req_mode {
385
    TXQ_REQ_MODE_THREAD,
386
    TXQ_REQ_MODE_HASH,
387
};
388
389
enum txq_mode {
390
    TXQ_MODE_STATIC,
391
    TXQ_MODE_XPS,
392
    TXQ_MODE_XPS_HASH,
393
};
394
395
/* A port in a netdev-based datapath. */
396
struct dp_netdev_port {
397
    odp_port_t port_no;
398
    enum txq_mode txq_mode;     /* static, XPS, XPS_HASH. */
399
    bool need_reconfigure;      /* True if we should reconfigure netdev. */
400
    struct netdev *netdev;
401
    struct hmap_node node;      /* Node in dp_netdev's 'ports'. */
402
    struct netdev_saved_flags *sf;
403
    struct dp_netdev_rxq *rxqs;
404
    unsigned n_rxq;             /* Number of elements in 'rxqs' */
405
    unsigned *txq_used;         /* Number of threads that use each tx queue. */
406
    struct ovs_mutex txq_used_mutex;
407
    bool emc_enabled;           /* If true EMC will be used. */
408
    char *type;                 /* Port type as requested by user. */
409
    char *rxq_affinity_list;    /* Requested affinity of rx queues. */
410
    enum txq_req_mode txq_requested_mode;
411
};
412
413
static bool dp_netdev_flow_ref(struct dp_netdev_flow *);
414
static int dpif_netdev_flow_from_nlattrs(const struct nlattr *, uint32_t,
415
                                         struct flow *, bool);
416
417
struct dp_netdev_actions *dp_netdev_actions_create(const struct nlattr *,
418
                                                   size_t);
419
struct dp_netdev_actions *dp_netdev_flow_get_actions(
420
    const struct dp_netdev_flow *);
421
static void dp_netdev_actions_free(struct dp_netdev_actions *);
422
423
struct polled_queue {
424
    struct dp_netdev_rxq *rxq;
425
    odp_port_t port_no;
426
    bool emc_enabled;
427
    bool rxq_enabled;
428
    uint64_t change_seq;
429
};
430
431
/* Contained by struct dp_netdev_pmd_thread's 'poll_list' member. */
432
struct rxq_poll {
433
    struct dp_netdev_rxq *rxq;
434
    struct hmap_node node;
435
};
436
437
/* Contained by struct dp_netdev_pmd_thread's 'send_port_cache',
438
 * 'tnl_port_cache' or 'tx_ports'. */
439
struct tx_port {
440
    struct dp_netdev_port *port;
441
    int qid;
442
    long long last_used;
443
    struct hmap_node node;
444
    long long flush_time;
445
    struct dp_packet_batch output_pkts;
446
    struct dp_packet_batch *txq_pkts; /* Only for hash mode. */
447
    struct dp_netdev_rxq **output_pkts_rxqs;
448
};
449
450
/* Contained by struct tx_bond 'member_buckets'. */
451
struct member_entry {
452
    odp_port_t member_id;
453
    atomic_ullong n_packets;
454
    atomic_ullong n_bytes;
455
};
456
457
/* Contained by struct dp_netdev_pmd_thread's 'tx_bonds'. */
458
struct tx_bond {
459
    struct cmap_node node;
460
    uint32_t bond_id;
461
    struct member_entry member_buckets[BOND_BUCKETS];
462
};
463
464
/* Interface to netdev-based datapath. */
465
struct dpif_netdev {
466
    struct dpif dpif;
467
    struct dp_netdev *dp;
468
    uint64_t last_port_seq;
469
};
470
471
static int get_port_by_number(struct dp_netdev *dp, odp_port_t port_no,
472
                              struct dp_netdev_port **portp)
473
    OVS_REQ_RDLOCK(dp->port_rwlock);
474
static int get_port_by_name(struct dp_netdev *dp, const char *devname,
475
                            struct dp_netdev_port **portp)
476
    OVS_REQ_RDLOCK(dp->port_rwlock);
477
static void dp_netdev_free(struct dp_netdev *)
478
    OVS_REQUIRES(dp_netdev_mutex);
479
static int do_add_port(struct dp_netdev *dp, const char *devname,
480
                       const char *type, odp_port_t port_no)
481
    OVS_REQ_WRLOCK(dp->port_rwlock);
482
static void do_del_port(struct dp_netdev *dp, struct dp_netdev_port *)
483
    OVS_REQ_WRLOCK(dp->port_rwlock);
484
static int dpif_netdev_open(const struct dpif_class *, const char *name,
485
                            bool create, struct dpif **);
486
static void dp_netdev_execute_actions(struct dp_netdev_pmd_thread *pmd,
487
                                      struct dp_packet_batch *,
488
                                      bool should_steal,
489
                                      const struct flow *flow,
490
                                      const struct nlattr *actions,
491
                                      size_t actions_len);
492
static void dp_netdev_input(struct dp_netdev_pmd_thread *,
493
                            struct dp_packet_batch *, odp_port_t port_no);
494
static void dp_netdev_recirculate(struct dp_netdev_pmd_thread *,
495
                                  struct dp_packet_batch *);
496
497
static void dp_netdev_disable_upcall(struct dp_netdev *);
498
static void dp_netdev_pmd_reload_done(struct dp_netdev_pmd_thread *pmd);
499
static void dp_netdev_configure_pmd(struct dp_netdev_pmd_thread *pmd,
500
                                    struct dp_netdev *dp, unsigned core_id,
501
                                    int numa_id);
502
static void dp_netdev_destroy_pmd(struct dp_netdev_pmd_thread *pmd);
503
static void dp_netdev_set_nonpmd(struct dp_netdev *dp)
504
    OVS_REQ_WRLOCK(dp->port_rwlock);
505
506
static void *pmd_thread_main(void *);
507
static struct dp_netdev_pmd_thread *dp_netdev_get_pmd(struct dp_netdev *dp,
508
                                                      unsigned core_id);
509
static struct dp_netdev_pmd_thread *
510
dp_netdev_pmd_get_next(struct dp_netdev *dp, struct cmap_position *pos);
511
static void dp_netdev_del_pmd(struct dp_netdev *dp,
512
                              struct dp_netdev_pmd_thread *pmd);
513
static void dp_netdev_destroy_all_pmds(struct dp_netdev *dp, bool non_pmd);
514
static void dp_netdev_pmd_clear_ports(struct dp_netdev_pmd_thread *pmd);
515
static void dp_netdev_add_port_tx_to_pmd(struct dp_netdev_pmd_thread *pmd,
516
                                         struct dp_netdev_port *port)
517
    OVS_REQUIRES(pmd->port_mutex);
518
static void dp_netdev_del_port_tx_from_pmd(struct dp_netdev_pmd_thread *pmd,
519
                                           struct tx_port *tx)
520
    OVS_REQUIRES(pmd->port_mutex);
521
static void dp_netdev_add_rxq_to_pmd(struct dp_netdev_pmd_thread *pmd,
522
                                     struct dp_netdev_rxq *rxq)
523
    OVS_REQUIRES(pmd->port_mutex);
524
static void dp_netdev_del_rxq_from_pmd(struct dp_netdev_pmd_thread *pmd,
525
                                       struct rxq_poll *poll)
526
    OVS_REQUIRES(pmd->port_mutex);
527
static int
528
dp_netdev_pmd_flush_output_packets(struct dp_netdev_pmd_thread *pmd,
529
                                   bool force);
530
static void dp_netdev_add_bond_tx_to_pmd(struct dp_netdev_pmd_thread *pmd,
531
                                         struct tx_bond *bond, bool update)
532
    OVS_EXCLUDED(pmd->bond_mutex);
533
static void dp_netdev_del_bond_tx_from_pmd(struct dp_netdev_pmd_thread *pmd,
534
                                           uint32_t bond_id)
535
    OVS_EXCLUDED(pmd->bond_mutex);
536
537
static void reconfigure_datapath(struct dp_netdev *dp)
538
    OVS_REQ_RDLOCK(dp->port_rwlock);
539
static bool dp_netdev_pmd_try_ref(struct dp_netdev_pmd_thread *pmd);
540
static void dp_netdev_pmd_unref(struct dp_netdev_pmd_thread *pmd);
541
static void dp_netdev_pmd_flow_flush(struct dp_netdev_pmd_thread *pmd);
542
static void pmd_load_cached_ports(struct dp_netdev_pmd_thread *pmd)
543
    OVS_REQUIRES(pmd->port_mutex);
544
static inline void
545
dp_netdev_pmd_try_optimize(struct dp_netdev_pmd_thread *pmd,
546
                           struct polled_queue *poll_list, int poll_cnt);
547
static void
548
dp_netdev_rxq_set_cycles(struct dp_netdev_rxq *rx,
549
                         enum rxq_cycles_counter_type type,
550
                         unsigned long long cycles);
551
static uint64_t
552
dp_netdev_rxq_get_cycles(struct dp_netdev_rxq *rx,
553
                         enum rxq_cycles_counter_type type);
554
static void
555
dp_netdev_rxq_set_intrvl_cycles(struct dp_netdev_rxq *rx,
556
                           unsigned long long cycles);
557
static uint64_t
558
dp_netdev_rxq_get_intrvl_cycles(struct dp_netdev_rxq *rx, unsigned idx);
559
static uint64_t
560
get_interval_values(atomic_ullong *source, atomic_count *cur_idx,
561
                    int num_to_read);
562
static void
563
dpif_netdev_xps_revalidate_pmd(const struct dp_netdev_pmd_thread *pmd,
564
                               bool purge);
565
static int dpif_netdev_xps_get_tx_qid(const struct dp_netdev_pmd_thread *pmd,
566
                                      struct tx_port *tx);
567
static inline struct dpcls *dp_netdev_pmd_lookup_dpcls(
568
    struct dp_netdev_pmd_thread *pmd, odp_port_t in_port);
569
570
static void dp_netdev_request_reconfigure(struct dp_netdev *dp);
571
static inline bool
572
pmd_perf_metrics_enabled(const struct dp_netdev_pmd_thread *pmd);
573
574
static void dp_netdev_simple_match_insert(struct dp_netdev_pmd_thread *pmd,
575
                                          struct dp_netdev_flow *flow)
576
    OVS_REQUIRES(pmd->flow_mutex);
577
static void dp_netdev_simple_match_remove(struct dp_netdev_pmd_thread *pmd,
578
                                          struct dp_netdev_flow *flow)
579
    OVS_REQUIRES(pmd->flow_mutex);
580
581
static bool dp_netdev_flow_is_simple_match(const struct match *);
582
583
/* Updates the time in PMD threads context and should be called in three cases:
584
 *
585
 *     1. PMD structure initialization:
586
 *         - dp_netdev_configure_pmd()
587
 *
588
 *     2. Before processing of the new packet batch:
589
 *         - dpif_netdev_execute()
590
 *         - dp_netdev_process_rxq_port()
591
 *
592
 *     3. At least once per polling iteration in main polling threads if no
593
 *        packets received on current iteration:
594
 *         - dpif_netdev_run()
595
 *         - pmd_thread_main()
596
 *
597
 * 'pmd->ctx.now' should be used without update in all other cases if possible.
598
 */
599
static inline void
600
pmd_thread_ctx_time_update(struct dp_netdev_pmd_thread *pmd)
601
0
{
602
0
    pmd->ctx.now = time_usec();
603
0
}
604
605
/* Returns true if 'dpif' is a netdev or dummy dpif, false otherwise. */
606
bool
607
dpif_is_netdev(const struct dpif *dpif)
608
0
{
609
0
    return dpif->dpif_class->open == dpif_netdev_open;
610
0
}
611
612
static struct dpif_netdev *
613
dpif_netdev_cast(const struct dpif *dpif)
614
0
{
615
0
    ovs_assert(dpif_is_netdev(dpif));
616
0
    return CONTAINER_OF(dpif, struct dpif_netdev, dpif);
617
0
}
618
619
static struct dp_netdev *
620
get_dp_netdev(const struct dpif *dpif)
621
0
{
622
0
    return dpif_netdev_cast(dpif)->dp;
623
0
}
624

625
enum pmd_info_type {
626
    PMD_INFO_CLEAR_STATS, /* Set the cycle and the packet counters to 0. */
627
    PMD_INFO_SHOW_RXQ,    /* Show poll lists of pmd threads. */
628
    PMD_INFO_PERF_SHOW,   /* Show pmd performance details. */
629
    PMD_INFO_SLEEP_SHOW,  /* Show max sleep configuration details. */
630
};
631
632
static void
633
format_pmd_thread(struct ds *reply, struct dp_netdev_pmd_thread *pmd)
634
0
{
635
0
    ds_put_cstr(reply, (pmd->core_id == NON_PMD_CORE_ID)
636
0
                        ? "main thread" : "pmd thread");
637
0
    if (pmd->numa_id != OVS_NUMA_UNSPEC) {
638
0
        ds_put_format(reply, " numa_id %d", pmd->numa_id);
639
0
    }
640
0
    if (pmd->core_id != OVS_CORE_UNSPEC && pmd->core_id != NON_PMD_CORE_ID) {
641
0
        ds_put_format(reply, " core_id %u", pmd->core_id);
642
0
    }
643
0
    ds_put_cstr(reply, ":\n");
644
0
}
645
646
static void
647
pmd_info_show_perf(struct ds *reply,
648
                   struct dp_netdev_pmd_thread *pmd,
649
                   struct pmd_perf_params *par)
650
0
{
651
0
    char *time_str = xastrftime_msec("%H:%M:%S.###", time_wall_msec(), true);
652
0
    long long now = time_msec();
653
0
    double duration = (now - pmd->perf_stats.start_ms) / 1000.0;
654
655
0
    ds_put_cstr(reply, "\n");
656
0
    ds_put_format(reply, "Time: %s\n", time_str);
657
0
    ds_put_format(reply, "Measurement duration: %.3f s\n", duration);
658
0
    ds_put_cstr(reply, "\n");
659
0
    format_pmd_thread(reply, pmd);
660
0
    ds_put_cstr(reply, "\n");
661
0
    pmd_perf_format_overall_stats(reply, &pmd->perf_stats, duration,
662
0
                                  pmd->core_id != NON_PMD_CORE_ID);
663
0
    if (pmd_perf_metrics_enabled(pmd) && pmd->core_id != NON_PMD_CORE_ID) {
664
        /* Prevent parallel clearing of perf metrics. */
665
0
        ovs_mutex_lock(&pmd->perf_stats.clear_mutex);
666
0
        if (par->histograms) {
667
0
            ds_put_cstr(reply, "\n");
668
0
            pmd_perf_format_histograms(reply, &pmd->perf_stats);
669
0
        }
670
0
        if (par->iter_hist_len > 0) {
671
0
            ds_put_cstr(reply, "\n");
672
0
            pmd_perf_format_iteration_history(reply, &pmd->perf_stats,
673
0
                    par->iter_hist_len);
674
0
        }
675
0
        if (par->ms_hist_len > 0) {
676
0
            ds_put_cstr(reply, "\n");
677
0
            pmd_perf_format_ms_history(reply, &pmd->perf_stats,
678
0
                    par->ms_hist_len);
679
0
        }
680
0
        ovs_mutex_unlock(&pmd->perf_stats.clear_mutex);
681
0
    }
682
0
    free(time_str);
683
0
}
684
685
static int
686
compare_poll_list(const void *a_, const void *b_)
687
0
{
688
0
    const struct rxq_poll *a = a_;
689
0
    const struct rxq_poll *b = b_;
690
691
0
    const char *namea = netdev_rxq_get_name(a->rxq->rx);
692
0
    const char *nameb = netdev_rxq_get_name(b->rxq->rx);
693
694
0
    int cmp = strcmp(namea, nameb);
695
0
    if (!cmp) {
696
0
        return netdev_rxq_get_queue_id(a->rxq->rx)
697
0
               - netdev_rxq_get_queue_id(b->rxq->rx);
698
0
    } else {
699
0
        return cmp;
700
0
    }
701
0
}
702
703
static void
704
sorted_poll_list(struct dp_netdev_pmd_thread *pmd, struct rxq_poll **list,
705
                 size_t *n)
706
    OVS_REQUIRES(pmd->port_mutex)
707
0
{
708
0
    struct rxq_poll *ret, *poll;
709
0
    size_t i;
710
711
0
    *n = hmap_count(&pmd->poll_list);
712
0
    if (!*n) {
713
0
        ret = NULL;
714
0
    } else {
715
0
        ret = xcalloc(*n, sizeof *ret);
716
0
        i = 0;
717
0
        HMAP_FOR_EACH (poll, node, &pmd->poll_list) {
718
0
            ret[i] = *poll;
719
0
            i++;
720
0
        }
721
0
        ovs_assert(i == *n);
722
0
        qsort(ret, *n, sizeof *ret, compare_poll_list);
723
0
    }
724
725
0
    *list = ret;
726
0
}
727
728
static void
729
pmd_info_show_rxq(struct ds *reply, struct dp_netdev_pmd_thread *pmd,
730
                  int secs)
731
0
{
732
0
    if (pmd->core_id != NON_PMD_CORE_ID) {
733
0
        struct rxq_poll *list;
734
0
        size_t n_rxq;
735
0
        uint64_t total_pmd_cycles = 0;
736
0
        uint64_t busy_pmd_cycles = 0;
737
0
        uint64_t total_rxq_proc_cycles = 0;
738
0
        unsigned int intervals;
739
740
0
        ds_put_format(reply,
741
0
                      "pmd thread numa_id %d core_id %u:\n  isolated : %s\n",
742
0
                      pmd->numa_id, pmd->core_id, (pmd->isolated)
743
0
                                                  ? "true" : "false");
744
745
0
        ovs_mutex_lock(&pmd->port_mutex);
746
0
        sorted_poll_list(pmd, &list, &n_rxq);
747
748
        /* Get the total pmd cycles for an interval. */
749
0
        atomic_read_relaxed(&pmd->intrvl_cycles, &total_pmd_cycles);
750
        /* Calculate how many intervals are to be used. */
751
0
        intervals = DIV_ROUND_UP(secs,
752
0
                                 PMD_INTERVAL_LEN / INTERVAL_USEC_TO_SEC);
753
        /* Estimate the cycles to cover all intervals. */
754
0
        total_pmd_cycles *= intervals;
755
0
        busy_pmd_cycles = get_interval_values(pmd->busy_cycles_intrvl,
756
0
                                              &pmd->intrvl_idx,
757
0
                                              intervals);
758
0
        if (busy_pmd_cycles > total_pmd_cycles) {
759
0
            busy_pmd_cycles = total_pmd_cycles;
760
0
        }
761
762
0
        for (int i = 0; i < n_rxq; i++) {
763
0
            struct dp_netdev_rxq *rxq = list[i].rxq;
764
0
            const char *name = netdev_rxq_get_name(rxq->rx);
765
0
            uint64_t rxq_proc_cycles = 0;
766
767
0
            rxq_proc_cycles = get_interval_values(rxq->cycles_intrvl,
768
0
                                                  &rxq->intrvl_idx,
769
0
                                                  intervals);
770
0
            total_rxq_proc_cycles += rxq_proc_cycles;
771
0
            ds_put_format(reply, "  port: %-16s  queue-id: %2d", name,
772
0
                          netdev_rxq_get_queue_id(list[i].rxq->rx));
773
0
            ds_put_format(reply, " %s", netdev_rxq_enabled(list[i].rxq->rx)
774
0
                                        ? "(enabled) " : "(disabled)");
775
0
            ds_put_format(reply, "  pmd usage: ");
776
0
            if (total_pmd_cycles) {
777
0
                ds_put_format(reply, "%2.0f %%",
778
0
                              (double) (rxq_proc_cycles * 100) /
779
0
                              total_pmd_cycles);
780
0
            } else {
781
0
                ds_put_format(reply, "%s", "NOT AVAIL");
782
0
            }
783
0
            ds_put_cstr(reply, "\n");
784
0
        }
785
786
0
        if (n_rxq > 0) {
787
0
            ds_put_cstr(reply, "  overhead: ");
788
0
            if (total_pmd_cycles) {
789
0
                uint64_t overhead_cycles = 0;
790
791
0
                if (total_rxq_proc_cycles < busy_pmd_cycles) {
792
0
                    overhead_cycles = busy_pmd_cycles - total_rxq_proc_cycles;
793
0
                }
794
795
0
                ds_put_format(reply, "%2.0f %%",
796
0
                              (double) (overhead_cycles * 100) /
797
0
                              total_pmd_cycles);
798
0
            } else {
799
0
                ds_put_cstr(reply, "NOT AVAIL");
800
0
            }
801
0
            ds_put_cstr(reply, "\n");
802
0
        }
803
804
0
        ovs_mutex_unlock(&pmd->port_mutex);
805
0
        free(list);
806
0
    }
807
0
}
808
809
static int
810
compare_poll_thread_list(const void *a_, const void *b_)
811
0
{
812
0
    const struct dp_netdev_pmd_thread *a, *b;
813
814
0
    a = *(struct dp_netdev_pmd_thread **)a_;
815
0
    b = *(struct dp_netdev_pmd_thread **)b_;
816
817
0
    if (a->core_id < b->core_id) {
818
0
        return -1;
819
0
    }
820
0
    if (a->core_id > b->core_id) {
821
0
        return 1;
822
0
    }
823
0
    return 0;
824
0
}
825
826
/* Create a sorted list of pmd's from the dp->poll_threads cmap. We can use
827
 * this list, as long as we do not go to quiescent state. */
828
static void
829
sorted_poll_thread_list(struct dp_netdev *dp,
830
                        struct dp_netdev_pmd_thread ***list,
831
                        size_t *n)
832
0
{
833
0
    struct dp_netdev_pmd_thread *pmd;
834
0
    struct dp_netdev_pmd_thread **pmd_list;
835
0
    size_t k = 0, n_pmds;
836
837
0
    n_pmds = cmap_count(&dp->poll_threads);
838
0
    pmd_list = xcalloc(n_pmds, sizeof *pmd_list);
839
840
0
    CMAP_FOR_EACH (pmd, node, &dp->poll_threads) {
841
0
        if (k >= n_pmds) {
842
0
            break;
843
0
        }
844
0
        pmd_list[k++] = pmd;
845
0
    }
846
847
0
    qsort(pmd_list, k, sizeof *pmd_list, compare_poll_thread_list);
848
849
0
    *list = pmd_list;
850
0
    *n = k;
851
0
}
852
853
static void
854
dpif_netdev_pmd_rebalance(struct unixctl_conn *conn, int argc,
855
                          const char *argv[], void *aux OVS_UNUSED)
856
0
{
857
0
    struct ds reply = DS_EMPTY_INITIALIZER;
858
0
    struct dp_netdev *dp = NULL;
859
860
0
    ovs_mutex_lock(&dp_netdev_mutex);
861
862
0
    if (argc == 2) {
863
0
        dp = shash_find_data(&dp_netdevs, argv[1]);
864
0
    } else if (shash_count(&dp_netdevs) == 1) {
865
        /* There's only one datapath */
866
0
        dp = shash_first(&dp_netdevs)->data;
867
0
    }
868
869
0
    if (!dp) {
870
0
        ovs_mutex_unlock(&dp_netdev_mutex);
871
0
        unixctl_command_reply_error(conn,
872
0
                                    "please specify an existing datapath");
873
0
        return;
874
0
    }
875
876
0
    dp_netdev_request_reconfigure(dp);
877
0
    ovs_mutex_unlock(&dp_netdev_mutex);
878
0
    ds_put_cstr(&reply, "pmd rxq rebalance requested.\n");
879
0
    unixctl_command_reply(conn, ds_cstr(&reply));
880
0
    ds_destroy(&reply);
881
0
}
882
883
static void
884
pmd_info_show_sleep(struct ds *reply, unsigned core_id, int numa_id,
885
                    uint64_t pmd_max_sleep)
886
0
{
887
0
    if (core_id == NON_PMD_CORE_ID) {
888
0
        return;
889
0
    }
890
0
    ds_put_format(reply,
891
0
                  "pmd thread numa_id %d core_id %d:\n"
892
0
                  "  max sleep: %4"PRIu64" us\n",
893
0
                  numa_id, core_id, pmd_max_sleep);
894
0
}
895
896
static void
897
dpif_netdev_pmd_info(struct unixctl_conn *conn, int argc, const char *argv[],
898
                     void *aux)
899
0
{
900
0
    struct ds reply = DS_EMPTY_INITIALIZER;
901
0
    struct dp_netdev_pmd_thread **pmd_list;
902
0
    struct dp_netdev *dp = NULL;
903
0
    enum pmd_info_type type = *(enum pmd_info_type *) aux;
904
0
    unsigned int core_id;
905
0
    bool filter_on_pmd = false;
906
0
    size_t n;
907
0
    unsigned int secs = 0;
908
0
    unsigned long long max_secs = (PMD_INTERVAL_LEN * PMD_INTERVAL_MAX)
909
0
                                      / INTERVAL_USEC_TO_SEC;
910
0
    bool show_header = true;
911
0
    uint64_t max_sleep;
912
913
0
    ovs_mutex_lock(&dp_netdev_mutex);
914
915
0
    while (argc > 1) {
916
0
        if (!strcmp(argv[1], "-pmd") && argc > 2) {
917
0
            if (str_to_uint(argv[2], 10, &core_id)) {
918
0
                filter_on_pmd = true;
919
0
            }
920
0
            argc -= 2;
921
0
            argv += 2;
922
0
        } else if (type == PMD_INFO_SHOW_RXQ &&
923
0
                       !strcmp(argv[1], "-secs") &&
924
0
                       argc > 2) {
925
0
            if (!str_to_uint(argv[2], 10, &secs)) {
926
0
                secs = max_secs;
927
0
            }
928
0
            argc -= 2;
929
0
            argv += 2;
930
0
        } else {
931
0
            dp = shash_find_data(&dp_netdevs, argv[1]);
932
0
            argc -= 1;
933
0
            argv += 1;
934
0
        }
935
0
    }
936
937
0
    if (!dp) {
938
0
        if (shash_count(&dp_netdevs) == 1) {
939
            /* There's only one datapath */
940
0
            dp = shash_first(&dp_netdevs)->data;
941
0
        } else {
942
0
            ovs_mutex_unlock(&dp_netdev_mutex);
943
0
            unixctl_command_reply_error(conn,
944
0
                                        "please specify an existing datapath");
945
0
            return;
946
0
        }
947
0
    }
948
949
0
    sorted_poll_thread_list(dp, &pmd_list, &n);
950
0
    for (size_t i = 0; i < n; i++) {
951
0
        struct dp_netdev_pmd_thread *pmd = pmd_list[i];
952
0
        if (!pmd) {
953
0
            break;
954
0
        }
955
0
        if (filter_on_pmd && pmd->core_id != core_id) {
956
0
            continue;
957
0
        }
958
0
        if (type == PMD_INFO_SHOW_RXQ) {
959
0
            if (show_header) {
960
0
                if (!secs || secs > max_secs) {
961
0
                    secs = max_secs;
962
0
                } else {
963
0
                    secs = ROUND_UP(secs,
964
0
                                    PMD_INTERVAL_LEN / INTERVAL_USEC_TO_SEC);
965
0
                }
966
0
                ds_put_format(&reply, "Displaying last %u seconds "
967
0
                              "pmd usage %%\n", secs);
968
0
                show_header = false;
969
0
            }
970
0
            pmd_info_show_rxq(&reply, pmd, secs);
971
0
        } else if (type == PMD_INFO_CLEAR_STATS) {
972
0
            pmd_perf_stats_clear(&pmd->perf_stats);
973
0
        } else if (type == PMD_INFO_PERF_SHOW) {
974
0
            pmd_info_show_perf(&reply, pmd, (struct pmd_perf_params *)aux);
975
0
        } else if (type == PMD_INFO_SLEEP_SHOW) {
976
0
            if (show_header) {
977
0
                ds_put_format(&reply, "Default max sleep: %4"PRIu64" us\n",
978
0
                              dp->pmd_max_sleep_default);
979
0
                show_header = false;
980
0
            }
981
0
            atomic_read_relaxed(&pmd->max_sleep, &max_sleep);
982
0
            pmd_info_show_sleep(&reply, pmd->core_id, pmd->numa_id,
983
0
                                max_sleep);
984
0
        }
985
0
    }
986
0
    free(pmd_list);
987
988
0
    ovs_mutex_unlock(&dp_netdev_mutex);
989
990
0
    unixctl_command_reply(conn, ds_cstr(&reply));
991
0
    ds_destroy(&reply);
992
0
}
993
994
static void
995
pmd_perf_show_cmd(struct unixctl_conn *conn, int argc,
996
                          const char *argv[],
997
                          void *aux OVS_UNUSED)
998
0
{
999
0
    struct pmd_perf_params par;
1000
0
    long int it_hist = 0, ms_hist = 0;
1001
0
    par.histograms = true;
1002
1003
0
    while (argc > 1) {
1004
0
        if (!strcmp(argv[1], "-nh")) {
1005
0
            par.histograms = false;
1006
0
            argc -= 1;
1007
0
            argv += 1;
1008
0
        } else if (!strcmp(argv[1], "-it") && argc > 2) {
1009
0
            it_hist = strtol(argv[2], NULL, 10);
1010
0
            if (it_hist < 0) {
1011
0
                it_hist = 0;
1012
0
            } else if (it_hist > HISTORY_LEN) {
1013
0
                it_hist = HISTORY_LEN;
1014
0
            }
1015
0
            argc -= 2;
1016
0
            argv += 2;
1017
0
        } else if (!strcmp(argv[1], "-ms") && argc > 2) {
1018
0
            ms_hist = strtol(argv[2], NULL, 10);
1019
0
            if (ms_hist < 0) {
1020
0
                ms_hist = 0;
1021
0
            } else if (ms_hist > HISTORY_LEN) {
1022
0
                ms_hist = HISTORY_LEN;
1023
0
            }
1024
0
            argc -= 2;
1025
0
            argv += 2;
1026
0
        } else {
1027
0
            break;
1028
0
        }
1029
0
    }
1030
0
    par.iter_hist_len = it_hist;
1031
0
    par.ms_hist_len = ms_hist;
1032
0
    par.command_type = PMD_INFO_PERF_SHOW;
1033
0
    dpif_netdev_pmd_info(conn, argc, argv, &par);
1034
0
}
1035
1036
static void
1037
dpif_netdev_bond_show(struct unixctl_conn *conn, int argc,
1038
                      const char *argv[], void *aux OVS_UNUSED)
1039
0
{
1040
0
    struct ds reply = DS_EMPTY_INITIALIZER;
1041
0
    struct dp_netdev *dp = NULL;
1042
1043
0
    ovs_mutex_lock(&dp_netdev_mutex);
1044
0
    if (argc == 2) {
1045
0
        dp = shash_find_data(&dp_netdevs, argv[1]);
1046
0
    } else if (shash_count(&dp_netdevs) == 1) {
1047
        /* There's only one datapath. */
1048
0
        dp = shash_first(&dp_netdevs)->data;
1049
0
    }
1050
0
    if (!dp) {
1051
0
        ovs_mutex_unlock(&dp_netdev_mutex);
1052
0
        unixctl_command_reply_error(conn,
1053
0
                                    "please specify an existing datapath");
1054
0
        return;
1055
0
    }
1056
1057
0
    if (cmap_count(&dp->tx_bonds) > 0) {
1058
0
        struct tx_bond *dp_bond_entry;
1059
1060
0
        ds_put_cstr(&reply, "Bonds:\n");
1061
0
        CMAP_FOR_EACH (dp_bond_entry, node, &dp->tx_bonds) {
1062
0
            ds_put_format(&reply, "  bond-id %"PRIu32":\n",
1063
0
                          dp_bond_entry->bond_id);
1064
0
            for (int bucket = 0; bucket < BOND_BUCKETS; bucket++) {
1065
0
                uint32_t member_id = odp_to_u32(
1066
0
                    dp_bond_entry->member_buckets[bucket].member_id);
1067
0
                ds_put_format(&reply,
1068
0
                              "    bucket %d - member %"PRIu32"\n",
1069
0
                              bucket, member_id);
1070
0
            }
1071
0
        }
1072
0
    }
1073
0
    ovs_mutex_unlock(&dp_netdev_mutex);
1074
0
    unixctl_command_reply(conn, ds_cstr(&reply));
1075
0
    ds_destroy(&reply);
1076
0
}
1077
1078

1079
static int
1080
dpif_netdev_init(void)
1081
0
{
1082
0
    static enum pmd_info_type clear_aux = PMD_INFO_CLEAR_STATS,
1083
0
                              poll_aux = PMD_INFO_SHOW_RXQ,
1084
0
                              sleep_aux = PMD_INFO_SLEEP_SHOW;
1085
1086
0
    unixctl_command_register("dpif-netdev/pmd-stats-clear", "[-pmd core] [dp]",
1087
0
                             0, 3, dpif_netdev_pmd_info,
1088
0
                             (void *)&clear_aux);
1089
0
    unixctl_command_register("dpif-netdev/pmd-rxq-show", "[-pmd core] "
1090
0
                             "[-secs secs] [dp]",
1091
0
                             0, 5, dpif_netdev_pmd_info,
1092
0
                             (void *)&poll_aux);
1093
0
    unixctl_command_register("dpif-netdev/pmd-sleep-show", "[dp]",
1094
0
                             0, 1, dpif_netdev_pmd_info,
1095
0
                             (void *)&sleep_aux);
1096
0
    unixctl_command_register("dpif-netdev/pmd-perf-show",
1097
0
                             "[-nh] [-it iter-history-len]"
1098
0
                             " [-ms ms-history-len]"
1099
0
                             " [-pmd core] [dp]",
1100
0
                             0, 8, pmd_perf_show_cmd,
1101
0
                             NULL);
1102
    /* 'pmd-stats-show' is just an undocumented alias for 'pmd-perf-show',
1103
     * for compatibility with old muscle memory. */
1104
0
    unixctl_command_register("dpif-netdev/pmd-stats-show", NULL,
1105
0
                             0, 8, pmd_perf_show_cmd, NULL);
1106
0
    unixctl_command_register("dpif-netdev/pmd-rxq-rebalance", "[dp]",
1107
0
                             0, 1, dpif_netdev_pmd_rebalance,
1108
0
                             NULL);
1109
0
    unixctl_command_register("dpif-netdev/pmd-perf-log-set",
1110
0
                             "on|off [-b before] [-a after] [-e|-ne] "
1111
0
                             "[-us usec] [-q qlen]",
1112
0
                             0, 10, pmd_perf_log_set_cmd,
1113
0
                             NULL);
1114
0
    unixctl_command_register("dpif-netdev/bond-show", "[dp]",
1115
0
                             0, 1, dpif_netdev_bond_show,
1116
0
                             NULL);
1117
0
    return 0;
1118
0
}
1119
1120
static int
1121
dpif_netdev_enumerate(struct sset *all_dps,
1122
                      const struct dpif_class *dpif_class)
1123
0
{
1124
0
    struct shash_node *node;
1125
1126
0
    ovs_mutex_lock(&dp_netdev_mutex);
1127
0
    SHASH_FOR_EACH(node, &dp_netdevs) {
1128
0
        struct dp_netdev *dp = node->data;
1129
0
        if (dpif_class != dp->class) {
1130
            /* 'dp_netdevs' contains both "netdev" and "dummy" dpifs.
1131
             * If the class doesn't match, skip this dpif. */
1132
0
             continue;
1133
0
        }
1134
0
        sset_add(all_dps, node->name);
1135
0
    }
1136
0
    ovs_mutex_unlock(&dp_netdev_mutex);
1137
1138
0
    return 0;
1139
0
}
1140
1141
static bool
1142
dpif_netdev_class_is_dummy(const struct dpif_class *class)
1143
0
{
1144
0
    return class != &dpif_netdev_class;
1145
0
}
1146
1147
static const char *
1148
dpif_netdev_port_open_type(const struct dpif_class *class, const char *type)
1149
0
{
1150
0
    return strcmp(type, "internal") ? type
1151
0
                  : dpif_netdev_class_is_dummy(class) ? "dummy-internal"
1152
0
                  : "tap";
1153
0
}
1154
1155
static struct dpif *
1156
create_dpif_netdev(struct dp_netdev *dp)
1157
0
{
1158
0
    uint16_t netflow_id = hash_string(dp->name, 0);
1159
0
    struct dpif_netdev *dpif;
1160
1161
0
    ovs_refcount_ref(&dp->ref_cnt);
1162
1163
0
    dpif = xmalloc(sizeof *dpif);
1164
0
    dpif_init(&dpif->dpif, dp->class, dp->name, netflow_id >> 8, netflow_id);
1165
0
    dpif->dp = dp;
1166
0
    dpif->last_port_seq = seq_read(dp->port_seq);
1167
1168
0
    return &dpif->dpif;
1169
0
}
1170
1171
/* Choose an unused, non-zero port number and return it on success.
1172
 * Return ODPP_NONE on failure. */
1173
static odp_port_t
1174
choose_port(struct dp_netdev *dp, const char *name)
1175
    OVS_REQ_RDLOCK(dp->port_rwlock)
1176
0
{
1177
0
    uint32_t port_no;
1178
1179
0
    if (dp->class != &dpif_netdev_class) {
1180
0
        const char *p;
1181
0
        int start_no = 0;
1182
1183
        /* If the port name begins with "br", start the number search at
1184
         * 100 to make writing tests easier. */
1185
0
        if (!strncmp(name, "br", 2)) {
1186
0
            start_no = 100;
1187
0
        }
1188
1189
        /* If the port name contains a number, try to assign that port number.
1190
         * This can make writing unit tests easier because port numbers are
1191
         * predictable. */
1192
0
        for (p = name; *p != '\0'; p++) {
1193
0
            if (isdigit((unsigned char) *p)) {
1194
0
                port_no = start_no + strtol(p, NULL, 10);
1195
0
                if (port_no > 0 && port_no != odp_to_u32(ODPP_NONE)
1196
0
                    && !dp_netdev_lookup_port(dp, u32_to_odp(port_no))) {
1197
0
                    return u32_to_odp(port_no);
1198
0
                }
1199
0
                break;
1200
0
            }
1201
0
        }
1202
0
    }
1203
1204
0
    for (port_no = 1; port_no <= UINT16_MAX; port_no++) {
1205
0
        if (!dp_netdev_lookup_port(dp, u32_to_odp(port_no))) {
1206
0
            return u32_to_odp(port_no);
1207
0
        }
1208
0
    }
1209
1210
0
    return ODPP_NONE;
1211
0
}
1212
1213
static uint32_t
1214
dp_meter_hash(uint32_t meter_id)
1215
0
{
1216
    /* In the ofproto-dpif layer, we use the id-pool to alloc meter id
1217
     * orderly (e.g. 1, 2, ... N.), which provides a better hash
1218
     * distribution.  Use them directly instead of hash_xxx function for
1219
     * achieving high-performance. */
1220
0
    return meter_id;
1221
0
}
1222
1223
static void
1224
dp_netdev_meter_destroy(struct dp_netdev *dp)
1225
0
{
1226
0
    struct dp_meter *m;
1227
1228
0
    ovs_mutex_lock(&dp->meters_lock);
1229
0
    CMAP_FOR_EACH (m, node, &dp->meters) {
1230
0
        cmap_remove(&dp->meters, &m->node, dp_meter_hash(m->id));
1231
0
        ovsrcu_postpone(free, m);
1232
0
    }
1233
1234
0
    cmap_destroy(&dp->meters);
1235
0
    ovs_mutex_unlock(&dp->meters_lock);
1236
0
    ovs_mutex_destroy(&dp->meters_lock);
1237
0
}
1238
1239
static struct dp_meter *
1240
dp_meter_lookup(struct cmap *meters, uint32_t meter_id)
1241
0
{
1242
0
    uint32_t hash = dp_meter_hash(meter_id);
1243
0
    struct dp_meter *m;
1244
1245
0
    CMAP_FOR_EACH_WITH_HASH (m, node, hash, meters) {
1246
0
        if (m->id == meter_id) {
1247
0
            return m;
1248
0
        }
1249
0
    }
1250
1251
0
    return NULL;
1252
0
}
1253
1254
static void
1255
dp_meter_detach_free(struct cmap *meters, uint32_t meter_id)
1256
0
{
1257
0
    struct dp_meter *m = dp_meter_lookup(meters, meter_id);
1258
1259
0
    if (m) {
1260
0
        cmap_remove(meters, &m->node, dp_meter_hash(meter_id));
1261
0
        ovsrcu_postpone(free, m);
1262
0
    }
1263
0
}
1264
1265
static void
1266
dp_meter_attach(struct cmap *meters, struct dp_meter *meter)
1267
0
{
1268
0
    cmap_insert(meters, &meter->node, dp_meter_hash(meter->id));
1269
0
}
1270
1271
static int
1272
create_dp_netdev(const char *name, const struct dpif_class *class,
1273
                 struct dp_netdev **dpp)
1274
    OVS_REQUIRES(dp_netdev_mutex)
1275
0
{
1276
0
    static struct ovsthread_once tsc_freq_check = OVSTHREAD_ONCE_INITIALIZER;
1277
0
    struct dp_netdev *dp;
1278
0
    int error;
1279
1280
    /* Avoid estimating TSC frequency for dummy datapath to not slow down
1281
     * unit tests. */
1282
0
    if (!dpif_netdev_class_is_dummy(class)
1283
0
        && ovsthread_once_start(&tsc_freq_check)) {
1284
0
        pmd_perf_estimate_tsc_frequency();
1285
0
        ovsthread_once_done(&tsc_freq_check);
1286
0
    }
1287
1288
0
    dp = xzalloc(sizeof *dp);
1289
0
    shash_add(&dp_netdevs, name, dp);
1290
1291
0
    *CONST_CAST(const struct dpif_class **, &dp->class) = class;
1292
0
    *CONST_CAST(const char **, &dp->name) = xstrdup(name);
1293
0
    *CONST_CAST(const char **, &dp->full_name) = xasprintf("%s@%s",
1294
0
                                                           class->type, name);
1295
0
    ovs_refcount_init(&dp->ref_cnt);
1296
0
    atomic_flag_clear(&dp->destroyed);
1297
1298
0
    ovs_rwlock_init(&dp->port_rwlock);
1299
0
    hmap_init(&dp->ports);
1300
0
    dp->port_seq = seq_create();
1301
0
    ovs_mutex_init(&dp->bond_mutex);
1302
0
    cmap_init(&dp->tx_bonds);
1303
1304
0
    fat_rwlock_init(&dp->upcall_rwlock);
1305
1306
0
    dp->reconfigure_seq = seq_create();
1307
0
    dp->last_reconfigure_seq = seq_read(dp->reconfigure_seq);
1308
0
    dp->once_set_config = (struct ovsthread_once) OVSTHREAD_ONCE_INITIALIZER;
1309
1310
    /* Init meter resources. */
1311
0
    cmap_init(&dp->meters);
1312
0
    ovs_mutex_init(&dp->meters_lock);
1313
1314
    /* Disable upcalls by default. */
1315
0
    dp_netdev_disable_upcall(dp);
1316
0
    dp->upcall_aux = NULL;
1317
0
    dp->upcall_cb = NULL;
1318
1319
0
    dp->conntrack = conntrack_init();
1320
1321
0
    atomic_init(&dp->emc_insert_min, DEFAULT_EM_FLOW_INSERT_MIN);
1322
0
    atomic_init(&dp->tx_flush_interval, DEFAULT_TX_FLUSH_INTERVAL);
1323
1324
0
    cmap_init(&dp->poll_threads);
1325
0
    dp->pmd_rxq_assign_type = SCHED_CYCLES;
1326
1327
0
    ovs_mutex_init(&dp->tx_qid_pool_mutex);
1328
    /* We need 1 Tx queue for each possible core + 1 for non-PMD threads. */
1329
0
    dp->tx_qid_pool = id_pool_create(0, ovs_numa_get_n_cores() + 1);
1330
1331
0
    ovs_mutex_init_recursive(&dp->non_pmd_mutex);
1332
0
    ovsthread_key_create(&dp->per_pmd_key, NULL);
1333
1334
0
    ovs_rwlock_wrlock(&dp->port_rwlock);
1335
    /* non-PMD will be created before all other threads and will
1336
     * allocate static_tx_qid = 0. */
1337
0
    dp_netdev_set_nonpmd(dp);
1338
1339
0
    error = do_add_port(dp, name, dpif_netdev_port_open_type(dp->class,
1340
0
                                                             "internal"),
1341
0
                        ODPP_LOCAL);
1342
0
    ovs_rwlock_unlock(&dp->port_rwlock);
1343
0
    if (error) {
1344
0
        dp_netdev_free(dp);
1345
0
        return error;
1346
0
    }
1347
1348
0
    dp->max_sleep_list = NULL;
1349
1350
0
    dp->last_tnl_conf_seq = seq_read(tnl_conf_seq);
1351
0
    *dpp = dp;
1352
0
    return 0;
1353
0
}
1354
1355
static void
1356
dp_netdev_request_reconfigure(struct dp_netdev *dp)
1357
0
{
1358
0
    seq_change(dp->reconfigure_seq);
1359
0
}
1360
1361
static bool
1362
dp_netdev_is_reconf_required(struct dp_netdev *dp)
1363
0
{
1364
0
    return seq_read(dp->reconfigure_seq) != dp->last_reconfigure_seq;
1365
0
}
1366
1367
static int
1368
dpif_netdev_open(const struct dpif_class *class, const char *name,
1369
                 bool create, struct dpif **dpifp)
1370
0
{
1371
0
    struct dp_netdev *dp;
1372
0
    int error;
1373
1374
0
    ovs_mutex_lock(&dp_netdev_mutex);
1375
0
    dp = shash_find_data(&dp_netdevs, name);
1376
0
    if (!dp) {
1377
0
        error = create ? create_dp_netdev(name, class, &dp) : ENODEV;
1378
0
    } else {
1379
0
        error = (dp->class != class ? EINVAL
1380
0
                 : create ? EEXIST
1381
0
                 : 0);
1382
0
    }
1383
0
    if (!error) {
1384
0
        *dpifp = create_dpif_netdev(dp);
1385
0
    }
1386
0
    ovs_mutex_unlock(&dp_netdev_mutex);
1387
1388
0
    return error;
1389
0
}
1390
1391
static void
1392
dp_netdev_destroy_upcall_lock(struct dp_netdev *dp)
1393
    OVS_NO_THREAD_SAFETY_ANALYSIS
1394
0
{
1395
    /* Check that upcalls are disabled, i.e. that the rwlock is taken */
1396
0
    ovs_assert(fat_rwlock_tryrdlock(&dp->upcall_rwlock));
1397
1398
    /* Before freeing a lock we should release it */
1399
0
    fat_rwlock_unlock(&dp->upcall_rwlock);
1400
0
    fat_rwlock_destroy(&dp->upcall_rwlock);
1401
0
}
1402
1403
static uint32_t
1404
hash_bond_id(uint32_t bond_id)
1405
0
{
1406
0
    return hash_int(bond_id, 0);
1407
0
}
1408
1409
/* Requires dp_netdev_mutex so that we can't get a new reference to 'dp'
1410
 * through the 'dp_netdevs' shash while freeing 'dp'. */
1411
static void
1412
dp_netdev_free(struct dp_netdev *dp)
1413
    OVS_REQUIRES(dp_netdev_mutex)
1414
0
{
1415
0
    struct dp_netdev_port *port;
1416
0
    struct tx_bond *bond;
1417
1418
0
    shash_find_and_delete(&dp_netdevs, dp->name);
1419
1420
0
    ovs_rwlock_wrlock(&dp->port_rwlock);
1421
0
    HMAP_FOR_EACH_SAFE (port, node, &dp->ports) {
1422
0
        do_del_port(dp, port);
1423
0
    }
1424
0
    ovs_rwlock_unlock(&dp->port_rwlock);
1425
1426
0
    ovs_mutex_lock(&dp->bond_mutex);
1427
0
    CMAP_FOR_EACH (bond, node, &dp->tx_bonds) {
1428
0
        cmap_remove(&dp->tx_bonds, &bond->node, hash_bond_id(bond->bond_id));
1429
0
        ovsrcu_postpone(free, bond);
1430
0
    }
1431
0
    ovs_mutex_unlock(&dp->bond_mutex);
1432
1433
0
    dp_netdev_destroy_all_pmds(dp, true);
1434
0
    cmap_destroy(&dp->poll_threads);
1435
1436
0
    ovs_mutex_destroy(&dp->tx_qid_pool_mutex);
1437
0
    id_pool_destroy(dp->tx_qid_pool);
1438
1439
0
    ovs_mutex_destroy(&dp->non_pmd_mutex);
1440
0
    ovsthread_key_delete(dp->per_pmd_key);
1441
1442
0
    conntrack_destroy(dp->conntrack);
1443
1444
1445
0
    seq_destroy(dp->reconfigure_seq);
1446
0
    ovsthread_once_destroy(&dp->once_set_config);
1447
1448
0
    seq_destroy(dp->port_seq);
1449
0
    hmap_destroy(&dp->ports);
1450
0
    ovs_rwlock_destroy(&dp->port_rwlock);
1451
1452
0
    cmap_destroy(&dp->tx_bonds);
1453
0
    ovs_mutex_destroy(&dp->bond_mutex);
1454
1455
    /* Upcalls must be disabled at this point */
1456
0
    dp_netdev_destroy_upcall_lock(dp);
1457
1458
0
    dp_netdev_meter_destroy(dp);
1459
1460
0
    free(dp->max_sleep_list);
1461
0
    free(dp->pmd_cmask);
1462
0
    free(CONST_CAST(char *, dp->name));
1463
0
    free(CONST_CAST(char *, dp->full_name));
1464
0
    free(dp);
1465
0
}
1466
1467
static void
1468
dp_netdev_unref(struct dp_netdev *dp)
1469
0
{
1470
0
    if (dp) {
1471
        /* Take dp_netdev_mutex so that, if dp->ref_cnt falls to zero, we can't
1472
         * get a new reference to 'dp' through the 'dp_netdevs' shash. */
1473
0
        ovs_mutex_lock(&dp_netdev_mutex);
1474
0
        if (ovs_refcount_unref_relaxed(&dp->ref_cnt) == 1) {
1475
0
            dp_netdev_free(dp);
1476
0
        }
1477
0
        ovs_mutex_unlock(&dp_netdev_mutex);
1478
0
    }
1479
0
}
1480
1481
static void
1482
dpif_netdev_close(struct dpif *dpif)
1483
0
{
1484
0
    struct dp_netdev *dp = get_dp_netdev(dpif);
1485
1486
0
    dp_netdev_unref(dp);
1487
0
    free(dpif);
1488
0
}
1489
1490
static int
1491
dpif_netdev_destroy(struct dpif *dpif)
1492
0
{
1493
0
    struct dp_netdev *dp = get_dp_netdev(dpif);
1494
1495
0
    if (!atomic_flag_test_and_set(&dp->destroyed)) {
1496
0
        if (ovs_refcount_unref_relaxed(&dp->ref_cnt) == 1) {
1497
            /* Can't happen: 'dpif' still owns a reference to 'dp'. */
1498
0
            OVS_NOT_REACHED();
1499
0
        }
1500
0
    }
1501
1502
0
    return 0;
1503
0
}
1504
1505
/* Add 'n' to the atomic variable 'var' non-atomically and using relaxed
1506
 * load/store semantics.  While the increment is not atomic, the load and
1507
 * store operations are, making it impossible to read inconsistent values.
1508
 *
1509
 * This is used to update thread local stats counters. */
1510
static void
1511
non_atomic_ullong_add(atomic_ullong *var, unsigned long long n)
1512
0
{
1513
0
    unsigned long long tmp;
1514
1515
0
    atomic_read_relaxed(var, &tmp);
1516
0
    tmp += n;
1517
0
    atomic_store_relaxed(var, tmp);
1518
0
}
1519
1520
static int
1521
dpif_netdev_get_stats(const struct dpif *dpif, struct dpif_dp_stats *stats)
1522
0
{
1523
0
    struct dp_netdev *dp = get_dp_netdev(dpif);
1524
0
    struct dp_netdev_pmd_thread *pmd;
1525
0
    uint64_t pmd_stats[PMD_N_STATS];
1526
1527
0
    stats->n_flows = stats->n_hit = stats->n_missed = stats->n_lost = 0;
1528
0
    CMAP_FOR_EACH (pmd, node, &dp->poll_threads) {
1529
0
        stats->n_flows += cmap_count(&pmd->flow_table);
1530
0
        pmd_perf_read_counters(&pmd->perf_stats, pmd_stats);
1531
0
        stats->n_hit += pmd_stats[PMD_STAT_PHWOL_HIT];
1532
0
        stats->n_hit += pmd_stats[PMD_STAT_SIMPLE_HIT];
1533
0
        stats->n_hit += pmd_stats[PMD_STAT_EXACT_HIT];
1534
0
        stats->n_hit += pmd_stats[PMD_STAT_SMC_HIT];
1535
0
        stats->n_hit += pmd_stats[PMD_STAT_MASKED_HIT];
1536
0
        stats->n_missed += pmd_stats[PMD_STAT_MISS];
1537
0
        stats->n_lost += pmd_stats[PMD_STAT_LOST];
1538
0
    }
1539
0
    stats->n_masks = UINT32_MAX;
1540
0
    stats->n_mask_hit = UINT64_MAX;
1541
0
    stats->n_cache_hit = UINT64_MAX;
1542
1543
0
    return 0;
1544
0
}
1545
1546
static void
1547
dp_netdev_reload_pmd__(struct dp_netdev_pmd_thread *pmd)
1548
0
{
1549
0
    if (pmd->core_id == NON_PMD_CORE_ID) {
1550
0
        ovs_mutex_lock(&pmd->dp->non_pmd_mutex);
1551
0
        ovs_mutex_lock(&pmd->port_mutex);
1552
0
        pmd_load_cached_ports(pmd);
1553
0
        ovs_mutex_unlock(&pmd->port_mutex);
1554
0
        ovs_mutex_unlock(&pmd->dp->non_pmd_mutex);
1555
0
        return;
1556
0
    }
1557
1558
0
    seq_change(pmd->reload_seq);
1559
0
    atomic_store_explicit(&pmd->reload, true, memory_order_release);
1560
0
}
1561
1562
static uint32_t
1563
hash_port_no(odp_port_t port_no)
1564
0
{
1565
0
    return hash_int(odp_to_u32(port_no), 0);
1566
0
}
1567
1568
static int
1569
port_create(const char *devname, const char *type,
1570
            odp_port_t port_no, struct dp_netdev_port **portp)
1571
0
{
1572
0
    struct dp_netdev_port *port;
1573
0
    enum netdev_flags flags;
1574
0
    struct netdev *netdev;
1575
0
    int error;
1576
1577
0
    *portp = NULL;
1578
1579
    /* Open and validate network device. */
1580
0
    error = netdev_open(devname, type, &netdev);
1581
0
    if (error) {
1582
0
        return error;
1583
0
    }
1584
    /* XXX reject non-Ethernet devices */
1585
1586
0
    netdev_get_flags(netdev, &flags);
1587
0
    if (flags & NETDEV_LOOPBACK) {
1588
0
        VLOG_ERR("%s: cannot add a loopback device", devname);
1589
0
        error = EINVAL;
1590
0
        goto out;
1591
0
    }
1592
1593
0
    port = xzalloc(sizeof *port);
1594
0
    port->port_no = port_no;
1595
0
    port->netdev = netdev;
1596
0
    port->type = xstrdup(type);
1597
0
    port->sf = NULL;
1598
0
    port->emc_enabled = true;
1599
0
    port->need_reconfigure = true;
1600
0
    ovs_mutex_init(&port->txq_used_mutex);
1601
1602
0
    *portp = port;
1603
1604
0
    return 0;
1605
1606
0
out:
1607
0
    netdev_close(netdev);
1608
0
    return error;
1609
0
}
1610
1611
static int
1612
do_add_port(struct dp_netdev *dp, const char *devname, const char *type,
1613
            odp_port_t port_no)
1614
    OVS_REQ_WRLOCK(dp->port_rwlock)
1615
0
{
1616
0
    struct netdev_saved_flags *sf;
1617
0
    struct dp_netdev_port *port;
1618
0
    int error;
1619
1620
    /* Reject devices already in 'dp'. */
1621
0
    if (!get_port_by_name(dp, devname, &port)) {
1622
0
        return EEXIST;
1623
0
    }
1624
1625
0
    error = port_create(devname, type, port_no, &port);
1626
0
    if (error) {
1627
0
        return error;
1628
0
    }
1629
1630
0
    hmap_insert(&dp->ports, &port->node, hash_port_no(port_no));
1631
0
    seq_change(dp->port_seq);
1632
1633
0
    reconfigure_datapath(dp);
1634
1635
    /* Check that port was successfully configured. */
1636
0
    if (!dp_netdev_lookup_port(dp, port_no)) {
1637
0
        return EINVAL;
1638
0
    }
1639
1640
    /* Updating device flags triggers an if_notifier, which triggers a bridge
1641
     * reconfiguration and another attempt to add this port, leading to an
1642
     * infinite loop if the device is configured incorrectly and cannot be
1643
     * added.  Setting the promisc mode after a successful reconfiguration,
1644
     * since we already know that the device is somehow properly configured. */
1645
0
    error = netdev_turn_flags_on(port->netdev, NETDEV_PROMISC, &sf);
1646
0
    if (error) {
1647
0
        VLOG_ERR("%s: cannot set promisc flag", devname);
1648
0
        do_del_port(dp, port);
1649
0
        return error;
1650
0
    }
1651
0
    port->sf = sf;
1652
1653
0
    return 0;
1654
0
}
1655
1656
static int
1657
dpif_netdev_port_add(struct dpif *dpif, struct netdev *netdev,
1658
                     odp_port_t *port_nop)
1659
0
{
1660
0
    struct dp_netdev *dp = get_dp_netdev(dpif);
1661
0
    char namebuf[NETDEV_VPORT_NAME_BUFSIZE];
1662
0
    const char *dpif_port;
1663
0
    odp_port_t port_no;
1664
0
    int error;
1665
1666
0
    ovs_rwlock_wrlock(&dp->port_rwlock);
1667
0
    dpif_port = netdev_vport_get_dpif_port(netdev, namebuf, sizeof namebuf);
1668
0
    if (*port_nop != ODPP_NONE) {
1669
0
        port_no = *port_nop;
1670
0
        error = dp_netdev_lookup_port(dp, *port_nop) ? EBUSY : 0;
1671
0
    } else {
1672
0
        port_no = choose_port(dp, dpif_port);
1673
0
        error = port_no == ODPP_NONE ? EFBIG : 0;
1674
0
    }
1675
0
    if (!error) {
1676
0
        *port_nop = port_no;
1677
0
        error = do_add_port(dp, dpif_port, netdev_get_type(netdev), port_no);
1678
0
    }
1679
0
    ovs_rwlock_unlock(&dp->port_rwlock);
1680
1681
0
    return error;
1682
0
}
1683
1684
static int
1685
dpif_netdev_port_del(struct dpif *dpif, odp_port_t port_no)
1686
0
{
1687
0
    struct dp_netdev *dp = get_dp_netdev(dpif);
1688
0
    int error;
1689
1690
0
    ovs_rwlock_wrlock(&dp->port_rwlock);
1691
0
    if (port_no == ODPP_LOCAL) {
1692
0
        error = EINVAL;
1693
0
    } else {
1694
0
        struct dp_netdev_port *port;
1695
1696
0
        error = get_port_by_number(dp, port_no, &port);
1697
0
        if (!error) {
1698
0
            do_del_port(dp, port);
1699
0
        }
1700
0
    }
1701
0
    ovs_rwlock_unlock(&dp->port_rwlock);
1702
1703
0
    return error;
1704
0
}
1705
1706
static bool
1707
is_valid_port_number(odp_port_t port_no)
1708
0
{
1709
0
    return port_no != ODPP_NONE;
1710
0
}
1711
1712
static struct dp_netdev_port *
1713
dp_netdev_lookup_port(const struct dp_netdev *dp, odp_port_t port_no)
1714
    OVS_REQ_RDLOCK(dp->port_rwlock)
1715
0
{
1716
0
    struct dp_netdev_port *port;
1717
1718
0
    HMAP_FOR_EACH_WITH_HASH (port, node, hash_port_no(port_no), &dp->ports) {
1719
0
        if (port->port_no == port_no) {
1720
0
            return port;
1721
0
        }
1722
0
    }
1723
0
    return NULL;
1724
0
}
1725
1726
static int
1727
get_port_by_number(struct dp_netdev *dp,
1728
                   odp_port_t port_no, struct dp_netdev_port **portp)
1729
    OVS_REQ_RDLOCK(dp->port_rwlock)
1730
0
{
1731
0
    if (!is_valid_port_number(port_no)) {
1732
0
        *portp = NULL;
1733
0
        return EINVAL;
1734
0
    } else {
1735
0
        *portp = dp_netdev_lookup_port(dp, port_no);
1736
0
        return *portp ? 0 : ENODEV;
1737
0
    }
1738
0
}
1739
1740
static void
1741
port_destroy(struct dp_netdev_port *port)
1742
0
{
1743
0
    if (!port) {
1744
0
        return;
1745
0
    }
1746
1747
0
    netdev_close(port->netdev);
1748
0
    netdev_restore_flags(port->sf);
1749
1750
0
    for (unsigned i = 0; i < port->n_rxq; i++) {
1751
0
        netdev_rxq_close(port->rxqs[i].rx);
1752
0
    }
1753
0
    ovs_mutex_destroy(&port->txq_used_mutex);
1754
0
    free(port->rxq_affinity_list);
1755
0
    free(port->txq_used);
1756
0
    free(port->rxqs);
1757
0
    free(port->type);
1758
0
    free(port);
1759
0
}
1760
1761
static int
1762
get_port_by_name(struct dp_netdev *dp,
1763
                 const char *devname, struct dp_netdev_port **portp)
1764
    OVS_REQ_RDLOCK(dp->port_rwlock)
1765
0
{
1766
0
    struct dp_netdev_port *port;
1767
1768
0
    HMAP_FOR_EACH (port, node, &dp->ports) {
1769
0
        if (!strcmp(netdev_get_name(port->netdev), devname)) {
1770
0
            *portp = port;
1771
0
            return 0;
1772
0
        }
1773
0
    }
1774
1775
    /* Callers of dpif_netdev_port_query_by_name() expect ENODEV for a non
1776
     * existing port. */
1777
0
    return ENODEV;
1778
0
}
1779
1780
/* Returns 'true' if there is a port with pmd netdev. */
1781
static bool
1782
has_pmd_port(struct dp_netdev *dp)
1783
    OVS_REQ_RDLOCK(dp->port_rwlock)
1784
0
{
1785
0
    struct dp_netdev_port *port;
1786
1787
0
    HMAP_FOR_EACH (port, node, &dp->ports) {
1788
0
        if (netdev_is_pmd(port->netdev)) {
1789
0
            return true;
1790
0
        }
1791
0
    }
1792
1793
0
    return false;
1794
0
}
1795
1796
static void
1797
do_del_port(struct dp_netdev *dp, struct dp_netdev_port *port)
1798
    OVS_REQ_WRLOCK(dp->port_rwlock)
1799
0
{
1800
0
    hmap_remove(&dp->ports, &port->node);
1801
0
    seq_change(dp->port_seq);
1802
1803
0
    reconfigure_datapath(dp);
1804
0
    port_destroy(port);
1805
0
}
1806
1807
static void
1808
answer_port_query(const struct dp_netdev_port *port,
1809
                  struct dpif_port *dpif_port)
1810
0
{
1811
0
    dpif_port->name = xstrdup(netdev_get_name(port->netdev));
1812
0
    dpif_port->type = xstrdup(port->type);
1813
0
    dpif_port->port_no = port->port_no;
1814
0
}
1815
1816
static int
1817
dpif_netdev_port_query_by_number(const struct dpif *dpif, odp_port_t port_no,
1818
                                 struct dpif_port *dpif_port)
1819
0
{
1820
0
    struct dp_netdev *dp = get_dp_netdev(dpif);
1821
0
    struct dp_netdev_port *port;
1822
0
    int error;
1823
1824
0
    ovs_rwlock_rdlock(&dp->port_rwlock);
1825
0
    error = get_port_by_number(dp, port_no, &port);
1826
0
    if (!error && dpif_port) {
1827
0
        answer_port_query(port, dpif_port);
1828
0
    }
1829
0
    ovs_rwlock_unlock(&dp->port_rwlock);
1830
1831
0
    return error;
1832
0
}
1833
1834
static int
1835
dpif_netdev_port_query_by_name(const struct dpif *dpif, const char *devname,
1836
                               struct dpif_port *dpif_port)
1837
0
{
1838
0
    struct dp_netdev *dp = get_dp_netdev(dpif);
1839
0
    struct dp_netdev_port *port;
1840
0
    int error;
1841
1842
0
    ovs_rwlock_rdlock(&dp->port_rwlock);
1843
0
    error = get_port_by_name(dp, devname, &port);
1844
0
    if (!error && dpif_port) {
1845
0
        answer_port_query(port, dpif_port);
1846
0
    }
1847
0
    ovs_rwlock_unlock(&dp->port_rwlock);
1848
1849
0
    return error;
1850
0
}
1851
1852
static void
1853
dp_netdev_flow_free(struct dp_netdev_flow *flow)
1854
0
{
1855
0
    dp_netdev_actions_free(dp_netdev_flow_get_actions(flow));
1856
0
    free(flow->dp_extra_info);
1857
0
    free(flow);
1858
0
}
1859
1860
void dp_netdev_flow_unref(struct dp_netdev_flow *flow)
1861
0
{
1862
0
    if (ovs_refcount_unref_relaxed(&flow->ref_cnt) == 1) {
1863
0
        ovsrcu_postpone(dp_netdev_flow_free, flow);
1864
0
    }
1865
0
}
1866
1867
static inline struct dpcls *
1868
dp_netdev_pmd_lookup_dpcls(struct dp_netdev_pmd_thread *pmd,
1869
                           odp_port_t in_port)
1870
0
{
1871
0
    struct dpcls *cls;
1872
0
    uint32_t hash = hash_port_no(in_port);
1873
0
    CMAP_FOR_EACH_WITH_HASH (cls, node, hash, &pmd->classifiers) {
1874
0
        if (cls->in_port == in_port) {
1875
            /* Port classifier exists already */
1876
0
            return cls;
1877
0
        }
1878
0
    }
1879
0
    return NULL;
1880
0
}
1881
1882
static inline struct dpcls *
1883
dp_netdev_pmd_find_dpcls(struct dp_netdev_pmd_thread *pmd,
1884
                         odp_port_t in_port)
1885
    OVS_REQUIRES(pmd->flow_mutex)
1886
0
{
1887
0
    struct dpcls *cls = dp_netdev_pmd_lookup_dpcls(pmd, in_port);
1888
1889
0
    if (!cls) {
1890
0
        uint32_t hash = hash_port_no(in_port);
1891
1892
        /* Create new classifier for in_port */
1893
0
        cls = xmalloc(sizeof(*cls));
1894
0
        dpcls_init(cls);
1895
0
        cls->in_port = in_port;
1896
0
        cmap_insert(&pmd->classifiers, &cls->node, hash);
1897
0
        VLOG_DBG("Creating dpcls %p for in_port %d", cls, in_port);
1898
0
    }
1899
0
    return cls;
1900
0
}
1901
1902
static void
1903
log_netdev_flow_change(const struct dp_netdev_flow *flow,
1904
                       const struct match *match,
1905
                       const struct dp_netdev_actions *old_actions,
1906
                       const struct nlattr *actions,
1907
                       size_t actions_len)
1908
0
{
1909
0
    struct ds ds = DS_EMPTY_INITIALIZER;
1910
0
    struct ofpbuf key_buf, mask_buf;
1911
0
    struct odp_flow_key_parms odp_parms = {
1912
0
        .flow = &match->flow,
1913
0
        .mask = &match->wc.masks,
1914
0
        .support = dp_netdev_support,
1915
0
    };
1916
1917
0
    if (OVS_LIKELY(VLOG_DROP_DBG((&upcall_rl)))) {
1918
0
        return;
1919
0
    }
1920
1921
0
    ofpbuf_init(&key_buf, 0);
1922
0
    ofpbuf_init(&mask_buf, 0);
1923
1924
0
    odp_flow_key_from_flow(&odp_parms, &key_buf);
1925
0
    odp_parms.key_buf = &key_buf;
1926
0
    odp_flow_key_from_mask(&odp_parms, &mask_buf);
1927
1928
0
    if (old_actions) {
1929
0
        ds_put_cstr(&ds, "flow_mod: ");
1930
0
    } else {
1931
0
        ds_put_cstr(&ds, "flow_add: ");
1932
0
    }
1933
0
    odp_format_ufid(&flow->ufid, &ds);
1934
0
    ds_put_cstr(&ds, " mega_");
1935
0
    odp_format_ufid(&flow->mega_ufid, &ds);
1936
0
    ds_put_cstr(&ds, " ");
1937
0
    odp_flow_format(key_buf.data, key_buf.size,
1938
0
                    mask_buf.data, mask_buf.size,
1939
0
                    NULL, &ds, false, true);
1940
0
    if (old_actions) {
1941
0
        ds_put_cstr(&ds, ", old_actions:");
1942
0
        format_odp_actions(&ds, old_actions->actions, old_actions->size,
1943
0
                           NULL);
1944
0
    }
1945
0
    ds_put_cstr(&ds, ", actions:");
1946
0
    format_odp_actions(&ds, actions, actions_len, NULL);
1947
1948
0
    VLOG_DBG("%s", ds_cstr(&ds));
1949
1950
0
    ofpbuf_uninit(&key_buf);
1951
0
    ofpbuf_uninit(&mask_buf);
1952
1953
    /* Add a printout of the actual match installed. */
1954
0
    struct match m;
1955
0
    ds_clear(&ds);
1956
0
    ds_put_cstr(&ds, "flow match: ");
1957
0
    miniflow_expand(&flow->cr.flow.mf, &m.flow);
1958
0
    miniflow_expand(&flow->cr.mask->mf, &m.wc.masks);
1959
0
    memset(&m.tun_md, 0, sizeof m.tun_md);
1960
0
    match_format(&m, NULL, &ds, OFP_DEFAULT_PRIORITY);
1961
1962
0
    VLOG_DBG("%s", ds_cstr(&ds));
1963
1964
0
    ds_destroy(&ds);
1965
0
}
1966
1967
/* Offloaded flows can be handled asynchronously, so we do not always know
1968
 * whether a specific flow is offloaded or not.  It might still be pending;
1969
 * in fact, multiple modifications can be pending, and the actual offload
1970
 * state depends on the completion of each modification.
1971
 *
1972
 * To correctly determine whether a flow is offloaded when it is being
1973
 * destroyed (and therefore requires cleanup), we must ensure that all
1974
 * operations have completed.  To achieve this, we track the number of
1975
 * outstanding offloaded flow modifications. */
1976
static bool
1977
offload_queue_inc(struct dp_netdev_flow *flow)
1978
0
{
1979
0
    int current;
1980
1981
0
    while (true) {
1982
0
        atomic_read(&flow->offload_queue_depth, &current);
1983
0
        if (current < 0) {
1984
            /* We are cleaning up, so no longer enqueue operations. */
1985
0
            return false;
1986
0
        }
1987
1988
        /* Here we try to atomically increase the value.  If we do not succeed,
1989
         * someone else has modified it, and we need to check again for a
1990
         * current negative value. */
1991
0
        if (atomic_compare_exchange_strong(&flow->offload_queue_depth,
1992
0
                                           &current, current + 1)) {
1993
0
            return true;
1994
0
        }
1995
0
    }
1996
0
}
1997
1998
static bool
1999
offload_queue_dec(struct dp_netdev_flow *flow)
2000
0
{
2001
0
    int old;
2002
2003
0
    atomic_sub(&flow->offload_queue_depth, 1, &old);
2004
0
    ovs_assert(old >= 1);
2005
2006
0
    if (old == 1) {
2007
        /* Note that this only indicates that the queue might be empty. */
2008
0
        return true;
2009
0
    }
2010
0
    return false;
2011
0
}
2012
2013
static bool
2014
offload_queue_complete(struct dp_netdev_flow *flow)
2015
0
{
2016
    /* This function returns false if the queue is still in use.
2017
     * If the queue is empty, it will attempt to atomically mark it as
2018
     * 'not in use' by making the queue depth negative.  This prevents
2019
     * other flow operations from being added.  If successful, it returns
2020
     * true. */
2021
0
     int expected_val = 0;
2022
2023
0
    return atomic_compare_exchange_strong(&flow->offload_queue_depth,
2024
0
                                          &expected_val, -1);
2025
0
}
2026
2027
static void
2028
offload_flow_reference_unreference_cb(unsigned pmd_id OVS_UNUSED,
2029
                                      void *flow_reference_)
2030
0
{
2031
0
    struct dp_netdev_flow *flow_reference = flow_reference_;
2032
2033
0
    if (flow_reference) {
2034
0
        flow_reference->offloaded = false;
2035
0
        dp_netdev_flow_unref(flow_reference);
2036
0
    }
2037
0
}
2038
2039
static void
2040
offload_flow_del_resume(struct dp_netdev_flow *flow_reference,
2041
                        int error)
2042
0
{
2043
0
    if (error == EINPROGRESS) {
2044
0
        return;
2045
0
    }
2046
2047
0
    if (error) {
2048
0
        odp_port_t in_port = flow_reference->flow.in_port.odp_port;
2049
2050
0
        VLOG_DBG(
2051
0
            "Failed removing offload flow ufid " UUID_FMT " from port %d: %d",
2052
0
            UUID_ARGS((struct uuid *)&flow_reference->mega_ufid), in_port,
2053
0
            error);
2054
0
    } else {
2055
        /* Release because we successfully removed the reference. */
2056
0
        dp_netdev_flow_unref(flow_reference);
2057
0
    }
2058
2059
    /* Release as we took a reference in offload_flow_del(). */
2060
0
    dp_netdev_flow_unref(flow_reference);
2061
0
}
2062
2063
static void
2064
offload_flow_del_resume_cb(void *aux OVS_UNUSED,
2065
                           struct dpif_flow_stats *stats OVS_UNUSED,
2066
                           unsigned pmd_id OVS_UNUSED,
2067
                           void *flow_reference,
2068
                           void *previous_flow_reference OVS_UNUSED, int error)
2069
0
{
2070
0
    offload_flow_del_resume(flow_reference, error);
2071
0
}
2072
2073
static void
2074
offload_flow_del(struct dp_netdev *dp, unsigned pmd_id,
2075
                 struct dp_netdev_flow *flow)
2076
0
{
2077
0
    odp_port_t in_port = flow->flow.in_port.odp_port;
2078
0
    struct dpif_offload_flow_del del = {
2079
0
        .in_port = in_port,
2080
0
        .pmd_id = pmd_id,
2081
0
        .ufid = CONST_CAST(ovs_u128 *, &flow->mega_ufid),
2082
0
        .flow_reference = flow,
2083
0
        .stats = NULL,
2084
0
        .cb_data = { .callback = offload_flow_del_resume_cb },
2085
0
    };
2086
0
    int error;
2087
2088
0
    if (!dpif_offload_enabled()) {
2089
0
        return;
2090
0
    }
2091
2092
    /* This offload flow delete is only called when the actual flow is
2093
     * destructed.  However, we can only trust the state of flow->offloaded
2094
     * if no more flow_put operations are pending.  Below, we check whether
2095
     * the queue can be marked as complete, and then determine if we need
2096
     * to schedule a removal.  If not, the delete will be rescheduled later
2097
     * in the last offload_flow_put_resume_cb() callback. */
2098
0
    ovs_assert(flow->dead);
2099
0
    if (!offload_queue_complete(flow) || !flow->offloaded) {
2100
0
        return;
2101
0
    }
2102
2103
0
    flow->offloaded = false;
2104
0
    dp_netdev_flow_ref(flow);
2105
2106
    /* It's the responsibility of the offload provider to remove the
2107
     * actual rule from hardware only if none of the other PMD threads
2108
     * have the rule installed in hardware. */
2109
0
    error = dpif_offload_datapath_flow_del(dp->full_name, &del);
2110
0
    offload_flow_del_resume(flow, error);
2111
0
}
2112
2113
static void
2114
dp_netdev_pmd_remove_flow(struct dp_netdev_pmd_thread *pmd,
2115
                          struct dp_netdev_flow *flow)
2116
    OVS_REQUIRES(pmd->flow_mutex)
2117
0
{
2118
0
    struct cmap_node *node = CONST_CAST(struct cmap_node *, &flow->node);
2119
0
    struct dpcls *cls;
2120
0
    odp_port_t in_port = flow->flow.in_port.odp_port;
2121
2122
0
    cls = dp_netdev_pmd_lookup_dpcls(pmd, in_port);
2123
0
    ovs_assert(cls != NULL);
2124
0
    dpcls_remove(cls, &flow->cr);
2125
0
    dp_netdev_simple_match_remove(pmd, flow);
2126
0
    cmap_remove(&pmd->flow_table, node, dp_netdev_flow_hash(&flow->ufid));
2127
0
    ccmap_dec(&pmd->n_flows, odp_to_u32(in_port));
2128
0
    flow->dead = true;
2129
0
    offload_flow_del(pmd->dp, pmd->core_id, flow);
2130
2131
0
    dp_netdev_flow_unref(flow);
2132
0
}
2133
2134
static void
2135
dp_netdev_pmd_flow_flush(struct dp_netdev_pmd_thread *pmd)
2136
0
{
2137
0
    struct dp_netdev_flow *netdev_flow;
2138
2139
0
    ovs_mutex_lock(&pmd->flow_mutex);
2140
0
    CMAP_FOR_EACH (netdev_flow, node, &pmd->flow_table) {
2141
0
        dp_netdev_pmd_remove_flow(pmd, netdev_flow);
2142
0
    }
2143
0
    ovs_mutex_unlock(&pmd->flow_mutex);
2144
0
}
2145
2146
static int
2147
dpif_netdev_flow_flush(struct dpif *dpif)
2148
0
{
2149
0
    struct dp_netdev *dp = get_dp_netdev(dpif);
2150
0
    struct dp_netdev_pmd_thread *pmd;
2151
2152
0
    CMAP_FOR_EACH (pmd, node, &dp->poll_threads) {
2153
0
        dp_netdev_pmd_flow_flush(pmd);
2154
0
    }
2155
2156
0
    return 0;
2157
0
}
2158
2159
struct dp_netdev_port_state {
2160
    struct hmap_position position;
2161
    char *name;
2162
};
2163
2164
static int
2165
dpif_netdev_port_dump_start(const struct dpif *dpif OVS_UNUSED, void **statep)
2166
0
{
2167
0
    *statep = xzalloc(sizeof(struct dp_netdev_port_state));
2168
0
    return 0;
2169
0
}
2170
2171
static int
2172
dpif_netdev_port_dump_next(const struct dpif *dpif, void *state_,
2173
                           struct dpif_port *dpif_port)
2174
0
{
2175
0
    struct dp_netdev_port_state *state = state_;
2176
0
    struct dp_netdev *dp = get_dp_netdev(dpif);
2177
0
    struct hmap_node *node;
2178
0
    int retval;
2179
2180
0
    ovs_rwlock_rdlock(&dp->port_rwlock);
2181
0
    node = hmap_at_position(&dp->ports, &state->position);
2182
0
    if (node) {
2183
0
        struct dp_netdev_port *port;
2184
2185
0
        port = CONTAINER_OF(node, struct dp_netdev_port, node);
2186
2187
0
        free(state->name);
2188
0
        state->name = xstrdup(netdev_get_name(port->netdev));
2189
0
        dpif_port->name = state->name;
2190
0
        dpif_port->type = port->type;
2191
0
        dpif_port->port_no = port->port_no;
2192
2193
0
        retval = 0;
2194
0
    } else {
2195
0
        retval = EOF;
2196
0
    }
2197
0
    ovs_rwlock_unlock(&dp->port_rwlock);
2198
2199
0
    return retval;
2200
0
}
2201
2202
static int
2203
dpif_netdev_port_dump_done(const struct dpif *dpif OVS_UNUSED, void *state_)
2204
0
{
2205
0
    struct dp_netdev_port_state *state = state_;
2206
0
    free(state->name);
2207
0
    free(state);
2208
0
    return 0;
2209
0
}
2210
2211
static int
2212
dpif_netdev_port_poll(const struct dpif *dpif_, char **devnamep OVS_UNUSED)
2213
0
{
2214
0
    struct dpif_netdev *dpif = dpif_netdev_cast(dpif_);
2215
0
    uint64_t new_port_seq;
2216
0
    int error;
2217
2218
0
    new_port_seq = seq_read(dpif->dp->port_seq);
2219
0
    if (dpif->last_port_seq != new_port_seq) {
2220
0
        dpif->last_port_seq = new_port_seq;
2221
0
        error = ENOBUFS;
2222
0
    } else {
2223
0
        error = EAGAIN;
2224
0
    }
2225
2226
0
    return error;
2227
0
}
2228
2229
static void
2230
dpif_netdev_port_poll_wait(const struct dpif *dpif_)
2231
0
{
2232
0
    struct dpif_netdev *dpif = dpif_netdev_cast(dpif_);
2233
2234
0
    seq_wait(dpif->dp->port_seq, dpif->last_port_seq);
2235
0
}
2236
2237
static struct dp_netdev_flow *
2238
dp_netdev_flow_cast(const struct dpcls_rule *cr)
2239
0
{
2240
0
    return cr ? CONTAINER_OF(cr, struct dp_netdev_flow, cr) : NULL;
2241
0
}
2242
2243
static bool dp_netdev_flow_ref(struct dp_netdev_flow *flow)
2244
0
{
2245
0
    return ovs_refcount_try_ref_rcu(&flow->ref_cnt);
2246
0
}
2247
2248
/* netdev_flow_key utilities.
2249
 *
2250
 * netdev_flow_key is basically a miniflow.  We use these functions
2251
 * (netdev_flow_key_clone, netdev_flow_key_equal, ...) instead of the miniflow
2252
 * functions (miniflow_clone_inline, miniflow_equal, ...), because:
2253
 *
2254
 * - Since we are dealing exclusively with miniflows created by
2255
 *   miniflow_extract(), if the map is different the miniflow is different.
2256
 *   Therefore we can be faster by comparing the map and the miniflow in a
2257
 *   single memcmp().
2258
 * - These functions can be inlined by the compiler. */
2259
2260
static inline bool
2261
netdev_flow_key_equal(const struct netdev_flow_key *a,
2262
                      const struct netdev_flow_key *b)
2263
0
{
2264
    /* 'b->len' may be not set yet. */
2265
0
    return a->hash == b->hash && !memcmp(&a->mf, &b->mf, a->len);
2266
0
}
2267
2268
static inline void
2269
netdev_flow_key_clone(struct netdev_flow_key *dst,
2270
                      const struct netdev_flow_key *src)
2271
0
{
2272
0
    memcpy(dst, src,
2273
0
           offsetof(struct netdev_flow_key, mf) + src->len);
2274
0
}
2275
2276
/* Initialize a netdev_flow_key 'mask' from 'match'. */
2277
static inline void
2278
netdev_flow_mask_init(struct netdev_flow_key *mask,
2279
                      const struct match *match)
2280
0
{
2281
0
    uint64_t *dst = miniflow_values(&mask->mf);
2282
0
    struct flowmap fmap;
2283
0
    uint32_t hash = 0;
2284
0
    size_t idx;
2285
2286
    /* Only check masks that make sense for the flow. */
2287
0
    flow_wc_map(&match->flow, &fmap);
2288
0
    flowmap_init(&mask->mf.map);
2289
2290
0
    FLOWMAP_FOR_EACH_INDEX(idx, fmap) {
2291
0
        uint64_t mask_u64 = flow_u64_value(&match->wc.masks, idx);
2292
2293
0
        if (mask_u64) {
2294
0
            flowmap_set(&mask->mf.map, idx, 1);
2295
0
            *dst++ = mask_u64;
2296
0
            hash = hash_add64(hash, mask_u64);
2297
0
        }
2298
0
    }
2299
2300
0
    map_t map;
2301
2302
0
    FLOWMAP_FOR_EACH_MAP (map, mask->mf.map) {
2303
0
        hash = hash_add64(hash, map);
2304
0
    }
2305
2306
0
    size_t n = dst - miniflow_get_values(&mask->mf);
2307
2308
0
    mask->hash = hash_finish(hash, n * 8);
2309
0
    mask->len = netdev_flow_key_size(n);
2310
0
}
2311
2312
/* Initializes 'dst' as a copy of 'flow' masked with 'mask'. */
2313
static inline void
2314
netdev_flow_key_init_masked(struct netdev_flow_key *dst,
2315
                            const struct flow *flow,
2316
                            const struct netdev_flow_key *mask)
2317
0
{
2318
0
    uint64_t *dst_u64 = miniflow_values(&dst->mf);
2319
0
    const uint64_t *mask_u64 = miniflow_get_values(&mask->mf);
2320
0
    uint32_t hash = 0;
2321
0
    uint64_t value;
2322
2323
0
    dst->len = mask->len;
2324
0
    dst->mf = mask->mf;   /* Copy maps. */
2325
2326
0
    FLOW_FOR_EACH_IN_MAPS(value, flow, mask->mf.map) {
2327
0
        *dst_u64 = value & *mask_u64++;
2328
0
        hash = hash_add64(hash, *dst_u64++);
2329
0
    }
2330
0
    dst->hash = hash_finish(hash,
2331
0
                            (dst_u64 - miniflow_get_values(&dst->mf)) * 8);
2332
0
}
2333
2334
/* Initializes 'key' as a copy of 'flow'. */
2335
static inline void
2336
netdev_flow_key_init(struct netdev_flow_key *key,
2337
                     const struct flow *flow)
2338
0
{
2339
0
    uint32_t hash = 0;
2340
0
    uint64_t value;
2341
2342
0
    miniflow_map_init(&key->mf, flow);
2343
0
    miniflow_init(&key->mf, flow);
2344
2345
0
    size_t n = miniflow_n_values(&key->mf);
2346
2347
0
    FLOW_FOR_EACH_IN_MAPS (value, flow, key->mf.map) {
2348
0
        hash = hash_add64(hash, value);
2349
0
    }
2350
2351
0
    key->hash = hash_finish(hash, n * 8);
2352
0
    key->len = netdev_flow_key_size(n);
2353
0
}
2354
2355
static inline void
2356
emc_change_entry(struct emc_entry *ce, struct dp_netdev_flow *flow,
2357
                 const struct netdev_flow_key *key)
2358
0
{
2359
0
    if (ce->flow != flow) {
2360
0
        if (ce->flow) {
2361
0
            dp_netdev_flow_unref(ce->flow);
2362
0
        }
2363
2364
0
        if (dp_netdev_flow_ref(flow)) {
2365
0
            ce->flow = flow;
2366
0
        } else {
2367
0
            ce->flow = NULL;
2368
0
        }
2369
0
    }
2370
0
    if (key) {
2371
0
        netdev_flow_key_clone(&ce->key, key);
2372
0
    }
2373
0
}
2374
2375
static inline void
2376
emc_insert(struct emc_cache *cache, const struct netdev_flow_key *key,
2377
           struct dp_netdev_flow *flow)
2378
0
{
2379
0
    struct emc_entry *to_be_replaced = NULL;
2380
0
    struct emc_entry *current_entry;
2381
2382
0
    EMC_FOR_EACH_POS_WITH_HASH(cache, current_entry, key->hash) {
2383
0
        if (netdev_flow_key_equal(&current_entry->key, key)) {
2384
            /* We found the entry with the 'mf' miniflow */
2385
0
            emc_change_entry(current_entry, flow, NULL);
2386
0
            return;
2387
0
        }
2388
2389
        /* Replacement policy: put the flow in an empty (not alive) entry, or
2390
         * in the first entry where it can be */
2391
0
        if (!to_be_replaced
2392
0
            || (emc_entry_alive(to_be_replaced)
2393
0
                && !emc_entry_alive(current_entry))
2394
0
            || current_entry->key.hash < to_be_replaced->key.hash) {
2395
0
            to_be_replaced = current_entry;
2396
0
        }
2397
0
    }
2398
    /* We didn't find the miniflow in the cache.
2399
     * The 'to_be_replaced' entry is where the new flow will be stored */
2400
2401
0
    emc_change_entry(to_be_replaced, flow, key);
2402
0
}
2403
2404
static inline void
2405
emc_probabilistic_insert(struct dp_netdev_pmd_thread *pmd,
2406
                         const struct netdev_flow_key *key,
2407
                         struct dp_netdev_flow *flow)
2408
0
{
2409
    /* Insert an entry into the EMC based on probability value 'min'. By
2410
     * default the value is UINT32_MAX / 100 which yields an insertion
2411
     * probability of 1/100 ie. 1% */
2412
2413
0
    uint32_t min = pmd->ctx.emc_insert_min;
2414
2415
0
    if (min && random_uint32() <= min) {
2416
0
        emc_insert(&(pmd->flow_cache).emc_cache, key, flow);
2417
0
    }
2418
0
}
2419
2420
static inline const struct cmap_node *
2421
smc_entry_get(struct dp_netdev_pmd_thread *pmd, const uint32_t hash)
2422
0
{
2423
0
    struct smc_cache *cache = &(pmd->flow_cache).smc_cache;
2424
0
    struct smc_bucket *bucket = &cache->buckets[hash & SMC_MASK];
2425
0
    uint16_t sig = hash >> 16;
2426
0
    uint16_t index = UINT16_MAX;
2427
2428
0
    for (int i = 0; i < SMC_ENTRY_PER_BUCKET; i++) {
2429
0
        if (bucket->sig[i] == sig) {
2430
0
            index = bucket->flow_idx[i];
2431
0
            break;
2432
0
        }
2433
0
    }
2434
0
    if (index != UINT16_MAX) {
2435
0
        return cmap_find_by_index(&pmd->flow_table, index);
2436
0
    }
2437
0
    return NULL;
2438
0
}
2439
2440
/* Insert the flow_table index into SMC. Insertion may fail when 1) SMC is
2441
 * turned off, 2) the flow_table index is larger than uint16_t can handle.
2442
 * If there is already an SMC entry having same signature, the index will be
2443
 * updated. If there is no existing entry, but an empty entry is available,
2444
 * the empty entry will be taken. If no empty entry or existing same signature,
2445
 * a random entry from the hashed bucket will be picked. */
2446
static inline void
2447
smc_insert(struct dp_netdev_pmd_thread *pmd,
2448
           const struct netdev_flow_key *key,
2449
           uint32_t hash)
2450
0
{
2451
0
    struct smc_cache *smc_cache = &(pmd->flow_cache).smc_cache;
2452
0
    struct smc_bucket *bucket = &smc_cache->buckets[key->hash & SMC_MASK];
2453
0
    uint16_t index;
2454
0
    uint32_t cmap_index;
2455
0
    int i;
2456
2457
0
    if (!pmd->ctx.smc_enable_db) {
2458
0
        return;
2459
0
    }
2460
2461
0
    cmap_index = cmap_find_index(&pmd->flow_table, hash);
2462
0
    index = (cmap_index >= UINT16_MAX) ? UINT16_MAX : (uint16_t)cmap_index;
2463
2464
    /* If the index is larger than SMC can handle (uint16_t), we don't
2465
     * insert */
2466
0
    if (index == UINT16_MAX) {
2467
0
        return;
2468
0
    }
2469
2470
    /* If an entry with same signature already exists, update the index */
2471
0
    uint16_t sig = key->hash >> 16;
2472
0
    for (i = 0; i < SMC_ENTRY_PER_BUCKET; i++) {
2473
0
        if (bucket->sig[i] == sig) {
2474
0
            bucket->flow_idx[i] = index;
2475
0
            return;
2476
0
        }
2477
0
    }
2478
    /* If there is an empty entry, occupy it. */
2479
0
    for (i = 0; i < SMC_ENTRY_PER_BUCKET; i++) {
2480
0
        if (bucket->flow_idx[i] == UINT16_MAX) {
2481
0
            bucket->sig[i] = sig;
2482
0
            bucket->flow_idx[i] = index;
2483
0
            return;
2484
0
        }
2485
0
    }
2486
    /* Otherwise, pick a random entry. */
2487
0
    i = random_uint32() % SMC_ENTRY_PER_BUCKET;
2488
0
    bucket->sig[i] = sig;
2489
0
    bucket->flow_idx[i] = index;
2490
0
}
2491
2492
inline void
2493
emc_probabilistic_insert_batch(struct dp_netdev_pmd_thread *pmd,
2494
                               const struct netdev_flow_key *keys,
2495
                               struct dpcls_rule **rules,
2496
                               uint32_t emc_insert_mask)
2497
0
{
2498
0
    while (emc_insert_mask) {
2499
0
        uint32_t i = raw_ctz(emc_insert_mask);
2500
0
        emc_insert_mask &= emc_insert_mask - 1;
2501
        /* Get the require parameters for EMC/SMC from the rule */
2502
0
        struct dp_netdev_flow *flow = dp_netdev_flow_cast(rules[i]);
2503
        /* Insert the key into EMC/SMC. */
2504
0
        emc_probabilistic_insert(pmd, &keys[i], flow);
2505
0
    }
2506
0
}
2507
2508
inline void
2509
smc_insert_batch(struct dp_netdev_pmd_thread *pmd,
2510
                 const struct netdev_flow_key *keys,
2511
                 struct dpcls_rule **rules,
2512
                 uint32_t smc_insert_mask)
2513
0
{
2514
0
    while (smc_insert_mask) {
2515
0
        uint32_t i = raw_ctz(smc_insert_mask);
2516
0
        smc_insert_mask &= smc_insert_mask - 1;
2517
        /* Get the require parameters for EMC/SMC from the rule */
2518
0
        struct dp_netdev_flow *flow = dp_netdev_flow_cast(rules[i]);
2519
0
        uint32_t hash = dp_netdev_flow_hash(&flow->ufid);
2520
        /* Insert the key into EMC/SMC. */
2521
0
        smc_insert(pmd, &keys[i], hash);
2522
0
    }
2523
0
}
2524
2525
static struct dp_netdev_flow *
2526
dp_netdev_pmd_lookup_flow(struct dp_netdev_pmd_thread *pmd,
2527
                          const struct netdev_flow_key *key,
2528
                          int *lookup_num_p)
2529
0
{
2530
0
    struct dpcls *cls;
2531
0
    struct dpcls_rule *rule = NULL;
2532
0
    odp_port_t in_port = u32_to_odp(MINIFLOW_GET_U32(&key->mf,
2533
0
                                                     in_port.odp_port));
2534
0
    struct dp_netdev_flow *netdev_flow = NULL;
2535
2536
0
    cls = dp_netdev_pmd_lookup_dpcls(pmd, in_port);
2537
0
    if (OVS_LIKELY(cls)) {
2538
0
        dpcls_lookup(cls, &key, &rule, 1, lookup_num_p);
2539
0
        netdev_flow = dp_netdev_flow_cast(rule);
2540
0
    }
2541
0
    return netdev_flow;
2542
0
}
2543
2544
static struct dp_netdev_flow *
2545
dp_netdev_pmd_find_flow(const struct dp_netdev_pmd_thread *pmd,
2546
                        const ovs_u128 *ufidp, const struct nlattr *key,
2547
                        size_t key_len)
2548
0
{
2549
0
    struct dp_netdev_flow *netdev_flow;
2550
0
    struct flow flow;
2551
0
    ovs_u128 ufid;
2552
2553
    /* If a UFID is not provided, determine one based on the key. */
2554
0
    if (!ufidp && key && key_len
2555
0
        && !dpif_netdev_flow_from_nlattrs(key, key_len, &flow, false)) {
2556
0
        odp_flow_key_hash(&flow, sizeof flow, &ufid);
2557
0
        ufidp = &ufid;
2558
0
    }
2559
2560
0
    if (ufidp) {
2561
0
        CMAP_FOR_EACH_WITH_HASH (netdev_flow, node, dp_netdev_flow_hash(ufidp),
2562
0
                                 &pmd->flow_table) {
2563
0
            if (ovs_u128_equals(netdev_flow->ufid, *ufidp)) {
2564
0
                return netdev_flow;
2565
0
            }
2566
0
        }
2567
0
    }
2568
2569
0
    return NULL;
2570
0
}
2571
2572
static void
2573
get_dpif_flow_status(const struct dp_netdev *dp,
2574
                     const struct dp_netdev_flow *netdev_flow_,
2575
                     struct dpif_flow_stats *stats,
2576
                     struct dpif_flow_attrs *attrs)
2577
0
{
2578
0
    struct dpif_flow_stats offload_stats;
2579
0
    struct dpif_flow_attrs offload_attrs;
2580
0
    struct dp_netdev_flow *netdev_flow;
2581
0
    unsigned long long n;
2582
0
    long long used;
2583
0
    uint16_t flags;
2584
2585
0
    netdev_flow = CONST_CAST(struct dp_netdev_flow *, netdev_flow_);
2586
2587
0
    atomic_read_relaxed(&netdev_flow->stats.packet_count, &n);
2588
0
    stats->n_packets = n;
2589
0
    atomic_read_relaxed(&netdev_flow->stats.byte_count, &n);
2590
0
    stats->n_bytes = n;
2591
0
    atomic_read_relaxed(&netdev_flow->stats.used, &used);
2592
0
    stats->used = used;
2593
0
    atomic_read_relaxed(&netdev_flow->stats.tcp_flags, &flags);
2594
0
    stats->tcp_flags = flags;
2595
2596
0
    if (dpif_offload_datapath_flow_stats(dp->full_name,
2597
0
                                         netdev_flow->flow.in_port.odp_port,
2598
0
                                         &netdev_flow->mega_ufid,
2599
0
                                         &offload_stats, &offload_attrs)) {
2600
0
        stats->n_packets += offload_stats.n_packets;
2601
0
        stats->n_bytes += offload_stats.n_bytes;
2602
0
        stats->used = MAX(stats->used, offload_stats.used);
2603
0
        stats->tcp_flags |= offload_stats.tcp_flags;
2604
0
        if (attrs) {
2605
0
            attrs->offloaded = offload_attrs.offloaded;
2606
0
            attrs->dp_layer = offload_attrs.dp_layer;
2607
0
        }
2608
0
    } else if (attrs) {
2609
0
        attrs->offloaded = false;
2610
0
        attrs->dp_layer = "ovs";
2611
0
    }
2612
0
}
2613
2614
/* Converts to the dpif_flow format, using 'key_buf' and 'mask_buf' for
2615
 * storing the netlink-formatted key/mask. 'key_buf' may be the same as
2616
 * 'mask_buf'. Actions will be returned without copying, by relying on RCU to
2617
 * protect them. */
2618
static void
2619
dp_netdev_flow_to_dpif_flow(const struct dp_netdev *dp,
2620
                            const struct dp_netdev_flow *netdev_flow,
2621
                            struct ofpbuf *key_buf, struct ofpbuf *mask_buf,
2622
                            struct dpif_flow *flow, bool terse)
2623
0
{
2624
0
    if (terse) {
2625
0
        memset(flow, 0, sizeof *flow);
2626
0
    } else {
2627
0
        struct flow_wildcards wc;
2628
0
        struct dp_netdev_actions *actions;
2629
0
        size_t offset;
2630
0
        struct odp_flow_key_parms odp_parms = {
2631
0
            .flow = &netdev_flow->flow,
2632
0
            .mask = &wc.masks,
2633
0
            .support = dp_netdev_support,
2634
0
        };
2635
2636
0
        miniflow_expand(&netdev_flow->cr.mask->mf, &wc.masks);
2637
        /* in_port is exact matched, but we have left it out from the mask for
2638
         * optimnization reasons. Add in_port back to the mask. */
2639
0
        wc.masks.in_port.odp_port = ODPP_NONE;
2640
2641
        /* Key */
2642
0
        offset = key_buf->size;
2643
0
        flow->key = ofpbuf_tail(key_buf);
2644
0
        odp_flow_key_from_flow(&odp_parms, key_buf);
2645
0
        flow->key_len = key_buf->size - offset;
2646
2647
        /* Mask */
2648
0
        offset = mask_buf->size;
2649
0
        flow->mask = ofpbuf_tail(mask_buf);
2650
0
        odp_parms.key_buf = key_buf;
2651
0
        odp_flow_key_from_mask(&odp_parms, mask_buf);
2652
0
        flow->mask_len = mask_buf->size - offset;
2653
2654
        /* Actions */
2655
0
        actions = dp_netdev_flow_get_actions(netdev_flow);
2656
0
        flow->actions = actions->actions;
2657
0
        flow->actions_len = actions->size;
2658
0
    }
2659
2660
0
    flow->ufid = netdev_flow->ufid;
2661
0
    flow->ufid_present = true;
2662
0
    flow->pmd_id = netdev_flow->pmd_id;
2663
2664
0
    get_dpif_flow_status(dp, netdev_flow, &flow->stats, &flow->attrs);
2665
0
    flow->attrs.dp_extra_info = netdev_flow->dp_extra_info;
2666
0
}
2667
2668
static int
2669
dpif_netdev_mask_from_nlattrs(const struct nlattr *key, uint32_t key_len,
2670
                              const struct nlattr *mask_key,
2671
                              uint32_t mask_key_len, const struct flow *flow,
2672
                              struct flow_wildcards *wc, bool probe)
2673
0
{
2674
0
    enum odp_key_fitness fitness;
2675
2676
0
    fitness = odp_flow_key_to_mask(mask_key, mask_key_len, wc, flow, NULL);
2677
0
    if (fitness) {
2678
0
        if (!probe) {
2679
            /* This should not happen: it indicates that
2680
             * odp_flow_key_from_mask() and odp_flow_key_to_mask()
2681
             * disagree on the acceptable form of a mask.  Log the problem
2682
             * as an error, with enough details to enable debugging. */
2683
0
            static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
2684
2685
0
            if (!VLOG_DROP_ERR(&rl)) {
2686
0
                struct ds s;
2687
2688
0
                ds_init(&s);
2689
0
                odp_flow_format(key, key_len, mask_key, mask_key_len, NULL, &s,
2690
0
                                true, true);
2691
0
                VLOG_ERR("internal error parsing flow mask %s (%s)",
2692
0
                ds_cstr(&s), odp_key_fitness_to_string(fitness));
2693
0
                ds_destroy(&s);
2694
0
            }
2695
0
        }
2696
2697
0
        return EINVAL;
2698
0
    }
2699
2700
0
    return 0;
2701
0
}
2702
2703
static int
2704
dpif_netdev_flow_from_nlattrs(const struct nlattr *key, uint32_t key_len,
2705
                              struct flow *flow, bool probe)
2706
0
{
2707
0
    if (odp_flow_key_to_flow(key, key_len, flow, NULL)) {
2708
0
        if (!probe) {
2709
            /* This should not happen: it indicates that
2710
             * odp_flow_key_from_flow() and odp_flow_key_to_flow() disagree on
2711
             * the acceptable form of a flow.  Log the problem as an error,
2712
             * with enough details to enable debugging. */
2713
0
            static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
2714
2715
0
            if (!VLOG_DROP_ERR(&rl)) {
2716
0
                struct ds s;
2717
2718
0
                ds_init(&s);
2719
0
                odp_flow_format(key, key_len, NULL, 0, NULL, &s, true, false);
2720
0
                VLOG_ERR("internal error parsing flow key %s", ds_cstr(&s));
2721
0
                ds_destroy(&s);
2722
0
            }
2723
0
        }
2724
2725
0
        return EINVAL;
2726
0
    }
2727
2728
0
    if (flow->ct_state & DP_NETDEV_CS_UNSUPPORTED_MASK) {
2729
0
        return EINVAL;
2730
0
    }
2731
2732
0
    return 0;
2733
0
}
2734
2735
static int
2736
dpif_netdev_flow_get(const struct dpif *dpif, const struct dpif_flow_get *get)
2737
0
{
2738
0
    struct dp_netdev *dp = get_dp_netdev(dpif);
2739
0
    struct dp_netdev_flow *netdev_flow;
2740
0
    struct dp_netdev_pmd_thread *pmd;
2741
0
    struct hmapx to_find = HMAPX_INITIALIZER(&to_find);
2742
0
    struct hmapx_node *node;
2743
0
    int error = EINVAL;
2744
2745
0
    if (get->pmd_id == PMD_ID_NULL) {
2746
0
        CMAP_FOR_EACH (pmd, node, &dp->poll_threads) {
2747
0
            if (dp_netdev_pmd_try_ref(pmd) && !hmapx_add(&to_find, pmd)) {
2748
0
                dp_netdev_pmd_unref(pmd);
2749
0
            }
2750
0
        }
2751
0
    } else {
2752
0
        pmd = dp_netdev_get_pmd(dp, get->pmd_id);
2753
0
        if (!pmd) {
2754
0
            goto out;
2755
0
        }
2756
0
        hmapx_add(&to_find, pmd);
2757
0
    }
2758
2759
0
    if (!hmapx_count(&to_find)) {
2760
0
        goto out;
2761
0
    }
2762
2763
0
    HMAPX_FOR_EACH (node, &to_find) {
2764
0
        pmd = (struct dp_netdev_pmd_thread *) node->data;
2765
0
        netdev_flow = dp_netdev_pmd_find_flow(pmd, get->ufid, get->key,
2766
0
                                              get->key_len);
2767
0
        if (netdev_flow) {
2768
0
            dp_netdev_flow_to_dpif_flow(dp, netdev_flow, get->buffer,
2769
0
                                        get->buffer, get->flow, false);
2770
0
            error = 0;
2771
0
            break;
2772
0
        } else {
2773
0
            error = ENOENT;
2774
0
        }
2775
0
    }
2776
2777
0
    HMAPX_FOR_EACH (node, &to_find) {
2778
0
        pmd = (struct dp_netdev_pmd_thread *) node->data;
2779
0
        dp_netdev_pmd_unref(pmd);
2780
0
    }
2781
0
out:
2782
0
    hmapx_destroy(&to_find);
2783
0
    return error;
2784
0
}
2785
2786
static void
2787
dp_netdev_get_mega_ufid(const struct match *match, ovs_u128 *mega_ufid)
2788
0
{
2789
0
    struct {
2790
0
        struct flow masked_flow;
2791
0
        struct flow wc;
2792
0
    } key;
2793
0
    size_t i;
2794
2795
0
    memset(&key, 0, sizeof key);
2796
0
    for (i = 0; i < sizeof(struct flow); i++) {
2797
0
        ((uint8_t *)&key.masked_flow)[i] = ((uint8_t *)&match->flow)[i] &
2798
0
                                           ((uint8_t *)&match->wc)[i];
2799
0
        ((uint8_t *)&key.wc)[i] = ((uint8_t *)&match->wc)[i];
2800
0
    }
2801
2802
0
    odp_flow_key_hash(&key, sizeof key, mega_ufid);
2803
0
}
2804
2805
static uint64_t
2806
dp_netdev_simple_match_mark(odp_port_t in_port, ovs_be16 dl_type,
2807
                            uint8_t nw_frag, ovs_be16 vlan_tci)
2808
0
{
2809
    /* Simple Match Mark:
2810
     *
2811
     * BE:
2812
     * +-----------------+-------------++---------+---+-----------+
2813
     * |     in_port     |   dl_type   || nw_frag |CFI|  VID(12)  |
2814
     * +-----------------+-------------++---------+---+-----------+
2815
     * 0                 32          47 49         51  52     63
2816
     *
2817
     * LE:
2818
     * +-----------------+-------------+------++-------+---+------+
2819
     * |     in_port     |   dl_type   |VID(8)||nw_frag|CFI|VID(4)|
2820
     * +-----------------+-------------+------++-------+---+------+
2821
     * 0                 32          47 48  55  57   59 60  61   63
2822
     *
2823
     *         Big Endian              Little Endian
2824
     * in_port : 32 bits [ 0..31]  in_port : 32 bits [ 0..31]
2825
     * dl_type : 16 bits [32..47]  dl_type : 16 bits [32..47]
2826
     * <empty> :  1 bit  [48..48]  vlan VID:  8 bits [48..55]
2827
     * nw_frag :  2 bits [49..50]  <empty> :  1 bit  [56..56]
2828
     * vlan CFI:  1 bit  [51..51]  nw_frag :  2 bits [57..59]
2829
     * vlan VID: 12 bits [52..63]  vlan CFI:  1 bit  [60..60]
2830
     *                             vlan VID:  4 bits [61..63]
2831
     *
2832
     * Layout is different for LE and BE in order to save a couple of
2833
     * network to host translations.
2834
     * */
2835
0
    return ((uint64_t) odp_to_u32(in_port) << 32)
2836
0
           | ((OVS_FORCE uint32_t) dl_type << 16)
2837
#if WORDS_BIGENDIAN
2838
           | (((uint16_t) nw_frag & FLOW_NW_FRAG_MASK) << VLAN_PCP_SHIFT)
2839
#else
2840
0
           | ((nw_frag & FLOW_NW_FRAG_MASK) << (VLAN_PCP_SHIFT - 8))
2841
0
#endif
2842
0
           | (OVS_FORCE uint16_t) (vlan_tci & htons(VLAN_VID_MASK | VLAN_CFI));
2843
0
}
2844
2845
static struct dp_netdev_flow *
2846
dp_netdev_simple_match_lookup(const struct dp_netdev_pmd_thread *pmd,
2847
                              odp_port_t in_port, ovs_be16 dl_type,
2848
                              uint8_t nw_frag, ovs_be16 vlan_tci)
2849
0
{
2850
0
    uint64_t mark = dp_netdev_simple_match_mark(in_port, dl_type,
2851
0
                                                nw_frag, vlan_tci);
2852
0
    uint32_t hash = hash_uint64(mark);
2853
0
    struct dp_netdev_flow *flow;
2854
0
    bool found = false;
2855
2856
0
    CMAP_FOR_EACH_WITH_HASH (flow, simple_match_node,
2857
0
                             hash, &pmd->simple_match_table) {
2858
0
        if (flow->simple_match_mark == mark) {
2859
0
            found = true;
2860
0
            break;
2861
0
        }
2862
0
    }
2863
0
    return found ? flow : NULL;
2864
0
}
2865
2866
static bool
2867
dp_netdev_simple_match_enabled(const struct dp_netdev_pmd_thread *pmd,
2868
                               odp_port_t in_port)
2869
0
{
2870
0
    return ccmap_find(&pmd->n_flows, odp_to_u32(in_port))
2871
0
           == ccmap_find(&pmd->n_simple_flows, odp_to_u32(in_port));
2872
0
}
2873
2874
static void
2875
dp_netdev_simple_match_insert(struct dp_netdev_pmd_thread *pmd,
2876
                              struct dp_netdev_flow *dp_flow)
2877
    OVS_REQUIRES(pmd->flow_mutex)
2878
0
{
2879
0
    odp_port_t in_port = dp_flow->flow.in_port.odp_port;
2880
0
    ovs_be16 vlan_tci = dp_flow->flow.vlans[0].tci;
2881
0
    ovs_be16 dl_type = dp_flow->flow.dl_type;
2882
0
    uint8_t nw_frag = dp_flow->flow.nw_frag;
2883
2884
0
    if (!dp_netdev_flow_ref(dp_flow)) {
2885
0
        return;
2886
0
    }
2887
2888
    /* Avoid double insertion.  Should not happen in practice. */
2889
0
    dp_netdev_simple_match_remove(pmd, dp_flow);
2890
2891
0
    uint64_t mark = dp_netdev_simple_match_mark(in_port, dl_type,
2892
0
                                                nw_frag, vlan_tci);
2893
0
    uint32_t hash = hash_uint64(mark);
2894
2895
0
    dp_flow->simple_match_mark = mark;
2896
0
    cmap_insert(&pmd->simple_match_table,
2897
0
                CONST_CAST(struct cmap_node *, &dp_flow->simple_match_node),
2898
0
                hash);
2899
0
    ccmap_inc(&pmd->n_simple_flows, odp_to_u32(in_port));
2900
2901
0
    VLOG_DBG("Simple match insert: "
2902
0
             "core_id(%d),in_port(%"PRIu32"),mark(0x%016"PRIx64").",
2903
0
             pmd->core_id, in_port, mark);
2904
0
}
2905
2906
static void
2907
dp_netdev_simple_match_remove(struct dp_netdev_pmd_thread *pmd,
2908
                               struct dp_netdev_flow *dp_flow)
2909
    OVS_REQUIRES(pmd->flow_mutex)
2910
0
{
2911
0
    odp_port_t in_port = dp_flow->flow.in_port.odp_port;
2912
0
    ovs_be16 vlan_tci = dp_flow->flow.vlans[0].tci;
2913
0
    ovs_be16 dl_type = dp_flow->flow.dl_type;
2914
0
    uint8_t nw_frag = dp_flow->flow.nw_frag;
2915
0
    struct dp_netdev_flow *flow;
2916
0
    uint64_t mark = dp_netdev_simple_match_mark(in_port, dl_type,
2917
0
                                                nw_frag, vlan_tci);
2918
0
    uint32_t hash = hash_uint64(mark);
2919
2920
0
    flow = dp_netdev_simple_match_lookup(pmd, in_port, dl_type,
2921
0
                                         nw_frag, vlan_tci);
2922
0
    if (flow == dp_flow) {
2923
0
        VLOG_DBG("Simple match remove: "
2924
0
                 "core_id(%d),in_port(%"PRIu32"),mark(0x%016"PRIx64").",
2925
0
                 pmd->core_id, in_port, mark);
2926
0
        cmap_remove(&pmd->simple_match_table,
2927
0
                    CONST_CAST(struct cmap_node *, &flow->simple_match_node),
2928
0
                    hash);
2929
0
        ccmap_dec(&pmd->n_simple_flows, odp_to_u32(in_port));
2930
0
        dp_netdev_flow_unref(flow);
2931
0
    }
2932
0
}
2933
2934
static bool
2935
dp_netdev_flow_is_simple_match(const struct match *match)
2936
0
{
2937
0
    const struct flow *flow = &match->flow;
2938
0
    const struct flow_wildcards *wc = &match->wc;
2939
2940
0
    if (flow->recirc_id || flow->packet_type != htonl(PT_ETH)) {
2941
0
        return false;
2942
0
    }
2943
2944
    /* Check that flow matches only minimal set of fields that always set.
2945
     * Also checking that VLAN VID+CFI is an exact match, because these
2946
     * are not mandatory and could be masked. */
2947
0
    struct flow_wildcards *minimal = xmalloc(sizeof *minimal);
2948
0
    ovs_be16 vlan_tci_mask = htons(VLAN_VID_MASK | VLAN_CFI);
2949
2950
0
    flow_wildcards_init_catchall(minimal);
2951
    /* 'dpif-netdev' always has following in exact match:
2952
     *   - recirc_id                   <-- recirc_id == 0 checked on input.
2953
     *   - in_port                     <-- Will be checked on input.
2954
     *   - packet_type                 <-- Assuming all packets are PT_ETH.
2955
     *   - dl_type                     <-- Need to match with.
2956
     *   - vlan_tci                    <-- Need to match with.
2957
     *   - and nw_frag for ip packets. <-- Need to match with.
2958
     */
2959
0
    WC_MASK_FIELD(minimal, recirc_id);
2960
0
    WC_MASK_FIELD(minimal, in_port);
2961
0
    WC_MASK_FIELD(minimal, packet_type);
2962
0
    WC_MASK_FIELD(minimal, dl_type);
2963
0
    WC_MASK_FIELD_MASK(minimal, vlans[0].tci, vlan_tci_mask);
2964
0
    WC_MASK_FIELD_MASK(minimal, nw_frag, FLOW_NW_FRAG_MASK);
2965
2966
0
    if (flow_wildcards_has_extra(minimal, wc)
2967
0
        || wc->masks.vlans[0].tci != vlan_tci_mask) {
2968
0
        free(minimal);
2969
0
        return false;
2970
0
    }
2971
0
    free(minimal);
2972
2973
0
    return true;
2974
0
}
2975
2976
static void
2977
offload_flow_put_resume(struct dp_netdev *dp, struct dp_netdev_flow *flow,
2978
                        struct dp_netdev_flow *previous_flow_reference,
2979
                        unsigned pmd_id, int error)
2980
0
{
2981
0
    if (error == EINPROGRESS) {
2982
0
        return;
2983
0
    }
2984
2985
0
    if (!error) {
2986
0
        flow->offloaded = true;
2987
0
    } else {
2988
        /* If the flow was already offloaded, the new action set can no
2989
         * longer be offloaded.  In theory, we should disassociate the
2990
         * offload from all PMDs that have this flow marked as offloaded.
2991
         * Unfortunately, there is no mechanism to inform other PMDs, so
2992
         * we cannot explicitly mark such flows.  This situation typically
2993
         * occurs when the revalidator modifies the flow, so it is safe to
2994
         * assume it will update all affected flows and that the offload
2995
         * will subsequently fail. */
2996
0
        flow->offloaded = false;
2997
2998
        /* On error, the flow reference was not stored by the offload provider,
2999
         * so we should decrease the reference. */
3000
0
        dp_netdev_flow_unref(flow);
3001
0
    }
3002
3003
0
    if (offload_queue_dec(flow) && flow->dead) {
3004
        /* If flows are processed asynchronously, modifications might
3005
         * still be queued up while the flow is being removed.  If this
3006
         * was the last flow in the queue on a dead flow, we try again
3007
         * to see if we need to remove this flow. */
3008
0
        offload_flow_del(dp, pmd_id, flow);
3009
0
    }
3010
3011
0
    if (previous_flow_reference) {
3012
0
        dp_netdev_flow_unref(previous_flow_reference);
3013
0
        if (previous_flow_reference != flow) {
3014
0
            VLOG_DBG("Updated flow reference was from outdated flow");
3015
0
        }
3016
0
    }
3017
0
}
3018
3019
static void
3020
offload_flow_put_resume_cb(void *aux, struct dpif_flow_stats *stats OVS_UNUSED,
3021
                           unsigned pmd_id, void *flow_reference_,
3022
                           void *old_flow_reference_,
3023
                           int error)
3024
0
{
3025
0
    struct dp_netdev *dp = aux;
3026
0
    struct dp_netdev_flow *flow_reference = flow_reference_;
3027
0
    struct dp_netdev_flow *old_flow_reference = old_flow_reference_;
3028
3029
0
    offload_flow_put_resume(dp, flow_reference, old_flow_reference,
3030
0
                            pmd_id, error);
3031
0
}
3032
3033
static void
3034
offload_flow_put(struct dp_netdev_pmd_thread *pmd, struct dp_netdev_flow *flow,
3035
                 struct match *match, const struct nlattr *actions,
3036
                 size_t actions_len)
3037
0
{
3038
0
    struct dpif_offload_flow_put put = {
3039
0
        .in_port = match->flow.in_port.odp_port,
3040
0
        .orig_in_port = flow->orig_in_port,
3041
0
        .pmd_id = pmd->core_id,
3042
0
        .ufid = CONST_CAST(ovs_u128 *, &flow->mega_ufid),
3043
0
        .match = match,
3044
0
        .actions = actions,
3045
0
        .actions_len = actions_len,
3046
0
        .stats = NULL,
3047
0
        .flow_reference = flow,
3048
0
        .cb_data = {
3049
0
            .callback = offload_flow_put_resume_cb,
3050
0
            .callback_aux = pmd->dp,
3051
0
        },
3052
0
    };
3053
0
    void *previous_flow_reference = NULL;
3054
0
    int error;
3055
3056
0
    if (!dpif_offload_enabled() || flow->dead || !offload_queue_inc(flow)) {
3057
0
        return;
3058
0
    }
3059
3060
0
    dp_netdev_flow_ref(flow);
3061
3062
0
    error = dpif_offload_datapath_flow_put(pmd->dp->full_name, &put,
3063
0
                                           &previous_flow_reference);
3064
0
    offload_flow_put_resume(pmd->dp, put.flow_reference,
3065
0
                            previous_flow_reference,
3066
0
                            pmd->core_id, error);
3067
0
}
3068
3069
static struct dp_netdev_flow *
3070
dp_netdev_flow_add(struct dp_netdev_pmd_thread *pmd,
3071
                   struct match *match, const ovs_u128 *ufid,
3072
                   const struct nlattr *actions, size_t actions_len,
3073
                   odp_port_t orig_in_port)
3074
    OVS_REQUIRES(pmd->flow_mutex)
3075
0
{
3076
0
    struct ds extra_info = DS_EMPTY_INITIALIZER;
3077
0
    struct dp_netdev_flow *flow;
3078
0
    struct netdev_flow_key mask;
3079
0
    struct dpcls *cls;
3080
0
    size_t unit;
3081
3082
    /* Make sure in_port is exact matched before we read it. */
3083
0
    ovs_assert(match->wc.masks.in_port.odp_port == ODPP_NONE);
3084
0
    odp_port_t in_port = match->flow.in_port.odp_port;
3085
3086
    /* As we select the dpcls based on the port number, each netdev flow
3087
     * belonging to the same dpcls will have the same odp_port value.
3088
     * For performance reasons we wildcard odp_port here in the mask.  In the
3089
     * typical case dp_hash is also wildcarded, and the resulting 8-byte
3090
     * chunk {dp_hash, in_port} will be ignored by netdev_flow_mask_init() and
3091
     * will not be part of the subtable mask.
3092
     * This will speed up the hash computation during dpcls_lookup() because
3093
     * there is one less call to hash_add64() in this case. */
3094
0
    match->wc.masks.in_port.odp_port = 0;
3095
0
    netdev_flow_mask_init(&mask, match);
3096
0
    match->wc.masks.in_port.odp_port = ODPP_NONE;
3097
3098
    /* Make sure wc does not have metadata. */
3099
0
    ovs_assert(!FLOWMAP_HAS_FIELD(&mask.mf.map, metadata)
3100
0
               && !FLOWMAP_HAS_FIELD(&mask.mf.map, regs));
3101
3102
    /* Do not allocate extra space. */
3103
0
    flow = xmalloc(sizeof *flow - sizeof flow->cr.flow.mf + mask.len);
3104
0
    memset(&flow->stats, 0, sizeof flow->stats);
3105
0
    flow->dead = false;
3106
0
    flow->offloaded = false;
3107
0
    atomic_init(&flow->offload_queue_depth, 0);
3108
0
    flow->batch = NULL;
3109
0
    flow->orig_in_port = orig_in_port;
3110
0
    *CONST_CAST(unsigned *, &flow->pmd_id) = pmd->core_id;
3111
0
    *CONST_CAST(struct flow *, &flow->flow) = match->flow;
3112
0
    *CONST_CAST(ovs_u128 *, &flow->ufid) = *ufid;
3113
0
    ovs_refcount_init(&flow->ref_cnt);
3114
0
    ovsrcu_set(&flow->actions, dp_netdev_actions_create(actions, actions_len));
3115
3116
0
    dp_netdev_get_mega_ufid(match, CONST_CAST(ovs_u128 *, &flow->mega_ufid));
3117
0
    netdev_flow_key_init_masked(&flow->cr.flow, &match->flow, &mask);
3118
3119
    /* Select dpcls for in_port. Relies on in_port to be exact match. */
3120
0
    cls = dp_netdev_pmd_find_dpcls(pmd, in_port);
3121
0
    dpcls_insert(cls, &flow->cr, &mask);
3122
3123
0
    ds_put_cstr(&extra_info, "miniflow_bits(");
3124
0
    FLOWMAP_FOR_EACH_UNIT (unit) {
3125
0
        if (unit) {
3126
0
            ds_put_char(&extra_info, ',');
3127
0
        }
3128
0
        ds_put_format(&extra_info, "%d",
3129
0
                      count_1bits(flow->cr.mask->mf.map.bits[unit]));
3130
0
    }
3131
0
    ds_put_char(&extra_info, ')');
3132
0
    flow->dp_extra_info = ds_steal_cstr(&extra_info);
3133
0
    ds_destroy(&extra_info);
3134
3135
0
    cmap_insert(&pmd->flow_table, CONST_CAST(struct cmap_node *, &flow->node),
3136
0
                dp_netdev_flow_hash(&flow->ufid));
3137
0
    ccmap_inc(&pmd->n_flows, odp_to_u32(in_port));
3138
3139
0
    if (dp_netdev_flow_is_simple_match(match)) {
3140
0
        dp_netdev_simple_match_insert(pmd, flow);
3141
0
    }
3142
3143
0
    offload_flow_put(pmd, flow, match, actions, actions_len);
3144
0
    log_netdev_flow_change(flow, match, NULL, actions, actions_len);
3145
3146
0
    return flow;
3147
0
}
3148
3149
static int
3150
flow_put_on_pmd(struct dp_netdev_pmd_thread *pmd,
3151
                struct netdev_flow_key *key,
3152
                struct match *match,
3153
                ovs_u128 *ufid,
3154
                const struct dpif_flow_put *put,
3155
                struct dpif_flow_stats *stats)
3156
0
{
3157
0
    struct dp_netdev_flow *netdev_flow = NULL;
3158
0
    int error = 0;
3159
3160
0
    if (stats) {
3161
0
        memset(stats, 0, sizeof *stats);
3162
0
    }
3163
3164
0
    ovs_mutex_lock(&pmd->flow_mutex);
3165
0
    if (put->ufid) {
3166
0
        netdev_flow = dp_netdev_pmd_find_flow(pmd, put->ufid,
3167
0
                                              put->key, put->key_len);
3168
0
    } else {
3169
        /* Use key instead of the locally generated ufid
3170
         * to search netdev_flow. */
3171
0
        netdev_flow = dp_netdev_pmd_lookup_flow(pmd, key, NULL);
3172
0
    }
3173
3174
0
    if (put->flags & DPIF_FP_CREATE) {
3175
0
        if (!netdev_flow) {
3176
0
            dp_netdev_flow_add(pmd, match, ufid,
3177
0
                               put->actions, put->actions_len, ODPP_NONE);
3178
0
        } else {
3179
0
            error = EEXIST;
3180
0
        }
3181
0
        goto exit;
3182
0
    }
3183
3184
0
    if (put->flags & DPIF_FP_MODIFY) {
3185
0
        if (!netdev_flow) {
3186
0
            error = ENOENT;
3187
0
        } else {
3188
0
            if (!put->ufid && !flow_equal(&match->flow, &netdev_flow->flow)) {
3189
                /* Overlapping flow. */
3190
0
                error = EINVAL;
3191
0
                goto exit;
3192
0
            }
3193
3194
0
            struct dp_netdev_actions *new_actions;
3195
0
            struct dp_netdev_actions *old_actions;
3196
3197
0
            new_actions = dp_netdev_actions_create(put->actions,
3198
0
                                                   put->actions_len);
3199
3200
0
            old_actions = dp_netdev_flow_get_actions(netdev_flow);
3201
0
            ovsrcu_set(&netdev_flow->actions, new_actions);
3202
3203
0
            offload_flow_put(pmd, netdev_flow, match, put->actions,
3204
0
                             put->actions_len);
3205
0
            log_netdev_flow_change(netdev_flow, match, old_actions,
3206
0
                                   put->actions, put->actions_len);
3207
3208
0
            if (stats) {
3209
0
                get_dpif_flow_status(pmd->dp, netdev_flow, stats, NULL);
3210
0
            }
3211
0
            if (put->flags & DPIF_FP_ZERO_STATS) {
3212
                /* XXX: The userspace datapath uses thread local statistics
3213
                 * (for flows), which should be updated only by the owning
3214
                 * thread.  Since we cannot write on stats memory here,
3215
                 * we choose not to support this flag.  Please note:
3216
                 * - This feature is currently used only by dpctl commands with
3217
                 *   option --clear.
3218
                 * - Should the need arise, this operation can be implemented
3219
                 *   by keeping a base value (to be update here) for each
3220
                 *   counter, and subtracting it before outputting the stats */
3221
0
                error = EOPNOTSUPP;
3222
0
            }
3223
0
            ovsrcu_postpone(dp_netdev_actions_free, old_actions);
3224
0
        }
3225
0
    }
3226
3227
0
exit:
3228
0
    ovs_mutex_unlock(&pmd->flow_mutex);
3229
0
    return error;
3230
0
}
3231
3232
static int
3233
dpif_netdev_flow_put(struct dpif *dpif, const struct dpif_flow_put *put)
3234
0
{
3235
0
    struct dp_netdev *dp = get_dp_netdev(dpif);
3236
0
    struct netdev_flow_key key;
3237
0
    struct dp_netdev_pmd_thread *pmd;
3238
0
    struct match match;
3239
0
    ovs_u128 ufid;
3240
0
    int error;
3241
0
    bool probe = put->flags & DPIF_FP_PROBE;
3242
3243
0
    if (put->stats) {
3244
0
        memset(put->stats, 0, sizeof *put->stats);
3245
0
    }
3246
0
    error = dpif_netdev_flow_from_nlattrs(put->key, put->key_len, &match.flow,
3247
0
                                          probe);
3248
0
    if (error) {
3249
0
        return error;
3250
0
    }
3251
0
    error = dpif_netdev_mask_from_nlattrs(put->key, put->key_len,
3252
0
                                          put->mask, put->mask_len,
3253
0
                                          &match.flow, &match.wc, probe);
3254
0
    if (error) {
3255
0
        return error;
3256
0
    }
3257
3258
0
    if (match.wc.masks.in_port.odp_port != ODPP_NONE) {
3259
0
        static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
3260
3261
0
        VLOG_ERR_RL(&rl, "failed to put%s flow: in_port is not an exact match",
3262
0
                    (put->flags & DPIF_FP_CREATE) ? "[create]"
3263
0
                    : (put->flags & DPIF_FP_MODIFY) ? "[modify]" : "[zero]");
3264
0
        return EINVAL;
3265
0
    }
3266
3267
0
    if (put->ufid) {
3268
0
        ufid = *put->ufid;
3269
0
    } else {
3270
0
        odp_flow_key_hash(&match.flow, sizeof match.flow, &ufid);
3271
0
    }
3272
3273
    /* The Netlink encoding of datapath flow keys cannot express
3274
     * wildcarding the presence of a VLAN tag. Instead, a missing VLAN
3275
     * tag is interpreted as exact match on the fact that there is no
3276
     * VLAN.  Unless we refactor a lot of code that translates between
3277
     * Netlink and struct flow representations, we have to do the same
3278
     * here.  This must be in sync with 'match' in handle_packet_upcall(). */
3279
0
    if (!match.wc.masks.vlans[0].tci) {
3280
0
        match.wc.masks.vlans[0].tci = htons(VLAN_VID_MASK | VLAN_CFI);
3281
0
    }
3282
3283
    /* Must produce a netdev_flow_key for lookup.
3284
     * Use the same method as employed to create the key when adding
3285
     * the flow to the dplcs to make sure they match.
3286
     * We need to put in the unmasked key as flow_put_on_pmd() will first try
3287
     * to see if an entry exists doing a packet type lookup. As masked-out
3288
     * fields are interpreted as zeros, they could falsely match a wider IP
3289
     * address mask. Installation of the flow will use the match variable. */
3290
0
    netdev_flow_key_init(&key, &match.flow);
3291
3292
0
    if (put->pmd_id == PMD_ID_NULL) {
3293
0
        if (cmap_count(&dp->poll_threads) == 0) {
3294
0
            return EINVAL;
3295
0
        }
3296
0
        CMAP_FOR_EACH (pmd, node, &dp->poll_threads) {
3297
0
            struct dpif_flow_stats pmd_stats;
3298
0
            int pmd_error;
3299
3300
0
            pmd_error = flow_put_on_pmd(pmd, &key, &match, &ufid, put,
3301
0
                                        &pmd_stats);
3302
0
            if (pmd_error) {
3303
0
                error = pmd_error;
3304
0
            } else if (put->stats) {
3305
0
                put->stats->n_packets += pmd_stats.n_packets;
3306
0
                put->stats->n_bytes += pmd_stats.n_bytes;
3307
0
                put->stats->used = MAX(put->stats->used, pmd_stats.used);
3308
0
                put->stats->tcp_flags |= pmd_stats.tcp_flags;
3309
0
            }
3310
0
        }
3311
0
    } else {
3312
0
        pmd = dp_netdev_get_pmd(dp, put->pmd_id);
3313
0
        if (!pmd) {
3314
0
            return EINVAL;
3315
0
        }
3316
0
        error = flow_put_on_pmd(pmd, &key, &match, &ufid, put, put->stats);
3317
0
        dp_netdev_pmd_unref(pmd);
3318
0
    }
3319
3320
0
    return error;
3321
0
}
3322
3323
static int
3324
flow_del_on_pmd(struct dp_netdev_pmd_thread *pmd,
3325
                struct dpif_flow_stats *stats,
3326
                const struct dpif_flow_del *del)
3327
0
{
3328
0
    struct dp_netdev_flow *netdev_flow;
3329
0
    int error = 0;
3330
3331
0
    ovs_mutex_lock(&pmd->flow_mutex);
3332
0
    netdev_flow = dp_netdev_pmd_find_flow(pmd, del->ufid, del->key,
3333
0
                                          del->key_len);
3334
0
    if (netdev_flow) {
3335
0
        if (stats) {
3336
0
            get_dpif_flow_status(pmd->dp, netdev_flow, stats, NULL);
3337
0
        }
3338
0
        dp_netdev_pmd_remove_flow(pmd, netdev_flow);
3339
0
    } else {
3340
0
        error = ENOENT;
3341
0
    }
3342
0
    ovs_mutex_unlock(&pmd->flow_mutex);
3343
3344
0
    return error;
3345
0
}
3346
3347
static int
3348
dpif_netdev_flow_del(struct dpif *dpif, const struct dpif_flow_del *del)
3349
0
{
3350
0
    struct dp_netdev *dp = get_dp_netdev(dpif);
3351
0
    struct dp_netdev_pmd_thread *pmd;
3352
0
    int error = 0;
3353
3354
0
    if (del->stats) {
3355
0
        memset(del->stats, 0, sizeof *del->stats);
3356
0
    }
3357
3358
0
    if (del->pmd_id == PMD_ID_NULL) {
3359
0
        if (cmap_count(&dp->poll_threads) == 0) {
3360
0
            return EINVAL;
3361
0
        }
3362
0
        CMAP_FOR_EACH (pmd, node, &dp->poll_threads) {
3363
0
            struct dpif_flow_stats pmd_stats;
3364
0
            int pmd_error;
3365
3366
0
            pmd_error = flow_del_on_pmd(pmd, &pmd_stats, del);
3367
0
            if (pmd_error) {
3368
0
                error = pmd_error;
3369
0
            } else if (del->stats) {
3370
0
                del->stats->n_packets += pmd_stats.n_packets;
3371
0
                del->stats->n_bytes += pmd_stats.n_bytes;
3372
0
                del->stats->used = MAX(del->stats->used, pmd_stats.used);
3373
0
                del->stats->tcp_flags |= pmd_stats.tcp_flags;
3374
0
            }
3375
0
        }
3376
0
    } else {
3377
0
        pmd = dp_netdev_get_pmd(dp, del->pmd_id);
3378
0
        if (!pmd) {
3379
0
            return EINVAL;
3380
0
        }
3381
0
        error = flow_del_on_pmd(pmd, del->stats, del);
3382
0
        dp_netdev_pmd_unref(pmd);
3383
0
    }
3384
3385
3386
0
    return error;
3387
0
}
3388
3389
struct dpif_netdev_flow_dump {
3390
    struct dpif_flow_dump up;
3391
    struct cmap_position poll_thread_pos;
3392
    struct cmap_position flow_pos;
3393
    struct dp_netdev_pmd_thread *cur_pmd;
3394
    int status;
3395
    struct ovs_mutex mutex;
3396
};
3397
3398
static struct dpif_netdev_flow_dump *
3399
dpif_netdev_flow_dump_cast(struct dpif_flow_dump *dump)
3400
0
{
3401
0
    return CONTAINER_OF(dump, struct dpif_netdev_flow_dump, up);
3402
0
}
3403
3404
static struct dpif_flow_dump *
3405
dpif_netdev_flow_dump_create(const struct dpif *dpif_, bool terse,
3406
                             struct dpif_flow_dump_types *types)
3407
0
{
3408
0
    struct dpif_netdev_flow_dump *dump;
3409
3410
0
    dump = xzalloc(sizeof *dump);
3411
0
    dpif_flow_dump_init(&dump->up, dpif_, terse, types);
3412
0
    ovs_mutex_init(&dump->mutex);
3413
3414
0
    return &dump->up;
3415
0
}
3416
3417
static int
3418
dpif_netdev_flow_dump_destroy(struct dpif_flow_dump *dump_)
3419
0
{
3420
0
    struct dpif_netdev_flow_dump *dump = dpif_netdev_flow_dump_cast(dump_);
3421
3422
0
    ovs_mutex_destroy(&dump->mutex);
3423
0
    free(dump);
3424
0
    return 0;
3425
0
}
3426
3427
struct dpif_netdev_flow_dump_thread {
3428
    struct dpif_flow_dump_thread up;
3429
    struct dpif_netdev_flow_dump *dump;
3430
    struct odputil_keybuf keybuf[FLOW_DUMP_MAX_BATCH];
3431
    struct odputil_keybuf maskbuf[FLOW_DUMP_MAX_BATCH];
3432
};
3433
3434
static struct dpif_netdev_flow_dump_thread *
3435
dpif_netdev_flow_dump_thread_cast(struct dpif_flow_dump_thread *thread)
3436
0
{
3437
0
    return CONTAINER_OF(thread, struct dpif_netdev_flow_dump_thread, up);
3438
0
}
3439
3440
static struct dpif_flow_dump_thread *
3441
dpif_netdev_flow_dump_thread_create(struct dpif_flow_dump *dump_)
3442
0
{
3443
0
    struct dpif_netdev_flow_dump *dump = dpif_netdev_flow_dump_cast(dump_);
3444
0
    struct dpif_netdev_flow_dump_thread *thread;
3445
3446
0
    thread = xmalloc(sizeof *thread);
3447
0
    dpif_flow_dump_thread_init(&thread->up, &dump->up);
3448
0
    thread->dump = dump;
3449
0
    return &thread->up;
3450
0
}
3451
3452
static void
3453
dpif_netdev_flow_dump_thread_destroy(struct dpif_flow_dump_thread *thread_)
3454
0
{
3455
0
    struct dpif_netdev_flow_dump_thread *thread
3456
0
        = dpif_netdev_flow_dump_thread_cast(thread_);
3457
3458
0
    free(thread);
3459
0
}
3460
3461
static int
3462
dpif_netdev_flow_dump_next(struct dpif_flow_dump_thread *thread_,
3463
                           struct dpif_flow *flows, int max_flows)
3464
0
{
3465
0
    struct dpif_netdev_flow_dump_thread *thread
3466
0
        = dpif_netdev_flow_dump_thread_cast(thread_);
3467
0
    struct dpif_netdev_flow_dump *dump = thread->dump;
3468
0
    struct dp_netdev_flow *netdev_flows[FLOW_DUMP_MAX_BATCH];
3469
0
    struct dpif_netdev *dpif = dpif_netdev_cast(thread->up.dump->dpif);
3470
0
    struct dp_netdev *dp = get_dp_netdev(&dpif->dpif);
3471
0
    int n_flows = 0;
3472
0
    int i;
3473
3474
0
    ovs_mutex_lock(&dump->mutex);
3475
0
    if (!dump->status) {
3476
0
        struct dp_netdev_pmd_thread *pmd = dump->cur_pmd;
3477
0
        int flow_limit = MIN(max_flows, FLOW_DUMP_MAX_BATCH);
3478
3479
        /* First call to dump_next(), extracts the first pmd thread.
3480
         * If there is no pmd thread, returns immediately. */
3481
0
        if (!pmd) {
3482
0
            pmd = dp_netdev_pmd_get_next(dp, &dump->poll_thread_pos);
3483
0
            if (!pmd) {
3484
0
                ovs_mutex_unlock(&dump->mutex);
3485
0
                return n_flows;
3486
3487
0
            }
3488
0
        }
3489
3490
0
        do {
3491
0
            for (n_flows = 0; n_flows < flow_limit; n_flows++) {
3492
0
                struct cmap_node *node;
3493
3494
0
                node = cmap_next_position(&pmd->flow_table, &dump->flow_pos);
3495
0
                if (!node) {
3496
0
                    break;
3497
0
                }
3498
0
                netdev_flows[n_flows] = CONTAINER_OF(node,
3499
0
                                                     struct dp_netdev_flow,
3500
0
                                                     node);
3501
0
            }
3502
            /* When finishing dumping the current pmd thread, moves to
3503
             * the next. */
3504
0
            if (n_flows < flow_limit) {
3505
0
                memset(&dump->flow_pos, 0, sizeof dump->flow_pos);
3506
0
                dp_netdev_pmd_unref(pmd);
3507
0
                pmd = dp_netdev_pmd_get_next(dp, &dump->poll_thread_pos);
3508
0
                if (!pmd) {
3509
0
                    dump->status = EOF;
3510
0
                    break;
3511
0
                }
3512
0
            }
3513
            /* Keeps the reference to next caller. */
3514
0
            dump->cur_pmd = pmd;
3515
3516
            /* If the current dump is empty, do not exit the loop, since the
3517
             * remaining pmds could have flows to be dumped.  Just dumps again
3518
             * on the new 'pmd'. */
3519
0
        } while (!n_flows);
3520
0
    }
3521
0
    ovs_mutex_unlock(&dump->mutex);
3522
3523
0
    for (i = 0; i < n_flows; i++) {
3524
0
        struct odputil_keybuf *maskbuf = &thread->maskbuf[i];
3525
0
        struct odputil_keybuf *keybuf = &thread->keybuf[i];
3526
0
        struct dp_netdev_flow *netdev_flow = netdev_flows[i];
3527
0
        struct dpif_flow *f = &flows[i];
3528
0
        struct ofpbuf key, mask;
3529
3530
0
        ofpbuf_use_stack(&key, keybuf, sizeof *keybuf);
3531
0
        ofpbuf_use_stack(&mask, maskbuf, sizeof *maskbuf);
3532
0
        dp_netdev_flow_to_dpif_flow(dp, netdev_flow, &key, &mask, f,
3533
0
                                    dump->up.terse);
3534
0
    }
3535
3536
0
    return n_flows;
3537
0
}
3538
3539
static int
3540
dpif_netdev_execute(struct dpif *dpif, struct dpif_execute *execute)
3541
    OVS_NO_THREAD_SAFETY_ANALYSIS
3542
0
{
3543
0
    struct dp_netdev *dp = get_dp_netdev(dpif);
3544
0
    struct dp_netdev_pmd_thread *pmd;
3545
0
    struct dp_packet_batch pp;
3546
3547
0
    if (dp_packet_size(execute->packet) < ETH_HEADER_LEN ||
3548
0
        dp_packet_size(execute->packet) > UINT16_MAX) {
3549
0
        return EINVAL;
3550
0
    }
3551
3552
    /* Tries finding the 'pmd'.  If NULL is returned, that means
3553
     * the current thread is a non-pmd thread and should use
3554
     * dp_netdev_get_pmd(dp, NON_PMD_CORE_ID). */
3555
0
    pmd = ovsthread_getspecific(dp->per_pmd_key);
3556
0
    if (!pmd) {
3557
0
        pmd = dp_netdev_get_pmd(dp, NON_PMD_CORE_ID);
3558
0
        if (!pmd) {
3559
0
            return EBUSY;
3560
0
        }
3561
0
    }
3562
3563
0
    if (execute->probe) {
3564
        /* If this is part of a probe, Drop the packet, since executing
3565
         * the action may actually cause spurious packets be sent into
3566
         * the network. */
3567
0
        if (pmd->core_id == NON_PMD_CORE_ID) {
3568
0
            dp_netdev_pmd_unref(pmd);
3569
0
        }
3570
0
        return 0;
3571
0
    }
3572
3573
    /* If the current thread is non-pmd thread, acquires
3574
     * the 'non_pmd_mutex'. */
3575
0
    if (pmd->core_id == NON_PMD_CORE_ID) {
3576
0
        ovs_mutex_lock(&dp->non_pmd_mutex);
3577
0
    }
3578
3579
    /* Update current time in PMD context. We don't care about EMC insertion
3580
     * probability, because we are on a slow path. */
3581
0
    pmd_thread_ctx_time_update(pmd);
3582
3583
    /* The action processing expects the RSS hash to be valid, because
3584
     * it's always initialized at the beginning of datapath processing.
3585
     * In this case, though, 'execute->packet' may not have gone through
3586
     * the datapath at all, it may have been generated by the upper layer
3587
     * (OpenFlow packet-out, BFD frame, ...). */
3588
0
    if (!dp_packet_rss_valid(execute->packet)) {
3589
0
        dp_packet_set_rss_hash(execute->packet,
3590
0
                               flow_hash_5tuple(execute->flow, 0));
3591
0
    }
3592
3593
    /* Making a copy because the packet might be stolen during the execution
3594
     * and caller might still need it.  */
3595
0
    struct dp_packet *packet_clone = dp_packet_clone(execute->packet);
3596
0
    dp_packet_batch_init_packet(&pp, packet_clone);
3597
0
    dp_netdev_execute_actions(pmd, &pp, false, execute->flow,
3598
0
                              execute->actions, execute->actions_len);
3599
0
    dp_netdev_pmd_flush_output_packets(pmd, true);
3600
3601
0
    if (pmd->core_id == NON_PMD_CORE_ID) {
3602
0
        ovs_mutex_unlock(&dp->non_pmd_mutex);
3603
0
        dp_netdev_pmd_unref(pmd);
3604
0
    }
3605
3606
0
    if (dp_packet_batch_size(&pp) == 1) {
3607
        /* Packet wasn't dropped during the execution.  Swapping content with
3608
         * the original packet, because the caller might expect actions to
3609
         * modify it.  Uisng the packet from a batch instead of 'packet_clone'
3610
         * because it maybe stolen and replaced by other packet, e.g. by
3611
         * the fragmentation engine. */
3612
0
        dp_packet_swap(execute->packet, pp.packets[0]);
3613
0
        dp_packet_delete_batch(&pp, true);
3614
0
    } else if (dp_packet_batch_size(&pp)) {
3615
        /* FIXME: We have more packets than expected.  Likely, we got IP
3616
         * fragments of the reassembled packet.  Dropping them here as we have
3617
         * no way to get them to the caller.  It might be that all the required
3618
         * actions with them are already executed, but it also might not be a
3619
         * case, e.g. if dpif_netdev_execute() called to execute a single
3620
         * tunnel push. */
3621
0
        dp_packet_delete_batch(&pp, true);
3622
0
    }
3623
0
    dp_packet_batch_destroy(&pp);
3624
3625
0
    return 0;
3626
0
}
3627
3628
static void
3629
dpif_netdev_operate(struct dpif *dpif, struct dpif_op **ops, size_t n_ops)
3630
0
{
3631
0
    size_t i;
3632
3633
0
    for (i = 0; i < n_ops; i++) {
3634
0
        struct dpif_op *op = ops[i];
3635
3636
0
        switch (op->type) {
3637
0
        case DPIF_OP_FLOW_PUT:
3638
0
            op->error = dpif_netdev_flow_put(dpif, &op->flow_put);
3639
0
            break;
3640
3641
0
        case DPIF_OP_FLOW_DEL:
3642
0
            op->error = dpif_netdev_flow_del(dpif, &op->flow_del);
3643
0
            break;
3644
3645
0
        case DPIF_OP_EXECUTE:
3646
0
            op->error = dpif_netdev_execute(dpif, &op->execute);
3647
0
            break;
3648
3649
0
        case DPIF_OP_FLOW_GET:
3650
0
            op->error = dpif_netdev_flow_get(dpif, &op->flow_get);
3651
0
            break;
3652
0
        }
3653
0
    }
3654
0
}
3655
3656
/* Enable or Disable PMD auto load balancing. */
3657
static void
3658
set_pmd_auto_lb(struct dp_netdev *dp, bool state, bool always_log)
3659
0
{
3660
0
    struct pmd_auto_lb *pmd_alb = &dp->pmd_alb;
3661
3662
0
    if (pmd_alb->is_enabled != state || always_log) {
3663
0
        pmd_alb->is_enabled = state;
3664
0
        if (pmd_alb->is_enabled) {
3665
0
            uint8_t rebalance_load_thresh;
3666
3667
0
            atomic_read_relaxed(&pmd_alb->rebalance_load_thresh,
3668
0
                                &rebalance_load_thresh);
3669
0
            VLOG_INFO("PMD auto load balance is enabled, "
3670
0
                      "interval %"PRIu64" mins, "
3671
0
                      "pmd load threshold %"PRIu8"%%, "
3672
0
                      "improvement threshold %"PRIu8"%%.",
3673
0
                       pmd_alb->rebalance_intvl / MIN_TO_MSEC,
3674
0
                       rebalance_load_thresh,
3675
0
                       pmd_alb->rebalance_improve_thresh);
3676
0
        } else {
3677
0
            pmd_alb->rebalance_poll_timer = 0;
3678
0
            VLOG_INFO("PMD auto load balance is disabled.");
3679
0
        }
3680
0
    }
3681
0
}
3682
3683
static int
3684
parse_pmd_sleep_list(const char *max_sleep_list,
3685
                     struct pmd_sleep **pmd_sleeps)
3686
0
{
3687
0
    char *list, *copy, *key, *value;
3688
0
    int num_vals = 0;
3689
3690
0
    if (!max_sleep_list) {
3691
0
        return num_vals;
3692
0
    }
3693
3694
0
    list = copy = xstrdup(max_sleep_list);
3695
3696
0
    while (ofputil_parse_key_value(&list, &key, &value)) {
3697
0
        uint64_t temp, pmd_max_sleep;
3698
0
        char *error = NULL;
3699
0
        unsigned core;
3700
0
        int i;
3701
3702
0
        error = str_to_u64(key, &temp);
3703
0
        if (error) {
3704
0
            free(error);
3705
0
            continue;
3706
0
        }
3707
3708
0
        if (value[0] == '\0') {
3709
            /* No value specified. key is dp default. */
3710
0
            core = UINT_MAX;
3711
0
            pmd_max_sleep = temp;
3712
0
        } else {
3713
0
            error = str_to_u64(value, &pmd_max_sleep);
3714
0
            if (!error && temp < UINT_MAX) {
3715
                /* Key is pmd core id. */
3716
0
                core = (unsigned) temp;
3717
0
            } else {
3718
0
                free(error);
3719
0
                continue;
3720
0
            }
3721
0
        }
3722
3723
        /* Detect duplicate max sleep values. */
3724
0
        for (i = 0; i < num_vals; i++) {
3725
0
            if ((*pmd_sleeps)[i].core_id == core) {
3726
0
                break;
3727
0
            }
3728
0
        }
3729
0
        if (i == num_vals) {
3730
            /* Not duplicate, add a new entry. */
3731
0
            *pmd_sleeps = xrealloc(*pmd_sleeps,
3732
0
                                   (num_vals + 1) * sizeof **pmd_sleeps);
3733
0
            num_vals++;
3734
0
        }
3735
3736
0
        pmd_max_sleep = MIN(PMD_RCU_QUIESCE_INTERVAL, pmd_max_sleep);
3737
3738
0
        (*pmd_sleeps)[i].core_id = core;
3739
0
        (*pmd_sleeps)[i].max_sleep = pmd_max_sleep;
3740
0
    }
3741
3742
0
    free(copy);
3743
0
    return num_vals;
3744
0
}
3745
3746
static void
3747
log_pmd_sleep(unsigned core_id, int numa_id, uint64_t pmd_max_sleep)
3748
0
{
3749
0
    if (core_id == NON_PMD_CORE_ID) {
3750
0
        return;
3751
0
    }
3752
0
    VLOG_INFO("PMD thread on numa_id: %d, core id: %2d, "
3753
0
              "max sleep: %4"PRIu64" us.", numa_id, core_id, pmd_max_sleep);
3754
0
}
3755
3756
static void
3757
pmd_init_max_sleep(struct dp_netdev *dp, struct dp_netdev_pmd_thread *pmd)
3758
0
{
3759
0
    uint64_t max_sleep = dp->pmd_max_sleep_default;
3760
0
    struct pmd_sleep *pmd_sleeps = NULL;
3761
0
    int num_vals;
3762
3763
0
    num_vals = parse_pmd_sleep_list(dp->max_sleep_list, &pmd_sleeps);
3764
3765
    /* Check if the user has set a specific value for this pmd. */
3766
0
    for (int i = 0; i < num_vals; i++) {
3767
0
        if (pmd_sleeps[i].core_id == pmd->core_id) {
3768
0
            max_sleep = pmd_sleeps[i].max_sleep;
3769
0
            break;
3770
0
        }
3771
0
    }
3772
0
    atomic_init(&pmd->max_sleep, max_sleep);
3773
0
    log_pmd_sleep(pmd->core_id, pmd->numa_id, max_sleep);
3774
0
    free(pmd_sleeps);
3775
0
}
3776
3777
static bool
3778
assign_sleep_values_to_pmds(struct dp_netdev *dp, int num_vals,
3779
                            struct pmd_sleep *pmd_sleeps)
3780
0
{
3781
0
    struct dp_netdev_pmd_thread *pmd;
3782
0
    bool value_changed = false;
3783
3784
0
    CMAP_FOR_EACH (pmd, node, &dp->poll_threads) {
3785
0
        uint64_t new_max_sleep, cur_pmd_max_sleep;
3786
3787
0
        if (pmd->core_id == NON_PMD_CORE_ID) {
3788
0
            continue;
3789
0
        }
3790
3791
        /* Default to global value. */
3792
0
        new_max_sleep = dp->pmd_max_sleep_default;
3793
3794
        /* Check for pmd specific value. */
3795
0
        for (int i = 0;  i < num_vals; i++) {
3796
0
            if (pmd->core_id == pmd_sleeps[i].core_id) {
3797
0
                new_max_sleep = pmd_sleeps[i].max_sleep;
3798
0
                break;
3799
0
            }
3800
0
        }
3801
0
        atomic_read_relaxed(&pmd->max_sleep, &cur_pmd_max_sleep);
3802
0
        if (new_max_sleep != cur_pmd_max_sleep) {
3803
0
            atomic_store_relaxed(&pmd->max_sleep, new_max_sleep);
3804
0
            value_changed = true;
3805
0
        }
3806
0
    }
3807
0
    return value_changed;
3808
0
}
3809
3810
static void
3811
log_all_pmd_sleeps(struct dp_netdev *dp)
3812
0
{
3813
0
    struct dp_netdev_pmd_thread **pmd_list = NULL;
3814
0
    struct dp_netdev_pmd_thread *pmd;
3815
0
    size_t n;
3816
3817
0
    VLOG_INFO("Default PMD thread max sleep: %4"PRIu64" us.",
3818
0
              dp->pmd_max_sleep_default);
3819
3820
0
    sorted_poll_thread_list(dp, &pmd_list, &n);
3821
3822
0
    for (size_t i = 0; i < n; i++) {
3823
0
        uint64_t cur_pmd_max_sleep;
3824
3825
0
        pmd = pmd_list[i];
3826
0
        atomic_read_relaxed(&pmd->max_sleep, &cur_pmd_max_sleep);
3827
0
        log_pmd_sleep(pmd->core_id, pmd->numa_id, cur_pmd_max_sleep);
3828
0
    }
3829
0
    free(pmd_list);
3830
0
}
3831
3832
static bool
3833
set_all_pmd_max_sleeps(struct dp_netdev *dp, const struct smap *config)
3834
0
{
3835
0
    const char *max_sleep_list = smap_get(config, "pmd-sleep-max");
3836
0
    struct pmd_sleep *pmd_sleeps = NULL;
3837
0
    uint64_t default_max_sleep = 0;
3838
0
    bool default_changed = false;
3839
0
    bool pmd_changed = false;
3840
0
    uint64_t pmd_maxsleep;
3841
0
    int num_vals = 0;
3842
3843
    /* Check for deprecated 'pmd-maxsleep' value. */
3844
0
    pmd_maxsleep = smap_get_ullong(config, "pmd-maxsleep", UINT64_MAX);
3845
0
    if (pmd_maxsleep != UINT64_MAX && !max_sleep_list) {
3846
0
        VLOG_WARN_ONCE("pmd-maxsleep is deprecated. "
3847
0
                       "Please use pmd-sleep-max instead.");
3848
0
        default_max_sleep = pmd_maxsleep;
3849
0
    }
3850
3851
    /* Check if there is no change in string or value. */
3852
0
    if (!!dp->max_sleep_list == !!max_sleep_list) {
3853
0
        if (max_sleep_list
3854
0
            ? nullable_string_is_equal(max_sleep_list, dp->max_sleep_list)
3855
0
            : default_max_sleep == dp->pmd_max_sleep_default) {
3856
0
            return false;
3857
0
        }
3858
0
    }
3859
3860
    /* Free existing string and copy new one (if any). */
3861
0
    free(dp->max_sleep_list);
3862
0
    dp->max_sleep_list = nullable_xstrdup(max_sleep_list);
3863
3864
0
    if (max_sleep_list) {
3865
0
        num_vals = parse_pmd_sleep_list(max_sleep_list, &pmd_sleeps);
3866
3867
        /* Check if the user has set a global value. */
3868
0
        for (int i = 0; i < num_vals; i++) {
3869
0
            if (pmd_sleeps[i].core_id == UINT_MAX) {
3870
0
                default_max_sleep = pmd_sleeps[i].max_sleep;
3871
0
                break;
3872
0
            }
3873
0
        }
3874
0
    }
3875
3876
0
    if (dp->pmd_max_sleep_default != default_max_sleep) {
3877
0
        dp->pmd_max_sleep_default = default_max_sleep;
3878
0
        default_changed = true;
3879
0
    }
3880
0
    pmd_changed = assign_sleep_values_to_pmds(dp, num_vals, pmd_sleeps);
3881
3882
0
    free(pmd_sleeps);
3883
0
    return default_changed || pmd_changed;
3884
0
}
3885
3886
/* Applies datapath configuration from the database. Some of the changes are
3887
 * actually applied in dpif_netdev_run(). */
3888
static int
3889
dpif_netdev_set_config(struct dpif *dpif, const struct smap *other_config)
3890
0
{
3891
0
    struct dp_netdev *dp = get_dp_netdev(dpif);
3892
0
    const char *cmask = smap_get(other_config, "pmd-cpu-mask");
3893
0
    const char *pmd_rxq_assign = smap_get_def(other_config, "pmd-rxq-assign",
3894
0
                                             "cycles");
3895
0
    unsigned long long insert_prob =
3896
0
        smap_get_ullong(other_config, "emc-insert-inv-prob",
3897
0
                        DEFAULT_EM_FLOW_INSERT_INV_PROB);
3898
0
    uint32_t insert_min, cur_min;
3899
0
    uint32_t tx_flush_interval, cur_tx_flush_interval;
3900
0
    uint64_t rebalance_intvl;
3901
0
    uint8_t cur_rebalance_load;
3902
0
    uint32_t rebalance_load, rebalance_improve;
3903
0
    bool log_autolb = false;
3904
0
    enum sched_assignment_type pmd_rxq_assign_type;
3905
3906
0
    tx_flush_interval = smap_get_int(other_config, "tx-flush-interval",
3907
0
                                     DEFAULT_TX_FLUSH_INTERVAL);
3908
0
    atomic_read_relaxed(&dp->tx_flush_interval, &cur_tx_flush_interval);
3909
0
    if (tx_flush_interval != cur_tx_flush_interval) {
3910
0
        atomic_store_relaxed(&dp->tx_flush_interval, tx_flush_interval);
3911
0
        VLOG_INFO("Flushing interval for tx queues set to %"PRIu32" us",
3912
0
                  tx_flush_interval);
3913
0
    }
3914
3915
0
    if (!nullable_string_is_equal(dp->pmd_cmask, cmask)) {
3916
0
        free(dp->pmd_cmask);
3917
0
        dp->pmd_cmask = nullable_xstrdup(cmask);
3918
0
        dp_netdev_request_reconfigure(dp);
3919
0
    }
3920
3921
0
    atomic_read_relaxed(&dp->emc_insert_min, &cur_min);
3922
0
    if (insert_prob <= UINT32_MAX) {
3923
0
        insert_min = insert_prob == 0 ? 0 : UINT32_MAX / insert_prob;
3924
0
    } else {
3925
0
        insert_min = DEFAULT_EM_FLOW_INSERT_MIN;
3926
0
        insert_prob = DEFAULT_EM_FLOW_INSERT_INV_PROB;
3927
0
    }
3928
3929
0
    if (insert_min != cur_min) {
3930
0
        atomic_store_relaxed(&dp->emc_insert_min, insert_min);
3931
0
        if (insert_min == 0) {
3932
0
            VLOG_INFO("EMC insertion probability changed to zero");
3933
0
        } else {
3934
0
            VLOG_INFO("EMC insertion probability changed to 1/%llu (~%.2f%%)",
3935
0
                      insert_prob, (100 / (float)insert_prob));
3936
0
        }
3937
0
    }
3938
3939
0
    bool perf_enabled = smap_get_bool(other_config, "pmd-perf-metrics", false);
3940
0
    bool cur_perf_enabled;
3941
0
    atomic_read_relaxed(&dp->pmd_perf_metrics, &cur_perf_enabled);
3942
0
    if (perf_enabled != cur_perf_enabled) {
3943
0
        atomic_store_relaxed(&dp->pmd_perf_metrics, perf_enabled);
3944
0
        if (perf_enabled) {
3945
0
            VLOG_INFO("PMD performance metrics collection enabled");
3946
0
        } else {
3947
0
            VLOG_INFO("PMD performance metrics collection disabled");
3948
0
        }
3949
0
    }
3950
3951
0
    bool smc_enable = smap_get_bool(other_config, "smc-enable", false);
3952
0
    bool cur_smc;
3953
0
    atomic_read_relaxed(&dp->smc_enable_db, &cur_smc);
3954
0
    if (smc_enable != cur_smc) {
3955
0
        atomic_store_relaxed(&dp->smc_enable_db, smc_enable);
3956
0
        if (smc_enable) {
3957
0
            VLOG_INFO("SMC cache is enabled");
3958
0
        } else {
3959
0
            VLOG_INFO("SMC cache is disabled");
3960
0
        }
3961
0
    }
3962
3963
0
    if (!strcmp(pmd_rxq_assign, "roundrobin")) {
3964
0
        pmd_rxq_assign_type = SCHED_ROUNDROBIN;
3965
0
    } else if (!strcmp(pmd_rxq_assign, "cycles")) {
3966
0
        pmd_rxq_assign_type = SCHED_CYCLES;
3967
0
    } else if (!strcmp(pmd_rxq_assign, "group")) {
3968
0
        pmd_rxq_assign_type = SCHED_GROUP;
3969
0
    } else {
3970
        /* Default. */
3971
0
        VLOG_WARN("Unsupported rx queue to PMD assignment mode in "
3972
0
                  "pmd-rxq-assign. Defaulting to 'cycles'.");
3973
0
        pmd_rxq_assign_type = SCHED_CYCLES;
3974
0
        pmd_rxq_assign = "cycles";
3975
0
    }
3976
0
    if (dp->pmd_rxq_assign_type != pmd_rxq_assign_type) {
3977
0
        dp->pmd_rxq_assign_type = pmd_rxq_assign_type;
3978
0
        VLOG_INFO("Rxq to PMD assignment mode changed to: \'%s\'.",
3979
0
                  pmd_rxq_assign);
3980
0
        dp_netdev_request_reconfigure(dp);
3981
0
    }
3982
3983
0
    bool pmd_iso = smap_get_bool(other_config, "pmd-rxq-isolate", true);
3984
3985
0
    if (pmd_rxq_assign_type != SCHED_GROUP && pmd_iso == false) {
3986
        /* Invalid combination. */
3987
0
        VLOG_WARN("pmd-rxq-isolate can only be set false "
3988
0
                  "when using pmd-rxq-assign=group");
3989
0
        pmd_iso = true;
3990
0
    }
3991
0
    if (dp->pmd_iso != pmd_iso) {
3992
0
        dp->pmd_iso = pmd_iso;
3993
0
        if (pmd_iso) {
3994
0
            VLOG_INFO("pmd-rxq-affinity isolates PMD core");
3995
0
        } else {
3996
0
            VLOG_INFO("pmd-rxq-affinity does not isolate PMD core");
3997
0
        }
3998
0
        dp_netdev_request_reconfigure(dp);
3999
0
    }
4000
4001
0
    struct pmd_auto_lb *pmd_alb = &dp->pmd_alb;
4002
4003
0
    rebalance_intvl = smap_get_ullong(other_config,
4004
0
                                      "pmd-auto-lb-rebal-interval",
4005
0
                                      ALB_REBALANCE_INTERVAL);
4006
0
    if (rebalance_intvl > MAX_ALB_REBALANCE_INTERVAL) {
4007
0
        rebalance_intvl = ALB_REBALANCE_INTERVAL;
4008
0
    }
4009
4010
    /* Input is in min, convert it to msec. */
4011
0
    rebalance_intvl =
4012
0
        rebalance_intvl ? rebalance_intvl * MIN_TO_MSEC : MIN_TO_MSEC;
4013
4014
0
    if (pmd_alb->rebalance_intvl != rebalance_intvl) {
4015
0
        pmd_alb->rebalance_intvl = rebalance_intvl;
4016
0
        VLOG_INFO("PMD auto load balance interval set to "
4017
0
                  "%"PRIu64" mins\n", rebalance_intvl / MIN_TO_MSEC);
4018
0
        log_autolb = true;
4019
0
    }
4020
4021
0
    rebalance_improve = smap_get_uint(other_config,
4022
0
                                      "pmd-auto-lb-improvement-threshold",
4023
0
                                      ALB_IMPROVEMENT_THRESHOLD);
4024
0
    if (rebalance_improve > 100) {
4025
0
        rebalance_improve = ALB_IMPROVEMENT_THRESHOLD;
4026
0
    }
4027
0
    if (rebalance_improve != pmd_alb->rebalance_improve_thresh) {
4028
0
        pmd_alb->rebalance_improve_thresh = rebalance_improve;
4029
0
        VLOG_INFO("PMD auto load balance improvement threshold set to "
4030
0
                  "%"PRIu32"%%", rebalance_improve);
4031
0
        log_autolb = true;
4032
0
    }
4033
4034
0
    rebalance_load = smap_get_uint(other_config, "pmd-auto-lb-load-threshold",
4035
0
                                   ALB_LOAD_THRESHOLD);
4036
0
    if (rebalance_load > 100) {
4037
0
        rebalance_load = ALB_LOAD_THRESHOLD;
4038
0
    }
4039
0
    atomic_read_relaxed(&pmd_alb->rebalance_load_thresh, &cur_rebalance_load);
4040
0
    if (rebalance_load != cur_rebalance_load) {
4041
0
        atomic_store_relaxed(&pmd_alb->rebalance_load_thresh,
4042
0
                             rebalance_load);
4043
0
        VLOG_INFO("PMD auto load balance load threshold set to %"PRIu32"%%",
4044
0
                  rebalance_load);
4045
0
        log_autolb = true;
4046
0
    }
4047
4048
0
    bool autolb_state = smap_get_bool(other_config, "pmd-auto-lb", false);
4049
4050
0
    set_pmd_auto_lb(dp, autolb_state, log_autolb);
4051
4052
0
    bool sleep_changed = set_all_pmd_max_sleeps(dp, other_config);
4053
4054
0
    if (ovsthread_once_start(&dp->once_set_config)) {
4055
0
        log_all_pmd_sleeps(dp);
4056
0
        dpif_offload_datapath_register_flow_unreference_cb(
4057
0
            dpif, offload_flow_reference_unreference_cb);
4058
4059
0
        ovsthread_once_done(&dp->once_set_config);
4060
0
    } else if (sleep_changed) {
4061
0
        log_all_pmd_sleeps(dp);
4062
0
    }
4063
4064
0
    return 0;
4065
0
}
4066
4067
static bool
4068
dpif_netdev_number_handlers_required(struct dpif *dpif_ OVS_UNUSED,
4069
                                     uint32_t *n_handlers)
4070
0
{
4071
0
    *n_handlers = 0;
4072
0
    return true;
4073
0
}
4074
4075
/* Parses affinity list and returns result in 'core_ids'. */
4076
static int
4077
parse_affinity_list(const char *affinity_list, unsigned *core_ids, int n_rxq)
4078
0
{
4079
0
    unsigned i;
4080
0
    char *list, *copy, *key, *value;
4081
0
    int error = 0;
4082
4083
0
    for (i = 0; i < n_rxq; i++) {
4084
0
        core_ids[i] = OVS_CORE_UNSPEC;
4085
0
    }
4086
4087
0
    if (!affinity_list) {
4088
0
        return 0;
4089
0
    }
4090
4091
0
    list = copy = xstrdup(affinity_list);
4092
4093
0
    while (ofputil_parse_key_value(&list, &key, &value)) {
4094
0
        int rxq_id, core_id;
4095
4096
0
        if (!str_to_int(key, 0, &rxq_id) || rxq_id < 0
4097
0
            || !str_to_int(value, 0, &core_id) || core_id < 0) {
4098
0
            error = EINVAL;
4099
0
            break;
4100
0
        }
4101
4102
0
        if (rxq_id < n_rxq) {
4103
0
            core_ids[rxq_id] = core_id;
4104
0
        }
4105
0
    }
4106
4107
0
    free(copy);
4108
0
    return error;
4109
0
}
4110
4111
/* Parses 'affinity_list' and applies configuration if it is valid. */
4112
static int
4113
dpif_netdev_port_set_rxq_affinity(struct dp_netdev_port *port,
4114
                                  const char *affinity_list)
4115
0
{
4116
0
    unsigned *core_ids, i;
4117
0
    int error = 0;
4118
4119
0
    core_ids = xmalloc(port->n_rxq * sizeof *core_ids);
4120
0
    if (parse_affinity_list(affinity_list, core_ids, port->n_rxq)) {
4121
0
        error = EINVAL;
4122
0
        goto exit;
4123
0
    }
4124
4125
0
    for (i = 0; i < port->n_rxq; i++) {
4126
0
        port->rxqs[i].core_id = core_ids[i];
4127
0
    }
4128
4129
0
exit:
4130
0
    free(core_ids);
4131
0
    return error;
4132
0
}
4133
4134
/* Returns 'true' if one of the 'port's RX queues exists in 'poll_list'
4135
 * of given PMD thread. */
4136
static bool
4137
dpif_netdev_pmd_polls_port(struct dp_netdev_pmd_thread *pmd,
4138
                           struct dp_netdev_port *port)
4139
    OVS_EXCLUDED(pmd->port_mutex)
4140
0
{
4141
0
    struct rxq_poll *poll;
4142
0
    bool found = false;
4143
4144
0
    ovs_mutex_lock(&pmd->port_mutex);
4145
0
    HMAP_FOR_EACH (poll, node, &pmd->poll_list) {
4146
0
        if (port == poll->rxq->port) {
4147
0
            found = true;
4148
0
            break;
4149
0
        }
4150
0
    }
4151
0
    ovs_mutex_unlock(&pmd->port_mutex);
4152
0
    return found;
4153
0
}
4154
4155
/* Updates port configuration from the database.  The changes are actually
4156
 * applied in dpif_netdev_run(). */
4157
static int
4158
dpif_netdev_port_set_config(struct dpif *dpif, odp_port_t port_no,
4159
                            const struct smap *cfg)
4160
0
{
4161
0
    struct dp_netdev *dp = get_dp_netdev(dpif);
4162
0
    struct dp_netdev_port *port;
4163
0
    int error = 0;
4164
0
    const char *affinity_list = smap_get(cfg, "pmd-rxq-affinity");
4165
0
    bool emc_enabled = smap_get_bool(cfg, "emc-enable", true);
4166
0
    const char *tx_steering_mode = smap_get(cfg, "tx-steering");
4167
0
    enum txq_req_mode txq_mode;
4168
4169
0
    ovs_rwlock_wrlock(&dp->port_rwlock);
4170
0
    error = get_port_by_number(dp, port_no, &port);
4171
0
    if (error) {
4172
0
        goto unlock;
4173
0
    }
4174
4175
0
    if (emc_enabled != port->emc_enabled) {
4176
0
        struct dp_netdev_pmd_thread *pmd;
4177
0
        struct ds ds = DS_EMPTY_INITIALIZER;
4178
0
        uint32_t cur_min, insert_prob;
4179
4180
0
        port->emc_enabled = emc_enabled;
4181
        /* Mark for reload all the threads that polls this port and request
4182
         * for reconfiguration for the actual reloading of threads. */
4183
0
        CMAP_FOR_EACH (pmd, node, &dp->poll_threads) {
4184
0
            if (dpif_netdev_pmd_polls_port(pmd, port)) {
4185
0
                pmd->need_reload = true;
4186
0
            }
4187
0
        }
4188
0
        dp_netdev_request_reconfigure(dp);
4189
4190
0
        ds_put_format(&ds, "%s: EMC has been %s.",
4191
0
                      netdev_get_name(port->netdev),
4192
0
                      (emc_enabled) ? "enabled" : "disabled");
4193
0
        if (emc_enabled) {
4194
0
            ds_put_cstr(&ds, " Current insertion probability is ");
4195
0
            atomic_read_relaxed(&dp->emc_insert_min, &cur_min);
4196
0
            if (!cur_min) {
4197
0
                ds_put_cstr(&ds, "zero.");
4198
0
            } else {
4199
0
                insert_prob = UINT32_MAX / cur_min;
4200
0
                ds_put_format(&ds, "1/%"PRIu32" (~%.2f%%).",
4201
0
                              insert_prob, 100 / (float) insert_prob);
4202
0
            }
4203
0
        }
4204
0
        VLOG_INFO("%s", ds_cstr(&ds));
4205
0
        ds_destroy(&ds);
4206
0
    }
4207
4208
    /* Checking for RXq affinity changes. */
4209
0
    if (netdev_is_pmd(port->netdev)
4210
0
        && !nullable_string_is_equal(affinity_list, port->rxq_affinity_list)) {
4211
4212
0
        error = dpif_netdev_port_set_rxq_affinity(port, affinity_list);
4213
0
        if (error) {
4214
0
            goto unlock;
4215
0
        }
4216
0
        free(port->rxq_affinity_list);
4217
0
        port->rxq_affinity_list = nullable_xstrdup(affinity_list);
4218
4219
0
        dp_netdev_request_reconfigure(dp);
4220
0
    }
4221
4222
0
    if (nullable_string_is_equal(tx_steering_mode, "hash")) {
4223
0
        txq_mode = TXQ_REQ_MODE_HASH;
4224
0
    } else {
4225
0
        txq_mode = TXQ_REQ_MODE_THREAD;
4226
0
    }
4227
4228
0
    if (txq_mode != port->txq_requested_mode) {
4229
0
        port->txq_requested_mode = txq_mode;
4230
0
        VLOG_INFO("%s: Tx packet steering mode has been set to '%s'.",
4231
0
                  netdev_get_name(port->netdev),
4232
0
                  (txq_mode == TXQ_REQ_MODE_THREAD) ? "thread" : "hash");
4233
0
        dp_netdev_request_reconfigure(dp);
4234
0
    }
4235
4236
0
unlock:
4237
0
    ovs_rwlock_unlock(&dp->port_rwlock);
4238
0
    return error;
4239
0
}
4240
4241
static int
4242
dpif_netdev_queue_to_priority(const struct dpif *dpif OVS_UNUSED,
4243
                              uint32_t queue_id, uint32_t *priority)
4244
0
{
4245
0
    *priority = queue_id;
4246
0
    return 0;
4247
0
}
4248
4249

4250
/* Creates and returns a new 'struct dp_netdev_actions', whose actions are
4251
 * a copy of the 'size' bytes of 'actions' input parameters. */
4252
struct dp_netdev_actions *
4253
dp_netdev_actions_create(const struct nlattr *actions, size_t size)
4254
0
{
4255
0
    struct dp_netdev_actions *netdev_actions;
4256
4257
0
    netdev_actions = xmalloc(sizeof *netdev_actions + size);
4258
0
    netdev_actions->size = size;
4259
0
    if (size) {
4260
0
        memcpy(netdev_actions->actions, actions, size);
4261
0
    }
4262
4263
0
    return netdev_actions;
4264
0
}
4265
4266
struct dp_netdev_actions *
4267
dp_netdev_flow_get_actions(const struct dp_netdev_flow *flow)
4268
0
{
4269
0
    return ovsrcu_get(struct dp_netdev_actions *, &flow->actions);
4270
0
}
4271
4272
static void
4273
dp_netdev_actions_free(struct dp_netdev_actions *actions)
4274
0
{
4275
0
    free(actions);
4276
0
}
4277

4278
static void
4279
dp_netdev_rxq_set_cycles(struct dp_netdev_rxq *rx,
4280
                         enum rxq_cycles_counter_type type,
4281
                         unsigned long long cycles)
4282
0
{
4283
0
   atomic_store_relaxed(&rx->cycles[type], cycles);
4284
0
}
4285
4286
static void
4287
dp_netdev_rxq_add_cycles(struct dp_netdev_rxq *rx,
4288
                         enum rxq_cycles_counter_type type,
4289
                         unsigned long long cycles)
4290
0
{
4291
0
    non_atomic_ullong_add(&rx->cycles[type], cycles);
4292
0
}
4293
4294
static uint64_t
4295
dp_netdev_rxq_get_cycles(struct dp_netdev_rxq *rx,
4296
                         enum rxq_cycles_counter_type type)
4297
0
{
4298
0
    unsigned long long processing_cycles;
4299
0
    atomic_read_relaxed(&rx->cycles[type], &processing_cycles);
4300
0
    return processing_cycles;
4301
0
}
4302
4303
static void
4304
dp_netdev_rxq_set_intrvl_cycles(struct dp_netdev_rxq *rx,
4305
                                unsigned long long cycles)
4306
0
{
4307
0
    unsigned int idx = atomic_count_inc(&rx->intrvl_idx) % PMD_INTERVAL_MAX;
4308
0
    atomic_store_relaxed(&rx->cycles_intrvl[idx], cycles);
4309
0
}
4310
4311
static uint64_t
4312
dp_netdev_rxq_get_intrvl_cycles(struct dp_netdev_rxq *rx, unsigned idx)
4313
0
{
4314
0
    unsigned long long processing_cycles;
4315
0
    atomic_read_relaxed(&rx->cycles_intrvl[idx], &processing_cycles);
4316
0
    return processing_cycles;
4317
0
}
4318
4319
#if ATOMIC_ALWAYS_LOCK_FREE_8B
4320
static inline bool
4321
pmd_perf_metrics_enabled(const struct dp_netdev_pmd_thread *pmd)
4322
0
{
4323
0
    bool pmd_perf_enabled;
4324
0
    atomic_read_relaxed(&pmd->dp->pmd_perf_metrics, &pmd_perf_enabled);
4325
0
    return pmd_perf_enabled;
4326
0
}
4327
#else
4328
/* If stores and reads of 64-bit integers are not atomic, the full PMD
4329
 * performance metrics are not available as locked access to 64 bit
4330
 * integers would be prohibitively expensive. */
4331
static inline bool
4332
pmd_perf_metrics_enabled(const struct dp_netdev_pmd_thread *pmd OVS_UNUSED)
4333
{
4334
    return false;
4335
}
4336
#endif
4337
4338
static int
4339
dp_netdev_pmd_flush_output_on_port(struct dp_netdev_pmd_thread *pmd,
4340
                                   struct tx_port *p)
4341
0
{
4342
0
    int i;
4343
0
    int tx_qid;
4344
0
    int output_cnt;
4345
0
    bool concurrent_txqs;
4346
0
    struct cycle_timer timer;
4347
0
    uint64_t cycles;
4348
0
    uint32_t tx_flush_interval;
4349
4350
0
    cycle_timer_start(&pmd->perf_stats, &timer);
4351
4352
0
    output_cnt = dp_packet_batch_size(&p->output_pkts);
4353
0
    ovs_assert(output_cnt > 0);
4354
4355
0
    if (p->port->txq_mode == TXQ_MODE_XPS_HASH) {
4356
0
        int n_txq = netdev_n_txq(p->port->netdev);
4357
4358
        /* Re-batch per txq based on packet hash. */
4359
0
        struct dp_packet *packet;
4360
0
        DP_PACKET_BATCH_FOR_EACH (j, packet, &p->output_pkts) {
4361
0
            uint32_t hash;
4362
4363
0
            if (OVS_LIKELY(dp_packet_rss_valid(packet))) {
4364
0
                hash = dp_packet_get_rss_hash(packet);
4365
0
            } else {
4366
0
                struct flow flow;
4367
4368
0
                flow_extract(packet, &flow);
4369
0
                hash = flow_hash_5tuple(&flow, 0);
4370
0
            }
4371
0
            dp_packet_batch_add(&p->txq_pkts[hash % n_txq], packet);
4372
0
        }
4373
4374
        /* Flush batches of each Tx queues. */
4375
0
        for (i = 0; i < n_txq; i++) {
4376
0
            if (dp_packet_batch_is_empty(&p->txq_pkts[i])) {
4377
0
                continue;
4378
0
            }
4379
0
            netdev_send(p->port->netdev, i, &p->txq_pkts[i], true);
4380
0
            dp_packet_batch_reset(&p->txq_pkts[i]);
4381
0
        }
4382
0
    } else {
4383
0
        if (p->port->txq_mode == TXQ_MODE_XPS) {
4384
0
            tx_qid = dpif_netdev_xps_get_tx_qid(pmd, p);
4385
0
            concurrent_txqs = true;
4386
0
        } else {
4387
0
            tx_qid = pmd->static_tx_qid;
4388
0
            concurrent_txqs = false;
4389
0
        }
4390
0
        netdev_send(p->port->netdev, tx_qid, &p->output_pkts, concurrent_txqs);
4391
0
    }
4392
0
    dp_packet_batch_reset(&p->output_pkts);
4393
4394
    /* Update time of the next flush. */
4395
0
    atomic_read_relaxed(&pmd->dp->tx_flush_interval, &tx_flush_interval);
4396
0
    p->flush_time = pmd->ctx.now + tx_flush_interval;
4397
4398
0
    ovs_assert(pmd->n_output_batches > 0);
4399
0
    pmd->n_output_batches--;
4400
4401
0
    pmd_perf_update_counter(&pmd->perf_stats, PMD_STAT_SENT_PKTS, output_cnt);
4402
0
    pmd_perf_update_counter(&pmd->perf_stats, PMD_STAT_SENT_BATCHES, 1);
4403
4404
    /* Distribute send cycles evenly among transmitted packets and assign to
4405
     * their respective rx queues. */
4406
0
    cycles = cycle_timer_stop(&pmd->perf_stats, &timer) / output_cnt;
4407
0
    for (i = 0; i < output_cnt; i++) {
4408
0
        if (p->output_pkts_rxqs[i]) {
4409
0
            dp_netdev_rxq_add_cycles(p->output_pkts_rxqs[i],
4410
0
                                     RXQ_CYCLES_PROC_CURR, cycles);
4411
0
        }
4412
0
    }
4413
4414
0
    return output_cnt;
4415
0
}
4416
4417
static int
4418
dp_netdev_pmd_flush_output_packets(struct dp_netdev_pmd_thread *pmd,
4419
                                   bool force)
4420
0
{
4421
0
    struct tx_port *p;
4422
0
    int output_cnt = 0;
4423
4424
0
    if (!pmd->n_output_batches) {
4425
0
        return 0;
4426
0
    }
4427
4428
0
    HMAP_FOR_EACH (p, node, &pmd->send_port_cache) {
4429
0
        if (!dp_packet_batch_is_empty(&p->output_pkts)
4430
0
            && (force || pmd->ctx.now >= p->flush_time)) {
4431
0
            output_cnt += dp_netdev_pmd_flush_output_on_port(pmd, p);
4432
0
        }
4433
0
    }
4434
0
    return output_cnt;
4435
0
}
4436
4437
static int
4438
dp_netdev_process_rxq_port(struct dp_netdev_pmd_thread *pmd,
4439
                           struct dp_netdev_rxq *rxq,
4440
                           odp_port_t port_no)
4441
0
{
4442
0
    struct pmd_perf_stats *s = &pmd->perf_stats;
4443
0
    struct dp_packet_batch batch;
4444
0
    struct cycle_timer timer;
4445
0
    int error;
4446
0
    int batch_cnt = 0;
4447
0
    int rem_qlen = 0, *qlen_p = NULL;
4448
0
    uint64_t cycles;
4449
4450
    /* Measure duration for polling and processing rx burst. */
4451
0
    cycle_timer_start(&pmd->perf_stats, &timer);
4452
4453
0
    pmd->ctx.last_rxq = rxq;
4454
0
    dp_packet_batch_init(&batch);
4455
4456
    /* Fetch the rx queue length only for vhostuser ports. */
4457
0
    if (pmd_perf_metrics_enabled(pmd) && rxq->is_vhost) {
4458
0
        qlen_p = &rem_qlen;
4459
0
    }
4460
4461
0
    error = netdev_rxq_recv(rxq->rx, &batch, qlen_p);
4462
0
    if (!error) {
4463
        /* At least one packet received. */
4464
0
        *recirc_depth_get() = 0;
4465
0
        pmd_thread_ctx_time_update(pmd);
4466
0
        batch_cnt = dp_packet_batch_size(&batch);
4467
0
        if (pmd_perf_metrics_enabled(pmd)) {
4468
            /* Update batch histogram. */
4469
0
            s->current.batches++;
4470
0
            histogram_add_sample(&s->pkts_per_batch, batch_cnt);
4471
            /* Update the maximum vhost rx queue fill level. */
4472
0
            if (rxq->is_vhost && rem_qlen >= 0) {
4473
0
                uint32_t qfill = batch_cnt + rem_qlen;
4474
0
                if (qfill > s->current.max_vhost_qfill) {
4475
0
                    s->current.max_vhost_qfill = qfill;
4476
0
                }
4477
0
            }
4478
0
        }
4479
4480
        /* Process packet batch. */
4481
0
        dp_netdev_input(pmd, &batch, port_no);
4482
4483
        /* Assign processing cycles to rx queue. */
4484
0
        cycles = cycle_timer_stop(&pmd->perf_stats, &timer);
4485
0
        dp_netdev_rxq_add_cycles(rxq, RXQ_CYCLES_PROC_CURR, cycles);
4486
4487
0
        dp_netdev_pmd_flush_output_packets(pmd, false);
4488
0
    } else {
4489
        /* Discard cycles. */
4490
0
        cycle_timer_stop(&pmd->perf_stats, &timer);
4491
0
        if (error != EAGAIN && error != EOPNOTSUPP) {
4492
0
            static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
4493
4494
0
            VLOG_ERR_RL(&rl, "error receiving data from %s: %s",
4495
0
                    netdev_rxq_get_name(rxq->rx), ovs_strerror(error));
4496
0
        }
4497
0
    }
4498
4499
0
    dp_packet_batch_destroy(&batch);
4500
4501
0
    pmd->ctx.last_rxq = NULL;
4502
4503
0
    return batch_cnt;
4504
0
}
4505
4506
static struct tx_port *
4507
tx_port_lookup(const struct hmap *hmap, odp_port_t port_no)
4508
0
{
4509
0
    struct tx_port *tx;
4510
4511
0
    HMAP_FOR_EACH_IN_BUCKET (tx, node, hash_port_no(port_no), hmap) {
4512
0
        if (tx->port->port_no == port_no) {
4513
0
            return tx;
4514
0
        }
4515
0
    }
4516
4517
0
    return NULL;
4518
0
}
4519
4520
static struct tx_port *
4521
tx_port_create(struct dp_netdev_port *port)
4522
0
{
4523
0
    struct tx_port *tx = xzalloc(sizeof *tx);
4524
4525
0
    tx->port = port;
4526
0
    tx->qid = -1;
4527
0
    tx->flush_time = 0LL;
4528
0
    dp_packet_batch_init(&tx->output_pkts);
4529
0
    tx->output_pkts_rxqs = xcalloc(dp_packet_batch_capacity(&tx->output_pkts),
4530
0
                                   sizeof *tx->output_pkts_rxqs);
4531
4532
0
    if (tx->port->txq_mode == TXQ_MODE_XPS_HASH) {
4533
0
        int n_txq = netdev_n_txq(tx->port->netdev);
4534
4535
0
        tx->txq_pkts = xzalloc(n_txq * sizeof *tx->txq_pkts);
4536
0
        for (int i = 0; i < n_txq; i++) {
4537
0
            dp_packet_batch_init(&tx->txq_pkts[i]);
4538
0
        }
4539
0
    }
4540
4541
0
    return tx;
4542
0
}
4543
4544
static struct tx_port *
4545
tx_port_clone(const struct tx_port *tx_port)
4546
0
{
4547
0
    struct tx_port *clone = tx_port_create(tx_port->port);
4548
4549
0
    clone->qid = tx_port->qid;
4550
0
    return clone;
4551
0
}
4552
4553
static void
4554
tx_port_destroy(struct tx_port *tx)
4555
0
{
4556
0
    if (tx->txq_pkts) {
4557
0
        int n_txq = netdev_n_txq(tx->port->netdev);
4558
4559
0
        for (int i = 0; i < n_txq; i++) {
4560
0
            dp_packet_batch_destroy(&tx->txq_pkts[i]);
4561
0
        }
4562
0
    }
4563
0
    free(tx->txq_pkts);
4564
0
    dp_packet_batch_destroy(&tx->output_pkts);
4565
0
    free(tx->output_pkts_rxqs);
4566
0
    free(tx);
4567
0
}
4568
4569
static struct tx_bond *
4570
tx_bond_lookup(const struct cmap *tx_bonds, uint32_t bond_id)
4571
0
{
4572
0
    uint32_t hash = hash_bond_id(bond_id);
4573
0
    struct tx_bond *tx;
4574
4575
0
    CMAP_FOR_EACH_WITH_HASH (tx, node, hash, tx_bonds) {
4576
0
        if (tx->bond_id == bond_id) {
4577
0
            return tx;
4578
0
        }
4579
0
    }
4580
0
    return NULL;
4581
0
}
4582
4583
static int
4584
port_reconfigure(struct dp_netdev_port *port)
4585
0
{
4586
0
    struct netdev *netdev = port->netdev;
4587
0
    int i, err;
4588
4589
    /* Closes the existing 'rxq's. */
4590
0
    for (i = 0; i < port->n_rxq; i++) {
4591
0
        netdev_rxq_close(port->rxqs[i].rx);
4592
0
        port->rxqs[i].rx = NULL;
4593
0
    }
4594
0
    unsigned last_nrxq = port->n_rxq;
4595
0
    port->n_rxq = 0;
4596
4597
    /* Allows 'netdev' to apply the pending configuration changes. */
4598
0
    if (netdev_is_reconf_required(netdev) || port->need_reconfigure) {
4599
0
        err = netdev_reconfigure(netdev);
4600
0
        if (err && (err != EOPNOTSUPP)) {
4601
0
            VLOG_ERR("Failed to set interface %s new configuration",
4602
0
                     netdev_get_name(netdev));
4603
0
            return err;
4604
0
        }
4605
0
    }
4606
    /* If the netdev_reconfigure() above succeeds, reopens the 'rxq's. */
4607
0
    port->rxqs = xrealloc(port->rxqs,
4608
0
                          sizeof *port->rxqs * netdev_n_rxq(netdev));
4609
    /* Realloc 'used' counters for tx queues. */
4610
0
    free(port->txq_used);
4611
0
    port->txq_used = xcalloc(netdev_n_txq(netdev), sizeof *port->txq_used);
4612
4613
0
    for (i = 0; i < netdev_n_rxq(netdev); i++) {
4614
0
        bool new_queue = i >= last_nrxq;
4615
0
        if (new_queue) {
4616
0
            memset(&port->rxqs[i], 0, sizeof port->rxqs[i]);
4617
0
        }
4618
4619
0
        port->rxqs[i].port = port;
4620
0
        port->rxqs[i].is_vhost = !strncmp(port->type, "dpdkvhost", 9);
4621
4622
0
        err = netdev_rxq_open(netdev, &port->rxqs[i].rx, i);
4623
0
        if (err) {
4624
0
            return err;
4625
0
        }
4626
0
        port->n_rxq++;
4627
0
    }
4628
4629
    /* Parse affinity list to apply configuration for new queues. */
4630
0
    dpif_netdev_port_set_rxq_affinity(port, port->rxq_affinity_list);
4631
4632
    /* If reconfiguration was successful mark it as such, so we can use it */
4633
0
    port->need_reconfigure = false;
4634
4635
0
    return 0;
4636
0
}
4637
4638
struct sched_numa_list {
4639
    struct hmap numas;  /* Contains 'struct sched_numa'. */
4640
};
4641
4642
/* Meta data for out-of-place pmd rxq assignments. */
4643
struct sched_pmd {
4644
    struct sched_numa *numa;
4645
    /* Associated PMD thread. */
4646
    struct dp_netdev_pmd_thread *pmd;
4647
    uint64_t pmd_proc_cycles;
4648
    struct dp_netdev_rxq **rxqs;
4649
    unsigned n_rxq;
4650
    bool isolated;
4651
};
4652
4653
struct sched_numa {
4654
    struct hmap_node node;
4655
    int numa_id;
4656
    /* PMDs on numa node. */
4657
    struct sched_pmd *pmds;
4658
    /* Num of PMDs on numa node. */
4659
    unsigned n_pmds;
4660
    /* Num of isolated PMDs on numa node. */
4661
    unsigned n_isolated;
4662
    int rr_cur_index;
4663
    bool rr_idx_inc;
4664
};
4665
4666
static size_t
4667
sched_numa_list_count(struct sched_numa_list *numa_list)
4668
0
{
4669
0
    return hmap_count(&numa_list->numas);
4670
0
}
4671
4672
static struct sched_numa *
4673
sched_numa_list_next(struct sched_numa_list *numa_list,
4674
                     const struct sched_numa *numa)
4675
0
{
4676
0
    struct hmap_node *node = NULL;
4677
4678
0
    if (numa) {
4679
0
        node = hmap_next(&numa_list->numas, &numa->node);
4680
0
    }
4681
0
    if (!node) {
4682
0
        node = hmap_first(&numa_list->numas);
4683
0
    }
4684
4685
0
    return (node) ? CONTAINER_OF(node, struct sched_numa, node) : NULL;
4686
0
}
4687
4688
static struct sched_numa *
4689
sched_numa_list_lookup(struct sched_numa_list *numa_list, int numa_id)
4690
0
{
4691
0
    struct sched_numa *numa;
4692
4693
0
    HMAP_FOR_EACH_WITH_HASH (numa, node, hash_int(numa_id, 0),
4694
0
                             &numa_list->numas) {
4695
0
        if (numa->numa_id == numa_id) {
4696
0
            return numa;
4697
0
        }
4698
0
    }
4699
0
    return NULL;
4700
0
}
4701
4702
static int
4703
compare_sched_pmd_list(const void *a_, const void *b_)
4704
0
{
4705
0
    struct sched_pmd *a, *b;
4706
4707
0
    a = (struct sched_pmd *) a_;
4708
0
    b = (struct sched_pmd *) b_;
4709
4710
0
    return compare_poll_thread_list(&a->pmd, &b->pmd);
4711
0
}
4712
4713
static void
4714
sort_numa_list_pmds(struct sched_numa_list *numa_list)
4715
0
{
4716
0
    struct sched_numa *numa;
4717
4718
0
    HMAP_FOR_EACH (numa, node, &numa_list->numas) {
4719
0
        if (numa->n_pmds > 1) {
4720
0
            qsort(numa->pmds, numa->n_pmds, sizeof *numa->pmds,
4721
0
                  compare_sched_pmd_list);
4722
0
        }
4723
0
    }
4724
0
}
4725
4726
/* Populate numas and pmds on those numas. */
4727
static void
4728
sched_numa_list_populate(struct sched_numa_list *numa_list,
4729
                         struct dp_netdev *dp)
4730
0
{
4731
0
    struct dp_netdev_pmd_thread *pmd;
4732
4733
0
    hmap_init(&numa_list->numas);
4734
4735
    /* For each pmd on this datapath. */
4736
0
    CMAP_FOR_EACH (pmd, node, &dp->poll_threads) {
4737
0
        struct sched_numa *numa;
4738
0
        struct sched_pmd *sched_pmd;
4739
0
        if (pmd->core_id == NON_PMD_CORE_ID) {
4740
0
            continue;
4741
0
        }
4742
4743
        /* Get the numa of the PMD. */
4744
0
        numa = sched_numa_list_lookup(numa_list, pmd->numa_id);
4745
        /* Create a new numa node for it if not already created. */
4746
0
        if (!numa) {
4747
0
            numa = xzalloc(sizeof *numa);
4748
0
            numa->numa_id = pmd->numa_id;
4749
0
            hmap_insert(&numa_list->numas, &numa->node,
4750
0
                        hash_int(pmd->numa_id, 0));
4751
0
        }
4752
4753
        /* Create a sched_pmd on this numa for the pmd. */
4754
0
        numa->n_pmds++;
4755
0
        numa->pmds = xrealloc(numa->pmds, numa->n_pmds * sizeof *numa->pmds);
4756
0
        sched_pmd = &numa->pmds[numa->n_pmds - 1];
4757
0
        memset(sched_pmd, 0, sizeof *sched_pmd);
4758
0
        sched_pmd->numa = numa;
4759
0
        sched_pmd->pmd = pmd;
4760
        /* At least one pmd is present so initialize curr_idx and idx_inc. */
4761
0
        numa->rr_cur_index = 0;
4762
0
        numa->rr_idx_inc = true;
4763
0
    }
4764
0
    sort_numa_list_pmds(numa_list);
4765
0
}
4766
4767
static void
4768
sched_numa_list_free_entries(struct sched_numa_list *numa_list)
4769
0
{
4770
0
    struct sched_numa *numa;
4771
4772
0
    HMAP_FOR_EACH_POP (numa, node, &numa_list->numas) {
4773
0
        for (unsigned i = 0; i < numa->n_pmds; i++) {
4774
0
            struct sched_pmd *sched_pmd;
4775
4776
0
            sched_pmd = &numa->pmds[i];
4777
0
            sched_pmd->n_rxq = 0;
4778
0
            free(sched_pmd->rxqs);
4779
0
        }
4780
0
        numa->n_pmds = 0;
4781
0
        free(numa->pmds);
4782
0
        free(numa);
4783
0
    }
4784
0
    hmap_destroy(&numa_list->numas);
4785
0
}
4786
4787
static struct sched_pmd *
4788
sched_pmd_find_by_pmd(struct sched_numa_list *numa_list,
4789
                      struct dp_netdev_pmd_thread *pmd)
4790
0
{
4791
0
    struct sched_numa *numa;
4792
4793
0
    HMAP_FOR_EACH (numa, node, &numa_list->numas) {
4794
0
        for (unsigned i = 0; i < numa->n_pmds; i++) {
4795
0
            struct sched_pmd *sched_pmd;
4796
4797
0
            sched_pmd = &numa->pmds[i];
4798
0
            if (pmd == sched_pmd->pmd) {
4799
0
                return sched_pmd;
4800
0
            }
4801
0
        }
4802
0
    }
4803
0
    return NULL;
4804
0
}
4805
4806
static void
4807
sched_pmd_add_rxq(struct sched_pmd *sched_pmd, struct dp_netdev_rxq *rxq,
4808
                  uint64_t cycles)
4809
0
{
4810
    /* As sched_pmd is allocated outside this fn. better to not assume
4811
     * rxqs is initialized to NULL. */
4812
0
    if (sched_pmd->n_rxq == 0) {
4813
0
        sched_pmd->rxqs = xmalloc(sizeof *sched_pmd->rxqs);
4814
0
    } else {
4815
0
        sched_pmd->rxqs = xrealloc(sched_pmd->rxqs, (sched_pmd->n_rxq + 1) *
4816
0
                                                    sizeof *sched_pmd->rxqs);
4817
0
    }
4818
4819
0
    sched_pmd->rxqs[sched_pmd->n_rxq++] = rxq;
4820
0
    sched_pmd->pmd_proc_cycles += cycles;
4821
0
}
4822
4823
static void
4824
sched_numa_list_assignments(struct sched_numa_list *numa_list,
4825
                            struct dp_netdev *dp)
4826
    OVS_REQ_RDLOCK(dp->port_rwlock)
4827
0
{
4828
0
    struct dp_netdev_port *port;
4829
4830
    /* For each port. */
4831
0
    HMAP_FOR_EACH (port, node, &dp->ports) {
4832
0
        if (!netdev_is_pmd(port->netdev)) {
4833
0
            continue;
4834
0
        }
4835
        /* For each rxq on the port. */
4836
0
        for (unsigned qid = 0; qid < port->n_rxq; qid++) {
4837
0
            struct dp_netdev_rxq *rxq = &port->rxqs[qid];
4838
0
            struct sched_pmd *sched_pmd;
4839
0
            uint64_t proc_cycles = 0;
4840
4841
0
            for (int i = 0; i < PMD_INTERVAL_MAX; i++) {
4842
0
                proc_cycles  += dp_netdev_rxq_get_intrvl_cycles(rxq, i);
4843
0
            }
4844
4845
0
            sched_pmd = sched_pmd_find_by_pmd(numa_list, rxq->pmd);
4846
0
            if (sched_pmd) {
4847
0
                if (rxq->core_id != OVS_CORE_UNSPEC && dp->pmd_iso) {
4848
0
                    sched_pmd->isolated = true;
4849
0
                }
4850
0
                sched_pmd_add_rxq(sched_pmd, rxq, proc_cycles);
4851
0
            }
4852
0
        }
4853
0
    }
4854
0
}
4855
4856
static void
4857
sched_numa_list_put_in_place(struct sched_numa_list *numa_list)
4858
0
{
4859
0
    struct sched_numa *numa;
4860
4861
    /* For each numa. */
4862
0
    HMAP_FOR_EACH (numa, node, &numa_list->numas) {
4863
        /* For each pmd. */
4864
0
        for (int i = 0; i < numa->n_pmds; i++) {
4865
0
            struct sched_pmd *sched_pmd;
4866
4867
0
            sched_pmd = &numa->pmds[i];
4868
0
            sched_pmd->pmd->isolated = sched_pmd->isolated;
4869
            /* For each rxq. */
4870
0
            for (unsigned k = 0; k < sched_pmd->n_rxq; k++) {
4871
                /* Store the new pmd from the out of place sched_numa_list
4872
                 * struct to the dp_netdev_rxq struct */
4873
0
                sched_pmd->rxqs[k]->pmd = sched_pmd->pmd;
4874
0
            }
4875
0
        }
4876
0
    }
4877
0
}
4878
4879
/* Returns 'true' if OVS rxq scheduling algorithm assigned any unpinned rxq to
4880
 * a PMD thread core on a non-local numa node. */
4881
static bool
4882
sched_numa_list_cross_numa_polling(struct sched_numa_list *numa_list)
4883
0
{
4884
0
    struct sched_numa *numa;
4885
4886
0
    HMAP_FOR_EACH (numa, node, &numa_list->numas) {
4887
0
        for (int i = 0; i < numa->n_pmds; i++) {
4888
0
            struct sched_pmd *sched_pmd;
4889
4890
0
            sched_pmd = &numa->pmds[i];
4891
0
            if (sched_pmd->isolated) {
4892
                /* All rxqs on this PMD thread core are pinned. */
4893
0
                continue;
4894
0
            }
4895
0
            for (unsigned k = 0; k < sched_pmd->n_rxq; k++) {
4896
0
                struct dp_netdev_rxq *rxq = sched_pmd->rxqs[k];
4897
                /* Check if the rxq is not pinned to a specific PMD thread core
4898
                 * by the user AND the PMD thread core that OVS assigned is
4899
                 * non-local to the rxq port. */
4900
0
                if (rxq->core_id == OVS_CORE_UNSPEC &&
4901
0
                    rxq->pmd->numa_id !=
4902
0
                        netdev_get_numa_id(rxq->port->netdev)) {
4903
0
                    return true;
4904
0
                }
4905
0
            }
4906
0
        }
4907
0
    }
4908
0
    return false;
4909
0
}
4910
4911
static unsigned
4912
sched_numa_noniso_pmd_count(struct sched_numa *numa)
4913
0
{
4914
0
    if (numa->n_pmds > numa->n_isolated) {
4915
0
        return numa->n_pmds - numa->n_isolated;
4916
0
    }
4917
0
    return 0;
4918
0
}
4919
4920
/* Sort Rx Queues by the processing cycles they are consuming. */
4921
static int
4922
compare_rxq_cycles(const void *a, const void *b)
4923
0
{
4924
0
    struct dp_netdev_rxq *qa;
4925
0
    struct dp_netdev_rxq *qb;
4926
0
    uint64_t cycles_qa, cycles_qb;
4927
4928
0
    qa = *(struct dp_netdev_rxq **) a;
4929
0
    qb = *(struct dp_netdev_rxq **) b;
4930
4931
0
    cycles_qa = dp_netdev_rxq_get_cycles(qa, RXQ_CYCLES_PROC_HIST);
4932
0
    cycles_qb = dp_netdev_rxq_get_cycles(qb, RXQ_CYCLES_PROC_HIST);
4933
4934
0
    if (cycles_qa != cycles_qb) {
4935
0
        return (cycles_qa < cycles_qb) ? 1 : -1;
4936
0
    } else {
4937
        /* Cycles are the same so tiebreak on port/queue id.
4938
         * Tiebreaking (as opposed to return 0) ensures consistent
4939
         * sort results across multiple OS's. */
4940
0
        uint32_t port_qa = odp_to_u32(qa->port->port_no);
4941
0
        uint32_t port_qb = odp_to_u32(qb->port->port_no);
4942
0
        if (port_qa != port_qb) {
4943
0
            return port_qa > port_qb ? 1 : -1;
4944
0
        } else {
4945
0
            return netdev_rxq_get_queue_id(qa->rx)
4946
0
                    - netdev_rxq_get_queue_id(qb->rx);
4947
0
        }
4948
0
    }
4949
0
}
4950
4951
static bool
4952
sched_pmd_new_lowest(struct sched_pmd *current_lowest, struct sched_pmd *pmd,
4953
                     bool has_proc)
4954
0
{
4955
0
    uint64_t current_num, pmd_num;
4956
4957
0
    if (current_lowest == NULL) {
4958
0
        return true;
4959
0
    }
4960
4961
0
    if (has_proc) {
4962
0
        current_num = current_lowest->pmd_proc_cycles;
4963
0
        pmd_num = pmd->pmd_proc_cycles;
4964
0
    } else {
4965
0
        current_num = current_lowest->n_rxq;
4966
0
        pmd_num = pmd->n_rxq;
4967
0
    }
4968
4969
0
    if (pmd_num < current_num) {
4970
0
        return true;
4971
0
    }
4972
0
    return false;
4973
0
}
4974
4975
static struct sched_pmd *
4976
sched_pmd_get_lowest(struct sched_numa *numa, bool has_cyc)
4977
0
{
4978
0
    struct sched_pmd *lowest_sched_pmd = NULL;
4979
4980
0
    for (unsigned i = 0; i < numa->n_pmds; i++) {
4981
0
        struct sched_pmd *sched_pmd;
4982
4983
0
        sched_pmd = &numa->pmds[i];
4984
0
        if (sched_pmd->isolated) {
4985
0
            continue;
4986
0
        }
4987
0
        if (sched_pmd_new_lowest(lowest_sched_pmd, sched_pmd, has_cyc)) {
4988
0
            lowest_sched_pmd = sched_pmd;
4989
0
        }
4990
0
    }
4991
0
    return lowest_sched_pmd;
4992
0
}
4993
4994
/*
4995
 * Returns the next pmd from the numa node.
4996
 *
4997
 * If 'updown' is 'true' it will alternate between selecting the next pmd in
4998
 * either an up or down walk, switching between up/down when the first or last
4999
 * core is reached. e.g. 1,2,3,3,2,1,1,2...
5000
 *
5001
 * If 'updown' is 'false' it will select the next pmd wrapping around when
5002
 * last core reached. e.g. 1,2,3,1,2,3,1,2...
5003
 */
5004
static struct sched_pmd *
5005
sched_pmd_next_rr(struct sched_numa *numa, bool updown)
5006
0
{
5007
0
    int numa_idx = numa->rr_cur_index;
5008
5009
0
    if (numa->rr_idx_inc == true) {
5010
        /* Incrementing through list of pmds. */
5011
0
        if (numa->rr_cur_index == numa->n_pmds - 1) {
5012
            /* Reached the last pmd. */
5013
0
            if (updown) {
5014
0
                numa->rr_idx_inc = false;
5015
0
            } else {
5016
0
                numa->rr_cur_index = 0;
5017
0
            }
5018
0
        } else {
5019
0
            numa->rr_cur_index++;
5020
0
        }
5021
0
    } else {
5022
        /* Decrementing through list of pmds. */
5023
0
        if (numa->rr_cur_index == 0) {
5024
            /* Reached the first pmd. */
5025
0
            numa->rr_idx_inc = true;
5026
0
        } else {
5027
0
            numa->rr_cur_index--;
5028
0
        }
5029
0
    }
5030
0
    return &numa->pmds[numa_idx];
5031
0
}
5032
5033
static struct sched_pmd *
5034
sched_pmd_next_noniso_rr(struct sched_numa *numa, bool updown)
5035
0
{
5036
0
    struct sched_pmd *sched_pmd = NULL;
5037
5038
    /* sched_pmd_next_rr() may return duplicate PMDs before all PMDs have been
5039
     * returned depending on updown. Call it more than n_pmds to ensure all
5040
     * PMDs can be searched for the next non-isolated PMD. */
5041
0
    for (unsigned i = 0; i < numa->n_pmds * 2; i++) {
5042
0
        sched_pmd = sched_pmd_next_rr(numa, updown);
5043
0
        if (!sched_pmd->isolated) {
5044
0
            break;
5045
0
        }
5046
0
        sched_pmd = NULL;
5047
0
    }
5048
0
    return sched_pmd;
5049
0
}
5050
5051
static struct sched_pmd *
5052
sched_pmd_next(struct sched_numa *numa, enum sched_assignment_type algo,
5053
               bool has_proc)
5054
0
{
5055
0
    if (algo == SCHED_GROUP) {
5056
0
        return sched_pmd_get_lowest(numa, has_proc);
5057
0
    }
5058
5059
    /* By default RR the PMDs. */
5060
0
    return sched_pmd_next_noniso_rr(numa, algo == SCHED_CYCLES ? true : false);
5061
0
}
5062
5063
static const char *
5064
get_assignment_type_string(enum sched_assignment_type algo)
5065
0
{
5066
0
    switch (algo) {
5067
0
    case SCHED_ROUNDROBIN: return "roundrobin";
5068
0
    case SCHED_CYCLES: return "cycles";
5069
0
    case SCHED_GROUP: return "group";
5070
0
    default: return "Unknown";
5071
0
    }
5072
0
}
5073
5074
0
#define MAX_RXQ_CYC_TEXT 40
5075
0
#define MAX_RXQ_CYC_STRLEN (INT_STRLEN(uint64_t) + MAX_RXQ_CYC_TEXT)
5076
5077
static char *
5078
get_rxq_cyc_log(char *a, enum sched_assignment_type algo, uint64_t cycles)
5079
0
{
5080
0
    int ret = 0;
5081
5082
0
    if (algo != SCHED_ROUNDROBIN) {
5083
0
        ret = snprintf(a, MAX_RXQ_CYC_STRLEN,
5084
0
                       " (measured processing cycles %"PRIu64")", cycles);
5085
0
    }
5086
5087
0
    if (algo == SCHED_ROUNDROBIN || ret <= 0) {
5088
0
        a[0] = '\0';
5089
0
    }
5090
0
    return a;
5091
0
}
5092
5093
static void
5094
sched_numa_list_schedule(struct sched_numa_list *numa_list,
5095
                         struct dp_netdev *dp,
5096
                         enum sched_assignment_type algo,
5097
                         enum vlog_level level)
5098
    OVS_REQ_RDLOCK(dp->port_rwlock)
5099
0
{
5100
0
    struct dp_netdev_port *port;
5101
0
    struct dp_netdev_rxq **rxqs = NULL;
5102
0
    struct sched_numa *last_cross_numa;
5103
0
    unsigned n_rxqs = 0;
5104
0
    bool start_logged = false;
5105
0
    size_t n_numa;
5106
5107
    /* For each port. */
5108
0
    HMAP_FOR_EACH (port, node, &dp->ports) {
5109
0
        if (!netdev_is_pmd(port->netdev)) {
5110
0
            continue;
5111
0
        }
5112
5113
        /* For each rxq on the port. */
5114
0
        for (int qid = 0; qid < port->n_rxq; qid++) {
5115
0
            struct dp_netdev_rxq *rxq = &port->rxqs[qid];
5116
5117
0
            if (algo != SCHED_ROUNDROBIN) {
5118
0
                uint64_t cycle_hist = 0;
5119
5120
                /* Sum the queue intervals and store the cycle history. */
5121
0
                for (unsigned i = 0; i < PMD_INTERVAL_MAX; i++) {
5122
0
                    cycle_hist += dp_netdev_rxq_get_intrvl_cycles(rxq, i);
5123
0
                }
5124
0
                dp_netdev_rxq_set_cycles(rxq, RXQ_CYCLES_PROC_HIST,
5125
0
                                         cycle_hist);
5126
0
            }
5127
5128
            /* Check if this rxq is pinned. */
5129
0
            if (rxq->core_id != OVS_CORE_UNSPEC) {
5130
0
                struct sched_pmd *sched_pmd;
5131
0
                struct dp_netdev_pmd_thread *pmd;
5132
0
                struct sched_numa *numa;
5133
0
                bool iso = dp->pmd_iso;
5134
0
                uint64_t proc_cycles;
5135
0
                char rxq_cyc_log[MAX_RXQ_CYC_STRLEN];
5136
5137
                /* This rxq should be pinned, pin it now. */
5138
0
                pmd = dp_netdev_get_pmd(dp, rxq->core_id);
5139
0
                sched_pmd = sched_pmd_find_by_pmd(numa_list, pmd);
5140
0
                dp_netdev_pmd_unref(pmd);
5141
0
                if (!sched_pmd) {
5142
                    /* Cannot find the PMD.  Cannot pin this rxq. */
5143
0
                    VLOG(level == VLL_DBG ? VLL_DBG : VLL_WARN,
5144
0
                            "Core %2u cannot be pinned with "
5145
0
                            "port \'%s\' rx queue %d. Use pmd-cpu-mask to "
5146
0
                            "enable a pmd on core %u. An alternative core "
5147
0
                            "will be assigned.",
5148
0
                            rxq->core_id,
5149
0
                            netdev_rxq_get_name(rxq->rx),
5150
0
                            netdev_rxq_get_queue_id(rxq->rx),
5151
0
                            rxq->core_id);
5152
0
                    rxqs = xrealloc(rxqs, (n_rxqs + 1) * sizeof *rxqs);
5153
0
                    rxqs[n_rxqs++] = rxq;
5154
0
                    continue;
5155
0
                }
5156
0
                if (iso) {
5157
                    /* Mark PMD as isolated if not done already. */
5158
0
                    if (sched_pmd->isolated == false) {
5159
0
                        sched_pmd->isolated = true;
5160
0
                        numa = sched_pmd->numa;
5161
0
                        numa->n_isolated++;
5162
0
                    }
5163
0
                }
5164
0
                proc_cycles = dp_netdev_rxq_get_cycles(rxq,
5165
0
                                                       RXQ_CYCLES_PROC_HIST);
5166
0
                VLOG(level, "Core %2u on numa node %d is pinned with "
5167
0
                            "port \'%s\' rx queue %d%s",
5168
0
                            sched_pmd->pmd->core_id, sched_pmd->pmd->numa_id,
5169
0
                            netdev_rxq_get_name(rxq->rx),
5170
0
                            netdev_rxq_get_queue_id(rxq->rx),
5171
0
                            get_rxq_cyc_log(rxq_cyc_log, algo, proc_cycles));
5172
0
                sched_pmd_add_rxq(sched_pmd, rxq, proc_cycles);
5173
0
            } else {
5174
0
                rxqs = xrealloc(rxqs, (n_rxqs + 1) * sizeof *rxqs);
5175
0
                rxqs[n_rxqs++] = rxq;
5176
0
            }
5177
0
        }
5178
0
    }
5179
5180
0
    if (n_rxqs > 1 && algo != SCHED_ROUNDROBIN) {
5181
        /* Sort the queues in order of the processing cycles
5182
         * they consumed during their last pmd interval. */
5183
0
        qsort(rxqs, n_rxqs, sizeof *rxqs, compare_rxq_cycles);
5184
0
    }
5185
5186
0
    last_cross_numa = NULL;
5187
0
    n_numa = sched_numa_list_count(numa_list);
5188
0
    for (unsigned i = 0; i < n_rxqs; i++) {
5189
0
        struct dp_netdev_rxq *rxq = rxqs[i];
5190
0
        struct sched_pmd *sched_pmd = NULL;
5191
0
        struct sched_numa *numa;
5192
0
        int port_numa_id;
5193
0
        uint64_t proc_cycles;
5194
0
        char rxq_cyc_log[MAX_RXQ_CYC_STRLEN];
5195
5196
0
        if (start_logged == false && level != VLL_DBG) {
5197
0
            VLOG(level, "Performing pmd to rx queue assignment using %s "
5198
0
                        "algorithm.", get_assignment_type_string(algo));
5199
0
            start_logged = true;
5200
0
        }
5201
5202
        /* Store the cycles for this rxq as we will log these later. */
5203
0
        proc_cycles = dp_netdev_rxq_get_cycles(rxq, RXQ_CYCLES_PROC_HIST);
5204
5205
0
        port_numa_id = netdev_get_numa_id(rxq->port->netdev);
5206
5207
        /* Select numa. */
5208
0
        numa = sched_numa_list_lookup(numa_list, port_numa_id);
5209
5210
        /* Check if numa has no PMDs or no non-isolated PMDs. */
5211
0
        if (!numa || !sched_numa_noniso_pmd_count(numa)) {
5212
            /* Unable to use this numa to find a PMD. */
5213
0
            numa = NULL;
5214
            /* Find any numa with available PMDs. */
5215
0
            for (int j = 0; j < n_numa; j++) {
5216
0
                numa = sched_numa_list_next(numa_list, last_cross_numa);
5217
0
                last_cross_numa = numa;
5218
0
                if (sched_numa_noniso_pmd_count(numa)) {
5219
0
                    break;
5220
0
                }
5221
0
                numa = NULL;
5222
0
            }
5223
0
        }
5224
5225
0
        if (numa) {
5226
            /* Select the PMD that should be used for this rxq. */
5227
0
            sched_pmd = sched_pmd_next(numa, algo,
5228
0
                                       proc_cycles ? true : false);
5229
0
        }
5230
5231
        /* Check that a pmd has been selected. */
5232
0
        if (sched_pmd) {
5233
0
            int pmd_numa_id;
5234
5235
0
            pmd_numa_id = sched_pmd->numa->numa_id;
5236
            /* Check if selected pmd numa matches port numa. */
5237
0
            if (pmd_numa_id != port_numa_id) {
5238
0
                VLOG(level, "There's no available (non-isolated) pmd thread "
5239
0
                            "on numa node %d. Port \'%s\' rx queue %d will "
5240
0
                            "be assigned to a pmd on numa node %d. "
5241
0
                            "This may lead to reduced performance.",
5242
0
                            port_numa_id, netdev_rxq_get_name(rxq->rx),
5243
0
                            netdev_rxq_get_queue_id(rxq->rx), pmd_numa_id);
5244
0
            }
5245
0
            VLOG(level, "Core %2u on numa node %d assigned port \'%s\' "
5246
0
                        "rx queue %d%s.",
5247
0
                        sched_pmd->pmd->core_id, sched_pmd->pmd->numa_id,
5248
0
                        netdev_rxq_get_name(rxq->rx),
5249
0
                        netdev_rxq_get_queue_id(rxq->rx),
5250
0
                        get_rxq_cyc_log(rxq_cyc_log, algo, proc_cycles));
5251
0
            sched_pmd_add_rxq(sched_pmd, rxq, proc_cycles);
5252
0
        } else  {
5253
0
            VLOG(level == VLL_DBG ? level : VLL_WARN,
5254
0
                 "No non-isolated pmd on any numa available for "
5255
0
                 "port \'%s\' rx queue %d%s. "
5256
0
                 "This rx queue will not be polled.",
5257
0
                 netdev_rxq_get_name(rxq->rx),
5258
0
                 netdev_rxq_get_queue_id(rxq->rx),
5259
0
                 get_rxq_cyc_log(rxq_cyc_log, algo, proc_cycles));
5260
0
        }
5261
0
    }
5262
0
    free(rxqs);
5263
0
}
5264
5265
static void
5266
rxq_scheduling(struct dp_netdev *dp)
5267
    OVS_REQ_RDLOCK(dp->port_rwlock)
5268
0
{
5269
0
    struct sched_numa_list numa_list;
5270
0
    enum sched_assignment_type algo = dp->pmd_rxq_assign_type;
5271
5272
0
    sched_numa_list_populate(&numa_list, dp);
5273
0
    sched_numa_list_schedule(&numa_list, dp, algo, VLL_INFO);
5274
0
    sched_numa_list_put_in_place(&numa_list);
5275
5276
0
    sched_numa_list_free_entries(&numa_list);
5277
0
}
5278
5279
static uint64_t variance(uint64_t a[], int n);
5280
5281
static uint64_t
5282
sched_numa_variance(struct sched_numa *numa)
5283
0
{
5284
0
    uint64_t *percent_busy = NULL;
5285
0
    int n_proc = 0;
5286
0
    uint64_t var;
5287
5288
0
    percent_busy = xmalloc(numa->n_pmds * sizeof *percent_busy);
5289
5290
0
    for (unsigned i = 0; i < numa->n_pmds; i++) {
5291
0
        struct sched_pmd *sched_pmd;
5292
0
        uint64_t total_cycles = 0;
5293
5294
0
        sched_pmd = &numa->pmds[i];
5295
        /* Exclude isolated PMDs from variance calculations. */
5296
0
        if (sched_pmd->isolated == true) {
5297
0
            continue;
5298
0
        }
5299
        /* Get the total pmd cycles for an interval. */
5300
0
        atomic_read_relaxed(&sched_pmd->pmd->intrvl_cycles, &total_cycles);
5301
5302
0
        if (total_cycles) {
5303
            /* Estimate the cycles to cover all intervals. */
5304
0
            total_cycles *= PMD_INTERVAL_MAX;
5305
0
            percent_busy[n_proc++] = (sched_pmd->pmd_proc_cycles * 100)
5306
0
                                            / total_cycles;
5307
0
        } else {
5308
0
            percent_busy[n_proc++] = 0;
5309
0
        }
5310
0
    }
5311
0
    var = variance(percent_busy, n_proc);
5312
0
    free(percent_busy);
5313
0
    return var;
5314
0
}
5315
5316
/*
5317
 * This function checks that some basic conditions needed for a rebalance to be
5318
 * effective are met. Such as Rxq scheduling assignment type, more than one
5319
 * PMD, more than 2 Rxqs on a PMD. If there was no reconfiguration change
5320
 * since the last check, it reuses the last result.
5321
 *
5322
 * It is not intended to be an inclusive check of every condition that may make
5323
 * a rebalance ineffective. It is done as a quick check so a full
5324
 * pmd_rebalance_dry_run() can be avoided when it is not needed.
5325
 */
5326
static bool
5327
pmd_rebalance_dry_run_needed(struct dp_netdev *dp)
5328
    OVS_REQ_RDLOCK(dp->port_rwlock)
5329
0
{
5330
0
    struct dp_netdev_pmd_thread *pmd;
5331
0
    struct pmd_auto_lb *pmd_alb = &dp->pmd_alb;
5332
0
    unsigned int cnt = 0;
5333
0
    bool multi_rxq = false;
5334
5335
    /* Check if there was no reconfiguration since last check. */
5336
0
    if (!pmd_alb->recheck_config) {
5337
0
        if (!pmd_alb->do_dry_run) {
5338
0
            VLOG_DBG("PMD auto load balance nothing to do, "
5339
0
                     "no configuration changes since last check.");
5340
0
            return false;
5341
0
        }
5342
0
        return true;
5343
0
    }
5344
0
    pmd_alb->recheck_config = false;
5345
5346
    /* Check for incompatible assignment type. */
5347
0
    if (dp->pmd_rxq_assign_type == SCHED_ROUNDROBIN) {
5348
0
        VLOG_DBG("PMD auto load balance nothing to do, "
5349
0
                 "pmd-rxq-assign=roundrobin assignment type configured.");
5350
0
        return pmd_alb->do_dry_run = false;
5351
0
    }
5352
5353
    /* Check that there is at least 2 non-isolated PMDs and
5354
     * one of them is polling more than one rxq. */
5355
0
    CMAP_FOR_EACH (pmd, node, &dp->poll_threads) {
5356
0
        if (pmd->core_id == NON_PMD_CORE_ID || pmd->isolated) {
5357
0
            continue;
5358
0
        }
5359
5360
0
        if (hmap_count(&pmd->poll_list) > 1) {
5361
0
            multi_rxq = true;
5362
0
        }
5363
0
        if (cnt && multi_rxq) {
5364
0
            return pmd_alb->do_dry_run = true;
5365
0
        }
5366
0
        cnt++;
5367
0
    }
5368
5369
0
    VLOG_DBG("PMD auto load balance nothing to do, "
5370
0
             "not enough non-isolated PMDs or RxQs.");
5371
0
    return pmd_alb->do_dry_run = false;
5372
0
}
5373
5374
static bool
5375
pmd_rebalance_dry_run(struct dp_netdev *dp)
5376
    OVS_REQ_RDLOCK(dp->port_rwlock)
5377
0
{
5378
0
    struct sched_numa_list numa_list_cur;
5379
0
    struct sched_numa_list numa_list_est;
5380
0
    bool thresh_met = false;
5381
5382
0
    VLOG_DBG("PMD auto load balance performing dry run.");
5383
5384
    /* Populate current assignments. */
5385
0
    sched_numa_list_populate(&numa_list_cur, dp);
5386
0
    sched_numa_list_assignments(&numa_list_cur, dp);
5387
5388
    /* Populate estimated assignments. */
5389
0
    sched_numa_list_populate(&numa_list_est, dp);
5390
0
    sched_numa_list_schedule(&numa_list_est, dp,
5391
0
                             dp->pmd_rxq_assign_type, VLL_DBG);
5392
5393
    /* Check if cross-numa polling, there is only one numa with PMDs. */
5394
0
    if (!sched_numa_list_cross_numa_polling(&numa_list_est) ||
5395
0
            sched_numa_list_count(&numa_list_est) == 1) {
5396
0
        struct sched_numa *numa_cur;
5397
5398
        /* Calculate variances. */
5399
0
        HMAP_FOR_EACH (numa_cur, node, &numa_list_cur.numas) {
5400
0
            uint64_t current_var, estimate_var;
5401
0
            struct sched_numa *numa_est;
5402
0
            uint64_t improvement = 0;
5403
5404
0
            numa_est = sched_numa_list_lookup(&numa_list_est,
5405
0
                                              numa_cur->numa_id);
5406
0
            if (!numa_est) {
5407
0
                continue;
5408
0
            }
5409
0
            current_var = sched_numa_variance(numa_cur);
5410
0
            estimate_var = sched_numa_variance(numa_est);
5411
0
            if (estimate_var < current_var) {
5412
0
                improvement = ((current_var - estimate_var) * 100)
5413
0
                              / current_var;
5414
0
            }
5415
0
            VLOG_DBG("Numa node %d. Current variance %"PRIu64" Estimated "
5416
0
                     "variance %"PRIu64". Variance improvement %"PRIu64"%%.",
5417
0
                     numa_cur->numa_id, current_var,
5418
0
                     estimate_var, improvement);
5419
0
            if (improvement >= dp->pmd_alb.rebalance_improve_thresh) {
5420
0
                thresh_met = true;
5421
0
            }
5422
0
        }
5423
0
        VLOG_DBG("PMD load variance improvement threshold %u%% is %s.",
5424
0
                 dp->pmd_alb.rebalance_improve_thresh,
5425
0
                 thresh_met ? "met" : "not met");
5426
0
    } else {
5427
0
        VLOG_DBG("PMD auto load balance detected cross-numa polling with "
5428
0
                 "multiple numa nodes. Unable to accurately estimate.");
5429
0
    }
5430
5431
0
    sched_numa_list_free_entries(&numa_list_cur);
5432
0
    sched_numa_list_free_entries(&numa_list_est);
5433
5434
0
    return thresh_met;
5435
0
}
5436
5437
static void
5438
reload_affected_pmds(struct dp_netdev *dp)
5439
0
{
5440
0
    struct dp_netdev_pmd_thread *pmd;
5441
5442
0
    CMAP_FOR_EACH (pmd, node, &dp->poll_threads) {
5443
0
        if (pmd->need_reload) {
5444
0
            dp_netdev_reload_pmd__(pmd);
5445
0
        }
5446
0
    }
5447
5448
0
    CMAP_FOR_EACH (pmd, node, &dp->poll_threads) {
5449
0
        if (pmd->need_reload) {
5450
0
            if (pmd->core_id != NON_PMD_CORE_ID) {
5451
0
                bool reload;
5452
5453
0
                do {
5454
0
                    atomic_read_explicit(&pmd->reload, &reload,
5455
0
                                         memory_order_acquire);
5456
0
                } while (reload);
5457
0
            }
5458
0
            pmd->need_reload = false;
5459
0
        }
5460
0
    }
5461
0
}
5462
5463
static void
5464
reconfigure_pmd_threads(struct dp_netdev *dp)
5465
    OVS_REQ_RDLOCK(dp->port_rwlock)
5466
0
{
5467
0
    struct dp_netdev_pmd_thread *pmd;
5468
0
    struct ovs_numa_dump *pmd_cores;
5469
0
    struct ovs_numa_info_core *core;
5470
0
    struct hmapx to_delete = HMAPX_INITIALIZER(&to_delete);
5471
0
    struct hmapx_node *node;
5472
0
    bool changed = false;
5473
0
    bool need_to_adjust_static_tx_qids = false;
5474
5475
    /* The pmd threads should be started only if there's a pmd port in the
5476
     * datapath.  If the user didn't provide any "pmd-cpu-mask", we start
5477
     * NR_PMD_THREADS per numa node. */
5478
0
    if (!has_pmd_port(dp)) {
5479
0
        pmd_cores = ovs_numa_dump_n_cores_per_numa(0);
5480
0
    } else if (dp->pmd_cmask && dp->pmd_cmask[0]) {
5481
0
        pmd_cores = ovs_numa_dump_cores_with_cmask(dp->pmd_cmask);
5482
0
    } else {
5483
0
        pmd_cores = ovs_numa_dump_n_cores_per_numa(NR_PMD_THREADS);
5484
0
    }
5485
5486
    /* We need to adjust 'static_tx_qid's only if we're reducing number of
5487
     * PMD threads. Otherwise, new threads will allocate all the freed ids. */
5488
0
    if (ovs_numa_dump_count(pmd_cores) < cmap_count(&dp->poll_threads) - 1) {
5489
        /* Adjustment is required to keep 'static_tx_qid's sequential and
5490
         * avoid possible issues, for example, imbalanced tx queue usage
5491
         * and unnecessary locking caused by remapping on netdev level. */
5492
0
        need_to_adjust_static_tx_qids = true;
5493
0
    }
5494
5495
    /* Check for unwanted pmd threads */
5496
0
    CMAP_FOR_EACH (pmd, node, &dp->poll_threads) {
5497
0
        if (pmd->core_id == NON_PMD_CORE_ID) {
5498
0
            continue;
5499
0
        }
5500
0
        if (!ovs_numa_dump_contains_core(pmd_cores, pmd->numa_id,
5501
0
                                                    pmd->core_id)) {
5502
0
            hmapx_add(&to_delete, pmd);
5503
0
        } else if (need_to_adjust_static_tx_qids) {
5504
0
            atomic_store_relaxed(&pmd->reload_tx_qid, true);
5505
0
            pmd->need_reload = true;
5506
0
        }
5507
0
    }
5508
5509
0
    HMAPX_FOR_EACH (node, &to_delete) {
5510
0
        pmd = (struct dp_netdev_pmd_thread *) node->data;
5511
0
        VLOG_INFO("PMD thread on numa_id: %d, core id: %2d destroyed.",
5512
0
                  pmd->numa_id, pmd->core_id);
5513
0
        dp_netdev_del_pmd(dp, pmd);
5514
0
    }
5515
0
    changed = !hmapx_is_empty(&to_delete);
5516
0
    hmapx_destroy(&to_delete);
5517
5518
0
    if (need_to_adjust_static_tx_qids) {
5519
        /* 'static_tx_qid's are not sequential now.
5520
         * Reload remaining threads to fix this. */
5521
0
        reload_affected_pmds(dp);
5522
0
    }
5523
5524
    /* Check for required new pmd threads */
5525
0
    FOR_EACH_CORE_ON_DUMP(core, pmd_cores) {
5526
0
        pmd = dp_netdev_get_pmd(dp, core->core_id);
5527
0
        if (!pmd) {
5528
0
            struct ds name = DS_EMPTY_INITIALIZER;
5529
5530
0
            pmd = xzalloc(sizeof *pmd);
5531
0
            dp_netdev_configure_pmd(pmd, dp, core->core_id, core->numa_id);
5532
5533
0
            ds_put_format(&name, "pmd-c%02d/id:", core->core_id);
5534
0
            pmd->thread = ovs_thread_create(ds_cstr(&name),
5535
0
                                            pmd_thread_main, pmd);
5536
0
            ds_destroy(&name);
5537
5538
0
            VLOG_INFO("PMD thread on numa_id: %d, core id: %2d created.",
5539
0
                      pmd->numa_id, pmd->core_id);
5540
0
            changed = true;
5541
0
        } else {
5542
0
            dp_netdev_pmd_unref(pmd);
5543
0
        }
5544
0
    }
5545
5546
0
    if (changed) {
5547
0
        struct ovs_numa_info_numa *numa;
5548
5549
        /* Log the number of pmd threads per numa node. */
5550
0
        FOR_EACH_NUMA_ON_DUMP (numa, pmd_cores) {
5551
0
            VLOG_INFO("There are %"PRIuSIZE" pmd threads on numa node %d",
5552
0
                      numa->n_cores, numa->numa_id);
5553
0
        }
5554
0
    }
5555
5556
0
    ovs_numa_dump_destroy(pmd_cores);
5557
0
}
5558
5559
static void
5560
pmd_remove_stale_ports(struct dp_netdev *dp,
5561
                       struct dp_netdev_pmd_thread *pmd)
5562
    OVS_EXCLUDED(pmd->port_mutex)
5563
    OVS_REQ_RDLOCK(dp->port_rwlock)
5564
0
{
5565
0
    struct rxq_poll *poll;
5566
0
    struct tx_port *tx;
5567
5568
0
    ovs_mutex_lock(&pmd->port_mutex);
5569
0
    HMAP_FOR_EACH_SAFE (poll, node, &pmd->poll_list) {
5570
0
        struct dp_netdev_port *port = poll->rxq->port;
5571
5572
0
        if (port->need_reconfigure
5573
0
            || !hmap_contains(&dp->ports, &port->node)) {
5574
0
            dp_netdev_del_rxq_from_pmd(pmd, poll);
5575
0
        }
5576
0
    }
5577
0
    HMAP_FOR_EACH_SAFE (tx, node, &pmd->tx_ports) {
5578
0
        struct dp_netdev_port *port = tx->port;
5579
5580
0
        if (port->need_reconfigure
5581
0
            || !hmap_contains(&dp->ports, &port->node)) {
5582
0
            dp_netdev_del_port_tx_from_pmd(pmd, tx);
5583
0
        }
5584
0
    }
5585
0
    ovs_mutex_unlock(&pmd->port_mutex);
5586
0
}
5587
5588
/* Must be called each time a port is added/removed or the cmask changes.
5589
 * This creates and destroys pmd threads, reconfigures ports, opens their
5590
 * rxqs and assigns all rxqs/txqs to pmd threads. */
5591
static void
5592
reconfigure_datapath(struct dp_netdev *dp)
5593
    OVS_REQ_RDLOCK(dp->port_rwlock)
5594
0
{
5595
0
    struct hmapx busy_threads = HMAPX_INITIALIZER(&busy_threads);
5596
0
    struct dp_netdev_pmd_thread *pmd;
5597
0
    struct dp_netdev_port *port;
5598
0
    int wanted_txqs;
5599
5600
0
    dp->last_reconfigure_seq = seq_read(dp->reconfigure_seq);
5601
5602
    /* Step 1: Adjust the pmd threads based on the datapath ports, the cores
5603
     * on the system and the user configuration. */
5604
0
    reconfigure_pmd_threads(dp);
5605
5606
0
    wanted_txqs = cmap_count(&dp->poll_threads);
5607
5608
    /* The number of pmd threads might have changed, or a port can be new:
5609
     * adjust the txqs. */
5610
0
    HMAP_FOR_EACH (port, node, &dp->ports) {
5611
0
        netdev_set_tx_multiq(port->netdev, wanted_txqs);
5612
0
    }
5613
5614
    /* Step 2: Remove from the pmd threads ports that have been removed or
5615
     * need reconfiguration. */
5616
5617
    /* Check for all the ports that need reconfiguration.  We cache this in
5618
     * 'port->need_reconfigure', because netdev_is_reconf_required() can
5619
     * change at any time.
5620
     * Also mark for reconfiguration all ports which will likely change their
5621
     * 'txq_mode' parameter.  It's required to stop using them before
5622
     * changing this setting and it's simpler to mark ports here and allow
5623
     * 'pmd_remove_stale_ports' to remove them from threads.  There will be
5624
     * no actual reconfiguration in 'port_reconfigure' because it's
5625
     * unnecessary.  */
5626
0
    HMAP_FOR_EACH (port, node, &dp->ports) {
5627
0
        if (netdev_is_reconf_required(port->netdev)
5628
0
            || ((port->txq_mode == TXQ_MODE_XPS)
5629
0
                != (netdev_n_txq(port->netdev) < wanted_txqs))
5630
0
            || ((port->txq_mode == TXQ_MODE_XPS_HASH)
5631
0
                != (port->txq_requested_mode == TXQ_REQ_MODE_HASH
5632
0
                    && netdev_n_txq(port->netdev) > 1))) {
5633
0
            port->need_reconfigure = true;
5634
0
        }
5635
0
    }
5636
5637
    /* Remove from the pmd threads all the ports that have been deleted or
5638
     * need reconfiguration. */
5639
0
    CMAP_FOR_EACH (pmd, node, &dp->poll_threads) {
5640
0
        pmd_remove_stale_ports(dp, pmd);
5641
0
    }
5642
5643
    /* Reload affected pmd threads.  We must wait for the pmd threads before
5644
     * reconfiguring the ports, because a port cannot be reconfigured while
5645
     * it's being used. */
5646
0
    reload_affected_pmds(dp);
5647
5648
    /* Step 3: Reconfigure ports. */
5649
5650
    /* We only reconfigure the ports that we determined above, because they're
5651
     * not being used by any pmd thread at the moment.  If a port fails to
5652
     * reconfigure we remove it from the datapath. */
5653
0
    HMAP_FOR_EACH_SAFE (port, node, &dp->ports) {
5654
0
        int err;
5655
5656
0
        if (!port->need_reconfigure) {
5657
0
            continue;
5658
0
        }
5659
5660
0
        err = port_reconfigure(port);
5661
0
        if (err) {
5662
0
            hmap_remove(&dp->ports, &port->node);
5663
0
            seq_change(dp->port_seq);
5664
0
            port_destroy(port);
5665
0
        } else {
5666
            /* With a single queue, there is no point in using hash mode. */
5667
0
            if (port->txq_requested_mode == TXQ_REQ_MODE_HASH &&
5668
0
                netdev_n_txq(port->netdev) > 1) {
5669
0
                port->txq_mode = TXQ_MODE_XPS_HASH;
5670
0
            } else if (netdev_n_txq(port->netdev) < wanted_txqs) {
5671
0
                port->txq_mode = TXQ_MODE_XPS;
5672
0
            } else {
5673
0
                port->txq_mode = TXQ_MODE_STATIC;
5674
0
            }
5675
0
        }
5676
0
    }
5677
5678
    /* Step 4: Compute new rxq scheduling.  We don't touch the pmd threads
5679
     * for now, we just update the 'pmd' pointer in each rxq to point to the
5680
     * wanted thread according to the scheduling policy. */
5681
5682
    /* Reset all the pmd threads to non isolated. */
5683
0
    CMAP_FOR_EACH (pmd, node, &dp->poll_threads) {
5684
0
        pmd->isolated = false;
5685
0
    }
5686
5687
    /* Reset all the queues to unassigned */
5688
0
    HMAP_FOR_EACH (port, node, &dp->ports) {
5689
0
        for (int i = 0; i < port->n_rxq; i++) {
5690
0
            port->rxqs[i].pmd = NULL;
5691
0
        }
5692
0
    }
5693
0
    rxq_scheduling(dp);
5694
5695
    /* Step 5: Remove queues not compliant with new scheduling. */
5696
5697
    /* Count all the threads that will have at least one queue to poll. */
5698
0
    HMAP_FOR_EACH (port, node, &dp->ports) {
5699
0
        for (int qid = 0; qid < port->n_rxq; qid++) {
5700
0
            struct dp_netdev_rxq *q = &port->rxqs[qid];
5701
5702
0
            if (q->pmd) {
5703
0
                hmapx_add(&busy_threads, q->pmd);
5704
0
            }
5705
0
        }
5706
0
    }
5707
5708
0
    CMAP_FOR_EACH (pmd, node, &dp->poll_threads) {
5709
0
        struct rxq_poll *poll;
5710
5711
0
        ovs_mutex_lock(&pmd->port_mutex);
5712
0
        HMAP_FOR_EACH_SAFE (poll, node, &pmd->poll_list) {
5713
0
            if (poll->rxq->pmd != pmd) {
5714
0
                dp_netdev_del_rxq_from_pmd(pmd, poll);
5715
5716
                /* This pmd might sleep after this step if it has no rxq
5717
                 * remaining. Tell it to busy wait for new assignment if it
5718
                 * has at least one scheduled queue. */
5719
0
                if (hmap_count(&pmd->poll_list) == 0 &&
5720
0
                    hmapx_contains(&busy_threads, pmd)) {
5721
0
                    atomic_store_relaxed(&pmd->wait_for_reload, true);
5722
0
                }
5723
0
            }
5724
0
        }
5725
0
        ovs_mutex_unlock(&pmd->port_mutex);
5726
0
    }
5727
5728
0
    hmapx_destroy(&busy_threads);
5729
5730
    /* Reload affected pmd threads.  We must wait for the pmd threads to remove
5731
     * the old queues before readding them, otherwise a queue can be polled by
5732
     * two threads at the same time. */
5733
0
    reload_affected_pmds(dp);
5734
5735
    /* Step 6: Add queues from scheduling, if they're not there already. */
5736
0
    HMAP_FOR_EACH (port, node, &dp->ports) {
5737
0
        if (!netdev_is_pmd(port->netdev)) {
5738
0
            continue;
5739
0
        }
5740
5741
0
        for (int qid = 0; qid < port->n_rxq; qid++) {
5742
0
            struct dp_netdev_rxq *q = &port->rxqs[qid];
5743
5744
0
            if (q->pmd) {
5745
0
                ovs_mutex_lock(&q->pmd->port_mutex);
5746
0
                dp_netdev_add_rxq_to_pmd(q->pmd, q);
5747
0
                ovs_mutex_unlock(&q->pmd->port_mutex);
5748
0
            }
5749
0
        }
5750
0
    }
5751
5752
    /* Add every port and bond to the tx port and bond caches of
5753
     * every pmd thread, if it's not there already and if this pmd
5754
     * has at least one rxq to poll.
5755
     */
5756
0
    CMAP_FOR_EACH (pmd, node, &dp->poll_threads) {
5757
0
        ovs_mutex_lock(&pmd->port_mutex);
5758
0
        if (hmap_count(&pmd->poll_list) || pmd->core_id == NON_PMD_CORE_ID) {
5759
0
            struct tx_bond *bond;
5760
5761
0
            HMAP_FOR_EACH (port, node, &dp->ports) {
5762
0
                dp_netdev_add_port_tx_to_pmd(pmd, port);
5763
0
            }
5764
5765
0
            CMAP_FOR_EACH (bond, node, &dp->tx_bonds) {
5766
0
                dp_netdev_add_bond_tx_to_pmd(pmd, bond, false);
5767
0
            }
5768
0
        }
5769
0
        ovs_mutex_unlock(&pmd->port_mutex);
5770
0
    }
5771
5772
    /* Reload affected pmd threads. */
5773
0
    reload_affected_pmds(dp);
5774
5775
    /* PMD ALB will need to recheck if dry run needed. */
5776
0
    dp->pmd_alb.recheck_config = true;
5777
0
}
5778
5779
/* Returns true if one of the netdevs in 'dp' requires a reconfiguration */
5780
static bool
5781
ports_require_restart(const struct dp_netdev *dp)
5782
    OVS_REQ_RDLOCK(dp->port_rwlock)
5783
0
{
5784
0
    struct dp_netdev_port *port;
5785
5786
0
    HMAP_FOR_EACH (port, node, &dp->ports) {
5787
0
        if (netdev_is_reconf_required(port->netdev)) {
5788
0
            return true;
5789
0
        }
5790
0
    }
5791
5792
0
    return false;
5793
0
}
5794
5795
/* Calculates variance in the values stored in array 'a'. 'n' is the number
5796
 * of elements in array to be considered for calculating vairance.
5797
 * Usage example: data array 'a' contains the processing load of each pmd and
5798
 * 'n' is the number of PMDs. It returns the variance in processing load of
5799
 * PMDs*/
5800
static uint64_t
5801
variance(uint64_t a[], int n)
5802
0
{
5803
    /* Compute mean (average of elements). */
5804
0
    uint64_t sum = 0;
5805
0
    uint64_t mean = 0;
5806
0
    uint64_t sqDiff = 0;
5807
5808
0
    if (!n) {
5809
0
        return 0;
5810
0
    }
5811
5812
0
    for (int i = 0; i < n; i++) {
5813
0
        sum += a[i];
5814
0
    }
5815
5816
0
    if (sum) {
5817
0
        mean = sum / n;
5818
5819
        /* Compute sum squared differences with mean. */
5820
0
        for (int i = 0; i < n; i++) {
5821
0
            sqDiff += (a[i] - mean)*(a[i] - mean);
5822
0
        }
5823
0
    }
5824
0
    return (sqDiff ? (sqDiff / n) : 0);
5825
0
}
5826
5827
/* Return true if needs to revalidate datapath flows. */
5828
static bool
5829
dpif_netdev_run(struct dpif *dpif)
5830
0
{
5831
0
    struct dp_netdev_port *port;
5832
0
    struct dp_netdev *dp = get_dp_netdev(dpif);
5833
0
    struct dp_netdev_pmd_thread *non_pmd;
5834
0
    uint64_t new_tnl_seq;
5835
0
    bool need_to_flush = true;
5836
0
    bool pmd_rebalance = false;
5837
0
    long long int now = time_msec();
5838
0
    struct dp_netdev_pmd_thread *pmd;
5839
5840
0
    ovs_rwlock_rdlock(&dp->port_rwlock);
5841
0
    non_pmd = dp_netdev_get_pmd(dp, NON_PMD_CORE_ID);
5842
0
    if (non_pmd) {
5843
0
        ovs_mutex_lock(&dp->non_pmd_mutex);
5844
5845
0
        atomic_read_relaxed(&dp->smc_enable_db, &non_pmd->ctx.smc_enable_db);
5846
5847
0
        HMAP_FOR_EACH (port, node, &dp->ports) {
5848
0
            if (!netdev_is_pmd(port->netdev)) {
5849
0
                int i;
5850
5851
0
                if (port->emc_enabled) {
5852
0
                    atomic_read_relaxed(&dp->emc_insert_min,
5853
0
                                        &non_pmd->ctx.emc_insert_min);
5854
0
                } else {
5855
0
                    non_pmd->ctx.emc_insert_min = 0;
5856
0
                }
5857
5858
0
                for (i = 0; i < port->n_rxq; i++) {
5859
5860
0
                    if (!netdev_rxq_enabled(port->rxqs[i].rx)) {
5861
0
                        continue;
5862
0
                    }
5863
5864
0
                    if (dp_netdev_process_rxq_port(non_pmd,
5865
0
                                                   &port->rxqs[i],
5866
0
                                                   port->port_no)) {
5867
0
                        need_to_flush = false;
5868
0
                    }
5869
0
                }
5870
0
            }
5871
0
        }
5872
0
        if (need_to_flush) {
5873
            /* We didn't receive anything in the process loop.
5874
             * Check if we need to send something.
5875
             * There was no time updates on current iteration. */
5876
0
            pmd_thread_ctx_time_update(non_pmd);
5877
0
            dp_netdev_pmd_flush_output_packets(non_pmd, false);
5878
0
        }
5879
5880
0
        dpif_netdev_xps_revalidate_pmd(non_pmd, false);
5881
0
        ovs_mutex_unlock(&dp->non_pmd_mutex);
5882
5883
0
        dp_netdev_pmd_unref(non_pmd);
5884
0
    }
5885
5886
0
    struct pmd_auto_lb *pmd_alb = &dp->pmd_alb;
5887
0
    if (pmd_alb->is_enabled) {
5888
0
        if (!pmd_alb->rebalance_poll_timer) {
5889
0
            pmd_alb->rebalance_poll_timer = now;
5890
0
        } else if ((pmd_alb->rebalance_poll_timer +
5891
0
                   pmd_alb->rebalance_intvl) < now) {
5892
0
            pmd_alb->rebalance_poll_timer = now;
5893
0
            CMAP_FOR_EACH (pmd, node, &dp->poll_threads) {
5894
0
                if (atomic_count_get(&pmd->pmd_overloaded) >=
5895
0
                                    PMD_INTERVAL_MAX) {
5896
0
                    pmd_rebalance = true;
5897
0
                    break;
5898
0
                }
5899
0
            }
5900
5901
0
            if (pmd_rebalance &&
5902
0
                !dp_netdev_is_reconf_required(dp) &&
5903
0
                !ports_require_restart(dp) &&
5904
0
                pmd_rebalance_dry_run_needed(dp) &&
5905
0
                pmd_rebalance_dry_run(dp)) {
5906
0
                VLOG_INFO("PMD auto load balance dry run. "
5907
0
                          "Requesting datapath reconfigure.");
5908
0
                dp_netdev_request_reconfigure(dp);
5909
0
            }
5910
0
        }
5911
0
    }
5912
5913
0
    if (dp_netdev_is_reconf_required(dp) || ports_require_restart(dp)) {
5914
0
        reconfigure_datapath(dp);
5915
0
    }
5916
0
    ovs_rwlock_unlock(&dp->port_rwlock);
5917
5918
0
    tnl_neigh_cache_run();
5919
0
    tnl_port_map_run();
5920
0
    new_tnl_seq = seq_read(tnl_conf_seq);
5921
5922
0
    if (dp->last_tnl_conf_seq != new_tnl_seq) {
5923
0
        dp->last_tnl_conf_seq = new_tnl_seq;
5924
0
        return true;
5925
0
    }
5926
0
    return false;
5927
0
}
5928
5929
static void
5930
dpif_netdev_wait(struct dpif *dpif)
5931
0
{
5932
0
    struct dp_netdev_port *port;
5933
0
    struct dp_netdev *dp = get_dp_netdev(dpif);
5934
5935
0
    ovs_mutex_lock(&dp_netdev_mutex);
5936
0
    ovs_rwlock_rdlock(&dp->port_rwlock);
5937
0
    HMAP_FOR_EACH (port, node, &dp->ports) {
5938
0
        netdev_wait_reconf_required(port->netdev);
5939
0
        if (!netdev_is_pmd(port->netdev)) {
5940
0
            int i;
5941
5942
0
            for (i = 0; i < port->n_rxq; i++) {
5943
0
                netdev_rxq_wait(port->rxqs[i].rx);
5944
0
            }
5945
0
        }
5946
0
    }
5947
0
    ovs_rwlock_unlock(&dp->port_rwlock);
5948
0
    ovs_mutex_unlock(&dp_netdev_mutex);
5949
0
    seq_wait(tnl_conf_seq, dp->last_tnl_conf_seq);
5950
0
}
5951
5952
static void
5953
pmd_free_cached_ports(struct dp_netdev_pmd_thread *pmd)
5954
0
{
5955
0
    struct tx_port *tx_port_cached;
5956
5957
    /* Flush all the queued packets. */
5958
0
    dp_netdev_pmd_flush_output_packets(pmd, true);
5959
    /* Free all used tx queue ids. */
5960
0
    dpif_netdev_xps_revalidate_pmd(pmd, true);
5961
5962
0
    HMAP_FOR_EACH_POP (tx_port_cached, node, &pmd->tnl_port_cache) {
5963
0
        tx_port_destroy(tx_port_cached);
5964
0
    }
5965
0
    HMAP_FOR_EACH_POP (tx_port_cached, node, &pmd->send_port_cache) {
5966
0
        tx_port_destroy(tx_port_cached);
5967
0
    }
5968
0
}
5969
5970
/* Copies ports from 'pmd->tx_ports' (shared with the main thread) to
5971
 * thread-local copies. Copy to 'pmd->tnl_port_cache' if it is a tunnel
5972
 * device, otherwise to 'pmd->send_port_cache' if the port has at least
5973
 * one txq. */
5974
static void
5975
pmd_load_cached_ports(struct dp_netdev_pmd_thread *pmd)
5976
    OVS_REQUIRES(pmd->port_mutex)
5977
0
{
5978
0
    struct tx_port *tx_port, *tx_port_cached;
5979
5980
0
    pmd_free_cached_ports(pmd);
5981
0
    hmap_shrink(&pmd->send_port_cache);
5982
0
    hmap_shrink(&pmd->tnl_port_cache);
5983
5984
0
    HMAP_FOR_EACH (tx_port, node, &pmd->tx_ports) {
5985
0
        if (netdev_has_tunnel_push_pop(tx_port->port->netdev)) {
5986
0
            tx_port_cached = tx_port_clone(tx_port);
5987
0
            hmap_insert(&pmd->tnl_port_cache, &tx_port_cached->node,
5988
0
                        hash_port_no(tx_port_cached->port->port_no));
5989
0
        }
5990
5991
0
        if (netdev_n_txq(tx_port->port->netdev)) {
5992
0
            tx_port_cached = tx_port_clone(tx_port);
5993
0
            hmap_insert(&pmd->send_port_cache, &tx_port_cached->node,
5994
0
                        hash_port_no(tx_port_cached->port->port_no));
5995
0
        }
5996
0
    }
5997
0
}
5998
5999
static void
6000
pmd_alloc_static_tx_qid(struct dp_netdev_pmd_thread *pmd)
6001
0
{
6002
0
    ovs_mutex_lock(&pmd->dp->tx_qid_pool_mutex);
6003
0
    if (!id_pool_alloc_id(pmd->dp->tx_qid_pool, &pmd->static_tx_qid)) {
6004
0
        VLOG_ABORT("static_tx_qid allocation failed for PMD on core %2d"
6005
0
                   ", numa_id %d.", pmd->core_id, pmd->numa_id);
6006
0
    }
6007
0
    ovs_mutex_unlock(&pmd->dp->tx_qid_pool_mutex);
6008
6009
0
    VLOG_DBG("static_tx_qid = %d allocated for PMD thread on core %2d"
6010
0
             ", numa_id %d.", pmd->static_tx_qid, pmd->core_id, pmd->numa_id);
6011
0
}
6012
6013
static void
6014
pmd_free_static_tx_qid(struct dp_netdev_pmd_thread *pmd)
6015
0
{
6016
0
    ovs_mutex_lock(&pmd->dp->tx_qid_pool_mutex);
6017
0
    id_pool_free_id(pmd->dp->tx_qid_pool, pmd->static_tx_qid);
6018
0
    ovs_mutex_unlock(&pmd->dp->tx_qid_pool_mutex);
6019
0
}
6020
6021
static int
6022
pmd_load_queues_and_ports(struct dp_netdev_pmd_thread *pmd,
6023
                          struct polled_queue **ppoll_list)
6024
0
{
6025
0
    struct polled_queue *poll_list = *ppoll_list;
6026
0
    struct rxq_poll *poll;
6027
0
    int i;
6028
6029
0
    ovs_mutex_lock(&pmd->port_mutex);
6030
0
    poll_list = xrealloc(poll_list, hmap_count(&pmd->poll_list)
6031
0
                                    * sizeof *poll_list);
6032
6033
0
    i = 0;
6034
0
    HMAP_FOR_EACH (poll, node, &pmd->poll_list) {
6035
0
        poll_list[i].rxq = poll->rxq;
6036
0
        poll_list[i].port_no = poll->rxq->port->port_no;
6037
0
        poll_list[i].emc_enabled = poll->rxq->port->emc_enabled;
6038
0
        poll_list[i].rxq_enabled = netdev_rxq_enabled(poll->rxq->rx);
6039
0
        poll_list[i].change_seq =
6040
0
                     netdev_get_change_seq(poll->rxq->port->netdev);
6041
0
        i++;
6042
0
    }
6043
6044
0
    pmd_load_cached_ports(pmd);
6045
6046
0
    ovs_mutex_unlock(&pmd->port_mutex);
6047
6048
0
    *ppoll_list = poll_list;
6049
0
    return i;
6050
0
}
6051
6052
static void *
6053
pmd_thread_main(void *f_)
6054
0
{
6055
0
    struct dp_netdev_pmd_thread *pmd = f_;
6056
0
    struct pmd_perf_stats *s = &pmd->perf_stats;
6057
0
    unsigned int lc = 0;
6058
0
    struct polled_queue *poll_list;
6059
0
    bool wait_for_reload = false;
6060
0
    bool dpdk_attached;
6061
0
    bool reload_tx_qid;
6062
0
    bool exiting;
6063
0
    bool reload;
6064
0
    int poll_cnt;
6065
0
    int i;
6066
0
    int process_packets = 0;
6067
0
    uint64_t sleep_time = 0;
6068
6069
0
    poll_list = NULL;
6070
6071
    /* Stores the pmd thread's 'pmd' to 'per_pmd_key'. */
6072
0
    ovsthread_setspecific(pmd->dp->per_pmd_key, pmd);
6073
0
    ovs_numa_thread_setaffinity_core(pmd->core_id);
6074
0
    dpdk_attached = dpdk_attach_thread(pmd->core_id);
6075
0
    poll_cnt = pmd_load_queues_and_ports(pmd, &poll_list);
6076
0
    dfc_cache_init(&pmd->flow_cache);
6077
0
    pmd_alloc_static_tx_qid(pmd);
6078
0
    set_timer_resolution(PMD_TIMER_RES_NS);
6079
6080
0
reload:
6081
0
    atomic_count_init(&pmd->pmd_overloaded, 0);
6082
6083
0
    pmd->intrvl_tsc_prev = 0;
6084
0
    atomic_store_relaxed(&pmd->intrvl_cycles, 0);
6085
6086
0
    if (!dpdk_attached) {
6087
0
        dpdk_attached = dpdk_attach_thread(pmd->core_id);
6088
0
    }
6089
6090
    /* List port/core affinity */
6091
0
    for (i = 0; i < poll_cnt; i++) {
6092
0
       VLOG_DBG("Core %d processing port \'%s\' with queue-id %d\n",
6093
0
                pmd->core_id, netdev_rxq_get_name(poll_list[i].rxq->rx),
6094
0
                netdev_rxq_get_queue_id(poll_list[i].rxq->rx));
6095
       /* Reset the rxq current cycles counter. */
6096
0
       dp_netdev_rxq_set_cycles(poll_list[i].rxq, RXQ_CYCLES_PROC_CURR, 0);
6097
0
       for (int j = 0; j < PMD_INTERVAL_MAX; j++) {
6098
0
           dp_netdev_rxq_set_intrvl_cycles(poll_list[i].rxq, 0);
6099
0
       }
6100
0
    }
6101
6102
0
    if (!poll_cnt) {
6103
0
        if (wait_for_reload) {
6104
            /* Don't sleep, control thread will ask for a reload shortly. */
6105
0
            do {
6106
0
                atomic_read_explicit(&pmd->reload, &reload,
6107
0
                                     memory_order_acquire);
6108
0
            } while (!reload);
6109
0
        } else {
6110
0
            while (seq_read(pmd->reload_seq) == pmd->last_reload_seq) {
6111
0
                seq_wait(pmd->reload_seq, pmd->last_reload_seq);
6112
0
                poll_block();
6113
0
            }
6114
0
        }
6115
0
    }
6116
6117
0
    for (i = 0; i < PMD_INTERVAL_MAX; i++) {
6118
0
        atomic_store_relaxed(&pmd->busy_cycles_intrvl[i], 0);
6119
0
    }
6120
0
    atomic_count_set(&pmd->intrvl_idx, 0);
6121
0
    cycles_counter_update(s);
6122
6123
0
    pmd->next_rcu_quiesce = pmd->ctx.now + PMD_RCU_QUIESCE_INTERVAL;
6124
6125
    /* Protect pmd stats from external clearing while polling. */
6126
0
    ovs_mutex_lock(&pmd->perf_stats.stats_mutex);
6127
0
    for (;;) {
6128
0
        uint64_t rx_packets = 0, tx_packets = 0;
6129
0
        uint64_t time_slept = 0;
6130
0
        uint64_t max_sleep;
6131
6132
0
        pmd_perf_start_iteration(s);
6133
6134
0
        atomic_read_relaxed(&pmd->dp->smc_enable_db, &pmd->ctx.smc_enable_db);
6135
0
        atomic_read_relaxed(&pmd->max_sleep, &max_sleep);
6136
6137
0
        for (i = 0; i < poll_cnt; i++) {
6138
6139
0
            if (!poll_list[i].rxq_enabled) {
6140
0
                continue;
6141
0
            }
6142
6143
0
            if (poll_list[i].emc_enabled) {
6144
0
                atomic_read_relaxed(&pmd->dp->emc_insert_min,
6145
0
                                    &pmd->ctx.emc_insert_min);
6146
0
            } else {
6147
0
                pmd->ctx.emc_insert_min = 0;
6148
0
            }
6149
6150
0
            process_packets =
6151
0
                dp_netdev_process_rxq_port(pmd, poll_list[i].rxq,
6152
0
                                           poll_list[i].port_no);
6153
0
            rx_packets += process_packets;
6154
0
            if (process_packets >= PMD_SLEEP_THRESH) {
6155
0
                sleep_time = 0;
6156
0
            }
6157
0
        }
6158
6159
0
        if (!rx_packets) {
6160
            /* We didn't receive anything in the process loop.
6161
             * Check if we need to send something.
6162
             * There was no time updates on current iteration. */
6163
0
            pmd_thread_ctx_time_update(pmd);
6164
0
            tx_packets = dp_netdev_pmd_flush_output_packets(pmd,
6165
0
                                                   max_sleep && sleep_time
6166
0
                                                   ? true : false);
6167
0
        }
6168
6169
0
        if (max_sleep) {
6170
            /* Check if a sleep should happen on this iteration. */
6171
0
            if (sleep_time) {
6172
0
                struct cycle_timer sleep_timer;
6173
6174
0
                cycle_timer_start(&pmd->perf_stats, &sleep_timer);
6175
0
                xnanosleep_no_quiesce(sleep_time * 1000);
6176
0
                time_slept = cycle_timer_stop(&pmd->perf_stats, &sleep_timer);
6177
0
                pmd_thread_ctx_time_update(pmd);
6178
0
            }
6179
0
            if (sleep_time < max_sleep) {
6180
                /* Increase sleep time for next iteration. */
6181
0
                sleep_time += PMD_SLEEP_INC_US;
6182
0
            } else {
6183
0
                sleep_time = max_sleep;
6184
0
            }
6185
0
        } else {
6186
            /* Reset sleep time as max sleep policy may have been changed. */
6187
0
            sleep_time = 0;
6188
0
        }
6189
6190
        /* Do RCU synchronization at fixed interval.  This ensures that
6191
         * synchronization would not be delayed long even at high load of
6192
         * packet processing. */
6193
0
        if (pmd->ctx.now > pmd->next_rcu_quiesce) {
6194
0
            if (!ovsrcu_try_quiesce()) {
6195
0
                pmd->next_rcu_quiesce =
6196
0
                    pmd->ctx.now + PMD_RCU_QUIESCE_INTERVAL;
6197
0
            }
6198
0
        }
6199
6200
0
        if (lc++ > 1024) {
6201
0
            lc = 0;
6202
6203
0
            coverage_try_clear();
6204
0
            dp_netdev_pmd_try_optimize(pmd, poll_list, poll_cnt);
6205
0
            if (!ovsrcu_try_quiesce()) {
6206
0
                emc_cache_slow_sweep(&((pmd->flow_cache).emc_cache));
6207
0
                pmd->next_rcu_quiesce =
6208
0
                    pmd->ctx.now + PMD_RCU_QUIESCE_INTERVAL;
6209
0
            }
6210
6211
0
            for (i = 0; i < poll_cnt; i++) {
6212
0
                uint64_t current_seq =
6213
0
                         netdev_get_change_seq(poll_list[i].rxq->port->netdev);
6214
0
                if (poll_list[i].change_seq != current_seq) {
6215
0
                    poll_list[i].change_seq = current_seq;
6216
0
                    poll_list[i].rxq_enabled =
6217
0
                                 netdev_rxq_enabled(poll_list[i].rxq->rx);
6218
0
                }
6219
0
            }
6220
0
        }
6221
6222
0
        atomic_read_explicit(&pmd->reload, &reload, memory_order_acquire);
6223
0
        if (OVS_UNLIKELY(reload)) {
6224
0
            break;
6225
0
        }
6226
6227
0
        pmd_perf_end_iteration(s, rx_packets, tx_packets, time_slept,
6228
0
                               pmd_perf_metrics_enabled(pmd));
6229
0
    }
6230
0
    ovs_mutex_unlock(&pmd->perf_stats.stats_mutex);
6231
6232
0
    poll_cnt = pmd_load_queues_and_ports(pmd, &poll_list);
6233
0
    atomic_read_relaxed(&pmd->wait_for_reload, &wait_for_reload);
6234
0
    atomic_read_relaxed(&pmd->reload_tx_qid, &reload_tx_qid);
6235
0
    atomic_read_relaxed(&pmd->exit, &exiting);
6236
    /* Signal here to make sure the pmd finishes
6237
     * reloading the updated configuration. */
6238
0
    dp_netdev_pmd_reload_done(pmd);
6239
6240
0
    if (reload_tx_qid) {
6241
0
        pmd_free_static_tx_qid(pmd);
6242
0
        pmd_alloc_static_tx_qid(pmd);
6243
0
    }
6244
6245
0
    if (!exiting) {
6246
0
        goto reload;
6247
0
    }
6248
6249
0
    pmd_free_static_tx_qid(pmd);
6250
0
    dfc_cache_uninit(&pmd->flow_cache);
6251
0
    free(poll_list);
6252
0
    pmd_free_cached_ports(pmd);
6253
0
    if (dpdk_attached) {
6254
0
        dpdk_detach_thread();
6255
0
    }
6256
0
    return NULL;
6257
0
}
6258
6259
static void
6260
dp_netdev_disable_upcall(struct dp_netdev *dp)
6261
    OVS_ACQUIRES(dp->upcall_rwlock)
6262
0
{
6263
0
    fat_rwlock_wrlock(&dp->upcall_rwlock);
6264
0
}
6265
6266

6267
/* Meters */
6268
static void
6269
dpif_netdev_meter_get_features(const struct dpif * dpif OVS_UNUSED,
6270
                               struct ofputil_meter_features *features)
6271
0
{
6272
0
    features->max_meters = MAX_METERS;
6273
0
    features->band_types = DP_SUPPORTED_METER_BAND_TYPES;
6274
0
    features->capabilities = DP_SUPPORTED_METER_FLAGS_MASK;
6275
0
    features->max_bands = MAX_BANDS;
6276
0
    features->max_color = 0;
6277
0
}
6278
6279
/* Tries to atomically add 'n' to 'value' in terms of saturation arithmetic,
6280
 * i.e., if the result will be larger than 'max_value', will store 'max_value'
6281
 * instead. */
6282
static void
6283
atomic_sat_add(atomic_uint64_t *value, uint64_t n, uint64_t max_value)
6284
0
{
6285
0
    uint64_t current, new_value;
6286
6287
0
    atomic_read_relaxed(value, &current);
6288
0
    do {
6289
0
        new_value = current + n;
6290
0
        new_value = MIN(new_value, max_value);
6291
0
    } while (!atomic_compare_exchange_weak_relaxed(value, &current,
6292
0
                                                   new_value));
6293
0
}
6294
6295
/* Tries to atomically subtract 'n' from 'value'.  Does not perform the
6296
 * operation and returns 'false' if the result will be less than 'min_value'.
6297
 * Otherwise, stores the result and returns 'true'. */
6298
static bool
6299
atomic_bound_sub(atomic_uint64_t *value, uint64_t n, uint64_t min_value)
6300
0
{
6301
0
    uint64_t current;
6302
6303
0
    atomic_read_relaxed(value, &current);
6304
0
    do {
6305
0
        if (current < min_value + n) {
6306
0
            return false;
6307
0
        }
6308
0
    } while (!atomic_compare_exchange_weak_relaxed(value, &current,
6309
0
                                                   current - n));
6310
0
    return true;
6311
0
}
6312
6313
/* Applies the meter identified by 'meter_id' to 'packets_'.  Packets
6314
 * that exceed a band are dropped in-place. */
6315
static void
6316
dp_netdev_run_meter(struct dp_netdev *dp, struct dp_packet_batch *packets_,
6317
                    uint32_t meter_id, long long int now_ms)
6318
0
{
6319
0
    unsigned long failed_bands[BITMAP_N_LONGS(MAX_BANDS)];
6320
0
    const size_t cnt = dp_packet_batch_size(packets_);
6321
0
    uint64_t bytes, volume, meter_used, old;
6322
0
    uint64_t band_packets[MAX_BANDS];
6323
0
    uint64_t band_bytes[MAX_BANDS];
6324
0
    struct dp_meter_band *band;
6325
0
    struct dp_packet *packet;
6326
0
    struct dp_meter *meter;
6327
6328
0
    if (meter_id >= MAX_METERS) {
6329
0
        return;
6330
0
    }
6331
6332
0
    meter = dp_meter_lookup(&dp->meters, meter_id);
6333
0
    if (!meter) {
6334
0
        return;
6335
0
    }
6336
6337
0
    atomic_read_relaxed(&meter->used, &meter_used);
6338
0
    do {
6339
0
        if (meter_used >= now_ms) {
6340
            /* The '>' condition means that we have several threads hitting the
6341
             * same meter, and the other one already advanced the time. */
6342
0
            meter_used = now_ms;
6343
0
            break;
6344
0
        }
6345
0
    } while (!atomic_compare_exchange_weak_relaxed(&meter->used,
6346
0
                                                   &meter_used, now_ms));
6347
6348
    /* Refill all buckets right away, since other threads may use them. */
6349
0
    if (meter_used < now_ms) {
6350
        /* All packets will hit the meter at the same time. */
6351
0
        uint64_t delta_t = now_ms - meter_used;
6352
6353
        /* Make sure delta_t will not be too large, so that bucket will not
6354
         * wrap around below. */
6355
0
        delta_t = MIN(delta_t, meter->max_delta_t);
6356
6357
0
        for (int m = 0; m < meter->n_bands; m++) {
6358
0
            band = &meter->bands[m];
6359
            /* Update band's bucket.  We can't just use atomic add here,
6360
             * because we should never add above the max capacity. */
6361
0
            atomic_sat_add(&band->bucket, delta_t * band->rate,
6362
0
                           band->burst_size * 1000ULL);
6363
0
        }
6364
0
    }
6365
6366
    /* Update meter stats. */
6367
0
    atomic_add_relaxed(&meter->packet_count, cnt, &old);
6368
0
    bytes = 0;
6369
0
    DP_PACKET_BATCH_FOR_EACH (i, packet, packets_) {
6370
0
        bytes += dp_packet_size(packet);
6371
0
    }
6372
0
    atomic_add_relaxed(&meter->byte_count, bytes, &old);
6373
6374
    /* Meters can operate in terms of packets per second or kilobits per
6375
     * second. */
6376
0
    if (meter->flags & OFPMF13_PKTPS) {
6377
        /* Rate in packets/second, bucket 1/1000 packets.
6378
         * msec * packets/sec = 1/1000 packets. */
6379
0
        volume = cnt * 1000; /* Take 'cnt' packets from the bucket. */
6380
0
    } else {
6381
        /* Rate in kbps, bucket in bits.
6382
         * msec * kbps = bits */
6383
0
        volume = bytes * 8;
6384
0
    }
6385
6386
    /* Find the band hit with the highest rate for each packet (if any). */
6387
0
    memset(failed_bands, 0, sizeof failed_bands);
6388
0
    for (int m = 0; m < meter->n_bands; m++) {
6389
0
        band = &meter->bands[m];
6390
6391
        /* Drain the bucket for all the packets, if possible. */
6392
0
        if (atomic_bound_sub(&band->bucket, volume, 0)) {
6393
0
            continue;
6394
0
        }
6395
6396
0
        bitmap_set1(failed_bands, m);
6397
0
    }
6398
6399
    /* No need to iterate over packets if there are no drops. */
6400
0
    if (bitmap_is_all_zeros(failed_bands, meter->n_bands)) {
6401
0
        return;
6402
0
    }
6403
6404
    /* Fire the highest rate band exceeded by each packet, and drop
6405
     * packets if needed. */
6406
6407
0
    memset(band_packets, 0, sizeof band_packets);
6408
0
    memset(band_bytes,   0, sizeof band_bytes);
6409
6410
0
    size_t j;
6411
0
    DP_PACKET_BATCH_REFILL_FOR_EACH (j, cnt, packet, packets_) {
6412
0
        uint64_t packet_volume = (meter->flags & OFPMF13_PKTPS)
6413
0
                                 ? 1000 : (dp_packet_size(packet) * 8);
6414
0
        uint32_t exceeded_rate = 0;
6415
0
        int m = -1;
6416
0
        int b;
6417
6418
0
        BITMAP_FOR_EACH_1 (b, meter->n_bands, failed_bands) {
6419
0
            band = &meter->bands[b];
6420
0
            if (!atomic_bound_sub(&band->bucket, packet_volume, 0)) {
6421
                /* Update the exceeding band for the exceeding packet.
6422
                 * Only one band will be fired by a packet, and that can
6423
                 * be different for each packet. */
6424
0
                if (band->rate > exceeded_rate) {
6425
0
                    exceeded_rate = band->rate;
6426
0
                    m = b;
6427
0
                }
6428
0
            }
6429
0
        }
6430
6431
0
        if (m >= 0) {
6432
            /* Meter drop packet. */
6433
0
            band_packets[m]++;
6434
0
            band_bytes[m] += dp_packet_size(packet);
6435
0
            dp_packet_delete(packet);
6436
0
        } else {
6437
            /* Meter accepts packet. */
6438
0
            dp_packet_batch_add(packets_, packet);
6439
0
        }
6440
0
    }
6441
6442
0
    for (int m = 0; m < meter->n_bands; m++) {
6443
0
        if (!band_packets[m]) {
6444
0
            continue;
6445
0
        }
6446
0
        band = &meter->bands[m];
6447
0
        atomic_add_relaxed(&band->packet_count, band_packets[m], &old);
6448
0
        atomic_add_relaxed(&band->byte_count,   band_bytes[m],   &old);
6449
0
        COVERAGE_ADD(datapath_drop_meter, band_packets[m]);
6450
0
    }
6451
0
}
6452
6453
/* Meter set/get/del processing is still single-threaded. */
6454
static int
6455
dpif_netdev_meter_set(struct dpif *dpif, ofproto_meter_id meter_id,
6456
                      struct ofputil_meter_config *config)
6457
0
{
6458
0
    struct dp_netdev *dp = get_dp_netdev(dpif);
6459
0
    uint32_t mid = meter_id.uint32;
6460
0
    struct dp_meter *meter;
6461
0
    int i;
6462
6463
0
    if (mid >= MAX_METERS) {
6464
0
        return EFBIG; /* Meter_id out of range. */
6465
0
    }
6466
6467
0
    if (config->flags & ~DP_SUPPORTED_METER_FLAGS_MASK) {
6468
0
        return EBADF; /* Unsupported flags set */
6469
0
    }
6470
6471
0
    if (config->n_bands > MAX_BANDS) {
6472
0
        return EINVAL;
6473
0
    }
6474
6475
0
    for (i = 0; i < config->n_bands; ++i) {
6476
0
        switch (config->bands[i].type) {
6477
0
        case OFPMBT13_DROP:
6478
0
            break;
6479
0
        default:
6480
0
            return ENODEV; /* Unsupported band type */
6481
0
        }
6482
0
    }
6483
6484
    /* Allocate meter */
6485
0
    meter = xzalloc(sizeof *meter
6486
0
                    + config->n_bands * sizeof(struct dp_meter_band));
6487
6488
0
    meter->flags = config->flags;
6489
0
    meter->n_bands = config->n_bands;
6490
0
    meter->max_delta_t = 0;
6491
0
    meter->id = mid;
6492
0
    atomic_init(&meter->used, time_msec());
6493
6494
    /* set up bands */
6495
0
    for (i = 0; i < config->n_bands; ++i) {
6496
0
        uint32_t band_max_delta_t;
6497
0
        uint64_t bucket_size;
6498
6499
        /* Set burst size to a workable value if none specified. */
6500
0
        if (config->bands[i].burst_size == 0) {
6501
0
            config->bands[i].burst_size = config->bands[i].rate;
6502
0
        }
6503
6504
0
        meter->bands[i].rate = config->bands[i].rate;
6505
0
        meter->bands[i].burst_size = config->bands[i].burst_size;
6506
        /* Start with a full bucket. */
6507
0
        bucket_size = meter->bands[i].burst_size * 1000ULL;
6508
0
        atomic_init(&meter->bands[i].bucket, bucket_size);
6509
6510
        /* Figure out max delta_t that is enough to fill any bucket. */
6511
0
        band_max_delta_t = bucket_size / meter->bands[i].rate;
6512
0
        if (band_max_delta_t > meter->max_delta_t) {
6513
0
            meter->max_delta_t = band_max_delta_t;
6514
0
        }
6515
0
    }
6516
6517
0
    ovs_mutex_lock(&dp->meters_lock);
6518
6519
0
    dp_meter_detach_free(&dp->meters, mid); /* Free existing meter, if any. */
6520
0
    dp_meter_attach(&dp->meters, meter);
6521
6522
0
    ovs_mutex_unlock(&dp->meters_lock);
6523
6524
0
    return 0;
6525
0
}
6526
6527
static int
6528
dpif_netdev_meter_get(const struct dpif *dpif,
6529
                      ofproto_meter_id meter_id_,
6530
                      struct ofputil_meter_stats *stats, uint16_t n_bands)
6531
0
{
6532
0
    struct dp_netdev *dp = get_dp_netdev(dpif);
6533
0
    uint32_t meter_id = meter_id_.uint32;
6534
0
    struct dp_meter *meter;
6535
6536
0
    if (meter_id >= MAX_METERS) {
6537
0
        return EFBIG;
6538
0
    }
6539
6540
0
    meter = dp_meter_lookup(&dp->meters, meter_id);
6541
0
    if (!meter) {
6542
0
        return ENOENT;
6543
0
    }
6544
6545
0
    if (stats) {
6546
0
        int i = 0;
6547
6548
0
        atomic_read_relaxed(&meter->packet_count, &stats->packet_in_count);
6549
0
        atomic_read_relaxed(&meter->byte_count, &stats->byte_in_count);
6550
6551
0
        for (i = 0; i < n_bands && i < meter->n_bands; ++i) {
6552
0
            atomic_read_relaxed(&meter->bands[i].packet_count,
6553
0
                                &stats->bands[i].packet_count);
6554
0
            atomic_read_relaxed(&meter->bands[i].byte_count,
6555
0
                                &stats->bands[i].byte_count);
6556
0
        }
6557
0
        stats->n_bands = i;
6558
0
    }
6559
6560
0
    return 0;
6561
0
}
6562
6563
static int
6564
dpif_netdev_meter_del(struct dpif *dpif,
6565
                      ofproto_meter_id meter_id_,
6566
                      struct ofputil_meter_stats *stats, uint16_t n_bands)
6567
0
{
6568
0
    struct dp_netdev *dp = get_dp_netdev(dpif);
6569
0
    int error;
6570
6571
0
    error = dpif_netdev_meter_get(dpif, meter_id_, stats, n_bands);
6572
0
    if (!error) {
6573
0
        uint32_t meter_id = meter_id_.uint32;
6574
6575
0
        ovs_mutex_lock(&dp->meters_lock);
6576
0
        dp_meter_detach_free(&dp->meters, meter_id);
6577
0
        ovs_mutex_unlock(&dp->meters_lock);
6578
0
    }
6579
0
    return error;
6580
0
}
6581
6582

6583
static void
6584
dpif_netdev_disable_upcall(struct dpif *dpif)
6585
    OVS_NO_THREAD_SAFETY_ANALYSIS
6586
0
{
6587
0
    struct dp_netdev *dp = get_dp_netdev(dpif);
6588
0
    dp_netdev_disable_upcall(dp);
6589
0
}
6590
6591
static void
6592
dp_netdev_enable_upcall(struct dp_netdev *dp)
6593
    OVS_RELEASES(dp->upcall_rwlock)
6594
0
{
6595
0
    fat_rwlock_unlock(&dp->upcall_rwlock);
6596
0
}
6597
6598
static void
6599
dpif_netdev_enable_upcall(struct dpif *dpif)
6600
    OVS_NO_THREAD_SAFETY_ANALYSIS
6601
0
{
6602
0
    struct dp_netdev *dp = get_dp_netdev(dpif);
6603
0
    dp_netdev_enable_upcall(dp);
6604
0
}
6605
6606
static void
6607
dp_netdev_pmd_reload_done(struct dp_netdev_pmd_thread *pmd)
6608
0
{
6609
0
    atomic_store_relaxed(&pmd->wait_for_reload, false);
6610
0
    atomic_store_relaxed(&pmd->reload_tx_qid, false);
6611
0
    pmd->last_reload_seq = seq_read(pmd->reload_seq);
6612
0
    atomic_store_explicit(&pmd->reload, false, memory_order_release);
6613
0
}
6614
6615
/* Finds and refs the dp_netdev_pmd_thread on core 'core_id'.  Returns
6616
 * the pointer if succeeds, otherwise, NULL (it can return NULL even if
6617
 * 'core_id' is NON_PMD_CORE_ID).
6618
 *
6619
 * Caller must unrefs the returned reference.  */
6620
static struct dp_netdev_pmd_thread *
6621
dp_netdev_get_pmd(struct dp_netdev *dp, unsigned core_id)
6622
0
{
6623
0
    struct dp_netdev_pmd_thread *pmd;
6624
6625
0
    CMAP_FOR_EACH_WITH_HASH (pmd, node, hash_int(core_id, 0),
6626
0
                             &dp->poll_threads) {
6627
0
        if (pmd->core_id == core_id) {
6628
0
            return dp_netdev_pmd_try_ref(pmd) ? pmd : NULL;
6629
0
        }
6630
0
    }
6631
6632
0
    return NULL;
6633
0
}
6634
6635
/* Sets the 'struct dp_netdev_pmd_thread' for non-pmd threads. */
6636
static void
6637
dp_netdev_set_nonpmd(struct dp_netdev *dp)
6638
    OVS_REQ_WRLOCK(dp->port_rwlock)
6639
0
{
6640
0
    struct dp_netdev_pmd_thread *non_pmd;
6641
6642
0
    non_pmd = xzalloc(sizeof *non_pmd);
6643
0
    dp_netdev_configure_pmd(non_pmd, dp, NON_PMD_CORE_ID, OVS_NUMA_UNSPEC);
6644
0
}
6645
6646
/* Caller must have valid pointer to 'pmd'. */
6647
static bool
6648
dp_netdev_pmd_try_ref(struct dp_netdev_pmd_thread *pmd)
6649
0
{
6650
0
    return ovs_refcount_try_ref_rcu(&pmd->ref_cnt);
6651
0
}
6652
6653
static void
6654
dp_netdev_pmd_unref(struct dp_netdev_pmd_thread *pmd)
6655
0
{
6656
0
    if (pmd && ovs_refcount_unref(&pmd->ref_cnt) == 1) {
6657
0
        ovsrcu_postpone(dp_netdev_destroy_pmd, pmd);
6658
0
    }
6659
0
}
6660
6661
/* Given cmap position 'pos', tries to ref the next node.  If try_ref()
6662
 * fails, keeps checking for next node until reaching the end of cmap.
6663
 *
6664
 * Caller must unrefs the returned reference. */
6665
static struct dp_netdev_pmd_thread *
6666
dp_netdev_pmd_get_next(struct dp_netdev *dp, struct cmap_position *pos)
6667
0
{
6668
0
    struct dp_netdev_pmd_thread *next;
6669
6670
0
    do {
6671
0
        struct cmap_node *node;
6672
6673
0
        node = cmap_next_position(&dp->poll_threads, pos);
6674
0
        next = node ? CONTAINER_OF(node, struct dp_netdev_pmd_thread, node)
6675
0
            : NULL;
6676
0
    } while (next && !dp_netdev_pmd_try_ref(next));
6677
6678
0
    return next;
6679
0
}
6680
6681
/* Configures the 'pmd' based on the input argument. */
6682
static void
6683
dp_netdev_configure_pmd(struct dp_netdev_pmd_thread *pmd, struct dp_netdev *dp,
6684
                        unsigned core_id, int numa_id)
6685
    OVS_NO_THREAD_SAFETY_ANALYSIS
6686
0
{
6687
0
    pmd->dp = dp;
6688
0
    pmd->core_id = core_id;
6689
0
    pmd->numa_id = numa_id;
6690
0
    pmd->need_reload = false;
6691
0
    pmd->n_output_batches = 0;
6692
6693
0
    ovs_refcount_init(&pmd->ref_cnt);
6694
0
    atomic_init(&pmd->exit, false);
6695
0
    pmd->reload_seq = seq_create();
6696
0
    pmd->last_reload_seq = seq_read(pmd->reload_seq);
6697
0
    atomic_init(&pmd->reload, false);
6698
0
    ovs_mutex_init(&pmd->flow_mutex);
6699
0
    ovs_mutex_init(&pmd->port_mutex);
6700
0
    ovs_mutex_init(&pmd->bond_mutex);
6701
0
    cmap_init(&pmd->flow_table);
6702
0
    cmap_init(&pmd->classifiers);
6703
0
    cmap_init(&pmd->simple_match_table);
6704
0
    ccmap_init(&pmd->n_flows);
6705
0
    ccmap_init(&pmd->n_simple_flows);
6706
0
    pmd->ctx.last_rxq = NULL;
6707
0
    pmd_thread_ctx_time_update(pmd);
6708
0
    pmd->next_optimization = pmd->ctx.now + DPCLS_OPTIMIZATION_INTERVAL;
6709
0
    pmd->next_rcu_quiesce = pmd->ctx.now + PMD_RCU_QUIESCE_INTERVAL;
6710
0
    pmd->next_cycle_store = pmd->ctx.now + PMD_INTERVAL_LEN;
6711
0
    pmd->busy_cycles_intrvl = xzalloc(PMD_INTERVAL_MAX *
6712
0
                                      sizeof *pmd->busy_cycles_intrvl);
6713
0
    hmap_init(&pmd->poll_list);
6714
0
    hmap_init(&pmd->tx_ports);
6715
0
    hmap_init(&pmd->tnl_port_cache);
6716
0
    hmap_init(&pmd->send_port_cache);
6717
0
    cmap_init(&pmd->tx_bonds);
6718
6719
0
    pmd_init_max_sleep(dp, pmd);
6720
6721
    /* init the 'flow_cache' since there is no
6722
     * actual thread created for NON_PMD_CORE_ID. */
6723
0
    if (core_id == NON_PMD_CORE_ID) {
6724
0
        dfc_cache_init(&pmd->flow_cache);
6725
0
        pmd_alloc_static_tx_qid(pmd);
6726
0
    }
6727
0
    pmd_perf_stats_init(&pmd->perf_stats);
6728
0
    cmap_insert(&dp->poll_threads, CONST_CAST(struct cmap_node *, &pmd->node),
6729
0
                hash_int(core_id, 0));
6730
0
}
6731
6732
static void
6733
dp_netdev_destroy_pmd(struct dp_netdev_pmd_thread *pmd)
6734
    OVS_NO_THREAD_SAFETY_ANALYSIS
6735
0
{
6736
0
    struct dpcls *cls;
6737
6738
0
    dp_netdev_pmd_flow_flush(pmd);
6739
0
    hmap_destroy(&pmd->send_port_cache);
6740
0
    hmap_destroy(&pmd->tnl_port_cache);
6741
0
    hmap_destroy(&pmd->tx_ports);
6742
0
    cmap_destroy(&pmd->tx_bonds);
6743
0
    hmap_destroy(&pmd->poll_list);
6744
0
    free(pmd->busy_cycles_intrvl);
6745
    /* All flows (including their dpcls_rules) have been deleted already */
6746
0
    CMAP_FOR_EACH (cls, node, &pmd->classifiers) {
6747
0
        dpcls_destroy(cls);
6748
0
        ovsrcu_postpone(free, cls);
6749
0
    }
6750
0
    cmap_destroy(&pmd->classifiers);
6751
0
    cmap_destroy(&pmd->flow_table);
6752
0
    cmap_destroy(&pmd->simple_match_table);
6753
0
    ccmap_destroy(&pmd->n_flows);
6754
0
    ccmap_destroy(&pmd->n_simple_flows);
6755
0
    ovs_mutex_destroy(&pmd->flow_mutex);
6756
0
    seq_destroy(pmd->reload_seq);
6757
0
    ovs_mutex_destroy(&pmd->port_mutex);
6758
0
    ovs_mutex_destroy(&pmd->bond_mutex);
6759
0
    free(pmd);
6760
0
}
6761
6762
/* Stops the pmd thread, removes it from the 'dp->poll_threads',
6763
 * and unrefs the struct. */
6764
static void
6765
dp_netdev_del_pmd(struct dp_netdev *dp, struct dp_netdev_pmd_thread *pmd)
6766
0
{
6767
    /* NON_PMD_CORE_ID doesn't have a thread, so we don't have to synchronize,
6768
     * but extra cleanup is necessary */
6769
0
    if (pmd->core_id == NON_PMD_CORE_ID) {
6770
0
        ovs_mutex_lock(&dp->non_pmd_mutex);
6771
0
        dfc_cache_uninit(&pmd->flow_cache);
6772
0
        pmd_free_cached_ports(pmd);
6773
0
        pmd_free_static_tx_qid(pmd);
6774
0
        ovs_mutex_unlock(&dp->non_pmd_mutex);
6775
0
    } else {
6776
0
        atomic_store_relaxed(&pmd->exit, true);
6777
0
        dp_netdev_reload_pmd__(pmd);
6778
0
        xpthread_join(pmd->thread, NULL);
6779
0
    }
6780
6781
0
    dp_netdev_pmd_clear_ports(pmd);
6782
6783
    /* Purges the 'pmd''s flows after stopping the thread, but before
6784
     * destroying the flows, so that the flow stats can be collected. */
6785
0
    if (dp->dp_purge_cb) {
6786
0
        dp->dp_purge_cb(dp->dp_purge_aux, pmd->core_id);
6787
0
    }
6788
0
    cmap_remove(&pmd->dp->poll_threads, &pmd->node, hash_int(pmd->core_id, 0));
6789
0
    dp_netdev_pmd_unref(pmd);
6790
0
}
6791
6792
/* Destroys all pmd threads. If 'non_pmd' is true it also destroys the non pmd
6793
 * thread. */
6794
static void
6795
dp_netdev_destroy_all_pmds(struct dp_netdev *dp, bool non_pmd)
6796
0
{
6797
0
    struct dp_netdev_pmd_thread *pmd;
6798
0
    struct dp_netdev_pmd_thread **pmd_list;
6799
0
    size_t k = 0, n_pmds;
6800
6801
0
    n_pmds = cmap_count(&dp->poll_threads);
6802
0
    pmd_list = xcalloc(n_pmds, sizeof *pmd_list);
6803
6804
0
    CMAP_FOR_EACH (pmd, node, &dp->poll_threads) {
6805
0
        if (!non_pmd && pmd->core_id == NON_PMD_CORE_ID) {
6806
0
            continue;
6807
0
        }
6808
        /* We cannot call dp_netdev_del_pmd(), since it alters
6809
         * 'dp->poll_threads' (while we're iterating it) and it
6810
         * might quiesce. */
6811
0
        ovs_assert(k < n_pmds);
6812
0
        pmd_list[k++] = pmd;
6813
0
    }
6814
6815
0
    for (size_t i = 0; i < k; i++) {
6816
0
        dp_netdev_del_pmd(dp, pmd_list[i]);
6817
0
    }
6818
0
    free(pmd_list);
6819
0
}
6820
6821
/* Deletes all rx queues from pmd->poll_list and all the ports from
6822
 * pmd->tx_ports. */
6823
static void
6824
dp_netdev_pmd_clear_ports(struct dp_netdev_pmd_thread *pmd)
6825
0
{
6826
0
    struct rxq_poll *poll;
6827
0
    struct tx_port *port;
6828
0
    struct tx_bond *tx;
6829
6830
0
    ovs_mutex_lock(&pmd->port_mutex);
6831
0
    HMAP_FOR_EACH_POP (poll, node, &pmd->poll_list) {
6832
0
        free(poll);
6833
0
    }
6834
0
    HMAP_FOR_EACH_POP (port, node, &pmd->tx_ports) {
6835
0
        tx_port_destroy(port);
6836
0
    }
6837
0
    ovs_mutex_unlock(&pmd->port_mutex);
6838
6839
0
    ovs_mutex_lock(&pmd->bond_mutex);
6840
0
    CMAP_FOR_EACH (tx, node, &pmd->tx_bonds) {
6841
0
        cmap_remove(&pmd->tx_bonds, &tx->node, hash_bond_id(tx->bond_id));
6842
0
        ovsrcu_postpone(free, tx);
6843
0
    }
6844
0
    ovs_mutex_unlock(&pmd->bond_mutex);
6845
0
}
6846
6847
/* Adds rx queue to poll_list of PMD thread, if it's not there already. */
6848
static void
6849
dp_netdev_add_rxq_to_pmd(struct dp_netdev_pmd_thread *pmd,
6850
                         struct dp_netdev_rxq *rxq)
6851
    OVS_REQUIRES(pmd->port_mutex)
6852
0
{
6853
0
    int qid = netdev_rxq_get_queue_id(rxq->rx);
6854
0
    uint32_t hash = hash_2words(odp_to_u32(rxq->port->port_no), qid);
6855
0
    struct rxq_poll *poll;
6856
6857
0
    HMAP_FOR_EACH_WITH_HASH (poll, node, hash, &pmd->poll_list) {
6858
0
        if (poll->rxq == rxq) {
6859
            /* 'rxq' is already polled by this thread. Do nothing. */
6860
0
            return;
6861
0
        }
6862
0
    }
6863
6864
0
    poll = xmalloc(sizeof *poll);
6865
0
    poll->rxq = rxq;
6866
0
    hmap_insert(&pmd->poll_list, &poll->node, hash);
6867
6868
0
    pmd->need_reload = true;
6869
0
}
6870
6871
/* Delete 'poll' from poll_list of PMD thread. */
6872
static void
6873
dp_netdev_del_rxq_from_pmd(struct dp_netdev_pmd_thread *pmd,
6874
                           struct rxq_poll *poll)
6875
    OVS_REQUIRES(pmd->port_mutex)
6876
0
{
6877
0
    hmap_remove(&pmd->poll_list, &poll->node);
6878
0
    free(poll);
6879
6880
0
    pmd->need_reload = true;
6881
0
}
6882
6883
/* Add 'port' to the tx port cache of 'pmd', which must be reloaded for the
6884
 * changes to take effect. */
6885
static void
6886
dp_netdev_add_port_tx_to_pmd(struct dp_netdev_pmd_thread *pmd,
6887
                             struct dp_netdev_port *port)
6888
    OVS_REQUIRES(pmd->port_mutex)
6889
0
{
6890
0
    struct tx_port *tx;
6891
6892
0
    tx = tx_port_lookup(&pmd->tx_ports, port->port_no);
6893
0
    if (tx) {
6894
        /* 'port' is already on this thread tx cache. Do nothing. */
6895
0
        return;
6896
0
    }
6897
6898
0
    tx = tx_port_create(port);
6899
0
    hmap_insert(&pmd->tx_ports, &tx->node, hash_port_no(tx->port->port_no));
6900
0
    pmd->need_reload = true;
6901
0
}
6902
6903
/* Del 'tx' from the tx port cache of 'pmd', which must be reloaded for the
6904
 * changes to take effect. */
6905
static void
6906
dp_netdev_del_port_tx_from_pmd(struct dp_netdev_pmd_thread *pmd,
6907
                               struct tx_port *tx)
6908
    OVS_REQUIRES(pmd->port_mutex)
6909
0
{
6910
0
    hmap_remove(&pmd->tx_ports, &tx->node);
6911
0
    tx_port_destroy(tx);
6912
0
    pmd->need_reload = true;
6913
0
}
6914
6915
/* Add bond to the tx bond cmap of 'pmd'. */
6916
static void
6917
dp_netdev_add_bond_tx_to_pmd(struct dp_netdev_pmd_thread *pmd,
6918
                             struct tx_bond *bond, bool update)
6919
    OVS_EXCLUDED(pmd->bond_mutex)
6920
0
{
6921
0
    struct tx_bond *tx;
6922
6923
0
    ovs_mutex_lock(&pmd->bond_mutex);
6924
0
    tx = tx_bond_lookup(&pmd->tx_bonds, bond->bond_id);
6925
6926
0
    if (tx && !update) {
6927
        /* It's not an update and the entry already exists.  Do nothing. */
6928
0
        goto unlock;
6929
0
    }
6930
6931
0
    if (tx) {
6932
0
        struct tx_bond *new_tx = xmemdup(bond, sizeof *bond);
6933
6934
        /* Copy the stats for each bucket. */
6935
0
        for (int i = 0; i < BOND_BUCKETS; i++) {
6936
0
            uint64_t n_packets, n_bytes;
6937
6938
0
            atomic_read_relaxed(&tx->member_buckets[i].n_packets, &n_packets);
6939
0
            atomic_read_relaxed(&tx->member_buckets[i].n_bytes, &n_bytes);
6940
0
            atomic_init(&new_tx->member_buckets[i].n_packets, n_packets);
6941
0
            atomic_init(&new_tx->member_buckets[i].n_bytes, n_bytes);
6942
0
        }
6943
0
        cmap_replace(&pmd->tx_bonds, &tx->node, &new_tx->node,
6944
0
                     hash_bond_id(bond->bond_id));
6945
0
        ovsrcu_postpone(free, tx);
6946
0
    } else {
6947
0
        tx = xmemdup(bond, sizeof *bond);
6948
0
        cmap_insert(&pmd->tx_bonds, &tx->node, hash_bond_id(bond->bond_id));
6949
0
    }
6950
0
unlock:
6951
0
    ovs_mutex_unlock(&pmd->bond_mutex);
6952
0
}
6953
6954
/* Delete bond from the tx bond cmap of 'pmd'. */
6955
static void
6956
dp_netdev_del_bond_tx_from_pmd(struct dp_netdev_pmd_thread *pmd,
6957
                               uint32_t bond_id)
6958
    OVS_EXCLUDED(pmd->bond_mutex)
6959
0
{
6960
0
    struct tx_bond *tx;
6961
6962
0
    ovs_mutex_lock(&pmd->bond_mutex);
6963
0
    tx = tx_bond_lookup(&pmd->tx_bonds, bond_id);
6964
0
    if (tx) {
6965
0
        cmap_remove(&pmd->tx_bonds, &tx->node, hash_bond_id(tx->bond_id));
6966
0
        ovsrcu_postpone(free, tx);
6967
0
    }
6968
0
    ovs_mutex_unlock(&pmd->bond_mutex);
6969
0
}
6970

6971
static char *
6972
dpif_netdev_get_datapath_version(void)
6973
0
{
6974
0
     return xstrdup("<built-in>");
6975
0
}
6976
6977
static void
6978
dp_netdev_flow_used(struct dp_netdev_flow *netdev_flow, int cnt, int size,
6979
                    uint16_t tcp_flags, long long now)
6980
0
{
6981
0
    uint16_t flags;
6982
6983
0
    atomic_store_relaxed(&netdev_flow->stats.used, now);
6984
0
    non_atomic_ullong_add(&netdev_flow->stats.packet_count, cnt);
6985
0
    non_atomic_ullong_add(&netdev_flow->stats.byte_count, size);
6986
0
    atomic_read_relaxed(&netdev_flow->stats.tcp_flags, &flags);
6987
0
    flags |= tcp_flags;
6988
0
    atomic_store_relaxed(&netdev_flow->stats.tcp_flags, flags);
6989
0
}
6990
6991
static int
6992
dp_netdev_upcall(struct dp_netdev_pmd_thread *pmd, struct dp_packet *packet_,
6993
                 struct flow *flow, struct flow_wildcards *wc, ovs_u128 *ufid,
6994
                 enum dpif_upcall_type type, const struct nlattr *userdata,
6995
                 struct ofpbuf *actions, struct ofpbuf *put_actions)
6996
0
{
6997
0
    struct dp_netdev *dp = pmd->dp;
6998
6999
0
    if (OVS_UNLIKELY(!dp->upcall_cb)) {
7000
0
        return ENODEV;
7001
0
    }
7002
7003
0
    if (OVS_UNLIKELY(!VLOG_DROP_DBG(&upcall_rl))) {
7004
0
        struct ds ds = DS_EMPTY_INITIALIZER;
7005
0
        char *packet_str;
7006
0
        struct ofpbuf key;
7007
0
        struct odp_flow_key_parms odp_parms = {
7008
0
            .flow = flow,
7009
0
            .mask = wc ? &wc->masks : NULL,
7010
0
            .support = dp_netdev_support,
7011
0
        };
7012
7013
0
        ofpbuf_init(&key, 0);
7014
0
        odp_flow_key_from_flow(&odp_parms, &key);
7015
0
        packet_str = ofp_dp_packet_to_string(packet_);
7016
7017
0
        odp_flow_key_format(key.data, key.size, &ds);
7018
7019
0
        VLOG_DBG("%s: %s upcall:\n%s\n%s", dp->name,
7020
0
                 dpif_upcall_type_to_string(type), ds_cstr(&ds), packet_str);
7021
7022
0
        ofpbuf_uninit(&key);
7023
0
        free(packet_str);
7024
7025
0
        ds_destroy(&ds);
7026
0
    }
7027
7028
0
    if (type != DPIF_UC_MISS) {
7029
0
        dp_packet_ol_send_prepare(packet_, 0);
7030
0
    }
7031
7032
0
    return dp->upcall_cb(packet_, flow, ufid, pmd->core_id, type, userdata,
7033
0
                         actions, wc, put_actions, dp->upcall_aux);
7034
0
}
7035
7036
static inline uint32_t
7037
dpif_netdev_packet_get_rss_hash(struct dp_packet *packet,
7038
                                const struct miniflow *mf)
7039
0
{
7040
0
    uint32_t hash, recirc_depth;
7041
7042
0
    if (OVS_LIKELY(dp_packet_rss_valid(packet))) {
7043
0
        hash = dp_packet_get_rss_hash(packet);
7044
0
    } else {
7045
0
        hash = miniflow_hash_5tuple(mf, 0);
7046
0
        dp_packet_set_rss_hash(packet, hash);
7047
0
    }
7048
7049
    /* The RSS hash must account for the recirculation depth to avoid
7050
     * collisions in the exact match cache */
7051
0
    recirc_depth = *recirc_depth_get_unsafe();
7052
0
    if (OVS_UNLIKELY(recirc_depth)) {
7053
0
        hash = hash_finish(hash, recirc_depth);
7054
0
    }
7055
0
    return hash;
7056
0
}
7057
7058
struct packet_batch_per_flow {
7059
    unsigned int byte_count;
7060
    uint16_t tcp_flags;
7061
    struct dp_netdev_flow *flow;
7062
7063
    struct dp_packet_batch array;
7064
};
7065
7066
static inline void
7067
packet_batch_per_flow_update(struct packet_batch_per_flow *batch,
7068
                             struct dp_packet *packet,
7069
                             uint16_t tcp_flags)
7070
0
{
7071
0
    batch->byte_count += dp_packet_size(packet);
7072
0
    batch->tcp_flags |= tcp_flags;
7073
0
    dp_packet_batch_add(&batch->array, packet);
7074
0
}
7075
7076
static inline void
7077
packet_batch_per_flow_init(struct packet_batch_per_flow *batch,
7078
                           struct dp_netdev_flow *flow)
7079
0
{
7080
0
    flow->batch = batch;
7081
7082
0
    batch->flow = flow;
7083
0
    dp_packet_batch_init(&batch->array);
7084
0
    batch->byte_count = 0;
7085
0
    batch->tcp_flags = 0;
7086
0
}
7087
7088
static inline void
7089
packet_batch_per_flow_execute(struct packet_batch_per_flow *batch,
7090
                              struct dp_netdev_pmd_thread *pmd)
7091
0
{
7092
0
    struct dp_netdev_actions *actions;
7093
0
    struct dp_netdev_flow *flow = batch->flow;
7094
7095
0
    dp_netdev_flow_used(flow, dp_packet_batch_size(&batch->array),
7096
0
                        batch->byte_count,
7097
0
                        batch->tcp_flags, pmd->ctx.now / 1000);
7098
7099
0
    actions = dp_netdev_flow_get_actions(flow);
7100
7101
0
    dp_netdev_execute_actions(pmd, &batch->array, true, &flow->flow,
7102
0
                              actions->actions, actions->size);
7103
0
}
7104
7105
static inline void
7106
dp_netdev_queue_batches(struct dp_packet *pkt,
7107
                        struct dp_netdev_flow *flow, uint16_t tcp_flags,
7108
                        struct packet_batch_per_flow *batches,
7109
                        size_t *n_batches)
7110
0
{
7111
0
    struct packet_batch_per_flow *batch = flow->batch;
7112
7113
0
    if (OVS_UNLIKELY(!batch)) {
7114
0
        batch = &batches[(*n_batches)++];
7115
0
        packet_batch_per_flow_init(batch, flow);
7116
0
    }
7117
7118
0
    packet_batch_per_flow_update(batch, pkt, tcp_flags);
7119
0
}
7120
7121
static inline void
7122
packet_enqueue_to_flow_map(struct dp_packet *packet,
7123
                           struct dp_netdev_flow *flow,
7124
                           uint16_t tcp_flags,
7125
                           struct dp_packet_flow_map *flow_map,
7126
                           size_t index)
7127
0
{
7128
0
    struct dp_packet_flow_map *map = &flow_map[index];
7129
0
    map->flow = flow;
7130
0
    map->packet = packet;
7131
0
    map->tcp_flags = tcp_flags;
7132
0
}
7133
7134
/* SMC lookup function for a batch of packets.
7135
 * By doing batching SMC lookup, we can use prefetch
7136
 * to hide memory access latency.
7137
 */
7138
static inline void
7139
smc_lookup_batch(struct dp_netdev_pmd_thread *pmd,
7140
            struct netdev_flow_key *keys,
7141
            struct netdev_flow_key **missed_keys,
7142
            struct dp_packet_batch *packets_,
7143
            const int cnt,
7144
            struct dp_packet_flow_map *flow_map,
7145
            uint8_t *index_map)
7146
0
{
7147
0
    int i;
7148
0
    struct dp_packet *packet;
7149
0
    size_t n_smc_hit = 0, n_missed = 0;
7150
0
    struct dfc_cache *cache = &pmd->flow_cache;
7151
0
    struct smc_cache *smc_cache = &cache->smc_cache;
7152
0
    const struct cmap_node *flow_node;
7153
0
    int recv_idx;
7154
0
    uint16_t tcp_flags;
7155
7156
    /* Prefetch buckets for all packets */
7157
0
    for (i = 0; i < cnt; i++) {
7158
0
        OVS_PREFETCH(&smc_cache->buckets[keys[i].hash & SMC_MASK]);
7159
0
    }
7160
7161
0
    DP_PACKET_BATCH_REFILL_FOR_EACH (i, cnt, packet, packets_) {
7162
0
        struct dp_netdev_flow *flow = NULL;
7163
0
        flow_node = smc_entry_get(pmd, keys[i].hash);
7164
0
        bool hit = false;
7165
        /* Get the original order of this packet in received batch. */
7166
0
        recv_idx = index_map[i];
7167
7168
0
        if (OVS_LIKELY(flow_node != NULL)) {
7169
0
            CMAP_NODE_FOR_EACH (flow, node, flow_node) {
7170
                /* Since we dont have per-port megaflow to check the port
7171
                 * number, we need to  verify that the input ports match. */
7172
0
                if (OVS_LIKELY(dpcls_rule_matches_key(&flow->cr, &keys[i]) &&
7173
0
                flow->flow.in_port.odp_port == packet->md.in_port.odp_port)) {
7174
0
                    tcp_flags = miniflow_get_tcp_flags(&keys[i].mf);
7175
7176
                    /* SMC hit and emc miss, we insert into EMC */
7177
0
                    keys[i].len =
7178
0
                        netdev_flow_key_size(miniflow_n_values(&keys[i].mf));
7179
0
                    emc_probabilistic_insert(pmd, &keys[i], flow);
7180
                    /* Add these packets into the flow map in the same order
7181
                     * as received.
7182
                     */
7183
0
                    packet_enqueue_to_flow_map(packet, flow, tcp_flags,
7184
0
                                               flow_map, recv_idx);
7185
0
                    n_smc_hit++;
7186
0
                    hit = true;
7187
0
                    break;
7188
0
                }
7189
0
            }
7190
0
            if (hit) {
7191
0
                continue;
7192
0
            }
7193
0
        }
7194
7195
        /* SMC missed. Group missed packets together at
7196
         * the beginning of the 'packets' array. */
7197
0
        dp_packet_batch_add(packets_, packet);
7198
7199
        /* Preserve the order of packet for flow batching. */
7200
0
        index_map[n_missed] = recv_idx;
7201
7202
        /* Put missed keys to the pointer arrays return to the caller */
7203
0
        missed_keys[n_missed++] = &keys[i];
7204
0
    }
7205
7206
0
    pmd_perf_update_counter(&pmd->perf_stats, PMD_STAT_SMC_HIT, n_smc_hit);
7207
0
}
7208
7209
struct dp_netdev_flow *
7210
smc_lookup_single(struct dp_netdev_pmd_thread *pmd,
7211
                  struct dp_packet *packet,
7212
                  struct netdev_flow_key *key)
7213
0
{
7214
0
    const struct cmap_node *flow_node = smc_entry_get(pmd, key->hash);
7215
7216
0
    if (OVS_LIKELY(flow_node != NULL)) {
7217
0
        struct dp_netdev_flow *flow = NULL;
7218
7219
0
        CMAP_NODE_FOR_EACH (flow, node, flow_node) {
7220
            /* Since we dont have per-port megaflow to check the port
7221
             * number, we need to verify that the input ports match. */
7222
0
            if (OVS_LIKELY(dpcls_rule_matches_key(&flow->cr, key) &&
7223
0
                flow->flow.in_port.odp_port == packet->md.in_port.odp_port)) {
7224
7225
0
                return (void *) flow;
7226
0
            }
7227
0
        }
7228
0
    }
7229
7230
0
    return NULL;
7231
0
}
7232
7233
static inline int
7234
dp_netdev_hw_flow(const struct dp_netdev_pmd_thread *pmd,
7235
                  struct dp_packet *packet,
7236
                  struct dp_netdev_flow **flow)
7237
0
{
7238
0
    struct dp_netdev_rxq *rxq = pmd->ctx.last_rxq;
7239
0
    bool post_process_api_supported;
7240
0
    void *flow_reference = NULL;
7241
0
    int err;
7242
7243
0
    atomic_read_relaxed(&rxq->port->netdev->hw_info.post_process_api_supported,
7244
0
                        &post_process_api_supported);
7245
7246
0
    if (!post_process_api_supported) {
7247
0
        *flow = NULL;
7248
0
        return 0;
7249
0
    }
7250
7251
0
    err = dpif_offload_netdev_hw_post_process(rxq->port->netdev, pmd->core_id,
7252
0
                                              packet, &flow_reference);
7253
0
    if (err && err != EOPNOTSUPP) {
7254
0
        if (err != ECANCELED) {
7255
0
            COVERAGE_INC(datapath_drop_hw_post_process);
7256
0
        } else {
7257
0
            COVERAGE_INC(datapath_drop_hw_post_process_consumed);
7258
0
        }
7259
0
        return -1;
7260
0
    }
7261
7262
0
    *flow = flow_reference;
7263
0
    return 0;
7264
0
}
7265
7266
/* Enqueues already classified packet into per-flow batches or the flow map,
7267
 * depending on the fact if batching enabled. */
7268
static inline void
7269
dfc_processing_enqueue_classified_packet(struct dp_packet *packet,
7270
                                         struct dp_netdev_flow *flow,
7271
                                         uint16_t tcp_flags,
7272
                                         bool batch_enable,
7273
                                         struct packet_batch_per_flow *batches,
7274
                                         size_t *n_batches,
7275
                                         struct dp_packet_flow_map *flow_map,
7276
                                         size_t *map_cnt)
7277
7278
0
{
7279
0
    if (OVS_LIKELY(batch_enable)) {
7280
0
        dp_netdev_queue_batches(packet, flow, tcp_flags, batches,
7281
0
                                n_batches);
7282
0
    } else {
7283
        /* Flow batching should be performed only after fast-path
7284
         * processing is also completed for packets with emc miss
7285
         * or else it will result in reordering of packets with
7286
         * same datapath flows. */
7287
0
        packet_enqueue_to_flow_map(packet, flow, tcp_flags,
7288
0
                                   flow_map, (*map_cnt)++);
7289
0
    }
7290
7291
0
}
7292
7293
/* Try to process all ('cnt') the 'packets' using only the datapath flow cache
7294
 * 'pmd->flow_cache'. If a flow is not found for a packet 'packets[i]', the
7295
 * miniflow is copied into 'keys' and the packet pointer is moved at the
7296
 * beginning of the 'packets' array. The pointers of missed keys are put in the
7297
 * missed_keys pointer array for future processing.
7298
 *
7299
 * The function returns the number of packets that needs to be processed in the
7300
 * 'packets' array (they have been moved to the beginning of the vector).
7301
 *
7302
 * For performance reasons a caller may choose not to initialize the metadata
7303
 * in 'packets_'.  If 'md_is_valid' is false, the metadata in 'packets'
7304
 * is not valid and must be initialized by this function using 'port_no'.
7305
 * If 'md_is_valid' is true, the metadata is already valid and 'port_no'
7306
 * will be ignored.
7307
 */
7308
static inline size_t
7309
dfc_processing(struct dp_netdev_pmd_thread *pmd,
7310
               struct dp_packet_batch *packets_,
7311
               struct netdev_flow_key *keys,
7312
               struct netdev_flow_key **missed_keys,
7313
               struct packet_batch_per_flow batches[], size_t *n_batches,
7314
               struct dp_packet_flow_map *flow_map,
7315
               size_t *n_flows, uint8_t *index_map,
7316
               bool md_is_valid, odp_port_t port_no)
7317
0
{
7318
0
    size_t n_missed = 0, n_emc_hit = 0, n_phwol_hit = 0, n_simple_hit = 0;
7319
0
    const bool offload_enabled = dpif_offload_enabled();
7320
0
    const uint32_t recirc_depth = *recirc_depth_get();
7321
0
    const size_t cnt = dp_packet_batch_size(packets_);
7322
0
    struct dfc_cache *cache = &pmd->flow_cache;
7323
0
    struct netdev_flow_key *key = &keys[0];
7324
0
    struct dp_packet *packet;
7325
0
    size_t map_cnt = 0;
7326
0
    bool batch_enable = true;
7327
7328
0
    const bool simple_match_enabled =
7329
0
        !md_is_valid && dp_netdev_simple_match_enabled(pmd, port_no);
7330
    /* 'simple_match_table' is a full flow table.  If the flow is not there,
7331
     * upcall is required, and there is no chance to find a match in caches. */
7332
0
    const bool smc_enable_db = !simple_match_enabled && pmd->ctx.smc_enable_db;
7333
0
    const uint32_t cur_min = simple_match_enabled
7334
0
                             ? 0 : pmd->ctx.emc_insert_min;
7335
7336
0
    pmd_perf_update_counter(&pmd->perf_stats,
7337
0
                            md_is_valid ? PMD_STAT_RECIRC : PMD_STAT_RECV,
7338
0
                            cnt);
7339
0
    int i;
7340
0
    DP_PACKET_BATCH_REFILL_FOR_EACH (i, cnt, packet, packets_) {
7341
0
        struct dp_netdev_flow *flow = NULL;
7342
0
        uint16_t tcp_flags;
7343
7344
0
        if (OVS_UNLIKELY(dp_packet_size(packet) < ETH_HEADER_LEN)) {
7345
0
            dp_packet_delete(packet);
7346
0
            COVERAGE_INC(datapath_drop_rx_invalid_packet);
7347
0
            continue;
7348
0
        }
7349
7350
0
        if (i != cnt - 1) {
7351
0
            struct dp_packet **packets = packets_->packets;
7352
            /* Prefetch next packet data and metadata. */
7353
0
            OVS_PREFETCH(dp_packet_data(packets[i+1]));
7354
0
            pkt_metadata_prefetch_init(&packets[i+1]->md);
7355
0
        }
7356
7357
0
        if (!md_is_valid) {
7358
0
            pkt_metadata_init(&packet->md, port_no);
7359
0
        }
7360
7361
0
        if (offload_enabled && recirc_depth == 0) {
7362
0
            if (OVS_UNLIKELY(dp_netdev_hw_flow(pmd, packet, &flow))) {
7363
                /* Packet restoration failed and it was dropped, do not
7364
                 * continue processing.
7365
                 */
7366
0
                continue;
7367
0
            }
7368
0
            if (OVS_LIKELY(flow)) {
7369
0
                tcp_flags = parse_tcp_flags(packet, NULL, NULL, NULL);
7370
0
                n_phwol_hit++;
7371
0
                dfc_processing_enqueue_classified_packet(
7372
0
                        packet, flow, tcp_flags, batch_enable,
7373
0
                        batches, n_batches, flow_map, &map_cnt);
7374
0
                continue;
7375
0
            }
7376
0
        }
7377
7378
0
        if (!flow && simple_match_enabled) {
7379
0
            ovs_be16 dl_type = 0, vlan_tci = 0;
7380
0
            uint8_t nw_frag = 0;
7381
7382
0
            tcp_flags = parse_tcp_flags(packet, &dl_type, &nw_frag, &vlan_tci);
7383
0
            flow = dp_netdev_simple_match_lookup(pmd, port_no, dl_type,
7384
0
                                                 nw_frag, vlan_tci);
7385
0
            if (OVS_LIKELY(flow)) {
7386
0
                n_simple_hit++;
7387
0
                dfc_processing_enqueue_classified_packet(
7388
0
                        packet, flow, tcp_flags, batch_enable,
7389
0
                        batches, n_batches, flow_map, &map_cnt);
7390
0
                continue;
7391
0
            }
7392
0
        }
7393
7394
0
        miniflow_extract(packet, &key->mf);
7395
0
        key->len = 0; /* Not computed yet. */
7396
0
        key->hash =
7397
0
                (md_is_valid == false)
7398
0
                ? dpif_netdev_packet_get_rss_hash_orig_pkt(packet, &key->mf)
7399
0
                : dpif_netdev_packet_get_rss_hash(packet, &key->mf);
7400
7401
        /* If EMC is disabled skip emc_lookup */
7402
0
        flow = (cur_min != 0) ? emc_lookup(&cache->emc_cache, key) : NULL;
7403
0
        if (OVS_LIKELY(flow)) {
7404
0
            tcp_flags = miniflow_get_tcp_flags(&key->mf);
7405
0
            n_emc_hit++;
7406
0
            dfc_processing_enqueue_classified_packet(
7407
0
                    packet, flow, tcp_flags, batch_enable,
7408
0
                    batches, n_batches, flow_map, &map_cnt);
7409
0
        } else {
7410
            /* Exact match cache missed. Group missed packets together at
7411
             * the beginning of the 'packets' array. */
7412
0
            dp_packet_batch_add(packets_, packet);
7413
7414
            /* Preserve the order of packet for flow batching. */
7415
0
            index_map[n_missed] = map_cnt;
7416
0
            flow_map[map_cnt++].flow = NULL;
7417
7418
            /* 'key[n_missed]' contains the key of the current packet and it
7419
             * will be passed to SMC lookup. The next key should be extracted
7420
             * to 'keys[n_missed + 1]'.
7421
             * We also maintain a pointer array to keys missed both SMC and EMC
7422
             * which will be returned to the caller for future processing. */
7423
0
            missed_keys[n_missed] = key;
7424
0
            key = &keys[++n_missed];
7425
7426
            /* Skip batching for subsequent packets to avoid reordering. */
7427
0
            batch_enable = false;
7428
0
        }
7429
0
    }
7430
    /* Count of packets which are not flow batched. */
7431
0
    *n_flows = map_cnt;
7432
7433
0
    pmd_perf_update_counter(&pmd->perf_stats, PMD_STAT_PHWOL_HIT, n_phwol_hit);
7434
0
    pmd_perf_update_counter(&pmd->perf_stats, PMD_STAT_SIMPLE_HIT,
7435
0
                            n_simple_hit);
7436
0
    pmd_perf_update_counter(&pmd->perf_stats, PMD_STAT_EXACT_HIT, n_emc_hit);
7437
7438
0
    if (!smc_enable_db) {
7439
0
        return dp_packet_batch_size(packets_);
7440
0
    }
7441
7442
    /* Packets miss EMC will do a batch lookup in SMC if enabled */
7443
0
    smc_lookup_batch(pmd, keys, missed_keys, packets_,
7444
0
                     n_missed, flow_map, index_map);
7445
7446
0
    return dp_packet_batch_size(packets_);
7447
0
}
7448
7449
static inline int
7450
handle_packet_upcall(struct dp_netdev_pmd_thread *pmd,
7451
                     struct dp_packet *packet,
7452
                     const struct netdev_flow_key *key,
7453
                     struct ofpbuf *actions, struct ofpbuf *put_actions)
7454
0
{
7455
0
    struct ofpbuf *add_actions;
7456
0
    struct dp_packet_batch b;
7457
0
    struct match match;
7458
0
    ovs_u128 ufid;
7459
0
    int error;
7460
0
    uint64_t cycles = cycles_counter_update(&pmd->perf_stats);
7461
0
    odp_port_t orig_in_port = packet->md.orig_in_port;
7462
7463
0
    match.tun_md.valid = false;
7464
0
    miniflow_expand(&key->mf, &match.flow);
7465
0
    memset(&match.wc, 0, sizeof match.wc);
7466
7467
0
    ofpbuf_clear(actions);
7468
0
    ofpbuf_clear(put_actions);
7469
7470
0
    odp_flow_key_hash(&match.flow, sizeof match.flow, &ufid);
7471
0
    error = dp_netdev_upcall(pmd, packet, &match.flow, &match.wc,
7472
0
                             &ufid, DPIF_UC_MISS, NULL, actions,
7473
0
                             put_actions);
7474
0
    if (OVS_UNLIKELY(error && error != ENOSPC)) {
7475
0
        dp_packet_delete(packet);
7476
0
        COVERAGE_INC(datapath_drop_upcall_error);
7477
0
        return error;
7478
0
    }
7479
7480
    /* The Netlink encoding of datapath flow keys cannot express
7481
     * wildcarding the presence of a VLAN tag. Instead, a missing VLAN
7482
     * tag is interpreted as exact match on the fact that there is no
7483
     * VLAN.  Unless we refactor a lot of code that translates between
7484
     * Netlink and struct flow representations, we have to do the same
7485
     * here.  This must be in sync with 'match' in dpif_netdev_flow_put(). */
7486
0
    if (!match.wc.masks.vlans[0].tci) {
7487
0
        match.wc.masks.vlans[0].tci = htons(VLAN_VID_MASK | VLAN_CFI);
7488
0
    }
7489
7490
    /* We can't allow the packet batching in the next loop to execute
7491
     * the actions.  Otherwise, if there are any slow path actions,
7492
     * we'll send the packet up twice. */
7493
0
    dp_packet_batch_init_packet(&b, packet);
7494
0
    dp_netdev_execute_actions(pmd, &b, true, &match.flow,
7495
0
                              actions->data, actions->size);
7496
0
    dp_packet_batch_destroy(&b);
7497
7498
0
    add_actions = put_actions->size ? put_actions : actions;
7499
0
    if (OVS_LIKELY(error != ENOSPC)) {
7500
0
        struct dp_netdev_flow *netdev_flow;
7501
7502
        /* XXX: There's a race window where a flow covering this packet
7503
         * could have already been installed since we last did the flow
7504
         * lookup before upcall.  This could be solved by moving the
7505
         * mutex lock outside the loop, but that's an awful long time
7506
         * to be locking revalidators out of making flow modifications. */
7507
0
        ovs_mutex_lock(&pmd->flow_mutex);
7508
0
        netdev_flow = dp_netdev_pmd_lookup_flow(pmd, key, NULL);
7509
0
        if (OVS_LIKELY(!netdev_flow)) {
7510
0
            netdev_flow = dp_netdev_flow_add(pmd, &match, &ufid,
7511
0
                                             add_actions->data,
7512
0
                                             add_actions->size, orig_in_port);
7513
0
        }
7514
0
        ovs_mutex_unlock(&pmd->flow_mutex);
7515
0
        uint32_t hash = dp_netdev_flow_hash(&netdev_flow->ufid);
7516
0
        smc_insert(pmd, key, hash);
7517
0
        emc_probabilistic_insert(pmd, key, netdev_flow);
7518
0
    }
7519
0
    if (pmd_perf_metrics_enabled(pmd)) {
7520
        /* Update upcall stats. */
7521
0
        cycles = cycles_counter_update(&pmd->perf_stats) - cycles;
7522
0
        struct pmd_perf_stats *s = &pmd->perf_stats;
7523
0
        s->current.upcalls++;
7524
0
        s->current.upcall_cycles += cycles;
7525
0
        histogram_add_sample(&s->cycles_per_upcall, cycles);
7526
0
    }
7527
0
    return error;
7528
0
}
7529
7530
static inline void
7531
fast_path_processing(struct dp_netdev_pmd_thread *pmd,
7532
                     struct dp_packet_batch *packets_,
7533
                     struct netdev_flow_key **keys,
7534
                     struct dp_packet_flow_map *flow_map,
7535
                     uint8_t *index_map,
7536
                     odp_port_t in_port)
7537
0
{
7538
0
    const size_t cnt = dp_packet_batch_size(packets_);
7539
0
    struct dp_packet *packet;
7540
0
    struct dpcls *cls;
7541
0
    struct dpcls_rule *rules[NETDEV_MAX_BURST];
7542
0
    struct dp_netdev *dp = pmd->dp;
7543
0
    int upcall_ok_cnt = 0, upcall_fail_cnt = 0;
7544
0
    int lookup_cnt = 0, add_lookup_cnt;
7545
0
    bool any_miss;
7546
7547
0
    for (size_t i = 0; i < cnt; i++) {
7548
        /* Key length is needed in all the cases, hash computed on demand. */
7549
0
        keys[i]->len = netdev_flow_key_size(miniflow_n_values(&keys[i]->mf));
7550
0
    }
7551
    /* Get the classifier for the in_port */
7552
0
    cls = dp_netdev_pmd_lookup_dpcls(pmd, in_port);
7553
0
    if (OVS_LIKELY(cls)) {
7554
0
        any_miss = !dpcls_lookup(cls, (const struct netdev_flow_key **)keys,
7555
0
                                rules, cnt, &lookup_cnt);
7556
0
    } else {
7557
0
        any_miss = true;
7558
0
        memset(rules, 0, sizeof(rules));
7559
0
    }
7560
0
    if (OVS_UNLIKELY(any_miss) && !fat_rwlock_tryrdlock(&dp->upcall_rwlock)) {
7561
0
        uint64_t actions_stub[512 / 8], slow_stub[512 / 8];
7562
0
        struct ofpbuf actions, put_actions;
7563
7564
0
        ofpbuf_use_stub(&actions, actions_stub, sizeof actions_stub);
7565
0
        ofpbuf_use_stub(&put_actions, slow_stub, sizeof slow_stub);
7566
7567
0
        DP_PACKET_BATCH_FOR_EACH (i, packet, packets_) {
7568
0
            struct dp_netdev_flow *netdev_flow;
7569
7570
0
            if (OVS_LIKELY(rules[i])) {
7571
0
                continue;
7572
0
            }
7573
7574
            /* It's possible that an earlier slow path execution installed
7575
             * a rule covering this flow.  In this case, it's a lot cheaper
7576
             * to catch it here than execute a miss. */
7577
0
            netdev_flow = dp_netdev_pmd_lookup_flow(pmd, keys[i],
7578
0
                                                    &add_lookup_cnt);
7579
0
            if (netdev_flow) {
7580
0
                lookup_cnt += add_lookup_cnt;
7581
0
                rules[i] = &netdev_flow->cr;
7582
0
                continue;
7583
0
            }
7584
7585
0
            int error = handle_packet_upcall(pmd, packet, keys[i],
7586
0
                                             &actions, &put_actions);
7587
7588
0
            if (OVS_UNLIKELY(error)) {
7589
0
                upcall_fail_cnt++;
7590
0
            } else {
7591
0
                upcall_ok_cnt++;
7592
0
            }
7593
0
        }
7594
7595
0
        ofpbuf_uninit(&actions);
7596
0
        ofpbuf_uninit(&put_actions);
7597
0
        fat_rwlock_unlock(&dp->upcall_rwlock);
7598
0
    } else if (OVS_UNLIKELY(any_miss)) {
7599
0
        DP_PACKET_BATCH_FOR_EACH (i, packet, packets_) {
7600
0
            if (OVS_UNLIKELY(!rules[i])) {
7601
0
                dp_packet_delete(packet);
7602
0
                COVERAGE_INC(datapath_drop_lock_error);
7603
0
                upcall_fail_cnt++;
7604
0
            }
7605
0
        }
7606
0
    }
7607
7608
0
    DP_PACKET_BATCH_FOR_EACH (i, packet, packets_) {
7609
0
        struct dp_netdev_flow *flow;
7610
        /* Get the original order of this packet in received batch. */
7611
0
        int recv_idx = index_map[i];
7612
0
        uint16_t tcp_flags;
7613
7614
0
        if (OVS_UNLIKELY(!rules[i])) {
7615
0
            continue;
7616
0
        }
7617
7618
0
        flow = dp_netdev_flow_cast(rules[i]);
7619
0
        uint32_t hash =  dp_netdev_flow_hash(&flow->ufid);
7620
0
        smc_insert(pmd, keys[i], hash);
7621
7622
0
        emc_probabilistic_insert(pmd, keys[i], flow);
7623
        /* Add these packets into the flow map in the same order
7624
         * as received.
7625
         */
7626
0
        tcp_flags = miniflow_get_tcp_flags(&keys[i]->mf);
7627
0
        packet_enqueue_to_flow_map(packet, flow, tcp_flags,
7628
0
                                   flow_map, recv_idx);
7629
0
    }
7630
7631
0
    pmd_perf_update_counter(&pmd->perf_stats, PMD_STAT_MASKED_HIT,
7632
0
                            cnt - upcall_ok_cnt - upcall_fail_cnt);
7633
0
    pmd_perf_update_counter(&pmd->perf_stats, PMD_STAT_MASKED_LOOKUP,
7634
0
                            lookup_cnt);
7635
0
    pmd_perf_update_counter(&pmd->perf_stats, PMD_STAT_MISS,
7636
0
                            upcall_ok_cnt);
7637
0
    pmd_perf_update_counter(&pmd->perf_stats, PMD_STAT_LOST,
7638
0
                            upcall_fail_cnt);
7639
0
}
7640
7641
/* Packets enter the datapath from a port (or from recirculation) here.
7642
 *
7643
 * When 'md_is_valid' is true the metadata in 'packets' are already valid.
7644
 * When false the metadata in 'packets' need to be initialized. */
7645
static void
7646
dp_netdev_input__(struct dp_netdev_pmd_thread *pmd,
7647
                  struct dp_packet_batch *packets,
7648
                  bool md_is_valid, odp_port_t port_no)
7649
0
{
7650
0
    OVS_ALIGNED_VAR(CACHE_LINE_SIZE)
7651
0
        struct netdev_flow_key keys[NETDEV_MAX_BURST];
7652
0
    struct netdev_flow_key *missed_keys[NETDEV_MAX_BURST];
7653
0
    struct packet_batch_per_flow batches[NETDEV_MAX_BURST];
7654
0
    size_t n_batches;
7655
0
    struct dp_packet_flow_map flow_map[NETDEV_MAX_BURST];
7656
0
    uint8_t index_map[NETDEV_MAX_BURST];
7657
0
    size_t n_flows, i;
7658
7659
0
    odp_port_t in_port;
7660
7661
0
    n_batches = 0;
7662
0
    dfc_processing(pmd, packets, keys, missed_keys, batches, &n_batches,
7663
0
                   flow_map, &n_flows, index_map, md_is_valid, port_no);
7664
7665
0
    if (!dp_packet_batch_is_empty(packets)) {
7666
        /* Get ingress port from first packet's metadata. */
7667
0
        in_port = packets->packets[0]->md.in_port.odp_port;
7668
0
        fast_path_processing(pmd, packets, missed_keys,
7669
0
                             flow_map, index_map, in_port);
7670
0
    }
7671
7672
    /* Batch rest of packets which are in flow map. */
7673
0
    for (i = 0; i < n_flows; i++) {
7674
0
        struct dp_packet_flow_map *map = &flow_map[i];
7675
7676
0
        if (OVS_UNLIKELY(!map->flow)) {
7677
0
            continue;
7678
0
        }
7679
0
        dp_netdev_queue_batches(map->packet, map->flow, map->tcp_flags,
7680
0
                                batches, &n_batches);
7681
0
     }
7682
7683
    /* All the flow batches need to be reset before any call to
7684
     * packet_batch_per_flow_execute() as it could potentially trigger
7685
     * recirculation. When a packet matching flow 'j' happens to be
7686
     * recirculated, the nested call to dp_netdev_input__() could potentially
7687
     * classify the packet as matching another flow - say 'k'. It could happen
7688
     * that in the previous call to dp_netdev_input__() that same flow 'k' had
7689
     * already its own batches[k] still waiting to be served.  So if its
7690
     * 'batch' member is not reset, the recirculated packet would be wrongly
7691
     * appended to batches[k] of the 1st call to dp_netdev_input__(). */
7692
0
    for (i = 0; i < n_batches; i++) {
7693
0
        batches[i].flow->batch = NULL;
7694
0
    }
7695
7696
0
    for (i = 0; i < n_batches; i++) {
7697
0
        packet_batch_per_flow_execute(&batches[i], pmd);
7698
0
        dp_packet_batch_destroy(&batches[i].array);
7699
0
    }
7700
0
}
7701
7702
static void
7703
dp_netdev_input(struct dp_netdev_pmd_thread *pmd,
7704
                struct dp_packet_batch *packets,
7705
                odp_port_t port_no)
7706
0
{
7707
0
    dp_netdev_input__(pmd, packets, false, port_no);
7708
0
}
7709
7710
static void
7711
dp_netdev_recirculate(struct dp_netdev_pmd_thread *pmd,
7712
                      struct dp_packet_batch *packets)
7713
0
{
7714
0
    if (dp_packet_batch_size(packets) > NETDEV_MAX_BURST) {
7715
0
        struct dp_packet_batch smaller_batch;
7716
0
        size_t processed = 0;
7717
0
        size_t batch_cnt;
7718
7719
0
        COVERAGE_INC(dpif_netdev_recirc_big_batch);
7720
0
        batch_cnt = dp_packet_batch_size(packets);
7721
0
        dp_packet_batch_init(&smaller_batch);
7722
7723
0
        do {
7724
0
            size_t count = MIN(batch_cnt - processed, NETDEV_MAX_BURST);
7725
7726
0
            dp_packet_batch_reset(&smaller_batch);
7727
0
            smaller_batch.trunc = packets->trunc;
7728
0
            dp_packet_batch_add_array(&smaller_batch,
7729
0
                                      &packets->packets[processed], count);
7730
0
            dp_netdev_input__(pmd, &smaller_batch, true, 0);
7731
0
            processed += count;
7732
7733
0
        } while (processed < batch_cnt);
7734
7735
0
        dp_packet_batch_destroy(&smaller_batch);
7736
0
        return;
7737
0
    }
7738
7739
0
    dp_netdev_input__(pmd, packets, true, 0);
7740
0
}
7741
7742
struct dp_netdev_execute_aux {
7743
    struct dp_netdev_pmd_thread *pmd;
7744
    const struct flow *flow;
7745
};
7746
7747
static void
7748
dpif_netdev_register_dp_purge_cb(struct dpif *dpif, dp_purge_callback *cb,
7749
                                 void *aux)
7750
0
{
7751
0
    struct dp_netdev *dp = get_dp_netdev(dpif);
7752
0
    dp->dp_purge_aux = aux;
7753
0
    dp->dp_purge_cb = cb;
7754
0
}
7755
7756
static void
7757
dpif_netdev_register_upcall_cb(struct dpif *dpif, upcall_callback *cb,
7758
                               void *aux)
7759
0
{
7760
0
    struct dp_netdev *dp = get_dp_netdev(dpif);
7761
0
    dp->upcall_aux = aux;
7762
0
    dp->upcall_cb = cb;
7763
0
}
7764
7765
static void
7766
dpif_netdev_xps_revalidate_pmd(const struct dp_netdev_pmd_thread *pmd,
7767
                               bool purge)
7768
0
{
7769
0
    struct tx_port *tx;
7770
0
    struct dp_netdev_port *port;
7771
0
    long long interval;
7772
7773
0
    HMAP_FOR_EACH (tx, node, &pmd->send_port_cache) {
7774
0
        if (tx->port->txq_mode != TXQ_MODE_XPS) {
7775
0
            continue;
7776
0
        }
7777
0
        interval = pmd->ctx.now - tx->last_used;
7778
0
        if (tx->qid >= 0 && (purge || interval >= XPS_TIMEOUT)) {
7779
0
            port = tx->port;
7780
0
            ovs_mutex_lock(&port->txq_used_mutex);
7781
0
            port->txq_used[tx->qid]--;
7782
0
            ovs_mutex_unlock(&port->txq_used_mutex);
7783
0
            tx->qid = -1;
7784
0
        }
7785
0
    }
7786
0
}
7787
7788
static int
7789
dpif_netdev_xps_get_tx_qid(const struct dp_netdev_pmd_thread *pmd,
7790
                           struct tx_port *tx)
7791
0
{
7792
0
    struct dp_netdev_port *port;
7793
0
    long long interval;
7794
0
    int i, min_cnt, min_qid;
7795
7796
0
    interval = pmd->ctx.now - tx->last_used;
7797
0
    tx->last_used = pmd->ctx.now;
7798
7799
0
    if (OVS_LIKELY(tx->qid >= 0 && interval < XPS_TIMEOUT)) {
7800
0
        return tx->qid;
7801
0
    }
7802
7803
0
    port = tx->port;
7804
7805
0
    ovs_mutex_lock(&port->txq_used_mutex);
7806
0
    if (tx->qid >= 0) {
7807
0
        port->txq_used[tx->qid]--;
7808
0
        tx->qid = -1;
7809
0
    }
7810
7811
0
    min_cnt = -1;
7812
0
    min_qid = 0;
7813
0
    for (i = 0; i < netdev_n_txq(port->netdev); i++) {
7814
0
        if (port->txq_used[i] < min_cnt || min_cnt == -1) {
7815
0
            min_cnt = port->txq_used[i];
7816
0
            min_qid = i;
7817
0
        }
7818
0
    }
7819
7820
0
    port->txq_used[min_qid]++;
7821
0
    tx->qid = min_qid;
7822
7823
0
    ovs_mutex_unlock(&port->txq_used_mutex);
7824
7825
0
    dpif_netdev_xps_revalidate_pmd(pmd, false);
7826
7827
0
    VLOG_DBG("Core %d: New TX queue ID %d for port \'%s\'.",
7828
0
             pmd->core_id, tx->qid, netdev_get_name(tx->port->netdev));
7829
0
    return min_qid;
7830
0
}
7831
7832
static struct tx_port *
7833
pmd_tnl_port_cache_lookup(const struct dp_netdev_pmd_thread *pmd,
7834
                          odp_port_t port_no)
7835
0
{
7836
0
    return tx_port_lookup(&pmd->tnl_port_cache, port_no);
7837
0
}
7838
7839
static struct tx_port *
7840
pmd_send_port_cache_lookup(const struct dp_netdev_pmd_thread *pmd,
7841
                           odp_port_t port_no)
7842
0
{
7843
0
    return tx_port_lookup(&pmd->send_port_cache, port_no);
7844
0
}
7845
7846
static int
7847
push_tnl_action(const struct dp_netdev_pmd_thread *pmd,
7848
                const struct nlattr *attr,
7849
                struct dp_packet_batch *batch)
7850
0
{
7851
0
    const struct netdev *ingress_netdev = NULL;
7852
0
    const struct ovs_action_push_tnl *data;
7853
0
    struct tx_port *tun_port;
7854
0
    int err;
7855
7856
0
    data = nl_attr_get(attr);
7857
7858
0
    tun_port = pmd_tnl_port_cache_lookup(pmd, data->tnl_port);
7859
0
    if (!tun_port) {
7860
0
        err = -EINVAL;
7861
0
        goto error;
7862
0
    }
7863
7864
0
    if (dpif_offload_enabled() && !dp_packet_batch_is_empty(batch)) {
7865
        /* To avoid multiple port lookups per batch, assume that all packets
7866
         * in the batch originate from the same flow and therefore share the
7867
         * same original input port. */
7868
0
        struct tx_port *in_port = pmd_send_port_cache_lookup(
7869
0
                                      pmd, batch->packets[0]->md.orig_in_port);
7870
0
        if (in_port) {
7871
0
            ingress_netdev = in_port->port->netdev;
7872
0
        }
7873
0
    }
7874
7875
0
    err = netdev_push_header(tun_port->port->netdev, ingress_netdev, batch,
7876
0
                             data);
7877
0
    if (!err) {
7878
0
        return 0;
7879
0
    }
7880
0
error:
7881
0
    dp_packet_delete_batch(batch, true);
7882
0
    return err;
7883
0
}
7884
7885
static void
7886
dp_execute_userspace_action(struct dp_netdev_pmd_thread *pmd,
7887
                            struct dp_packet *packet, bool should_steal,
7888
                            struct flow *flow, ovs_u128 *ufid,
7889
                            struct ofpbuf *actions,
7890
                            const struct nlattr *userdata)
7891
0
{
7892
0
    struct dp_packet_batch b;
7893
0
    int error;
7894
7895
0
    ofpbuf_clear(actions);
7896
7897
0
    error = dp_netdev_upcall(pmd, packet, flow, NULL, ufid,
7898
0
                             DPIF_UC_ACTION, userdata, actions,
7899
0
                             NULL);
7900
0
    if (!error || error == ENOSPC) {
7901
0
        dp_packet_batch_init_packet(&b, packet);
7902
0
        dp_netdev_execute_actions(pmd, &b, should_steal, flow,
7903
0
                                  actions->data, actions->size);
7904
0
        dp_packet_batch_destroy(&b);
7905
0
    } else if (should_steal) {
7906
0
        dp_packet_delete(packet);
7907
0
        COVERAGE_INC(datapath_drop_userspace_action_error);
7908
0
    }
7909
0
}
7910
7911
static bool
7912
dp_execute_output_action(struct dp_netdev_pmd_thread *pmd,
7913
                         struct dp_packet_batch *packets_,
7914
                         bool should_steal, odp_port_t port_no)
7915
0
{
7916
0
    struct tx_port *p = pmd_send_port_cache_lookup(pmd, port_no);
7917
0
    size_t batch_cnt = dp_packet_batch_size(packets_);
7918
0
    size_t output_batch_capacity;
7919
0
    struct dp_packet_batch out;
7920
0
    size_t output_batch_size;
7921
7922
0
    if (!OVS_LIKELY(p)) {
7923
0
        COVERAGE_ADD(datapath_drop_invalid_port, batch_cnt);
7924
0
        dp_packet_delete_batch(packets_, should_steal);
7925
0
        return false;
7926
0
    }
7927
0
    if (!should_steal) {
7928
0
        dp_packet_batch_clone(&out, packets_);
7929
0
        dp_packet_batch_reset_cutlen(packets_);
7930
0
        packets_ = &out;
7931
0
    }
7932
0
    dp_packet_batch_apply_cutlen(packets_);
7933
7934
0
    output_batch_capacity = dp_packet_batch_capacity(&p->output_pkts);
7935
0
    output_batch_size = dp_packet_batch_size(&p->output_pkts);
7936
0
    if (!output_batch_size) {
7937
0
        pmd->n_output_batches++;
7938
0
    }
7939
7940
0
    dp_packet_batch_add_array(&p->output_pkts, packets_->packets, batch_cnt);
7941
0
    if (OVS_UNLIKELY(output_batch_capacity
7942
0
                     != dp_packet_batch_capacity(&p->output_pkts))) {
7943
0
        COVERAGE_INC(dpif_netdev_output_grow_queues);
7944
0
        p->output_pkts_rxqs =
7945
0
            xrealloc(p->output_pkts_rxqs,
7946
0
                     dp_packet_batch_capacity(&p->output_pkts)
7947
0
                     * sizeof *p->output_pkts_rxqs);
7948
0
    }
7949
7950
0
    for (unsigned i = 0; i < batch_cnt; i++) {
7951
0
        p->output_pkts_rxqs[output_batch_size + i] = pmd->ctx.last_rxq;
7952
0
    }
7953
7954
0
    if (!should_steal) {
7955
0
        dp_packet_batch_destroy(&out);
7956
0
    }
7957
0
    return true;
7958
0
}
7959
7960
static void
7961
dp_execute_lb_output_action(struct dp_netdev_pmd_thread *pmd,
7962
                            struct dp_packet_batch *packets_,
7963
                            bool should_steal, uint32_t bond)
7964
0
{
7965
0
    struct tx_bond *p_bond = tx_bond_lookup(&pmd->tx_bonds, bond);
7966
0
    struct dp_packet_batch out;
7967
0
    struct dp_packet *packet;
7968
7969
0
    if (!p_bond) {
7970
0
        COVERAGE_ADD(datapath_drop_invalid_bond,
7971
0
                     dp_packet_batch_size(packets_));
7972
0
        dp_packet_delete_batch(packets_, should_steal);
7973
0
        return;
7974
0
    }
7975
0
    if (!should_steal) {
7976
0
        dp_packet_batch_clone(&out, packets_);
7977
0
        dp_packet_batch_reset_cutlen(packets_);
7978
0
        packets_ = &out;
7979
0
    }
7980
0
    dp_packet_batch_apply_cutlen(packets_);
7981
7982
0
    DP_PACKET_BATCH_FOR_EACH (i, packet, packets_) {
7983
        /*
7984
         * Lookup the bond-hash table using hash to get the member.
7985
         */
7986
0
        uint32_t hash = dp_packet_get_rss_hash(packet);
7987
0
        struct member_entry *s_entry
7988
0
            = &p_bond->member_buckets[hash & BOND_MASK];
7989
0
        odp_port_t bond_member = s_entry->member_id;
7990
0
        uint32_t size = dp_packet_size(packet);
7991
0
        struct dp_packet_batch output_pkt;
7992
7993
0
        dp_packet_batch_init_packet(&output_pkt, packet);
7994
0
        if (OVS_LIKELY(dp_execute_output_action(pmd, &output_pkt, true,
7995
0
                                                bond_member))) {
7996
            /* Update member stats. */
7997
0
            non_atomic_ullong_add(&s_entry->n_packets, 1);
7998
0
            non_atomic_ullong_add(&s_entry->n_bytes, size);
7999
0
        }
8000
0
        dp_packet_batch_destroy(&output_pkt);
8001
0
    }
8002
8003
0
    if (!should_steal) {
8004
0
        dp_packet_batch_destroy(&out);
8005
0
    }
8006
0
}
8007
8008
static void
8009
dp_execute_cb(void *aux_, struct dp_packet_batch *packets_,
8010
              const struct nlattr *a, bool should_steal)
8011
    OVS_NO_THREAD_SAFETY_ANALYSIS
8012
0
{
8013
0
    struct dp_netdev_execute_aux *aux = aux_;
8014
0
    uint32_t *depth = recirc_depth_get();
8015
0
    struct dp_netdev_pmd_thread *pmd = aux->pmd;
8016
0
    struct dp_netdev *dp = pmd->dp;
8017
0
    int type = nl_attr_type(a);
8018
0
    struct tx_port *p;
8019
0
    uint32_t packet_count, packets_dropped;
8020
8021
0
    switch ((enum ovs_action_attr)type) {
8022
0
    case OVS_ACTION_ATTR_OUTPUT:
8023
0
        dp_execute_output_action(pmd, packets_, should_steal,
8024
0
                                 nl_attr_get_odp_port(a));
8025
0
        return;
8026
8027
0
    case OVS_ACTION_ATTR_LB_OUTPUT:
8028
0
        dp_execute_lb_output_action(pmd, packets_, should_steal,
8029
0
                                    nl_attr_get_u32(a));
8030
0
        return;
8031
8032
0
    case OVS_ACTION_ATTR_TUNNEL_PUSH:
8033
0
        if (should_steal) {
8034
            /* We're requested to push tunnel header, but also we need to take
8035
             * the ownership of these packets. Thus, we can avoid performing
8036
             * the action, because the caller will not use the result anyway.
8037
             * Just break to free the batch. */
8038
0
            break;
8039
0
        }
8040
0
        dp_packet_batch_apply_cutlen(packets_);
8041
0
        packet_count = dp_packet_batch_size(packets_);
8042
0
        if (push_tnl_action(pmd, a, packets_)) {
8043
0
            COVERAGE_ADD(datapath_drop_tunnel_push_error,
8044
0
                         packet_count);
8045
0
        }
8046
0
        return;
8047
8048
0
    case OVS_ACTION_ATTR_TUNNEL_POP:
8049
0
        if (*depth < MAX_RECIRC_DEPTH) {
8050
0
            struct dp_packet_batch *orig_packets_ = packets_;
8051
0
            odp_port_t portno = nl_attr_get_odp_port(a);
8052
8053
0
            p = pmd_tnl_port_cache_lookup(pmd, portno);
8054
0
            if (p) {
8055
0
                struct dp_packet_batch tnl_pkt;
8056
8057
0
                if (!should_steal) {
8058
0
                    dp_packet_batch_clone(&tnl_pkt, packets_);
8059
0
                    packets_ = &tnl_pkt;
8060
0
                    dp_packet_batch_reset_cutlen(orig_packets_);
8061
0
                }
8062
8063
0
                dp_packet_batch_apply_cutlen(packets_);
8064
8065
0
                packet_count = dp_packet_batch_size(packets_);
8066
0
                netdev_pop_header(p->port->netdev, packets_);
8067
0
                packets_dropped =
8068
0
                   packet_count - dp_packet_batch_size(packets_);
8069
0
                if (packets_dropped) {
8070
0
                    COVERAGE_ADD(datapath_drop_tunnel_pop_error,
8071
0
                                 packets_dropped);
8072
0
                }
8073
0
                if (dp_packet_batch_is_empty(packets_)) {
8074
0
                    if (!should_steal) {
8075
0
                        dp_packet_batch_destroy(&tnl_pkt);
8076
0
                    }
8077
0
                    return;
8078
0
                }
8079
8080
0
                struct dp_packet *packet;
8081
0
                DP_PACKET_BATCH_FOR_EACH (i, packet, packets_) {
8082
0
                    packet->md.in_port.odp_port = portno;
8083
0
                }
8084
8085
0
                (*depth)++;
8086
0
                dp_netdev_recirculate(pmd, packets_);
8087
0
                (*depth)--;
8088
8089
0
                if (!should_steal) {
8090
0
                    dp_packet_batch_destroy(&tnl_pkt);
8091
0
                }
8092
0
                return;
8093
0
            }
8094
0
            COVERAGE_ADD(datapath_drop_invalid_tnl_port,
8095
0
                         dp_packet_batch_size(packets_));
8096
0
        } else {
8097
0
            COVERAGE_ADD(datapath_drop_recirc_error,
8098
0
                         dp_packet_batch_size(packets_));
8099
0
        }
8100
0
        break;
8101
8102
0
    case OVS_ACTION_ATTR_USERSPACE:
8103
0
        if (!fat_rwlock_tryrdlock(&dp->upcall_rwlock)) {
8104
0
            struct dp_packet_batch *orig_packets_ = packets_;
8105
0
            const struct nlattr *userdata;
8106
0
            struct dp_packet_batch usr_pkt;
8107
0
            struct ofpbuf actions;
8108
0
            struct flow flow;
8109
0
            ovs_u128 ufid;
8110
0
            bool clone = false;
8111
8112
0
            userdata = nl_attr_find_nested(a, OVS_USERSPACE_ATTR_USERDATA);
8113
0
            ofpbuf_init(&actions, 0);
8114
8115
0
            if (packets_->trunc) {
8116
0
                if (!should_steal) {
8117
0
                    dp_packet_batch_clone(&usr_pkt, packets_);
8118
0
                    packets_ = &usr_pkt;
8119
0
                    clone = true;
8120
0
                    dp_packet_batch_reset_cutlen(orig_packets_);
8121
0
                }
8122
8123
0
                dp_packet_batch_apply_cutlen(packets_);
8124
0
            }
8125
8126
0
            struct dp_packet *packet;
8127
0
            DP_PACKET_BATCH_FOR_EACH (i, packet, packets_) {
8128
0
                flow_extract(packet, &flow);
8129
0
                odp_flow_key_hash(&flow, sizeof flow, &ufid);
8130
0
                dp_execute_userspace_action(pmd, packet, should_steal, &flow,
8131
0
                                            &ufid, &actions, userdata);
8132
0
            }
8133
8134
0
            if (clone) {
8135
0
                dp_packet_delete_batch(&usr_pkt, true);
8136
0
                dp_packet_batch_destroy(&usr_pkt);
8137
0
            }
8138
8139
0
            ofpbuf_uninit(&actions);
8140
0
            fat_rwlock_unlock(&dp->upcall_rwlock);
8141
8142
0
            return;
8143
0
        }
8144
0
        COVERAGE_ADD(datapath_drop_lock_error,
8145
0
                     dp_packet_batch_size(packets_));
8146
0
        break;
8147
8148
0
    case OVS_ACTION_ATTR_RECIRC:
8149
0
        if (*depth < MAX_RECIRC_DEPTH) {
8150
0
            struct dp_packet_batch recirc_pkts;
8151
8152
0
            if (!should_steal) {
8153
0
               dp_packet_batch_clone(&recirc_pkts, packets_);
8154
0
               packets_ = &recirc_pkts;
8155
0
            }
8156
8157
0
            struct dp_packet *packet;
8158
0
            DP_PACKET_BATCH_FOR_EACH (i, packet, packets_) {
8159
0
                packet->md.recirc_id = nl_attr_get_u32(a);
8160
0
            }
8161
8162
0
            (*depth)++;
8163
0
            dp_netdev_recirculate(pmd, packets_);
8164
0
            (*depth)--;
8165
8166
0
            if (!should_steal) {
8167
0
                dp_packet_batch_destroy(&recirc_pkts);
8168
0
            }
8169
0
            return;
8170
0
        }
8171
8172
0
        COVERAGE_ADD(datapath_drop_recirc_error,
8173
0
                     dp_packet_batch_size(packets_));
8174
0
        VLOG_WARN("Packet dropped. Max recirculation depth exceeded.");
8175
0
        break;
8176
8177
0
    case OVS_ACTION_ATTR_CT: {
8178
0
        const struct nlattr *b;
8179
0
        bool force = false;
8180
0
        bool commit = false;
8181
0
        unsigned int left;
8182
0
        uint16_t zone = 0;
8183
0
        uint32_t tp_id = 0;
8184
0
        const char *helper = NULL;
8185
0
        const uint32_t *setmark = NULL;
8186
0
        const struct ovs_key_ct_labels *setlabel = NULL;
8187
0
        struct nat_action_info_t nat_action_info;
8188
0
        struct nat_action_info_t *nat_action_info_ref = NULL;
8189
0
        bool nat_config = false;
8190
8191
0
        NL_ATTR_FOR_EACH_UNSAFE (b, left, nl_attr_get(a),
8192
0
                                 nl_attr_get_size(a)) {
8193
0
            enum ovs_ct_attr sub_type = nl_attr_type(b);
8194
8195
0
            switch(sub_type) {
8196
0
            case OVS_CT_ATTR_FORCE_COMMIT:
8197
0
                force = true;
8198
                /* fall through. */
8199
0
            case OVS_CT_ATTR_COMMIT:
8200
0
                commit = true;
8201
0
                break;
8202
0
            case OVS_CT_ATTR_ZONE:
8203
0
                zone = nl_attr_get_u16(b);
8204
0
                break;
8205
0
            case OVS_CT_ATTR_HELPER:
8206
0
                helper = nl_attr_get_string(b);
8207
0
                break;
8208
0
            case OVS_CT_ATTR_MARK:
8209
0
                setmark = nl_attr_get(b);
8210
0
                break;
8211
0
            case OVS_CT_ATTR_LABELS:
8212
0
                setlabel = nl_attr_get(b);
8213
0
                break;
8214
0
            case OVS_CT_ATTR_EVENTMASK:
8215
                /* Silently ignored, as userspace datapath does not generate
8216
                 * netlink events. */
8217
0
                break;
8218
0
            case OVS_CT_ATTR_TIMEOUT:
8219
0
                if (!str_to_uint(nl_attr_get_string(b), 10, &tp_id)) {
8220
0
                    VLOG_WARN("Invalid Timeout Policy ID: %s.",
8221
0
                              nl_attr_get_string(b));
8222
0
                    tp_id = DEFAULT_TP_ID;
8223
0
                }
8224
0
                break;
8225
0
            case OVS_CT_ATTR_NAT: {
8226
0
                const struct nlattr *b_nest;
8227
0
                unsigned int left_nest;
8228
0
                bool ip_min_specified = false;
8229
0
                bool proto_num_min_specified = false;
8230
0
                bool ip_max_specified = false;
8231
0
                bool proto_num_max_specified = false;
8232
0
                memset(&nat_action_info, 0, sizeof nat_action_info);
8233
0
                nat_action_info_ref = &nat_action_info;
8234
8235
0
                NL_NESTED_FOR_EACH_UNSAFE (b_nest, left_nest, b) {
8236
0
                    enum ovs_nat_attr sub_type_nest = nl_attr_type(b_nest);
8237
8238
0
                    switch (sub_type_nest) {
8239
0
                    case OVS_NAT_ATTR_SRC:
8240
0
                    case OVS_NAT_ATTR_DST:
8241
0
                        nat_config = true;
8242
0
                        nat_action_info.nat_action |=
8243
0
                            ((sub_type_nest == OVS_NAT_ATTR_SRC)
8244
0
                                ? NAT_ACTION_SRC : NAT_ACTION_DST);
8245
0
                        break;
8246
0
                    case OVS_NAT_ATTR_IP_MIN:
8247
0
                        memcpy(&nat_action_info.min_addr,
8248
0
                               nl_attr_get(b_nest),
8249
0
                               nl_attr_get_size(b_nest));
8250
0
                        ip_min_specified = true;
8251
0
                        break;
8252
0
                    case OVS_NAT_ATTR_IP_MAX:
8253
0
                        memcpy(&nat_action_info.max_addr,
8254
0
                               nl_attr_get(b_nest),
8255
0
                               nl_attr_get_size(b_nest));
8256
0
                        ip_max_specified = true;
8257
0
                        break;
8258
0
                    case OVS_NAT_ATTR_PROTO_MIN:
8259
0
                        nat_action_info.min_port =
8260
0
                            nl_attr_get_u16(b_nest);
8261
0
                        proto_num_min_specified = true;
8262
0
                        break;
8263
0
                    case OVS_NAT_ATTR_PROTO_MAX:
8264
0
                        nat_action_info.max_port =
8265
0
                            nl_attr_get_u16(b_nest);
8266
0
                        proto_num_max_specified = true;
8267
0
                        break;
8268
0
                    case OVS_NAT_ATTR_PROTO_RANDOM:
8269
0
                        nat_action_info.nat_flags |= NAT_RANGE_RANDOM;
8270
0
                        break;
8271
0
                    case OVS_NAT_ATTR_PERSISTENT:
8272
0
                        nat_action_info.nat_flags |= NAT_PERSISTENT;
8273
0
                        break;
8274
0
                    case OVS_NAT_ATTR_PROTO_HASH:
8275
0
                        break;
8276
0
                    case OVS_NAT_ATTR_UNSPEC:
8277
0
                    case __OVS_NAT_ATTR_MAX:
8278
0
                        OVS_NOT_REACHED();
8279
0
                    }
8280
0
                }
8281
8282
0
                if (ip_min_specified && !ip_max_specified) {
8283
0
                    nat_action_info.max_addr = nat_action_info.min_addr;
8284
0
                }
8285
0
                if (proto_num_min_specified && !proto_num_max_specified) {
8286
0
                    nat_action_info.max_port = nat_action_info.min_port;
8287
0
                }
8288
0
                if (proto_num_min_specified || proto_num_max_specified) {
8289
0
                    if (nat_action_info.nat_action & NAT_ACTION_SRC) {
8290
0
                        nat_action_info.nat_action |= NAT_ACTION_SRC_PORT;
8291
0
                    } else if (nat_action_info.nat_action & NAT_ACTION_DST) {
8292
0
                        nat_action_info.nat_action |= NAT_ACTION_DST_PORT;
8293
0
                    }
8294
0
                }
8295
0
                break;
8296
0
            }
8297
0
            case OVS_CT_ATTR_UNSPEC:
8298
0
            case __OVS_CT_ATTR_MAX:
8299
0
                OVS_NOT_REACHED();
8300
0
            }
8301
0
        }
8302
8303
        /* We won't be able to function properly in this case, hence
8304
         * complain loudly. */
8305
0
        if (nat_config && !commit) {
8306
0
            static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 5);
8307
0
            VLOG_WARN_RL(&rl, "NAT specified without commit.");
8308
0
        }
8309
8310
0
        conntrack_execute(dp->conntrack, packets_, aux->flow->dl_type, force,
8311
0
                          commit, zone, setmark, setlabel, helper,
8312
0
                          nat_action_info_ref, pmd->ctx.now / 1000, tp_id);
8313
0
        break;
8314
0
    }
8315
8316
0
    case OVS_ACTION_ATTR_METER:
8317
0
        dp_netdev_run_meter(pmd->dp, packets_, nl_attr_get_u32(a),
8318
0
                            pmd->ctx.now / 1000);
8319
0
        break;
8320
8321
0
    case OVS_ACTION_ATTR_PUSH_VLAN:
8322
0
    case OVS_ACTION_ATTR_POP_VLAN:
8323
0
    case OVS_ACTION_ATTR_PUSH_MPLS:
8324
0
    case OVS_ACTION_ATTR_POP_MPLS:
8325
0
    case OVS_ACTION_ATTR_SET:
8326
0
    case OVS_ACTION_ATTR_SET_MASKED:
8327
0
    case OVS_ACTION_ATTR_SAMPLE:
8328
0
    case OVS_ACTION_ATTR_HASH:
8329
0
    case OVS_ACTION_ATTR_UNSPEC:
8330
0
    case OVS_ACTION_ATTR_TRUNC:
8331
0
    case OVS_ACTION_ATTR_PUSH_ETH:
8332
0
    case OVS_ACTION_ATTR_POP_ETH:
8333
0
    case OVS_ACTION_ATTR_CLONE:
8334
0
    case OVS_ACTION_ATTR_PUSH_NSH:
8335
0
    case OVS_ACTION_ATTR_POP_NSH:
8336
0
    case OVS_ACTION_ATTR_CT_CLEAR:
8337
0
    case OVS_ACTION_ATTR_CHECK_PKT_LEN:
8338
0
    case OVS_ACTION_ATTR_DROP:
8339
0
    case OVS_ACTION_ATTR_ADD_MPLS:
8340
0
    case OVS_ACTION_ATTR_DEC_TTL:
8341
0
    case OVS_ACTION_ATTR_PSAMPLE:
8342
0
    case __OVS_ACTION_ATTR_MAX:
8343
0
        OVS_NOT_REACHED();
8344
0
    }
8345
8346
0
    dp_packet_delete_batch(packets_, should_steal);
8347
0
}
8348
8349
static void
8350
dp_netdev_execute_actions(struct dp_netdev_pmd_thread *pmd,
8351
                          struct dp_packet_batch *packets,
8352
                          bool should_steal, const struct flow *flow,
8353
                          const struct nlattr *actions, size_t actions_len)
8354
0
{
8355
0
    struct dp_netdev_execute_aux aux = { pmd, flow };
8356
8357
0
    odp_execute_actions(&aux, packets, should_steal, actions,
8358
0
                        actions_len, dp_execute_cb);
8359
0
}
8360
8361
struct dp_netdev_ct_dump {
8362
    struct ct_dpif_dump_state up;
8363
    struct conntrack_dump dump;
8364
    struct conntrack *ct;
8365
    struct dp_netdev *dp;
8366
};
8367
8368
static int
8369
dpif_netdev_ct_dump_start(struct dpif *dpif, struct ct_dpif_dump_state **dump_,
8370
                          const uint16_t *pzone, int *ptot_bkts)
8371
0
{
8372
0
    struct dp_netdev *dp = get_dp_netdev(dpif);
8373
0
    struct dp_netdev_ct_dump *dump;
8374
8375
0
    dump = xzalloc(sizeof *dump);
8376
0
    dump->dp = dp;
8377
0
    dump->ct = dp->conntrack;
8378
8379
0
    conntrack_dump_start(dp->conntrack, &dump->dump, pzone, ptot_bkts);
8380
8381
0
    *dump_ = &dump->up;
8382
8383
0
    return 0;
8384
0
}
8385
8386
static int
8387
dpif_netdev_ct_dump_next(struct dpif *dpif OVS_UNUSED,
8388
                         struct ct_dpif_dump_state *dump_,
8389
                         struct ct_dpif_entry *entry)
8390
0
{
8391
0
    struct dp_netdev_ct_dump *dump;
8392
8393
0
    INIT_CONTAINER(dump, dump_, up);
8394
8395
0
    return conntrack_dump_next(&dump->dump, entry);
8396
0
}
8397
8398
static int
8399
dpif_netdev_ct_dump_done(struct dpif *dpif OVS_UNUSED,
8400
                         struct ct_dpif_dump_state *dump_)
8401
0
{
8402
0
    struct dp_netdev_ct_dump *dump;
8403
0
    int err;
8404
8405
0
    INIT_CONTAINER(dump, dump_, up);
8406
8407
0
    err = conntrack_dump_done(&dump->dump);
8408
8409
0
    free(dump);
8410
8411
0
    return err;
8412
0
}
8413
8414
static int
8415
dpif_netdev_ct_exp_dump_start(struct dpif *dpif,
8416
                              struct ct_dpif_dump_state **dump_,
8417
                              const uint16_t *pzone)
8418
0
{
8419
0
    struct dp_netdev *dp = get_dp_netdev(dpif);
8420
0
    struct dp_netdev_ct_dump *dump;
8421
8422
0
    dump = xzalloc(sizeof *dump);
8423
0
    dump->dp = dp;
8424
0
    dump->ct = dp->conntrack;
8425
8426
0
    conntrack_exp_dump_start(dp->conntrack, &dump->dump, pzone);
8427
8428
0
    *dump_ = &dump->up;
8429
8430
0
    return 0;
8431
0
}
8432
8433
static int
8434
dpif_netdev_ct_exp_dump_next(struct dpif *dpif OVS_UNUSED,
8435
                             struct ct_dpif_dump_state *dump_,
8436
                             struct ct_dpif_exp *entry)
8437
0
{
8438
0
    struct dp_netdev_ct_dump *dump;
8439
8440
0
    INIT_CONTAINER(dump, dump_, up);
8441
8442
0
    return conntrack_exp_dump_next(&dump->dump, entry);
8443
0
}
8444
8445
static int
8446
dpif_netdev_ct_exp_dump_done(struct dpif *dpif OVS_UNUSED,
8447
                             struct ct_dpif_dump_state *dump_)
8448
0
{
8449
0
    struct dp_netdev_ct_dump *dump;
8450
0
    int err;
8451
8452
0
    INIT_CONTAINER(dump, dump_, up);
8453
8454
0
    err = conntrack_exp_dump_done(&dump->dump);
8455
8456
0
    free(dump);
8457
8458
0
    return err;
8459
0
}
8460
8461
static int
8462
dpif_netdev_ct_flush(struct dpif *dpif, const uint16_t *zone,
8463
                     const struct ct_dpif_tuple *tuple)
8464
0
{
8465
0
    struct dp_netdev *dp = get_dp_netdev(dpif);
8466
8467
0
    if (tuple) {
8468
0
        return conntrack_flush_tuple(dp->conntrack, tuple, zone ? *zone : 0);
8469
0
    }
8470
0
    return conntrack_flush(dp->conntrack, zone);
8471
0
}
8472
8473
static int
8474
dpif_netdev_ct_set_maxconns(struct dpif *dpif, uint32_t maxconns)
8475
0
{
8476
0
    struct dp_netdev *dp = get_dp_netdev(dpif);
8477
8478
0
    return conntrack_set_maxconns(dp->conntrack, maxconns);
8479
0
}
8480
8481
static int
8482
dpif_netdev_ct_get_maxconns(struct dpif *dpif, uint32_t *maxconns)
8483
0
{
8484
0
    struct dp_netdev *dp = get_dp_netdev(dpif);
8485
8486
0
    return conntrack_get_maxconns(dp->conntrack, maxconns);
8487
0
}
8488
8489
static int
8490
dpif_netdev_ct_get_nconns(struct dpif *dpif, uint32_t *nconns)
8491
0
{
8492
0
    struct dp_netdev *dp = get_dp_netdev(dpif);
8493
8494
0
    return conntrack_get_nconns(dp->conntrack, nconns);
8495
0
}
8496
8497
static int
8498
dpif_netdev_ct_set_tcp_seq_chk(struct dpif *dpif, bool enabled)
8499
0
{
8500
0
    struct dp_netdev *dp = get_dp_netdev(dpif);
8501
8502
0
    return conntrack_set_tcp_seq_chk(dp->conntrack, enabled);
8503
0
}
8504
8505
static int
8506
dpif_netdev_ct_get_tcp_seq_chk(struct dpif *dpif, bool *enabled)
8507
0
{
8508
0
    struct dp_netdev *dp = get_dp_netdev(dpif);
8509
0
    *enabled = conntrack_get_tcp_seq_chk(dp->conntrack);
8510
0
    return 0;
8511
0
}
8512
8513
static int
8514
dpif_netdev_ct_set_sweep_interval(struct dpif *dpif, uint32_t ms)
8515
0
{
8516
0
    struct dp_netdev *dp = get_dp_netdev(dpif);
8517
0
    return conntrack_set_sweep_interval(dp->conntrack, ms);
8518
0
}
8519
8520
static int
8521
dpif_netdev_ct_get_sweep_interval(struct dpif *dpif, uint32_t *ms)
8522
0
{
8523
0
    struct dp_netdev *dp = get_dp_netdev(dpif);
8524
0
    *ms = conntrack_get_sweep_interval(dp->conntrack);
8525
0
    return 0;
8526
0
}
8527
8528
static int
8529
dpif_netdev_ct_set_limits(struct dpif *dpif,
8530
                           const struct ovs_list *zone_limits)
8531
0
{
8532
0
    int err = 0;
8533
0
    struct dp_netdev *dp = get_dp_netdev(dpif);
8534
8535
0
    struct ct_dpif_zone_limit *zone_limit;
8536
0
    LIST_FOR_EACH (zone_limit, node, zone_limits) {
8537
0
        err = zone_limit_update(dp->conntrack, zone_limit->zone,
8538
0
                                zone_limit->limit);
8539
0
        if (err != 0) {
8540
0
            break;
8541
0
        }
8542
0
    }
8543
0
    return err;
8544
0
}
8545
8546
static int
8547
dpif_netdev_ct_get_limits(struct dpif *dpif,
8548
                           const struct ovs_list *zone_limits_request,
8549
                           struct ovs_list *zone_limits_reply)
8550
0
{
8551
0
    struct dp_netdev *dp = get_dp_netdev(dpif);
8552
0
    struct conntrack_zone_info czl;
8553
8554
0
    if (!ovs_list_is_empty(zone_limits_request)) {
8555
0
        struct ct_dpif_zone_limit *zone_limit;
8556
0
        LIST_FOR_EACH (zone_limit, node, zone_limits_request) {
8557
0
            czl = zone_limit_get(dp->conntrack, zone_limit->zone);
8558
0
            if (czl.zone == zone_limit->zone || czl.zone == DEFAULT_ZONE) {
8559
0
                ct_dpif_push_zone_limit(zone_limits_reply, zone_limit->zone,
8560
0
                                        czl.limit,
8561
0
                                        czl.count);
8562
0
            } else {
8563
0
                return EINVAL;
8564
0
            }
8565
0
        }
8566
0
    } else {
8567
0
        czl = zone_limit_get(dp->conntrack, DEFAULT_ZONE);
8568
0
        if (czl.zone == DEFAULT_ZONE) {
8569
0
            ct_dpif_push_zone_limit(zone_limits_reply, DEFAULT_ZONE,
8570
0
                                    czl.limit, 0);
8571
0
        }
8572
8573
0
        for (int z = MIN_ZONE; z <= MAX_ZONE; z++) {
8574
0
            czl = zone_limit_get(dp->conntrack, z);
8575
0
            if (czl.zone == z) {
8576
0
                ct_dpif_push_zone_limit(zone_limits_reply, z, czl.limit,
8577
0
                                        czl.count);
8578
0
            }
8579
0
        }
8580
0
    }
8581
8582
0
    return 0;
8583
0
}
8584
8585
static int
8586
dpif_netdev_ct_del_limits(struct dpif *dpif,
8587
                           const struct ovs_list *zone_limits)
8588
0
{
8589
0
    int err = 0;
8590
0
    struct dp_netdev *dp = get_dp_netdev(dpif);
8591
0
    struct ct_dpif_zone_limit *zone_limit;
8592
0
    LIST_FOR_EACH (zone_limit, node, zone_limits) {
8593
0
        err = zone_limit_delete(dp->conntrack, zone_limit->zone);
8594
0
        if (err != 0) {
8595
0
            break;
8596
0
        }
8597
0
    }
8598
8599
0
    return err;
8600
0
}
8601
8602
static int
8603
dpif_netdev_ct_get_features(struct dpif *dpif OVS_UNUSED,
8604
                            enum ct_features *features)
8605
0
{
8606
0
    if (features != NULL) {
8607
0
        *features = CONNTRACK_F_ZERO_SNAT;
8608
0
    }
8609
0
    return 0;
8610
0
}
8611
8612
static int
8613
dpif_netdev_ct_set_timeout_policy(struct dpif *dpif,
8614
                                  const struct ct_dpif_timeout_policy *dpif_tp)
8615
0
{
8616
0
    struct timeout_policy tp;
8617
0
    struct dp_netdev *dp;
8618
8619
0
    dp = get_dp_netdev(dpif);
8620
0
    memcpy(&tp.policy, dpif_tp, sizeof tp.policy);
8621
0
    return timeout_policy_update(dp->conntrack, &tp);
8622
0
}
8623
8624
static int
8625
dpif_netdev_ct_get_timeout_policy(struct dpif *dpif, uint32_t tp_id,
8626
                                  struct ct_dpif_timeout_policy *dpif_tp)
8627
0
{
8628
0
    struct timeout_policy *tp;
8629
0
    struct dp_netdev *dp;
8630
0
    int err = 0;
8631
8632
0
    dp = get_dp_netdev(dpif);
8633
0
    tp = timeout_policy_get(dp->conntrack, tp_id);
8634
0
    if (!tp) {
8635
0
        return ENOENT;
8636
0
    }
8637
0
    memcpy(dpif_tp, &tp->policy, sizeof tp->policy);
8638
0
    return err;
8639
0
}
8640
8641
static int
8642
dpif_netdev_ct_del_timeout_policy(struct dpif *dpif,
8643
                                  uint32_t tp_id)
8644
0
{
8645
0
    struct dp_netdev *dp;
8646
0
    int err = 0;
8647
8648
0
    dp = get_dp_netdev(dpif);
8649
0
    err = timeout_policy_delete(dp->conntrack, tp_id);
8650
0
    return err;
8651
0
}
8652
8653
static int
8654
dpif_netdev_ct_get_timeout_policy_name(struct dpif *dpif OVS_UNUSED,
8655
                                       uint32_t tp_id,
8656
                                       uint16_t dl_type OVS_UNUSED,
8657
                                       uint8_t nw_proto OVS_UNUSED,
8658
                                       char **tp_name, bool *is_generic)
8659
0
{
8660
0
    struct ds ds = DS_EMPTY_INITIALIZER;
8661
8662
0
    ds_put_format(&ds, "%"PRIu32, tp_id);
8663
0
    *tp_name = ds_steal_cstr(&ds);
8664
0
    *is_generic = true;
8665
0
    return 0;
8666
0
}
8667
8668
static int
8669
dpif_netdev_ipf_set_enabled(struct dpif *dpif, bool v6, bool enable)
8670
0
{
8671
0
    struct dp_netdev *dp = get_dp_netdev(dpif);
8672
0
    return ipf_set_enabled(conntrack_ipf_ctx(dp->conntrack), v6, enable);
8673
0
}
8674
8675
static int
8676
dpif_netdev_ipf_set_min_frag(struct dpif *dpif, bool v6, uint32_t min_frag)
8677
0
{
8678
0
    struct dp_netdev *dp = get_dp_netdev(dpif);
8679
0
    return ipf_set_min_frag(conntrack_ipf_ctx(dp->conntrack), v6, min_frag);
8680
0
}
8681
8682
static int
8683
dpif_netdev_ipf_set_max_nfrags(struct dpif *dpif, uint32_t max_frags)
8684
0
{
8685
0
    struct dp_netdev *dp = get_dp_netdev(dpif);
8686
0
    return ipf_set_max_nfrags(conntrack_ipf_ctx(dp->conntrack), max_frags);
8687
0
}
8688
8689
/* Adjust this function if 'dpif_ipf_status' and 'ipf_status' were to
8690
 * diverge. */
8691
static int
8692
dpif_netdev_ipf_get_status(struct dpif *dpif,
8693
                           struct dpif_ipf_status *dpif_ipf_status)
8694
0
{
8695
0
    struct dp_netdev *dp = get_dp_netdev(dpif);
8696
0
    ipf_get_status(conntrack_ipf_ctx(dp->conntrack),
8697
0
                   (struct ipf_status *) dpif_ipf_status);
8698
0
    return 0;
8699
0
}
8700
8701
static int
8702
dpif_netdev_ipf_dump_start(struct dpif *dpif OVS_UNUSED,
8703
                           struct ipf_dump_ctx **ipf_dump_ctx)
8704
0
{
8705
0
    return ipf_dump_start(ipf_dump_ctx);
8706
0
}
8707
8708
static int
8709
dpif_netdev_ipf_dump_next(struct dpif *dpif, void *ipf_dump_ctx, char **dump)
8710
0
{
8711
0
    struct dp_netdev *dp = get_dp_netdev(dpif);
8712
0
    return ipf_dump_next(conntrack_ipf_ctx(dp->conntrack), ipf_dump_ctx,
8713
0
                         dump);
8714
0
}
8715
8716
static int
8717
dpif_netdev_ipf_dump_done(struct dpif *dpif OVS_UNUSED, void *ipf_dump_ctx)
8718
0
{
8719
0
    return ipf_dump_done(ipf_dump_ctx);
8720
8721
0
}
8722
8723
static int
8724
dpif_netdev_bond_add(struct dpif *dpif, uint32_t bond_id,
8725
                     odp_port_t *member_map)
8726
0
{
8727
0
    struct tx_bond *new_tx = xzalloc(sizeof *new_tx);
8728
0
    struct dp_netdev *dp = get_dp_netdev(dpif);
8729
0
    struct dp_netdev_pmd_thread *pmd;
8730
8731
    /* Prepare new bond mapping. */
8732
0
    new_tx->bond_id = bond_id;
8733
0
    for (int bucket = 0; bucket < BOND_BUCKETS; bucket++) {
8734
0
        new_tx->member_buckets[bucket].member_id = member_map[bucket];
8735
0
    }
8736
8737
0
    ovs_mutex_lock(&dp->bond_mutex);
8738
    /* Check if bond already existed. */
8739
0
    struct tx_bond *old_tx = tx_bond_lookup(&dp->tx_bonds, bond_id);
8740
0
    if (old_tx) {
8741
0
        cmap_replace(&dp->tx_bonds, &old_tx->node, &new_tx->node,
8742
0
                     hash_bond_id(bond_id));
8743
0
        ovsrcu_postpone(free, old_tx);
8744
0
    } else {
8745
0
        cmap_insert(&dp->tx_bonds, &new_tx->node, hash_bond_id(bond_id));
8746
0
    }
8747
0
    ovs_mutex_unlock(&dp->bond_mutex);
8748
8749
    /* Update all PMDs with new bond mapping. */
8750
0
    CMAP_FOR_EACH (pmd, node, &dp->poll_threads) {
8751
0
        dp_netdev_add_bond_tx_to_pmd(pmd, new_tx, true);
8752
0
    }
8753
0
    return 0;
8754
0
}
8755
8756
static int
8757
dpif_netdev_bond_del(struct dpif *dpif, uint32_t bond_id)
8758
0
{
8759
0
    struct dp_netdev *dp = get_dp_netdev(dpif);
8760
0
    struct dp_netdev_pmd_thread *pmd;
8761
0
    struct tx_bond *tx;
8762
8763
0
    ovs_mutex_lock(&dp->bond_mutex);
8764
    /* Check if bond existed. */
8765
0
    tx = tx_bond_lookup(&dp->tx_bonds, bond_id);
8766
0
    if (tx) {
8767
0
        cmap_remove(&dp->tx_bonds, &tx->node, hash_bond_id(bond_id));
8768
0
        ovsrcu_postpone(free, tx);
8769
0
    } else {
8770
        /* Bond is not present. */
8771
0
        ovs_mutex_unlock(&dp->bond_mutex);
8772
0
        return ENOENT;
8773
0
    }
8774
0
    ovs_mutex_unlock(&dp->bond_mutex);
8775
8776
    /* Remove the bond map in all pmds. */
8777
0
    CMAP_FOR_EACH (pmd, node, &dp->poll_threads) {
8778
0
        dp_netdev_del_bond_tx_from_pmd(pmd, bond_id);
8779
0
    }
8780
0
    return 0;
8781
0
}
8782
8783
static int
8784
dpif_netdev_bond_stats_get(struct dpif *dpif, uint32_t bond_id,
8785
                           uint64_t *n_bytes)
8786
0
{
8787
0
    struct dp_netdev *dp = get_dp_netdev(dpif);
8788
0
    struct dp_netdev_pmd_thread *pmd;
8789
8790
0
    if (!tx_bond_lookup(&dp->tx_bonds, bond_id)) {
8791
0
        return ENOENT;
8792
0
    }
8793
8794
    /* Search the bond in all PMDs. */
8795
0
    CMAP_FOR_EACH (pmd, node, &dp->poll_threads) {
8796
0
        struct tx_bond *pmd_bond_entry
8797
0
            = tx_bond_lookup(&pmd->tx_bonds, bond_id);
8798
8799
0
        if (!pmd_bond_entry) {
8800
0
            continue;
8801
0
        }
8802
8803
        /* Read bond stats. */
8804
0
        for (int i = 0; i < BOND_BUCKETS; i++) {
8805
0
            uint64_t pmd_n_bytes;
8806
8807
0
            atomic_read_relaxed(&pmd_bond_entry->member_buckets[i].n_bytes,
8808
0
                                &pmd_n_bytes);
8809
0
            n_bytes[i] += pmd_n_bytes;
8810
0
        }
8811
0
    }
8812
0
    return 0;
8813
0
}
8814
8815
const struct dpif_class dpif_netdev_class = {
8816
    "netdev",
8817
    true,                       /* cleanup_required */
8818
    dpif_netdev_init,
8819
    dpif_netdev_enumerate,
8820
    dpif_netdev_port_open_type,
8821
    dpif_netdev_open,
8822
    dpif_netdev_close,
8823
    dpif_netdev_destroy,
8824
    dpif_netdev_run,
8825
    dpif_netdev_wait,
8826
    dpif_netdev_get_stats,
8827
    NULL,                      /* set_features */
8828
    NULL,                      /* get_features */
8829
    dpif_netdev_port_add,
8830
    dpif_netdev_port_del,
8831
    dpif_netdev_port_set_config,
8832
    dpif_netdev_port_query_by_number,
8833
    dpif_netdev_port_query_by_name,
8834
    NULL,                       /* port_get_pid */
8835
    dpif_netdev_port_dump_start,
8836
    dpif_netdev_port_dump_next,
8837
    dpif_netdev_port_dump_done,
8838
    dpif_netdev_port_poll,
8839
    dpif_netdev_port_poll_wait,
8840
    dpif_netdev_flow_flush,
8841
    dpif_netdev_flow_dump_create,
8842
    dpif_netdev_flow_dump_destroy,
8843
    dpif_netdev_flow_dump_thread_create,
8844
    dpif_netdev_flow_dump_thread_destroy,
8845
    dpif_netdev_flow_dump_next,
8846
    dpif_netdev_operate,
8847
    NULL,                       /* recv_set */
8848
    NULL,                       /* handlers_set */
8849
    dpif_netdev_number_handlers_required,
8850
    dpif_netdev_set_config,
8851
    dpif_netdev_queue_to_priority,
8852
    NULL,                       /* recv */
8853
    NULL,                       /* recv_wait */
8854
    NULL,                       /* recv_purge */
8855
    dpif_netdev_register_dp_purge_cb,
8856
    dpif_netdev_register_upcall_cb,
8857
    dpif_netdev_enable_upcall,
8858
    dpif_netdev_disable_upcall,
8859
    dpif_netdev_get_datapath_version,
8860
    dpif_netdev_ct_dump_start,
8861
    dpif_netdev_ct_dump_next,
8862
    dpif_netdev_ct_dump_done,
8863
    dpif_netdev_ct_exp_dump_start,
8864
    dpif_netdev_ct_exp_dump_next,
8865
    dpif_netdev_ct_exp_dump_done,
8866
    dpif_netdev_ct_flush,
8867
    dpif_netdev_ct_set_maxconns,
8868
    dpif_netdev_ct_get_maxconns,
8869
    dpif_netdev_ct_get_nconns,
8870
    dpif_netdev_ct_set_tcp_seq_chk,
8871
    dpif_netdev_ct_get_tcp_seq_chk,
8872
    dpif_netdev_ct_set_sweep_interval,
8873
    dpif_netdev_ct_get_sweep_interval,
8874
    dpif_netdev_ct_set_limits,
8875
    dpif_netdev_ct_get_limits,
8876
    dpif_netdev_ct_del_limits,
8877
    dpif_netdev_ct_set_timeout_policy,
8878
    dpif_netdev_ct_get_timeout_policy,
8879
    dpif_netdev_ct_del_timeout_policy,
8880
    NULL,                       /* ct_timeout_policy_dump_start */
8881
    NULL,                       /* ct_timeout_policy_dump_next */
8882
    NULL,                       /* ct_timeout_policy_dump_done */
8883
    dpif_netdev_ct_get_timeout_policy_name,
8884
    dpif_netdev_ct_get_features,
8885
    dpif_netdev_ipf_set_enabled,
8886
    dpif_netdev_ipf_set_min_frag,
8887
    dpif_netdev_ipf_set_max_nfrags,
8888
    dpif_netdev_ipf_get_status,
8889
    dpif_netdev_ipf_dump_start,
8890
    dpif_netdev_ipf_dump_next,
8891
    dpif_netdev_ipf_dump_done,
8892
    dpif_netdev_meter_get_features,
8893
    dpif_netdev_meter_set,
8894
    dpif_netdev_meter_get,
8895
    dpif_netdev_meter_del,
8896
    dpif_netdev_bond_add,
8897
    dpif_netdev_bond_del,
8898
    dpif_netdev_bond_stats_get,
8899
    NULL,                       /* cache_get_supported_levels */
8900
    NULL,                       /* cache_get_name */
8901
    NULL,                       /* cache_get_size */
8902
    NULL,                       /* cache_set_size */
8903
};
8904
8905
static void
8906
dpif_dummy_change_port_number(struct unixctl_conn *conn, int argc OVS_UNUSED,
8907
                              const char *argv[], void *aux OVS_UNUSED)
8908
0
{
8909
0
    struct dp_netdev_port *port;
8910
0
    struct dp_netdev *dp;
8911
0
    odp_port_t port_no;
8912
8913
0
    ovs_mutex_lock(&dp_netdev_mutex);
8914
0
    dp = shash_find_data(&dp_netdevs, argv[1]);
8915
0
    if (!dp || !dpif_netdev_class_is_dummy(dp->class)) {
8916
0
        ovs_mutex_unlock(&dp_netdev_mutex);
8917
0
        unixctl_command_reply_error(conn, "unknown datapath or not a dummy");
8918
0
        return;
8919
0
    }
8920
0
    ovs_refcount_ref(&dp->ref_cnt);
8921
0
    ovs_mutex_unlock(&dp_netdev_mutex);
8922
8923
0
    ovs_rwlock_wrlock(&dp->port_rwlock);
8924
0
    if (get_port_by_name(dp, argv[2], &port)) {
8925
0
        unixctl_command_reply_error(conn, "unknown port");
8926
0
        goto exit;
8927
0
    }
8928
8929
0
    port_no = u32_to_odp(atoi(argv[3]));
8930
0
    if (!port_no || port_no == ODPP_NONE) {
8931
0
        unixctl_command_reply_error(conn, "bad port number");
8932
0
        goto exit;
8933
0
    }
8934
0
    if (dp_netdev_lookup_port(dp, port_no)) {
8935
0
        unixctl_command_reply_error(conn, "port number already in use");
8936
0
        goto exit;
8937
0
    }
8938
8939
    /* Remove port. */
8940
0
    hmap_remove(&dp->ports, &port->node);
8941
0
    reconfigure_datapath(dp);
8942
8943
    /* Reinsert with new port number. */
8944
0
    port->port_no = port_no;
8945
0
    hmap_insert(&dp->ports, &port->node, hash_port_no(port_no));
8946
0
    reconfigure_datapath(dp);
8947
8948
0
    seq_change(dp->port_seq);
8949
0
    unixctl_command_reply(conn, NULL);
8950
8951
0
exit:
8952
0
    ovs_rwlock_unlock(&dp->port_rwlock);
8953
0
    dp_netdev_unref(dp);
8954
0
}
8955
8956
static void
8957
dpif_dummy_register__(const char *type)
8958
0
{
8959
0
    struct dpif_class *class;
8960
8961
0
    class = xmalloc(sizeof *class);
8962
0
    *class = dpif_netdev_class;
8963
0
    class->type = xstrdup(type);
8964
0
    dp_register_provider(class);
8965
0
}
8966
8967
static void
8968
dpif_dummy_override(const char *type)
8969
0
{
8970
0
    int error;
8971
8972
    /*
8973
     * Ignore EAFNOSUPPORT to allow --enable-dummy=system with
8974
     * a userland-only build.  It's useful for testsuite.
8975
     */
8976
0
    error = dp_unregister_provider(type);
8977
0
    if (error == 0 || error == EAFNOSUPPORT) {
8978
0
        dpif_dummy_register__(type);
8979
0
    }
8980
0
}
8981
8982
void
8983
dpif_dummy_register(enum dummy_level level)
8984
0
{
8985
0
    if (level == DUMMY_OVERRIDE_ALL) {
8986
0
        struct sset types;
8987
0
        const char *type;
8988
8989
0
        sset_init(&types);
8990
0
        dp_enumerate_types(&types);
8991
0
        SSET_FOR_EACH (type, &types) {
8992
0
            dpif_dummy_override(type);
8993
0
        }
8994
0
        sset_destroy(&types);
8995
0
    } else if (level == DUMMY_OVERRIDE_SYSTEM) {
8996
0
        dpif_dummy_override("system");
8997
0
    }
8998
8999
0
    dpif_dummy_register__("dummy");
9000
9001
0
    unixctl_command_register("dpif-dummy/change-port-number",
9002
0
                             "dp port new-number",
9003
0
                             3, 3, dpif_dummy_change_port_number, NULL);
9004
0
}
9005

9006
/* Datapath Classifier. */
9007
9008
static void
9009
dpcls_subtable_destroy_cb(struct dpcls_subtable *subtable)
9010
0
{
9011
0
    cmap_destroy(&subtable->rules);
9012
0
    ovsrcu_postpone(free, subtable->mf_masks);
9013
0
    ovsrcu_postpone(free, subtable);
9014
0
}
9015
9016
/* Initializes 'cls' as a classifier that initially contains no classification
9017
 * rules. */
9018
static void
9019
dpcls_init(struct dpcls *cls)
9020
0
{
9021
0
    cmap_init(&cls->subtables_map);
9022
0
    pvector_init(&cls->subtables);
9023
0
}
9024
9025
static void
9026
dpcls_destroy_subtable(struct dpcls *cls, struct dpcls_subtable *subtable)
9027
0
{
9028
0
    VLOG_DBG("Destroying subtable %p for in_port %d", subtable, cls->in_port);
9029
0
    pvector_remove(&cls->subtables, subtable);
9030
0
    cmap_remove(&cls->subtables_map, &subtable->cmap_node,
9031
0
                subtable->mask.hash);
9032
0
    ovsrcu_postpone(dpcls_subtable_destroy_cb, subtable);
9033
0
}
9034
9035
/* Destroys 'cls'.  Rules within 'cls', if any, are not freed; this is the
9036
 * caller's responsibility.
9037
 * May only be called after all the readers have been terminated. */
9038
static void
9039
dpcls_destroy(struct dpcls *cls)
9040
0
{
9041
0
    if (cls) {
9042
0
        struct dpcls_subtable *subtable;
9043
9044
0
        CMAP_FOR_EACH (subtable, cmap_node, &cls->subtables_map) {
9045
0
            ovs_assert(cmap_count(&subtable->rules) == 0);
9046
0
            dpcls_destroy_subtable(cls, subtable);
9047
0
        }
9048
0
        cmap_destroy(&cls->subtables_map);
9049
0
        pvector_destroy(&cls->subtables);
9050
0
    }
9051
0
}
9052
9053
static struct dpcls_subtable *
9054
dpcls_create_subtable(struct dpcls *cls, const struct netdev_flow_key *mask)
9055
0
{
9056
0
    struct dpcls_subtable *subtable;
9057
9058
    /* Need to add one. */
9059
0
    subtable = xmalloc(sizeof *subtable
9060
0
                       - sizeof subtable->mask.mf + mask->len);
9061
0
    cmap_init(&subtable->rules);
9062
0
    subtable->hit_cnt = 0;
9063
0
    netdev_flow_key_clone(&subtable->mask, mask);
9064
9065
    /* The count of bits in the mask defines the space required for masks.
9066
     * Then call gen_masks() to create the appropriate masks, avoiding the cost
9067
     * of doing runtime calculations. */
9068
0
    uint32_t unit0 = count_1bits(mask->mf.map.bits[0]);
9069
0
    uint32_t unit1 = count_1bits(mask->mf.map.bits[1]);
9070
0
    subtable->mf_bits_set_unit0 = unit0;
9071
0
    subtable->mf_bits_set_unit1 = unit1;
9072
0
    subtable->mf_masks = xmalloc(sizeof(uint64_t) * (unit0 + unit1));
9073
0
    dpcls_flow_key_gen_masks(mask, subtable->mf_masks, unit0, unit1);
9074
9075
    /* Get the preferred subtable search function for this (u0,u1) subtable.
9076
     * The function is guaranteed to always return a valid implementation, and
9077
     * possibly a specialized implementation. */
9078
0
    subtable->lookup_func = dpcls_subtable_lookup_probe(unit0, unit1);
9079
9080
0
    cmap_insert(&cls->subtables_map, &subtable->cmap_node, mask->hash);
9081
    /* Add the new subtable at the end of the pvector (with no hits yet) */
9082
0
    pvector_insert(&cls->subtables, subtable, 0);
9083
0
    VLOG_DBG("Creating %"PRIuSIZE". subtable %p for in_port %d",
9084
0
             cmap_count(&cls->subtables_map), subtable, cls->in_port);
9085
0
    pvector_publish(&cls->subtables);
9086
9087
0
    return subtable;
9088
0
}
9089
9090
static inline struct dpcls_subtable *
9091
dpcls_find_subtable(struct dpcls *cls, const struct netdev_flow_key *mask)
9092
0
{
9093
0
    struct dpcls_subtable *subtable;
9094
9095
0
    CMAP_FOR_EACH_WITH_HASH (subtable, cmap_node, mask->hash,
9096
0
                             &cls->subtables_map) {
9097
0
        if (netdev_flow_key_equal(&subtable->mask, mask)) {
9098
0
            return subtable;
9099
0
        }
9100
0
    }
9101
0
    return dpcls_create_subtable(cls, mask);
9102
0
}
9103
9104
/* Periodically sort the dpcls subtable vectors according to hit counts */
9105
static void
9106
dpcls_sort_subtable_vector(struct dpcls *cls)
9107
0
{
9108
0
    struct pvector *pvec = &cls->subtables;
9109
0
    struct dpcls_subtable *subtable;
9110
9111
0
    PVECTOR_FOR_EACH (subtable, pvec) {
9112
0
        pvector_change_priority(pvec, subtable, subtable->hit_cnt);
9113
0
        subtable->hit_cnt = 0;
9114
0
    }
9115
0
    pvector_publish(pvec);
9116
0
}
9117
9118
static inline void
9119
dp_netdev_pmd_try_optimize(struct dp_netdev_pmd_thread *pmd,
9120
                           struct polled_queue *poll_list, int poll_cnt)
9121
0
{
9122
0
    struct dpcls *cls;
9123
0
    uint64_t tot_idle = 0, tot_proc = 0, tot_sleep = 0;
9124
0
    unsigned int pmd_load = 0;
9125
9126
0
    if (pmd->ctx.now > pmd->next_cycle_store) {
9127
0
        uint64_t curr_tsc;
9128
0
        uint8_t rebalance_load_trigger;
9129
0
        struct pmd_auto_lb *pmd_alb = &pmd->dp->pmd_alb;
9130
0
        unsigned int idx;
9131
9132
0
        if (pmd->perf_stats.counters.n[PMD_CYCLES_ITER_IDLE] >=
9133
0
                pmd->prev_stats[PMD_CYCLES_ITER_IDLE] &&
9134
0
            pmd->perf_stats.counters.n[PMD_CYCLES_ITER_BUSY] >=
9135
0
                pmd->prev_stats[PMD_CYCLES_ITER_BUSY]) {
9136
0
            tot_idle = pmd->perf_stats.counters.n[PMD_CYCLES_ITER_IDLE] -
9137
0
                       pmd->prev_stats[PMD_CYCLES_ITER_IDLE];
9138
0
            tot_proc = pmd->perf_stats.counters.n[PMD_CYCLES_ITER_BUSY] -
9139
0
                       pmd->prev_stats[PMD_CYCLES_ITER_BUSY];
9140
0
            tot_sleep = pmd->perf_stats.counters.n[PMD_CYCLES_SLEEP] -
9141
0
                        pmd->prev_stats[PMD_CYCLES_SLEEP];
9142
9143
0
            if (pmd_alb->is_enabled && !pmd->isolated) {
9144
0
                if (tot_proc) {
9145
0
                    pmd_load = ((tot_proc * 100) /
9146
0
                                    (tot_idle + tot_proc + tot_sleep));
9147
0
                }
9148
9149
0
                atomic_read_relaxed(&pmd_alb->rebalance_load_thresh,
9150
0
                                    &rebalance_load_trigger);
9151
0
                if (pmd_load >= rebalance_load_trigger) {
9152
0
                    atomic_count_inc(&pmd->pmd_overloaded);
9153
0
                } else {
9154
0
                    atomic_count_set(&pmd->pmd_overloaded, 0);
9155
0
                }
9156
0
            }
9157
0
        }
9158
9159
0
        pmd->prev_stats[PMD_CYCLES_ITER_IDLE] =
9160
0
                        pmd->perf_stats.counters.n[PMD_CYCLES_ITER_IDLE];
9161
0
        pmd->prev_stats[PMD_CYCLES_ITER_BUSY] =
9162
0
                        pmd->perf_stats.counters.n[PMD_CYCLES_ITER_BUSY];
9163
0
        pmd->prev_stats[PMD_CYCLES_SLEEP] =
9164
0
                        pmd->perf_stats.counters.n[PMD_CYCLES_SLEEP];
9165
9166
        /* Get the cycles that were used to process each queue and store. */
9167
0
        for (unsigned i = 0; i < poll_cnt; i++) {
9168
0
            uint64_t rxq_cyc_curr = dp_netdev_rxq_get_cycles(poll_list[i].rxq,
9169
0
                                                        RXQ_CYCLES_PROC_CURR);
9170
0
            dp_netdev_rxq_set_intrvl_cycles(poll_list[i].rxq, rxq_cyc_curr);
9171
0
            dp_netdev_rxq_set_cycles(poll_list[i].rxq, RXQ_CYCLES_PROC_CURR,
9172
0
                                     0);
9173
0
        }
9174
0
        curr_tsc = cycles_counter_update(&pmd->perf_stats);
9175
0
        if (pmd->intrvl_tsc_prev) {
9176
            /* There is a prev timestamp, store a new intrvl cycle count. */
9177
0
            atomic_store_relaxed(&pmd->intrvl_cycles,
9178
0
                                 curr_tsc - pmd->intrvl_tsc_prev);
9179
0
        }
9180
0
        idx = atomic_count_inc(&pmd->intrvl_idx) % PMD_INTERVAL_MAX;
9181
0
        atomic_store_relaxed(&pmd->busy_cycles_intrvl[idx], tot_proc);
9182
0
        pmd->intrvl_tsc_prev = curr_tsc;
9183
        /* Start new measuring interval */
9184
0
        pmd->next_cycle_store = pmd->ctx.now + PMD_INTERVAL_LEN;
9185
0
    }
9186
9187
0
    if (pmd->ctx.now > pmd->next_optimization) {
9188
        /* Try to obtain the flow lock to block out revalidator threads.
9189
         * If not possible, just try next time. */
9190
0
        if (!ovs_mutex_trylock(&pmd->flow_mutex)) {
9191
            /* Optimize each classifier */
9192
0
            CMAP_FOR_EACH (cls, node, &pmd->classifiers) {
9193
0
                dpcls_sort_subtable_vector(cls);
9194
0
            }
9195
0
            ovs_mutex_unlock(&pmd->flow_mutex);
9196
            /* Start new measuring interval */
9197
0
            pmd->next_optimization = pmd->ctx.now
9198
0
                                     + DPCLS_OPTIMIZATION_INTERVAL;
9199
0
        }
9200
0
    }
9201
0
}
9202
9203
/* Returns the sum of a specified number of newest to
9204
 * oldest interval values. 'cur_idx' is where the next
9205
 * write will be and wrap around needs to be handled.
9206
 */
9207
static uint64_t
9208
get_interval_values(atomic_ullong *source, atomic_count *cur_idx,
9209
0
                    int num_to_read) {
9210
0
    unsigned int i;
9211
0
    uint64_t total = 0;
9212
9213
0
    i = atomic_count_get(cur_idx) % PMD_INTERVAL_MAX;
9214
0
    for (int read = 0; read < num_to_read; read++) {
9215
0
        uint64_t interval_value;
9216
9217
0
        i = i ? i - 1 : PMD_INTERVAL_MAX - 1;
9218
0
        atomic_read_relaxed(&source[i], &interval_value);
9219
0
        total += interval_value;
9220
0
    }
9221
0
    return total;
9222
0
}
9223
9224
/* Insert 'rule' into 'cls'. */
9225
static void
9226
dpcls_insert(struct dpcls *cls, struct dpcls_rule *rule,
9227
             const struct netdev_flow_key *mask)
9228
0
{
9229
0
    struct dpcls_subtable *subtable = dpcls_find_subtable(cls, mask);
9230
9231
    /* Refer to subtable's mask, also for later removal. */
9232
0
    rule->mask = &subtable->mask;
9233
0
    cmap_insert(&subtable->rules, &rule->cmap_node, rule->flow.hash);
9234
0
}
9235
9236
/* Removes 'rule' from 'cls', also destructing the 'rule'. */
9237
static void
9238
dpcls_remove(struct dpcls *cls, struct dpcls_rule *rule)
9239
0
{
9240
0
    struct dpcls_subtable *subtable;
9241
9242
0
    ovs_assert(rule->mask);
9243
9244
    /* Get subtable from reference in rule->mask. */
9245
0
    INIT_CONTAINER(subtable, rule->mask, mask);
9246
0
    if (cmap_remove(&subtable->rules, &rule->cmap_node, rule->flow.hash)
9247
0
        == 0) {
9248
        /* Delete empty subtable. */
9249
0
        dpcls_destroy_subtable(cls, subtable);
9250
0
        pvector_publish(&cls->subtables);
9251
0
    }
9252
0
}
9253
9254
/* Inner loop for mask generation of a unit, see dpcls_flow_key_gen_masks. */
9255
static inline void
9256
dpcls_flow_key_gen_mask_unit(uint64_t iter, const uint64_t count,
9257
                             uint64_t *mf_masks)
9258
0
{
9259
0
    int i;
9260
0
    for (i = 0; i < count; i++) {
9261
0
        uint64_t lowest_bit = (iter & -iter);
9262
0
        iter &= ~lowest_bit;
9263
0
        mf_masks[i] = (lowest_bit - 1);
9264
0
    }
9265
    /* Checks that count has covered all bits in the iter bitmap. */
9266
0
    ovs_assert(iter == 0);
9267
0
}
9268
9269
/* Generate a mask for each block in the miniflow, based on the bits set. This
9270
 * allows easily masking packets with the generated array here, without
9271
 * calculations. This replaces runtime-calculating the masks.
9272
 * @param key The table to generate the mf_masks for
9273
 * @param mf_masks Pointer to a u64 array of at least *mf_bits* in size
9274
 * @param mf_bits_total Number of bits set in the whole miniflow (both units)
9275
 * @param mf_bits_unit0 Number of bits set in unit0 of the miniflow
9276
 */
9277
void
9278
dpcls_flow_key_gen_masks(const struct netdev_flow_key *tbl,
9279
                         uint64_t *mf_masks,
9280
                         const uint32_t mf_bits_u0,
9281
                         const uint32_t mf_bits_u1)
9282
0
{
9283
0
    uint64_t iter_u0 = tbl->mf.map.bits[0];
9284
0
    uint64_t iter_u1 = tbl->mf.map.bits[1];
9285
9286
0
    dpcls_flow_key_gen_mask_unit(iter_u0, mf_bits_u0, &mf_masks[0]);
9287
0
    dpcls_flow_key_gen_mask_unit(iter_u1, mf_bits_u1, &mf_masks[mf_bits_u0]);
9288
0
}
9289
9290
/* Returns true if 'target' satisfies 'key' in 'mask', that is, if each 1-bit
9291
 * in 'mask' the values in 'key' and 'target' are the same. */
9292
inline bool
9293
dpcls_rule_matches_key(const struct dpcls_rule *rule,
9294
                       const struct netdev_flow_key *target)
9295
0
{
9296
0
    const uint64_t *keyp = miniflow_get_values(&rule->flow.mf);
9297
0
    const uint64_t *maskp = miniflow_get_values(&rule->mask->mf);
9298
0
    uint64_t value;
9299
9300
0
    NETDEV_FLOW_KEY_FOR_EACH_IN_FLOWMAP(value, target, rule->flow.mf.map) {
9301
0
        if (OVS_UNLIKELY((value & *maskp++) != *keyp++)) {
9302
0
            return false;
9303
0
        }
9304
0
    }
9305
0
    return true;
9306
0
}
9307
9308
/* For each miniflow in 'keys' performs a classifier lookup writing the result
9309
 * into the corresponding slot in 'rules'.  If a particular entry in 'keys' is
9310
 * NULL it is skipped.
9311
 *
9312
 * This function is optimized for use in the userspace datapath and therefore
9313
 * does not implement a lot of features available in the standard
9314
 * classifier_lookup() function.  Specifically, it does not implement
9315
 * priorities, instead returning any rule which matches the flow.
9316
 *
9317
 * Returns true if all miniflows found a corresponding rule. */
9318
bool
9319
dpcls_lookup(struct dpcls *cls, const struct netdev_flow_key *keys[],
9320
             struct dpcls_rule **rules, const size_t cnt,
9321
             int *num_lookups_p)
9322
0
{
9323
    /* The received 'cnt' miniflows are the search-keys that will be processed
9324
     * to find a matching entry into the available subtables.
9325
     * The number of bits in map_type is equal to NETDEV_MAX_BURST. */
9326
0
#define MAP_BITS (sizeof(uint32_t) * CHAR_BIT)
9327
0
    BUILD_ASSERT_DECL(MAP_BITS >= NETDEV_MAX_BURST);
9328
9329
0
    struct dpcls_subtable *subtable;
9330
0
    uint32_t keys_map = TYPE_MAXIMUM(uint32_t); /* Set all bits. */
9331
9332
0
    if (cnt != MAP_BITS) {
9333
0
        keys_map >>= MAP_BITS - cnt; /* Clear extra bits. */
9334
0
    }
9335
0
    memset(rules, 0, cnt * sizeof *rules);
9336
9337
0
    int lookups_match = 0, subtable_pos = 1;
9338
0
    uint32_t found_map;
9339
9340
    /* The Datapath classifier - aka dpcls - is composed of subtables.
9341
     * Subtables are dynamically created as needed when new rules are inserted.
9342
     * Each subtable collects rules with matches on a specific subset of packet
9343
     * fields as defined by the subtable's mask.  We proceed to process every
9344
     * search-key against each subtable, but when a match is found for a
9345
     * search-key, the search for that key can stop because the rules are
9346
     * non-overlapping. */
9347
0
    PVECTOR_FOR_EACH (subtable, &cls->subtables) {
9348
        /* Call the subtable specific lookup function. */
9349
0
        found_map = subtable->lookup_func(subtable, keys_map, keys, rules);
9350
9351
        /* Count the number of subtables searched for this packet match. This
9352
         * estimates the "spread" of subtables looked at per matched packet. */
9353
0
        uint32_t pkts_matched = count_1bits(found_map);
9354
0
        lookups_match += pkts_matched * subtable_pos;
9355
9356
        /* Clear the found rules, and return early if all packets are found. */
9357
0
        keys_map &= ~found_map;
9358
0
        if (!keys_map) {
9359
0
            if (num_lookups_p) {
9360
0
                *num_lookups_p = lookups_match;
9361
0
            }
9362
0
            return true;
9363
0
        }
9364
0
        subtable_pos++;
9365
0
    }
9366
9367
0
    if (num_lookups_p) {
9368
0
        *num_lookups_p = lookups_match;
9369
0
    }
9370
    return false;
9371
0
}