Coverage Report

Created: 2026-07-16 06:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openvswitch/lib/netdev.c
Line
Count
Source
1
/*
2
 * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2016, 2017 Nicira, Inc.
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at:
7
 *
8
 *     http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
17
#include <config.h>
18
#include "netdev.h"
19
20
#include <errno.h>
21
#include <inttypes.h>
22
#include <sys/types.h>
23
#include <netinet/in.h>
24
#include <stdlib.h>
25
#include <string.h>
26
#include <unistd.h>
27
#include <ifaddrs.h>
28
#include <net/if.h>
29
#include <sys/ioctl.h>
30
31
#include "cmap.h"
32
#include "coverage.h"
33
#include "dpif.h"
34
#include "dp-packet.h"
35
#include "dp-packet-gso.h"
36
#include "openvswitch/dynamic-string.h"
37
#include "fatal-signal.h"
38
#include "hash.h"
39
#include "openvswitch/list.h"
40
#include "netdev-provider.h"
41
#include "netdev-vport.h"
42
#include "odp-netlink.h"
43
#include "openvswitch/json.h"
44
#include "openflow/openflow.h"
45
#include "packets.h"
46
#include "openvswitch/ofp-print.h"
47
#include "openvswitch/poll-loop.h"
48
#include "seq.h"
49
#include "openvswitch/shash.h"
50
#include "smap.h"
51
#include "socket-util.h"
52
#include "sset.h"
53
#include "svec.h"
54
#include "openvswitch/vlog.h"
55
#include "flow.h"
56
#include "userspace-tso.h"
57
#include "util.h"
58
#ifdef __linux__
59
#include "tc.h"
60
#endif
61
62
VLOG_DEFINE_THIS_MODULE(netdev);
63
64
COVERAGE_DEFINE(netdev_received);
65
COVERAGE_DEFINE(netdev_sent);
66
COVERAGE_DEFINE(netdev_add_router);
67
COVERAGE_DEFINE(netdev_get_stats);
68
COVERAGE_DEFINE(netdev_push_header_drops);
69
70
struct netdev_saved_flags {
71
    struct netdev *netdev;
72
    struct ovs_list node;           /* In struct netdev's saved_flags_list. */
73
    enum netdev_flags saved_flags;
74
    enum netdev_flags saved_values;
75
};
76
77
/* Protects 'netdev_shash' and the mutable members of struct netdev. */
78
static struct ovs_mutex netdev_mutex = OVS_MUTEX_INITIALIZER;
79
80
/* All created network devices. */
81
static struct shash netdev_shash OVS_GUARDED_BY(netdev_mutex)
82
    = SHASH_INITIALIZER(&netdev_shash);
83
84
/* Mutual exclusion of */
85
static struct ovs_mutex netdev_class_mutex OVS_ACQ_BEFORE(netdev_mutex)
86
    = OVS_MUTEX_INITIALIZER;
87
88
/* Contains 'struct netdev_registered_class'es. */
89
static struct cmap netdev_classes = CMAP_INITIALIZER;
90
91
struct netdev_registered_class {
92
    struct cmap_node cmap_node; /* In 'netdev_classes', by class->type. */
93
    const struct netdev_class *class;
94
95
    /* Number of references: one for the class itself and one for every
96
     * instance of the class. */
97
    struct ovs_refcount refcnt;
98
};
99
100
/* This is set pretty low because we probably won't learn anything from the
101
 * additional log messages. */
102
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 20);
103
104
static void restore_all_flags(void *aux OVS_UNUSED);
105
void update_device_args(struct netdev *, const struct shash *args);
106
#ifdef HAVE_AF_XDP
107
void signal_remove_xdp(struct netdev *netdev);
108
#endif
109
110
int
111
netdev_n_txq(const struct netdev *netdev)
112
0
{
113
0
    return netdev->n_txq;
114
0
}
115
116
int
117
netdev_n_rxq(const struct netdev *netdev)
118
0
{
119
0
    return netdev->n_rxq;
120
0
}
121
122
bool
123
netdev_is_pmd(const struct netdev *netdev)
124
0
{
125
0
    return netdev->netdev_class->is_pmd;
126
0
}
127
128
bool
129
netdev_has_tunnel_push_pop(const struct netdev *netdev)
130
0
{
131
0
    return netdev->netdev_class->push_header
132
0
           && netdev->netdev_class->pop_header;
133
0
}
134
135
static void
136
netdev_initialize(void)
137
    OVS_EXCLUDED(netdev_mutex)
138
0
{
139
0
    static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER;
140
141
0
    if (ovsthread_once_start(&once)) {
142
0
        fatal_signal_add_hook(restore_all_flags, NULL, NULL, true);
143
144
0
        netdev_vport_patch_register();
145
146
0
#ifdef __linux__
147
0
        netdev_register_provider(&netdev_linux_class);
148
0
        netdev_register_provider(&netdev_internal_class);
149
0
        netdev_register_provider(&netdev_tap_class);
150
0
        netdev_vport_tunnel_register();
151
#ifdef HAVE_AF_XDP
152
        netdev_register_provider(&netdev_afxdp_class);
153
        netdev_register_provider(&netdev_afxdp_nonpmd_class);
154
#endif
155
0
#endif
156
#if defined(__FreeBSD__) || defined(__NetBSD__)
157
        netdev_register_provider(&netdev_tap_class);
158
        netdev_register_provider(&netdev_bsd_class);
159
#endif
160
0
        ovsthread_once_done(&once);
161
0
    }
162
0
}
163
164
/* Performs periodic work needed by all the various kinds of netdevs.
165
 *
166
 * If your program opens any netdevs, it must call this function within its
167
 * main poll loop. */
168
void
169
netdev_run(void)
170
    OVS_EXCLUDED(netdev_mutex)
171
0
{
172
0
    netdev_initialize();
173
174
0
    struct netdev_registered_class *rc;
175
0
    CMAP_FOR_EACH (rc, cmap_node, &netdev_classes) {
176
0
        if (rc->class->run) {
177
0
            rc->class->run(rc->class);
178
0
        }
179
0
    }
180
0
}
181
182
/* Arranges for poll_block() to wake up when netdev_run() needs to be called.
183
 *
184
 * If your program opens any netdevs, it must call this function within its
185
 * main poll loop. */
186
void
187
netdev_wait(void)
188
    OVS_EXCLUDED(netdev_mutex)
189
0
{
190
0
    netdev_initialize();
191
192
0
    struct netdev_registered_class *rc;
193
0
    CMAP_FOR_EACH (rc, cmap_node, &netdev_classes) {
194
0
        if (rc->class->wait) {
195
0
            rc->class->wait(rc->class);
196
0
        }
197
0
    }
198
0
}
199
200
static struct netdev_registered_class *
201
netdev_lookup_class(const char *type)
202
0
{
203
0
    struct netdev_registered_class *rc;
204
0
    CMAP_FOR_EACH_WITH_HASH (rc, cmap_node, hash_string(type, 0),
205
0
                             &netdev_classes) {
206
0
        if (!strcmp(type, rc->class->type)) {
207
0
            return rc;
208
0
        }
209
0
    }
210
0
    return NULL;
211
0
}
212
213
/* Initializes and registers a new netdev provider.  After successful
214
 * registration, new netdevs of that type can be opened using netdev_open(). */
215
int
216
netdev_register_provider(const struct netdev_class *new_class)
217
    OVS_EXCLUDED(netdev_class_mutex, netdev_mutex)
218
0
{
219
0
    int error;
220
221
0
    ovs_mutex_lock(&netdev_class_mutex);
222
0
    if (netdev_lookup_class(new_class->type)) {
223
0
        VLOG_WARN("attempted to register duplicate netdev provider: %s",
224
0
                   new_class->type);
225
0
        error = EEXIST;
226
0
    } else {
227
0
        error = new_class->init ? new_class->init() : 0;
228
0
        if (!error) {
229
0
            struct netdev_registered_class *rc;
230
231
0
            rc = xmalloc(sizeof *rc);
232
0
            cmap_insert(&netdev_classes, &rc->cmap_node,
233
0
                        hash_string(new_class->type, 0));
234
0
            rc->class = new_class;
235
0
            ovs_refcount_init(&rc->refcnt);
236
0
        } else {
237
0
            VLOG_ERR("failed to initialize %s network device class: %s",
238
0
                     new_class->type, ovs_strerror(error));
239
0
        }
240
0
    }
241
0
    ovs_mutex_unlock(&netdev_class_mutex);
242
243
0
    return error;
244
0
}
245
246
/* Unregisters a netdev provider.  'type' must have been previously registered
247
 * and not currently be in use by any netdevs.  After unregistration new
248
 * netdevs of that type cannot be opened using netdev_open().  (However, the
249
 * provider may still be accessible from other threads until the next RCU grace
250
 * period, so the caller must not free or re-register the same netdev_class
251
 * until that has passed.) */
252
int
253
netdev_unregister_provider(const char *type)
254
    OVS_EXCLUDED(netdev_class_mutex, netdev_mutex)
255
0
{
256
0
    struct netdev_registered_class *rc;
257
0
    int error;
258
259
0
    netdev_initialize();
260
261
0
    ovs_mutex_lock(&netdev_class_mutex);
262
0
    rc = netdev_lookup_class(type);
263
0
    if (!rc) {
264
0
        VLOG_WARN("attempted to unregister a netdev provider that is not "
265
0
                  "registered: %s", type);
266
0
        error = EAFNOSUPPORT;
267
0
    } else if (ovs_refcount_unref(&rc->refcnt) != 1) {
268
0
        ovs_refcount_ref(&rc->refcnt);
269
0
        VLOG_WARN("attempted to unregister in use netdev provider: %s",
270
0
                  type);
271
0
        error = EBUSY;
272
0
    } else  {
273
0
        cmap_remove(&netdev_classes, &rc->cmap_node,
274
0
                    hash_string(rc->class->type, 0));
275
0
        ovsrcu_postpone(free, rc);
276
0
        error = 0;
277
0
    }
278
0
    ovs_mutex_unlock(&netdev_class_mutex);
279
280
0
    return error;
281
0
}
282
283
/* Clears 'types' and enumerates the types of all currently registered netdev
284
 * providers into it.  The caller must first initialize the sset. */
285
void
286
netdev_enumerate_types(struct sset *types)
287
    OVS_EXCLUDED(netdev_mutex)
288
0
{
289
0
    netdev_initialize();
290
0
    sset_clear(types);
291
292
0
    struct netdev_registered_class *rc;
293
0
    CMAP_FOR_EACH (rc, cmap_node, &netdev_classes) {
294
0
        sset_add(types, rc->class->type);
295
0
    }
296
0
}
297
298
static const char *
299
netdev_vport_type_from_name(const char *name)
300
0
{
301
0
    struct netdev_registered_class *rc;
302
0
    const char *type;
303
0
    CMAP_FOR_EACH (rc, cmap_node, &netdev_classes) {
304
0
        const char *dpif_port = netdev_vport_class_get_dpif_port(rc->class);
305
0
        if (dpif_port && !strncmp(name, dpif_port, strlen(dpif_port))) {
306
0
            type = rc->class->type;
307
0
            return type;
308
0
        }
309
0
    }
310
0
    return NULL;
311
0
}
312
313
/* Check that the network device name is not the same as any of the registered
314
 * vport providers' dpif_port name (dpif_port is NULL if the vport provider
315
 * does not define it) or the datapath internal port name (e.g. ovs-system).
316
 *
317
 * Returns true if there is a name conflict, false otherwise. */
318
bool
319
netdev_is_reserved_name(const char *name)
320
    OVS_EXCLUDED(netdev_mutex)
321
0
{
322
0
    netdev_initialize();
323
324
0
    struct netdev_registered_class *rc;
325
0
    CMAP_FOR_EACH (rc, cmap_node, &netdev_classes) {
326
0
        const char *dpif_port = netdev_vport_class_get_dpif_port(rc->class);
327
0
        if (dpif_port && !strncmp(name, dpif_port, strlen(dpif_port))) {
328
0
            return true;
329
0
        }
330
0
    }
331
332
0
    if (!strncmp(name, "ovs-", 4)) {
333
0
        struct sset types;
334
0
        const char *type;
335
336
0
        sset_init(&types);
337
0
        dp_enumerate_types(&types);
338
0
        SSET_FOR_EACH (type, &types) {
339
0
            if (!strcmp(name+4, type)) {
340
0
                sset_destroy(&types);
341
0
                return true;
342
0
            }
343
0
        }
344
0
        sset_destroy(&types);
345
0
    }
346
347
0
    return false;
348
0
}
349
350
/* Opens the network device named 'name' (e.g. "eth0") of the specified 'type'
351
 * (e.g. "system") and returns zero if successful, otherwise a positive errno
352
 * value.  On success, sets '*netdevp' to the new network device, otherwise to
353
 * null.
354
 *
355
 * Some network devices may need to be configured (with netdev_set_config())
356
 * before they can be used.
357
 *
358
 * Before opening rxqs or sending packets, '*netdevp' may need to be
359
 * reconfigured (with netdev_is_reconf_required() and netdev_reconfigure()).
360
 * */
361
int
362
netdev_open(const char *name, const char *type, struct netdev **netdevp)
363
    OVS_EXCLUDED(netdev_mutex)
364
0
{
365
0
    struct netdev *netdev;
366
0
    int error = 0;
367
368
0
    if (!name[0]) {
369
        /* Reject empty names.  This saves the providers having to do this.  At
370
         * least one screwed this up: the netdev-linux "tap" implementation
371
         * passed the name directly to the Linux TUNSETIFF call, which treats
372
         * an empty string as a request to generate a unique name. */
373
0
        return EINVAL;
374
0
    }
375
376
0
    netdev_initialize();
377
378
0
    ovs_mutex_lock(&netdev_mutex);
379
0
    netdev = shash_find_data(&netdev_shash, name);
380
381
0
    if (netdev && type && type[0]) {
382
0
        if (strcmp(type, netdev->netdev_class->type)) {
383
384
0
            if (netdev->auto_classified) {
385
                /* If this device was first created without a classification
386
                 * type, for example due to routing or tunneling code, and they
387
                 * keep a reference, a "classified" call to open will fail.
388
                 * In this case we remove the classless device, and re-add it
389
                 * below. We remove the netdev from the shash, and change the
390
                 * sequence, so owners of the old classless device can
391
                 * release/cleanup. */
392
0
                if (netdev->node) {
393
0
                    shash_delete(&netdev_shash, netdev->node);
394
0
                    netdev->node = NULL;
395
0
                    netdev_change_seq_changed(netdev);
396
0
                }
397
398
0
                netdev = NULL;
399
0
            } else {
400
0
                error = EEXIST;
401
0
            }
402
0
        } else if (netdev->auto_classified) {
403
            /* If netdev reopened with type "system", clear auto_classified. */
404
0
            netdev->auto_classified = false;
405
0
        }
406
0
    }
407
408
0
    if (!netdev) {
409
0
        struct netdev_registered_class *rc;
410
411
0
        rc = netdev_lookup_class(type && type[0] ? type : "system");
412
0
        if (rc && ovs_refcount_try_ref_rcu(&rc->refcnt)) {
413
0
            netdev = rc->class->alloc();
414
0
            if (netdev) {
415
0
                memset(netdev, 0, sizeof *netdev);
416
0
                netdev->netdev_class = rc->class;
417
0
                netdev->auto_classified = type && type[0] ? false : true;
418
0
                netdev->name = xstrdup(name);
419
0
                netdev->change_seq = 1;
420
0
                netdev->reconfigure_seq = seq_create();
421
0
                netdev->last_reconfigure_seq =
422
0
                    seq_read(netdev->reconfigure_seq);
423
0
                netdev->hw_info.oor = false;
424
0
                atomic_init(&netdev->hw_info.post_process_api_supported,
425
0
                            false);
426
0
                netdev->node = shash_add(&netdev_shash, name, netdev);
427
428
                /* By default enable one tx and rx queue per netdev. */
429
0
                netdev->n_txq = netdev->netdev_class->send ? 1 : 0;
430
0
                netdev->n_rxq = netdev->netdev_class->rxq_alloc ? 1 : 0;
431
432
0
                ovs_list_init(&netdev->saved_flags_list);
433
434
0
                error = rc->class->construct(netdev);
435
0
                if (!error) {
436
0
                    netdev_change_seq_changed(netdev);
437
0
                } else {
438
0
                    ovs_refcount_unref(&rc->refcnt);
439
0
                    seq_destroy(netdev->reconfigure_seq);
440
0
                    free(netdev->name);
441
0
                    ovs_assert(ovs_list_is_empty(&netdev->saved_flags_list));
442
0
                    shash_delete(&netdev_shash, netdev->node);
443
0
                    rc->class->dealloc(netdev);
444
0
                }
445
0
            } else {
446
0
                error = ENOMEM;
447
0
            }
448
0
        } else {
449
0
            VLOG_WARN("could not create netdev %s of unknown type %s",
450
0
                      name, type);
451
0
            error = EAFNOSUPPORT;
452
0
        }
453
0
    }
454
455
0
    if (!error) {
456
0
        netdev->ref_cnt++;
457
0
        *netdevp = netdev;
458
0
    } else {
459
0
        *netdevp = NULL;
460
0
    }
461
0
    ovs_mutex_unlock(&netdev_mutex);
462
463
0
    return error;
464
0
}
465
466
/* Returns a reference to 'netdev_' for the caller to own. Returns null if
467
 * 'netdev_' is null. */
468
struct netdev *
469
netdev_ref(const struct netdev *netdev_)
470
    OVS_EXCLUDED(netdev_mutex)
471
0
{
472
0
    struct netdev *netdev = CONST_CAST(struct netdev *, netdev_);
473
474
0
    if (netdev) {
475
0
        ovs_mutex_lock(&netdev_mutex);
476
0
        ovs_assert(netdev->ref_cnt > 0);
477
0
        netdev->ref_cnt++;
478
0
        ovs_mutex_unlock(&netdev_mutex);
479
0
    }
480
0
    return netdev;
481
0
}
482
483
/* Reconfigures the device 'netdev' with 'args'.  'args' may be empty
484
 * or NULL if none are needed. */
485
int
486
netdev_set_config(struct netdev *netdev, const struct smap *args, char **errp)
487
    OVS_EXCLUDED(netdev_mutex)
488
0
{
489
0
    if (netdev->netdev_class->set_config) {
490
0
        const struct smap no_args = SMAP_INITIALIZER(&no_args);
491
0
        char *verbose_error = NULL;
492
0
        int error;
493
494
0
        error = netdev->netdev_class->set_config(netdev,
495
0
                                                 args ? args : &no_args,
496
0
                                                 &verbose_error);
497
0
        if (error) {
498
0
            VLOG_WARN_BUF(verbose_error ? NULL : errp,
499
0
                          "%s: could not set configuration (%s)",
500
0
                          netdev_get_name(netdev), ovs_strerror(error));
501
0
            if (verbose_error) {
502
0
                if (errp) {
503
0
                    *errp = verbose_error;
504
0
                } else {
505
0
                    free(verbose_error);
506
0
                }
507
0
            }
508
0
        }
509
0
        return error;
510
0
    } else if (args && !smap_is_empty(args)) {
511
0
        VLOG_WARN_BUF(errp, "%s: arguments provided to device that is not configurable",
512
0
                      netdev_get_name(netdev));
513
0
    }
514
0
    return 0;
515
0
}
516
517
/* Returns the current configuration for 'netdev' in 'args'.  The caller must
518
 * have already initialized 'args' with smap_init().  Returns 0 on success, in
519
 * which case 'args' will be filled with 'netdev''s configuration.  On failure
520
 * returns a positive errno value, in which case 'args' will be empty.
521
 *
522
 * The caller owns 'args' and its contents and must eventually free them with
523
 * smap_destroy(). */
524
int
525
netdev_get_config(const struct netdev *netdev, struct smap *args)
526
    OVS_EXCLUDED(netdev_mutex)
527
0
{
528
0
    int error;
529
530
0
    smap_clear(args);
531
0
    if (netdev->netdev_class->get_config) {
532
0
        error = netdev->netdev_class->get_config(netdev, args);
533
0
        if (error) {
534
0
            smap_clear(args);
535
0
        }
536
0
    } else {
537
0
        error = 0;
538
0
    }
539
540
0
    return error;
541
0
}
542
543
const struct netdev_tunnel_config *
544
netdev_get_tunnel_config(const struct netdev *netdev)
545
    OVS_EXCLUDED(netdev_mutex)
546
0
{
547
0
    if (netdev->netdev_class->get_tunnel_config) {
548
0
        return netdev->netdev_class->get_tunnel_config(netdev);
549
0
    } else {
550
0
        return NULL;
551
0
    }
552
0
}
553
554
/* Returns the id of the numa node the 'netdev' is on.  If the function
555
 * is not implemented, returns NETDEV_NUMA_UNSPEC. */
556
int
557
netdev_get_numa_id(const struct netdev *netdev)
558
0
{
559
0
    if (netdev->netdev_class->get_numa_id) {
560
0
        return netdev->netdev_class->get_numa_id(netdev);
561
0
    } else {
562
0
        return NETDEV_NUMA_UNSPEC;
563
0
    }
564
0
}
565
566
static void
567
netdev_unref(struct netdev *dev)
568
    OVS_RELEASES(netdev_mutex)
569
0
{
570
0
    ovs_assert(dev->ref_cnt);
571
0
    if (!--dev->ref_cnt) {
572
0
        const struct netdev_class *class = dev->netdev_class;
573
0
        struct netdev_registered_class *rc;
574
575
0
        dev->netdev_class->destruct(dev);
576
577
0
        if (dev->node) {
578
0
            shash_delete(&netdev_shash, dev->node);
579
0
        }
580
0
        free(dev->name);
581
0
        seq_destroy(dev->reconfigure_seq);
582
0
        dev->netdev_class->dealloc(dev);
583
0
        ovs_mutex_unlock(&netdev_mutex);
584
585
0
        rc = netdev_lookup_class(class->type);
586
0
        ovs_refcount_unref(&rc->refcnt);
587
0
    } else {
588
0
        ovs_mutex_unlock(&netdev_mutex);
589
0
    }
590
0
}
591
592
/* Closes and destroys 'netdev'. */
593
void
594
netdev_close(struct netdev *netdev)
595
    OVS_EXCLUDED(netdev_mutex)
596
0
{
597
0
    if (netdev) {
598
0
        ovs_mutex_lock(&netdev_mutex);
599
0
        netdev_unref(netdev);
600
0
    }
601
0
}
602
603
/* Removes 'netdev' from the global shash and unrefs 'netdev'.
604
 *
605
 * This allows handler and revalidator threads to still retain references
606
 * to this netdev while the main thread changes interface configuration.
607
 *
608
 * This function should only be called by the main thread when closing
609
 * netdevs during user configuration changes. Otherwise, netdev_close should be
610
 * used to close netdevs. */
611
void
612
netdev_remove(struct netdev *netdev)
613
0
{
614
0
    if (netdev) {
615
0
        ovs_mutex_lock(&netdev_mutex);
616
0
        if (netdev->node) {
617
0
            shash_delete(&netdev_shash, netdev->node);
618
0
            netdev->node = NULL;
619
0
            netdev_change_seq_changed(netdev);
620
0
        }
621
0
        netdev_unref(netdev);
622
0
    }
623
0
}
624
625
/* Parses 'netdev_name_', which is of the form [type@]name into its component
626
 * pieces.  'name' and 'type' must be freed by the caller. */
627
void
628
netdev_parse_name(const char *netdev_name_, char **name, char **type)
629
0
{
630
0
    char *netdev_name = xstrdup(netdev_name_);
631
0
    char *separator;
632
633
0
    separator = strchr(netdev_name, '@');
634
0
    if (separator) {
635
0
        *separator = '\0';
636
0
        *type = netdev_name;
637
0
        *name = xstrdup(separator + 1);
638
0
    } else {
639
0
        *name = netdev_name;
640
0
        *type = xstrdup("system");
641
0
    }
642
0
}
643
644
/* Attempts to open a netdev_rxq handle for obtaining packets received on
645
 * 'netdev'.  On success, returns 0 and stores a nonnull 'netdev_rxq *' into
646
 * '*rxp'.  On failure, returns a positive errno value and stores NULL into
647
 * '*rxp'.
648
 *
649
 * Some kinds of network devices might not support receiving packets.  This
650
 * function returns EOPNOTSUPP in that case.*/
651
int
652
netdev_rxq_open(struct netdev *netdev, struct netdev_rxq **rxp, int id)
653
    OVS_EXCLUDED(netdev_mutex)
654
0
{
655
0
    int error;
656
657
0
    if (netdev->netdev_class->rxq_alloc && id < netdev->n_rxq) {
658
0
        struct netdev_rxq *rx = netdev->netdev_class->rxq_alloc();
659
0
        if (rx) {
660
0
            rx->netdev = netdev;
661
0
            rx->queue_id = id;
662
0
            error = netdev->netdev_class->rxq_construct(rx);
663
0
            if (!error) {
664
0
                netdev_ref(netdev);
665
0
                *rxp = rx;
666
0
                return 0;
667
0
            }
668
0
            netdev->netdev_class->rxq_dealloc(rx);
669
0
        } else {
670
0
            error = ENOMEM;
671
0
        }
672
0
    } else {
673
0
        error = EOPNOTSUPP;
674
0
    }
675
676
0
    *rxp = NULL;
677
0
    return error;
678
0
}
679
680
/* Closes 'rx'. */
681
void
682
netdev_rxq_close(struct netdev_rxq *rx)
683
    OVS_EXCLUDED(netdev_mutex)
684
0
{
685
0
    if (rx) {
686
0
        struct netdev *netdev = rx->netdev;
687
0
        netdev->netdev_class->rxq_destruct(rx);
688
0
        netdev->netdev_class->rxq_dealloc(rx);
689
0
        netdev_close(netdev);
690
0
    }
691
0
}
692
693
bool netdev_rxq_enabled(struct netdev_rxq *rx)
694
0
{
695
0
    bool enabled = true;
696
697
0
    if (rx->netdev->netdev_class->rxq_enabled) {
698
0
        enabled = rx->netdev->netdev_class->rxq_enabled(rx);
699
0
    }
700
0
    return enabled;
701
0
}
702
703
/* Attempts to receive a batch of packets from 'rx'.  'batch' should point to
704
 * the beginning of an array of NETDEV_MAX_BURST pointers to dp_packet.  If
705
 * successful, this function stores pointers to up to NETDEV_MAX_BURST
706
 * dp_packets into the array, transferring ownership of the packets to the
707
 * caller, stores the number of received packets in 'batch->count', and returns
708
 * 0.
709
 *
710
 * The implementation does not necessarily initialize any non-data members of
711
 * 'batch'.  That is, the caller must initialize layer pointers and metadata
712
 * itself, if desired, e.g. with pkt_metadata_init() and miniflow_extract().
713
 *
714
 * Returns EAGAIN immediately if no packet is ready to be received or another
715
 * positive errno value if an error was encountered. */
716
int
717
netdev_rxq_recv(struct netdev_rxq *rx, struct dp_packet_batch *batch,
718
                int *qfill)
719
0
{
720
0
    int retval;
721
722
0
    retval = rx->netdev->netdev_class->rxq_recv(rx, batch, qfill);
723
0
    if (!retval) {
724
0
        COVERAGE_INC(netdev_received);
725
0
    } else {
726
0
        batch->count = 0;
727
0
    }
728
0
    return retval;
729
0
}
730
731
/* Arranges for poll_block() to wake up when a packet is ready to be received
732
 * on 'rx'. */
733
void
734
netdev_rxq_wait(struct netdev_rxq *rx)
735
0
{
736
0
    rx->netdev->netdev_class->rxq_wait(rx);
737
0
}
738
739
/* Discards any packets ready to be received on 'rx'. */
740
int
741
netdev_rxq_drain(struct netdev_rxq *rx)
742
0
{
743
0
    return (rx->netdev->netdev_class->rxq_drain
744
0
            ? rx->netdev->netdev_class->rxq_drain(rx)
745
0
            : 0);
746
0
}
747
748
/* Configures the number of tx queues of 'netdev'. Returns 0 if successful,
749
 * otherwise a positive errno value.
750
 *
751
 * 'n_txq' specifies the exact number of transmission queues to create.
752
 *
753
 * The change might not effective immediately.  The caller must check if a
754
 * reconfiguration is required with netdev_is_reconf_required() and eventually
755
 * call netdev_reconfigure() before using the new queues.
756
 *
757
 * On error, the tx queue configuration is unchanged */
758
int
759
netdev_set_tx_multiq(struct netdev *netdev, unsigned int n_txq)
760
0
{
761
0
    int error;
762
763
0
    error = (netdev->netdev_class->set_tx_multiq
764
0
             ? netdev->netdev_class->set_tx_multiq(netdev, MAX(n_txq, 1))
765
0
             : EOPNOTSUPP);
766
767
0
    if (error && error != EOPNOTSUPP) {
768
0
        VLOG_DBG_RL(&rl, "failed to set tx queue for network device %s:"
769
0
                    "%s", netdev_get_name(netdev), ovs_strerror(error));
770
0
    }
771
772
0
    return error;
773
0
}
774
775
enum netdev_pt_mode
776
netdev_get_pt_mode(const struct netdev *netdev)
777
0
{
778
0
    return (netdev->netdev_class->get_pt_mode
779
0
            ? netdev->netdev_class->get_pt_mode(netdev)
780
0
            : NETDEV_PT_LEGACY_L2);
781
0
}
782
783
/* Sends 'batch' on 'netdev'.  Returns 0 if successful (for every packet),
784
 * otherwise a positive errno value.  Returns EAGAIN without blocking if
785
 * at least one the packets cannot be queued immediately.  Returns EMSGSIZE
786
 * if a partial packet was transmitted or if a packet is too big or too small
787
 * to transmit on the device.
788
 *
789
 * The caller must make sure that 'netdev' supports sending by making sure that
790
 * 'netdev_n_txq(netdev)' returns >= 1.
791
 *
792
 * If the function returns a non-zero value, some of the packets might have
793
 * been sent anyway.
794
 *
795
 * The caller transfers ownership of all the packets to the network device,
796
 * regardless of success.
797
 *
798
 * If 'concurrent_txq' is true, the caller may perform concurrent calls
799
 * to netdev_send() with the same 'qid'. The netdev provider is responsible
800
 * for making sure that these concurrent calls do not create a race condition
801
 * by using locking or other synchronization if required.
802
 *
803
 * The network device is expected to maintain one or more packet
804
 * transmission queues, so that the caller does not ordinarily have to
805
 * do additional queuing of packets.  'qid' specifies the queue to use
806
 * and can be ignored if the implementation does not support multiple
807
 * queues. */
808
int
809
netdev_send(struct netdev *netdev, int qid, struct dp_packet_batch *batch,
810
            bool concurrent_txq)
811
0
{
812
0
    const uint64_t netdev_flags = netdev->ol_flags;
813
0
    struct dp_packet *packet;
814
0
    int error;
815
816
0
    if (userspace_tso_enabled()) {
817
0
        if (!(netdev_flags & NETDEV_TX_OFFLOAD_TCP_TSO)) {
818
0
            DP_PACKET_BATCH_FOR_EACH (i, packet, batch) {
819
0
                if (dp_packet_get_tso_segsz(packet)) {
820
0
                    dp_packet_gso_batch(batch);
821
0
                    break;
822
0
                }
823
0
            }
824
0
        } else if (!(netdev_flags & (NETDEV_TX_VXLAN_TNL_TSO |
825
0
                                     NETDEV_TX_GRE_TNL_TSO |
826
0
                                     NETDEV_TX_GENEVE_TNL_TSO))) {
827
0
            DP_PACKET_BATCH_FOR_EACH (i, packet, batch) {
828
0
                if (dp_packet_get_tso_segsz(packet)
829
0
                    && dp_packet_tunnel(packet)) {
830
0
                    dp_packet_gso_batch(batch);
831
0
                    break;
832
0
                }
833
0
            }
834
0
        } else if (!(netdev_flags & NETDEV_TX_OFFLOAD_OUTER_UDP_CKSUM)) {
835
0
            DP_PACKET_BATCH_FOR_EACH (i, packet, batch) {
836
0
                if (dp_packet_get_tso_segsz(packet)
837
0
                    && dp_packet_gso_partial_nr_segs(packet) != 1) {
838
0
                    dp_packet_gso_batch_partial(batch);
839
0
                    break;
840
0
                }
841
0
            }
842
0
        }
843
0
    }
844
845
0
    DP_PACKET_BATCH_FOR_EACH (i, packet, batch) {
846
0
        dp_packet_ol_send_prepare(packet, netdev_flags);
847
0
    }
848
849
0
    error = netdev->netdev_class->send(netdev, qid, batch, concurrent_txq);
850
0
    if (!error) {
851
0
        COVERAGE_INC(netdev_sent);
852
0
    }
853
0
    return error;
854
0
}
855
856
/* Pop tunnel header, build tunnel metadata and resize 'batch->packets'
857
 * for further processing.
858
 *
859
 * The caller must make sure that 'netdev' support this operation by checking
860
 * that netdev_has_tunnel_push_pop() returns true. */
861
void
862
netdev_pop_header(struct netdev *netdev, struct dp_packet_batch *batch)
863
0
{
864
0
    struct dp_packet *packet;
865
0
    size_t i, size = dp_packet_batch_size(batch);
866
867
0
    DP_PACKET_BATCH_REFILL_FOR_EACH (i, size, packet, batch) {
868
0
        packet = netdev->netdev_class->pop_header(packet);
869
0
        if (packet) {
870
            /* Reset the offload flags if present, to avoid wrong
871
             * interpretation in the further packet processing when
872
             * recirculated.*/
873
0
            dp_packet_reset_offload(packet);
874
0
            pkt_metadata_init_conn(&packet->md);
875
0
            dp_packet_batch_add(batch, packet);
876
0
        }
877
0
    }
878
0
}
879
880
void
881
netdev_init_tnl_build_header_params(struct netdev_tnl_build_header_params *params,
882
                                    const struct flow *tnl_flow,
883
                                    const struct in6_addr *src,
884
                                    struct eth_addr dmac,
885
                                    struct eth_addr smac)
886
0
{
887
0
    params->flow = tnl_flow;
888
0
    params->dmac = dmac;
889
0
    params->smac = smac;
890
0
    params->s_ip = src;
891
0
    params->is_ipv6 = !IN6_IS_ADDR_V4MAPPED(src);
892
0
}
893
894
int netdev_build_header(const struct netdev *netdev,
895
                        struct ovs_action_push_tnl *data,
896
                        const struct netdev_tnl_build_header_params *params)
897
0
{
898
0
    if (netdev->netdev_class->build_header) {
899
0
        return netdev->netdev_class->build_header(netdev, data, params);
900
0
    }
901
0
    return EOPNOTSUPP;
902
0
}
903
904
/* Push tunnel header (reading from tunnel metadata) and resize
905
 * 'batch->packets' for further processing.
906
 *
907
 * The caller must make sure that 'netdev' support this operation by checking
908
 * that netdev_has_tunnel_push_pop() returns true. */
909
int
910
netdev_push_header(const struct netdev *netdev,
911
                   const struct netdev *ingress_netdev,
912
                   struct dp_packet_batch *batch,
913
                   const struct ovs_action_push_tnl *data)
914
0
{
915
0
    bool supported_offloads = (data->tnl_type == OVS_VPORT_TYPE_GENEVE)
916
0
                              || (data->tnl_type == OVS_VPORT_TYPE_VXLAN)
917
0
                              || (data->tnl_type == OVS_VPORT_TYPE_GRE)
918
0
                              || (data->tnl_type == OVS_VPORT_TYPE_IP6GRE);
919
0
    struct dp_packet *packet;
920
921
0
    if (userspace_tso_enabled()) {
922
0
        if (OVS_UNLIKELY(!supported_offloads)) {
923
0
            size_t i, size = dp_packet_batch_size(batch);
924
925
0
            DP_PACKET_BATCH_REFILL_FOR_EACH (i, size, packet, batch) {
926
0
                if (OVS_UNLIKELY(dp_packet_get_tso_segsz(packet))) {
927
0
                    COVERAGE_INC(netdev_push_header_drops);
928
0
                    dp_packet_delete(packet);
929
0
                    VLOG_WARN_RL(&rl, "%s: Tunneling packets with TSO is not "
930
0
                                 "supported for %s tunnels: packet dropped",
931
0
                                 netdev_get_name(netdev),
932
0
                                 netdev_get_type(netdev));
933
0
                    continue;
934
0
                }
935
0
                dp_packet_batch_add(batch, packet);
936
0
            }
937
0
        } else {
938
0
            DP_PACKET_BATCH_FOR_EACH (i, packet, batch) {
939
0
                if (dp_packet_tunnel(packet)
940
0
                    && dp_packet_get_tso_segsz(packet)) {
941
0
                    dp_packet_gso_batch(batch);
942
0
                    break;
943
0
                }
944
0
            }
945
0
        }
946
0
    }
947
948
0
    DP_PACKET_BATCH_FOR_EACH (i, packet, batch) {
949
0
        if (!supported_offloads || dp_packet_tunnel(packet)) {
950
0
            dp_packet_ol_send_prepare(packet, 0);
951
0
        }
952
0
        netdev->netdev_class->push_header(netdev, ingress_netdev, packet,
953
0
                                          data);
954
0
        pkt_metadata_init(&packet->md, data->out_port);
955
0
    }
956
957
0
    return 0;
958
0
}
959
960
/* Registers with the poll loop to wake up from the next call to poll_block()
961
 * when the packet transmission queue has sufficient room to transmit a packet
962
 * with netdev_send().
963
 *
964
 * The network device is expected to maintain one or more packet
965
 * transmission queues, so that the caller does not ordinarily have to
966
 * do additional queuing of packets.  'qid' specifies the queue to use
967
 * and can be ignored if the implementation does not support multiple
968
 * queues. */
969
void
970
netdev_send_wait(struct netdev *netdev, int qid)
971
0
{
972
0
    if (netdev->netdev_class->send_wait) {
973
0
        netdev->netdev_class->send_wait(netdev, qid);
974
0
    }
975
0
}
976
977
/* Attempts to set 'netdev''s MAC address to 'mac'.  Returns 0 if successful,
978
 * otherwise a positive errno value. */
979
int
980
netdev_set_etheraddr(struct netdev *netdev, const struct eth_addr mac)
981
0
{
982
0
    return netdev->netdev_class->set_etheraddr(netdev, mac);
983
0
}
984
985
/* Retrieves 'netdev''s MAC address.  If successful, returns 0 and copies the
986
 * the MAC address into 'mac'.  On failure, returns a positive errno value and
987
 * clears 'mac' to all-zeros. */
988
int
989
netdev_get_etheraddr(const struct netdev *netdev, struct eth_addr *mac)
990
0
{
991
0
    int error;
992
993
0
    error = netdev->netdev_class->get_etheraddr(netdev, mac);
994
0
    if (error) {
995
0
        memset(mac, 0, sizeof *mac);
996
0
    }
997
0
    return error;
998
0
}
999
1000
/* Returns the name of the network device that 'netdev' represents,
1001
 * e.g. "eth0".  The caller must not modify or free the returned string. */
1002
const char *
1003
netdev_get_name(const struct netdev *netdev)
1004
0
{
1005
0
    return netdev->name;
1006
0
}
1007
1008
/* Retrieves the MTU of 'netdev'.  The MTU is the maximum size of transmitted
1009
 * (and received) packets, in bytes, not including the hardware header; thus,
1010
 * this is typically 1500 bytes for Ethernet devices.
1011
 *
1012
 * If successful, returns 0 and stores the MTU size in '*mtup'.  Returns
1013
 * EOPNOTSUPP if 'netdev' does not have an MTU (as e.g. some tunnels do not).
1014
 * On other failure, returns a positive errno value.  On failure, sets '*mtup'
1015
 * to 0. */
1016
int
1017
netdev_get_mtu(const struct netdev *netdev, int *mtup)
1018
0
{
1019
0
    const struct netdev_class *class = netdev->netdev_class;
1020
0
    int error;
1021
1022
0
    error = class->get_mtu ? class->get_mtu(netdev, mtup) : EOPNOTSUPP;
1023
0
    if (error) {
1024
0
        *mtup = 0;
1025
0
        if (error != EOPNOTSUPP) {
1026
0
            VLOG_DBG_RL(&rl, "failed to retrieve MTU for network device %s: "
1027
0
                         "%s", netdev_get_name(netdev), ovs_strerror(error));
1028
0
        }
1029
0
    }
1030
0
    return error;
1031
0
}
1032
1033
/* Sets the MTU of 'netdev'.  The MTU is the maximum size of transmitted
1034
 * (and received) packets, in bytes.
1035
 *
1036
 * If successful, returns 0.  Returns EOPNOTSUPP if 'netdev' does not have an
1037
 * MTU (as e.g. some tunnels do not).  On other failure, returns a positive
1038
 * errno value. */
1039
int
1040
netdev_set_mtu(struct netdev *netdev, int mtu)
1041
0
{
1042
0
    const struct netdev_class *class = netdev->netdev_class;
1043
0
    int error;
1044
1045
0
    error = class->set_mtu ? class->set_mtu(netdev, mtu) : EOPNOTSUPP;
1046
0
    if (error && error != EOPNOTSUPP) {
1047
0
        VLOG_WARN_RL(&rl, "failed to set MTU for network device %s: %s",
1048
0
                     netdev_get_name(netdev), ovs_strerror(error));
1049
0
    }
1050
1051
0
    return error;
1052
0
}
1053
1054
/* If 'user_config' is true, the user wants to control 'netdev''s MTU and we
1055
 * should not override it.  If 'user_config' is false, we may adjust
1056
 * 'netdev''s MTU (e.g., if 'netdev' is internal). */
1057
void
1058
netdev_mtu_user_config(struct netdev *netdev, bool user_config)
1059
0
{
1060
0
    if (netdev->mtu_user_config != user_config) {
1061
0
        netdev_change_seq_changed(netdev);
1062
0
        netdev->mtu_user_config = user_config;
1063
0
    }
1064
0
}
1065
1066
/* Returns 'true' if the user explicitly specified an MTU value for 'netdev'.
1067
 * Otherwise, returns 'false', in which case we are allowed to adjust the
1068
 * device MTU. */
1069
bool
1070
netdev_mtu_is_user_config(struct netdev *netdev)
1071
0
{
1072
0
    return netdev->mtu_user_config;
1073
0
}
1074
1075
/* Returns the ifindex of 'netdev', if successful, as a positive number.  On
1076
 * failure, returns a negative errno value.
1077
 *
1078
 * The desired semantics of the ifindex value are a combination of those
1079
 * specified by POSIX for if_nametoindex() and by SNMP for ifIndex.  An ifindex
1080
 * value should be unique within a host and remain stable at least until
1081
 * reboot.  SNMP says an ifindex "ranges between 1 and the value of ifNumber"
1082
 * but many systems do not follow this rule anyhow.
1083
 *
1084
 * Some network devices may not implement support for this function.  In such
1085
 * cases this function will always return -EOPNOTSUPP.
1086
 */
1087
int
1088
netdev_get_ifindex(const struct netdev *netdev)
1089
0
{
1090
0
    int (*get_ifindex)(const struct netdev *);
1091
1092
0
    get_ifindex = netdev->netdev_class->get_ifindex;
1093
1094
0
    return get_ifindex ? get_ifindex(netdev) : -EOPNOTSUPP;
1095
0
}
1096
1097
/* Stores the features supported by 'netdev' into each of '*current',
1098
 * '*advertised', '*supported', and '*peer' that are non-null.  Each value is a
1099
 * bitmap of "enum ofp_port_features" bits, in host byte order.  Returns 0 if
1100
 * successful, otherwise a positive errno value.  On failure, all of the
1101
 * passed-in values are set to 0.
1102
 *
1103
 * Some network devices may not implement support for this function.  In such
1104
 * cases this function will always return EOPNOTSUPP. */
1105
int
1106
netdev_get_features(const struct netdev *netdev,
1107
                    enum netdev_features *current,
1108
                    enum netdev_features *advertised,
1109
                    enum netdev_features *supported,
1110
                    enum netdev_features *peer)
1111
0
{
1112
0
    int (*get_features)(const struct netdev *netdev,
1113
0
                        enum netdev_features *current,
1114
0
                        enum netdev_features *advertised,
1115
0
                        enum netdev_features *supported,
1116
0
                        enum netdev_features *peer);
1117
0
    enum netdev_features dummy[4];
1118
0
    int error;
1119
1120
0
    if (!current) {
1121
0
        current = &dummy[0];
1122
0
    }
1123
0
    if (!advertised) {
1124
0
        advertised = &dummy[1];
1125
0
    }
1126
0
    if (!supported) {
1127
0
        supported = &dummy[2];
1128
0
    }
1129
0
    if (!peer) {
1130
0
        peer = &dummy[3];
1131
0
    }
1132
1133
0
    get_features = netdev->netdev_class->get_features;
1134
0
    error = get_features
1135
0
                    ? get_features(netdev, current, advertised, supported,
1136
0
                                   peer)
1137
0
                    : EOPNOTSUPP;
1138
0
    if (error) {
1139
0
        *current = *advertised = *supported = *peer = 0;
1140
0
    }
1141
0
    return error;
1142
0
}
1143
1144
int
1145
netdev_get_speed(const struct netdev *netdev, uint32_t *current, uint32_t *max)
1146
0
{
1147
0
    uint32_t current_dummy, max_dummy;
1148
0
    int error;
1149
1150
0
    if (!current) {
1151
0
        current = &current_dummy;
1152
0
    }
1153
0
    if (!max) {
1154
0
        max = &max_dummy;
1155
0
    }
1156
1157
0
    error = netdev->netdev_class->get_speed
1158
0
            ? netdev->netdev_class->get_speed(netdev, current, max)
1159
0
            : EOPNOTSUPP;
1160
1161
0
    if (error == EOPNOTSUPP) {
1162
0
        enum netdev_features current_f, supported_f;
1163
1164
0
        error = netdev_get_features(netdev, &current_f, NULL,
1165
0
                                    &supported_f, NULL);
1166
0
        *current = netdev_features_to_bps(current_f, 0) / 1000000;
1167
0
        *max = netdev_features_to_bps(supported_f, 0) / 1000000;
1168
0
    } else if (error) {
1169
0
        *current = *max = 0;
1170
0
    }
1171
0
    return error;
1172
0
}
1173
1174
/* Returns the maximum speed of a network connection that has the NETDEV_F_*
1175
 * bits in 'features', in bits per second.  If no bits that indicate a speed
1176
 * are set in 'features', returns 'default_bps'. */
1177
uint64_t
1178
netdev_features_to_bps(enum netdev_features features,
1179
                       uint64_t default_bps)
1180
0
{
1181
0
    enum {
1182
0
        F_1000000MB = NETDEV_F_1TB_FD,
1183
0
        F_100000MB = NETDEV_F_100GB_FD,
1184
0
        F_40000MB = NETDEV_F_40GB_FD,
1185
0
        F_10000MB = NETDEV_F_10GB_FD,
1186
0
        F_1000MB = NETDEV_F_1GB_HD | NETDEV_F_1GB_FD,
1187
0
        F_100MB = NETDEV_F_100MB_HD | NETDEV_F_100MB_FD,
1188
0
        F_10MB = NETDEV_F_10MB_HD | NETDEV_F_10MB_FD
1189
0
    };
1190
1191
0
    return (  features & F_1000000MB ? UINT64_C(1000000000000)
1192
0
            : features & F_100000MB  ? UINT64_C(100000000000)
1193
0
            : features & F_40000MB   ? UINT64_C(40000000000)
1194
0
            : features & F_10000MB   ? UINT64_C(10000000000)
1195
0
            : features & F_1000MB    ? UINT64_C(1000000000)
1196
0
            : features & F_100MB     ? UINT64_C(100000000)
1197
0
            : features & F_10MB      ? UINT64_C(10000000)
1198
0
                                     : default_bps);
1199
0
}
1200
1201
/* Stores the duplex capability of 'netdev' into 'full_duplex'.
1202
 *
1203
 * Some network devices may not implement support for this function.
1204
 * In such cases this function will always return EOPNOTSUPP. */
1205
int
1206
netdev_get_duplex(const struct netdev *netdev, bool *full_duplex)
1207
0
{
1208
0
    int error;
1209
1210
0
    *full_duplex = false;
1211
0
    error = netdev->netdev_class->get_duplex
1212
0
            ? netdev->netdev_class->get_duplex(netdev, full_duplex)
1213
0
            : EOPNOTSUPP;
1214
1215
0
    if (error == EOPNOTSUPP) {
1216
0
        enum netdev_features current;
1217
1218
0
        error = netdev_get_features(netdev, &current, NULL, NULL, NULL);
1219
0
        if (!error && (current & NETDEV_F_OTHER)) {
1220
0
             error = EOPNOTSUPP;
1221
0
        }
1222
0
        if (!error) {
1223
0
            *full_duplex = (current & (NETDEV_F_10MB_FD | NETDEV_F_100MB_FD
1224
0
                                        | NETDEV_F_1GB_FD | NETDEV_F_10GB_FD
1225
0
                                        | NETDEV_F_40GB_FD | NETDEV_F_100GB_FD
1226
0
                                        | NETDEV_F_1TB_FD)) != 0;
1227
0
        }
1228
0
    }
1229
0
    return error;
1230
0
}
1231
1232
/* Set the features advertised by 'netdev' to 'advertise'.  Returns 0 if
1233
 * successful, otherwise a positive errno value. */
1234
int
1235
netdev_set_advertisements(struct netdev *netdev,
1236
                          enum netdev_features advertise)
1237
0
{
1238
0
    return (netdev->netdev_class->set_advertisements
1239
0
            ? netdev->netdev_class->set_advertisements(
1240
0
                    netdev, advertise)
1241
0
            : EOPNOTSUPP);
1242
0
}
1243
1244
static const char *
1245
netdev_feature_to_name(uint32_t bit)
1246
0
{
1247
0
    enum netdev_features f = bit;
1248
1249
0
    switch (f) {
1250
0
    case NETDEV_F_10MB_HD:    return "10MB-HD";
1251
0
    case NETDEV_F_10MB_FD:    return "10MB-FD";
1252
0
    case NETDEV_F_100MB_HD:   return "100MB-HD";
1253
0
    case NETDEV_F_100MB_FD:   return "100MB-FD";
1254
0
    case NETDEV_F_1GB_HD:     return "1GB-HD";
1255
0
    case NETDEV_F_1GB_FD:     return "1GB-FD";
1256
0
    case NETDEV_F_10GB_FD:    return "10GB-FD";
1257
0
    case NETDEV_F_40GB_FD:    return "40GB-FD";
1258
0
    case NETDEV_F_100GB_FD:   return "100GB-FD";
1259
0
    case NETDEV_F_1TB_FD:     return "1TB-FD";
1260
0
    case NETDEV_F_OTHER:      return "OTHER";
1261
0
    case NETDEV_F_COPPER:     return "COPPER";
1262
0
    case NETDEV_F_FIBER:      return "FIBER";
1263
0
    case NETDEV_F_AUTONEG:    return "AUTO_NEG";
1264
0
    case NETDEV_F_PAUSE:      return "AUTO_PAUSE";
1265
0
    case NETDEV_F_PAUSE_ASYM: return "AUTO_PAUSE_ASYM";
1266
0
    }
1267
1268
0
    return NULL;
1269
0
}
1270
1271
void
1272
netdev_features_format(struct ds *s, enum netdev_features features)
1273
0
{
1274
0
    ofp_print_bit_names(s, features, netdev_feature_to_name, ' ');
1275
0
    ds_put_char(s, '\n');
1276
0
}
1277
1278
/* Assigns 'addr' as 'netdev''s IPv4 address and 'mask' as its netmask.  If
1279
 * 'addr' is INADDR_ANY, 'netdev''s IPv4 address is cleared.  Returns a
1280
 * positive errno value. */
1281
int
1282
netdev_set_in4(struct netdev *netdev, struct in_addr addr, struct in_addr mask)
1283
0
{
1284
0
    return (netdev->netdev_class->set_in4
1285
0
            ? netdev->netdev_class->set_in4(netdev, addr, mask)
1286
0
            : EOPNOTSUPP);
1287
0
}
1288
1289
static int
1290
netdev_get_addresses_by_name(const char *device_name,
1291
                             struct in6_addr **addrsp, int *n_addrsp)
1292
0
{
1293
0
    struct netdev *netdev;
1294
0
    int error = netdev_open(device_name, NULL, &netdev);
1295
0
    if (error) {
1296
0
        *addrsp = NULL;
1297
0
        *n_addrsp = 0;
1298
0
        return error;
1299
0
    }
1300
1301
0
    struct in6_addr *masks;
1302
0
    error = netdev_get_addr_list(netdev, addrsp, &masks, n_addrsp);
1303
0
    netdev_close(netdev);
1304
0
    free(masks);
1305
0
    return error;
1306
0
}
1307
1308
/* Obtains an IPv4 address from 'device_name' and save the address in '*in4'.
1309
 * Returns 0 if successful, otherwise a positive errno value. */
1310
int
1311
netdev_get_in4_by_name(const char *device_name, struct in_addr *in4)
1312
0
{
1313
0
    struct in6_addr *addrs;
1314
0
    int n;
1315
0
    int error = netdev_get_addresses_by_name(device_name, &addrs, &n);
1316
1317
0
    in4->s_addr = 0;
1318
0
    if (!error) {
1319
0
        error = ENOENT;
1320
0
        for (int i = 0; i < n; i++) {
1321
0
            if (IN6_IS_ADDR_V4MAPPED(&addrs[i])) {
1322
0
                in4->s_addr = in6_addr_get_mapped_ipv4(&addrs[i]);
1323
0
                error = 0;
1324
0
                break;
1325
0
            }
1326
0
        }
1327
0
    }
1328
0
    free(addrs);
1329
1330
0
    return error;
1331
0
}
1332
1333
/* Obtains an IPv4 or IPv6 address from 'device_name' and save the address in
1334
 * '*in6', representing IPv4 addresses as v6-mapped.  Returns 0 if successful,
1335
 * otherwise a positive errno value. */
1336
int
1337
netdev_get_ip_by_name(const char *device_name, struct in6_addr *in6)
1338
0
{
1339
0
    struct in6_addr *addrs;
1340
0
    int n;
1341
0
    int error = netdev_get_addresses_by_name(device_name, &addrs, &n);
1342
1343
0
    *in6 = in6addr_any;
1344
0
    if (!error) {
1345
0
        error = ENOENT;
1346
0
        for (int i = 0; i < n; i++) {
1347
0
            if (!in6_is_lla(&addrs[i])) {
1348
0
                *in6 = addrs[i];
1349
0
                error = 0;
1350
0
                break;
1351
0
            }
1352
0
        }
1353
0
    }
1354
0
    free(addrs);
1355
1356
0
    return error;
1357
0
}
1358
1359
/* Adds 'router' as a default IP gateway for the TCP/IP stack that corresponds
1360
 * to 'netdev'. */
1361
int
1362
netdev_add_router(struct netdev *netdev, struct in_addr router)
1363
0
{
1364
0
    COVERAGE_INC(netdev_add_router);
1365
0
    return (netdev->netdev_class->add_router
1366
0
            ? netdev->netdev_class->add_router(netdev, router)
1367
0
            : EOPNOTSUPP);
1368
0
}
1369
1370
/* Looks up the next hop for 'host' for the TCP/IP stack that corresponds to
1371
 * 'netdev'.  If a route cannot not be determined, sets '*next_hop' to 0,
1372
 * '*netdev_name' to null, and returns a positive errno value.  Otherwise, if a
1373
 * next hop is found, stores the next hop gateway's address (0 if 'host' is on
1374
 * a directly connected network) in '*next_hop' and a copy of the name of the
1375
 * device to reach 'host' in '*netdev_name', and returns 0.  The caller is
1376
 * responsible for freeing '*netdev_name' (by calling free()). */
1377
int
1378
netdev_get_next_hop(const struct netdev *netdev,
1379
                    const struct in_addr *host, struct in_addr *next_hop,
1380
                    char **netdev_name)
1381
0
{
1382
0
    int error = (netdev->netdev_class->get_next_hop
1383
0
                 ? netdev->netdev_class->get_next_hop(
1384
0
                        host, next_hop, netdev_name)
1385
0
                 : EOPNOTSUPP);
1386
0
    if (error) {
1387
0
        next_hop->s_addr = 0;
1388
0
        *netdev_name = NULL;
1389
0
    }
1390
0
    return error;
1391
0
}
1392
1393
/* Populates 'smap' with status information.
1394
 *
1395
 * Populates 'smap' with 'netdev' specific status information.  This
1396
 * information may be used to populate the status column of the Interface table
1397
 * as defined in ovs-vswitchd.conf.db(5). */
1398
int
1399
netdev_get_status(const struct netdev *netdev, struct smap *smap)
1400
0
{
1401
0
    int err = EOPNOTSUPP;
1402
1403
    /* Set offload status only if relevant. */
1404
0
    if (netdev_get_dpif_type(netdev) &&
1405
0
        strcmp(netdev_get_dpif_type(netdev), "system")) {
1406
1407
0
#define OL_ADD_STAT(name, bit) \
1408
0
        smap_add(smap, "tx_" name "_offload", \
1409
0
                 netdev->ol_flags & bit ? "true" : "false");
1410
1411
0
        OL_ADD_STAT("ip_csum", NETDEV_TX_OFFLOAD_IPV4_CKSUM);
1412
0
        OL_ADD_STAT("tcp_csum", NETDEV_TX_OFFLOAD_TCP_CKSUM);
1413
0
        OL_ADD_STAT("udp_csum", NETDEV_TX_OFFLOAD_UDP_CKSUM);
1414
0
        OL_ADD_STAT("sctp_csum", NETDEV_TX_OFFLOAD_SCTP_CKSUM);
1415
0
        OL_ADD_STAT("tcp_seg", NETDEV_TX_OFFLOAD_TCP_TSO);
1416
0
        OL_ADD_STAT("vxlan_tso", NETDEV_TX_VXLAN_TNL_TSO);
1417
0
        OL_ADD_STAT("gre_tso", NETDEV_TX_GRE_TNL_TSO);
1418
0
        OL_ADD_STAT("geneve_tso", NETDEV_TX_GENEVE_TNL_TSO);
1419
0
        OL_ADD_STAT("out_ip_csum", NETDEV_TX_OFFLOAD_OUTER_IP_CKSUM);
1420
0
        OL_ADD_STAT("out_udp_csum", NETDEV_TX_OFFLOAD_OUTER_UDP_CKSUM);
1421
0
#undef OL_ADD_STAT
1422
1423
0
        err = 0;
1424
0
    }
1425
1426
0
    if (!netdev->netdev_class->get_status) {
1427
0
        return err;
1428
0
    }
1429
1430
0
    return netdev->netdev_class->get_status(netdev, smap);
1431
0
}
1432
1433
/* Returns all assigned IP address to  'netdev' and returns 0.
1434
 * API allocates array of address and masks and set it to
1435
 * '*addr' and '*mask'.
1436
 * Otherwise, returns a positive errno value and sets '*addr', '*mask
1437
 * and '*n_addr' to NULL.
1438
 *
1439
 * The following error values have well-defined meanings:
1440
 *
1441
 *   - EADDRNOTAVAIL: 'netdev' has no assigned IPv6 address.
1442
 *
1443
 *   - EOPNOTSUPP: No IPv6 network stack attached to 'netdev'.
1444
 *
1445
 * 'addr' may be null, in which case the address itself is not reported. */
1446
int
1447
netdev_get_addr_list(const struct netdev *netdev, struct in6_addr **addr,
1448
                     struct in6_addr **mask, int *n_addr)
1449
0
{
1450
0
    int error;
1451
1452
0
    error = (netdev->netdev_class->get_addr_list
1453
0
             ? netdev->netdev_class->get_addr_list(netdev, addr, mask, n_addr): EOPNOTSUPP);
1454
0
    if (error && addr) {
1455
0
        *addr = NULL;
1456
0
        *mask = NULL;
1457
0
        *n_addr = 0;
1458
0
    }
1459
1460
0
    return error;
1461
0
}
1462
1463
/* On 'netdev', turns off the flags in 'off' and then turns on the flags in
1464
 * 'on'.  Returns 0 if successful, otherwise a positive errno value. */
1465
static int
1466
do_update_flags(struct netdev *netdev, enum netdev_flags off,
1467
                enum netdev_flags on, enum netdev_flags *old_flagsp,
1468
                struct netdev_saved_flags **sfp)
1469
    OVS_EXCLUDED(netdev_mutex)
1470
0
{
1471
0
    struct netdev_saved_flags *sf = NULL;
1472
0
    enum netdev_flags old_flags;
1473
0
    int error;
1474
1475
0
    error = netdev->netdev_class->update_flags(netdev, off & ~on, on,
1476
0
                                               &old_flags);
1477
0
    if (error) {
1478
0
        VLOG_WARN_RL(&rl, "failed to %s flags for network device %s: %s",
1479
0
                     off || on ? "set" : "get", netdev_get_name(netdev),
1480
0
                     ovs_strerror(error));
1481
0
        old_flags = 0;
1482
0
    } else if ((off || on) && sfp) {
1483
0
        enum netdev_flags new_flags = (old_flags & ~off) | on;
1484
0
        enum netdev_flags changed_flags = old_flags ^ new_flags;
1485
0
        if (changed_flags) {
1486
0
            ovs_mutex_lock(&netdev_mutex);
1487
0
            *sfp = sf = xmalloc(sizeof *sf);
1488
0
            sf->netdev = netdev;
1489
0
            ovs_list_push_front(&netdev->saved_flags_list, &sf->node);
1490
0
            sf->saved_flags = changed_flags;
1491
0
            sf->saved_values = changed_flags & new_flags;
1492
1493
0
            netdev->ref_cnt++;
1494
0
            ovs_mutex_unlock(&netdev_mutex);
1495
0
        }
1496
0
    }
1497
1498
0
    if (old_flagsp) {
1499
0
        *old_flagsp = old_flags;
1500
0
    }
1501
0
    if (sfp) {
1502
0
        *sfp = sf;
1503
0
    }
1504
1505
0
    return error;
1506
0
}
1507
1508
/* Obtains the current flags for 'netdev' and stores them into '*flagsp'.
1509
 * Returns 0 if successful, otherwise a positive errno value.  On failure,
1510
 * stores 0 into '*flagsp'. */
1511
int
1512
netdev_get_flags(const struct netdev *netdev_, enum netdev_flags *flagsp)
1513
0
{
1514
0
    struct netdev *netdev = CONST_CAST(struct netdev *, netdev_);
1515
0
    return do_update_flags(netdev, 0, 0, flagsp, NULL);
1516
0
}
1517
1518
/* Sets the flags for 'netdev' to 'flags'.
1519
 * Returns 0 if successful, otherwise a positive errno value. */
1520
int
1521
netdev_set_flags(struct netdev *netdev, enum netdev_flags flags,
1522
                 struct netdev_saved_flags **sfp)
1523
0
{
1524
0
    return do_update_flags(netdev, -1, flags, NULL, sfp);
1525
0
}
1526
1527
/* Turns on the specified 'flags' on 'netdev':
1528
 *
1529
 *    - On success, returns 0.  If 'sfp' is nonnull, sets '*sfp' to a newly
1530
 *      allocated 'struct netdev_saved_flags *' that may be passed to
1531
 *      netdev_restore_flags() to restore the original values of 'flags' on
1532
 *      'netdev' (this will happen automatically at program termination if
1533
 *      netdev_restore_flags() is never called) , or to NULL if no flags were
1534
 *      actually changed.
1535
 *
1536
 *    - On failure, returns a positive errno value.  If 'sfp' is nonnull, sets
1537
 *      '*sfp' to NULL. */
1538
int
1539
netdev_turn_flags_on(struct netdev *netdev, enum netdev_flags flags,
1540
                     struct netdev_saved_flags **sfp)
1541
0
{
1542
0
    return do_update_flags(netdev, 0, flags, NULL, sfp);
1543
0
}
1544
1545
/* Turns off the specified 'flags' on 'netdev'.  See netdev_turn_flags_on() for
1546
 * details of the interface. */
1547
int
1548
netdev_turn_flags_off(struct netdev *netdev, enum netdev_flags flags,
1549
                      struct netdev_saved_flags **sfp)
1550
0
{
1551
0
    return do_update_flags(netdev, flags, 0, NULL, sfp);
1552
0
}
1553
1554
/* Restores the flags that were saved in 'sf', and destroys 'sf'.
1555
 * Does nothing if 'sf' is NULL. */
1556
void
1557
netdev_restore_flags(struct netdev_saved_flags *sf)
1558
    OVS_EXCLUDED(netdev_mutex)
1559
0
{
1560
0
    if (sf) {
1561
0
        struct netdev *netdev = sf->netdev;
1562
0
        enum netdev_flags old_flags;
1563
1564
0
        netdev->netdev_class->update_flags(netdev,
1565
0
                                           sf->saved_flags & sf->saved_values,
1566
0
                                           sf->saved_flags & ~sf->saved_values,
1567
0
                                           &old_flags);
1568
1569
0
        ovs_mutex_lock(&netdev_mutex);
1570
0
        ovs_list_remove(&sf->node);
1571
0
        free(sf);
1572
0
        netdev_unref(netdev);
1573
0
    }
1574
0
}
1575
1576
/* Looks up the ARP table entry for 'ip' on 'netdev'.  If one exists and can be
1577
 * successfully retrieved, it stores the corresponding MAC address in 'mac' and
1578
 * returns 0.  Otherwise, it returns a positive errno value; in particular,
1579
 * ENXIO indicates that there is no ARP table entry for 'ip' on 'netdev'. */
1580
int
1581
netdev_arp_lookup(const struct netdev *netdev,
1582
                  ovs_be32 ip, struct eth_addr *mac)
1583
0
{
1584
0
    int error = (netdev->netdev_class->arp_lookup
1585
0
                 ? netdev->netdev_class->arp_lookup(netdev, ip, mac)
1586
0
                 : EOPNOTSUPP);
1587
0
    if (error) {
1588
0
        *mac = eth_addr_zero;
1589
0
    }
1590
0
    return error;
1591
0
}
1592
1593
/* Returns true if carrier is active (link light is on) on 'netdev'. */
1594
bool
1595
netdev_get_carrier(const struct netdev *netdev)
1596
0
{
1597
0
    int error;
1598
0
    enum netdev_flags flags;
1599
0
    bool carrier;
1600
1601
0
    netdev_get_flags(netdev, &flags);
1602
0
    if (!(flags & NETDEV_UP)) {
1603
0
        return false;
1604
0
    }
1605
1606
0
    if (!netdev->netdev_class->get_carrier) {
1607
0
        return true;
1608
0
    }
1609
1610
0
    error = netdev->netdev_class->get_carrier(netdev, &carrier);
1611
0
    if (error) {
1612
0
        VLOG_DBG("%s: failed to get network device carrier status, assuming "
1613
0
                 "down: %s", netdev_get_name(netdev), ovs_strerror(error));
1614
0
        carrier = false;
1615
0
    }
1616
1617
0
    return carrier;
1618
0
}
1619
1620
/* Returns the number of times 'netdev''s carrier has changed. */
1621
long long int
1622
netdev_get_carrier_resets(const struct netdev *netdev)
1623
0
{
1624
0
    return (netdev->netdev_class->get_carrier_resets
1625
0
            ? netdev->netdev_class->get_carrier_resets(netdev)
1626
0
            : 0);
1627
0
}
1628
1629
/* Attempts to force netdev_get_carrier() to poll 'netdev''s MII registers for
1630
 * link status instead of checking 'netdev''s carrier.  'netdev''s MII
1631
 * registers will be polled once ever 'interval' milliseconds.  If 'netdev'
1632
 * does not support MII, another method may be used as a fallback.  If
1633
 * 'interval' is less than or equal to zero, reverts netdev_get_carrier() to
1634
 * its normal behavior.
1635
 *
1636
 * Returns 0 if successful, otherwise a positive errno value. */
1637
int
1638
netdev_set_miimon_interval(struct netdev *netdev, long long int interval)
1639
0
{
1640
0
    return (netdev->netdev_class->set_miimon_interval
1641
0
            ? netdev->netdev_class->set_miimon_interval(netdev, interval)
1642
0
            : EOPNOTSUPP);
1643
0
}
1644
1645
/* Retrieves current device stats for 'netdev'. */
1646
int
1647
netdev_get_stats(const struct netdev *netdev, struct netdev_stats *stats)
1648
0
{
1649
0
    int error;
1650
1651
    /* Statistics are initialized before passing it to particular device
1652
     * implementation so all values are filtered out by default. */
1653
0
    memset(stats, 0xFF, sizeof *stats);
1654
1655
0
    COVERAGE_INC(netdev_get_stats);
1656
0
    error = (netdev->netdev_class->get_stats
1657
0
             ? netdev->netdev_class->get_stats(netdev, stats)
1658
0
             : EOPNOTSUPP);
1659
0
    if (error) {
1660
        /* In case of error all statistics are filtered out */
1661
0
        memset(stats, 0xff, sizeof *stats);
1662
0
    }
1663
0
    return error;
1664
0
}
1665
1666
/* Retrieves current device custom stats for 'netdev'. */
1667
int
1668
netdev_get_custom_stats(const struct netdev *netdev,
1669
                        struct netdev_custom_stats *custom_stats)
1670
0
{
1671
0
    int error;
1672
0
    memset(custom_stats, 0, sizeof *custom_stats);
1673
0
    error = (netdev->netdev_class->get_custom_stats
1674
0
             ? netdev->netdev_class->get_custom_stats(netdev, custom_stats)
1675
0
             : EOPNOTSUPP);
1676
1677
0
    return error;
1678
0
}
1679
1680
/* Attempts to set input rate limiting (policing) policy, such that:
1681
 * - up to 'kbits_rate' kbps of traffic is accepted, with a maximum
1682
 *   accumulative burst size of 'kbits' kb; and
1683
 * - up to 'kpkts' kpps of traffic is accepted, with a maximum
1684
 *   accumulative burst size of 'kpkts' kilo packets.
1685
 */
1686
int
1687
netdev_set_policing(struct netdev *netdev, uint32_t kbits_rate,
1688
                    uint32_t kbits_burst, uint32_t kpkts_rate,
1689
                    uint32_t kpkts_burst)
1690
0
{
1691
0
    return (netdev->netdev_class->set_policing
1692
0
            ? netdev->netdev_class->set_policing(netdev,
1693
0
                    kbits_rate, kbits_burst, kpkts_rate, kpkts_burst)
1694
0
            : EOPNOTSUPP);
1695
0
}
1696
1697
/* Adds to 'types' all of the forms of QoS supported by 'netdev', or leaves it
1698
 * empty if 'netdev' does not support QoS.  Any names added to 'types' should
1699
 * be documented as valid for the "type" column in the "QoS" table in
1700
 * vswitchd/vswitch.xml (which is built as ovs-vswitchd.conf.db(8)).
1701
 *
1702
 * Every network device supports disabling QoS with a type of "", but this type
1703
 * will not be added to 'types'.
1704
 *
1705
 * The caller must initialize 'types' (e.g. with sset_init()) before calling
1706
 * this function.  The caller is responsible for destroying 'types' (e.g. with
1707
 * sset_destroy()) when it is no longer needed.
1708
 *
1709
 * Returns 0 if successful, otherwise a positive errno value. */
1710
int
1711
netdev_get_qos_types(const struct netdev *netdev, struct sset *types)
1712
0
{
1713
0
    const struct netdev_class *class = netdev->netdev_class;
1714
0
    return (class->get_qos_types
1715
0
            ? class->get_qos_types(netdev, types)
1716
0
            : 0);
1717
0
}
1718
1719
/* Queries 'netdev' for its capabilities regarding the specified 'type' of QoS,
1720
 * which should be "" or one of the types returned by netdev_get_qos_types()
1721
 * for 'netdev'.  Returns 0 if successful, otherwise a positive errno value.
1722
 * On success, initializes 'caps' with the QoS capabilities; on failure, clears
1723
 * 'caps' to all zeros. */
1724
int
1725
netdev_get_qos_capabilities(const struct netdev *netdev, const char *type,
1726
                            struct netdev_qos_capabilities *caps)
1727
0
{
1728
0
    const struct netdev_class *class = netdev->netdev_class;
1729
1730
0
    if (*type) {
1731
0
        int retval = (class->get_qos_capabilities
1732
0
                      ? class->get_qos_capabilities(netdev, type, caps)
1733
0
                      : EOPNOTSUPP);
1734
0
        if (retval) {
1735
0
            memset(caps, 0, sizeof *caps);
1736
0
        }
1737
0
        return retval;
1738
0
    } else {
1739
        /* Every netdev supports turning off QoS. */
1740
0
        memset(caps, 0, sizeof *caps);
1741
0
        return 0;
1742
0
    }
1743
0
}
1744
1745
/* Obtains the number of queues supported by 'netdev' for the specified 'type'
1746
 * of QoS.  Returns 0 if successful, otherwise a positive errno value.  Stores
1747
 * the number of queues (zero on failure) in '*n_queuesp'.
1748
 *
1749
 * This is just a simple wrapper around netdev_get_qos_capabilities(). */
1750
int
1751
netdev_get_n_queues(const struct netdev *netdev,
1752
                    const char *type, unsigned int *n_queuesp)
1753
0
{
1754
0
    struct netdev_qos_capabilities caps;
1755
0
    int retval;
1756
1757
0
    retval = netdev_get_qos_capabilities(netdev, type, &caps);
1758
0
    *n_queuesp = caps.n_queues;
1759
0
    return retval;
1760
0
}
1761
1762
/* Queries 'netdev' about its currently configured form of QoS.  If successful,
1763
 * stores the name of the current form of QoS into '*typep', stores any details
1764
 * of configuration as string key-value pairs in 'details', and returns 0.  On
1765
 * failure, sets '*typep' to NULL and returns a positive errno value.
1766
 *
1767
 * A '*typep' of "" indicates that QoS is currently disabled on 'netdev'.
1768
 *
1769
 * The caller must initialize 'details' as an empty smap (e.g. with
1770
 * smap_init()) before calling this function.  The caller must free 'details'
1771
 * when it is no longer needed (e.g. with smap_destroy()).
1772
 *
1773
 * The caller must not modify or free '*typep'.
1774
 *
1775
 * '*typep' will be one of the types returned by netdev_get_qos_types() for
1776
 * 'netdev'.  The contents of 'details' should be documented as valid for
1777
 * '*typep' in the "other_config" column in the "QoS" table in
1778
 * vswitchd/vswitch.xml (which is built as ovs-vswitchd.conf.db(8)). */
1779
int
1780
netdev_get_qos(const struct netdev *netdev,
1781
               const char **typep, struct smap *details)
1782
0
{
1783
0
    const struct netdev_class *class = netdev->netdev_class;
1784
0
    int retval;
1785
1786
0
    if (class->get_qos) {
1787
0
        retval = class->get_qos(netdev, typep, details);
1788
0
        if (retval) {
1789
0
            *typep = NULL;
1790
0
            smap_clear(details);
1791
0
        }
1792
0
        return retval;
1793
0
    } else {
1794
        /* 'netdev' doesn't support QoS, so report that QoS is disabled. */
1795
0
        *typep = "";
1796
0
        return 0;
1797
0
    }
1798
0
}
1799
1800
/* Attempts to reconfigure QoS on 'netdev', changing the form of QoS to 'type'
1801
 * with details of configuration from 'details'.  Returns 0 if successful,
1802
 * otherwise a positive errno value.  On error, the previous QoS configuration
1803
 * is retained.
1804
 *
1805
 * When this function changes the type of QoS (not just 'details'), this also
1806
 * resets all queue configuration for 'netdev' to their defaults (which depend
1807
 * on the specific type of QoS).  Otherwise, the queue configuration for
1808
 * 'netdev' is unchanged.
1809
 *
1810
 * 'type' should be "" (to disable QoS) or one of the types returned by
1811
 * netdev_get_qos_types() for 'netdev'.  The contents of 'details' should be
1812
 * documented as valid for the given 'type' in the "other_config" column in the
1813
 * "QoS" table in vswitchd/vswitch.xml (which is built as
1814
 * ovs-vswitchd.conf.db(8)).
1815
 *
1816
 * NULL may be specified for 'details' if there are no configuration
1817
 * details. */
1818
int
1819
netdev_set_qos(struct netdev *netdev,
1820
               const char *type, const struct smap *details)
1821
0
{
1822
0
    const struct netdev_class *class = netdev->netdev_class;
1823
1824
0
    if (!type) {
1825
0
        type = "";
1826
0
    }
1827
1828
0
    if (class->set_qos) {
1829
0
        if (!details) {
1830
0
            static const struct smap empty = SMAP_INITIALIZER(&empty);
1831
0
            details = &empty;
1832
0
        }
1833
0
        return class->set_qos(netdev, type, details);
1834
0
    } else {
1835
0
        return *type ? EOPNOTSUPP : 0;
1836
0
    }
1837
0
}
1838
1839
/* Queries 'netdev' for information about the queue numbered 'queue_id'.  If
1840
 * successful, adds that information as string key-value pairs to 'details'.
1841
 * Returns 0 if successful, otherwise a positive errno value.
1842
 *
1843
 * 'queue_id' must be less than the number of queues supported by 'netdev' for
1844
 * the current form of QoS (e.g. as returned by netdev_get_n_queues(netdev)).
1845
 *
1846
 * The returned contents of 'details' should be documented as valid for the
1847
 * given 'type' in the "other_config" column in the "Queue" table in
1848
 * vswitchd/vswitch.xml (which is built as ovs-vswitchd.conf.db(8)).
1849
 *
1850
 * The caller must initialize 'details' (e.g. with smap_init()) before calling
1851
 * this function.  The caller must free 'details' when it is no longer needed
1852
 * (e.g. with smap_destroy()). */
1853
int
1854
netdev_get_queue(const struct netdev *netdev,
1855
                 unsigned int queue_id, struct smap *details)
1856
0
{
1857
0
    const struct netdev_class *class = netdev->netdev_class;
1858
0
    int retval;
1859
1860
0
    retval = (class->get_queue
1861
0
              ? class->get_queue(netdev, queue_id, details)
1862
0
              : EOPNOTSUPP);
1863
0
    if (retval) {
1864
0
        smap_clear(details);
1865
0
    }
1866
0
    return retval;
1867
0
}
1868
1869
/* Configures the queue numbered 'queue_id' on 'netdev' with the key-value
1870
 * string pairs in 'details'.  The contents of 'details' should be documented
1871
 * as valid for the given 'type' in the "other_config" column in the "Queue"
1872
 * table in vswitchd/vswitch.xml (which is built as ovs-vswitchd.conf.db(8)).
1873
 * Returns 0 if successful, otherwise a positive errno value.  On failure, the
1874
 * given queue's configuration should be unmodified.
1875
 *
1876
 * 'queue_id' must be less than the number of queues supported by 'netdev' for
1877
 * the current form of QoS (e.g. as returned by netdev_get_n_queues(netdev)).
1878
 *
1879
 * This function does not modify 'details', and the caller retains ownership of
1880
 * it. */
1881
int
1882
netdev_set_queue(struct netdev *netdev,
1883
                 unsigned int queue_id, const struct smap *details)
1884
0
{
1885
0
    const struct netdev_class *class = netdev->netdev_class;
1886
0
    return (class->set_queue
1887
0
            ? class->set_queue(netdev, queue_id, details)
1888
0
            : EOPNOTSUPP);
1889
0
}
1890
1891
/* Attempts to delete the queue numbered 'queue_id' from 'netdev'.  Some kinds
1892
 * of QoS may have a fixed set of queues, in which case attempts to delete them
1893
 * will fail with EOPNOTSUPP.
1894
 *
1895
 * Returns 0 if successful, otherwise a positive errno value.  On failure, the
1896
 * given queue will be unmodified.
1897
 *
1898
 * 'queue_id' must be less than the number of queues supported by 'netdev' for
1899
 * the current form of QoS (e.g. as returned by
1900
 * netdev_get_n_queues(netdev)). */
1901
int
1902
netdev_delete_queue(struct netdev *netdev, unsigned int queue_id)
1903
0
{
1904
0
    const struct netdev_class *class = netdev->netdev_class;
1905
0
    return (class->delete_queue
1906
0
            ? class->delete_queue(netdev, queue_id)
1907
0
            : EOPNOTSUPP);
1908
0
}
1909
1910
/* Obtains statistics about 'queue_id' on 'netdev'.  On success, returns 0 and
1911
 * fills 'stats' with the queue's statistics; individual members of 'stats' may
1912
 * be set to all-1-bits if the statistic is unavailable.  On failure, returns a
1913
 * positive errno value and fills 'stats' with values indicating unsupported
1914
 * statistics. */
1915
int
1916
netdev_get_queue_stats(const struct netdev *netdev, unsigned int queue_id,
1917
                       struct netdev_queue_stats *stats)
1918
0
{
1919
0
    const struct netdev_class *class = netdev->netdev_class;
1920
0
    int retval;
1921
1922
0
    retval = (class->get_queue_stats
1923
0
              ? class->get_queue_stats(netdev, queue_id, stats)
1924
0
              : EOPNOTSUPP);
1925
0
    if (retval) {
1926
0
        stats->tx_bytes = UINT64_MAX;
1927
0
        stats->tx_packets = UINT64_MAX;
1928
0
        stats->tx_errors = UINT64_MAX;
1929
0
        stats->created = LLONG_MIN;
1930
0
    }
1931
0
    return retval;
1932
0
}
1933
1934
/* Initializes 'dump' to begin dumping the queues in a netdev.
1935
 *
1936
 * This function provides no status indication.  An error status for the entire
1937
 * dump operation is provided when it is completed by calling
1938
 * netdev_queue_dump_done().
1939
 */
1940
void
1941
netdev_queue_dump_start(struct netdev_queue_dump *dump,
1942
                        const struct netdev *netdev)
1943
0
{
1944
0
    dump->netdev = netdev_ref(netdev);
1945
0
    if (netdev->netdev_class->queue_dump_start) {
1946
0
        dump->error = netdev->netdev_class->queue_dump_start(netdev,
1947
0
                                                             &dump->state);
1948
0
    } else {
1949
0
        dump->error = EOPNOTSUPP;
1950
0
    }
1951
0
}
1952
1953
/* Attempts to retrieve another queue from 'dump', which must have been
1954
 * initialized with netdev_queue_dump_start().  On success, stores a new queue
1955
 * ID into '*queue_id', fills 'details' with configuration details for the
1956
 * queue, and returns true.  On failure, returns false.
1957
 *
1958
 * Queues are not necessarily dumped in increasing order of queue ID (or any
1959
 * other predictable order).
1960
 *
1961
 * Failure might indicate an actual error or merely that the last queue has
1962
 * been dumped.  An error status for the entire dump operation is provided when
1963
 * it is completed by calling netdev_queue_dump_done().
1964
 *
1965
 * The returned contents of 'details' should be documented as valid for the
1966
 * given 'type' in the "other_config" column in the "Queue" table in
1967
 * vswitchd/vswitch.xml (which is built as ovs-vswitchd.conf.db(8)).
1968
 *
1969
 * The caller must initialize 'details' (e.g. with smap_init()) before calling
1970
 * this function.  This function will clear and replace its contents.  The
1971
 * caller must free 'details' when it is no longer needed (e.g. with
1972
 * smap_destroy()). */
1973
bool
1974
netdev_queue_dump_next(struct netdev_queue_dump *dump,
1975
                       unsigned int *queue_id, struct smap *details)
1976
0
{
1977
0
    smap_clear(details);
1978
1979
0
    const struct netdev *netdev = dump->netdev;
1980
0
    if (dump->error) {
1981
0
        return false;
1982
0
    }
1983
1984
0
    dump->error = netdev->netdev_class->queue_dump_next(netdev, dump->state,
1985
0
                                                        queue_id, details);
1986
1987
0
    if (dump->error) {
1988
0
        netdev->netdev_class->queue_dump_done(netdev, dump->state);
1989
0
        return false;
1990
0
    }
1991
0
    return true;
1992
0
}
1993
1994
/* Completes queue table dump operation 'dump', which must have been
1995
 * initialized with netdev_queue_dump_start().  Returns 0 if the dump operation
1996
 * was error-free, otherwise a positive errno value describing the problem. */
1997
int
1998
netdev_queue_dump_done(struct netdev_queue_dump *dump)
1999
0
{
2000
0
    const struct netdev *netdev = dump->netdev;
2001
0
    if (!dump->error && netdev->netdev_class->queue_dump_done) {
2002
0
        dump->error = netdev->netdev_class->queue_dump_done(netdev,
2003
0
                                                            dump->state);
2004
0
    }
2005
0
    netdev_close(dump->netdev);
2006
0
    return dump->error == EOF ? 0 : dump->error;
2007
0
}
2008
2009
/* Iterates over all of 'netdev''s queues, calling 'cb' with the queue's ID,
2010
 * its statistics, and the 'aux' specified by the caller.  The order of
2011
 * iteration is unspecified, but (when successful) each queue is visited
2012
 * exactly once.
2013
 *
2014
 * Calling this function may be more efficient than calling
2015
 * netdev_get_queue_stats() for every queue.
2016
 *
2017
 * 'cb' must not modify or free the statistics passed in.
2018
 *
2019
 * Returns 0 if successful, otherwise a positive errno value.  On error, some
2020
 * configured queues may not have been included in the iteration. */
2021
int
2022
netdev_dump_queue_stats(const struct netdev *netdev,
2023
                        netdev_dump_queue_stats_cb *cb, void *aux)
2024
0
{
2025
0
    const struct netdev_class *class = netdev->netdev_class;
2026
0
    return (class->dump_queue_stats
2027
0
            ? class->dump_queue_stats(netdev, cb, aux)
2028
0
            : EOPNOTSUPP);
2029
0
}
2030
2031

2032
/* Returns the class type of 'netdev'.
2033
 *
2034
 * The caller must not free the returned value. */
2035
const char *
2036
netdev_get_type(const struct netdev *netdev)
2037
0
{
2038
0
    return netdev->netdev_class->type;
2039
0
}
2040
2041
/* Returns the class associated with 'netdev'. */
2042
const struct netdev_class *
2043
netdev_get_class(const struct netdev *netdev)
2044
0
{
2045
0
    return netdev->netdev_class;
2046
0
}
2047
2048
/* Set the type of 'dpif' this 'netdev' belongs to. */
2049
void
2050
netdev_set_dpif_type(struct netdev *netdev, const char *type)
2051
0
{
2052
0
    netdev->dpif_type = type;
2053
0
}
2054
2055
/* Returns the type of 'dpif' this 'netdev' belongs to.
2056
 *
2057
 * The caller must not free the returned value. */
2058
const char *
2059
netdev_get_dpif_type(const struct netdev *netdev)
2060
0
{
2061
0
    return netdev->dpif_type;
2062
0
}
2063
2064
/* Returns the netdev with 'name' or NULL if there is none.
2065
 *
2066
 * The caller must free the returned netdev with netdev_close(). */
2067
struct netdev *
2068
netdev_from_name(const char *name)
2069
    OVS_EXCLUDED(netdev_mutex)
2070
0
{
2071
0
    struct netdev *netdev;
2072
2073
0
    ovs_mutex_lock(&netdev_mutex);
2074
0
    netdev = shash_find_data(&netdev_shash, name);
2075
0
    if (netdev) {
2076
0
        netdev->ref_cnt++;
2077
0
    }
2078
0
    ovs_mutex_unlock(&netdev_mutex);
2079
2080
0
    return netdev;
2081
0
}
2082
2083
/* Fills 'device_list' with devices that match 'netdev_class'.
2084
 *
2085
 * The caller is responsible for initializing and destroying 'device_list' and
2086
 * must close each device on the list. */
2087
void
2088
netdev_get_devices(const struct netdev_class *netdev_class,
2089
                   struct shash *device_list)
2090
    OVS_EXCLUDED(netdev_mutex)
2091
0
{
2092
0
    struct shash_node *node;
2093
2094
0
    ovs_mutex_lock(&netdev_mutex);
2095
0
    SHASH_FOR_EACH (node, &netdev_shash) {
2096
0
        struct netdev *dev = node->data;
2097
2098
0
        if (dev->netdev_class == netdev_class) {
2099
0
            dev->ref_cnt++;
2100
0
            shash_add(device_list, node->name, node->data);
2101
0
        }
2102
0
    }
2103
0
    ovs_mutex_unlock(&netdev_mutex);
2104
0
}
2105
2106
/* Extracts pointers to all 'netdev-vports' into an array 'vports'
2107
 * and returns it.  Stores the size of the array into '*size'.
2108
 *
2109
 * The caller is responsible for freeing 'vports' and must close
2110
 * each 'netdev-vport' in the list. */
2111
struct netdev **
2112
netdev_get_vports(size_t *size)
2113
    OVS_EXCLUDED(netdev_mutex)
2114
0
{
2115
0
    struct netdev **vports;
2116
0
    struct shash_node *node;
2117
0
    size_t n = 0;
2118
2119
0
    if (!size) {
2120
0
        return NULL;
2121
0
    }
2122
2123
    /* Explicitly allocates big enough chunk of memory. */
2124
0
    ovs_mutex_lock(&netdev_mutex);
2125
0
    vports = xmalloc(shash_count(&netdev_shash) * sizeof *vports);
2126
0
    SHASH_FOR_EACH (node, &netdev_shash) {
2127
0
        struct netdev *dev = node->data;
2128
2129
0
        if (netdev_vport_is_vport_class(dev->netdev_class)) {
2130
0
            dev->ref_cnt++;
2131
0
            vports[n] = dev;
2132
0
            n++;
2133
0
        }
2134
0
    }
2135
0
    ovs_mutex_unlock(&netdev_mutex);
2136
0
    *size = n;
2137
2138
0
    return vports;
2139
0
}
2140
2141
const char *
2142
netdev_get_type_from_name(const char *name)
2143
0
{
2144
0
    struct netdev *dev;
2145
0
    const char *type;
2146
0
    type = netdev_vport_type_from_name(name);
2147
0
    if (type == NULL) {
2148
0
        dev = netdev_from_name(name);
2149
0
        type = dev ? netdev_get_type(dev) : NULL;
2150
0
        netdev_close(dev);
2151
0
    }
2152
0
    return type;
2153
0
}
2154

2155
struct netdev *
2156
netdev_rxq_get_netdev(const struct netdev_rxq *rx)
2157
0
{
2158
0
    ovs_assert(rx->netdev->ref_cnt > 0);
2159
0
    return rx->netdev;
2160
0
}
2161
2162
const char *
2163
netdev_rxq_get_name(const struct netdev_rxq *rx)
2164
0
{
2165
0
    return netdev_get_name(netdev_rxq_get_netdev(rx));
2166
0
}
2167
2168
int
2169
netdev_rxq_get_queue_id(const struct netdev_rxq *rx)
2170
0
{
2171
0
    return rx->queue_id;
2172
0
}
2173
2174
static void
2175
restore_all_flags(void *aux OVS_UNUSED)
2176
0
{
2177
0
    struct shash_node *node;
2178
2179
0
    SHASH_FOR_EACH (node, &netdev_shash) {
2180
0
        struct netdev *netdev = node->data;
2181
0
        const struct netdev_saved_flags *sf;
2182
0
        enum netdev_flags saved_values;
2183
0
        enum netdev_flags saved_flags;
2184
2185
0
        saved_values = saved_flags = 0;
2186
0
        LIST_FOR_EACH (sf, node, &netdev->saved_flags_list) {
2187
0
            saved_flags |= sf->saved_flags;
2188
0
            saved_values &= ~sf->saved_flags;
2189
0
            saved_values |= sf->saved_flags & sf->saved_values;
2190
0
        }
2191
0
        if (saved_flags) {
2192
0
            enum netdev_flags old_flags;
2193
2194
0
            netdev->netdev_class->update_flags(netdev,
2195
0
                                               saved_flags & saved_values,
2196
0
                                               saved_flags & ~saved_values,
2197
0
                                               &old_flags);
2198
0
        }
2199
#ifdef HAVE_AF_XDP
2200
        if (netdev->netdev_class == &netdev_afxdp_class) {
2201
            signal_remove_xdp(netdev);
2202
        }
2203
#endif
2204
0
    }
2205
0
}
2206
2207
uint64_t
2208
netdev_get_change_seq(const struct netdev *netdev)
2209
0
{
2210
0
    uint64_t change_seq;
2211
2212
0
    atomic_read_explicit(&CONST_CAST(struct netdev *, netdev)->change_seq,
2213
0
                        &change_seq, memory_order_acquire);
2214
2215
0
    return change_seq;
2216
0
}
2217
2218
/* This implementation is shared by Linux and BSD. */
2219
2220
static struct ifaddrs *if_addr_list;
2221
static struct ovs_mutex if_addr_list_lock = OVS_MUTEX_INITIALIZER;
2222
2223
void
2224
netdev_get_addrs_list_flush(void)
2225
0
{
2226
0
    ovs_mutex_lock(&if_addr_list_lock);
2227
0
    if (if_addr_list) {
2228
0
        freeifaddrs(if_addr_list);
2229
0
        if_addr_list = NULL;
2230
0
    }
2231
0
    ovs_mutex_unlock(&if_addr_list_lock);
2232
0
}
2233
2234
int
2235
netdev_get_addrs(const char dev[], struct in6_addr **paddr,
2236
                 struct in6_addr **pmask, int *n_in)
2237
0
{
2238
0
    struct in6_addr *addr_array, *mask_array;
2239
0
    const struct ifaddrs *ifa;
2240
0
    int cnt = 0, i = 0;
2241
0
    int retries = 3;
2242
2243
0
    ovs_mutex_lock(&if_addr_list_lock);
2244
0
    if (!if_addr_list) {
2245
0
        int err;
2246
2247
0
retry:
2248
0
        err = getifaddrs(&if_addr_list);
2249
0
        if (err) {
2250
0
            ovs_mutex_unlock(&if_addr_list_lock);
2251
0
            return -err;
2252
0
        }
2253
0
        retries--;
2254
0
    }
2255
2256
0
    for (ifa = if_addr_list; ifa; ifa = ifa->ifa_next) {
2257
0
        if (!ifa->ifa_name) {
2258
0
            if (retries) {
2259
                /* Older versions of glibc have a bug on race condition with
2260
                 * address addition which may cause one of the returned
2261
                 * ifa_name values to be NULL. In such case, we know that we've
2262
                 * got an inconsistent dump. Retry but beware of an endless
2263
                 * loop. From glibc 2.28 and beyond, this workaround is not
2264
                 * needed and should be eventually removed. */
2265
0
                freeifaddrs(if_addr_list);
2266
0
                goto retry;
2267
0
            } else {
2268
0
                VLOG_WARN("Proceeding with an inconsistent dump of "
2269
0
                          "interfaces from the kernel. Some may be missing");
2270
0
            }
2271
0
        }
2272
0
        if (ifa->ifa_addr && ifa->ifa_name && ifa->ifa_netmask) {
2273
0
            int family;
2274
2275
0
            family = ifa->ifa_addr->sa_family;
2276
0
            if (family == AF_INET || family == AF_INET6) {
2277
0
                if (!strncmp(ifa->ifa_name, dev, IFNAMSIZ)) {
2278
0
                    cnt++;
2279
0
                }
2280
0
            }
2281
0
        }
2282
0
    }
2283
2284
0
    if (!cnt) {
2285
0
        ovs_mutex_unlock(&if_addr_list_lock);
2286
0
        return EADDRNOTAVAIL;
2287
0
    }
2288
0
    addr_array = xzalloc(sizeof *addr_array * cnt);
2289
0
    mask_array = xzalloc(sizeof *mask_array * cnt);
2290
0
    for (ifa = if_addr_list; ifa; ifa = ifa->ifa_next) {
2291
0
        if (ifa->ifa_name
2292
0
            && ifa->ifa_addr
2293
0
            && ifa->ifa_netmask
2294
0
            && !strncmp(ifa->ifa_name, dev, IFNAMSIZ)
2295
0
            && sa_is_ip(ifa->ifa_addr)) {
2296
0
            addr_array[i] = sa_get_address(ifa->ifa_addr);
2297
0
            mask_array[i] = sa_get_address(ifa->ifa_netmask);
2298
0
            i++;
2299
0
        }
2300
0
    }
2301
0
    ovs_mutex_unlock(&if_addr_list_lock);
2302
0
    if (paddr) {
2303
0
        *n_in = cnt;
2304
0
        *paddr = addr_array;
2305
0
        *pmask = mask_array;
2306
0
    } else {
2307
0
        free(addr_array);
2308
0
        free(mask_array);
2309
0
    }
2310
0
    return 0;
2311
0
}
2312
2313
void
2314
netdev_wait_reconf_required(struct netdev *netdev)
2315
0
{
2316
0
    seq_wait(netdev->reconfigure_seq, netdev->last_reconfigure_seq);
2317
0
}
2318
2319
bool
2320
netdev_is_reconf_required(struct netdev *netdev)
2321
0
{
2322
0
    return seq_read(netdev->reconfigure_seq) != netdev->last_reconfigure_seq;
2323
0
}
2324
2325
/* Give a chance to 'netdev' to reconfigure some of its parameters.
2326
 *
2327
 * If a module uses netdev_send() and netdev_rxq_recv(), it must call this
2328
 * function when netdev_is_reconf_required() returns true.
2329
 *
2330
 * Return 0 if successful, otherwise a positive errno value.  If the
2331
 * reconfiguration fails the netdev will not be able to send or receive
2332
 * packets.
2333
 *
2334
 * When this function is called, no call to netdev_rxq_recv() or netdev_send()
2335
 * must be issued. */
2336
int
2337
netdev_reconfigure(struct netdev *netdev)
2338
0
{
2339
0
    const struct netdev_class *class = netdev->netdev_class;
2340
2341
0
    netdev->last_reconfigure_seq = seq_read(netdev->reconfigure_seq);
2342
2343
0
    return (class->reconfigure
2344
0
            ? class->reconfigure(netdev)
2345
0
            : EOPNOTSUPP);
2346
0
}
2347
2348
void
2349
netdev_free_custom_stats_counters(struct netdev_custom_stats *custom_stats)
2350
0
{
2351
0
    if (custom_stats) {
2352
0
        if (custom_stats->counters) {
2353
0
            free(custom_stats->counters);
2354
0
            custom_stats->counters = NULL;
2355
0
            custom_stats->size = 0;
2356
0
        }
2357
0
        free(custom_stats->label);
2358
0
        custom_stats->label = NULL;
2359
0
    }
2360
0
}
2361
2362
uint32_t
2363
netdev_get_block_id(struct netdev *netdev)
2364
0
{
2365
0
    const struct netdev_class *class = netdev->netdev_class;
2366
2367
0
    return (class->get_block_id
2368
0
            ? class->get_block_id(netdev)
2369
0
            : 0);
2370
0
}
2371
2372
/*
2373
 * Get the value of the hw info parameter specified by type.
2374
 * Returns the value on success (>= 0).  Returns -1 on failure.
2375
 */
2376
int
2377
netdev_get_hw_info(struct netdev *netdev, int type)
2378
0
{
2379
0
    int val = -1;
2380
2381
0
    switch (type) {
2382
0
    case HW_INFO_TYPE_OOR:
2383
0
        val = netdev->hw_info.oor;
2384
0
        break;
2385
0
    case HW_INFO_TYPE_PEND_COUNT:
2386
0
        val = netdev->hw_info.pending_count;
2387
0
        break;
2388
0
    case HW_INFO_TYPE_OFFL_COUNT:
2389
0
        val = netdev->hw_info.offload_count;
2390
0
        break;
2391
0
    default:
2392
0
        break;
2393
0
    }
2394
2395
0
    return val;
2396
0
}
2397
2398
/*
2399
 * Set the value of the hw info parameter specified by type.
2400
 */
2401
void
2402
netdev_set_hw_info(struct netdev *netdev, int type, int val)
2403
0
{
2404
0
    switch (type) {
2405
0
    case HW_INFO_TYPE_OOR:
2406
0
        if (val == 0) {
2407
0
            VLOG_DBG("Offload rebalance: netdev: %s is not OOR", netdev->name);
2408
0
        }
2409
0
        netdev->hw_info.oor = val;
2410
0
        break;
2411
0
    case HW_INFO_TYPE_PEND_COUNT:
2412
0
        netdev->hw_info.pending_count = val;
2413
0
        break;
2414
0
    case HW_INFO_TYPE_OFFL_COUNT:
2415
0
        netdev->hw_info.offload_count = val;
2416
0
        break;
2417
0
    default:
2418
0
        break;
2419
0
    }
2420
0
}