Coverage Report

Created: 2026-09-01 06:23

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openvswitch/lib/netdev-linux.c
Line
Count
Source
1
/*
2
 * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 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
19
#include "netdev-linux.h"
20
#include "netdev-linux-private.h"
21
22
#include <errno.h>
23
#include <fcntl.h>
24
#include <sys/types.h>
25
#include <netinet/in.h>
26
#include <arpa/inet.h>
27
#include <inttypes.h>
28
#include <math.h>
29
#include <linux/filter.h>
30
#include <linux/gen_stats.h>
31
#include <linux/if_ether.h>
32
#include <linux/if_packet.h>
33
#include <linux/if_tun.h>
34
#include <linux/types.h>
35
#include <linux/ethtool.h>
36
#include <linux/mii.h>
37
#include <linux/rtnetlink.h>
38
#include <linux/sockios.h>
39
#include <linux/virtio_net.h>
40
#include <sys/ioctl.h>
41
#include <sys/socket.h>
42
#include <sys/uio.h>
43
#include <net/if.h>
44
#include <net/if_arp.h>
45
#include <net/route.h>
46
#include <poll.h>
47
#include <stdlib.h>
48
#include <string.h>
49
#include <unistd.h>
50
51
#include "coverage.h"
52
#include "dp-packet.h"
53
#include "dpif-netlink.h"
54
#include "dpif-netdev.h"
55
#include "dpif-offload.h"
56
#include "openvswitch/dynamic-string.h"
57
#include "fatal-signal.h"
58
#include "hash.h"
59
#include "openvswitch/hmap.h"
60
#include "netdev-afxdp.h"
61
#include "netdev-provider.h"
62
#include "netdev-vport.h"
63
#include "netlink-notifier.h"
64
#include "netlink-socket.h"
65
#include "netlink.h"
66
#include "netnsid.h"
67
#include "openvswitch/ofpbuf.h"
68
#include "openflow/openflow.h"
69
#include "ovs-atomic.h"
70
#include "ovs-numa.h"
71
#include "packets.h"
72
#include "openvswitch/poll-loop.h"
73
#include "rtnetlink.h"
74
#include "openvswitch/shash.h"
75
#include "socket-util.h"
76
#include "sset.h"
77
#include "tc.h"
78
#include "timer.h"
79
#include "unaligned.h"
80
#include "openvswitch/vlog.h"
81
#include "userspace-tso.h"
82
#include "util.h"
83
84
VLOG_DEFINE_THIS_MODULE(netdev_linux);
85
86
COVERAGE_DEFINE(netdev_set_policing);
87
COVERAGE_DEFINE(netdev_arp_lookup);
88
COVERAGE_DEFINE(netdev_get_ifindex);
89
COVERAGE_DEFINE(netdev_get_hwaddr);
90
COVERAGE_DEFINE(netdev_set_hwaddr);
91
COVERAGE_DEFINE(netdev_get_ethtool);
92
COVERAGE_DEFINE(netdev_set_ethtool);
93
COVERAGE_DEFINE(netdev_linux_invalid_l4_csum);
94
COVERAGE_DEFINE(netdev_linux_unknown_l4_csum);
95
96

97
#ifndef HAVE_IFLA_IF_NETNSID
98
#define IFLA_IF_NETNSID 46
99
#endif
100
/* These were introduced in Linux 2.6.14, so they might be missing if we have
101
 * old headers. */
102
#ifndef ADVERTISED_Pause
103
#define ADVERTISED_Pause                (1 << 13)
104
#endif
105
#ifndef ADVERTISED_Asym_Pause
106
#define ADVERTISED_Asym_Pause           (1 << 14)
107
#endif
108
109
/* These were introduced in Linux 2.6.24, so they might be missing if we
110
 * have old headers. */
111
#ifndef ETHTOOL_GFLAGS
112
#define ETHTOOL_GFLAGS       0x00000025 /* Get flags bitmap(ethtool_value) */
113
#endif
114
#ifndef ETHTOOL_SFLAGS
115
#define ETHTOOL_SFLAGS       0x00000026 /* Set flags bitmap(ethtool_value) */
116
#endif
117
118
/* This was introduced in Linux 2.6.25, so it might be missing if we have old
119
 * headers. */
120
#ifndef TC_RTAB_SIZE
121
#define TC_RTAB_SIZE 1024
122
#endif
123
124
/* Linux 2.6.21 introduced struct tpacket_auxdata.
125
 * Linux 2.6.27 added the tp_vlan_tci member.
126
 * Linux 3.0 defined TP_STATUS_VLAN_VALID.
127
 * Linux 3.13 repurposed a padding member for tp_vlan_tpid and defined
128
 * TP_STATUS_VLAN_TPID_VALID.
129
 *
130
 * With all this churn it's easiest to unconditionally define a replacement
131
 * structure that has everything we want.
132
 */
133
#ifndef PACKET_AUXDATA
134
#define PACKET_AUXDATA                  8
135
#endif
136
#ifndef TP_STATUS_VLAN_VALID
137
#define TP_STATUS_VLAN_VALID            (1 << 4)
138
#endif
139
#ifndef TP_STATUS_VLAN_TPID_VALID
140
#define TP_STATUS_VLAN_TPID_VALID       (1 << 6)
141
#endif
142
#undef tpacket_auxdata
143
#define tpacket_auxdata rpl_tpacket_auxdata
144
struct tpacket_auxdata {
145
    uint32_t tp_status;
146
    uint32_t tp_len;
147
    uint32_t tp_snaplen;
148
    uint16_t tp_mac;
149
    uint16_t tp_net;
150
    uint16_t tp_vlan_tci;
151
    uint16_t tp_vlan_tpid;
152
};
153
154
/* Linux 2.6.27 introduced ethtool_cmd_speed
155
 *
156
 * To avoid revisiting problems reported with using configure to detect
157
 * compatibility (see report at
158
 * https://mail.openvswitch.org/pipermail/ovs-dev/2014-October/291521.html)
159
 * unconditionally replace ethtool_cmd_speed. */
160
0
#define ethtool_cmd_speed rpl_ethtool_cmd_speed
161
static inline uint32_t rpl_ethtool_cmd_speed(const struct ethtool_cmd *ep)
162
0
{
163
0
        return ep->speed | (ep->speed_hi << 16);
164
0
}
165
166
/* Linux 2.6.30 introduced supported and advertised flags for
167
 * 1G base KX, and 10G base KX4, KR and R. */
168
#ifndef SUPPORTED_1000baseKX_Full
169
#define SUPPORTED_1000baseKX_Full      (1 << 17)
170
#define SUPPORTED_10000baseKX4_Full    (1 << 18)
171
#define SUPPORTED_10000baseKR_Full     (1 << 19)
172
#define SUPPORTED_10000baseR_FEC       (1 << 20)
173
#define ADVERTISED_1000baseKX_Full     (1 << 17)
174
#define ADVERTISED_10000baseKX4_Full   (1 << 18)
175
#define ADVERTISED_10000baseKR_Full    (1 << 19)
176
#define ADVERTISED_10000baseR_FEC      (1 << 20)
177
#endif
178
179
/* Linux 3.2 introduced "unknown" speed and duplex. */
180
#ifndef SPEED_UNKNOWN
181
#define SPEED_UNKNOWN -1
182
#endif
183
#ifndef DUPLEX_UNKNOWN
184
#define DUPLEX_UNKNOWN 0xff
185
#endif
186
187
/* Linux 3.5 introduced supported and advertised flags for
188
 * 40G base KR4, CR4, SR4 and LR4. */
189
#ifndef SUPPORTED_40000baseKR4_Full
190
#define SUPPORTED_40000baseKR4_Full    (1 << 23)
191
#define SUPPORTED_40000baseCR4_Full    (1 << 24)
192
#define SUPPORTED_40000baseSR4_Full    (1 << 25)
193
#define SUPPORTED_40000baseLR4_Full    (1 << 26)
194
#define ADVERTISED_40000baseKR4_Full   (1 << 23)
195
#define ADVERTISED_40000baseCR4_Full   (1 << 24)
196
#define ADVERTISED_40000baseSR4_Full   (1 << 25)
197
#define ADVERTISED_40000baseLR4_Full   (1 << 26)
198
#endif
199
200
/* Linux 3.19 introduced speed for 40G. */
201
#ifndef SPEED_40000
202
#define SPEED_40000 40000
203
#endif
204
205
/* Linux 4.2 introduced speed for 100G. */
206
#ifndef SPEED_100000
207
#define SPEED_100000 100000
208
#endif
209
210
/* Linux 2.6.35 introduced IFLA_STATS64 and rtnl_link_stats64.
211
 *
212
 * Tests for rtnl_link_stats64 don't seem to consistently work, e.g. on
213
 * 2.6.32-431.29.2.el6.x86_64 (see report at
214
 * https://mail.openvswitch.org/pipermail/ovs-dev/2014-October/291521.html).
215
 * Maybe if_link.h is not self-contained on those kernels.  It is easiest to
216
 * unconditionally define a replacement. */
217
#ifndef IFLA_STATS64
218
0
#define IFLA_STATS64 23
219
#endif
220
#define rtnl_link_stats64 rpl_rtnl_link_stats64
221
struct rtnl_link_stats64 {
222
    uint64_t rx_packets;
223
    uint64_t tx_packets;
224
    uint64_t rx_bytes;
225
    uint64_t tx_bytes;
226
    uint64_t rx_errors;
227
    uint64_t tx_errors;
228
    uint64_t rx_dropped;
229
    uint64_t tx_dropped;
230
    uint64_t multicast;
231
    uint64_t collisions;
232
233
    uint64_t rx_length_errors;
234
    uint64_t rx_over_errors;
235
    uint64_t rx_crc_errors;
236
    uint64_t rx_frame_errors;
237
    uint64_t rx_fifo_errors;
238
    uint64_t rx_missed_errors;
239
240
    uint64_t tx_aborted_errors;
241
    uint64_t tx_carrier_errors;
242
    uint64_t tx_fifo_errors;
243
    uint64_t tx_heartbeat_errors;
244
    uint64_t tx_window_errors;
245
246
    uint64_t rx_compressed;
247
    uint64_t tx_compressed;
248
};
249
250
/* Linux 3.19 introduced virtio_types.h.  It might be missing
251
 * if we are using old kernel. */
252
#ifndef HAVE_VIRTIO_TYPES
253
typedef __u16 __bitwise__ __virtio16;
254
typedef __u32 __bitwise__ __virtio32;
255
typedef __u64 __bitwise__ __virtio64;
256
#endif
257
258
enum {
259
    VALID_IFINDEX           = 1 << 0,
260
    VALID_ETHERADDR         = 1 << 1,
261
    VALID_IN                = 1 << 2,
262
    VALID_MTU               = 1 << 3,
263
    VALID_POLICING          = 1 << 4,
264
    VALID_VPORT_STAT_ERROR  = 1 << 5,
265
    VALID_DRVINFO           = 1 << 6,
266
    VALID_FEATURES          = 1 << 7,
267
    VALID_NUMA_ID           = 1 << 8,
268
};
269
270
/* Linux 4.4 introduced the ability to skip the internal stats gathering
271
 * that netlink does via an external filter mask that can be passed into
272
 * a netlink request.
273
 */
274
#ifndef RTEXT_FILTER_SKIP_STATS
275
#define RTEXT_FILTER_SKIP_STATS (1 << 3)
276
#endif
277
278
/* Use one for the packet buffer and another for the aux buffer to receive
279
 * TSO packets. */
280
0
#define IOV_STD_SIZE 1
281
0
#define IOV_TSO_SIZE 2
282
283
enum {
284
    IOV_PACKET = 0,
285
    IOV_AUXBUF = 1,
286
};
287

288
struct linux_lag_member {
289
   uint32_t block_id;
290
   struct shash_node *node;
291
};
292
293
/* Protects 'lag_shash' and the mutable members of struct linux_lag_member. */
294
static struct ovs_mutex lag_mutex = OVS_MUTEX_INITIALIZER;
295
296
/* All members whose LAG primary interfaces are OVS network devices. */
297
static struct shash lag_shash OVS_GUARDED_BY(lag_mutex)
298
    = SHASH_INITIALIZER(&lag_shash);
299
300
/* Traffic control. */
301
302
/* An instance of a traffic control class.  Always associated with a particular
303
 * network device.
304
 *
305
 * Each TC implementation subclasses this with whatever additional data it
306
 * needs. */
307
struct tc {
308
    const struct tc_ops *ops;
309
    struct hmap queues;         /* Contains "struct tc_queue"s.
310
                                 * Read by generic TC layer.
311
                                 * Written only by TC implementation. */
312
};
313
314
0
#define TC_INITIALIZER(TC, OPS) { OPS, HMAP_INITIALIZER(&(TC)->queues) }
315
316
/* One traffic control queue.
317
 *
318
 * Each TC implementation subclasses this with whatever additional data it
319
 * needs. */
320
struct tc_queue {
321
    struct hmap_node hmap_node; /* In struct tc's "queues" hmap. */
322
    unsigned int queue_id;      /* OpenFlow queue ID. */
323
    long long int created;      /* Time queue was created, in msecs. */
324
};
325
326
/* A particular kind of traffic control.  Each implementation generally maps to
327
 * one particular Linux qdisc class.
328
 *
329
 * The functions below return 0 if successful or a positive errno value on
330
 * failure, except where otherwise noted.  All of them must be provided, except
331
 * where otherwise noted. */
332
struct tc_ops {
333
    /* Name used by kernel in the TCA_KIND attribute of tcmsg, e.g. "htb".
334
     * This is null for tc_ops_default and tc_ops_other, for which there are no
335
     * appropriate values. */
336
    const char *linux_name;
337
338
    /* Name used in OVS database, e.g. "linux-htb".  Must be nonnull. */
339
    const char *ovs_name;
340
341
    /* Number of supported OpenFlow queues, 0 for qdiscs that have no
342
     * queues.  The queues are numbered 0 through n_queues - 1. */
343
    unsigned int n_queues;
344
345
    /* Called to install this TC class on 'netdev'.  The implementation should
346
     * make the Netlink calls required to set up 'netdev' with the right qdisc
347
     * and configure it according to 'details'.  The implementation may assume
348
     * that the current qdisc is the default; that is, there is no need for it
349
     * to delete the current qdisc before installing itself.
350
     *
351
     * The contents of 'details' should be documented as valid for 'ovs_name'
352
     * in the "other_config" column in the "QoS" table in vswitchd/vswitch.xml
353
     * (which is built as ovs-vswitchd.conf.db(8)).
354
     *
355
     * This function must return 0 if and only if it sets 'netdev->tc' to an
356
     * initialized 'struct tc'.
357
     *
358
     * (This function is null for tc_ops_other, which cannot be installed.  For
359
     * other TC classes it should always be nonnull.) */
360
    int (*tc_install)(struct netdev *netdev, const struct smap *details);
361
362
    /* Called when the netdev code determines (through a Netlink query) that
363
     * this TC class's qdisc is installed on 'netdev', but we didn't install
364
     * it ourselves and so don't know any of the details.
365
     *
366
     * 'nlmsg' is the kernel reply to a RTM_GETQDISC Netlink message for
367
     * 'netdev'.  The TCA_KIND attribute of 'nlmsg' is 'linux_name'.  The
368
     * implementation should parse the other attributes of 'nlmsg' as
369
     * necessary to determine its configuration.  If necessary it should also
370
     * use Netlink queries to determine the configuration of queues on
371
     * 'netdev'.
372
     *
373
     * This function must return 0 if and only if it sets 'netdev->tc' to an
374
     * initialized 'struct tc'. */
375
    int (*tc_load)(struct netdev *netdev, struct ofpbuf *nlmsg);
376
377
    /* Destroys the data structures allocated by the implementation as part of
378
     * 'tc'.  (This includes destroying 'tc->queues' by calling
379
     * tc_destroy(tc).
380
     *
381
     * The implementation should not need to perform any Netlink calls.  If
382
     * desirable, the caller is responsible for deconfiguring the kernel qdisc.
383
     * (But it may not be desirable.)
384
     *
385
     * This function may be null if 'tc' is trivial. */
386
    void (*tc_destroy)(struct tc *tc);
387
388
    /* Retrieves details of 'netdev->tc' configuration into 'details'.
389
     *
390
     * The implementation should not need to perform any Netlink calls, because
391
     * the 'tc_install' or 'tc_load' that instantiated 'netdev->tc' should have
392
     * cached the configuration.
393
     *
394
     * The contents of 'details' should be documented as valid for 'ovs_name'
395
     * in the "other_config" column in the "QoS" table in vswitchd/vswitch.xml
396
     * (which is built as ovs-vswitchd.conf.db(8)).
397
     *
398
     * This function may be null if 'tc' is not configurable.
399
     */
400
    int (*qdisc_get)(const struct netdev *netdev, struct smap *details);
401
402
    /* Reconfigures 'netdev->tc' according to 'details', performing any
403
     * required Netlink calls to complete the reconfiguration.
404
     *
405
     * The contents of 'details' should be documented as valid for 'ovs_name'
406
     * in the "other_config" column in the "QoS" table in vswitchd/vswitch.xml
407
     * (which is built as ovs-vswitchd.conf.db(8)).
408
     *
409
     * This function may be null if 'tc' is not configurable.
410
     */
411
    int (*qdisc_set)(struct netdev *, const struct smap *details);
412
413
    /* Retrieves details of 'queue' on 'netdev->tc' into 'details'.  'queue' is
414
     * one of the 'struct tc_queue's within 'netdev->tc->queues'.
415
     *
416
     * The contents of 'details' should be documented as valid for 'ovs_name'
417
     * in the "other_config" column in the "Queue" table in
418
     * vswitchd/vswitch.xml (which is built as ovs-vswitchd.conf.db(8)).
419
     *
420
     * The implementation should not need to perform any Netlink calls, because
421
     * the 'tc_install' or 'tc_load' that instantiated 'netdev->tc' should have
422
     * cached the queue configuration.
423
     *
424
     * This function may be null if 'tc' does not have queues ('n_queues' is
425
     * 0). */
426
    int (*class_get)(const struct netdev *netdev, const struct tc_queue *queue,
427
                     struct smap *details);
428
429
    /* Configures or reconfigures 'queue_id' on 'netdev->tc' according to
430
     * 'details', perfoming any required Netlink calls to complete the
431
     * reconfiguration.  The caller ensures that 'queue_id' is less than
432
     * 'n_queues'.
433
     *
434
     * The contents of 'details' should be documented as valid for 'ovs_name'
435
     * in the "other_config" column in the "Queue" table in
436
     * vswitchd/vswitch.xml (which is built as ovs-vswitchd.conf.db(8)).
437
     *
438
     * This function may be null if 'tc' does not have queues or its queues are
439
     * not configurable. */
440
    int (*class_set)(struct netdev *, unsigned int queue_id,
441
                     const struct smap *details);
442
443
    /* Deletes 'queue' from 'netdev->tc'.  'queue' is one of the 'struct
444
     * tc_queue's within 'netdev->tc->queues'.
445
     *
446
     * This function may be null if 'tc' does not have queues or its queues
447
     * cannot be deleted. */
448
    int (*class_delete)(struct netdev *, struct tc_queue *queue);
449
450
    /* Obtains stats for 'queue' from 'netdev->tc'.  'queue' is one of the
451
     * 'struct tc_queue's within 'netdev->tc->queues'.
452
     *
453
     * On success, initializes '*stats'.
454
     *
455
     * This function may be null if 'tc' does not have queues or if it cannot
456
     * report queue statistics. */
457
    int (*class_get_stats)(const struct netdev *netdev,
458
                           const struct tc_queue *queue,
459
                           struct netdev_queue_stats *stats);
460
461
    /* Extracts queue stats from 'nlmsg', which is a response to a
462
     * RTM_GETTCLASS message, and passes them to 'cb' along with 'aux'.
463
     *
464
     * This function may be null if 'tc' does not have queues or if it cannot
465
     * report queue statistics. */
466
    int (*class_dump_stats)(const struct netdev *netdev,
467
                            const struct ofpbuf *nlmsg,
468
                            netdev_dump_queue_stats_cb *cb, void *aux);
469
};
470
471
static void
472
tc_init(struct tc *tc, const struct tc_ops *ops)
473
0
{
474
0
    tc->ops = ops;
475
0
    hmap_init(&tc->queues);
476
0
}
477
478
static void
479
tc_destroy(struct tc *tc)
480
0
{
481
0
    hmap_destroy(&tc->queues);
482
0
}
483
484
static const struct tc_ops tc_ops_htb;
485
static const struct tc_ops tc_ops_hfsc;
486
static const struct tc_ops tc_ops_codel;
487
static const struct tc_ops tc_ops_fqcodel;
488
static const struct tc_ops tc_ops_sfq;
489
static const struct tc_ops tc_ops_netem;
490
static const struct tc_ops tc_ops_default;
491
static const struct tc_ops tc_ops_noop;
492
static const struct tc_ops tc_ops_other;
493
494
static const struct tc_ops *const tcs[] = {
495
    &tc_ops_htb,                /* Hierarchy token bucket (see tc-htb(8)). */
496
    &tc_ops_hfsc,               /* Hierarchical fair service curve. */
497
    &tc_ops_codel,              /* Controlled delay */
498
    &tc_ops_fqcodel,            /* Fair queue controlled delay */
499
    &tc_ops_sfq,                /* Stochastic fair queueing */
500
    &tc_ops_netem,              /* Network Emulator */
501
    &tc_ops_noop,               /* Non operating qos type. */
502
    &tc_ops_default,            /* Default qdisc (see tc-pfifo_fast(8)). */
503
    &tc_ops_other,              /* Some other qdisc. */
504
    NULL
505
};
506
507
static unsigned int tc_ticks_to_bytes(uint64_t rate, unsigned int ticks);
508
static unsigned int tc_bytes_to_ticks(uint64_t rate, unsigned int size);
509
static unsigned int tc_buffer_per_jiffy(uint64_t rate);
510
static uint32_t tc_time_to_ticks(uint32_t time);
511
512
static struct tcmsg *netdev_linux_tc_make_request(const struct netdev *,
513
                                                  int type,
514
                                                  unsigned int flags,
515
                                                  struct ofpbuf *);
516
517
static int tc_add_policer(struct netdev *, uint64_t kbits_rate,
518
                          uint32_t kbits_burst, uint32_t kpkts_rate,
519
                          uint32_t kpkts_burst);
520
521
static int tc_parse_qdisc(const struct ofpbuf *, const char **kind,
522
                          struct nlattr **options);
523
static int tc_parse_class(const struct ofpbuf *, unsigned int *queue_id,
524
                          struct nlattr **options,
525
                          struct netdev_queue_stats *);
526
static int tc_query_class(const struct netdev *,
527
                          unsigned int handle, unsigned int parent,
528
                          struct ofpbuf **replyp);
529
static int tc_delete_class(const struct netdev *, unsigned int handle);
530
531
static int tc_del_qdisc(struct netdev *netdev);
532
static int tc_query_qdisc(const struct netdev *netdev);
533
static void tc_policer_init(struct tc_police *tc_police, uint64_t kbits_rate,
534
                            uint64_t kbits_burst);
535
536
void
537
tc_put_rtab(struct ofpbuf *msg, uint16_t type, const struct tc_ratespec *rate,
538
            uint64_t rate64);
539
static int tc_calc_cell_log(unsigned int mtu);
540
static void tc_fill_rate(struct tc_ratespec *rate, uint64_t bps, int mtu);
541
static int tc_calc_buffer(uint64_t Bps, int mtu, uint64_t burst_bytes);
542

543
544
/* This is set pretty low because we probably won't learn anything from the
545
 * additional log messages. */
546
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 20);
547
548
/* Polling miimon status for all ports causes performance degradation when
549
 * handling a large number of ports. If there are no devices using miimon, then
550
 * we skip netdev_linux_miimon_run() and netdev_linux_miimon_wait().
551
 *
552
 * Readers do not depend on this variable synchronizing with the related
553
 * changes in the device miimon status, so we can use atomic_count. */
554
static atomic_count miimon_cnt = ATOMIC_COUNT_INIT(0);
555
556
/* Very old kernels from the 2.6 era don't support vnet headers with the tun
557
 * device. We can detect this while constructing a netdev, but need this for
558
 * packet rx/tx. */
559
static bool tap_supports_vnet_hdr = true;
560
561
static int netdev_linux_parse_vnet_hdr(struct dp_packet *b);
562
static int netdev_linux_prepend_vnet_hdr(struct dp_packet *b, int mtu);
563
static int netdev_linux_do_ethtool(const char *name, struct ethtool_cmd *,
564
                                   int cmd, const char *cmd_name);
565
static int get_flags(const struct netdev *, unsigned int *flags);
566
static int set_flags(const char *, unsigned int flags);
567
static int update_flags(struct netdev_linux *netdev, enum netdev_flags off,
568
                        enum netdev_flags on, enum netdev_flags *old_flagsp)
569
    OVS_REQUIRES(netdev->mutex);
570
static int get_ifindex(const struct netdev *, int *ifindexp);
571
static int do_set_addr(struct netdev *netdev,
572
                       int ioctl_nr, const char *ioctl_name,
573
                       struct in_addr addr);
574
static int get_etheraddr(const char *netdev_name, struct eth_addr *ea);
575
static int set_etheraddr(const char *netdev_name, const struct eth_addr);
576
static int af_packet_sock(void);
577
static bool netdev_linux_miimon_enabled(void);
578
static void netdev_linux_miimon_run(void);
579
static void netdev_linux_miimon_wait(void);
580
static int netdev_linux_get_mtu__(struct netdev_linux *netdev, int *mtup);
581
static void netdev_linux_set_ol(struct netdev *netdev);
582
583
static bool
584
is_tap_netdev(const struct netdev *netdev)
585
0
{
586
0
    return netdev_get_class(netdev) == &netdev_tap_class;
587
0
}
588

589
/* Ensures that our own network namespace has a self-referential nsid mapping
590
 * and records its value through netnsid_set_self() so that netnsid_is_local()
591
 * treats it as the local namespace.
592
 *
593
 * NETLINK_LISTEN_ALL_NSID workaround: OVS enables this option on its RTNL
594
 * notification socket so that it can receive events from remote namespaces.
595
 * A side-effect of this option is that the kernel tags every broadcast
596
 * (including locally-originated RTM events) with the sender nsid as looked up
597
 * in the receiver nsid table.  Normally local events carry no nsid cmsg
598
 * (which OVS interprets as NETNSID_LOCAL), but if a self-referential nsid
599
 * mapping exists for the local namespace an older kernel may tag them with
600
 * that nsid instead, causing OVS to silently reject them.  Some container
601
 * runtimes create such a mapping as a side-effect of cross-namespace link
602
 * queries.
603
 *
604
 * To make this deterministic, we create the mapping ourselves (or read back
605
 * the existing one) at startup, before the notification socket exists and
606
 * record the resulting nsid as local.  A self-referential nsid mapping is
607
 * permanent once created, the kernel only removes nsid entries when the
608
 * peer namespace is destroyed, which can never happen for our own namespace.
609
 * Therefore, the value never changes and no runtime monitoring is required.
610
 *
611
 * The namespace is identified by our own pid (NETNSA_PID).
612
 *
613
 * This kernel behavior was fixed in commit 88b126b39f97 ("net: netlink: don't
614
 * set nsid on local notifications"), which stops tagging local events with the
615
 * self-referential nsid.  This workaround (and the self-nsid check in
616
 * netnsid_is_local()) is only needed for older kernels that lack that fix and
617
 * can be removed once such kernels are no longer supported. */
618
static void
619
netdev_linux_init_self_nsid(void)
620
0
{
621
0
#ifdef HAVE_LINUX_NET_NAMESPACE_H
622
0
    const int rta_offset = NLMSG_ALIGN(sizeof(struct rtgenmsg));
623
0
    struct ofpbuf request;
624
0
    struct ofpbuf *reply = NULL;
625
0
    uint32_t pid = getpid();
626
0
    int error;
627
628
    /* Create a self-referential nsid mapping for our own namespace.  Passing
629
     * NETNSA_NSID == -1 lets the kernel allocate a free id. If the mapping
630
     * already exists the request fails with EEXIST, which is harmless. */
631
0
    ofpbuf_init(&request, 0);
632
0
    nl_msg_put_nlmsghdr(&request,
633
0
                        rta_offset + 2 * NL_ATTR_SIZE(sizeof(uint32_t)),
634
0
                        RTM_NEWNSID, NLM_F_REQUEST | NLM_F_ACK);
635
0
    ofpbuf_put_zeros(&request, rta_offset);
636
0
    nl_msg_put_u32(&request, NETNSA_PID, pid);
637
0
    nl_msg_put_u32(&request, NETNSA_NSID, NETNSID_LOCAL);
638
0
    nl_transact(NETLINK_ROUTE, &request, NULL);
639
0
    ofpbuf_uninit(&request);
640
641
    /* Read back the nsid that the kernel assigned to our namespace. */
642
0
    ofpbuf_init(&request, 0);
643
0
    nl_msg_put_nlmsghdr(&request, rta_offset + NL_ATTR_SIZE(sizeof(uint32_t)),
644
0
                        RTM_GETNSID, NLM_F_REQUEST);
645
0
    ofpbuf_put_zeros(&request, rta_offset);
646
0
    nl_msg_put_u32(&request, NETNSA_PID, pid);
647
648
0
    error = nl_transact(NETLINK_ROUTE, &request, &reply);
649
0
    if (!error && reply) {
650
0
        const struct nlattr *a;
651
652
0
        a = nl_attr_find(reply, NLMSG_HDRLEN + rta_offset, NETNSA_NSID);
653
0
        if (a) {
654
0
            int nsid = nl_attr_get_u32(a);
655
656
0
            if (nsid >= 0) {
657
0
                netnsid_set_self(nsid);
658
0
                VLOG_DBG("local network namespace has nsid %d", nsid);
659
0
            }
660
0
        }
661
0
    } else {
662
0
        VLOG_WARN("could not query local network namespace nsid: %s",
663
0
                  ovs_strerror(error));
664
0
    }
665
666
0
    ofpbuf_uninit(&request);
667
0
    ofpbuf_delete(reply);
668
0
#endif
669
0
}
670
671
static int
672
netdev_linux_netnsid_update__(struct netdev_linux *netdev)
673
0
{
674
0
    struct dpif_netlink_vport reply;
675
0
    struct ofpbuf *buf;
676
0
    int error;
677
678
0
    error = dpif_netlink_vport_get(netdev_get_name(&netdev->up), &reply, &buf);
679
0
    if (error) {
680
0
        if (error == ENOENT) {
681
            /* Assume it is local if there is no API (e.g. if the openvswitch
682
             * kernel module is not loaded). */
683
0
            netnsid_set_local(&netdev->netnsid);
684
0
        } else {
685
0
            netnsid_unset(&netdev->netnsid);
686
0
        }
687
0
        return error;
688
0
    }
689
690
0
    netnsid_set(&netdev->netnsid, reply.netnsid);
691
0
    ofpbuf_delete(buf);
692
0
    return 0;
693
0
}
694
695
static int
696
netdev_linux_netnsid_update(struct netdev_linux *netdev)
697
0
{
698
0
    if (netnsid_is_unset(netdev->netnsid)) {
699
0
        const char *dpif_type = netdev_get_dpif_type(&netdev->up);
700
701
0
        if (netdev_get_class(&netdev->up) == &netdev_tap_class
702
0
            || (dpif_type && strcmp(dpif_type, "system"))) {
703
            /* vport netlink lookup makes no sense for
704
             * non-system dpif types, set nsid to local. */
705
0
            netnsid_set_local(&netdev->netnsid);
706
0
        } else {
707
0
            return netdev_linux_netnsid_update__(netdev);
708
0
        }
709
0
    }
710
711
0
    return 0;
712
0
}
713
714
static bool
715
netdev_linux_netnsid_is_eq(struct netdev_linux *netdev, int nsid)
716
0
{
717
0
    netdev_linux_netnsid_update(netdev);
718
0
    return netnsid_eq(netdev->netnsid, nsid);
719
0
}
720
721
static bool
722
netdev_linux_netnsid_is_remote(struct netdev_linux *netdev)
723
0
{
724
0
    netdev_linux_netnsid_update(netdev);
725
0
    return netnsid_is_remote(netdev->netnsid);
726
0
}
727
728
static int netdev_linux_update_via_netlink(struct netdev_linux *);
729
static void netdev_linux_update(struct netdev_linux *netdev, int,
730
                                const struct rtnetlink_change *)
731
    OVS_REQUIRES(netdev->mutex);
732
static void netdev_linux_changed(struct netdev_linux *netdev,
733
                                 unsigned int ifi_flags, unsigned int mask)
734
    OVS_REQUIRES(netdev->mutex);
735
736
/* Returns a NETLINK_ROUTE socket listening for RTNLGRP_LINK,
737
 * RTNLGRP_IPV4_IFADDR and RTNLGRP_IPV6_IFADDR changes, or NULL
738
 * if no such socket could be created. */
739
static struct nl_sock *
740
netdev_linux_notify_sock(void)
741
0
{
742
0
    static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER;
743
0
    static struct nl_sock *sock;
744
0
    unsigned int mcgroups[] = {RTNLGRP_LINK, RTNLGRP_IPV4_IFADDR,
745
0
                                RTNLGRP_IPV6_IFADDR, RTNLGRP_IPV6_IFINFO};
746
747
0
    if (ovsthread_once_start(&once)) {
748
0
        int error;
749
750
        /* Discover (creating it if necessary) the nsid that the kernel uses
751
         * for our own namespace, before the notification socket starts
752
         * receiving namespace-tagged events. */
753
0
        netdev_linux_init_self_nsid();
754
755
0
        error = nl_sock_create(NETLINK_ROUTE, &sock);
756
0
        if (!error) {
757
0
            size_t i;
758
759
0
            nl_sock_listen_all_nsid(sock, true);
760
0
            for (i = 0; i < ARRAY_SIZE(mcgroups); i++) {
761
0
                error = nl_sock_join_mcgroup(sock, mcgroups[i]);
762
0
                if (error) {
763
0
                    nl_sock_destroy(sock);
764
0
                    sock = NULL;
765
0
                    break;
766
0
                }
767
0
            }
768
0
        }
769
0
        ovsthread_once_done(&once);
770
0
    }
771
772
0
    return sock;
773
0
}
774
775
static bool
776
netdev_linux_miimon_enabled(void)
777
0
{
778
0
    return atomic_count_get(&miimon_cnt) > 0;
779
0
}
780
781
static bool
782
netdev_linux_kind_is_lag(const char *kind)
783
0
{
784
0
    if (!strcmp(kind, "bond") || !strcmp(kind, "team")) {
785
0
        return true;
786
0
    }
787
788
0
    return false;
789
0
}
790
791
static void
792
netdev_linux_update_lag(struct rtnetlink_change *change)
793
    OVS_REQUIRES(lag_mutex)
794
0
{
795
0
    struct linux_lag_member *lag;
796
797
0
    if (change->sub && netdev_linux_kind_is_lag(change->sub)) {
798
0
        lag = shash_find_data(&lag_shash, change->ifname);
799
800
0
        if (!lag) {
801
0
            struct netdev *primary_netdev;
802
0
            char primary_name[IFNAMSIZ];
803
0
            uint32_t block_id;
804
0
            int error = 0;
805
806
0
            if (!if_indextoname(change->master_ifindex, primary_name)) {
807
0
                return;
808
0
            }
809
0
            primary_netdev = netdev_from_name(primary_name);
810
0
            if (!primary_netdev) {
811
0
                return;
812
0
            }
813
814
            /* If LAG primary member is not attached to ovs,
815
             * ingress block on LAG members should not be updated. */
816
0
            if (!primary_netdev->auto_classified &&
817
0
                is_netdev_linux_class(primary_netdev->netdev_class)) {
818
0
                block_id = netdev_get_block_id(primary_netdev);
819
0
                if (!block_id) {
820
0
                    netdev_close(primary_netdev);
821
0
                    return;
822
0
                }
823
824
0
                lag = xmalloc(sizeof *lag);
825
0
                lag->block_id = block_id;
826
0
                lag->node = shash_add(&lag_shash, change->ifname, lag);
827
828
                /* delete ingress block in case it exists */
829
0
                tc_add_del_qdisc(change->if_index, false, 0, TC_INGRESS);
830
                /* LAG primary is linux netdev so add member to same block. */
831
0
                error = tc_add_del_qdisc(change->if_index, true, block_id,
832
0
                                         TC_INGRESS);
833
0
                if (error) {
834
0
                    VLOG_WARN("failed to bind LAG member %s to "
835
0
                              "primary's block", change->ifname);
836
0
                    shash_delete(&lag_shash, lag->node);
837
0
                    free(lag);
838
0
                }
839
0
            }
840
841
0
            netdev_close(primary_netdev);
842
0
        }
843
0
    } else if (change->master_ifindex == 0) {
844
        /* Check if this was a lag member that has been removed. */
845
0
        lag = shash_find_data(&lag_shash, change->ifname);
846
847
0
        if (lag) {
848
0
            tc_add_del_qdisc(change->if_index, false, lag->block_id,
849
0
                             TC_INGRESS);
850
0
            shash_delete(&lag_shash, lag->node);
851
0
            free(lag);
852
0
        }
853
0
    }
854
0
}
855
856
void
857
netdev_linux_run(const struct netdev_class *netdev_class OVS_UNUSED)
858
0
{
859
0
    struct nl_sock *sock;
860
0
    int error;
861
862
0
    if (netdev_linux_miimon_enabled()) {
863
0
        netdev_linux_miimon_run();
864
0
    }
865
866
0
    sock = netdev_linux_notify_sock();
867
0
    if (!sock) {
868
0
        return;
869
0
    }
870
871
0
    do {
872
0
        uint64_t buf_stub[4096 / 8];
873
0
        int nsid;
874
0
        struct ofpbuf buf;
875
876
0
        ofpbuf_use_stub(&buf, buf_stub, sizeof buf_stub);
877
0
        error = nl_sock_recv(sock, &buf, &nsid, false);
878
0
        if (!error) {
879
0
            struct rtnetlink_change change;
880
881
0
            if (rtnetlink_parse(&buf, &change) && !change.irrelevant) {
882
0
                struct netdev *netdev_ = NULL;
883
0
                char dev_name[IFNAMSIZ];
884
885
0
                if (!change.ifname) {
886
0
                     change.ifname = if_indextoname(change.if_index, dev_name);
887
0
                }
888
889
0
                if (change.ifname) {
890
0
                    netdev_ = netdev_from_name(change.ifname);
891
0
                }
892
0
                if (netdev_ && is_netdev_linux_class(netdev_->netdev_class)) {
893
0
                    struct netdev_linux *netdev = netdev_linux_cast(netdev_);
894
895
0
                    ovs_mutex_lock(&netdev->mutex);
896
0
                    netdev_linux_update(netdev, nsid, &change);
897
0
                    ovs_mutex_unlock(&netdev->mutex);
898
0
                }
899
900
0
                if (change.ifname &&
901
0
                    rtnetlink_type_is_rtnlgrp_link(change.nlmsg_type)) {
902
903
                    /* Need to try updating the LAG information. */
904
0
                    ovs_mutex_lock(&lag_mutex);
905
0
                    netdev_linux_update_lag(&change);
906
0
                    ovs_mutex_unlock(&lag_mutex);
907
0
                }
908
0
                netdev_close(netdev_);
909
0
            }
910
0
        } else if (error == ENOBUFS) {
911
0
            struct shash device_shash;
912
0
            struct shash_node *node;
913
914
0
            nl_sock_drain(sock);
915
916
0
            shash_init(&device_shash);
917
0
            netdev_get_devices(&netdev_linux_class, &device_shash);
918
0
            SHASH_FOR_EACH (node, &device_shash) {
919
0
                struct netdev *netdev_ = node->data;
920
0
                struct netdev_linux *netdev = netdev_linux_cast(netdev_);
921
0
                unsigned int flags;
922
923
0
                ovs_mutex_lock(&netdev->mutex);
924
0
                get_flags(netdev_, &flags);
925
0
                netdev_linux_changed(netdev, flags, 0);
926
0
                ovs_mutex_unlock(&netdev->mutex);
927
928
0
                netdev_close(netdev_);
929
0
            }
930
0
            shash_destroy(&device_shash);
931
0
        } else if (error != EAGAIN) {
932
0
            static struct vlog_rate_limit rll = VLOG_RATE_LIMIT_INIT(1, 5);
933
0
            VLOG_WARN_RL(&rll, "error reading or parsing netlink (%s)",
934
0
                         ovs_strerror(error));
935
0
        }
936
0
        ofpbuf_uninit(&buf);
937
0
    } while (!error);
938
0
}
939
940
static void
941
netdev_linux_wait(const struct netdev_class *netdev_class OVS_UNUSED)
942
0
{
943
0
    struct nl_sock *sock;
944
945
0
    if (netdev_linux_miimon_enabled()) {
946
0
        netdev_linux_miimon_wait();
947
0
    }
948
0
    sock = netdev_linux_notify_sock();
949
0
    if (sock) {
950
0
        nl_sock_wait(sock, POLLIN);
951
0
    }
952
0
}
953
954
static void
955
netdev_linux_changed(struct netdev_linux *dev,
956
                     unsigned int ifi_flags, unsigned int mask)
957
    OVS_REQUIRES(dev->mutex)
958
0
{
959
0
    netdev_change_seq_changed(&dev->up);
960
961
0
    if ((dev->ifi_flags ^ ifi_flags) & IFF_RUNNING) {
962
0
        dev->carrier_resets++;
963
0
    }
964
0
    dev->ifi_flags = ifi_flags;
965
966
0
    dev->cache_valid &= mask;
967
0
    if (!(mask & VALID_IN)) {
968
0
        netdev_get_addrs_list_flush();
969
0
    }
970
0
}
971
972
static void
973
netdev_linux_update__(struct netdev_linux *dev,
974
                      const struct rtnetlink_change *change)
975
    OVS_REQUIRES(dev->mutex)
976
0
{
977
0
    if (rtnetlink_type_is_rtnlgrp_link(change->nlmsg_type)) {
978
0
        if (change->nlmsg_type == RTM_NEWLINK) {
979
            /* Keep drv-info, ip addresses, and NUMA id. */
980
0
            netdev_linux_changed(dev, change->ifi_flags,
981
0
                                 VALID_DRVINFO | VALID_IN | VALID_NUMA_ID);
982
983
            /* Update netdev from rtnl-change msg. */
984
0
            if (change->mtu) {
985
0
                dev->mtu = change->mtu;
986
0
                dev->cache_valid |= VALID_MTU;
987
0
                dev->netdev_mtu_error = 0;
988
0
            }
989
990
0
            if (!eth_addr_is_zero(change->mac)) {
991
0
                dev->etheraddr = change->mac;
992
0
                dev->cache_valid |= VALID_ETHERADDR;
993
0
                dev->ether_addr_error = 0;
994
995
                /* The mac addr has been changed, report it now. */
996
0
                rtnetlink_report_link();
997
0
            }
998
999
0
            if (change->primary && netdev_linux_kind_is_lag(change->primary)) {
1000
0
                dev->is_lag_primary = true;
1001
0
            }
1002
1003
0
            dev->ifindex = change->if_index;
1004
0
            dev->cache_valid |= VALID_IFINDEX;
1005
0
            dev->get_ifindex_error = 0;
1006
0
            dev->present = true;
1007
0
        } else {
1008
            /* FIXME */
1009
0
            netdev_linux_changed(dev, change->ifi_flags, 0);
1010
0
            dev->present = false;
1011
0
            netnsid_unset(&dev->netnsid);
1012
0
        }
1013
0
    } else if (rtnetlink_type_is_rtnlgrp_addr(change->nlmsg_type)) {
1014
        /* Invalidates in4, in6. */
1015
0
        netdev_linux_changed(dev, dev->ifi_flags, ~VALID_IN);
1016
0
    } else {
1017
0
        OVS_NOT_REACHED();
1018
0
    }
1019
0
}
1020
1021
static void
1022
netdev_linux_update(struct netdev_linux *dev, int nsid,
1023
                    const struct rtnetlink_change *change)
1024
    OVS_REQUIRES(dev->mutex)
1025
0
{
1026
0
    if (netdev_linux_netnsid_is_eq(dev, nsid)) {
1027
0
        netdev_linux_update__(dev, change);
1028
0
    }
1029
0
}
1030
1031
static struct netdev *
1032
netdev_linux_alloc(void)
1033
0
{
1034
0
    struct netdev_linux *netdev = xzalloc(sizeof *netdev);
1035
0
    return &netdev->up;
1036
0
}
1037
1038
static int
1039
netdev_linux_common_construct(struct netdev *netdev_)
1040
0
{
1041
    /* Prevent any attempt to create (or open) a network device named "default"
1042
     * or "all".  These device names are effectively reserved on Linux because
1043
     * /proc/sys/net/ipv4/conf/ always contains directories by these names.  By
1044
     * itself this wouldn't call for any special treatment, but in practice if
1045
     * a program tries to create devices with these names, it causes the kernel
1046
     * to fire a "new device" notification event even though creation failed,
1047
     * and in turn that causes OVS to wake up and try to create them again,
1048
     * which ends up as a 100% CPU loop. */
1049
0
    struct netdev_linux *netdev = netdev_linux_cast(netdev_);
1050
0
    const char *name = netdev_->name;
1051
0
    if (!strcmp(name, "default") || !strcmp(name, "all")) {
1052
0
        static struct vlog_rate_limit rll = VLOG_RATE_LIMIT_INIT(1, 1);
1053
0
        VLOG_WARN_RL(&rll, "%s: Linux forbids network device with this name",
1054
0
                     name);
1055
0
        return EINVAL;
1056
0
    }
1057
0
    if (strlen(name) >= IFNAMSIZ) {
1058
0
        return ENAMETOOLONG;
1059
0
    }
1060
1061
    /* The device could be in the same network namespace or in another one. */
1062
0
    netnsid_unset(&netdev->netnsid);
1063
0
    ovs_mutex_init(&netdev->mutex);
1064
1065
0
    return 0;
1066
0
}
1067
1068
/* Creates system and internal devices. */
1069
int
1070
netdev_linux_construct(struct netdev *netdev_)
1071
0
{
1072
0
    struct netdev_linux *netdev = netdev_linux_cast(netdev_);
1073
0
    int error = netdev_linux_common_construct(netdev_);
1074
0
    if (error) {
1075
0
        return error;
1076
0
    }
1077
1078
0
    if (userspace_tso_enabled()) {
1079
        /* The AF_PACKET socket interface uses the same option to facilitate
1080
         * both csum and segmentation offloading. However, these features can
1081
         * be toggled off or on individually at the interface level. The netdev
1082
         * flags are set based on the features indicated by ethtool. */
1083
0
        netdev_linux_set_ol(netdev_);
1084
0
    }
1085
1086
0
    error = get_flags(&netdev->up, &netdev->ifi_flags);
1087
0
    if (error == ENODEV) {
1088
0
        if (netdev->up.netdev_class != &netdev_internal_class) {
1089
            /* The device does not exist, so don't allow it to be opened. */
1090
0
            return ENODEV;
1091
0
        } else {
1092
            /* "Internal" netdevs have to be created as netdev objects before
1093
             * they exist in the kernel, because creating them in the kernel
1094
             * happens by passing a netdev object to dpif_port_add().
1095
             * Therefore, ignore the error. */
1096
0
        }
1097
0
    }
1098
1099
0
    return 0;
1100
0
}
1101
1102
/* For most types of netdevs we open the device for each call of
1103
 * netdev_open().  However, this is not the case with tap devices,
1104
 * since it is only possible to open the device once.  In this
1105
 * situation we share a single file descriptor, and consequently
1106
 * buffers, across all readers.  Therefore once data is read it will
1107
 * be unavailable to other reads for tap devices. */
1108
static int
1109
netdev_linux_construct_tap(struct netdev *netdev_)
1110
0
{
1111
0
    static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER;
1112
0
    struct netdev_linux *netdev = netdev_linux_cast(netdev_);
1113
0
    static const char tap_dev[] = "/dev/net/tun";
1114
0
    const char *name = netdev_->name;
1115
0
    unsigned long oflags;
1116
0
    unsigned int up;
1117
0
    struct ifreq ifr;
1118
1119
0
    int error = netdev_linux_common_construct(netdev_);
1120
0
    if (error) {
1121
0
        return error;
1122
0
    }
1123
1124
    /* Open tap device. */
1125
0
    netdev->tap_fd = open(tap_dev, O_RDWR);
1126
0
    if (netdev->tap_fd < 0) {
1127
0
        error = errno;
1128
0
        VLOG_WARN("opening \"%s\" failed: %s", tap_dev, ovs_strerror(error));
1129
0
        return error;
1130
0
    }
1131
1132
    /* Create tap device. */
1133
0
    get_flags(&netdev->up, &netdev->ifi_flags);
1134
1135
0
    if (ovsthread_once_start(&once)) {
1136
0
        if (ioctl(netdev->tap_fd, TUNGETFEATURES, &up) == -1) {
1137
0
            VLOG_WARN("%s: querying tap features failed: %s", name,
1138
0
                      ovs_strerror(errno));
1139
0
            tap_supports_vnet_hdr = false;
1140
0
        } else if (!(up & IFF_VNET_HDR)) {
1141
0
            VLOG_WARN("TAP interfaces do not support virtio-net headers");
1142
0
            tap_supports_vnet_hdr = false;
1143
0
        }
1144
0
        ovsthread_once_done(&once);
1145
0
    }
1146
1147
0
    memset(&ifr, 0, sizeof ifr);
1148
1149
0
    ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
1150
0
    if (tap_supports_vnet_hdr) {
1151
0
        ifr.ifr_flags |= IFF_VNET_HDR;
1152
0
    }
1153
1154
0
    ovs_strzcpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
1155
0
    if (ioctl(netdev->tap_fd, TUNSETIFF, &ifr) == -1) {
1156
0
        VLOG_WARN("%s: creating tap device failed: %s", name,
1157
0
                  ovs_strerror(errno));
1158
0
        error = errno;
1159
0
        goto error_close;
1160
0
    }
1161
1162
    /* Make non-blocking. */
1163
0
    error = set_nonblocking(netdev->tap_fd);
1164
0
    if (error) {
1165
0
        goto error_close;
1166
0
    }
1167
1168
0
    if (ioctl(netdev->tap_fd, TUNSETPERSIST, 1)) {
1169
0
        VLOG_WARN("%s: creating tap device failed (persist): %s", name,
1170
0
                  ovs_strerror(errno));
1171
0
        error = errno;
1172
0
        goto error_close;
1173
0
    }
1174
1175
0
    oflags = TUN_F_CSUM;
1176
0
    if (userspace_tso_enabled()) {
1177
0
        oflags |= (TUN_F_TSO4 | TUN_F_TSO6);
1178
0
    }
1179
1180
0
    if (tap_supports_vnet_hdr
1181
0
        && ioctl(netdev->tap_fd, TUNSETOFFLOAD, oflags) == 0) {
1182
0
        netdev_->ol_flags |= (NETDEV_TX_OFFLOAD_TCP_CKSUM
1183
0
                              | NETDEV_TX_OFFLOAD_UDP_CKSUM);
1184
1185
0
        if (userspace_tso_enabled()) {
1186
0
            netdev_->ol_flags |= NETDEV_TX_OFFLOAD_TCP_TSO;
1187
0
        }
1188
0
    } else {
1189
0
       VLOG_INFO("%s: Disabling checksum and segment offloading due to "
1190
0
                 "missing kernel support", name);
1191
0
    }
1192
1193
0
    netdev->present = true;
1194
0
    return 0;
1195
1196
0
error_close:
1197
0
    close(netdev->tap_fd);
1198
0
    return error;
1199
0
}
1200
1201
static void
1202
netdev_linux_destruct(struct netdev *netdev_)
1203
0
{
1204
0
    struct netdev_linux *netdev = netdev_linux_cast(netdev_);
1205
1206
0
    if (netdev->tc && netdev->tc->ops->tc_destroy) {
1207
0
        netdev->tc->ops->tc_destroy(netdev->tc);
1208
0
    }
1209
1210
0
    if (netdev_get_class(netdev_) == &netdev_tap_class
1211
0
        && netdev->tap_fd >= 0)
1212
0
    {
1213
0
        ioctl(netdev->tap_fd, TUNSETPERSIST, 0);
1214
0
        close(netdev->tap_fd);
1215
0
    }
1216
1217
0
    if (netdev->miimon_interval > 0) {
1218
0
        atomic_count_dec(&miimon_cnt);
1219
0
    }
1220
1221
0
    ovs_mutex_destroy(&netdev->mutex);
1222
0
}
1223
1224
static void
1225
netdev_linux_dealloc(struct netdev *netdev_)
1226
0
{
1227
0
    struct netdev_linux *netdev = netdev_linux_cast(netdev_);
1228
0
    free(netdev);
1229
0
}
1230
1231
static struct netdev_rxq *
1232
netdev_linux_rxq_alloc(void)
1233
0
{
1234
0
    struct netdev_rxq_linux *rx = xzalloc(sizeof *rx);
1235
0
    return &rx->up;
1236
0
}
1237
1238
static int
1239
netdev_linux_rxq_construct(struct netdev_rxq *rxq_)
1240
0
{
1241
0
    struct netdev_rxq_linux *rx = netdev_rxq_linux_cast(rxq_);
1242
0
    struct netdev *netdev_ = rx->up.netdev;
1243
0
    struct netdev_linux *netdev = netdev_linux_cast(netdev_);
1244
0
    int error;
1245
1246
0
    ovs_mutex_lock(&netdev->mutex);
1247
0
    rx->is_tap = is_tap_netdev(netdev_);
1248
0
    if (rx->is_tap) {
1249
0
        rx->fd = netdev->tap_fd;
1250
0
    } else {
1251
0
        struct sockaddr_ll sll;
1252
0
        int ifindex, val;
1253
        /* Result of tcpdump -dd inbound */
1254
0
        static const struct sock_filter filt[] = {
1255
0
            { 0x28, 0, 0, 0xfffff004 }, /* ldh [0] */
1256
0
            { 0x15, 0, 1, 0x00000004 }, /* jeq #4     jt 2  jf 3 */
1257
0
            { 0x6, 0, 0, 0x00000000 },  /* ret #0 */
1258
0
            { 0x6, 0, 0, 0x0000ffff }   /* ret #65535 */
1259
0
        };
1260
0
        static const struct sock_fprog fprog = {
1261
0
            ARRAY_SIZE(filt), (struct sock_filter *) filt
1262
0
        };
1263
1264
        /* Create file descriptor. */
1265
0
        rx->fd = socket(PF_PACKET, SOCK_RAW, 0);
1266
0
        if (rx->fd < 0) {
1267
0
            error = errno;
1268
0
            VLOG_ERR("failed to create raw socket (%s)", ovs_strerror(error));
1269
0
            goto error;
1270
0
        }
1271
1272
0
        val = 1;
1273
0
        if (setsockopt(rx->fd, SOL_PACKET, PACKET_AUXDATA, &val, sizeof val)) {
1274
0
            error = errno;
1275
0
            VLOG_ERR("%s: failed to mark socket for auxdata (%s)",
1276
0
                     netdev_get_name(netdev_), ovs_strerror(error));
1277
0
            goto error;
1278
0
        }
1279
1280
0
        if (userspace_tso_enabled()
1281
0
            && setsockopt(rx->fd, SOL_PACKET, PACKET_VNET_HDR, &val,
1282
0
                          sizeof val)) {
1283
0
            error = errno;
1284
0
            VLOG_ERR("%s: failed to enable vnet hdr in txq raw socket: %s",
1285
0
                     netdev_get_name(netdev_), ovs_strerror(errno));
1286
0
            goto error;
1287
0
        }
1288
1289
        /* Set non-blocking mode. */
1290
0
        error = set_nonblocking(rx->fd);
1291
0
        if (error) {
1292
0
            goto error;
1293
0
        }
1294
1295
        /* Get ethernet device index. */
1296
0
        error = get_ifindex(&netdev->up, &ifindex);
1297
0
        if (error) {
1298
0
            goto error;
1299
0
        }
1300
1301
        /* Bind to specific ethernet device. */
1302
0
        memset(&sll, 0, sizeof sll);
1303
0
        sll.sll_family = AF_PACKET;
1304
0
        sll.sll_ifindex = ifindex;
1305
0
        sll.sll_protocol = htons(ETH_P_ALL);
1306
0
        if (bind(rx->fd, (struct sockaddr *) &sll, sizeof sll) < 0) {
1307
0
            error = errno;
1308
0
            VLOG_ERR("%s: failed to bind raw socket (%s)",
1309
0
                     netdev_get_name(netdev_), ovs_strerror(error));
1310
0
            goto error;
1311
0
        }
1312
1313
        /* Filter for only inbound packets. */
1314
0
        error = setsockopt(rx->fd, SOL_SOCKET, SO_ATTACH_FILTER, &fprog,
1315
0
                           sizeof fprog);
1316
0
        if (error) {
1317
0
            error = errno;
1318
0
            VLOG_ERR("%s: failed to attach filter (%s)",
1319
0
                     netdev_get_name(netdev_), ovs_strerror(error));
1320
0
            goto error;
1321
0
        }
1322
0
    }
1323
0
    ovs_mutex_unlock(&netdev->mutex);
1324
1325
0
    return 0;
1326
1327
0
error:
1328
0
    if (rx->fd >= 0) {
1329
0
        close(rx->fd);
1330
0
    }
1331
0
    ovs_mutex_unlock(&netdev->mutex);
1332
0
    return error;
1333
0
}
1334
1335
static void
1336
netdev_linux_rxq_destruct(struct netdev_rxq *rxq_)
1337
0
{
1338
0
    struct netdev_rxq_linux *rx = netdev_rxq_linux_cast(rxq_);
1339
0
    int i;
1340
1341
0
    if (!rx->is_tap) {
1342
0
        close(rx->fd);
1343
0
    }
1344
1345
0
    for (i = 0; i < NETDEV_MAX_BURST; i++) {
1346
0
        dp_packet_delete(rx->aux_bufs[i]);
1347
0
    }
1348
0
}
1349
1350
static void
1351
netdev_linux_rxq_dealloc(struct netdev_rxq *rxq_)
1352
0
{
1353
0
    struct netdev_rxq_linux *rx = netdev_rxq_linux_cast(rxq_);
1354
1355
0
    free(rx);
1356
0
}
1357
1358
static ovs_be16
1359
auxdata_to_vlan_tpid(const struct tpacket_auxdata *aux, bool double_tagged)
1360
0
{
1361
0
    if (aux->tp_status & TP_STATUS_VLAN_TPID_VALID) {
1362
0
        return htons(aux->tp_vlan_tpid);
1363
0
    } else if (double_tagged) {
1364
0
        return htons(ETH_TYPE_VLAN_8021AD);
1365
0
    } else {
1366
0
        return htons(ETH_TYPE_VLAN_8021Q);
1367
0
    }
1368
0
}
1369
1370
static bool
1371
auxdata_has_vlan_tci(const struct tpacket_auxdata *aux)
1372
0
{
1373
0
    return aux->tp_vlan_tci || aux->tp_status & TP_STATUS_VLAN_VALID;
1374
0
}
1375
1376
/*
1377
 * Receive packets from raw socket in batch process for better performance,
1378
 * it can receive NETDEV_MAX_BURST packets at most once, the received
1379
 * packets are added into *batch. The return value is 0 or errno.
1380
 *
1381
 * It also used recvmmsg to reduce multiple syscalls overhead;
1382
 */
1383
static int
1384
netdev_linux_batch_rxq_recv_sock(struct netdev_rxq_linux *rx, int mtu,
1385
                                 struct dp_packet_batch *batch)
1386
0
{
1387
0
    int iovlen;
1388
0
    size_t std_len;
1389
0
    ssize_t retval;
1390
0
    int virtio_net_hdr_size;
1391
0
    struct iovec iovs[NETDEV_MAX_BURST][IOV_TSO_SIZE];
1392
0
    struct cmsghdr *cmsg;
1393
0
    union {
1394
0
        struct cmsghdr cmsg;
1395
0
        char buffer[CMSG_SPACE(sizeof(struct tpacket_auxdata))];
1396
0
    } cmsg_buffers[NETDEV_MAX_BURST];
1397
0
    struct mmsghdr mmsgs[NETDEV_MAX_BURST];
1398
0
    struct dp_packet *buffers[NETDEV_MAX_BURST];
1399
0
    int i;
1400
1401
0
    if (userspace_tso_enabled()) {
1402
        /* Use the buffer from the allocated packet below to receive MTU
1403
         * sized packets and an aux_buf for extra TSO data. */
1404
0
        iovlen = IOV_TSO_SIZE;
1405
0
        virtio_net_hdr_size = sizeof(struct virtio_net_hdr);
1406
0
    } else {
1407
        /* Use only the buffer from the allocated packet. */
1408
0
        iovlen = IOV_STD_SIZE;
1409
0
        virtio_net_hdr_size = 0;
1410
0
    }
1411
1412
    /* The length here needs to be accounted in the same way when the
1413
     * aux_buf is allocated so that it can be prepended to TSO buffer. */
1414
0
    std_len = virtio_net_hdr_size + VLAN_ETH_HEADER_LEN + mtu;
1415
0
    for (i = 0; i < NETDEV_MAX_BURST; i++) {
1416
0
        buffers[i] = dp_packet_new_with_headroom(std_len, DP_NETDEV_HEADROOM);
1417
0
        iovs[i][IOV_PACKET].iov_base = dp_packet_data(buffers[i]);
1418
0
        iovs[i][IOV_PACKET].iov_len = std_len;
1419
0
        if (iovlen == IOV_TSO_SIZE) {
1420
0
            iovs[i][IOV_AUXBUF].iov_base = dp_packet_data(rx->aux_bufs[i]);
1421
0
            iovs[i][IOV_AUXBUF].iov_len = dp_packet_tailroom(rx->aux_bufs[i]);
1422
0
        }
1423
1424
0
        mmsgs[i].msg_hdr.msg_name = NULL;
1425
0
        mmsgs[i].msg_hdr.msg_namelen = 0;
1426
0
        mmsgs[i].msg_hdr.msg_iov = iovs[i];
1427
0
        mmsgs[i].msg_hdr.msg_iovlen = iovlen;
1428
0
        mmsgs[i].msg_hdr.msg_control = &cmsg_buffers[i];
1429
0
        mmsgs[i].msg_hdr.msg_controllen = sizeof cmsg_buffers[i];
1430
0
        mmsgs[i].msg_hdr.msg_flags = 0;
1431
0
    }
1432
1433
0
    do {
1434
0
        retval = recvmmsg(rx->fd, mmsgs, NETDEV_MAX_BURST, MSG_TRUNC, NULL);
1435
0
    } while (retval < 0 && errno == EINTR);
1436
1437
0
    if (retval < 0) {
1438
0
        retval = errno;
1439
0
        for (i = 0; i < NETDEV_MAX_BURST; i++) {
1440
0
            dp_packet_delete(buffers[i]);
1441
0
        }
1442
1443
0
        return retval;
1444
0
    }
1445
1446
0
    for (i = 0; i < retval; i++) {
1447
0
        struct dp_packet *pkt;
1448
1449
0
        if (mmsgs[i].msg_hdr.msg_flags & MSG_TRUNC
1450
0
            || mmsgs[i].msg_len < ETH_HEADER_LEN) {
1451
0
            struct netdev *netdev_ = netdev_rxq_get_netdev(&rx->up);
1452
0
            struct netdev_linux *netdev = netdev_linux_cast(netdev_);
1453
1454
            /* The rx->aux_bufs[i] will be re-used next time. */
1455
0
            dp_packet_delete(buffers[i]);
1456
0
            netdev->rx_dropped += 1;
1457
0
            if (mmsgs[i].msg_hdr.msg_flags & MSG_TRUNC) {
1458
                /* Data is truncated, so the packet is corrupted, and needs
1459
                 * to be dropped. This can happen if TSO/GRO is enabled in
1460
                 * the kernel, but not in userspace, i.e. there is no dp
1461
                 * buffer to store the full packet. */
1462
0
                VLOG_WARN_RL(&rl,
1463
0
                             "%s: Dropped packet: Too big. GRO/TSO enabled?",
1464
0
                             netdev_get_name(netdev_));
1465
0
            } else {
1466
0
                VLOG_WARN_RL(&rl,
1467
0
                             "%s: Dropped packet: less than ether hdr size",
1468
0
                             netdev_get_name(netdev_));
1469
0
            }
1470
1471
0
            continue;
1472
0
        }
1473
1474
0
        if (mmsgs[i].msg_len > std_len) {
1475
            /* Build a single linear TSO packet by prepending the data from
1476
             * std_len buffer to the aux_buf. */
1477
0
            pkt = rx->aux_bufs[i];
1478
0
            dp_packet_set_size(pkt, mmsgs[i].msg_len - std_len);
1479
0
            dp_packet_push(pkt, dp_packet_data(buffers[i]), std_len);
1480
            /* The headroom should be the same in buffers[i], pkt and
1481
             * DP_NETDEV_HEADROOM. */
1482
0
            dp_packet_resize(pkt, DP_NETDEV_HEADROOM, 0);
1483
0
            dp_packet_delete(buffers[i]);
1484
0
            rx->aux_bufs[i] = NULL;
1485
0
         } else {
1486
0
            dp_packet_set_size(buffers[i], mmsgs[i].msg_len);
1487
0
            pkt = buffers[i];
1488
0
         }
1489
1490
0
        if (virtio_net_hdr_size) {
1491
0
            int ret = netdev_linux_parse_vnet_hdr(pkt);
1492
0
            if (OVS_UNLIKELY(ret)) {
1493
0
                struct netdev *netdev_ = netdev_rxq_get_netdev(&rx->up);
1494
0
                struct netdev_linux *netdev = netdev_linux_cast(netdev_);
1495
1496
                /* Unexpected error situation: the virtio header is not
1497
                 * present or corrupted or contains unsupported features.
1498
                 * Drop the packet but continue in case next ones are
1499
                 * correct. */
1500
0
                dp_packet_delete(pkt);
1501
0
                netdev->rx_dropped += 1;
1502
0
                VLOG_WARN_RL(&rl, "%s: Dropped packet: vnet header is missing "
1503
0
                             "or corrupt: %s", netdev_get_name(netdev_),
1504
0
                             ovs_strerror(ret));
1505
0
                continue;
1506
0
            }
1507
0
        }
1508
1509
0
        for (cmsg = CMSG_FIRSTHDR(&mmsgs[i].msg_hdr); cmsg;
1510
0
                 cmsg = CMSG_NXTHDR(&mmsgs[i].msg_hdr, cmsg)) {
1511
0
            const struct tpacket_auxdata *aux;
1512
1513
0
            if (cmsg->cmsg_level != SOL_PACKET
1514
0
                || cmsg->cmsg_type != PACKET_AUXDATA
1515
0
                || cmsg->cmsg_len <
1516
0
                       CMSG_LEN(sizeof(struct tpacket_auxdata))) {
1517
0
                continue;
1518
0
            }
1519
1520
0
            aux = ALIGNED_CAST(struct tpacket_auxdata *, CMSG_DATA(cmsg));
1521
0
            if (auxdata_has_vlan_tci(aux)) {
1522
0
                struct eth_header *eth;
1523
0
                bool double_tagged;
1524
1525
0
                eth = dp_packet_data(pkt);
1526
0
                double_tagged = eth->eth_type == htons(ETH_TYPE_VLAN_8021Q);
1527
1528
0
                eth_push_vlan(pkt,
1529
0
                              auxdata_to_vlan_tpid(aux, double_tagged),
1530
0
                              htons(aux->tp_vlan_tci));
1531
0
                break;
1532
0
            }
1533
0
        }
1534
0
        dp_packet_batch_add(batch, pkt);
1535
0
    }
1536
1537
    /* Delete unused buffers. */
1538
0
    for (; i < NETDEV_MAX_BURST; i++) {
1539
0
        dp_packet_delete(buffers[i]);
1540
0
    }
1541
1542
0
    return 0;
1543
0
}
1544
1545
/*
1546
 * Receive packets from tap by batch process for better performance,
1547
 * it can receive NETDEV_MAX_BURST packets at most once, the received
1548
 * packets are added into *batch. The return value is 0 or errno.
1549
 */
1550
static int
1551
netdev_linux_batch_rxq_recv_tap(struct netdev_rxq_linux *rx, int mtu,
1552
                                struct dp_packet_batch *batch)
1553
0
{
1554
0
    int virtio_net_hdr_size;
1555
0
    ssize_t retval;
1556
0
    size_t std_len;
1557
0
    int iovlen;
1558
0
    int i;
1559
1560
0
    if (userspace_tso_enabled()) {
1561
        /* Use the buffer from the allocated packet below to receive MTU
1562
         * sized packets and an aux_buf for extra TSO data. */
1563
0
        iovlen = IOV_TSO_SIZE;
1564
0
    } else {
1565
        /* Use only the buffer from the allocated packet. */
1566
0
        iovlen = IOV_STD_SIZE;
1567
0
    }
1568
0
    if (OVS_LIKELY(tap_supports_vnet_hdr)) {
1569
0
        virtio_net_hdr_size = sizeof(struct virtio_net_hdr);
1570
0
    } else {
1571
0
        virtio_net_hdr_size = 0;
1572
0
    }
1573
1574
    /* The length here needs to be accounted in the same way when the
1575
     * aux_buf is allocated so that it can be prepended to TSO buffer. */
1576
0
    std_len = virtio_net_hdr_size + VLAN_ETH_HEADER_LEN + mtu;
1577
0
    for (i = 0; i < NETDEV_MAX_BURST; i++) {
1578
0
        struct dp_packet *buffer;
1579
0
        struct dp_packet *pkt;
1580
0
        struct iovec iov[IOV_TSO_SIZE];
1581
1582
        /* Assume Ethernet port. No need to set packet_type. */
1583
0
        buffer = dp_packet_new_with_headroom(std_len, DP_NETDEV_HEADROOM);
1584
0
        iov[IOV_PACKET].iov_base = dp_packet_data(buffer);
1585
0
        iov[IOV_PACKET].iov_len = std_len;
1586
0
        if (iovlen == IOV_TSO_SIZE) {
1587
0
            iov[IOV_AUXBUF].iov_base = dp_packet_data(rx->aux_bufs[i]);
1588
0
            iov[IOV_AUXBUF].iov_len = dp_packet_tailroom(rx->aux_bufs[i]);
1589
0
        }
1590
1591
0
        do {
1592
0
            retval = readv(rx->fd, iov, iovlen);
1593
0
        } while (retval < 0 && errno == EINTR);
1594
1595
0
        if (retval < 0) {
1596
0
            dp_packet_delete(buffer);
1597
0
            break;
1598
0
        }
1599
1600
0
        if (retval > std_len) {
1601
            /* Build a single linear TSO packet by prepending the data from
1602
             * std_len buffer to the aux_buf. */
1603
0
            pkt = rx->aux_bufs[i];
1604
0
            dp_packet_set_size(pkt, retval - std_len);
1605
0
            dp_packet_push(pkt, dp_packet_data(buffer), std_len);
1606
            /* The headroom should be the same in buffers[i], pkt and
1607
             * DP_NETDEV_HEADROOM. */
1608
0
            dp_packet_resize(pkt, DP_NETDEV_HEADROOM, 0);
1609
0
            dp_packet_delete(buffer);
1610
0
            rx->aux_bufs[i] = NULL;
1611
0
        } else {
1612
0
            dp_packet_set_size(buffer, dp_packet_size(buffer) + retval);
1613
0
            pkt = buffer;
1614
0
        }
1615
1616
0
        if (OVS_LIKELY(virtio_net_hdr_size) &&
1617
0
            netdev_linux_parse_vnet_hdr(pkt)) {
1618
0
            struct netdev *netdev_ = netdev_rxq_get_netdev(&rx->up);
1619
0
            struct netdev_linux *netdev = netdev_linux_cast(netdev_);
1620
1621
            /* Unexpected error situation: the virtio header is not present
1622
             * or corrupted. Drop the packet but continue in case next ones
1623
             * are correct. */
1624
0
            dp_packet_delete(pkt);
1625
0
            netdev->rx_dropped += 1;
1626
0
            VLOG_WARN_RL(&rl, "%s: Dropped packet: Invalid virtio net header",
1627
0
                         netdev_get_name(netdev_));
1628
0
            continue;
1629
0
        }
1630
1631
0
        dp_packet_batch_add(batch, pkt);
1632
0
    }
1633
1634
0
    if ((i == 0) && (retval < 0)) {
1635
0
        return errno;
1636
0
    }
1637
1638
0
    return 0;
1639
0
}
1640
1641
static int
1642
netdev_linux_rxq_recv(struct netdev_rxq *rxq_, struct dp_packet_batch *batch,
1643
                      int *qfill)
1644
0
{
1645
0
    struct netdev_rxq_linux *rx = netdev_rxq_linux_cast(rxq_);
1646
0
    struct netdev *netdev = rx->up.netdev;
1647
0
    ssize_t retval;
1648
0
    int mtu;
1649
1650
0
    if (netdev_linux_get_mtu__(netdev_linux_cast(netdev), &mtu)) {
1651
0
        mtu = ETH_PAYLOAD_MAX;
1652
0
    }
1653
1654
0
    if (userspace_tso_enabled()) {
1655
        /* Allocate TSO packets. The packet has enough headroom to store
1656
         * a full non-TSO packet. When a TSO packet is received, the data
1657
         * from non-TSO buffer (std_len) is prepended to the TSO packet
1658
         * (aux_buf). */
1659
0
        size_t std_len = sizeof(struct virtio_net_hdr) + VLAN_ETH_HEADER_LEN
1660
0
                         + DP_NETDEV_HEADROOM + mtu;
1661
0
        size_t data_len = LINUX_RXQ_TSO_MAX_LEN - std_len;
1662
0
        for (int i = 0; i < NETDEV_MAX_BURST; i++) {
1663
0
            if (rx->aux_bufs[i]) {
1664
0
                continue;
1665
0
            }
1666
1667
0
            rx->aux_bufs[i] = dp_packet_new_with_headroom(data_len, std_len);
1668
0
        }
1669
0
    }
1670
1671
0
    dp_packet_batch_reset(batch);
1672
0
    retval = (rx->is_tap
1673
0
              ? netdev_linux_batch_rxq_recv_tap(rx, mtu, batch)
1674
0
              : netdev_linux_batch_rxq_recv_sock(rx, mtu, batch));
1675
1676
0
    if (retval) {
1677
0
        if (retval != EAGAIN && retval != EMSGSIZE) {
1678
0
            VLOG_WARN_RL(&rl, "error receiving Ethernet packet on %s: %s",
1679
0
                         netdev_rxq_get_name(rxq_), ovs_strerror(errno));
1680
0
        }
1681
0
    }
1682
1683
0
    if (qfill) {
1684
0
        *qfill = -ENOTSUP;
1685
0
    }
1686
1687
0
    return retval;
1688
0
}
1689
1690
static void
1691
netdev_linux_rxq_wait(struct netdev_rxq *rxq_)
1692
0
{
1693
0
    struct netdev_rxq_linux *rx = netdev_rxq_linux_cast(rxq_);
1694
0
    poll_fd_wait(rx->fd, POLLIN);
1695
0
}
1696
1697
static int
1698
netdev_linux_rxq_drain(struct netdev_rxq *rxq_)
1699
0
{
1700
0
    struct netdev_rxq_linux *rx = netdev_rxq_linux_cast(rxq_);
1701
0
    if (rx->is_tap) {
1702
0
        struct ifreq ifr;
1703
0
        int error;
1704
1705
0
        memset(&ifr, 0, sizeof ifr);
1706
0
        error = af_inet_ifreq_ioctl(netdev_rxq_get_name(rxq_), &ifr,
1707
0
                                    SIOCGIFTXQLEN, "SIOCGIFTXQLEN");
1708
0
        if (error) {
1709
0
            return error;
1710
0
        }
1711
0
        drain_fd(rx->fd, ifr.ifr_qlen);
1712
0
        return 0;
1713
0
    } else {
1714
0
        return drain_rcvbuf(rx->fd);
1715
0
    }
1716
0
}
1717
1718
static int
1719
netdev_linux_sock_batch_send(struct netdev *netdev_, int sock, int ifindex,
1720
                             bool tso, int mtu, struct dp_packet_batch *batch)
1721
0
{
1722
0
    struct netdev_linux *netdev = netdev_linux_cast(netdev_);
1723
0
    const size_t size = dp_packet_batch_size(batch);
1724
    /* We don't bother setting most fields in sockaddr_ll because the
1725
     * kernel ignores them for SOCK_RAW. */
1726
0
    struct sockaddr_ll sll = { .sll_family = AF_PACKET,
1727
0
                               .sll_ifindex = ifindex };
1728
1729
0
    struct mmsghdr *mmsg = xmalloc(sizeof(*mmsg) * size);
1730
0
    struct iovec *iov = xmalloc(sizeof(*iov) * size);
1731
0
    struct dp_packet *packet;
1732
0
    int cnt = 0;
1733
1734
0
    DP_PACKET_BATCH_FOR_EACH (i, packet, batch) {
1735
0
        if (tso) {
1736
0
            int ret = netdev_linux_prepend_vnet_hdr(packet, mtu);
1737
1738
0
            if (OVS_UNLIKELY(ret)) {
1739
0
                netdev->tx_dropped += 1;
1740
0
                VLOG_WARN_RL(&rl, "%s: Prepend vnet hdr failed, packet "
1741
0
                                  "dropped. %s", netdev_get_name(netdev_),
1742
0
                             ovs_strerror(ret));
1743
0
                continue;
1744
0
            }
1745
0
         }
1746
1747
0
        iov[cnt].iov_base = dp_packet_data(packet);
1748
0
        iov[cnt].iov_len = dp_packet_size(packet);
1749
0
        mmsg[cnt].msg_hdr = (struct msghdr) { .msg_name = &sll,
1750
0
                                              .msg_namelen = sizeof sll,
1751
0
                                              .msg_iov = &iov[cnt],
1752
0
                                              .msg_iovlen = 1 };
1753
0
        cnt++;
1754
0
    }
1755
1756
0
    int error = 0;
1757
0
    for (uint32_t ofs = 0; ofs < cnt;) {
1758
0
        ssize_t retval;
1759
0
        do {
1760
0
            retval = sendmmsg(sock, mmsg + ofs, cnt - ofs, 0);
1761
0
            error = retval < 0 ? errno : 0;
1762
0
        } while (error == EINTR);
1763
0
        if (error) {
1764
0
            break;
1765
0
        }
1766
0
        ofs += retval;
1767
0
    }
1768
1769
0
    free(mmsg);
1770
0
    free(iov);
1771
0
    return error;
1772
0
}
1773
1774
/* Use the tap fd to send 'batch' to tap device 'netdev'.  Using the tap fd is
1775
 * essential, because packets sent to a tap device with an AF_PACKET socket
1776
 * will loop back to be *received* again on the tap device.  This doesn't occur
1777
 * on other interface types because we attach a socket filter to the rx
1778
 * socket. */
1779
static int
1780
netdev_linux_tap_batch_send(struct netdev *netdev_, int mtu,
1781
                            struct dp_packet_batch *batch)
1782
0
{
1783
0
    struct netdev_linux *netdev = netdev_linux_cast(netdev_);
1784
0
    struct dp_packet *packet;
1785
1786
    /* The Linux tap driver returns EIO if the device is not up,
1787
     * so if the device is not up, don't waste time sending it.
1788
     * However, if the device is in another network namespace
1789
     * then OVS can't retrieve the state. In that case, send the
1790
     * packets anyway. */
1791
0
    if (netdev->present && !(netdev->ifi_flags & IFF_UP)) {
1792
0
        netdev->tx_dropped += dp_packet_batch_size(batch);
1793
0
        return 0;
1794
0
    }
1795
1796
0
    DP_PACKET_BATCH_FOR_EACH (i, packet, batch) {
1797
0
        size_t size;
1798
0
        ssize_t retval;
1799
0
        int error;
1800
1801
0
        if (OVS_LIKELY(tap_supports_vnet_hdr)) {
1802
0
            error = netdev_linux_prepend_vnet_hdr(packet, mtu);
1803
0
            if (OVS_UNLIKELY(error)) {
1804
0
                netdev->tx_dropped++;
1805
0
                VLOG_WARN_RL(&rl, "%s: Prepend vnet hdr failed, packet "
1806
0
                             "dropped. %s", netdev_get_name(netdev_),
1807
0
                             ovs_strerror(error));
1808
0
                continue;
1809
0
            }
1810
0
        }
1811
1812
0
        size = dp_packet_size(packet);
1813
0
        do {
1814
0
            retval = write(netdev->tap_fd, dp_packet_data(packet), size);
1815
0
            error = retval < 0 ? errno : 0;
1816
0
        } while (error == EINTR);
1817
1818
0
        if (error) {
1819
            /* The Linux tap driver returns EIO if the device is not up.  From
1820
             * the OVS side this is not an error, so we ignore it; otherwise,
1821
             * return the erro. */
1822
0
            if (error != EIO) {
1823
0
                return error;
1824
0
            }
1825
0
        } else if (retval != size) {
1826
0
            VLOG_WARN_RL(&rl, "sent partial Ethernet packet (%"PRIuSIZE" "
1827
0
                         "bytes of %"PRIuSIZE") on %s",
1828
0
                         retval, size, netdev_get_name(netdev_));
1829
0
            return EMSGSIZE;
1830
0
        }
1831
0
    }
1832
0
    return 0;
1833
0
}
1834
1835
static int
1836
netdev_linux_get_numa_id__(struct netdev_linux *netdev)
1837
    OVS_REQUIRES(netdev->mutex)
1838
0
{
1839
0
    char *numa_node_path;
1840
0
    const char *name;
1841
0
    int node_id;
1842
0
    FILE *stream;
1843
0
1844
0
    if (netdev->cache_valid & VALID_NUMA_ID) {
1845
0
        return netdev->numa_id;
1846
0
    }
1847
0
1848
0
    netdev->numa_id = 0;
1849
0
    netdev->cache_valid |= VALID_NUMA_ID;
1850
0
1851
0
    if (ovs_numa_get_n_numas() < 2) {
1852
0
        /* No need to check on system with a single NUMA node. */
1853
0
        return 0;
1854
0
    }
1855
0
1856
0
    name = netdev_get_name(&netdev->up);
1857
0
    if (strpbrk(name, "/\\")) {
1858
0
        VLOG_ERR_RL(&rl, "\"%s\" is not a valid name for a port. "
1859
0
                    "A valid name must not include '/' or '\\'."
1860
0
                    "Using numa_id 0", name);
1861
0
        return 0;
1862
0
    }
1863
0
1864
0
    numa_node_path = xasprintf("/sys/class/net/%s/device/numa_node", name);
1865
0
1866
0
    stream = fopen(numa_node_path, "r");
1867
0
    if (!stream) {
1868
0
        /* Virtual device does not have this info. */
1869
0
        VLOG_INFO_RL(&rl, "%s: Can't open '%s': %s, using numa_id 0",
1870
0
                     name, numa_node_path, ovs_strerror(errno));
1871
0
        free(numa_node_path);
1872
0
        return 0;
1873
0
    }
1874
0
1875
0
    if (fscanf(stream, "%d", &node_id) != 1
1876
0
        || !ovs_numa_numa_id_is_valid(node_id))  {
1877
0
        VLOG_WARN_RL(&rl, "%s: Can't detect NUMA node, using numa_id 0", name);
1878
0
        node_id = 0;
1879
0
    }
1880
0
1881
0
    netdev->numa_id = node_id;
1882
0
    fclose(stream);
1883
0
    free(numa_node_path);
1884
0
    return node_id;
1885
0
}
1886
1887
static int OVS_UNUSED
1888
netdev_linux_get_numa_id(const struct netdev *netdev_)
1889
0
{
1890
0
    struct netdev_linux *netdev = netdev_linux_cast(netdev_);
1891
0
    int numa_id;
1892
0
1893
0
    ovs_mutex_lock(&netdev->mutex);
1894
0
    numa_id = netdev_linux_get_numa_id__(netdev);
1895
0
    ovs_mutex_unlock(&netdev->mutex);
1896
0
1897
0
    return numa_id;
1898
0
}
1899
1900
/* Sends 'batch' on 'netdev'.  Returns 0 if successful, otherwise a positive
1901
 * errno value.  Returns EAGAIN without blocking if the packet cannot be queued
1902
 * immediately.  Returns EMSGSIZE if a partial packet was transmitted or if
1903
 * the packet is too big or too small to transmit on the device.
1904
 *
1905
 * The kernel maintains a packet transmission queue, so the caller is not
1906
 * expected to do additional queuing of packets. */
1907
static int
1908
netdev_linux_send(struct netdev *netdev_, int qid OVS_UNUSED,
1909
                  struct dp_packet_batch *batch,
1910
                  bool concurrent_txq OVS_UNUSED)
1911
0
{
1912
0
    bool tso = userspace_tso_enabled();
1913
0
    int mtu = ETH_PAYLOAD_MAX;
1914
0
    int error = 0;
1915
0
    int sock = 0;
1916
1917
0
    if (tso) {
1918
0
        netdev_linux_get_mtu__(netdev_linux_cast(netdev_), &mtu);
1919
0
    }
1920
1921
0
    if (!is_tap_netdev(netdev_)) {
1922
0
        if (netdev_linux_netnsid_is_remote(netdev_linux_cast(netdev_))) {
1923
0
            error = EOPNOTSUPP;
1924
0
            goto free_batch;
1925
0
        }
1926
1927
0
        sock = af_packet_sock();
1928
0
        if (sock < 0) {
1929
0
            error = -sock;
1930
0
            goto free_batch;
1931
0
        }
1932
1933
0
        int ifindex = netdev_get_ifindex(netdev_);
1934
0
        if (ifindex < 0) {
1935
0
            error = -ifindex;
1936
0
            goto free_batch;
1937
0
        }
1938
1939
0
        error = netdev_linux_sock_batch_send(netdev_, sock, ifindex, tso, mtu,
1940
0
                                             batch);
1941
0
    } else {
1942
0
        error = netdev_linux_tap_batch_send(netdev_, mtu, batch);
1943
0
    }
1944
0
    if (error) {
1945
0
        if (error == ENOBUFS) {
1946
            /* The Linux AF_PACKET implementation never blocks waiting
1947
             * for room for packets, instead returning ENOBUFS.
1948
             * Translate this into EAGAIN for the caller. */
1949
0
            error = EAGAIN;
1950
0
        } else {
1951
0
            VLOG_WARN_RL(&rl, "error sending Ethernet packet on %s: %s",
1952
0
                         netdev_get_name(netdev_), ovs_strerror(error));
1953
0
        }
1954
0
    }
1955
1956
0
free_batch:
1957
0
    dp_packet_delete_batch(batch, true);
1958
0
    return error;
1959
0
}
1960
1961
/* Registers with the poll loop to wake up from the next call to poll_block()
1962
 * when the packet transmission queue has sufficient room to transmit a packet
1963
 * with netdev_send().
1964
 *
1965
 * The kernel maintains a packet transmission queue, so the client is not
1966
 * expected to do additional queuing of packets.  Thus, this function is
1967
 * unlikely to ever be used.  It is included for completeness. */
1968
static void
1969
netdev_linux_send_wait(struct netdev *netdev, int qid OVS_UNUSED)
1970
0
{
1971
0
    if (is_tap_netdev(netdev)) {
1972
        /* TAP device always accepts packets.*/
1973
0
        poll_immediate_wake();
1974
0
    }
1975
0
}
1976
1977
/* Attempts to set 'netdev''s MAC address to 'mac'.  Returns 0 if successful,
1978
 * otherwise a positive errno value. */
1979
static int
1980
netdev_linux_set_etheraddr(struct netdev *netdev_, const struct eth_addr mac)
1981
0
{
1982
0
    struct netdev_linux *netdev = netdev_linux_cast(netdev_);
1983
0
    enum netdev_flags old_flags = 0;
1984
0
    int error;
1985
1986
0
    ovs_mutex_lock(&netdev->mutex);
1987
0
    if (netdev_linux_netnsid_is_remote(netdev)) {
1988
0
        error = EOPNOTSUPP;
1989
0
        goto exit;
1990
0
    }
1991
1992
0
    if (netdev->cache_valid & VALID_ETHERADDR) {
1993
0
        error = netdev->ether_addr_error;
1994
0
        if (error || eth_addr_equals(netdev->etheraddr, mac)) {
1995
0
            goto exit;
1996
0
        }
1997
0
        netdev->cache_valid &= ~VALID_ETHERADDR;
1998
0
    }
1999
2000
    /* Tap devices must be brought down before setting the address. */
2001
0
    if (is_tap_netdev(netdev_)) {
2002
0
        update_flags(netdev, NETDEV_UP, 0, &old_flags);
2003
0
    }
2004
0
    error = set_etheraddr(netdev_get_name(netdev_), mac);
2005
0
    if (!error || error == ENODEV) {
2006
0
        netdev->ether_addr_error = error;
2007
0
        netdev->cache_valid |= VALID_ETHERADDR;
2008
0
        if (!error) {
2009
0
            netdev->etheraddr = mac;
2010
0
        }
2011
0
    }
2012
2013
0
    if (is_tap_netdev(netdev_) && old_flags & NETDEV_UP) {
2014
0
        update_flags(netdev, 0, NETDEV_UP, &old_flags);
2015
0
    }
2016
2017
0
exit:
2018
0
    ovs_mutex_unlock(&netdev->mutex);
2019
0
    return error;
2020
0
}
2021
2022
/* Copies 'netdev''s MAC address to 'mac' which is passed as param. */
2023
static int
2024
netdev_linux_get_etheraddr(const struct netdev *netdev_, struct eth_addr *mac)
2025
0
{
2026
0
    struct netdev_linux *netdev = netdev_linux_cast(netdev_);
2027
0
    int error;
2028
2029
0
    ovs_mutex_lock(&netdev->mutex);
2030
0
    if (!(netdev->cache_valid & VALID_ETHERADDR)) {
2031
0
        netdev_linux_update_via_netlink(netdev);
2032
0
    }
2033
2034
0
    if (!(netdev->cache_valid & VALID_ETHERADDR)) {
2035
        /* Fall back to ioctl if netlink fails */
2036
0
        netdev->ether_addr_error = get_etheraddr(netdev_get_name(netdev_),
2037
0
                                                 &netdev->etheraddr);
2038
0
        netdev->cache_valid |= VALID_ETHERADDR;
2039
0
    }
2040
2041
0
    error = netdev->ether_addr_error;
2042
0
    if (!error) {
2043
0
        *mac = netdev->etheraddr;
2044
0
    }
2045
0
    ovs_mutex_unlock(&netdev->mutex);
2046
2047
0
    return error;
2048
0
}
2049
2050
static int
2051
netdev_linux_get_mtu__(struct netdev_linux *netdev, int *mtup)
2052
0
{
2053
0
    int error;
2054
2055
0
    if (!(netdev->cache_valid & VALID_MTU)) {
2056
0
        netdev_linux_update_via_netlink(netdev);
2057
0
    }
2058
2059
0
    if (!(netdev->cache_valid & VALID_MTU)) {
2060
        /* Fall back to ioctl if netlink fails */
2061
0
        struct ifreq ifr;
2062
2063
0
        memset(&ifr, 0, sizeof ifr);
2064
0
        netdev->netdev_mtu_error = af_inet_ifreq_ioctl(
2065
0
            netdev_get_name(&netdev->up), &ifr, SIOCGIFMTU, "SIOCGIFMTU");
2066
0
        netdev->mtu = ifr.ifr_mtu;
2067
0
        netdev->cache_valid |= VALID_MTU;
2068
0
    }
2069
2070
0
    error = netdev->netdev_mtu_error;
2071
0
    if (!error) {
2072
0
        *mtup = netdev->mtu;
2073
0
    }
2074
2075
0
    return error;
2076
0
}
2077
2078
/* Returns the maximum size of transmitted (and received) packets on 'netdev',
2079
 * in bytes, not including the hardware header; thus, this is typically 1500
2080
 * bytes for Ethernet devices. */
2081
static int
2082
netdev_linux_get_mtu(const struct netdev *netdev_, int *mtup)
2083
0
{
2084
0
    struct netdev_linux *netdev = netdev_linux_cast(netdev_);
2085
0
    int error;
2086
2087
0
    ovs_mutex_lock(&netdev->mutex);
2088
0
    error = netdev_linux_get_mtu__(netdev, mtup);
2089
0
    ovs_mutex_unlock(&netdev->mutex);
2090
2091
0
    return error;
2092
0
}
2093
2094
/* Sets the maximum size of transmitted (MTU) for given device using linux
2095
 * networking ioctl interface.
2096
 */
2097
static int
2098
netdev_linux_set_mtu(struct netdev *netdev_, int mtu)
2099
0
{
2100
0
    struct netdev_linux *netdev = netdev_linux_cast(netdev_);
2101
0
    struct ifreq ifr;
2102
0
    int error;
2103
2104
0
    ovs_mutex_lock(&netdev->mutex);
2105
0
    if (netdev_linux_netnsid_is_remote(netdev)) {
2106
0
        error = EOPNOTSUPP;
2107
0
        goto exit;
2108
0
    }
2109
2110
#ifdef HAVE_AF_XDP
2111
    if (netdev_get_class(netdev_) == &netdev_afxdp_class) {
2112
        error = netdev_afxdp_verify_mtu_size(netdev_, mtu);
2113
        if (error) {
2114
            goto exit;
2115
        }
2116
    }
2117
#endif
2118
2119
0
    if (netdev->cache_valid & VALID_MTU) {
2120
0
        error = netdev->netdev_mtu_error;
2121
0
        if (error || netdev->mtu == mtu) {
2122
0
            goto exit;
2123
0
        }
2124
0
        netdev->cache_valid &= ~VALID_MTU;
2125
0
    }
2126
2127
0
    memset(&ifr, 0, sizeof ifr);
2128
0
    ifr.ifr_mtu = mtu;
2129
2130
0
    error = af_inet_ifreq_ioctl(netdev_get_name(netdev_), &ifr,
2131
0
                                SIOCSIFMTU, "SIOCSIFMTU");
2132
0
    if (!error || error == ENODEV) {
2133
0
        netdev->netdev_mtu_error = error;
2134
0
        netdev->mtu = ifr.ifr_mtu;
2135
0
        netdev->cache_valid |= VALID_MTU;
2136
0
    }
2137
0
exit:
2138
0
    ovs_mutex_unlock(&netdev->mutex);
2139
0
    return error;
2140
0
}
2141
2142
/* Returns the ifindex of 'netdev', if successful, as a positive number.
2143
 * On failure, returns a negative errno value. */
2144
static int
2145
netdev_linux_get_ifindex(const struct netdev *netdev_)
2146
0
{
2147
0
    struct netdev_linux *netdev = netdev_linux_cast(netdev_);
2148
0
    int ifindex, error;
2149
2150
0
    ovs_mutex_lock(&netdev->mutex);
2151
0
    if (netdev_linux_netnsid_is_remote(netdev)) {
2152
0
        error = EOPNOTSUPP;
2153
0
        goto exit;
2154
0
    }
2155
0
    error = get_ifindex(netdev_, &ifindex);
2156
2157
0
exit:
2158
0
    ovs_mutex_unlock(&netdev->mutex);
2159
0
    return error ? -error : ifindex;
2160
0
}
2161
2162
static int
2163
netdev_linux_get_carrier(const struct netdev *netdev_, bool *carrier)
2164
0
{
2165
0
    struct netdev_linux *netdev = netdev_linux_cast(netdev_);
2166
2167
0
    ovs_mutex_lock(&netdev->mutex);
2168
0
    if (netdev->miimon_interval > 0) {
2169
0
        *carrier = netdev->miimon;
2170
0
    } else {
2171
0
        *carrier = (netdev->ifi_flags & IFF_RUNNING) != 0;
2172
0
    }
2173
0
    ovs_mutex_unlock(&netdev->mutex);
2174
2175
0
    return 0;
2176
0
}
2177
2178
static long long int
2179
netdev_linux_get_carrier_resets(const struct netdev *netdev_)
2180
0
{
2181
0
    struct netdev_linux *netdev = netdev_linux_cast(netdev_);
2182
0
    long long int carrier_resets;
2183
2184
0
    ovs_mutex_lock(&netdev->mutex);
2185
0
    carrier_resets = netdev->carrier_resets;
2186
0
    ovs_mutex_unlock(&netdev->mutex);
2187
2188
0
    return carrier_resets;
2189
0
}
2190
2191
static int
2192
netdev_linux_do_miimon(const char *name, int cmd, const char *cmd_name,
2193
                       struct mii_ioctl_data *data)
2194
0
{
2195
0
    struct ifreq ifr;
2196
0
    int error;
2197
2198
0
    memset(&ifr, 0, sizeof ifr);
2199
0
    memcpy(&ifr.ifr_data, data, sizeof *data);
2200
0
    error = af_inet_ifreq_ioctl(name, &ifr, cmd, cmd_name);
2201
0
    memcpy(data, &ifr.ifr_data, sizeof *data);
2202
2203
0
    return error;
2204
0
}
2205
2206
static int
2207
netdev_linux_get_miimon(const char *name, bool *miimon)
2208
0
{
2209
0
    struct mii_ioctl_data data;
2210
0
    int error;
2211
2212
0
    *miimon = false;
2213
2214
0
    memset(&data, 0, sizeof data);
2215
0
    error = netdev_linux_do_miimon(name, SIOCGMIIPHY, "SIOCGMIIPHY", &data);
2216
0
    if (!error) {
2217
        /* data.phy_id is filled out by previous SIOCGMIIPHY miimon call. */
2218
0
        data.reg_num = MII_BMSR;
2219
0
        error = netdev_linux_do_miimon(name, SIOCGMIIREG, "SIOCGMIIREG",
2220
0
                                       &data);
2221
2222
0
        if (!error) {
2223
0
            *miimon = !!(data.val_out & BMSR_LSTATUS);
2224
0
        }
2225
0
    }
2226
0
    if (error) {
2227
0
        struct ethtool_cmd ecmd;
2228
2229
0
        VLOG_DBG_RL(&rl, "%s: failed to query MII, falling back to ethtool",
2230
0
                    name);
2231
2232
0
        COVERAGE_INC(netdev_get_ethtool);
2233
0
        memset(&ecmd, 0, sizeof ecmd);
2234
0
        error = netdev_linux_do_ethtool(name, &ecmd, ETHTOOL_GLINK,
2235
0
                                        "ETHTOOL_GLINK");
2236
0
        if (!error) {
2237
0
            struct ethtool_value eval;
2238
2239
0
            memcpy(&eval, &ecmd, sizeof eval);
2240
0
            *miimon = !!eval.data;
2241
0
        } else {
2242
0
            VLOG_WARN_RL(&rl, "%s: ethtool link status failed", name);
2243
0
        }
2244
0
    }
2245
2246
0
    return error;
2247
0
}
2248
2249
static int
2250
netdev_linux_set_miimon_interval(struct netdev *netdev_,
2251
                                 long long int interval)
2252
0
{
2253
0
    struct netdev_linux *netdev = netdev_linux_cast(netdev_);
2254
2255
0
    ovs_mutex_lock(&netdev->mutex);
2256
0
    interval = interval > 0 ? MAX(interval, 100) : 0;
2257
0
    if (netdev->miimon_interval != interval) {
2258
0
        if (interval && !netdev->miimon_interval) {
2259
0
            atomic_count_inc(&miimon_cnt);
2260
0
        } else if (!interval && netdev->miimon_interval) {
2261
0
            atomic_count_dec(&miimon_cnt);
2262
0
        }
2263
2264
0
        netdev->miimon_interval = interval;
2265
0
        timer_set_expired(&netdev->miimon_timer);
2266
0
    }
2267
0
    ovs_mutex_unlock(&netdev->mutex);
2268
2269
0
    return 0;
2270
0
}
2271
2272
static void
2273
netdev_linux_miimon_run(void)
2274
0
{
2275
0
    struct shash device_shash;
2276
0
    struct shash_node *node;
2277
2278
0
    shash_init(&device_shash);
2279
0
    netdev_get_devices(&netdev_linux_class, &device_shash);
2280
0
    SHASH_FOR_EACH (node, &device_shash) {
2281
0
        struct netdev *netdev = node->data;
2282
0
        struct netdev_linux *dev = netdev_linux_cast(netdev);
2283
0
        bool miimon;
2284
2285
0
        ovs_mutex_lock(&dev->mutex);
2286
0
        if (dev->miimon_interval > 0 && timer_expired(&dev->miimon_timer)) {
2287
0
            netdev_linux_get_miimon(dev->up.name, &miimon);
2288
0
            if (miimon != dev->miimon) {
2289
0
                dev->miimon = miimon;
2290
0
                netdev_linux_changed(dev, dev->ifi_flags, 0);
2291
0
            }
2292
2293
0
            timer_set_duration(&dev->miimon_timer, dev->miimon_interval);
2294
0
        }
2295
0
        ovs_mutex_unlock(&dev->mutex);
2296
0
        netdev_close(netdev);
2297
0
    }
2298
2299
0
    shash_destroy(&device_shash);
2300
0
}
2301
2302
static void
2303
netdev_linux_miimon_wait(void)
2304
0
{
2305
0
    struct shash device_shash;
2306
0
    struct shash_node *node;
2307
2308
0
    shash_init(&device_shash);
2309
0
    netdev_get_devices(&netdev_linux_class, &device_shash);
2310
0
    SHASH_FOR_EACH (node, &device_shash) {
2311
0
        struct netdev *netdev = node->data;
2312
0
        struct netdev_linux *dev = netdev_linux_cast(netdev);
2313
2314
0
        ovs_mutex_lock(&dev->mutex);
2315
0
        if (dev->miimon_interval > 0) {
2316
0
            timer_wait(&dev->miimon_timer);
2317
0
        }
2318
0
        ovs_mutex_unlock(&dev->mutex);
2319
0
        netdev_close(netdev);
2320
0
    }
2321
0
    shash_destroy(&device_shash);
2322
0
}
2323
2324
static void
2325
swap_uint64(uint64_t *a, uint64_t *b)
2326
0
{
2327
0
    uint64_t tmp = *a;
2328
0
    *a = *b;
2329
0
    *b = tmp;
2330
0
}
2331
2332
/* Copies 'src' into 'dst', performing format conversion in the process.
2333
 *
2334
 * 'src' is allowed to be misaligned. */
2335
static void
2336
netdev_stats_from_ovs_vport_stats(struct netdev_stats *dst,
2337
                                  const struct dpif_netlink_vport *vport)
2338
0
{
2339
0
    dst->rx_packets = get_32aligned_u64(&vport->stats->rx_packets);
2340
0
    dst->tx_packets = get_32aligned_u64(&vport->stats->tx_packets);
2341
0
    dst->rx_bytes = get_32aligned_u64(&vport->stats->rx_bytes);
2342
0
    dst->tx_bytes = get_32aligned_u64(&vport->stats->tx_bytes);
2343
0
    dst->rx_errors = get_32aligned_u64(&vport->stats->rx_errors);
2344
0
    dst->tx_errors = get_32aligned_u64(&vport->stats->tx_errors);
2345
0
    dst->rx_dropped = get_32aligned_u64(&vport->stats->rx_dropped);
2346
0
    dst->tx_dropped = get_32aligned_u64(&vport->stats->tx_dropped);
2347
0
    dst->multicast = 0;
2348
0
    dst->collisions = 0;
2349
0
    dst->rx_length_errors = 0;
2350
0
    dst->rx_over_errors = 0;
2351
0
    dst->rx_crc_errors = 0;
2352
0
    dst->rx_frame_errors = 0;
2353
0
    dst->rx_fifo_errors = 0;
2354
0
    dst->rx_missed_errors = 0;
2355
0
    dst->tx_aborted_errors = 0;
2356
0
    dst->tx_carrier_errors = 0;
2357
0
    dst->tx_fifo_errors = 0;
2358
0
    dst->tx_heartbeat_errors = 0;
2359
0
    dst->tx_window_errors = 0;
2360
0
    dst->upcall_packets = vport->upcall_success;
2361
0
    dst->upcall_errors = vport->upcall_fail;
2362
0
}
2363
2364
static int
2365
get_stats_via_vport__(const struct netdev *netdev, struct netdev_stats *stats)
2366
0
{
2367
0
    struct dpif_netlink_vport reply;
2368
0
    struct ofpbuf *buf;
2369
0
    int error;
2370
2371
0
    error = dpif_netlink_vport_get(netdev_get_name(netdev), &reply, &buf);
2372
0
    if (error) {
2373
0
        return error;
2374
0
    } else if (!reply.stats) {
2375
0
        ofpbuf_delete(buf);
2376
0
        return EOPNOTSUPP;
2377
0
    }
2378
2379
0
    netdev_stats_from_ovs_vport_stats(stats, &reply);
2380
2381
0
    ofpbuf_delete(buf);
2382
2383
0
    return 0;
2384
0
}
2385
2386
static void
2387
get_stats_via_vport(const struct netdev *netdev_,
2388
                    struct netdev_stats *stats)
2389
0
{
2390
0
    struct netdev_linux *netdev = netdev_linux_cast(netdev_);
2391
2392
0
    if (!netdev->vport_stats_error ||
2393
0
        !(netdev->cache_valid & VALID_VPORT_STAT_ERROR)) {
2394
0
        int error;
2395
2396
0
        error = get_stats_via_vport__(netdev_, stats);
2397
0
        if (error && error != ENOENT && error != ENODEV) {
2398
0
            VLOG_WARN_RL(&rl, "%s: obtaining netdev stats via vport failed "
2399
0
                         "(%s)",
2400
0
                         netdev_get_name(netdev_), ovs_strerror(error));
2401
0
        }
2402
0
        netdev->vport_stats_error = error;
2403
0
        netdev->cache_valid |= VALID_VPORT_STAT_ERROR;
2404
0
    }
2405
0
}
2406
2407
/* Retrieves current device stats for 'netdev-linux'. */
2408
static int
2409
netdev_linux_get_stats(const struct netdev *netdev_,
2410
                       struct netdev_stats *stats)
2411
0
{
2412
0
    struct netdev_linux *netdev = netdev_linux_cast(netdev_);
2413
0
    struct netdev_stats dev_stats;
2414
0
    int error;
2415
2416
0
    ovs_mutex_lock(&netdev->mutex);
2417
0
    get_stats_via_vport(netdev_, stats);
2418
0
    error = get_stats_via_netlink(netdev_, &dev_stats);
2419
0
    if (error) {
2420
0
        if (!netdev->vport_stats_error) {
2421
0
            error = 0;
2422
0
        }
2423
0
    } else if (netdev->vport_stats_error) {
2424
        /* stats not available from OVS then use netdev stats. */
2425
0
        *stats = dev_stats;
2426
0
    } else {
2427
0
        stats->multicast           += dev_stats.multicast;
2428
0
        stats->collisions          += dev_stats.collisions;
2429
0
        stats->rx_length_errors    += dev_stats.rx_length_errors;
2430
0
        stats->rx_over_errors      += dev_stats.rx_over_errors;
2431
0
        stats->rx_crc_errors       += dev_stats.rx_crc_errors;
2432
0
        stats->rx_frame_errors     += dev_stats.rx_frame_errors;
2433
0
        stats->rx_fifo_errors      += dev_stats.rx_fifo_errors;
2434
0
        stats->rx_missed_errors    += dev_stats.rx_missed_errors;
2435
0
        stats->tx_aborted_errors   += dev_stats.tx_aborted_errors;
2436
0
        stats->tx_carrier_errors   += dev_stats.tx_carrier_errors;
2437
0
        stats->tx_fifo_errors      += dev_stats.tx_fifo_errors;
2438
0
        stats->tx_heartbeat_errors += dev_stats.tx_heartbeat_errors;
2439
0
        stats->tx_window_errors    += dev_stats.tx_window_errors;
2440
0
    }
2441
0
    ovs_mutex_unlock(&netdev->mutex);
2442
2443
0
    return error;
2444
0
}
2445
2446
/* Retrieves current device stats for 'netdev-tap' netdev or
2447
 * netdev-internal. */
2448
static int
2449
netdev_tap_get_stats(const struct netdev *netdev_, struct netdev_stats *stats)
2450
0
{
2451
0
    struct netdev_linux *netdev = netdev_linux_cast(netdev_);
2452
0
    struct netdev_stats dev_stats;
2453
0
    int error;
2454
2455
0
    ovs_mutex_lock(&netdev->mutex);
2456
0
    get_stats_via_vport(netdev_, stats);
2457
0
    error = get_stats_via_netlink(netdev_, &dev_stats);
2458
0
    if (error) {
2459
0
        if (!netdev->vport_stats_error) {
2460
0
            error = 0;
2461
0
        }
2462
0
    } else if (netdev->vport_stats_error) {
2463
        /* Transmit and receive stats will appear to be swapped relative to the
2464
         * other ports since we are the one sending the data, not a remote
2465
         * computer.  For consistency, we swap them back here. This does not
2466
         * apply if we are getting stats from the vport layer because it always
2467
         * tracks stats from the perspective of the switch. */
2468
2469
0
        *stats = dev_stats;
2470
0
        swap_uint64(&stats->rx_packets, &stats->tx_packets);
2471
0
        swap_uint64(&stats->rx_bytes, &stats->tx_bytes);
2472
0
        swap_uint64(&stats->rx_errors, &stats->tx_errors);
2473
0
        swap_uint64(&stats->rx_dropped, &stats->tx_dropped);
2474
0
        stats->rx_length_errors = 0;
2475
0
        stats->rx_over_errors = 0;
2476
0
        stats->rx_crc_errors = 0;
2477
0
        stats->rx_frame_errors = 0;
2478
0
        stats->rx_fifo_errors = 0;
2479
0
        stats->rx_missed_errors = 0;
2480
0
        stats->tx_aborted_errors = 0;
2481
0
        stats->tx_carrier_errors = 0;
2482
0
        stats->tx_fifo_errors = 0;
2483
0
        stats->tx_heartbeat_errors = 0;
2484
0
        stats->tx_window_errors = 0;
2485
0
    } else {
2486
        /* Use kernel netdev's packet and byte counts since vport counters
2487
         * do not reflect packet counts on the wire when GSO, TSO or GRO
2488
         * are enabled. */
2489
0
        stats->rx_packets = dev_stats.tx_packets;
2490
0
        stats->rx_bytes = dev_stats.tx_bytes;
2491
0
        stats->tx_packets = dev_stats.rx_packets;
2492
0
        stats->tx_bytes = dev_stats.rx_bytes;
2493
2494
0
        stats->rx_dropped          += dev_stats.tx_dropped;
2495
0
        stats->tx_dropped          += dev_stats.rx_dropped;
2496
2497
0
        stats->rx_errors           += dev_stats.tx_errors;
2498
0
        stats->tx_errors           += dev_stats.rx_errors;
2499
2500
0
        stats->multicast           += dev_stats.multicast;
2501
0
        stats->collisions          += dev_stats.collisions;
2502
0
    }
2503
0
    stats->tx_dropped += netdev->tx_dropped;
2504
0
    stats->rx_dropped += netdev->rx_dropped;
2505
0
    ovs_mutex_unlock(&netdev->mutex);
2506
2507
0
    return error;
2508
0
}
2509
2510
static int
2511
netdev_internal_get_stats(const struct netdev *netdev_,
2512
                          struct netdev_stats *stats)
2513
0
{
2514
0
    struct netdev_linux *netdev = netdev_linux_cast(netdev_);
2515
0
    int error;
2516
2517
0
    ovs_mutex_lock(&netdev->mutex);
2518
0
    get_stats_via_vport(netdev_, stats);
2519
0
    error = netdev->vport_stats_error;
2520
0
    ovs_mutex_unlock(&netdev->mutex);
2521
2522
0
    return error;
2523
0
}
2524
2525
static int
2526
netdev_linux_read_stringset_info(struct netdev_linux *netdev,
2527
                                 enum ethtool_stringset string_set,
2528
                                 uint32_t *len)
2529
0
{
2530
0
    union {
2531
0
        struct ethtool_cmd ecmd;
2532
0
        struct ethtool_sset_info hdr;
2533
0
        struct {
2534
0
            uint64_t pad[2];
2535
0
            uint32_t sset_len[1];
2536
0
        };
2537
0
    } sset_info;
2538
0
    int error;
2539
2540
0
    sset_info.hdr.cmd = ETHTOOL_GSSET_INFO;
2541
0
    sset_info.hdr.reserved = 0;
2542
0
    sset_info.hdr.sset_mask = 1ULL << string_set;
2543
2544
0
    error = netdev_linux_do_ethtool(netdev_get_name(&netdev->up),
2545
0
                                    (struct ethtool_cmd *) &sset_info,
2546
0
                                    ETHTOOL_GSSET_INFO, "ETHTOOL_GSSET_INFO");
2547
0
    if (error) {
2548
0
        return error;
2549
0
    }
2550
0
    if (sset_info.hdr.sset_mask & (1ULL << string_set)) {
2551
0
        *len = sset_info.sset_len[0];
2552
0
        return 0;
2553
0
    } else {
2554
        /* String set is not supported. */
2555
0
        return -EOPNOTSUPP;
2556
0
    }
2557
0
}
2558
2559
2560
static int
2561
netdev_linux_read_definitions(struct netdev_linux *netdev,
2562
                              enum ethtool_stringset string_set,
2563
                              struct ethtool_gstrings **pstrings)
2564
0
{
2565
0
    struct ethtool_gstrings *strings = NULL;
2566
0
    uint32_t len = 0;
2567
0
    int error = 0;
2568
2569
0
    error = netdev_linux_read_stringset_info(netdev, string_set, &len);
2570
0
    if (error) {
2571
0
        return error;
2572
0
    } else if (!len) {
2573
0
        return -EOPNOTSUPP;
2574
0
    }
2575
2576
0
    strings = xzalloc(sizeof *strings + len * ETH_GSTRING_LEN);
2577
2578
0
    strings->cmd = ETHTOOL_GSTRINGS;
2579
0
    strings->string_set = string_set;
2580
0
    strings->len = len;
2581
0
    error = netdev_linux_do_ethtool(netdev_get_name(&netdev->up),
2582
0
                                    (struct ethtool_cmd *) strings,
2583
0
                                    ETHTOOL_GSTRINGS, "ETHTOOL_GSTRINGS");
2584
0
    if (error) {
2585
0
        goto out;
2586
0
    }
2587
2588
0
    for (int i = 0; i < len; i++) {
2589
0
        strings->data[(i + 1) * ETH_GSTRING_LEN - 1] = 0;
2590
0
    }
2591
2592
0
    *pstrings = strings;
2593
2594
0
    return 0;
2595
0
out:
2596
0
    *pstrings = NULL;
2597
0
    free(strings);
2598
0
    return error;
2599
0
}
2600
2601
static void
2602
netdev_linux_set_ol(struct netdev *netdev_)
2603
0
{
2604
0
    struct netdev_linux *netdev = netdev_linux_cast(netdev_);
2605
0
    struct ethtool_gfeatures *features = NULL;
2606
0
    struct ethtool_gstrings *names = NULL;
2607
0
    int error;
2608
2609
0
    COVERAGE_INC(netdev_get_ethtool);
2610
2611
0
    error = netdev_linux_read_definitions(netdev, ETH_SS_FEATURES, &names);
2612
0
    if (error) {
2613
0
        return;
2614
0
    }
2615
2616
0
    features = xzalloc(sizeof *features +
2617
0
                       DIV_ROUND_UP(names->len, 32) *
2618
0
                       sizeof features->features[0]);
2619
2620
0
    features->cmd = ETHTOOL_GFEATURES;
2621
0
    features->size = DIV_ROUND_UP(names->len, 32);
2622
0
    error = netdev_linux_do_ethtool(netdev_get_name(netdev_),
2623
0
                                    (struct ethtool_cmd *) features,
2624
0
                                    ETHTOOL_GFEATURES, "ETHTOOL_GFEATURES");
2625
2626
0
    if (error) {
2627
0
        goto out;
2628
0
    }
2629
2630
0
#define FEATURE_WORD(blocks, index, field)  ((blocks)[(index) / 32U].field)
2631
0
#define FEATURE_FIELD_FLAG(index)       (1U << (index) % 32U)
2632
0
#define FEATURE_BIT_IS_SET(blocks, index, field)        \
2633
0
    (FEATURE_WORD(blocks, index, field) & FEATURE_FIELD_FLAG(index))
2634
2635
0
    netdev->up.ol_flags = 0;
2636
0
    static const struct {
2637
0
        char *string;
2638
0
        uint32_t value;
2639
0
    } t_list[] = {
2640
0
        {"tx-checksum-ipv4", NETDEV_TX_OFFLOAD_TCP_CKSUM |
2641
0
                             NETDEV_TX_OFFLOAD_UDP_CKSUM},
2642
0
        {"tx-checksum-ipv6", NETDEV_TX_OFFLOAD_TCP_CKSUM |
2643
0
                             NETDEV_TX_OFFLOAD_UDP_CKSUM},
2644
0
        {"tx-checksum-ip-generic", NETDEV_TX_OFFLOAD_TCP_CKSUM |
2645
0
                                   NETDEV_TX_OFFLOAD_UDP_CKSUM},
2646
0
        {"tx-checksum-sctp", NETDEV_TX_OFFLOAD_SCTP_CKSUM},
2647
0
        {"tx-tcp-segmentation", NETDEV_TX_OFFLOAD_TCP_TSO},
2648
0
    };
2649
2650
0
    for (int j = 0; j < ARRAY_SIZE(t_list); j++) {
2651
0
        for (int i = 0; i < names->len; i++) {
2652
0
            char *name = (char *) names->data + i * ETH_GSTRING_LEN;
2653
0
            if (strcmp(t_list[j].string, name) == 0) {
2654
0
                if (FEATURE_BIT_IS_SET(features->features, i, active)) {
2655
0
                    netdev_->ol_flags |= t_list[j].value;
2656
0
                }
2657
0
                break;
2658
0
            }
2659
0
        }
2660
0
    }
2661
2662
0
out:
2663
0
    free(names);
2664
0
    free(features);
2665
0
}
2666
2667
static void
2668
netdev_linux_read_features(struct netdev_linux *netdev)
2669
0
{
2670
0
    struct ethtool_cmd ecmd;
2671
0
    int error;
2672
2673
0
    if (netdev->cache_valid & VALID_FEATURES) {
2674
0
        return;
2675
0
    }
2676
2677
0
    COVERAGE_INC(netdev_get_ethtool);
2678
0
    memset(&ecmd, 0, sizeof ecmd);
2679
0
    error = netdev_linux_do_ethtool(netdev->up.name, &ecmd,
2680
0
                                    ETHTOOL_GSET, "ETHTOOL_GSET");
2681
0
    if (error) {
2682
0
        goto out;
2683
0
    }
2684
2685
    /* Supported features. */
2686
0
    netdev->supported = 0;
2687
0
    if (ecmd.supported & SUPPORTED_10baseT_Half) {
2688
0
        netdev->supported |= NETDEV_F_10MB_HD;
2689
0
    }
2690
0
    if (ecmd.supported & SUPPORTED_10baseT_Full) {
2691
0
        netdev->supported |= NETDEV_F_10MB_FD;
2692
0
    }
2693
0
    if (ecmd.supported & SUPPORTED_100baseT_Half)  {
2694
0
        netdev->supported |= NETDEV_F_100MB_HD;
2695
0
    }
2696
0
    if (ecmd.supported & SUPPORTED_100baseT_Full) {
2697
0
        netdev->supported |= NETDEV_F_100MB_FD;
2698
0
    }
2699
0
    if (ecmd.supported & SUPPORTED_1000baseT_Half) {
2700
0
        netdev->supported |= NETDEV_F_1GB_HD;
2701
0
    }
2702
0
    if ((ecmd.supported & SUPPORTED_1000baseT_Full) ||
2703
0
        (ecmd.supported & SUPPORTED_1000baseKX_Full)) {
2704
0
        netdev->supported |= NETDEV_F_1GB_FD;
2705
0
    }
2706
0
    if ((ecmd.supported & SUPPORTED_10000baseT_Full) ||
2707
0
        (ecmd.supported & SUPPORTED_10000baseKX4_Full) ||
2708
0
        (ecmd.supported & SUPPORTED_10000baseKR_Full) ||
2709
0
        (ecmd.supported & SUPPORTED_10000baseR_FEC)) {
2710
0
        netdev->supported |= NETDEV_F_10GB_FD;
2711
0
    }
2712
0
    if ((ecmd.supported & SUPPORTED_40000baseKR4_Full) ||
2713
0
        (ecmd.supported & SUPPORTED_40000baseCR4_Full) ||
2714
0
        (ecmd.supported & SUPPORTED_40000baseSR4_Full) ||
2715
0
        (ecmd.supported & SUPPORTED_40000baseLR4_Full)) {
2716
0
        netdev->supported |= NETDEV_F_40GB_FD;
2717
0
    }
2718
0
    if (ecmd.supported & SUPPORTED_TP) {
2719
0
        netdev->supported |= NETDEV_F_COPPER;
2720
0
    }
2721
0
    if (ecmd.supported & SUPPORTED_FIBRE) {
2722
0
        netdev->supported |= NETDEV_F_FIBER;
2723
0
    }
2724
0
    if (ecmd.supported & SUPPORTED_Autoneg) {
2725
0
        netdev->supported |= NETDEV_F_AUTONEG;
2726
0
    }
2727
0
    if (ecmd.supported & SUPPORTED_Pause) {
2728
0
        netdev->supported |= NETDEV_F_PAUSE;
2729
0
    }
2730
0
    if (ecmd.supported & SUPPORTED_Asym_Pause) {
2731
0
        netdev->supported |= NETDEV_F_PAUSE_ASYM;
2732
0
    }
2733
2734
    /* Advertised features. */
2735
0
    netdev->advertised = 0;
2736
0
    if (ecmd.advertising & ADVERTISED_10baseT_Half) {
2737
0
        netdev->advertised |= NETDEV_F_10MB_HD;
2738
0
    }
2739
0
    if (ecmd.advertising & ADVERTISED_10baseT_Full) {
2740
0
        netdev->advertised |= NETDEV_F_10MB_FD;
2741
0
    }
2742
0
    if (ecmd.advertising & ADVERTISED_100baseT_Half) {
2743
0
        netdev->advertised |= NETDEV_F_100MB_HD;
2744
0
    }
2745
0
    if (ecmd.advertising & ADVERTISED_100baseT_Full) {
2746
0
        netdev->advertised |= NETDEV_F_100MB_FD;
2747
0
    }
2748
0
    if (ecmd.advertising & ADVERTISED_1000baseT_Half) {
2749
0
        netdev->advertised |= NETDEV_F_1GB_HD;
2750
0
    }
2751
0
    if ((ecmd.advertising & ADVERTISED_1000baseT_Full) ||
2752
0
        (ecmd.advertising & ADVERTISED_1000baseKX_Full)) {
2753
0
        netdev->advertised |= NETDEV_F_1GB_FD;
2754
0
    }
2755
0
    if ((ecmd.advertising & ADVERTISED_10000baseT_Full) ||
2756
0
        (ecmd.advertising & ADVERTISED_10000baseKX4_Full) ||
2757
0
        (ecmd.advertising & ADVERTISED_10000baseKR_Full) ||
2758
0
        (ecmd.advertising & ADVERTISED_10000baseR_FEC)) {
2759
0
        netdev->advertised |= NETDEV_F_10GB_FD;
2760
0
    }
2761
0
    if ((ecmd.advertising & ADVERTISED_40000baseKR4_Full) ||
2762
0
        (ecmd.advertising & ADVERTISED_40000baseCR4_Full) ||
2763
0
        (ecmd.advertising & ADVERTISED_40000baseSR4_Full) ||
2764
0
        (ecmd.advertising & ADVERTISED_40000baseLR4_Full)) {
2765
0
        netdev->advertised |= NETDEV_F_40GB_FD;
2766
0
    }
2767
0
    if (ecmd.advertising & ADVERTISED_TP) {
2768
0
        netdev->advertised |= NETDEV_F_COPPER;
2769
0
    }
2770
0
    if (ecmd.advertising & ADVERTISED_FIBRE) {
2771
0
        netdev->advertised |= NETDEV_F_FIBER;
2772
0
    }
2773
0
    if (ecmd.advertising & ADVERTISED_Autoneg) {
2774
0
        netdev->advertised |= NETDEV_F_AUTONEG;
2775
0
    }
2776
0
    if (ecmd.advertising & ADVERTISED_Pause) {
2777
0
        netdev->advertised |= NETDEV_F_PAUSE;
2778
0
    }
2779
0
    if (ecmd.advertising & ADVERTISED_Asym_Pause) {
2780
0
        netdev->advertised |= NETDEV_F_PAUSE_ASYM;
2781
0
    }
2782
2783
    /* Current settings. */
2784
0
    netdev->current_speed = ethtool_cmd_speed(&ecmd);
2785
0
    if (netdev->current_speed == SPEED_10) {
2786
0
        netdev->current = ecmd.duplex ? NETDEV_F_10MB_FD : NETDEV_F_10MB_HD;
2787
0
    } else if (netdev->current_speed == SPEED_100) {
2788
0
        netdev->current = ecmd.duplex ? NETDEV_F_100MB_FD : NETDEV_F_100MB_HD;
2789
0
    } else if (netdev->current_speed == SPEED_1000) {
2790
0
        netdev->current = ecmd.duplex ? NETDEV_F_1GB_FD : NETDEV_F_1GB_HD;
2791
0
    } else if (netdev->current_speed == SPEED_10000) {
2792
0
        netdev->current = NETDEV_F_10GB_FD;
2793
0
    } else if (netdev->current_speed == SPEED_40000) {
2794
0
        netdev->current = NETDEV_F_40GB_FD;
2795
0
    } else if (netdev->current_speed == SPEED_100000) {
2796
0
        netdev->current = NETDEV_F_100GB_FD;
2797
0
    } else if (netdev->current_speed == 1000000) {
2798
0
        netdev->current = NETDEV_F_1TB_FD;
2799
0
    } else if (netdev->current_speed
2800
0
               && netdev->current_speed != SPEED_UNKNOWN) {
2801
0
        netdev->current = NETDEV_F_OTHER;
2802
0
    } else {
2803
0
        netdev->current = 0;
2804
0
    }
2805
0
    netdev->current_duplex = ecmd.duplex;
2806
2807
0
    if (ecmd.port == PORT_TP) {
2808
0
        netdev->current |= NETDEV_F_COPPER;
2809
0
    } else if (ecmd.port == PORT_FIBRE) {
2810
0
        netdev->current |= NETDEV_F_FIBER;
2811
0
    }
2812
2813
0
    if (ecmd.autoneg) {
2814
0
        netdev->current |= NETDEV_F_AUTONEG;
2815
0
    }
2816
2817
0
out:
2818
0
    netdev->cache_valid |= VALID_FEATURES;
2819
0
    netdev->get_features_error = error;
2820
0
}
2821
2822
/* Stores the features supported by 'netdev' into of '*current', '*advertised',
2823
 * '*supported', and '*peer'.  Each value is a bitmap of NETDEV_* bits.
2824
 * Returns 0 if successful, otherwise a positive errno value. */
2825
static int
2826
netdev_linux_get_features(const struct netdev *netdev_,
2827
                          enum netdev_features *current,
2828
                          enum netdev_features *advertised,
2829
                          enum netdev_features *supported,
2830
                          enum netdev_features *peer)
2831
0
{
2832
0
    struct netdev_linux *netdev = netdev_linux_cast(netdev_);
2833
0
    int error;
2834
2835
0
    ovs_mutex_lock(&netdev->mutex);
2836
0
    if (netdev_linux_netnsid_is_remote(netdev)) {
2837
0
        error = EOPNOTSUPP;
2838
0
        goto exit;
2839
0
    }
2840
2841
0
    netdev_linux_read_features(netdev);
2842
0
    if (!netdev->get_features_error) {
2843
0
        *current = netdev->current;
2844
0
        *advertised = netdev->advertised;
2845
0
        *supported = netdev->supported;
2846
0
        *peer = 0;              /* XXX */
2847
0
    }
2848
0
    error = netdev->get_features_error;
2849
2850
0
exit:
2851
0
    ovs_mutex_unlock(&netdev->mutex);
2852
0
    return error;
2853
0
}
2854
2855
static int
2856
netdev_linux_get_speed_locked(struct netdev_linux *netdev,
2857
                              uint32_t *current, uint32_t *max)
2858
0
{
2859
0
    if (netdev_linux_netnsid_is_remote(netdev)) {
2860
0
        *current = *max = 0;
2861
0
        return EOPNOTSUPP;
2862
0
    }
2863
2864
0
    netdev_linux_read_features(netdev);
2865
0
    if (!netdev->get_features_error) {
2866
0
        *current = netdev->current_speed == SPEED_UNKNOWN
2867
0
                   ? 0 : netdev->current_speed;
2868
0
        *max = MIN(UINT32_MAX,
2869
0
                   netdev_features_to_bps(netdev->supported, 0) / 1000000ULL);
2870
0
    } else {
2871
0
        *current = *max = 0;
2872
0
    }
2873
0
    return netdev->get_features_error;
2874
0
}
2875
2876
static int
2877
netdev_linux_get_speed(const struct netdev *netdev_, uint32_t *current,
2878
                       uint32_t *max)
2879
0
{
2880
0
    struct netdev_linux *netdev = netdev_linux_cast(netdev_);
2881
0
    int error;
2882
2883
0
    ovs_mutex_lock(&netdev->mutex);
2884
0
    error = netdev_linux_get_speed_locked(netdev, current, max);
2885
0
    ovs_mutex_unlock(&netdev->mutex);
2886
0
    return error;
2887
0
}
2888
2889
static int
2890
netdev_linux_get_duplex(const struct netdev *netdev_, bool *full_duplex)
2891
0
{
2892
0
    struct netdev_linux *netdev = netdev_linux_cast(netdev_);
2893
0
    int err;
2894
2895
0
    ovs_mutex_lock(&netdev->mutex);
2896
2897
0
    if (netdev_linux_netnsid_is_remote(netdev)) {
2898
0
        err = EOPNOTSUPP;
2899
0
        goto exit;
2900
0
    }
2901
2902
0
    netdev_linux_read_features(netdev);
2903
0
    err = netdev->get_features_error;
2904
0
    if (!err && netdev->current_duplex == DUPLEX_UNKNOWN) {
2905
0
        err = EOPNOTSUPP;
2906
0
        goto exit;
2907
0
    }
2908
0
    *full_duplex = netdev->current_duplex == DUPLEX_FULL;
2909
2910
0
exit:
2911
0
    ovs_mutex_unlock(&netdev->mutex);
2912
0
    return err;
2913
0
}
2914
2915
/* Set the features advertised by 'netdev' to 'advertise'. */
2916
static int
2917
netdev_linux_set_advertisements(struct netdev *netdev_,
2918
                                enum netdev_features advertise)
2919
0
{
2920
0
    struct netdev_linux *netdev = netdev_linux_cast(netdev_);
2921
0
    struct ethtool_cmd ecmd;
2922
0
    int error;
2923
2924
0
    ovs_mutex_lock(&netdev->mutex);
2925
2926
0
    COVERAGE_INC(netdev_get_ethtool);
2927
2928
0
    if (netdev_linux_netnsid_is_remote(netdev)) {
2929
0
        error = EOPNOTSUPP;
2930
0
        goto exit;
2931
0
    }
2932
2933
0
    memset(&ecmd, 0, sizeof ecmd);
2934
0
    error = netdev_linux_do_ethtool(netdev_get_name(netdev_), &ecmd,
2935
0
                                    ETHTOOL_GSET, "ETHTOOL_GSET");
2936
0
    if (error) {
2937
0
        goto exit;
2938
0
    }
2939
2940
0
    ecmd.advertising = 0;
2941
0
    if (advertise & NETDEV_F_10MB_HD) {
2942
0
        ecmd.advertising |= ADVERTISED_10baseT_Half;
2943
0
    }
2944
0
    if (advertise & NETDEV_F_10MB_FD) {
2945
0
        ecmd.advertising |= ADVERTISED_10baseT_Full;
2946
0
    }
2947
0
    if (advertise & NETDEV_F_100MB_HD) {
2948
0
        ecmd.advertising |= ADVERTISED_100baseT_Half;
2949
0
    }
2950
0
    if (advertise & NETDEV_F_100MB_FD) {
2951
0
        ecmd.advertising |= ADVERTISED_100baseT_Full;
2952
0
    }
2953
0
    if (advertise & NETDEV_F_1GB_HD) {
2954
0
        ecmd.advertising |= ADVERTISED_1000baseT_Half;
2955
0
    }
2956
0
    if (advertise & NETDEV_F_1GB_FD) {
2957
0
        ecmd.advertising |= ADVERTISED_1000baseT_Full;
2958
0
    }
2959
0
    if (advertise & NETDEV_F_10GB_FD) {
2960
0
        ecmd.advertising |= ADVERTISED_10000baseT_Full;
2961
0
    }
2962
0
    if (advertise & NETDEV_F_COPPER) {
2963
0
        ecmd.advertising |= ADVERTISED_TP;
2964
0
    }
2965
0
    if (advertise & NETDEV_F_FIBER) {
2966
0
        ecmd.advertising |= ADVERTISED_FIBRE;
2967
0
    }
2968
0
    if (advertise & NETDEV_F_AUTONEG) {
2969
0
        ecmd.advertising |= ADVERTISED_Autoneg;
2970
0
    }
2971
0
    if (advertise & NETDEV_F_PAUSE) {
2972
0
        ecmd.advertising |= ADVERTISED_Pause;
2973
0
    }
2974
0
    if (advertise & NETDEV_F_PAUSE_ASYM) {
2975
0
        ecmd.advertising |= ADVERTISED_Asym_Pause;
2976
0
    }
2977
0
    COVERAGE_INC(netdev_set_ethtool);
2978
0
    error = netdev_linux_do_ethtool(netdev_get_name(netdev_), &ecmd,
2979
0
                                    ETHTOOL_SSET, "ETHTOOL_SSET");
2980
2981
0
exit:
2982
0
    ovs_mutex_unlock(&netdev->mutex);
2983
0
    return error;
2984
0
}
2985
2986
static void
2987
nl_msg_act_police_start_nest(struct ofpbuf *request, uint32_t prio,
2988
                             size_t *offset, size_t *act_offset,
2989
                             bool single_action)
2990
0
{
2991
0
    *act_offset = nl_msg_start_nested(request, prio);
2992
0
    nl_msg_put_string(request, TCA_ACT_KIND, "police");
2993
2994
    /* If police action is added independently from filter, we need to
2995
     * add action flag according to tc-policy. */
2996
0
    if (single_action) {
2997
0
        nl_msg_put_act_tc_policy_flag(request);
2998
0
    }
2999
0
    *offset = nl_msg_start_nested(request, TCA_ACT_OPTIONS);
3000
0
}
3001
3002
static void
3003
nl_msg_act_police_end_nest(struct ofpbuf *request, size_t offset,
3004
                           size_t act_offset, uint32_t notexceed_act)
3005
0
{
3006
0
    nl_msg_put_u32(request, TCA_POLICE_RESULT, notexceed_act);
3007
0
    nl_msg_end_nested(request, offset);
3008
0
    nl_msg_end_nested(request, act_offset);
3009
0
}
3010
3011
static void
3012
nl_msg_put_act_police(struct ofpbuf *request, uint32_t index,
3013
                      uint64_t kbits_rate, uint64_t kbits_burst,
3014
                      uint64_t pkts_rate, uint64_t pkts_burst,
3015
                      uint32_t notexceed_act, bool single_action)
3016
0
{
3017
0
    uint64_t bytes_rate = kbits_rate / 8 * 1000;
3018
0
    size_t offset, act_offset;
3019
0
    struct tc_police police;
3020
0
    uint32_t prio = 0;
3021
3022
0
    if (!kbits_rate && !pkts_rate) {
3023
0
        return;
3024
0
    }
3025
3026
0
    tc_policer_init(&police, kbits_rate, kbits_burst);
3027
0
    police.index = index;
3028
3029
0
    nl_msg_act_police_start_nest(request, ++prio, &offset, &act_offset,
3030
0
                                 single_action);
3031
0
    if (police.rate.rate) {
3032
0
        tc_put_rtab(request, TCA_POLICE_RATE, &police.rate, bytes_rate);
3033
0
    }
3034
#ifdef HAVE_TCA_POLICE_PKTRATE64
3035
    if (bytes_rate > UINT32_MAX) {
3036
        nl_msg_put_u64(request, TCA_POLICE_RATE64, bytes_rate);
3037
    }
3038
#endif
3039
0
    if (pkts_rate) {
3040
0
        uint64_t pkt_burst_ticks;
3041
        /* Here tc_bytes_to_ticks is used to convert packets rather than bytes
3042
           to ticks. */
3043
0
        pkt_burst_ticks = tc_bytes_to_ticks(pkts_rate, pkts_burst);
3044
0
        nl_msg_put_u64(request, TCA_POLICE_PKTRATE64, pkts_rate);
3045
0
        nl_msg_put_u64(request, TCA_POLICE_PKTBURST64, pkt_burst_ticks);
3046
0
    }
3047
0
    nl_msg_put_unspec(request, TCA_POLICE_TBF, &police, sizeof police);
3048
0
    nl_msg_act_police_end_nest(request, offset, act_offset, notexceed_act);
3049
0
}
3050
3051
static int
3052
tc_add_matchall_policer(struct netdev *netdev, uint64_t kbits_rate,
3053
                        uint32_t kbits_burst, uint32_t kpkts_rate,
3054
                        uint32_t kpkts_burst)
3055
0
{
3056
0
    uint16_t eth_type = (OVS_FORCE uint16_t) htons(ETH_P_ALL);
3057
0
    size_t basic_offset, action_offset;
3058
0
    uint16_t prio = TC_RESERVED_PRIORITY_POLICE;
3059
0
    int ifindex, err = 0;
3060
0
    struct ofpbuf request;
3061
0
    struct ofpbuf *reply;
3062
0
    struct tcmsg *tcmsg;
3063
0
    uint32_t handle = 1;
3064
3065
0
    err = get_ifindex(netdev, &ifindex);
3066
0
    if (err) {
3067
0
        return err;
3068
0
    }
3069
3070
0
    tcmsg = tc_make_request(ifindex, RTM_NEWTFILTER, NLM_F_CREATE | NLM_F_ECHO,
3071
0
                            &request);
3072
0
    tcmsg->tcm_parent = TC_INGRESS_PARENT;
3073
0
    tcmsg->tcm_info = tc_make_handle(prio, eth_type);
3074
0
    tcmsg->tcm_handle = handle;
3075
3076
0
    nl_msg_put_string(&request, TCA_KIND, "matchall");
3077
0
    basic_offset = nl_msg_start_nested(&request, TCA_OPTIONS);
3078
0
    action_offset = nl_msg_start_nested(&request, TCA_MATCHALL_ACT);
3079
0
    nl_msg_put_act_police(&request, 0, kbits_rate, kbits_burst,
3080
0
                          kpkts_rate * 1000ULL, kpkts_burst * 1000ULL,
3081
0
                          TC_ACT_UNSPEC, false);
3082
0
    nl_msg_end_nested(&request, action_offset);
3083
0
    nl_msg_end_nested(&request, basic_offset);
3084
3085
0
    err = tc_transact(&request, &reply);
3086
0
    if (!err) {
3087
0
        struct ofpbuf b = ofpbuf_const_initializer(reply->data, reply->size);
3088
0
        struct nlmsghdr *nlmsg = ofpbuf_try_pull(&b, sizeof *nlmsg);
3089
0
        struct tcmsg *tc = ofpbuf_try_pull(&b, sizeof *tc);
3090
3091
0
        if (!nlmsg || !tc) {
3092
0
            VLOG_ERR_RL(&rl,
3093
0
                        "Failed to add match all policer, malformed reply");
3094
0
            ofpbuf_delete(reply);
3095
0
            return EPROTO;
3096
0
        }
3097
0
        ofpbuf_delete(reply);
3098
0
    }
3099
3100
0
    return err;
3101
0
}
3102
3103
static int
3104
tc_del_matchall_policer(struct netdev *netdev)
3105
0
{
3106
0
    int prio = TC_RESERVED_PRIORITY_POLICE;
3107
0
    uint32_t block_id = 0;
3108
0
    struct tcf_id id;
3109
0
    int ifindex;
3110
0
    int err;
3111
3112
0
    err = get_ifindex(netdev, &ifindex);
3113
0
    if (err) {
3114
0
        return err;
3115
0
    }
3116
3117
0
    id = tc_make_tcf_id(ifindex, block_id, prio, TC_INGRESS);
3118
0
    err = tc_del_filter(&id, "matchall");
3119
0
    if (err) {
3120
0
        return err;
3121
0
    }
3122
3123
0
    return 0;
3124
0
}
3125
3126
/* Attempts to set input rate limiting (policing) policy.  Returns 0 if
3127
 * successful, otherwise a positive errno value. */
3128
static int
3129
netdev_linux_set_policing(struct netdev *netdev_, uint32_t kbits_rate,
3130
                          uint32_t kbits_burst, uint32_t kpkts_rate,
3131
                          uint32_t kpkts_burst)
3132
0
{
3133
0
    struct netdev_linux *netdev = netdev_linux_cast(netdev_);
3134
0
    const char *netdev_name = netdev_get_name(netdev_);
3135
0
    int ifindex;
3136
0
    int error;
3137
3138
0
    kbits_burst = (!kbits_rate ? 0       /* Force to 0 if no rate specified. */
3139
0
                   : !kbits_burst ? 8000 /* Default to 8000 kbits if 0. */
3140
0
                   : kbits_burst);       /* Stick with user-specified value. */
3141
3142
0
    kpkts_burst = (!kpkts_rate ? 0       /* Force to 0 if no rate specified. */
3143
0
                   : !kpkts_burst ? 16   /* Default to 16 kpkts if 0. */
3144
0
                   : kpkts_burst);       /* Stick with user-specified value. */
3145
3146
0
    ovs_mutex_lock(&netdev->mutex);
3147
0
    if (netdev_linux_netnsid_is_remote(netdev)) {
3148
0
        error = EOPNOTSUPP;
3149
0
        goto out;
3150
0
    }
3151
3152
0
    if (netdev->cache_valid & VALID_POLICING) {
3153
0
        error = netdev->netdev_policing_error;
3154
0
        if (error || (netdev->kbits_rate == kbits_rate &&
3155
0
                      netdev->kpkts_rate == kpkts_rate &&
3156
0
                      netdev->kbits_burst == kbits_burst &&
3157
0
                      netdev->kpkts_burst == kpkts_burst)) {
3158
            /* Assume that settings haven't changed since we last set them. */
3159
0
            goto out;
3160
0
        }
3161
0
        netdev->cache_valid &= ~VALID_POLICING;
3162
0
    }
3163
3164
0
    COVERAGE_INC(netdev_set_policing);
3165
3166
    /* Use matchall for policing when offloadling ovs with tc-flower. */
3167
0
    if (dpif_offload_enabled()) {
3168
0
        error = tc_del_matchall_policer(netdev_);
3169
0
        if (kbits_rate || kpkts_rate) {
3170
0
            error = tc_add_matchall_policer(netdev_, kbits_rate, kbits_burst,
3171
0
                                            kpkts_rate, kpkts_burst);
3172
0
        }
3173
0
        goto out;
3174
0
    }
3175
3176
0
    error = get_ifindex(netdev_, &ifindex);
3177
0
    if (error) {
3178
0
        goto out;
3179
0
    }
3180
3181
    /* Remove any existing ingress qdisc. */
3182
0
    error = tc_add_del_qdisc(ifindex, false, 0, TC_INGRESS);
3183
0
    if (error) {
3184
0
        VLOG_WARN_RL(&rl, "%s: removing policing failed: %s",
3185
0
                     netdev_name, ovs_strerror(error));
3186
0
        goto out;
3187
0
    }
3188
3189
0
    if (kbits_rate || kpkts_rate) {
3190
0
        const char *cls_name = "matchall";
3191
3192
0
        error = tc_add_del_qdisc(ifindex, true, 0, TC_INGRESS);
3193
0
        if (error) {
3194
0
            VLOG_WARN_RL(&rl, "%s: adding policing qdisc failed: %s",
3195
0
                         netdev_name, ovs_strerror(error));
3196
0
            goto out;
3197
0
        }
3198
3199
0
        error = tc_add_matchall_policer(netdev_, kbits_rate, kbits_burst,
3200
0
                                        kpkts_rate, kpkts_burst);
3201
0
        if (error == ENOENT) {
3202
0
            cls_name = "basic";
3203
            /* This error is returned when the matchall classifier is missing.
3204
             * Fall back to the basic classifier.  */
3205
0
            error = tc_add_policer(netdev_, kbits_rate, kbits_burst,
3206
0
                                   kpkts_rate, kpkts_burst);
3207
0
        }
3208
0
        if (error){
3209
0
            VLOG_WARN_RL(&rl, "%s: adding cls_%s policing action failed: %s",
3210
0
                         netdev_name, cls_name, ovs_strerror(error));
3211
0
            goto out;
3212
0
        }
3213
0
    }
3214
3215
0
out:
3216
0
    if (!error) {
3217
0
        netdev->kbits_rate = kbits_rate;
3218
0
        netdev->kbits_burst = kbits_burst;
3219
0
        netdev->kpkts_rate = kpkts_rate;
3220
0
        netdev->kpkts_burst = kpkts_burst;
3221
0
    }
3222
3223
0
    if (!error || error == ENODEV) {
3224
0
        netdev->netdev_policing_error = error;
3225
0
        netdev->cache_valid |= VALID_POLICING;
3226
0
    }
3227
0
    ovs_mutex_unlock(&netdev->mutex);
3228
0
    return error;
3229
0
}
3230
3231
static int
3232
netdev_linux_get_qos_types(const struct netdev *netdev OVS_UNUSED,
3233
                           struct sset *types)
3234
0
{
3235
0
    const struct tc_ops *const *opsp;
3236
0
    for (opsp = tcs; *opsp != NULL; opsp++) {
3237
0
        const struct tc_ops *ops = *opsp;
3238
0
        if (ops->tc_install && ops->ovs_name[0] != '\0') {
3239
0
            sset_add(types, ops->ovs_name);
3240
0
        }
3241
0
    }
3242
0
    return 0;
3243
0
}
3244
3245
static const struct tc_ops *
3246
tc_lookup_ovs_name(const char *name)
3247
0
{
3248
0
    const struct tc_ops *const *opsp;
3249
3250
0
    for (opsp = tcs; *opsp != NULL; opsp++) {
3251
0
        const struct tc_ops *ops = *opsp;
3252
0
        if (!strcmp(name, ops->ovs_name)) {
3253
0
            return ops;
3254
0
        }
3255
0
    }
3256
0
    return NULL;
3257
0
}
3258
3259
static const struct tc_ops *
3260
tc_lookup_linux_name(const char *name)
3261
0
{
3262
0
    const struct tc_ops *const *opsp;
3263
3264
0
    for (opsp = tcs; *opsp != NULL; opsp++) {
3265
0
        const struct tc_ops *ops = *opsp;
3266
0
        if (ops->linux_name && !strcmp(name, ops->linux_name)) {
3267
0
            return ops;
3268
0
        }
3269
0
    }
3270
0
    return NULL;
3271
0
}
3272
3273
static struct tc_queue *
3274
tc_find_queue__(const struct netdev *netdev_, unsigned int queue_id,
3275
                size_t hash)
3276
0
{
3277
0
    struct netdev_linux *netdev = netdev_linux_cast(netdev_);
3278
0
    struct tc_queue *queue;
3279
3280
0
    HMAP_FOR_EACH_IN_BUCKET (queue, hmap_node, hash, &netdev->tc->queues) {
3281
0
        if (queue->queue_id == queue_id) {
3282
0
            return queue;
3283
0
        }
3284
0
    }
3285
0
    return NULL;
3286
0
}
3287
3288
static struct tc_queue *
3289
tc_find_queue(const struct netdev *netdev, unsigned int queue_id)
3290
0
{
3291
0
    return tc_find_queue__(netdev, queue_id, hash_int(queue_id, 0));
3292
0
}
3293
3294
static int
3295
netdev_linux_get_qos_capabilities(const struct netdev *netdev OVS_UNUSED,
3296
                                  const char *type,
3297
                                  struct netdev_qos_capabilities *caps)
3298
0
{
3299
0
    const struct tc_ops *ops = tc_lookup_ovs_name(type);
3300
0
    if (!ops) {
3301
0
        return EOPNOTSUPP;
3302
0
    }
3303
0
    caps->n_queues = ops->n_queues;
3304
0
    return 0;
3305
0
}
3306
3307
static int
3308
netdev_linux_get_qos(const struct netdev *netdev_,
3309
                     const char **typep, struct smap *details)
3310
0
{
3311
0
    struct netdev_linux *netdev = netdev_linux_cast(netdev_);
3312
0
    int error;
3313
3314
0
    ovs_mutex_lock(&netdev->mutex);
3315
0
    if (netdev_linux_netnsid_is_remote(netdev)) {
3316
0
        error = EOPNOTSUPP;
3317
0
        goto exit;
3318
0
    }
3319
3320
0
    error = tc_query_qdisc(netdev_);
3321
0
    if (!error) {
3322
0
        *typep = netdev->tc->ops->ovs_name;
3323
0
        error = (netdev->tc->ops->qdisc_get
3324
0
                 ? netdev->tc->ops->qdisc_get(netdev_, details)
3325
0
                 : 0);
3326
0
    }
3327
3328
0
exit:
3329
0
    ovs_mutex_unlock(&netdev->mutex);
3330
0
    return error;
3331
0
}
3332
3333
static int
3334
netdev_linux_set_qos(struct netdev *netdev_,
3335
                     const char *type, const struct smap *details)
3336
0
{
3337
0
    struct netdev_linux *netdev = netdev_linux_cast(netdev_);
3338
0
    const struct tc_ops *new_ops;
3339
0
    int error;
3340
3341
0
    new_ops = tc_lookup_ovs_name(type);
3342
0
    if (!new_ops || !new_ops->tc_install) {
3343
0
        return EOPNOTSUPP;
3344
0
    }
3345
3346
0
    if (new_ops == &tc_ops_noop) {
3347
0
        return new_ops->tc_install(netdev_, details);
3348
0
    }
3349
3350
0
    ovs_mutex_lock(&netdev->mutex);
3351
0
    if (netdev_linux_netnsid_is_remote(netdev)) {
3352
0
        error = EOPNOTSUPP;
3353
0
        goto exit;
3354
0
    }
3355
3356
0
    error = tc_query_qdisc(netdev_);
3357
0
    if (error) {
3358
0
        goto exit;
3359
0
    }
3360
3361
0
    if (new_ops == netdev->tc->ops) {
3362
0
        error = new_ops->qdisc_set ? new_ops->qdisc_set(netdev_, details) : 0;
3363
0
    } else {
3364
        /* Delete existing qdisc. */
3365
0
        error = tc_del_qdisc(netdev_);
3366
0
        if (error) {
3367
0
            VLOG_WARN_RL(&rl, "%s: Failed to delete existing qdisc: %s",
3368
0
                         netdev_get_name(netdev_), ovs_strerror(error));
3369
0
            goto exit;
3370
0
        }
3371
0
        ovs_assert(netdev->tc == NULL);
3372
3373
        /* Install new qdisc. */
3374
0
        error = new_ops->tc_install(netdev_, details);
3375
0
        if (error) {
3376
0
            VLOG_WARN_RL(&rl, "%s: Failed to install new qdisc: %s",
3377
0
                         netdev_get_name(netdev_), ovs_strerror(error));
3378
0
        }
3379
0
        ovs_assert((error == 0) == (netdev->tc != NULL));
3380
0
    }
3381
3382
0
exit:
3383
0
    ovs_mutex_unlock(&netdev->mutex);
3384
0
    return error;
3385
0
}
3386
3387
static int
3388
netdev_linux_get_queue(const struct netdev *netdev_,
3389
                       unsigned int queue_id, struct smap *details)
3390
0
{
3391
0
    struct netdev_linux *netdev = netdev_linux_cast(netdev_);
3392
0
    int error;
3393
3394
0
    ovs_mutex_lock(&netdev->mutex);
3395
0
    if (netdev_linux_netnsid_is_remote(netdev)) {
3396
0
        error = EOPNOTSUPP;
3397
0
        goto exit;
3398
0
    }
3399
3400
0
    error = tc_query_qdisc(netdev_);
3401
0
    if (!error) {
3402
0
        struct tc_queue *queue = tc_find_queue(netdev_, queue_id);
3403
0
        error = (queue
3404
0
                ? netdev->tc->ops->class_get(netdev_, queue, details)
3405
0
                : ENOENT);
3406
0
    }
3407
3408
0
exit:
3409
0
    ovs_mutex_unlock(&netdev->mutex);
3410
0
    return error;
3411
0
}
3412
3413
static int
3414
netdev_linux_set_queue(struct netdev *netdev_,
3415
                       unsigned int queue_id, const struct smap *details)
3416
0
{
3417
0
    struct netdev_linux *netdev = netdev_linux_cast(netdev_);
3418
0
    int error;
3419
3420
0
    ovs_mutex_lock(&netdev->mutex);
3421
0
    if (netdev_linux_netnsid_is_remote(netdev)) {
3422
0
        error = EOPNOTSUPP;
3423
0
        goto exit;
3424
0
    }
3425
3426
0
    error = tc_query_qdisc(netdev_);
3427
0
    if (!error) {
3428
0
        error = (queue_id < netdev->tc->ops->n_queues
3429
0
                 && netdev->tc->ops->class_set
3430
0
                 ? netdev->tc->ops->class_set(netdev_, queue_id, details)
3431
0
                 : EINVAL);
3432
0
    }
3433
3434
0
exit:
3435
0
    ovs_mutex_unlock(&netdev->mutex);
3436
0
    return error;
3437
0
}
3438
3439
static int
3440
netdev_linux_delete_queue(struct netdev *netdev_, unsigned int queue_id)
3441
0
{
3442
0
    struct netdev_linux *netdev = netdev_linux_cast(netdev_);
3443
0
    int error;
3444
3445
0
    ovs_mutex_lock(&netdev->mutex);
3446
0
    if (netdev_linux_netnsid_is_remote(netdev)) {
3447
0
        error = EOPNOTSUPP;
3448
0
        goto exit;
3449
0
    }
3450
3451
0
    error = tc_query_qdisc(netdev_);
3452
0
    if (!error) {
3453
0
        if (netdev->tc->ops->class_delete) {
3454
0
            struct tc_queue *queue = tc_find_queue(netdev_, queue_id);
3455
0
            error = (queue
3456
0
                     ? netdev->tc->ops->class_delete(netdev_, queue)
3457
0
                     : ENOENT);
3458
0
        } else {
3459
0
            error = EINVAL;
3460
0
        }
3461
0
    }
3462
3463
0
exit:
3464
0
    ovs_mutex_unlock(&netdev->mutex);
3465
0
    return error;
3466
0
}
3467
3468
static int
3469
netdev_linux_get_queue_stats(const struct netdev *netdev_,
3470
                             unsigned int queue_id,
3471
                             struct netdev_queue_stats *stats)
3472
0
{
3473
0
    struct netdev_linux *netdev = netdev_linux_cast(netdev_);
3474
0
    int error;
3475
3476
0
    ovs_mutex_lock(&netdev->mutex);
3477
0
    if (netdev_linux_netnsid_is_remote(netdev)) {
3478
0
        error = EOPNOTSUPP;
3479
0
        goto exit;
3480
0
    }
3481
3482
0
    error = tc_query_qdisc(netdev_);
3483
0
    if (!error) {
3484
0
        if (netdev->tc->ops->class_get_stats) {
3485
0
            const struct tc_queue *queue = tc_find_queue(netdev_, queue_id);
3486
0
            if (queue) {
3487
0
                stats->created = queue->created;
3488
0
                error = netdev->tc->ops->class_get_stats(netdev_, queue,
3489
0
                                                         stats);
3490
0
            } else {
3491
0
                error = ENOENT;
3492
0
            }
3493
0
        } else {
3494
0
            error = EOPNOTSUPP;
3495
0
        }
3496
0
    }
3497
3498
0
exit:
3499
0
    ovs_mutex_unlock(&netdev->mutex);
3500
0
    return error;
3501
0
}
3502
3503
struct queue_dump_state {
3504
    struct nl_dump dump;
3505
    struct ofpbuf buf;
3506
};
3507
3508
static bool
3509
start_queue_dump(const struct netdev *netdev, struct queue_dump_state *state)
3510
0
{
3511
0
    struct ofpbuf request;
3512
0
    struct tcmsg *tcmsg;
3513
3514
0
    tcmsg = netdev_linux_tc_make_request(netdev, RTM_GETTCLASS, 0, &request);
3515
0
    if (!tcmsg) {
3516
0
        return false;
3517
0
    }
3518
0
    tcmsg->tcm_parent = 0;
3519
0
    nl_dump_start(&state->dump, NETLINK_ROUTE, &request);
3520
0
    ofpbuf_uninit(&request);
3521
3522
0
    ofpbuf_init(&state->buf, NL_DUMP_BUFSIZE);
3523
0
    return true;
3524
0
}
3525
3526
static int
3527
finish_queue_dump(struct queue_dump_state *state)
3528
0
{
3529
0
    ofpbuf_uninit(&state->buf);
3530
0
    return nl_dump_done(&state->dump);
3531
0
}
3532
3533
struct netdev_linux_queue_state {
3534
    unsigned int *queues;
3535
    size_t cur_queue;
3536
    size_t n_queues;
3537
};
3538
3539
static int
3540
netdev_linux_queue_dump_start(const struct netdev *netdev_, void **statep)
3541
0
{
3542
0
    struct netdev_linux *netdev = netdev_linux_cast(netdev_);
3543
0
    int error;
3544
3545
0
    ovs_mutex_lock(&netdev->mutex);
3546
0
    if (netdev_linux_netnsid_is_remote(netdev)) {
3547
0
        error = EOPNOTSUPP;
3548
0
        goto exit;
3549
0
    }
3550
3551
0
    error = tc_query_qdisc(netdev_);
3552
0
    if (!error) {
3553
0
        if (netdev->tc->ops->class_get) {
3554
0
            struct netdev_linux_queue_state *state;
3555
0
            struct tc_queue *queue;
3556
0
            size_t i;
3557
3558
0
            *statep = state = xmalloc(sizeof *state);
3559
0
            state->n_queues = hmap_count(&netdev->tc->queues);
3560
0
            state->cur_queue = 0;
3561
0
            state->queues = xmalloc(state->n_queues * sizeof *state->queues);
3562
3563
0
            i = 0;
3564
0
            HMAP_FOR_EACH (queue, hmap_node, &netdev->tc->queues) {
3565
0
                state->queues[i++] = queue->queue_id;
3566
0
            }
3567
0
        } else {
3568
0
            error = EOPNOTSUPP;
3569
0
        }
3570
0
    }
3571
3572
0
exit:
3573
0
    ovs_mutex_unlock(&netdev->mutex);
3574
0
    return error;
3575
0
}
3576
3577
static int
3578
netdev_linux_queue_dump_next(const struct netdev *netdev_, void *state_,
3579
                             unsigned int *queue_idp, struct smap *details)
3580
0
{
3581
0
    struct netdev_linux *netdev = netdev_linux_cast(netdev_);
3582
0
    struct netdev_linux_queue_state *state = state_;
3583
0
    int error = EOF;
3584
3585
0
    ovs_mutex_lock(&netdev->mutex);
3586
0
    if (netdev_linux_netnsid_is_remote(netdev)) {
3587
0
        error = EOPNOTSUPP;
3588
0
        goto exit;
3589
0
    }
3590
3591
0
    while (state->cur_queue < state->n_queues) {
3592
0
        unsigned int queue_id = state->queues[state->cur_queue++];
3593
0
        struct tc_queue *queue = tc_find_queue(netdev_, queue_id);
3594
3595
0
        if (queue) {
3596
0
            *queue_idp = queue_id;
3597
0
            error = netdev->tc->ops->class_get(netdev_, queue, details);
3598
0
            break;
3599
0
        }
3600
0
    }
3601
3602
0
exit:
3603
0
    ovs_mutex_unlock(&netdev->mutex);
3604
0
    return error;
3605
0
}
3606
3607
static int
3608
netdev_linux_queue_dump_done(const struct netdev *netdev OVS_UNUSED,
3609
                             void *state_)
3610
0
{
3611
0
    struct netdev_linux_queue_state *state = state_;
3612
3613
0
    free(state->queues);
3614
0
    free(state);
3615
0
    return 0;
3616
0
}
3617
3618
static int
3619
netdev_linux_dump_queue_stats(const struct netdev *netdev_,
3620
                              netdev_dump_queue_stats_cb *cb, void *aux)
3621
0
{
3622
0
    struct netdev_linux *netdev = netdev_linux_cast(netdev_);
3623
0
    int error;
3624
3625
0
    ovs_mutex_lock(&netdev->mutex);
3626
0
    if (netdev_linux_netnsid_is_remote(netdev)) {
3627
0
        error = EOPNOTSUPP;
3628
0
        goto exit;
3629
0
    }
3630
3631
0
    error = tc_query_qdisc(netdev_);
3632
0
    if (!error) {
3633
0
        struct queue_dump_state state;
3634
3635
0
        if (!netdev->tc->ops->class_dump_stats) {
3636
0
            error = EOPNOTSUPP;
3637
0
        } else if (!start_queue_dump(netdev_, &state)) {
3638
0
            error = ENODEV;
3639
0
        } else {
3640
0
            struct ofpbuf msg;
3641
0
            int retval;
3642
3643
0
            while (nl_dump_next(&state.dump, &msg, &state.buf)) {
3644
0
                retval = netdev->tc->ops->class_dump_stats(netdev_, &msg,
3645
0
                                                           cb, aux);
3646
0
                if (retval) {
3647
0
                    error = retval;
3648
0
                }
3649
0
            }
3650
3651
0
            retval = finish_queue_dump(&state);
3652
0
            if (retval) {
3653
0
                error = retval;
3654
0
            }
3655
0
        }
3656
0
    }
3657
3658
0
exit:
3659
0
    ovs_mutex_unlock(&netdev->mutex);
3660
0
    return error;
3661
0
}
3662
3663
static int
3664
netdev_linux_set_in4(struct netdev *netdev_, struct in_addr address,
3665
                     struct in_addr netmask)
3666
0
{
3667
0
    struct netdev_linux *netdev = netdev_linux_cast(netdev_);
3668
0
    int error;
3669
3670
0
    ovs_mutex_lock(&netdev->mutex);
3671
0
    if (netdev_linux_netnsid_is_remote(netdev)) {
3672
0
        error = EOPNOTSUPP;
3673
0
        goto exit;
3674
0
    }
3675
3676
0
    error = do_set_addr(netdev_, SIOCSIFADDR, "SIOCSIFADDR", address);
3677
0
    if (!error) {
3678
0
        if (address.s_addr != INADDR_ANY) {
3679
0
            error = do_set_addr(netdev_, SIOCSIFNETMASK,
3680
0
                                "SIOCSIFNETMASK", netmask);
3681
0
        }
3682
0
    }
3683
3684
0
exit:
3685
0
    ovs_mutex_unlock(&netdev->mutex);
3686
0
    return error;
3687
0
}
3688
3689
/* If 'netdev' has an assigned IPv6 address, sets '*in6' to that address.
3690
 * Otherwise, sets '*in6' to 'in6addr_any' and returns the corresponding
3691
 * error. */
3692
static int
3693
netdev_linux_get_addr_list(const struct netdev *netdev_,
3694
                          struct in6_addr **addr, struct in6_addr **mask, int *n_cnt)
3695
0
{
3696
0
    struct netdev_linux *netdev = netdev_linux_cast(netdev_);
3697
0
    int error;
3698
3699
0
    ovs_mutex_lock(&netdev->mutex);
3700
0
    if (netdev_linux_netnsid_is_remote(netdev)) {
3701
0
        error = EOPNOTSUPP;
3702
0
        goto exit;
3703
0
    }
3704
3705
0
    error = netdev_get_addrs(netdev_get_name(netdev_), addr, mask, n_cnt);
3706
3707
0
exit:
3708
0
    ovs_mutex_unlock(&netdev->mutex);
3709
0
    return error;
3710
0
}
3711
3712
static void
3713
make_in4_sockaddr(struct sockaddr *sa, struct in_addr addr)
3714
0
{
3715
0
    struct sockaddr_in sin;
3716
0
    memset(&sin, 0, sizeof sin);
3717
0
    sin.sin_family = AF_INET;
3718
0
    sin.sin_addr = addr;
3719
0
    sin.sin_port = 0;
3720
3721
0
    memset(sa, 0, sizeof *sa);
3722
0
    memcpy(sa, &sin, sizeof sin);
3723
0
}
3724
3725
static int
3726
do_set_addr(struct netdev *netdev,
3727
            int ioctl_nr, const char *ioctl_name, struct in_addr addr)
3728
0
{
3729
0
    struct ifreq ifr;
3730
3731
0
    memset(&ifr, 0, sizeof ifr);
3732
0
    make_in4_sockaddr(&ifr.ifr_addr, addr);
3733
0
    return af_inet_ifreq_ioctl(netdev_get_name(netdev), &ifr, ioctl_nr,
3734
0
                               ioctl_name);
3735
0
}
3736
3737
/* Adds 'router' as a default IP gateway. */
3738
static int
3739
netdev_linux_add_router(struct netdev *netdev OVS_UNUSED, struct in_addr router)
3740
0
{
3741
0
    struct in_addr any = { INADDR_ANY };
3742
0
    struct rtentry rt;
3743
0
    int error;
3744
3745
0
    memset(&rt, 0, sizeof rt);
3746
0
    make_in4_sockaddr(&rt.rt_dst, any);
3747
0
    make_in4_sockaddr(&rt.rt_gateway, router);
3748
0
    make_in4_sockaddr(&rt.rt_genmask, any);
3749
0
    rt.rt_flags = RTF_UP | RTF_GATEWAY;
3750
0
    error = af_inet_ioctl(SIOCADDRT, &rt);
3751
0
    if (error) {
3752
0
        VLOG_WARN("ioctl(SIOCADDRT): %s", ovs_strerror(error));
3753
0
    }
3754
0
    return error;
3755
0
}
3756
3757
static int
3758
netdev_linux_get_next_hop(const struct in_addr *host, struct in_addr *next_hop,
3759
                          char **netdev_name)
3760
0
{
3761
0
    static const char fn[] = "/proc/net/route";
3762
0
    FILE *stream;
3763
0
    char line[256];
3764
0
    int ln;
3765
3766
0
    *netdev_name = NULL;
3767
0
    stream = fopen(fn, "r");
3768
0
    if (stream == NULL) {
3769
0
        VLOG_WARN_RL(&rl, "%s: open failed: %s", fn, ovs_strerror(errno));
3770
0
        return errno;
3771
0
    }
3772
3773
0
    ln = 0;
3774
0
    while (fgets(line, sizeof line, stream)) {
3775
0
        if (++ln >= 2) {
3776
0
            char iface[17];
3777
0
            ovs_be32 dest, gateway, mask;
3778
0
            int refcnt, metric, mtu;
3779
0
            unsigned int flags, use, window, irtt;
3780
3781
0
            if (!ovs_scan(line,
3782
0
                          "%16s %"SCNx32" %"SCNx32" %04X %d %u %d %"SCNx32
3783
0
                          " %d %u %u\n",
3784
0
                          iface, &dest, &gateway, &flags, &refcnt,
3785
0
                          &use, &metric, &mask, &mtu, &window, &irtt)) {
3786
0
                VLOG_WARN_RL(&rl, "%s: could not parse line %d: %s",
3787
0
                        fn, ln, line);
3788
0
                continue;
3789
0
            }
3790
0
            if (!(flags & RTF_UP)) {
3791
                /* Skip routes that aren't up. */
3792
0
                continue;
3793
0
            }
3794
3795
            /* The output of 'dest', 'mask', and 'gateway' were given in
3796
             * network byte order, so we don't need need any endian
3797
             * conversions here. */
3798
0
            if ((dest & mask) == (host->s_addr & mask)) {
3799
0
                if (!gateway) {
3800
                    /* The host is directly reachable. */
3801
0
                    next_hop->s_addr = 0;
3802
0
                } else {
3803
                    /* To reach the host, we must go through a gateway. */
3804
0
                    next_hop->s_addr = gateway;
3805
0
                }
3806
0
                *netdev_name = xstrdup(iface);
3807
0
                fclose(stream);
3808
0
                return 0;
3809
0
            }
3810
0
        }
3811
0
    }
3812
3813
0
    fclose(stream);
3814
0
    return ENXIO;
3815
0
}
3816
3817
/* For veth devices, query peer_ifindex via ethtool statistics. */
3818
static void
3819
netdev_linux_get_peer_ifindex(struct netdev_linux *netdev)
3820
0
{
3821
0
    struct ethtool_gstrings *names = NULL;
3822
0
    struct ethtool_stats *stats = NULL;
3823
0
    size_t n_stats = netdev->drvinfo.n_stats;
3824
0
    struct ethtool_cmd *cmd;
3825
0
    int error;
3826
3827
0
    if (strcmp(netdev->drvinfo.driver, "veth") || !n_stats) {
3828
0
        return;
3829
0
    }
3830
3831
0
    error = netdev_linux_read_definitions(netdev, ETH_SS_STATS, &names);
3832
0
    if (error) {
3833
0
        return;
3834
0
    }
3835
3836
0
    stats = xzalloc(sizeof *stats + n_stats * sizeof stats->data[0]);
3837
0
    stats->cmd = ETHTOOL_GSTATS;
3838
0
    stats->n_stats = n_stats;
3839
3840
0
    cmd = (struct ethtool_cmd *) stats;
3841
0
    error = netdev_linux_do_ethtool(netdev->up.name, cmd,
3842
0
                                    ETHTOOL_GSTATS, "ETHTOOL_GSTATS");
3843
0
    if (error) {
3844
0
        free(stats);
3845
0
        free(names);
3846
0
        return;
3847
0
    }
3848
3849
0
    for (uint32_t i = 0; i < names->len && i < stats->n_stats; i++) {
3850
0
        char *name = (char *) &names->data[i * ETH_GSTRING_LEN];
3851
3852
0
        if (!strcmp(name, "peer_ifindex")) {
3853
0
            netdev->peer_ifindex = stats->data[i];
3854
0
            break;
3855
0
        }
3856
0
    }
3857
3858
0
    free(stats);
3859
0
    free(names);
3860
0
}
3861
3862
int
3863
netdev_linux_get_status(const struct netdev *netdev_, struct smap *smap)
3864
0
{
3865
0
    struct netdev_linux *netdev = netdev_linux_cast(netdev_);
3866
0
    int error = 0;
3867
3868
0
    ovs_mutex_lock(&netdev->mutex);
3869
0
    if (!(netdev->cache_valid & VALID_DRVINFO)) {
3870
0
        struct ethtool_cmd *cmd = (struct ethtool_cmd *) &netdev->drvinfo;
3871
3872
0
        COVERAGE_INC(netdev_get_ethtool);
3873
0
        memset(&netdev->drvinfo, 0, sizeof netdev->drvinfo);
3874
0
        netdev->peer_ifindex = 0;
3875
0
        error = netdev_linux_do_ethtool(netdev->up.name,
3876
0
                                        cmd,
3877
0
                                        ETHTOOL_GDRVINFO,
3878
0
                                        "ETHTOOL_GDRVINFO");
3879
0
        if (!error) {
3880
0
            netdev_linux_get_peer_ifindex(netdev);
3881
0
            netdev->cache_valid |= VALID_DRVINFO;
3882
0
        }
3883
0
    }
3884
3885
0
    if (!error) {
3886
0
        smap_add(smap, "driver_name", netdev->drvinfo.driver);
3887
0
        smap_add(smap, "driver_version", netdev->drvinfo.version);
3888
0
        smap_add(smap, "firmware_version", netdev->drvinfo.fw_version);
3889
3890
0
        if (netdev->peer_ifindex) {
3891
0
            smap_add_format(smap, "peer_ifindex",
3892
0
                            "%"PRIu64, netdev->peer_ifindex);
3893
0
        }
3894
0
    }
3895
0
    ovs_mutex_unlock(&netdev->mutex);
3896
3897
0
    return error;
3898
0
}
3899
3900
static int
3901
netdev_internal_get_status(const struct netdev *netdev OVS_UNUSED,
3902
                           struct smap *smap)
3903
0
{
3904
0
    smap_add(smap, "driver_name", "openvswitch");
3905
0
    return 0;
3906
0
}
3907
3908
static uint32_t
3909
netdev_linux_get_block_id(struct netdev *netdev_)
3910
0
{
3911
0
    struct netdev_linux *netdev = netdev_linux_cast(netdev_);
3912
0
    uint32_t block_id = 0;
3913
3914
0
    ovs_mutex_lock(&netdev->mutex);
3915
    /* Ensure the linux netdev has had its fields populated. */
3916
0
    if (!(netdev->cache_valid & VALID_IFINDEX)) {
3917
0
        netdev_linux_update_via_netlink(netdev);
3918
0
    }
3919
3920
    /* Only assigning block ids to linux netdevs that are
3921
     * LAG primary members. */
3922
0
    if (netdev->is_lag_primary) {
3923
0
        block_id = netdev->ifindex;
3924
0
    }
3925
0
    ovs_mutex_unlock(&netdev->mutex);
3926
3927
0
    return block_id;
3928
0
}
3929
3930
/* Looks up the ARP table entry for 'ip' on 'netdev'.  If one exists and can be
3931
 * successfully retrieved, it stores the corresponding MAC address in 'mac' and
3932
 * returns 0.  Otherwise, it returns a positive errno value; in particular,
3933
 * ENXIO indicates that there is not ARP table entry for 'ip' on 'netdev'. */
3934
static int
3935
netdev_linux_arp_lookup(const struct netdev *netdev,
3936
                        ovs_be32 ip, struct eth_addr *mac)
3937
0
{
3938
0
    struct arpreq r;
3939
0
    struct sockaddr_in sin;
3940
0
    int retval;
3941
3942
0
    memset(&r, 0, sizeof r);
3943
0
    memset(&sin, 0, sizeof sin);
3944
0
    sin.sin_family = AF_INET;
3945
0
    sin.sin_addr.s_addr = ip;
3946
0
    sin.sin_port = 0;
3947
0
    memcpy(&r.arp_pa, &sin, sizeof sin);
3948
0
    r.arp_ha.sa_family = ARPHRD_ETHER;
3949
0
    r.arp_flags = 0;
3950
0
    ovs_strzcpy(r.arp_dev, netdev_get_name(netdev), sizeof r.arp_dev);
3951
0
    COVERAGE_INC(netdev_arp_lookup);
3952
0
    retval = af_inet_ioctl(SIOCGARP, &r);
3953
0
    if (!retval) {
3954
0
        memcpy(mac, r.arp_ha.sa_data, ETH_ADDR_LEN);
3955
0
    } else if (retval != ENXIO) {
3956
0
        VLOG_WARN_RL(&rl, "%s: could not look up ARP entry for "IP_FMT": %s",
3957
0
                     netdev_get_name(netdev), IP_ARGS(ip),
3958
0
                     ovs_strerror(retval));
3959
0
    }
3960
0
    return retval;
3961
0
}
3962
3963
static unsigned int
3964
nd_to_iff_flags(enum netdev_flags nd)
3965
0
{
3966
0
    unsigned int iff = 0;
3967
0
    if (nd & NETDEV_UP) {
3968
0
        iff |= IFF_UP;
3969
0
    }
3970
0
    if (nd & NETDEV_PROMISC) {
3971
0
        iff |= IFF_PROMISC;
3972
0
    }
3973
0
    if (nd & NETDEV_LOOPBACK) {
3974
0
        iff |= IFF_LOOPBACK;
3975
0
    }
3976
0
    return iff;
3977
0
}
3978
3979
static int
3980
iff_to_nd_flags(unsigned int iff)
3981
0
{
3982
0
    enum netdev_flags nd = 0;
3983
0
    if (iff & IFF_UP) {
3984
0
        nd |= NETDEV_UP;
3985
0
    }
3986
0
    if (iff & IFF_PROMISC) {
3987
0
        nd |= NETDEV_PROMISC;
3988
0
    }
3989
0
    if (iff & IFF_LOOPBACK) {
3990
0
        nd |= NETDEV_LOOPBACK;
3991
0
    }
3992
0
    return nd;
3993
0
}
3994
3995
static int
3996
update_flags(struct netdev_linux *netdev, enum netdev_flags off,
3997
             enum netdev_flags on, enum netdev_flags *old_flagsp)
3998
    OVS_REQUIRES(netdev->mutex)
3999
0
{
4000
0
    unsigned int old_flags, new_flags;
4001
0
    int error = 0;
4002
4003
0
    old_flags = netdev->ifi_flags;
4004
0
    *old_flagsp = iff_to_nd_flags(old_flags);
4005
0
    new_flags = (old_flags & ~nd_to_iff_flags(off)) | nd_to_iff_flags(on);
4006
0
    if (new_flags != old_flags) {
4007
0
        error = set_flags(netdev_get_name(&netdev->up), new_flags);
4008
0
        get_flags(&netdev->up, &netdev->ifi_flags);
4009
0
    }
4010
4011
0
    return error;
4012
0
}
4013
4014
static int
4015
netdev_linux_update_flags(struct netdev *netdev_, enum netdev_flags off,
4016
                          enum netdev_flags on, enum netdev_flags *old_flagsp)
4017
0
{
4018
0
    struct netdev_linux *netdev = netdev_linux_cast(netdev_);
4019
0
    int error = 0;
4020
4021
0
    ovs_mutex_lock(&netdev->mutex);
4022
0
    if (on || off) {
4023
        /* Changing flags over netlink isn't support yet. */
4024
0
        if (netdev_linux_netnsid_is_remote(netdev)) {
4025
0
            error = EOPNOTSUPP;
4026
0
            goto exit;
4027
0
        }
4028
0
        error = update_flags(netdev, off, on, old_flagsp);
4029
0
    } else {
4030
        /* Try reading flags over netlink, or fall back to ioctl. */
4031
0
        if (!netdev_linux_update_via_netlink(netdev)) {
4032
0
            *old_flagsp = iff_to_nd_flags(netdev->ifi_flags);
4033
0
        } else {
4034
0
            error = update_flags(netdev, off, on, old_flagsp);
4035
0
        }
4036
0
    }
4037
4038
0
exit:
4039
0
    ovs_mutex_unlock(&netdev->mutex);
4040
0
    return error;
4041
0
}
4042
4043
#define NETDEV_LINUX_CLASS_COMMON                               \
4044
    .run = netdev_linux_run,                                    \
4045
    .wait = netdev_linux_wait,                                  \
4046
    .alloc = netdev_linux_alloc,                                \
4047
    .dealloc = netdev_linux_dealloc,                            \
4048
    .send_wait = netdev_linux_send_wait,                        \
4049
    .set_etheraddr = netdev_linux_set_etheraddr,                \
4050
    .get_etheraddr = netdev_linux_get_etheraddr,                \
4051
    .get_mtu = netdev_linux_get_mtu,                            \
4052
    .set_mtu = netdev_linux_set_mtu,                            \
4053
    .get_ifindex = netdev_linux_get_ifindex,                    \
4054
    .get_carrier = netdev_linux_get_carrier,                    \
4055
    .get_carrier_resets = netdev_linux_get_carrier_resets,      \
4056
    .set_miimon_interval = netdev_linux_set_miimon_interval,    \
4057
    .set_advertisements = netdev_linux_set_advertisements,      \
4058
    .set_policing = netdev_linux_set_policing,                  \
4059
    .get_qos_types = netdev_linux_get_qos_types,                \
4060
    .get_qos_capabilities = netdev_linux_get_qos_capabilities,  \
4061
    .get_qos = netdev_linux_get_qos,                            \
4062
    .set_qos = netdev_linux_set_qos,                            \
4063
    .get_queue = netdev_linux_get_queue,                        \
4064
    .set_queue = netdev_linux_set_queue,                        \
4065
    .delete_queue = netdev_linux_delete_queue,                  \
4066
    .get_queue_stats = netdev_linux_get_queue_stats,            \
4067
    .queue_dump_start = netdev_linux_queue_dump_start,          \
4068
    .queue_dump_next = netdev_linux_queue_dump_next,            \
4069
    .queue_dump_done = netdev_linux_queue_dump_done,            \
4070
    .dump_queue_stats = netdev_linux_dump_queue_stats,          \
4071
    .set_in4 = netdev_linux_set_in4,                            \
4072
    .get_addr_list = netdev_linux_get_addr_list,                \
4073
    .add_router = netdev_linux_add_router,                      \
4074
    .get_next_hop = netdev_linux_get_next_hop,                  \
4075
    .arp_lookup = netdev_linux_arp_lookup,                      \
4076
    .update_flags = netdev_linux_update_flags,                  \
4077
    .rxq_alloc = netdev_linux_rxq_alloc,                        \
4078
    .rxq_dealloc = netdev_linux_rxq_dealloc,                    \
4079
    .rxq_wait = netdev_linux_rxq_wait,                          \
4080
    .rxq_drain = netdev_linux_rxq_drain
4081
4082
const struct netdev_class netdev_linux_class = {
4083
    NETDEV_LINUX_CLASS_COMMON,
4084
    .type = "system",
4085
    .is_pmd = false,
4086
    .construct = netdev_linux_construct,
4087
    .destruct = netdev_linux_destruct,
4088
    .get_stats = netdev_linux_get_stats,
4089
    .get_features = netdev_linux_get_features,
4090
    .get_speed = netdev_linux_get_speed,
4091
    .get_duplex = netdev_linux_get_duplex,
4092
    .get_status = netdev_linux_get_status,
4093
    .get_block_id = netdev_linux_get_block_id,
4094
    .send = netdev_linux_send,
4095
    .rxq_construct = netdev_linux_rxq_construct,
4096
    .rxq_destruct = netdev_linux_rxq_destruct,
4097
    .rxq_recv = netdev_linux_rxq_recv,
4098
};
4099
4100
const struct netdev_class netdev_tap_class = {
4101
    NETDEV_LINUX_CLASS_COMMON,
4102
    .type = "tap",
4103
    .is_pmd = false,
4104
    .construct = netdev_linux_construct_tap,
4105
    .destruct = netdev_linux_destruct,
4106
    .get_stats = netdev_tap_get_stats,
4107
    .get_features = netdev_linux_get_features,
4108
    .get_speed = netdev_linux_get_speed,
4109
    .get_duplex = netdev_linux_get_duplex,
4110
    .get_status = netdev_linux_get_status,
4111
    .send = netdev_linux_send,
4112
    .rxq_construct = netdev_linux_rxq_construct,
4113
    .rxq_destruct = netdev_linux_rxq_destruct,
4114
    .rxq_recv = netdev_linux_rxq_recv,
4115
};
4116
4117
const struct netdev_class netdev_internal_class = {
4118
    NETDEV_LINUX_CLASS_COMMON,
4119
    .type = "internal",
4120
    .is_pmd = false,
4121
    .construct = netdev_linux_construct,
4122
    .destruct = netdev_linux_destruct,
4123
    .get_stats = netdev_internal_get_stats,
4124
    .get_status = netdev_internal_get_status,
4125
    .send = netdev_linux_send,
4126
    .rxq_construct = netdev_linux_rxq_construct,
4127
    .rxq_destruct = netdev_linux_rxq_destruct,
4128
    .rxq_recv = netdev_linux_rxq_recv,
4129
};
4130
4131
#ifdef HAVE_AF_XDP
4132
#define NETDEV_AFXDP_CLASS_COMMON                               \
4133
    .construct = netdev_afxdp_construct,                        \
4134
    .destruct = netdev_afxdp_destruct,                          \
4135
    .get_stats = netdev_afxdp_get_stats,                        \
4136
    .get_custom_stats = netdev_afxdp_get_custom_stats,          \
4137
    .get_status = netdev_afxdp_get_status,                      \
4138
    .set_config = netdev_afxdp_set_config,                      \
4139
    .get_config = netdev_afxdp_get_config,                      \
4140
    .reconfigure = netdev_afxdp_reconfigure,                    \
4141
    .get_numa_id = netdev_linux_get_numa_id,                    \
4142
    .send = netdev_afxdp_batch_send,                            \
4143
    .rxq_construct = netdev_afxdp_rxq_construct,                \
4144
    .rxq_destruct = netdev_afxdp_rxq_destruct,                  \
4145
    .rxq_recv = netdev_afxdp_rxq_recv
4146
4147
const struct netdev_class netdev_afxdp_class = {
4148
    NETDEV_LINUX_CLASS_COMMON,
4149
    NETDEV_AFXDP_CLASS_COMMON,
4150
    .type = "afxdp",
4151
    .is_pmd = true,
4152
};
4153
4154
const struct netdev_class netdev_afxdp_nonpmd_class = {
4155
    NETDEV_LINUX_CLASS_COMMON,
4156
    NETDEV_AFXDP_CLASS_COMMON,
4157
    .type = "afxdp-nonpmd",
4158
    .is_pmd = false,
4159
};
4160
#endif
4161

4162
4163
#define CODEL_N_QUEUES 0x0000
4164
4165
/* In sufficiently new kernel headers these are defined as enums in
4166
 * <linux/pkt_sched.h>.  Define them here as macros to help out with older
4167
 * kernels.  (This overrides any enum definition in the header file but that's
4168
 * harmless.) */
4169
0
#define TCA_CODEL_TARGET   1
4170
0
#define TCA_CODEL_LIMIT    2
4171
0
#define TCA_CODEL_INTERVAL 3
4172
4173
struct codel {
4174
    struct tc tc;
4175
    uint32_t target;
4176
    uint32_t limit;
4177
    uint32_t interval;
4178
};
4179
4180
static struct codel *
4181
codel_get__(const struct netdev *netdev_)
4182
0
{
4183
0
    struct netdev_linux *netdev = netdev_linux_cast(netdev_);
4184
0
    return CONTAINER_OF(netdev->tc, struct codel, tc);
4185
0
}
4186
4187
static void
4188
codel_install__(struct netdev *netdev_, uint32_t target, uint32_t limit,
4189
                uint32_t interval)
4190
0
{
4191
0
    struct netdev_linux *netdev = netdev_linux_cast(netdev_);
4192
0
    struct codel *codel;
4193
4194
0
    codel = xmalloc(sizeof *codel);
4195
0
    tc_init(&codel->tc, &tc_ops_codel);
4196
0
    codel->target = target;
4197
0
    codel->limit = limit;
4198
0
    codel->interval = interval;
4199
4200
0
    netdev->tc = &codel->tc;
4201
0
}
4202
4203
static int
4204
codel_setup_qdisc__(struct netdev *netdev, uint32_t target, uint32_t limit,
4205
                    uint32_t interval)
4206
0
{
4207
0
    size_t opt_offset;
4208
0
    struct ofpbuf request;
4209
0
    struct tcmsg *tcmsg;
4210
0
    uint32_t otarget, olimit, ointerval;
4211
0
    int error;
4212
4213
0
    tc_del_qdisc(netdev);
4214
4215
0
    tcmsg = netdev_linux_tc_make_request(netdev, RTM_NEWQDISC,
4216
0
                                         NLM_F_EXCL | NLM_F_CREATE, &request);
4217
0
    if (!tcmsg) {
4218
0
        return ENODEV;
4219
0
    }
4220
0
    tcmsg->tcm_handle = tc_make_handle(1, 0);
4221
0
    tcmsg->tcm_parent = TC_H_ROOT;
4222
4223
0
    otarget = target ? target : 5000;
4224
0
    olimit = limit ? limit : 10240;
4225
0
    ointerval = interval ? interval : 100000;
4226
4227
0
    nl_msg_put_string(&request, TCA_KIND, "codel");
4228
0
    opt_offset = nl_msg_start_nested(&request, TCA_OPTIONS);
4229
0
    nl_msg_put_u32(&request, TCA_CODEL_TARGET, otarget);
4230
0
    nl_msg_put_u32(&request, TCA_CODEL_LIMIT, olimit);
4231
0
    nl_msg_put_u32(&request, TCA_CODEL_INTERVAL, ointerval);
4232
0
    nl_msg_end_nested(&request, opt_offset);
4233
4234
0
    error = tc_transact(&request, NULL);
4235
0
    if (error) {
4236
0
        VLOG_WARN_RL(&rl, "failed to replace %s qdisc, "
4237
0
        "target %u, limit %u, interval %u error %d(%s)",
4238
0
        netdev_get_name(netdev),
4239
0
        otarget, olimit, ointerval,
4240
0
        error, ovs_strerror(error));
4241
0
    }
4242
0
    return error;
4243
0
}
4244
4245
static void
4246
codel_parse_qdisc_details__(struct netdev *netdev OVS_UNUSED,
4247
                            const struct smap *details, struct codel *codel)
4248
0
{
4249
0
    codel->target = smap_get_ullong(details, "target", 0);
4250
0
    codel->limit = smap_get_ullong(details, "limit", 0);
4251
0
    codel->interval = smap_get_ullong(details, "interval", 0);
4252
4253
0
    if (!codel->target) {
4254
0
        codel->target = 5000;
4255
0
    }
4256
0
    if (!codel->limit) {
4257
0
        codel->limit = 10240;
4258
0
    }
4259
0
    if (!codel->interval) {
4260
0
        codel->interval = 100000;
4261
0
    }
4262
0
}
4263
4264
static int
4265
codel_tc_install(struct netdev *netdev, const struct smap *details)
4266
0
{
4267
0
    int error;
4268
0
    struct codel codel;
4269
4270
0
    codel_parse_qdisc_details__(netdev, details, &codel);
4271
0
    error = codel_setup_qdisc__(netdev, codel.target, codel.limit,
4272
0
                                codel.interval);
4273
0
    if (!error) {
4274
0
        codel_install__(netdev, codel.target, codel.limit, codel.interval);
4275
0
    }
4276
0
    return error;
4277
0
}
4278
4279
static int
4280
codel_parse_tca_options__(struct nlattr *nl_options, struct codel *codel)
4281
0
{
4282
0
    static const struct nl_policy tca_codel_policy[] = {
4283
0
        [TCA_CODEL_TARGET] = { .type = NL_A_U32 },
4284
0
        [TCA_CODEL_LIMIT] = { .type = NL_A_U32 },
4285
0
        [TCA_CODEL_INTERVAL] = { .type = NL_A_U32 }
4286
0
    };
4287
4288
0
    struct nlattr *attrs[ARRAY_SIZE(tca_codel_policy)];
4289
4290
0
    if (!nl_parse_nested(nl_options, tca_codel_policy,
4291
0
                         attrs, ARRAY_SIZE(tca_codel_policy))) {
4292
0
        VLOG_WARN_RL(&rl, "failed to parse CoDel class options");
4293
0
        return EPROTO;
4294
0
    }
4295
4296
0
    codel->target = nl_attr_get_u32(attrs[TCA_CODEL_TARGET]);
4297
0
    codel->limit = nl_attr_get_u32(attrs[TCA_CODEL_LIMIT]);
4298
0
    codel->interval = nl_attr_get_u32(attrs[TCA_CODEL_INTERVAL]);
4299
0
    return 0;
4300
0
}
4301
4302
static int
4303
codel_tc_load(struct netdev *netdev, struct ofpbuf *nlmsg)
4304
0
{
4305
0
    struct nlattr *nlattr;
4306
0
    const char * kind;
4307
0
    int error;
4308
0
    struct codel codel;
4309
4310
0
    error = tc_parse_qdisc(nlmsg, &kind, &nlattr);
4311
0
    if (error != 0) {
4312
0
        return error;
4313
0
    }
4314
4315
0
    error = codel_parse_tca_options__(nlattr, &codel);
4316
0
    if (error != 0) {
4317
0
        return error;
4318
0
    }
4319
4320
0
    codel_install__(netdev, codel.target, codel.limit, codel.interval);
4321
0
    return 0;
4322
0
}
4323
4324
4325
static void
4326
codel_tc_destroy(struct tc *tc)
4327
0
{
4328
0
    struct codel *codel = CONTAINER_OF(tc, struct codel, tc);
4329
0
    tc_destroy(tc);
4330
0
    free(codel);
4331
0
}
4332
4333
static int
4334
codel_qdisc_get(const struct netdev *netdev, struct smap *details)
4335
0
{
4336
0
    const struct codel *codel = codel_get__(netdev);
4337
0
    smap_add_format(details, "target", "%u", codel->target);
4338
0
    smap_add_format(details, "limit", "%u", codel->limit);
4339
0
    smap_add_format(details, "interval", "%u", codel->interval);
4340
0
    return 0;
4341
0
}
4342
4343
static int
4344
codel_qdisc_set(struct netdev *netdev, const struct smap *details)
4345
0
{
4346
0
    struct codel codel;
4347
4348
0
    codel_parse_qdisc_details__(netdev, details, &codel);
4349
0
    codel_install__(netdev, codel.target, codel.limit, codel.interval);
4350
0
    codel_get__(netdev)->target = codel.target;
4351
0
    codel_get__(netdev)->limit = codel.limit;
4352
0
    codel_get__(netdev)->interval = codel.interval;
4353
0
    return 0;
4354
0
}
4355
4356
static const struct tc_ops tc_ops_codel = {
4357
    .linux_name = "codel",
4358
    .ovs_name = "linux-codel",
4359
    .n_queues = CODEL_N_QUEUES,
4360
    .tc_install = codel_tc_install,
4361
    .tc_load = codel_tc_load,
4362
    .tc_destroy = codel_tc_destroy,
4363
    .qdisc_get = codel_qdisc_get,
4364
    .qdisc_set = codel_qdisc_set,
4365
};
4366

4367
/* FQ-CoDel traffic control class. */
4368
4369
#define FQCODEL_N_QUEUES 0x0000
4370
4371
/* In sufficiently new kernel headers these are defined as enums in
4372
 * <linux/pkt_sched.h>.  Define them here as macros to help out with older
4373
 * kernels.  (This overrides any enum definition in the header file but that's
4374
 * harmless.) */
4375
0
#define TCA_FQ_CODEL_TARGET     1
4376
0
#define TCA_FQ_CODEL_LIMIT      2
4377
0
#define TCA_FQ_CODEL_INTERVAL   3
4378
#define TCA_FQ_CODEL_ECN        4
4379
0
#define TCA_FQ_CODEL_FLOWS      5
4380
0
#define TCA_FQ_CODEL_QUANTUM    6
4381
4382
struct fqcodel {
4383
    struct tc tc;
4384
    uint32_t target;
4385
    uint32_t limit;
4386
    uint32_t interval;
4387
    uint32_t flows;
4388
    uint32_t quantum;
4389
};
4390
4391
static struct fqcodel *
4392
fqcodel_get__(const struct netdev *netdev_)
4393
0
{
4394
0
    struct netdev_linux *netdev = netdev_linux_cast(netdev_);
4395
0
    return CONTAINER_OF(netdev->tc, struct fqcodel, tc);
4396
0
}
4397
4398
static void
4399
fqcodel_install__(struct netdev *netdev_, uint32_t target, uint32_t limit,
4400
                  uint32_t interval, uint32_t flows, uint32_t quantum)
4401
0
{
4402
0
    struct netdev_linux *netdev = netdev_linux_cast(netdev_);
4403
0
    struct fqcodel *fqcodel;
4404
4405
0
    fqcodel = xmalloc(sizeof *fqcodel);
4406
0
    tc_init(&fqcodel->tc, &tc_ops_fqcodel);
4407
0
    fqcodel->target = target;
4408
0
    fqcodel->limit = limit;
4409
0
    fqcodel->interval = interval;
4410
0
    fqcodel->flows = flows;
4411
0
    fqcodel->quantum = quantum;
4412
4413
0
    netdev->tc = &fqcodel->tc;
4414
0
}
4415
4416
static int
4417
fqcodel_setup_qdisc__(struct netdev *netdev, uint32_t target, uint32_t limit,
4418
                      uint32_t interval, uint32_t flows, uint32_t quantum)
4419
0
{
4420
0
    size_t opt_offset;
4421
0
    struct ofpbuf request;
4422
0
    struct tcmsg *tcmsg;
4423
0
    uint32_t otarget, olimit, ointerval, oflows,  oquantum;
4424
0
    int error;
4425
4426
0
    tc_del_qdisc(netdev);
4427
4428
0
    tcmsg = netdev_linux_tc_make_request(netdev, RTM_NEWQDISC,
4429
0
                                         NLM_F_EXCL | NLM_F_CREATE, &request);
4430
0
    if (!tcmsg) {
4431
0
        return ENODEV;
4432
0
    }
4433
0
    tcmsg->tcm_handle = tc_make_handle(1, 0);
4434
0
    tcmsg->tcm_parent = TC_H_ROOT;
4435
4436
0
    otarget = target ? target : 5000;
4437
0
    olimit = limit ? limit : 10240;
4438
0
    ointerval = interval ? interval : 100000;
4439
0
    oflows = flows ? flows : 1024;
4440
0
    oquantum = quantum ? quantum : 1514; /* fq_codel default quantum is 1514
4441
                                            not mtu */
4442
4443
0
    nl_msg_put_string(&request, TCA_KIND, "fq_codel");
4444
0
    opt_offset = nl_msg_start_nested(&request, TCA_OPTIONS);
4445
0
    nl_msg_put_u32(&request, TCA_FQ_CODEL_TARGET, otarget);
4446
0
    nl_msg_put_u32(&request, TCA_FQ_CODEL_LIMIT, olimit);
4447
0
    nl_msg_put_u32(&request, TCA_FQ_CODEL_INTERVAL, ointerval);
4448
0
    nl_msg_put_u32(&request, TCA_FQ_CODEL_FLOWS, oflows);
4449
0
    nl_msg_put_u32(&request, TCA_FQ_CODEL_QUANTUM, oquantum);
4450
0
    nl_msg_end_nested(&request, opt_offset);
4451
4452
0
    error = tc_transact(&request, NULL);
4453
0
    if (error) {
4454
0
        VLOG_WARN_RL(&rl, "failed to replace %s qdisc, "
4455
0
        "target %u, limit %u, interval %u, flows %u, quantum %u error %d(%s)",
4456
0
        netdev_get_name(netdev),
4457
0
        otarget, olimit, ointerval, oflows, oquantum,
4458
0
        error, ovs_strerror(error));
4459
0
    }
4460
0
    return error;
4461
0
}
4462
4463
static void
4464
fqcodel_parse_qdisc_details__(struct netdev *netdev OVS_UNUSED,
4465
                          const struct smap *details, struct fqcodel *fqcodel)
4466
0
{
4467
0
    fqcodel->target = smap_get_ullong(details, "target", 0);
4468
0
    fqcodel->limit = smap_get_ullong(details, "limit", 0);
4469
0
    fqcodel->interval = smap_get_ullong(details, "interval", 0);
4470
0
    fqcodel->flows = smap_get_ullong(details, "flows", 0);
4471
0
    fqcodel->quantum = smap_get_ullong(details, "quantum", 0);
4472
4473
0
    if (!fqcodel->target) {
4474
0
        fqcodel->target = 5000;
4475
0
    }
4476
0
    if (!fqcodel->limit) {
4477
0
        fqcodel->limit = 10240;
4478
0
    }
4479
0
    if (!fqcodel->interval) {
4480
0
        fqcodel->interval = 1000000;
4481
0
    }
4482
0
    if (!fqcodel->flows) {
4483
0
        fqcodel->flows = 1024;
4484
0
    }
4485
0
    if (!fqcodel->quantum) {
4486
0
        fqcodel->quantum = 1514;
4487
0
    }
4488
0
}
4489
4490
static int
4491
fqcodel_tc_install(struct netdev *netdev, const struct smap *details)
4492
0
{
4493
0
    int error;
4494
0
    struct fqcodel fqcodel;
4495
4496
0
    fqcodel_parse_qdisc_details__(netdev, details, &fqcodel);
4497
0
    error = fqcodel_setup_qdisc__(netdev, fqcodel.target, fqcodel.limit,
4498
0
                                  fqcodel.interval, fqcodel.flows,
4499
0
                                  fqcodel.quantum);
4500
0
    if (!error) {
4501
0
        fqcodel_install__(netdev, fqcodel.target, fqcodel.limit,
4502
0
                          fqcodel.interval, fqcodel.flows, fqcodel.quantum);
4503
0
    }
4504
0
    return error;
4505
0
}
4506
4507
static int
4508
fqcodel_parse_tca_options__(struct nlattr *nl_options, struct fqcodel *fqcodel)
4509
0
{
4510
0
    static const struct nl_policy tca_fqcodel_policy[] = {
4511
0
        [TCA_FQ_CODEL_TARGET] = { .type = NL_A_U32 },
4512
0
        [TCA_FQ_CODEL_LIMIT] = { .type = NL_A_U32 },
4513
0
        [TCA_FQ_CODEL_INTERVAL] = { .type = NL_A_U32 },
4514
0
        [TCA_FQ_CODEL_FLOWS] = { .type = NL_A_U32 },
4515
0
        [TCA_FQ_CODEL_QUANTUM] = { .type = NL_A_U32 }
4516
0
    };
4517
4518
0
    struct nlattr *attrs[ARRAY_SIZE(tca_fqcodel_policy)];
4519
4520
0
    if (!nl_parse_nested(nl_options, tca_fqcodel_policy,
4521
0
                         attrs, ARRAY_SIZE(tca_fqcodel_policy))) {
4522
0
        VLOG_WARN_RL(&rl, "failed to parse FQ_CoDel class options");
4523
0
        return EPROTO;
4524
0
    }
4525
4526
0
    fqcodel->target = nl_attr_get_u32(attrs[TCA_FQ_CODEL_TARGET]);
4527
0
    fqcodel->limit = nl_attr_get_u32(attrs[TCA_FQ_CODEL_LIMIT]);
4528
0
    fqcodel->interval =nl_attr_get_u32(attrs[TCA_FQ_CODEL_INTERVAL]);
4529
0
    fqcodel->flows = nl_attr_get_u32(attrs[TCA_FQ_CODEL_FLOWS]);
4530
0
    fqcodel->quantum = nl_attr_get_u32(attrs[TCA_FQ_CODEL_QUANTUM]);
4531
0
    return 0;
4532
0
}
4533
4534
static int
4535
fqcodel_tc_load(struct netdev *netdev, struct ofpbuf *nlmsg)
4536
0
{
4537
0
    struct nlattr *nlattr;
4538
0
    const char * kind;
4539
0
    int error;
4540
0
    struct fqcodel fqcodel;
4541
4542
0
    error = tc_parse_qdisc(nlmsg, &kind, &nlattr);
4543
0
    if (error != 0) {
4544
0
        return error;
4545
0
    }
4546
4547
0
    error = fqcodel_parse_tca_options__(nlattr, &fqcodel);
4548
0
    if (error != 0) {
4549
0
        return error;
4550
0
    }
4551
4552
0
    fqcodel_install__(netdev, fqcodel.target, fqcodel.limit, fqcodel.interval,
4553
0
                      fqcodel.flows, fqcodel.quantum);
4554
0
    return 0;
4555
0
}
4556
4557
static void
4558
fqcodel_tc_destroy(struct tc *tc)
4559
0
{
4560
0
    struct fqcodel *fqcodel = CONTAINER_OF(tc, struct fqcodel, tc);
4561
0
    tc_destroy(tc);
4562
0
    free(fqcodel);
4563
0
}
4564
4565
static int
4566
fqcodel_qdisc_get(const struct netdev *netdev, struct smap *details)
4567
0
{
4568
0
    const struct fqcodel *fqcodel = fqcodel_get__(netdev);
4569
0
    smap_add_format(details, "target", "%u", fqcodel->target);
4570
0
    smap_add_format(details, "limit", "%u", fqcodel->limit);
4571
0
    smap_add_format(details, "interval", "%u", fqcodel->interval);
4572
0
    smap_add_format(details, "flows", "%u", fqcodel->flows);
4573
0
    smap_add_format(details, "quantum", "%u", fqcodel->quantum);
4574
0
    return 0;
4575
0
}
4576
4577
static int
4578
fqcodel_qdisc_set(struct netdev *netdev, const struct smap *details)
4579
0
{
4580
0
    struct fqcodel fqcodel;
4581
4582
0
    fqcodel_parse_qdisc_details__(netdev, details, &fqcodel);
4583
0
    fqcodel_install__(netdev, fqcodel.target, fqcodel.limit, fqcodel.interval,
4584
0
                      fqcodel.flows, fqcodel.quantum);
4585
0
    fqcodel_get__(netdev)->target = fqcodel.target;
4586
0
    fqcodel_get__(netdev)->limit = fqcodel.limit;
4587
0
    fqcodel_get__(netdev)->interval = fqcodel.interval;
4588
0
    fqcodel_get__(netdev)->flows = fqcodel.flows;
4589
0
    fqcodel_get__(netdev)->quantum = fqcodel.quantum;
4590
0
    return 0;
4591
0
}
4592
4593
static const struct tc_ops tc_ops_fqcodel = {
4594
    .linux_name = "fq_codel",
4595
    .ovs_name = "linux-fq_codel",
4596
    .n_queues = FQCODEL_N_QUEUES,
4597
    .tc_install = fqcodel_tc_install,
4598
    .tc_load = fqcodel_tc_load,
4599
    .tc_destroy = fqcodel_tc_destroy,
4600
    .qdisc_get = fqcodel_qdisc_get,
4601
    .qdisc_set = fqcodel_qdisc_set,
4602
};
4603

4604
/* SFQ traffic control class. */
4605
4606
#define SFQ_N_QUEUES 0x0000
4607
4608
struct sfq {
4609
    struct tc tc;
4610
    uint32_t quantum;
4611
    uint32_t perturb;
4612
};
4613
4614
static struct sfq *
4615
sfq_get__(const struct netdev *netdev_)
4616
0
{
4617
0
    struct netdev_linux *netdev = netdev_linux_cast(netdev_);
4618
0
    return CONTAINER_OF(netdev->tc, struct sfq, tc);
4619
0
}
4620
4621
static void
4622
sfq_install__(struct netdev *netdev_, uint32_t quantum, uint32_t perturb)
4623
0
{
4624
0
    struct netdev_linux *netdev = netdev_linux_cast(netdev_);
4625
0
    struct sfq *sfq;
4626
4627
0
    sfq = xmalloc(sizeof *sfq);
4628
0
    tc_init(&sfq->tc, &tc_ops_sfq);
4629
0
    sfq->perturb = perturb;
4630
0
    sfq->quantum = quantum;
4631
4632
0
    netdev->tc = &sfq->tc;
4633
0
}
4634
4635
static int
4636
sfq_setup_qdisc__(struct netdev *netdev, uint32_t quantum, uint32_t perturb)
4637
0
{
4638
0
    struct tc_sfq_qopt opt;
4639
0
    struct ofpbuf request;
4640
0
    struct tcmsg *tcmsg;
4641
0
    int mtu;
4642
0
    int mtu_error, error;
4643
0
    mtu_error = netdev_linux_get_mtu__(netdev_linux_cast(netdev), &mtu);
4644
4645
0
    tc_del_qdisc(netdev);
4646
4647
0
    tcmsg = netdev_linux_tc_make_request(netdev, RTM_NEWQDISC,
4648
0
                                         NLM_F_EXCL | NLM_F_CREATE, &request);
4649
0
    if (!tcmsg) {
4650
0
        return ENODEV;
4651
0
    }
4652
0
    tcmsg->tcm_handle = tc_make_handle(1, 0);
4653
0
    tcmsg->tcm_parent = TC_H_ROOT;
4654
4655
0
    memset(&opt, 0, sizeof opt);
4656
0
    if (!quantum) {
4657
0
        if (!mtu_error) {
4658
0
            opt.quantum = mtu; /* if we cannot find mtu, use default */
4659
0
        }
4660
0
    } else {
4661
0
        opt.quantum = quantum;
4662
0
    }
4663
4664
0
    if (!perturb) {
4665
0
        opt.perturb_period = 10;
4666
0
    } else {
4667
0
        opt.perturb_period = perturb;
4668
0
    }
4669
4670
0
    nl_msg_put_string(&request, TCA_KIND, "sfq");
4671
0
    nl_msg_put_unspec(&request, TCA_OPTIONS, &opt, sizeof opt);
4672
4673
0
    error = tc_transact(&request, NULL);
4674
0
    if (error) {
4675
0
        VLOG_WARN_RL(&rl, "failed to replace %s qdisc, "
4676
0
                     "quantum %u, perturb %u error %d(%s)",
4677
0
                     netdev_get_name(netdev),
4678
0
                     opt.quantum, opt.perturb_period,
4679
0
                     error, ovs_strerror(error));
4680
0
    }
4681
0
    return error;
4682
0
}
4683
4684
static void
4685
sfq_parse_qdisc_details__(struct netdev *netdev,
4686
                          const struct smap *details, struct sfq *sfq)
4687
0
{
4688
0
    sfq->perturb = smap_get_ullong(details, "perturb", 0);
4689
0
    sfq->quantum = smap_get_ullong(details, "quantum", 0);
4690
4691
0
    if (!sfq->perturb) {
4692
0
        sfq->perturb = 10;
4693
0
    }
4694
4695
0
    if (!sfq->quantum) {
4696
0
        int mtu;
4697
0
        if (!netdev_linux_get_mtu__(netdev_linux_cast(netdev), &mtu)) {
4698
0
            sfq->quantum = mtu;
4699
0
        } else {
4700
0
            VLOG_WARN_RL(&rl, "when using SFQ, you must specify quantum on a "
4701
0
                         "device without mtu");
4702
0
        }
4703
0
    }
4704
0
}
4705
4706
static int
4707
sfq_tc_install(struct netdev *netdev, const struct smap *details)
4708
0
{
4709
0
    int error;
4710
0
    struct sfq sfq;
4711
4712
0
    sfq_parse_qdisc_details__(netdev, details, &sfq);
4713
0
    error = sfq_setup_qdisc__(netdev, sfq.quantum, sfq.perturb);
4714
0
    if (!error) {
4715
0
        sfq_install__(netdev, sfq.quantum, sfq.perturb);
4716
0
    }
4717
0
    return error;
4718
0
}
4719
4720
static int
4721
sfq_tc_load(struct netdev *netdev, struct ofpbuf *nlmsg)
4722
0
{
4723
0
    const struct tc_sfq_qopt *sfq;
4724
0
    struct nlattr *nlattr;
4725
0
    const char * kind;
4726
0
    int error;
4727
4728
0
    error = tc_parse_qdisc(nlmsg, &kind, &nlattr);
4729
0
    if (error == 0) {
4730
0
        sfq = nl_attr_get(nlattr);
4731
0
        sfq_install__(netdev, sfq->quantum, sfq->perturb_period);
4732
0
        return 0;
4733
0
    }
4734
4735
0
    return error;
4736
0
}
4737
4738
static void
4739
sfq_tc_destroy(struct tc *tc)
4740
0
{
4741
0
    struct sfq *sfq = CONTAINER_OF(tc, struct sfq, tc);
4742
0
    tc_destroy(tc);
4743
0
    free(sfq);
4744
0
}
4745
4746
static int
4747
sfq_qdisc_get(const struct netdev *netdev, struct smap *details)
4748
0
{
4749
0
    const struct sfq *sfq = sfq_get__(netdev);
4750
0
    smap_add_format(details, "quantum", "%u", sfq->quantum);
4751
0
    smap_add_format(details, "perturb", "%u", sfq->perturb);
4752
0
    return 0;
4753
0
}
4754
4755
static int
4756
sfq_qdisc_set(struct netdev *netdev, const struct smap *details)
4757
0
{
4758
0
    struct sfq sfq;
4759
4760
0
    sfq_parse_qdisc_details__(netdev, details, &sfq);
4761
0
    sfq_install__(netdev, sfq.quantum, sfq.perturb);
4762
0
    sfq_get__(netdev)->quantum = sfq.quantum;
4763
0
    sfq_get__(netdev)->perturb = sfq.perturb;
4764
0
    return 0;
4765
0
}
4766
4767
static const struct tc_ops tc_ops_sfq = {
4768
    .linux_name = "sfq",
4769
    .ovs_name = "linux-sfq",
4770
    .n_queues = SFQ_N_QUEUES,
4771
    .tc_install = sfq_tc_install,
4772
    .tc_load = sfq_tc_load,
4773
    .tc_destroy = sfq_tc_destroy,
4774
    .qdisc_get = sfq_qdisc_get,
4775
    .qdisc_set = sfq_qdisc_set,
4776
};
4777

4778
/* netem traffic control class. */
4779
4780
struct netem {
4781
    struct tc tc;
4782
    uint32_t latency;
4783
    uint32_t limit;
4784
    uint32_t loss;
4785
    uint32_t jitter;
4786
};
4787
4788
static struct netem *
4789
netem_get__(const struct netdev *netdev_)
4790
0
{
4791
0
    struct netdev_linux *netdev = netdev_linux_cast(netdev_);
4792
0
    return CONTAINER_OF(netdev->tc, struct netem, tc);
4793
0
}
4794
4795
static void
4796
netem_install__(struct netdev *netdev_, uint32_t latency,
4797
                uint32_t limit, uint32_t loss, uint32_t jitter)
4798
0
{
4799
0
    struct netdev_linux *netdev = netdev_linux_cast(netdev_);
4800
0
    struct netem *netem;
4801
4802
0
    netem = xmalloc(sizeof *netem);
4803
0
    tc_init(&netem->tc, &tc_ops_netem);
4804
0
    netem->latency = latency;
4805
0
    netem->limit = limit;
4806
0
    netem->loss = loss;
4807
0
    netem->jitter = jitter;
4808
4809
0
    netdev->tc = &netem->tc;
4810
0
}
4811
4812
static int
4813
netem_setup_qdisc__(struct netdev *netdev, uint32_t latency,
4814
                    uint32_t limit, uint32_t loss, uint32_t jitter)
4815
0
{
4816
0
    struct tc_netem_qopt opt;
4817
0
    struct ofpbuf request;
4818
0
    struct tcmsg *tcmsg;
4819
0
    int error;
4820
4821
0
    tc_del_qdisc(netdev);
4822
4823
0
    tcmsg = netdev_linux_tc_make_request(netdev, RTM_NEWQDISC,
4824
0
                                         NLM_F_EXCL | NLM_F_CREATE, &request);
4825
0
    if (!tcmsg) {
4826
0
        return ENODEV;
4827
0
    }
4828
0
    tcmsg->tcm_handle = tc_make_handle(1, 0);
4829
0
    tcmsg->tcm_parent = TC_H_ROOT;
4830
4831
0
    memset(&opt, 0, sizeof opt);
4832
4833
0
    if (!limit) {
4834
0
        opt.limit = 1000;
4835
0
    } else {
4836
0
        opt.limit = limit;
4837
0
    }
4838
4839
0
    if (loss) {
4840
0
        if (loss > 100) {
4841
0
            VLOG_WARN_RL(&rl,
4842
0
                         "loss should be a percentage value between 0 to 100, "
4843
0
                         "loss was %u", loss);
4844
0
            return EINVAL;
4845
0
        }
4846
0
        opt.loss = floor(UINT32_MAX * (loss / 100.0));
4847
0
    }
4848
4849
0
    opt.latency = tc_time_to_ticks(latency);
4850
0
    opt.jitter = tc_time_to_ticks(jitter);
4851
4852
0
    nl_msg_put_string(&request, TCA_KIND, "netem");
4853
0
    nl_msg_put_unspec(&request, TCA_OPTIONS, &opt, sizeof opt);
4854
4855
0
    error = tc_transact(&request, NULL);
4856
0
    if (error) {
4857
0
        VLOG_WARN_RL(&rl, "failed to replace %s qdisc, "
4858
0
                          "latency %u, limit %u, loss %u, jitter %u "
4859
0
                          "error %d(%s)",
4860
0
                     netdev_get_name(netdev),
4861
0
                     opt.latency, opt.limit, opt.loss, opt.jitter,
4862
0
                     error, ovs_strerror(error));
4863
0
    }
4864
0
    return error;
4865
0
}
4866
4867
static void
4868
netem_parse_qdisc_details__(struct netdev *netdev OVS_UNUSED,
4869
                          const struct smap *details, struct netem *netem)
4870
0
{
4871
0
    netem->latency = smap_get_ullong(details, "latency", 0);
4872
0
    netem->limit = smap_get_ullong(details, "limit", 0);
4873
0
    netem->loss = smap_get_ullong(details, "loss", 0);
4874
0
    netem->jitter = smap_get_ullong(details, "jitter", 0);
4875
4876
0
    if (!netem->limit) {
4877
0
        netem->limit = 1000;
4878
0
    }
4879
0
}
4880
4881
static int
4882
netem_tc_install(struct netdev *netdev, const struct smap *details)
4883
0
{
4884
0
    int error;
4885
0
    struct netem netem;
4886
4887
0
    netem_parse_qdisc_details__(netdev, details, &netem);
4888
0
    error = netem_setup_qdisc__(netdev, netem.latency,
4889
0
                                netem.limit, netem.loss, netem.jitter);
4890
0
    if (!error) {
4891
0
        netem_install__(netdev, netem.latency,
4892
0
                        netem.limit, netem.loss, netem.jitter);
4893
0
    }
4894
0
    return error;
4895
0
}
4896
4897
static int
4898
netem_tc_load(struct netdev *netdev, struct ofpbuf *nlmsg)
4899
0
{
4900
0
    const struct tc_netem_qopt *netem;
4901
0
    struct nlattr *nlattr;
4902
0
    const char *kind;
4903
0
    int error;
4904
4905
0
    error = tc_parse_qdisc(nlmsg, &kind, &nlattr);
4906
0
    if (error == 0) {
4907
0
        netem = nl_attr_get(nlattr);
4908
0
        netem_install__(netdev, netem->latency,
4909
0
                        netem->limit, netem->loss, netem->jitter);
4910
0
        return 0;
4911
0
    }
4912
4913
0
    return error;
4914
0
}
4915
4916
static void
4917
netem_tc_destroy(struct tc *tc)
4918
0
{
4919
0
    struct netem *netem = CONTAINER_OF(tc, struct netem, tc);
4920
0
    tc_destroy(tc);
4921
0
    free(netem);
4922
0
}
4923
4924
static int
4925
netem_qdisc_get(const struct netdev *netdev, struct smap *details)
4926
0
{
4927
0
    const struct netem *netem = netem_get__(netdev);
4928
0
    smap_add_format(details, "latency", "%u", netem->latency);
4929
0
    smap_add_format(details, "limit", "%u", netem->limit);
4930
0
    smap_add_format(details, "loss", "%u", netem->loss);
4931
0
    smap_add_format(details, "jitter", "%u", netem->jitter);
4932
0
    return 0;
4933
0
}
4934
4935
static int
4936
netem_qdisc_set(struct netdev *netdev, const struct smap *details)
4937
0
{
4938
0
    struct netem netem;
4939
4940
0
    netem_parse_qdisc_details__(netdev, details, &netem);
4941
0
    netem_install__(netdev, netem.latency,
4942
0
                    netem.limit, netem.loss, netem.jitter);
4943
0
    netem_get__(netdev)->latency = netem.latency;
4944
0
    netem_get__(netdev)->limit = netem.limit;
4945
0
    netem_get__(netdev)->loss = netem.loss;
4946
0
    netem_get__(netdev)->jitter = netem.jitter;
4947
0
    return 0;
4948
0
}
4949
4950
static const struct tc_ops tc_ops_netem = {
4951
    .linux_name = "netem",
4952
    .ovs_name = "linux-netem",
4953
    .n_queues = 0,
4954
    .tc_install = netem_tc_install,
4955
    .tc_load = netem_tc_load,
4956
    .tc_destroy = netem_tc_destroy,
4957
    .qdisc_get = netem_qdisc_get,
4958
    .qdisc_set = netem_qdisc_set,
4959
};
4960

4961
/* HTB traffic control class. */
4962
4963
0
#define HTB_N_QUEUES 0xf000
4964
0
#define HTB_RATE2QUANTUM 10
4965
4966
struct htb {
4967
    struct tc tc;
4968
    uint64_t max_rate;          /* In bytes/s. */
4969
};
4970
4971
struct htb_class {
4972
    struct tc_queue tc_queue;
4973
    uint64_t min_rate;          /* In bytes/s. */
4974
    uint64_t max_rate;          /* In bytes/s. */
4975
    unsigned int burst;         /* In bytes. */
4976
    unsigned int priority;      /* Lower values are higher priorities. */
4977
};
4978
4979
static struct htb *
4980
htb_get__(const struct netdev *netdev_)
4981
0
{
4982
0
    struct netdev_linux *netdev = netdev_linux_cast(netdev_);
4983
0
    return CONTAINER_OF(netdev->tc, struct htb, tc);
4984
0
}
4985
4986
static void
4987
htb_install__(struct netdev *netdev_, uint64_t max_rate)
4988
0
{
4989
0
    struct netdev_linux *netdev = netdev_linux_cast(netdev_);
4990
0
    struct htb *htb;
4991
4992
0
    htb = xmalloc(sizeof *htb);
4993
0
    tc_init(&htb->tc, &tc_ops_htb);
4994
0
    htb->max_rate = max_rate;
4995
4996
0
    netdev->tc = &htb->tc;
4997
0
}
4998
4999
/* Create an HTB qdisc.
5000
 *
5001
 * Equivalent to "tc qdisc add dev <dev> root handle 1: htb default 1". */
5002
static int
5003
htb_setup_qdisc__(struct netdev *netdev)
5004
0
{
5005
0
    size_t opt_offset;
5006
0
    struct tc_htb_glob opt;
5007
0
    struct ofpbuf request;
5008
0
    struct tcmsg *tcmsg;
5009
5010
0
    tc_del_qdisc(netdev);
5011
5012
0
    tcmsg = netdev_linux_tc_make_request(netdev, RTM_NEWQDISC,
5013
0
                                         NLM_F_EXCL | NLM_F_CREATE, &request);
5014
0
    if (!tcmsg) {
5015
0
        return ENODEV;
5016
0
    }
5017
0
    tcmsg->tcm_handle = tc_make_handle(1, 0);
5018
0
    tcmsg->tcm_parent = TC_H_ROOT;
5019
5020
0
    nl_msg_put_string(&request, TCA_KIND, "htb");
5021
5022
0
    memset(&opt, 0, sizeof opt);
5023
0
    opt.rate2quantum = HTB_RATE2QUANTUM;
5024
0
    opt.version = 3;
5025
0
    opt.defcls = 1;
5026
5027
0
    opt_offset = nl_msg_start_nested(&request, TCA_OPTIONS);
5028
0
    nl_msg_put_unspec(&request, TCA_HTB_INIT, &opt, sizeof opt);
5029
0
    nl_msg_end_nested(&request, opt_offset);
5030
5031
0
    return tc_transact(&request, NULL);
5032
0
}
5033
5034
/* Equivalent to "tc class replace <dev> classid <handle> parent <parent> htb
5035
 * rate <min_rate>bps ceil <max_rate>bps burst <burst>b prio <priority>". */
5036
static int
5037
htb_setup_class__(struct netdev *netdev, unsigned int handle,
5038
                  unsigned int parent, struct htb_class *class)
5039
0
{
5040
0
    size_t opt_offset;
5041
0
    struct tc_htb_opt opt;
5042
0
    struct ofpbuf request;
5043
0
    struct tcmsg *tcmsg;
5044
0
    int error;
5045
0
    int mtu;
5046
5047
0
    error = netdev_linux_get_mtu__(netdev_linux_cast(netdev), &mtu);
5048
0
    if (error) {
5049
0
        VLOG_WARN_RL(&rl, "cannot set up HTB on device %s that lacks MTU",
5050
0
                     netdev_get_name(netdev));
5051
0
        return error;
5052
0
    }
5053
5054
0
    memset(&opt, 0, sizeof opt);
5055
0
    tc_fill_rate(&opt.rate, class->min_rate, mtu);
5056
0
    tc_fill_rate(&opt.ceil, class->max_rate, mtu);
5057
    /* Makes sure the quantum is at least MTU.  Setting quantum will
5058
     * make htb ignore the r2q for this class. */
5059
0
    if ((class->min_rate / HTB_RATE2QUANTUM) < mtu) {
5060
0
        opt.quantum = mtu;
5061
0
    }
5062
0
    opt.buffer = tc_calc_buffer(class->min_rate, mtu, class->burst);
5063
0
    opt.cbuffer = tc_calc_buffer(class->max_rate, mtu, class->burst);
5064
0
    opt.prio = class->priority;
5065
5066
0
    tcmsg = netdev_linux_tc_make_request(netdev, RTM_NEWTCLASS, NLM_F_CREATE,
5067
0
                                         &request);
5068
0
    if (!tcmsg) {
5069
0
        return ENODEV;
5070
0
    }
5071
0
    tcmsg->tcm_handle = handle;
5072
0
    tcmsg->tcm_parent = parent;
5073
5074
0
    nl_msg_put_string(&request, TCA_KIND, "htb");
5075
0
    opt_offset = nl_msg_start_nested(&request, TCA_OPTIONS);
5076
5077
0
#ifdef HAVE_TCA_HTB_RATE64
5078
0
    if (class->min_rate > UINT32_MAX) {
5079
0
        nl_msg_put_u64(&request, TCA_HTB_RATE64, class->min_rate);
5080
0
    }
5081
0
    if (class->max_rate > UINT32_MAX) {
5082
0
        nl_msg_put_u64(&request, TCA_HTB_CEIL64, class->max_rate);
5083
0
    }
5084
0
#endif
5085
0
    nl_msg_put_unspec(&request, TCA_HTB_PARMS, &opt, sizeof opt);
5086
5087
0
    tc_put_rtab(&request, TCA_HTB_RTAB, &opt.rate, class->min_rate);
5088
0
    tc_put_rtab(&request, TCA_HTB_CTAB, &opt.ceil, class->max_rate);
5089
0
    nl_msg_end_nested(&request, opt_offset);
5090
5091
0
    error = tc_transact(&request, NULL);
5092
0
    if (error) {
5093
0
        VLOG_WARN_RL(&rl, "failed to replace %s class %u:%u, parent %u:%u, "
5094
0
                     "min_rate=%"PRIu64" max_rate=%"PRIu64" burst=%u prio=%u "
5095
0
                     "(%s)",
5096
0
                     netdev_get_name(netdev),
5097
0
                     tc_get_major(handle), tc_get_minor(handle),
5098
0
                     tc_get_major(parent), tc_get_minor(parent),
5099
0
                     class->min_rate, class->max_rate,
5100
0
                     class->burst, class->priority, ovs_strerror(error));
5101
0
    }
5102
0
    return error;
5103
0
}
5104
5105
/* Parses Netlink attributes in 'options' for HTB parameters and stores a
5106
 * description of them into 'details'.  The description complies with the
5107
 * specification given in the vswitch database documentation for linux-htb
5108
 * queue details. */
5109
static int
5110
htb_parse_tca_options__(struct nlattr *nl_options, struct htb_class *class)
5111
0
{
5112
0
    static const struct nl_policy tca_htb_policy[] = {
5113
0
        [TCA_HTB_PARMS] = { .type = NL_A_UNSPEC, .optional = false,
5114
0
                            .min_len = sizeof(struct tc_htb_opt) },
5115
0
#ifdef HAVE_TCA_HTB_RATE64
5116
0
        [TCA_HTB_RATE64] = { .type = NL_A_U64, .optional = true },
5117
0
        [TCA_HTB_CEIL64] = { .type = NL_A_U64, .optional = true },
5118
0
#endif
5119
0
    };
5120
5121
0
    struct nlattr *attrs[ARRAY_SIZE(tca_htb_policy)];
5122
0
    const struct tc_htb_opt *htb;
5123
5124
0
    if (!nl_parse_nested(nl_options, tca_htb_policy,
5125
0
                         attrs, ARRAY_SIZE(tca_htb_policy))) {
5126
0
        VLOG_WARN_RL(&rl, "failed to parse HTB class options");
5127
0
        return EPROTO;
5128
0
    }
5129
5130
0
    htb = nl_attr_get(attrs[TCA_HTB_PARMS]);
5131
0
    class->min_rate = htb->rate.rate;
5132
0
    class->max_rate = htb->ceil.rate;
5133
0
#ifdef HAVE_TCA_HTB_RATE64
5134
0
    if (attrs[TCA_HTB_RATE64]) {
5135
0
        class->min_rate = nl_attr_get_u64(attrs[TCA_HTB_RATE64]);
5136
0
    }
5137
0
    if (attrs[TCA_HTB_CEIL64]) {
5138
0
        class->max_rate = nl_attr_get_u64(attrs[TCA_HTB_CEIL64]);
5139
0
    }
5140
0
#endif
5141
0
    class->burst = tc_ticks_to_bytes(class->min_rate, htb->buffer);
5142
0
    class->priority = htb->prio;
5143
0
    return 0;
5144
0
}
5145
5146
static int
5147
htb_parse_tcmsg__(struct ofpbuf *tcmsg, unsigned int *queue_id,
5148
                  struct htb_class *options,
5149
                  struct netdev_queue_stats *stats)
5150
0
{
5151
0
    struct nlattr *nl_options;
5152
0
    unsigned int handle;
5153
0
    int error;
5154
5155
0
    error = tc_parse_class(tcmsg, &handle, &nl_options, stats);
5156
0
    if (!error && queue_id) {
5157
0
        unsigned int major = tc_get_major(handle);
5158
0
        unsigned int minor = tc_get_minor(handle);
5159
0
        if (major == 1 && minor > 0 && minor <= HTB_N_QUEUES) {
5160
0
            *queue_id = minor - 1;
5161
0
        } else {
5162
0
            error = EPROTO;
5163
0
        }
5164
0
    }
5165
0
    if (!error && options) {
5166
0
        error = htb_parse_tca_options__(nl_options, options);
5167
0
    }
5168
0
    return error;
5169
0
}
5170
5171
static void
5172
htb_parse_qdisc_details__(struct netdev *netdev, const struct smap *details,
5173
                          struct htb_class *hc)
5174
0
{
5175
0
    hc->max_rate = smap_get_ullong(details, "max-rate", 0) / 8;
5176
0
    if (!hc->max_rate) {
5177
0
        uint32_t current_speed;
5178
0
        uint32_t max_speed OVS_UNUSED;
5179
5180
0
        netdev_linux_get_speed_locked(netdev_linux_cast(netdev),
5181
0
                                      &current_speed, &max_speed);
5182
0
        hc->max_rate = current_speed ? current_speed / 8 * 1000000ULL
5183
0
                                     : NETDEV_DEFAULT_BPS / 8;
5184
0
    }
5185
0
    hc->min_rate = hc->max_rate;
5186
0
    hc->burst = 0;
5187
0
    hc->priority = 0;
5188
0
}
5189
5190
static int
5191
htb_parse_class_details__(struct netdev *netdev,
5192
                          const struct smap *details, struct htb_class *hc)
5193
0
{
5194
0
    const struct htb *htb = htb_get__(netdev);
5195
0
    int mtu, error;
5196
0
    unsigned long long int max_rate_bit;
5197
5198
0
    error = netdev_linux_get_mtu__(netdev_linux_cast(netdev), &mtu);
5199
0
    if (error) {
5200
0
        VLOG_WARN_RL(&rl, "cannot parse HTB class on device %s that lacks MTU",
5201
0
                     netdev_get_name(netdev));
5202
0
        return error;
5203
0
    }
5204
5205
    /* HTB requires at least an mtu sized min-rate to send any traffic even
5206
     * on uncongested links. */
5207
0
    hc->min_rate = smap_get_ullong(details, "min-rate", 0) / 8;
5208
0
    hc->min_rate = MAX(hc->min_rate, mtu);
5209
0
    hc->min_rate = MIN(hc->min_rate, htb->max_rate);
5210
5211
    /* max-rate */
5212
0
    max_rate_bit = smap_get_ullong(details, "max-rate", 0);
5213
0
    hc->max_rate = max_rate_bit ? max_rate_bit / 8 : htb->max_rate;
5214
0
    hc->max_rate = MAX(hc->max_rate, hc->min_rate);
5215
0
    hc->max_rate = MIN(hc->max_rate, htb->max_rate);
5216
5217
    /* burst
5218
     *
5219
     * According to hints in the documentation that I've read, it is important
5220
     * that 'burst' be at least as big as the largest frame that might be
5221
     * transmitted.  Also, making 'burst' a bit bigger than necessary is OK,
5222
     * but having it a bit too small is a problem.  Since netdev_get_mtu()
5223
     * doesn't include the Ethernet header, we need to add at least 14 (18?) to
5224
     * the MTU.  We actually add 64, instead of 14, as a guard against
5225
     * additional headers get tacked on somewhere that we're not aware of. */
5226
0
    hc->burst = smap_get_ullong(details, "burst", 0) / 8;
5227
0
    hc->burst = MAX(hc->burst, mtu + 64);
5228
5229
    /* priority */
5230
0
    hc->priority = smap_get_ullong(details, "priority", 0);
5231
5232
0
    return 0;
5233
0
}
5234
5235
static int
5236
htb_query_class__(const struct netdev *netdev, unsigned int handle,
5237
                  unsigned int parent, struct htb_class *options,
5238
                  struct netdev_queue_stats *stats)
5239
0
{
5240
0
    struct ofpbuf *reply;
5241
0
    int error;
5242
5243
0
    error = tc_query_class(netdev, handle, parent, &reply);
5244
0
    if (!error) {
5245
0
        error = htb_parse_tcmsg__(reply, NULL, options, stats);
5246
0
        ofpbuf_delete(reply);
5247
0
    }
5248
0
    return error;
5249
0
}
5250
5251
static int
5252
htb_tc_install(struct netdev *netdev, const struct smap *details)
5253
0
{
5254
0
    int error;
5255
5256
0
    error = htb_setup_qdisc__(netdev);
5257
0
    if (!error) {
5258
0
        struct htb_class hc;
5259
5260
0
        htb_parse_qdisc_details__(netdev, details, &hc);
5261
0
        error = htb_setup_class__(netdev, tc_make_handle(1, 0xfffe),
5262
0
                                  tc_make_handle(1, 0), &hc);
5263
0
        if (!error) {
5264
0
            htb_install__(netdev, hc.max_rate);
5265
0
        }
5266
0
    }
5267
0
    return error;
5268
0
}
5269
5270
static struct htb_class *
5271
htb_class_cast__(const struct tc_queue *queue)
5272
0
{
5273
0
    return CONTAINER_OF(queue, struct htb_class, tc_queue);
5274
0
}
5275
5276
static void
5277
htb_update_queue__(struct netdev *netdev, unsigned int queue_id,
5278
                   const struct htb_class *hc)
5279
0
{
5280
0
    struct htb *htb = htb_get__(netdev);
5281
0
    size_t hash = hash_int(queue_id, 0);
5282
0
    struct tc_queue *queue;
5283
0
    struct htb_class *hcp;
5284
5285
0
    queue = tc_find_queue__(netdev, queue_id, hash);
5286
0
    if (queue) {
5287
0
        hcp = htb_class_cast__(queue);
5288
0
    } else {
5289
0
        hcp = xmalloc(sizeof *hcp);
5290
0
        queue = &hcp->tc_queue;
5291
0
        queue->queue_id = queue_id;
5292
0
        queue->created = time_msec();
5293
0
        hmap_insert(&htb->tc.queues, &queue->hmap_node, hash);
5294
0
    }
5295
5296
0
    hcp->min_rate = hc->min_rate;
5297
0
    hcp->max_rate = hc->max_rate;
5298
0
    hcp->burst = hc->burst;
5299
0
    hcp->priority = hc->priority;
5300
0
}
5301
5302
static int
5303
htb_tc_load(struct netdev *netdev, struct ofpbuf *nlmsg OVS_UNUSED)
5304
0
{
5305
0
    struct ofpbuf msg;
5306
0
    struct queue_dump_state state;
5307
0
    struct htb_class hc;
5308
5309
    /* Get qdisc options. */
5310
0
    hc.max_rate = 0;
5311
0
    htb_query_class__(netdev, tc_make_handle(1, 0xfffe), 0, &hc, NULL);
5312
0
    htb_install__(netdev, hc.max_rate);
5313
5314
    /* Get queues. */
5315
0
    if (!start_queue_dump(netdev, &state)) {
5316
0
        return ENODEV;
5317
0
    }
5318
0
    while (nl_dump_next(&state.dump, &msg, &state.buf)) {
5319
0
        unsigned int queue_id;
5320
5321
0
        if (!htb_parse_tcmsg__(&msg, &queue_id, &hc, NULL)) {
5322
0
            htb_update_queue__(netdev, queue_id, &hc);
5323
0
        }
5324
0
    }
5325
0
    finish_queue_dump(&state);
5326
5327
0
    return 0;
5328
0
}
5329
5330
static void
5331
htb_tc_destroy(struct tc *tc)
5332
0
{
5333
0
    struct htb *htb = CONTAINER_OF(tc, struct htb, tc);
5334
0
    struct htb_class *hc;
5335
5336
0
    HMAP_FOR_EACH_POP (hc, tc_queue.hmap_node, &htb->tc.queues) {
5337
0
        free(hc);
5338
0
    }
5339
0
    tc_destroy(tc);
5340
0
    free(htb);
5341
0
}
5342
5343
static int
5344
htb_qdisc_get(const struct netdev *netdev, struct smap *details)
5345
0
{
5346
0
    const struct htb *htb = htb_get__(netdev);
5347
0
    smap_add_format(details, "max-rate", "%llu", 8ULL * htb->max_rate);
5348
0
    return 0;
5349
0
}
5350
5351
static int
5352
htb_qdisc_set(struct netdev *netdev, const struct smap *details)
5353
0
{
5354
0
    struct htb_class hc;
5355
0
    int error;
5356
5357
0
    htb_parse_qdisc_details__(netdev, details, &hc);
5358
0
    error = htb_setup_class__(netdev, tc_make_handle(1, 0xfffe),
5359
0
                              tc_make_handle(1, 0), &hc);
5360
0
    if (!error) {
5361
0
        htb_get__(netdev)->max_rate = hc.max_rate;
5362
0
    }
5363
0
    return error;
5364
0
}
5365
5366
static int
5367
htb_class_get(const struct netdev *netdev OVS_UNUSED,
5368
              const struct tc_queue *queue, struct smap *details)
5369
0
{
5370
0
    const struct htb_class *hc = htb_class_cast__(queue);
5371
5372
0
    smap_add_format(details, "min-rate", "%llu", 8ULL * hc->min_rate);
5373
0
    if (hc->min_rate != hc->max_rate) {
5374
0
        smap_add_format(details, "max-rate", "%llu", 8ULL * hc->max_rate);
5375
0
    }
5376
0
    smap_add_format(details, "burst", "%llu", 8ULL * hc->burst);
5377
0
    if (hc->priority) {
5378
0
        smap_add_format(details, "priority", "%u", hc->priority);
5379
0
    }
5380
0
    return 0;
5381
0
}
5382
5383
static int
5384
htb_class_set(struct netdev *netdev, unsigned int queue_id,
5385
              const struct smap *details)
5386
0
{
5387
0
    struct htb_class hc;
5388
0
    int error;
5389
5390
0
    error = htb_parse_class_details__(netdev, details, &hc);
5391
0
    if (error) {
5392
0
        return error;
5393
0
    }
5394
5395
0
    error = htb_setup_class__(netdev, tc_make_handle(1, queue_id + 1),
5396
0
                              tc_make_handle(1, 0xfffe), &hc);
5397
0
    if (error) {
5398
0
        return error;
5399
0
    }
5400
5401
0
    htb_update_queue__(netdev, queue_id, &hc);
5402
0
    return 0;
5403
0
}
5404
5405
static int
5406
htb_class_delete(struct netdev *netdev, struct tc_queue *queue)
5407
0
{
5408
0
    struct htb_class *hc = htb_class_cast__(queue);
5409
0
    struct htb *htb = htb_get__(netdev);
5410
0
    int error;
5411
5412
0
    error = tc_delete_class(netdev, tc_make_handle(1, queue->queue_id + 1));
5413
0
    if (!error) {
5414
0
        hmap_remove(&htb->tc.queues, &hc->tc_queue.hmap_node);
5415
0
        free(hc);
5416
0
    }
5417
0
    return error;
5418
0
}
5419
5420
static int
5421
htb_class_get_stats(const struct netdev *netdev, const struct tc_queue *queue,
5422
                    struct netdev_queue_stats *stats)
5423
0
{
5424
0
    return htb_query_class__(netdev, tc_make_handle(1, queue->queue_id + 1),
5425
0
                             tc_make_handle(1, 0xfffe), NULL, stats);
5426
0
}
5427
5428
static int
5429
htb_class_dump_stats(const struct netdev *netdev OVS_UNUSED,
5430
                     const struct ofpbuf *nlmsg,
5431
                     netdev_dump_queue_stats_cb *cb, void *aux)
5432
0
{
5433
0
    struct netdev_queue_stats stats;
5434
0
    unsigned int handle, major, minor;
5435
0
    int error;
5436
5437
0
    error = tc_parse_class(nlmsg, &handle, NULL, &stats);
5438
0
    if (error) {
5439
0
        return error;
5440
0
    }
5441
5442
0
    major = tc_get_major(handle);
5443
0
    minor = tc_get_minor(handle);
5444
0
    if (major == 1 && minor > 0 && minor <= HTB_N_QUEUES) {
5445
0
        (*cb)(minor - 1, &stats, aux);
5446
0
    }
5447
0
    return 0;
5448
0
}
5449
5450
static const struct tc_ops tc_ops_htb = {
5451
    .linux_name = "htb",
5452
    .ovs_name = "linux-htb",
5453
    .n_queues = HTB_N_QUEUES,
5454
    .tc_install = htb_tc_install,
5455
    .tc_load = htb_tc_load,
5456
    .tc_destroy = htb_tc_destroy,
5457
    .qdisc_get = htb_qdisc_get,
5458
    .qdisc_set = htb_qdisc_set,
5459
    .class_get = htb_class_get,
5460
    .class_set = htb_class_set,
5461
    .class_delete = htb_class_delete,
5462
    .class_get_stats = htb_class_get_stats,
5463
    .class_dump_stats = htb_class_dump_stats
5464
};
5465

5466
/* "linux-hfsc" traffic control class. */
5467
5468
0
#define HFSC_N_QUEUES 0xf000
5469
5470
struct hfsc {
5471
    struct tc tc;
5472
    uint32_t max_rate;
5473
};
5474
5475
struct hfsc_class {
5476
    struct tc_queue tc_queue;
5477
    uint32_t min_rate;
5478
    uint32_t max_rate;
5479
};
5480
5481
static struct hfsc *
5482
hfsc_get__(const struct netdev *netdev_)
5483
0
{
5484
0
    struct netdev_linux *netdev = netdev_linux_cast(netdev_);
5485
0
    return CONTAINER_OF(netdev->tc, struct hfsc, tc);
5486
0
}
5487
5488
static struct hfsc_class *
5489
hfsc_class_cast__(const struct tc_queue *queue)
5490
0
{
5491
0
    return CONTAINER_OF(queue, struct hfsc_class, tc_queue);
5492
0
}
5493
5494
static void
5495
hfsc_install__(struct netdev *netdev_, uint32_t max_rate)
5496
0
{
5497
0
    struct netdev_linux *netdev = netdev_linux_cast(netdev_);
5498
0
    struct hfsc *hfsc;
5499
5500
0
    hfsc = xmalloc(sizeof *hfsc);
5501
0
    tc_init(&hfsc->tc, &tc_ops_hfsc);
5502
0
    hfsc->max_rate = max_rate;
5503
0
    netdev->tc = &hfsc->tc;
5504
0
}
5505
5506
static void
5507
hfsc_update_queue__(struct netdev *netdev, unsigned int queue_id,
5508
                    const struct hfsc_class *hc)
5509
0
{
5510
0
    size_t hash;
5511
0
    struct hfsc *hfsc;
5512
0
    struct hfsc_class *hcp;
5513
0
    struct tc_queue *queue;
5514
5515
0
    hfsc = hfsc_get__(netdev);
5516
0
    hash = hash_int(queue_id, 0);
5517
5518
0
    queue = tc_find_queue__(netdev, queue_id, hash);
5519
0
    if (queue) {
5520
0
        hcp = hfsc_class_cast__(queue);
5521
0
    } else {
5522
0
        hcp             = xmalloc(sizeof *hcp);
5523
0
        queue           = &hcp->tc_queue;
5524
0
        queue->queue_id = queue_id;
5525
0
        queue->created  = time_msec();
5526
0
        hmap_insert(&hfsc->tc.queues, &queue->hmap_node, hash);
5527
0
    }
5528
5529
0
    hcp->min_rate = hc->min_rate;
5530
0
    hcp->max_rate = hc->max_rate;
5531
0
}
5532
5533
static int
5534
hfsc_parse_tca_options__(struct nlattr *nl_options, struct hfsc_class *class)
5535
0
{
5536
0
    const struct tc_service_curve *rsc, *fsc, *usc;
5537
0
    static const struct nl_policy tca_hfsc_policy[] = {
5538
0
        [TCA_HFSC_RSC] = {
5539
0
            .type      = NL_A_UNSPEC,
5540
0
            .optional  = false,
5541
0
            .min_len   = sizeof(struct tc_service_curve),
5542
0
        },
5543
0
        [TCA_HFSC_FSC] = {
5544
0
            .type      = NL_A_UNSPEC,
5545
0
            .optional  = false,
5546
0
            .min_len   = sizeof(struct tc_service_curve),
5547
0
        },
5548
0
        [TCA_HFSC_USC] = {
5549
0
            .type      = NL_A_UNSPEC,
5550
0
            .optional  = false,
5551
0
            .min_len   = sizeof(struct tc_service_curve),
5552
0
        },
5553
0
    };
5554
0
    struct nlattr *attrs[ARRAY_SIZE(tca_hfsc_policy)];
5555
5556
0
    if (!nl_parse_nested(nl_options, tca_hfsc_policy,
5557
0
                         attrs, ARRAY_SIZE(tca_hfsc_policy))) {
5558
0
        VLOG_WARN_RL(&rl, "failed to parse HFSC class options");
5559
0
        return EPROTO;
5560
0
    }
5561
5562
0
    rsc = nl_attr_get(attrs[TCA_HFSC_RSC]);
5563
0
    fsc = nl_attr_get(attrs[TCA_HFSC_FSC]);
5564
0
    usc = nl_attr_get(attrs[TCA_HFSC_USC]);
5565
5566
0
    if (rsc->m1 != 0 || rsc->d != 0 ||
5567
0
        fsc->m1 != 0 || fsc->d != 0 ||
5568
0
        usc->m1 != 0 || usc->d != 0) {
5569
0
        VLOG_WARN_RL(&rl, "failed to parse HFSC class options. "
5570
0
                     "Non-linear service curves are not supported.");
5571
0
        return EPROTO;
5572
0
    }
5573
5574
0
    if (rsc->m2 != fsc->m2) {
5575
0
        VLOG_WARN_RL(&rl, "failed to parse HFSC class options. "
5576
0
                     "Real-time service curves are not supported ");
5577
0
        return EPROTO;
5578
0
    }
5579
5580
0
    if (rsc->m2 > usc->m2) {
5581
0
        VLOG_WARN_RL(&rl, "failed to parse HFSC class options. "
5582
0
                     "Min-rate service curve is greater than "
5583
0
                     "the max-rate service curve.");
5584
0
        return EPROTO;
5585
0
    }
5586
5587
0
    class->min_rate = fsc->m2;
5588
0
    class->max_rate = usc->m2;
5589
0
    return 0;
5590
0
}
5591
5592
static int
5593
hfsc_parse_tcmsg__(struct ofpbuf *tcmsg, unsigned int *queue_id,
5594
                   struct hfsc_class *options,
5595
                   struct netdev_queue_stats *stats)
5596
0
{
5597
0
    int error;
5598
0
    unsigned int handle;
5599
0
    struct nlattr *nl_options;
5600
5601
0
    error = tc_parse_class(tcmsg, &handle, &nl_options, stats);
5602
0
    if (error) {
5603
0
        return error;
5604
0
    }
5605
5606
0
    if (queue_id) {
5607
0
        unsigned int major, minor;
5608
5609
0
        major = tc_get_major(handle);
5610
0
        minor = tc_get_minor(handle);
5611
0
        if (major == 1 && minor > 0 && minor <= HFSC_N_QUEUES) {
5612
0
            *queue_id = minor - 1;
5613
0
        } else {
5614
0
            return EPROTO;
5615
0
        }
5616
0
    }
5617
5618
0
    if (options) {
5619
0
        error = hfsc_parse_tca_options__(nl_options, options);
5620
0
    }
5621
5622
0
    return error;
5623
0
}
5624
5625
static int
5626
hfsc_query_class__(const struct netdev *netdev, unsigned int handle,
5627
                   unsigned int parent, struct hfsc_class *options,
5628
                   struct netdev_queue_stats *stats)
5629
0
{
5630
0
    int error;
5631
0
    struct ofpbuf *reply;
5632
5633
0
    error = tc_query_class(netdev, handle, parent, &reply);
5634
0
    if (error) {
5635
0
        return error;
5636
0
    }
5637
5638
0
    error = hfsc_parse_tcmsg__(reply, NULL, options, stats);
5639
0
    ofpbuf_delete(reply);
5640
0
    return error;
5641
0
}
5642
5643
static void
5644
hfsc_parse_qdisc_details__(struct netdev *netdev, const struct smap *details,
5645
                           struct hfsc_class *class)
5646
0
{
5647
0
    uint32_t max_rate = smap_get_ullong(details, "max-rate", 0) / 8;
5648
0
    if (!max_rate) {
5649
0
        uint32_t current_speed;
5650
0
        uint32_t max_speed OVS_UNUSED;
5651
5652
0
        netdev_linux_get_speed_locked(netdev_linux_cast(netdev),
5653
0
                                      &current_speed, &max_speed);
5654
0
        max_rate = current_speed ? current_speed / 8 * 1000000ULL
5655
0
                                 : NETDEV_DEFAULT_BPS / 8;
5656
0
    }
5657
5658
0
    class->min_rate = max_rate;
5659
0
    class->max_rate = max_rate;
5660
0
}
5661
5662
static int
5663
hfsc_parse_class_details__(struct netdev *netdev,
5664
                           const struct smap *details,
5665
                           struct hfsc_class * class)
5666
0
{
5667
0
    const struct hfsc *hfsc;
5668
0
    uint32_t min_rate, max_rate;
5669
5670
0
    hfsc       = hfsc_get__(netdev);
5671
5672
0
    min_rate = smap_get_ullong(details, "min-rate", 0) / 8;
5673
0
    min_rate = MAX(min_rate, 1);
5674
0
    min_rate = MIN(min_rate, hfsc->max_rate);
5675
5676
0
    max_rate = smap_get_ullong(details, "max-rate", hfsc->max_rate * 8) / 8;
5677
0
    max_rate = MAX(max_rate, min_rate);
5678
0
    max_rate = MIN(max_rate, hfsc->max_rate);
5679
5680
0
    class->min_rate = min_rate;
5681
0
    class->max_rate = max_rate;
5682
5683
0
    return 0;
5684
0
}
5685
5686
/* Create an HFSC qdisc.
5687
 *
5688
 * Equivalent to "tc qdisc add dev <dev> root handle 1: hfsc default 1". */
5689
static int
5690
hfsc_setup_qdisc__(struct netdev * netdev)
5691
0
{
5692
0
    struct tcmsg *tcmsg;
5693
0
    struct ofpbuf request;
5694
0
    struct tc_hfsc_qopt opt;
5695
5696
0
    tc_del_qdisc(netdev);
5697
5698
0
    tcmsg = netdev_linux_tc_make_request(netdev, RTM_NEWQDISC,
5699
0
                                         NLM_F_EXCL | NLM_F_CREATE, &request);
5700
5701
0
    if (!tcmsg) {
5702
0
        return ENODEV;
5703
0
    }
5704
5705
0
    tcmsg->tcm_handle = tc_make_handle(1, 0);
5706
0
    tcmsg->tcm_parent = TC_H_ROOT;
5707
5708
0
    memset(&opt, 0, sizeof opt);
5709
0
    opt.defcls = 1;
5710
5711
0
    nl_msg_put_string(&request, TCA_KIND, "hfsc");
5712
0
    nl_msg_put_unspec(&request, TCA_OPTIONS, &opt, sizeof opt);
5713
5714
0
    return tc_transact(&request, NULL);
5715
0
}
5716
5717
/* Create an HFSC class.
5718
 *
5719
 * Equivalent to "tc class add <dev> parent <parent> classid <handle> hfsc
5720
 * sc rate <min_rate> ul rate <max_rate>" */
5721
static int
5722
hfsc_setup_class__(struct netdev *netdev, unsigned int handle,
5723
                   unsigned int parent, struct hfsc_class *class)
5724
0
{
5725
0
    int error;
5726
0
    size_t opt_offset;
5727
0
    struct tcmsg *tcmsg;
5728
0
    struct ofpbuf request;
5729
0
    struct tc_service_curve min, max;
5730
5731
0
    tcmsg = netdev_linux_tc_make_request(netdev, RTM_NEWTCLASS, NLM_F_CREATE,
5732
0
                                         &request);
5733
5734
0
    if (!tcmsg) {
5735
0
        return ENODEV;
5736
0
    }
5737
5738
0
    tcmsg->tcm_handle = handle;
5739
0
    tcmsg->tcm_parent = parent;
5740
5741
0
    min.m1 = 0;
5742
0
    min.d  = 0;
5743
0
    min.m2 = class->min_rate;
5744
5745
0
    max.m1 = 0;
5746
0
    max.d  = 0;
5747
0
    max.m2 = class->max_rate;
5748
5749
0
    nl_msg_put_string(&request, TCA_KIND, "hfsc");
5750
0
    opt_offset = nl_msg_start_nested(&request, TCA_OPTIONS);
5751
0
    nl_msg_put_unspec(&request, TCA_HFSC_RSC, &min, sizeof min);
5752
0
    nl_msg_put_unspec(&request, TCA_HFSC_FSC, &min, sizeof min);
5753
0
    nl_msg_put_unspec(&request, TCA_HFSC_USC, &max, sizeof max);
5754
0
    nl_msg_end_nested(&request, opt_offset);
5755
5756
0
    error = tc_transact(&request, NULL);
5757
0
    if (error) {
5758
0
        VLOG_WARN_RL(&rl, "failed to replace %s class %u:%u, parent %u:%u, "
5759
0
                     "min-rate %ubps, max-rate %ubps (%s)",
5760
0
                     netdev_get_name(netdev),
5761
0
                     tc_get_major(handle), tc_get_minor(handle),
5762
0
                     tc_get_major(parent), tc_get_minor(parent),
5763
0
                     class->min_rate, class->max_rate, ovs_strerror(error));
5764
0
    }
5765
5766
0
    return error;
5767
0
}
5768
5769
static int
5770
hfsc_tc_install(struct netdev *netdev, const struct smap *details)
5771
0
{
5772
0
    int error;
5773
0
    struct hfsc_class class;
5774
5775
0
    error = hfsc_setup_qdisc__(netdev);
5776
5777
0
    if (error) {
5778
0
        return error;
5779
0
    }
5780
5781
0
    hfsc_parse_qdisc_details__(netdev, details, &class);
5782
0
    error = hfsc_setup_class__(netdev, tc_make_handle(1, 0xfffe),
5783
0
                               tc_make_handle(1, 0), &class);
5784
5785
0
    if (error) {
5786
0
        return error;
5787
0
    }
5788
5789
0
    hfsc_install__(netdev, class.max_rate);
5790
0
    return 0;
5791
0
}
5792
5793
static int
5794
hfsc_tc_load(struct netdev *netdev, struct ofpbuf *nlmsg OVS_UNUSED)
5795
0
{
5796
0
    struct ofpbuf msg;
5797
0
    struct queue_dump_state state;
5798
0
    struct hfsc_class hc;
5799
5800
0
    hc.max_rate = 0;
5801
0
    hfsc_query_class__(netdev, tc_make_handle(1, 0xfffe), 0, &hc, NULL);
5802
0
    hfsc_install__(netdev, hc.max_rate);
5803
5804
0
    if (!start_queue_dump(netdev, &state)) {
5805
0
        return ENODEV;
5806
0
    }
5807
5808
0
    while (nl_dump_next(&state.dump, &msg, &state.buf)) {
5809
0
        unsigned int queue_id;
5810
5811
0
        if (!hfsc_parse_tcmsg__(&msg, &queue_id, &hc, NULL)) {
5812
0
            hfsc_update_queue__(netdev, queue_id, &hc);
5813
0
        }
5814
0
    }
5815
5816
0
    finish_queue_dump(&state);
5817
0
    return 0;
5818
0
}
5819
5820
static void
5821
hfsc_tc_destroy(struct tc *tc)
5822
0
{
5823
0
    struct hfsc *hfsc;
5824
0
    struct hfsc_class *hc;
5825
5826
0
    hfsc = CONTAINER_OF(tc, struct hfsc, tc);
5827
5828
0
    HMAP_FOR_EACH_SAFE (hc, tc_queue.hmap_node, &hfsc->tc.queues) {
5829
0
        hmap_remove(&hfsc->tc.queues, &hc->tc_queue.hmap_node);
5830
0
        free(hc);
5831
0
    }
5832
5833
0
    tc_destroy(tc);
5834
0
    free(hfsc);
5835
0
}
5836
5837
static int
5838
hfsc_qdisc_get(const struct netdev *netdev, struct smap *details)
5839
0
{
5840
0
    const struct hfsc *hfsc;
5841
0
    hfsc = hfsc_get__(netdev);
5842
0
    smap_add_format(details, "max-rate", "%llu", 8ULL * hfsc->max_rate);
5843
0
    return 0;
5844
0
}
5845
5846
static int
5847
hfsc_qdisc_set(struct netdev *netdev, const struct smap *details)
5848
0
{
5849
0
    int error;
5850
0
    struct hfsc_class class;
5851
5852
0
    hfsc_parse_qdisc_details__(netdev, details, &class);
5853
0
    error = hfsc_setup_class__(netdev, tc_make_handle(1, 0xfffe),
5854
0
                               tc_make_handle(1, 0), &class);
5855
5856
0
    if (!error) {
5857
0
        hfsc_get__(netdev)->max_rate = class.max_rate;
5858
0
    }
5859
5860
0
    return error;
5861
0
}
5862
5863
static int
5864
hfsc_class_get(const struct netdev *netdev OVS_UNUSED,
5865
              const struct tc_queue *queue, struct smap *details)
5866
0
{
5867
0
    const struct hfsc_class *hc;
5868
5869
0
    hc = hfsc_class_cast__(queue);
5870
0
    smap_add_format(details, "min-rate", "%llu", 8ULL * hc->min_rate);
5871
0
    if (hc->min_rate != hc->max_rate) {
5872
0
        smap_add_format(details, "max-rate", "%llu", 8ULL * hc->max_rate);
5873
0
    }
5874
0
    return 0;
5875
0
}
5876
5877
static int
5878
hfsc_class_set(struct netdev *netdev, unsigned int queue_id,
5879
               const struct smap *details)
5880
0
{
5881
0
    int error;
5882
0
    struct hfsc_class class;
5883
5884
0
    error = hfsc_parse_class_details__(netdev, details, &class);
5885
0
    if (error) {
5886
0
        return error;
5887
0
    }
5888
5889
0
    error = hfsc_setup_class__(netdev, tc_make_handle(1, queue_id + 1),
5890
0
                               tc_make_handle(1, 0xfffe), &class);
5891
0
    if (error) {
5892
0
        return error;
5893
0
    }
5894
5895
0
    hfsc_update_queue__(netdev, queue_id, &class);
5896
0
    return 0;
5897
0
}
5898
5899
static int
5900
hfsc_class_delete(struct netdev *netdev, struct tc_queue *queue)
5901
0
{
5902
0
    int error;
5903
0
    struct hfsc *hfsc;
5904
0
    struct hfsc_class *hc;
5905
5906
0
    hc   = hfsc_class_cast__(queue);
5907
0
    hfsc = hfsc_get__(netdev);
5908
5909
0
    error = tc_delete_class(netdev, tc_make_handle(1, queue->queue_id + 1));
5910
0
    if (!error) {
5911
0
        hmap_remove(&hfsc->tc.queues, &hc->tc_queue.hmap_node);
5912
0
        free(hc);
5913
0
    }
5914
0
    return error;
5915
0
}
5916
5917
static int
5918
hfsc_class_get_stats(const struct netdev *netdev, const struct tc_queue *queue,
5919
                     struct netdev_queue_stats *stats)
5920
0
{
5921
0
    return hfsc_query_class__(netdev, tc_make_handle(1, queue->queue_id + 1),
5922
0
                             tc_make_handle(1, 0xfffe), NULL, stats);
5923
0
}
5924
5925
static int
5926
hfsc_class_dump_stats(const struct netdev *netdev OVS_UNUSED,
5927
                      const struct ofpbuf *nlmsg,
5928
                      netdev_dump_queue_stats_cb *cb, void *aux)
5929
0
{
5930
0
    struct netdev_queue_stats stats;
5931
0
    unsigned int handle, major, minor;
5932
0
    int error;
5933
5934
0
    error = tc_parse_class(nlmsg, &handle, NULL, &stats);
5935
0
    if (error) {
5936
0
        return error;
5937
0
    }
5938
5939
0
    major = tc_get_major(handle);
5940
0
    minor = tc_get_minor(handle);
5941
0
    if (major == 1 && minor > 0 && minor <= HFSC_N_QUEUES) {
5942
0
        (*cb)(minor - 1, &stats, aux);
5943
0
    }
5944
0
    return 0;
5945
0
}
5946
5947
static const struct tc_ops tc_ops_hfsc = {
5948
    .linux_name = "hfsc",
5949
    .ovs_name = "linux-hfsc",
5950
    .n_queues = HFSC_N_QUEUES,              /* n_queues */
5951
    .tc_install = hfsc_tc_install,
5952
    .tc_load = hfsc_tc_load,
5953
    .tc_destroy = hfsc_tc_destroy,
5954
    .qdisc_get = hfsc_qdisc_get,
5955
    .qdisc_set = hfsc_qdisc_set,
5956
    .class_get = hfsc_class_get,
5957
    .class_set = hfsc_class_set,
5958
    .class_delete = hfsc_class_delete,
5959
    .class_get_stats = hfsc_class_get_stats,
5960
    .class_dump_stats = hfsc_class_dump_stats,
5961
};
5962

5963
/* "linux-noop" traffic control class. */
5964
5965
static void
5966
noop_install__(struct netdev *netdev_)
5967
0
{
5968
0
    struct netdev_linux *netdev = netdev_linux_cast(netdev_);
5969
0
    static const struct tc tc = TC_INITIALIZER(&tc, &tc_ops_default);
5970
5971
0
    netdev->tc = CONST_CAST(struct tc *, &tc);
5972
0
}
5973
5974
static int
5975
noop_tc_install(struct netdev *netdev,
5976
                   const struct smap *details OVS_UNUSED)
5977
0
{
5978
0
    noop_install__(netdev);
5979
0
    return 0;
5980
0
}
5981
5982
static int
5983
noop_tc_load(struct netdev *netdev, struct ofpbuf *nlmsg OVS_UNUSED)
5984
0
{
5985
0
    noop_install__(netdev);
5986
0
    return 0;
5987
0
}
5988
5989
static const struct tc_ops tc_ops_noop = {
5990
    .ovs_name = "linux-noop",               /* ovs_name */
5991
    .tc_install = noop_tc_install,
5992
    .tc_load = noop_tc_load,
5993
};
5994

5995
/* "linux-default" traffic control class.
5996
 *
5997
 * This class represents the default, unnamed Linux qdisc.  It corresponds to
5998
 * the "" (empty string) QoS type in the OVS database. */
5999
6000
static void
6001
default_install__(struct netdev *netdev_)
6002
0
{
6003
0
    struct netdev_linux *netdev = netdev_linux_cast(netdev_);
6004
0
    static const struct tc tc = TC_INITIALIZER(&tc, &tc_ops_default);
6005
6006
    /* Nothing but a tc class implementation is allowed to write to a tc.  This
6007
     * class never does that, so we can legitimately use a const tc object. */
6008
0
    netdev->tc = CONST_CAST(struct tc *, &tc);
6009
0
}
6010
6011
static int
6012
default_tc_install(struct netdev *netdev,
6013
                   const struct smap *details OVS_UNUSED)
6014
0
{
6015
0
    default_install__(netdev);
6016
0
    return 0;
6017
0
}
6018
6019
static int
6020
default_tc_load(struct netdev *netdev, struct ofpbuf *nlmsg OVS_UNUSED)
6021
0
{
6022
0
    default_install__(netdev);
6023
0
    return 0;
6024
0
}
6025
6026
static const struct tc_ops tc_ops_default = {
6027
    .ovs_name = "",                         /* ovs_name */
6028
    .tc_install = default_tc_install,
6029
    .tc_load = default_tc_load,
6030
};
6031

6032
/* "linux-other" traffic control class.
6033
 *
6034
 * */
6035
6036
static int
6037
other_tc_load(struct netdev *netdev_, struct ofpbuf *nlmsg OVS_UNUSED)
6038
0
{
6039
0
    struct netdev_linux *netdev = netdev_linux_cast(netdev_);
6040
0
    static const struct tc tc = TC_INITIALIZER(&tc, &tc_ops_other);
6041
6042
    /* Nothing but a tc class implementation is allowed to write to a tc.  This
6043
     * class never does that, so we can legitimately use a const tc object. */
6044
0
    netdev->tc = CONST_CAST(struct tc *, &tc);
6045
0
    return 0;
6046
0
}
6047
6048
static const struct tc_ops tc_ops_other = {
6049
    .ovs_name = "linux-other",
6050
    .tc_load = other_tc_load,
6051
};
6052

6053
/* Traffic control. */
6054
6055
/* Number of kernel "tc" ticks per second. */
6056
static double ticks_per_s;
6057
6058
/* Number of kernel "jiffies" per second.  This is used for the purpose of
6059
 * computing buffer sizes.  Generally kernel qdiscs need to be able to buffer
6060
 * one jiffy's worth of data.
6061
 *
6062
 * There are two possibilities here:
6063
 *
6064
 *    - 'buffer_hz' is the kernel's real timer tick rate, a small number in the
6065
 *      approximate range of 100 to 1024.  That means that we really need to
6066
 *      make sure that the qdisc can buffer that much data.
6067
 *
6068
 *    - 'buffer_hz' is an absurdly large number.  That means that the kernel
6069
 *      has finely granular timers and there's no need to fudge additional room
6070
 *      for buffers.  (There's no extra effort needed to implement that: the
6071
 *      large 'buffer_hz' is used as a divisor, so practically any number will
6072
 *      come out as 0 in the division.  Small integer results in the case of
6073
 *      really high dividends won't have any real effect anyhow.)
6074
 */
6075
static unsigned int buffer_hz;
6076
6077
static struct tcmsg *
6078
netdev_linux_tc_make_request(const struct netdev *netdev, int type,
6079
                             unsigned int flags, struct ofpbuf *request)
6080
0
{
6081
0
    int ifindex;
6082
0
    int error;
6083
6084
0
    error = get_ifindex(netdev, &ifindex);
6085
0
    if (error) {
6086
0
        return NULL;
6087
0
    }
6088
6089
0
    return tc_make_request(ifindex, type, flags, request);
6090
0
}
6091
6092
static void
6093
tc_policer_init(struct tc_police *tc_police, uint64_t kbits_rate,
6094
                uint64_t kbits_burst)
6095
0
{
6096
0
    int mtu = 65535;
6097
6098
0
    memset(tc_police, 0, sizeof *tc_police);
6099
6100
0
    tc_police->action = TC_POLICE_SHOT;
6101
0
    tc_police->mtu = mtu;
6102
0
    tc_fill_rate(&tc_police->rate, kbits_rate * 1000 / 8, mtu);
6103
6104
    /* The following appears wrong in one way: In networking a kilobit is
6105
     * usually 1000 bits but this uses 1024 bits.
6106
     *
6107
     * However if you "fix" those problems then "tc filter show ..." shows
6108
     * "125000b", meaning 125,000 bits, when OVS configures it for 1000 kbit ==
6109
     * 1,000,000 bits, whereas this actually ends up doing the right thing from
6110
     * tc's point of view.  Whatever. */
6111
0
    tc_police->burst = tc_bytes_to_ticks(
6112
0
        tc_police->rate.rate, kbits_burst * 1024 / 8);
6113
0
}
6114
6115
/* Adds a policer to 'netdev' with a rate of 'kbits_rate' and a burst size
6116
 * of 'kbits_burst', with a rate of 'kpkts_rate' and a burst size of
6117
 * 'kpkts_burst'.
6118
 *
6119
 * This function is equivalent to running:
6120
 *     /sbin/tc filter add dev <devname> parent ffff: protocol all prio 49
6121
 *              basic police rate <kbits_rate>kbit burst <kbits_burst>k
6122
 *              mtu 65535 drop
6123
 *
6124
 * The configuration and stats may be seen with the following command:
6125
 *     /sbin/tc -s filter show dev <devname> parent ffff:
6126
 *
6127
 * Returns 0 if successful, otherwise a positive errno value.
6128
 */
6129
static int
6130
tc_add_policer(struct netdev *netdev, uint64_t kbits_rate,
6131
               uint32_t kbits_burst, uint32_t kpkts_rate, uint32_t kpkts_burst)
6132
0
{
6133
0
    size_t basic_offset, police_offset;
6134
0
    struct ofpbuf request;
6135
0
    struct tcmsg *tcmsg;
6136
0
    int error;
6137
6138
0
    tcmsg = netdev_linux_tc_make_request(netdev, RTM_NEWTFILTER,
6139
0
                                         NLM_F_EXCL | NLM_F_CREATE, &request);
6140
0
    if (!tcmsg) {
6141
0
        return ENODEV;
6142
0
    }
6143
0
    tcmsg->tcm_parent = tc_make_handle(0xffff, 0);
6144
0
    tcmsg->tcm_info = tc_make_handle(49,
6145
0
                                     (OVS_FORCE uint16_t) htons(ETH_P_ALL));
6146
0
    nl_msg_put_string(&request, TCA_KIND, "basic");
6147
6148
0
    basic_offset = nl_msg_start_nested(&request, TCA_OPTIONS);
6149
0
    police_offset = nl_msg_start_nested(&request, TCA_BASIC_ACT);
6150
0
    nl_msg_put_act_police(&request, 0, kbits_rate, kbits_burst,
6151
0
                          kpkts_rate * 1000ULL, kpkts_burst * 1000ULL,
6152
0
                          TC_ACT_UNSPEC, false);
6153
0
    nl_msg_end_nested(&request, police_offset);
6154
0
    nl_msg_end_nested(&request, basic_offset);
6155
6156
0
    error = tc_transact(&request, NULL);
6157
0
    if (error) {
6158
0
        return error;
6159
0
    }
6160
6161
0
    return 0;
6162
0
}
6163
6164
int
6165
tc_add_policer_action(uint32_t index, uint64_t kbits_rate,
6166
                      uint32_t kbits_burst, uint32_t pkts_rate,
6167
                      uint32_t pkts_burst, bool update)
6168
0
{
6169
0
    struct ofpbuf request;
6170
0
    struct tcamsg *tcamsg;
6171
0
    size_t offset;
6172
0
    int flags;
6173
0
    int error;
6174
6175
0
    flags = (update ? NLM_F_REPLACE : NLM_F_EXCL) | NLM_F_CREATE;
6176
0
    tcamsg = tc_make_action_request(RTM_NEWACTION, flags, &request);
6177
0
    if (!tcamsg) {
6178
0
        return ENODEV;
6179
0
    }
6180
6181
0
    offset = nl_msg_start_nested(&request, TCA_ACT_TAB);
6182
0
    nl_msg_put_act_police(&request, index, kbits_rate, kbits_burst, pkts_rate,
6183
0
                          pkts_burst, TC_ACT_PIPE, true);
6184
0
    nl_msg_end_nested(&request, offset);
6185
6186
0
    error = tc_transact(&request, NULL);
6187
0
    if (error) {
6188
0
        VLOG_ERR_RL(&rl, "Failed to %s police action, err=%d",
6189
0
                    update ? "update" : "add", error);
6190
0
    }
6191
6192
0
    return error;
6193
0
}
6194
6195
static int
6196
tc_update_policer_action_stats(struct ofpbuf *msg,
6197
                               struct ofputil_meter_stats *stats)
6198
0
{
6199
0
    struct ofpbuf b = ofpbuf_const_initializer(msg->data, msg->size);
6200
0
    struct nlmsghdr *nlmsg = ofpbuf_try_pull(&b, sizeof *nlmsg);
6201
0
    struct tcamsg *tca = ofpbuf_try_pull(&b, sizeof *tca);
6202
0
    struct ovs_flow_stats stats_dropped;
6203
0
    struct ovs_flow_stats stats_hw;
6204
0
    struct ovs_flow_stats stats_sw;
6205
0
    const struct nlattr *act;
6206
0
    struct nlattr *prio;
6207
0
    int error = 0;
6208
6209
0
    if (!stats) {
6210
0
        goto exit;
6211
0
    }
6212
6213
0
    if (!nlmsg || !tca) {
6214
0
        VLOG_ERR_RL(&rl, "Failed to get action stats, size error");
6215
0
        error = EPROTO;
6216
0
        goto exit;
6217
0
    }
6218
6219
0
    act = nl_attr_find(&b, 0, TCA_ACT_TAB);
6220
0
    if (!act) {
6221
0
        VLOG_ERR_RL(&rl, "Failed to get action stats, can't find attribute");
6222
0
        error = EPROTO;
6223
0
        goto exit;
6224
0
    }
6225
6226
0
    prio = (struct nlattr *) act + 1;
6227
0
    memset(&stats_sw, 0, sizeof stats_sw);
6228
0
    memset(&stats_hw, 0, sizeof stats_hw);
6229
0
    memset(&stats_dropped, 0, sizeof stats_dropped);
6230
0
    error = tc_parse_action_stats(prio, &stats_sw, &stats_hw, &stats_dropped);
6231
0
    if (!error) {
6232
0
        stats->packet_in_count +=
6233
0
            get_32aligned_u64(&stats_sw.n_packets);
6234
0
        stats->byte_in_count += get_32aligned_u64(&stats_sw.n_bytes);
6235
0
        stats->packet_in_count +=
6236
0
            get_32aligned_u64(&stats_hw.n_packets);
6237
0
        stats->byte_in_count += get_32aligned_u64(&stats_hw.n_bytes);
6238
0
        if (stats->n_bands >= 1) {
6239
0
            stats->bands[0].packet_count +=
6240
0
                get_32aligned_u64(&stats_dropped.n_packets);
6241
0
        }
6242
0
    }
6243
6244
0
exit:
6245
0
    ofpbuf_delete(msg);
6246
0
    return error;
6247
0
}
6248
6249
int
6250
tc_get_policer_action(uint32_t index, struct ofputil_meter_stats *stats)
6251
0
{
6252
0
    struct ofpbuf *replyp = NULL;
6253
0
    struct ofpbuf request;
6254
0
    struct tcamsg *tcamsg;
6255
0
    size_t root_offset;
6256
0
    size_t prio_offset;
6257
0
    int error;
6258
6259
0
    tcamsg = tc_make_action_request(RTM_GETACTION, 0, &request);
6260
0
    if (!tcamsg) {
6261
0
        return ENODEV;
6262
0
    }
6263
6264
0
    root_offset = nl_msg_start_nested(&request, TCA_ACT_TAB);
6265
0
    prio_offset = nl_msg_start_nested(&request, 1);
6266
0
    nl_msg_put_string(&request, TCA_ACT_KIND, "police");
6267
0
    nl_msg_put_u32(&request, TCA_ACT_INDEX, index);
6268
0
    nl_msg_end_nested(&request, prio_offset);
6269
0
    nl_msg_end_nested(&request, root_offset);
6270
6271
0
    error = tc_transact(&request, &replyp);
6272
0
    if (error) {
6273
0
        VLOG_ERR_RL(&rl, "Failed to dump police action (index: %u), err=%d",
6274
0
                    index, error);
6275
0
        return error;
6276
0
    }
6277
6278
0
    return tc_update_policer_action_stats(replyp, stats);
6279
0
}
6280
6281
int
6282
tc_del_policer_action(uint32_t index, struct ofputil_meter_stats *stats)
6283
0
{
6284
0
    struct ofpbuf *replyp = NULL;
6285
0
    struct ofpbuf request;
6286
0
    struct tcamsg *tcamsg;
6287
0
    size_t root_offset;
6288
0
    size_t prio_offset;
6289
0
    int error;
6290
6291
0
    tcamsg = tc_make_action_request(RTM_DELACTION, NLM_F_ACK, &request);
6292
0
    if (!tcamsg) {
6293
0
        return ENODEV;
6294
0
    }
6295
6296
0
    root_offset = nl_msg_start_nested(&request, TCA_ACT_TAB);
6297
0
    prio_offset = nl_msg_start_nested(&request, 1);
6298
0
    nl_msg_put_string(&request, TCA_ACT_KIND, "police");
6299
0
    nl_msg_put_u32(&request, TCA_ACT_INDEX, index);
6300
0
    nl_msg_end_nested(&request, prio_offset);
6301
0
    nl_msg_end_nested(&request, root_offset);
6302
6303
0
    error = tc_transact(&request, &replyp);
6304
0
    if (error) {
6305
0
        VLOG_ERR_RL(&rl, "Failed to delete police action (index: %u), err=%d",
6306
0
                    index, error);
6307
0
        return error;
6308
0
    }
6309
6310
0
    return tc_update_policer_action_stats(replyp, stats);
6311
0
}
6312
6313
static void
6314
read_psched(void)
6315
0
{
6316
    /* The values in psched are not individually very meaningful, but they are
6317
     * important.  The tables below show some values seen in the wild.
6318
     *
6319
     * Some notes:
6320
     *
6321
     *   - "c" has always been a constant 1000000 since at least Linux 2.4.14.
6322
     *     (Before that, there are hints that it was 1000000000.)
6323
     *
6324
     *   - "d" can be unrealistically large, see the comment on 'buffer_hz'
6325
     *     above.
6326
     *
6327
     *                        /proc/net/psched
6328
     *     -----------------------------------
6329
     * [1] 000c8000 000f4240 000f4240 00000064
6330
     * [2] 000003e8 00000400 000f4240 3b9aca00
6331
     * [3] 000003e8 00000400 000f4240 3b9aca00
6332
     * [4] 000003e8 00000400 000f4240 00000064
6333
     * [5] 000003e8 00000040 000f4240 3b9aca00
6334
     * [6] 000003e8 00000040 000f4240 000000f9
6335
     *
6336
     *           a         b          c             d ticks_per_s     buffer_hz
6337
     *     ------- --------- ---------- ------------- ----------- -------------
6338
     * [1] 819,200 1,000,000  1,000,000           100     819,200           100
6339
     * [2]   1,000     1,024  1,000,000 1,000,000,000     976,562 1,000,000,000
6340
     * [3]   1,000     1,024  1,000,000 1,000,000,000     976,562 1,000,000,000
6341
     * [4]   1,000     1,024  1,000,000           100     976,562           100
6342
     * [5]   1,000        64  1,000,000 1,000,000,000  15,625,000 1,000,000,000
6343
     * [6]   1,000        64  1,000,000           249  15,625,000           249
6344
     *
6345
     * [1] 2.6.18-128.1.6.el5.xs5.5.0.505.1024xen from XenServer 5.5.0-24648p
6346
     * [2] 2.6.26-1-686-bigmem from Debian lenny
6347
     * [3] 2.6.26-2-sparc64 from Debian lenny
6348
     * [4] 2.6.27.42-0.1.1.xs5.6.810.44.111163xen from XenServer 5.6.810-31078p
6349
     * [5] 2.6.32.21.22 (approx.) from Ubuntu 10.04 on VMware Fusion
6350
     * [6] 2.6.34 from kernel.org on KVM
6351
     */
6352
0
    static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER;
6353
0
    static const char fn[] = "/proc/net/psched";
6354
0
    unsigned int a, b, c, d;
6355
0
    FILE *stream;
6356
6357
0
    if (!ovsthread_once_start(&once)) {
6358
0
        return;
6359
0
    }
6360
6361
0
    ticks_per_s = 1.0;
6362
0
    buffer_hz = 100;
6363
6364
0
    stream = fopen(fn, "r");
6365
0
    if (!stream) {
6366
0
        VLOG_WARN("%s: open failed: %s", fn, ovs_strerror(errno));
6367
0
        goto exit;
6368
0
    }
6369
6370
0
    if (fscanf(stream, "%x %x %x %x", &a, &b, &c, &d) != 4) {
6371
0
        VLOG_WARN("%s: read failed", fn);
6372
0
        fclose(stream);
6373
0
        goto exit;
6374
0
    }
6375
0
    VLOG_DBG("%s: psched parameters are: %u %u %u %u", fn, a, b, c, d);
6376
0
    fclose(stream);
6377
6378
0
    if (!a || !b || !c) {
6379
0
        VLOG_WARN("%s: invalid scheduler parameters", fn);
6380
0
        goto exit;
6381
0
    }
6382
6383
0
    ticks_per_s = (double) a * c / b;
6384
0
    if (c == 1000000) {
6385
0
        buffer_hz = d;
6386
0
    } else {
6387
0
        VLOG_WARN("%s: unexpected psched parameters: %u %u %u %u",
6388
0
                  fn, a, b, c, d);
6389
0
    }
6390
0
    VLOG_DBG("%s: ticks_per_s=%f buffer_hz=%u", fn, ticks_per_s, buffer_hz);
6391
6392
0
exit:
6393
0
    ovsthread_once_done(&once);
6394
0
}
6395
6396
/* Returns the number of bytes that can be transmitted in 'ticks' ticks at a
6397
 * rate of 'rate' bytes per second. */
6398
static unsigned int
6399
tc_ticks_to_bytes(uint64_t rate, unsigned int ticks)
6400
0
{
6401
0
    read_psched();
6402
0
    return (rate * ticks) / ticks_per_s;
6403
0
}
6404
6405
/* Returns the number of ticks that it would take to transmit 'size' bytes at a
6406
 * rate of 'rate' bytes per second. */
6407
static unsigned int
6408
tc_bytes_to_ticks(uint64_t rate, unsigned int size)
6409
0
{
6410
0
    read_psched();
6411
0
    return rate ? ((unsigned long long int) ticks_per_s * size) / rate : 0;
6412
0
}
6413
6414
/* Returns the number of bytes that need to be reserved for qdisc buffering at
6415
 * a transmission rate of 'rate' bytes per second. */
6416
static unsigned int
6417
tc_buffer_per_jiffy(uint64_t rate)
6418
0
{
6419
0
    read_psched();
6420
0
    return rate / buffer_hz;
6421
0
}
6422
6423
static uint32_t
6424
0
tc_time_to_ticks(uint32_t time) {
6425
0
    read_psched();
6426
0
    return time * (ticks_per_s / 1000000);
6427
0
}
6428
6429
/* Given Netlink 'msg' that describes a qdisc, extracts the name of the qdisc,
6430
 * e.g. "htb", into '*kind' (if it is nonnull).  If 'options' is nonnull,
6431
 * extracts 'msg''s TCA_OPTIONS attributes into '*options' if it is present or
6432
 * stores NULL into it if it is absent.
6433
 *
6434
 * '*kind' and '*options' point into 'msg', so they are owned by whoever owns
6435
 * 'msg'.
6436
 *
6437
 * Returns 0 if successful, otherwise a positive errno value. */
6438
static int
6439
tc_parse_qdisc(const struct ofpbuf *msg, const char **kind,
6440
               struct nlattr **options)
6441
0
{
6442
0
    static const struct nl_policy tca_policy[] = {
6443
0
        [TCA_KIND] = { .type = NL_A_STRING, .optional = false },
6444
0
        [TCA_OPTIONS] = { .type = NL_A_NESTED, .optional = true },
6445
0
    };
6446
0
    struct nlattr *ta[ARRAY_SIZE(tca_policy)];
6447
6448
0
    if (!nl_policy_parse(msg, NLMSG_HDRLEN + sizeof(struct tcmsg),
6449
0
                         tca_policy, ta, ARRAY_SIZE(ta))) {
6450
0
        VLOG_WARN_RL(&rl, "failed to parse qdisc message");
6451
0
        goto error;
6452
0
    }
6453
6454
0
    if (kind) {
6455
0
        *kind = nl_attr_get_string(ta[TCA_KIND]);
6456
0
    }
6457
6458
0
    if (options) {
6459
0
        *options = ta[TCA_OPTIONS];
6460
0
    }
6461
6462
0
    return 0;
6463
6464
0
error:
6465
0
    if (kind) {
6466
0
        *kind = NULL;
6467
0
    }
6468
0
    if (options) {
6469
0
        *options = NULL;
6470
0
    }
6471
0
    return EPROTO;
6472
0
}
6473
6474
/* Given Netlink 'msg' that describes a class, extracts the queue ID (e.g. the
6475
 * minor number of its class ID) into '*queue_id', its TCA_OPTIONS attribute
6476
 * into '*options', and its queue statistics into '*stats'.  Any of the output
6477
 * arguments may be null.
6478
 *
6479
 * Returns 0 if successful, otherwise a positive errno value. */
6480
static int
6481
tc_parse_class(const struct ofpbuf *msg, unsigned int *handlep,
6482
               struct nlattr **options, struct netdev_queue_stats *stats)
6483
0
{
6484
0
    struct ofpbuf b = ofpbuf_const_initializer(msg->data, msg->size);
6485
0
    struct nlmsghdr *nlmsg = ofpbuf_try_pull(&b, sizeof *nlmsg);
6486
0
    struct tcmsg *tc = ofpbuf_try_pull(&b, sizeof *tc);
6487
0
    static const struct nl_policy tca_policy[] = {
6488
0
        [TCA_OPTIONS] = { .type = NL_A_NESTED, .optional = false },
6489
0
        [TCA_STATS2] = { .type = NL_A_NESTED, .optional = false },
6490
0
    };
6491
0
    struct nlattr *ta[ARRAY_SIZE(tca_policy)];
6492
6493
0
    if (!nlmsg || !tc) {
6494
0
        VLOG_ERR_RL(&rl, "failed to parse class message, malformed reply");
6495
0
        goto error;
6496
0
    }
6497
6498
0
    if (!nl_policy_parse(&b, 0, tca_policy, ta, ARRAY_SIZE(ta))) {
6499
0
        VLOG_WARN_RL(&rl, "failed to parse class message");
6500
0
        goto error;
6501
0
    }
6502
6503
0
    if (handlep) {
6504
0
        *handlep = tc->tcm_handle;
6505
0
    }
6506
6507
0
    if (options) {
6508
0
        *options = ta[TCA_OPTIONS];
6509
0
    }
6510
6511
0
    if (stats) {
6512
0
        const struct gnet_stats_queue *gsq;
6513
0
        struct gnet_stats_basic gsb;
6514
6515
0
        static const struct nl_policy stats_policy[] = {
6516
0
            [TCA_STATS_BASIC] = { .type = NL_A_UNSPEC, .optional = false,
6517
0
                                  .min_len = sizeof gsb },
6518
0
            [TCA_STATS_QUEUE] = { .type = NL_A_UNSPEC, .optional = false,
6519
0
                                  .min_len = sizeof *gsq },
6520
0
        };
6521
0
        struct nlattr *sa[ARRAY_SIZE(stats_policy)];
6522
6523
0
        if (!nl_parse_nested(ta[TCA_STATS2], stats_policy,
6524
0
                             sa, ARRAY_SIZE(sa))) {
6525
0
            VLOG_WARN_RL(&rl, "failed to parse class stats");
6526
0
            goto error;
6527
0
        }
6528
6529
        /* Alignment issues screw up the length of struct gnet_stats_basic on
6530
         * some arch/bitsize combinations.  Newer versions of Linux have a
6531
         * struct gnet_stats_basic_packed, but we can't depend on that.  The
6532
         * easiest thing to do is just to make a copy. */
6533
0
        memset(&gsb, 0, sizeof gsb);
6534
0
        memcpy(&gsb, nl_attr_get(sa[TCA_STATS_BASIC]),
6535
0
               MIN(nl_attr_get_size(sa[TCA_STATS_BASIC]), sizeof gsb));
6536
0
        stats->tx_bytes = gsb.bytes;
6537
0
        stats->tx_packets = gsb.packets;
6538
6539
0
        gsq = nl_attr_get(sa[TCA_STATS_QUEUE]);
6540
0
        stats->tx_errors = gsq->drops;
6541
0
    }
6542
6543
0
    return 0;
6544
6545
0
error:
6546
0
    if (options) {
6547
0
        *options = NULL;
6548
0
    }
6549
0
    if (stats) {
6550
0
        memset(stats, 0, sizeof *stats);
6551
0
    }
6552
0
    return EPROTO;
6553
0
}
6554
6555
/* Queries the kernel for class with identifier 'handle' and parent 'parent'
6556
 * on 'netdev'. */
6557
static int
6558
tc_query_class(const struct netdev *netdev,
6559
               unsigned int handle, unsigned int parent,
6560
               struct ofpbuf **replyp)
6561
0
{
6562
0
    struct ofpbuf request;
6563
0
    struct tcmsg *tcmsg;
6564
0
    int error;
6565
6566
0
    tcmsg = netdev_linux_tc_make_request(netdev, RTM_GETTCLASS, NLM_F_ECHO,
6567
0
                                         &request);
6568
0
    if (!tcmsg) {
6569
0
        return ENODEV;
6570
0
    }
6571
0
    tcmsg->tcm_handle = handle;
6572
0
    tcmsg->tcm_parent = parent;
6573
6574
0
    error = tc_transact(&request, replyp);
6575
0
    if (error) {
6576
0
        VLOG_WARN_RL(&rl, "query %s class %u:%u (parent %u:%u) failed (%s)",
6577
0
                     netdev_get_name(netdev),
6578
0
                     tc_get_major(handle), tc_get_minor(handle),
6579
0
                     tc_get_major(parent), tc_get_minor(parent),
6580
0
                     ovs_strerror(error));
6581
0
    }
6582
0
    return error;
6583
0
}
6584
6585
/* Equivalent to "tc class del dev <name> handle <handle>". */
6586
static int
6587
tc_delete_class(const struct netdev *netdev, unsigned int handle)
6588
0
{
6589
0
    struct ofpbuf request;
6590
0
    struct tcmsg *tcmsg;
6591
0
    int error;
6592
6593
0
    tcmsg = netdev_linux_tc_make_request(netdev, RTM_DELTCLASS, 0, &request);
6594
0
    if (!tcmsg) {
6595
0
        return ENODEV;
6596
0
    }
6597
0
    tcmsg->tcm_handle = handle;
6598
0
    tcmsg->tcm_parent = 0;
6599
6600
0
    error = tc_transact(&request, NULL);
6601
0
    if (error) {
6602
0
        VLOG_WARN_RL(&rl, "delete %s class %u:%u failed (%s)",
6603
0
                     netdev_get_name(netdev),
6604
0
                     tc_get_major(handle), tc_get_minor(handle),
6605
0
                     ovs_strerror(error));
6606
0
    }
6607
0
    return error;
6608
0
}
6609
6610
/* Equivalent to "tc qdisc del dev <name> root". */
6611
static int
6612
tc_del_qdisc(struct netdev *netdev_)
6613
0
{
6614
0
    struct netdev_linux *netdev = netdev_linux_cast(netdev_);
6615
0
    struct ofpbuf request;
6616
0
    struct tcmsg *tcmsg;
6617
0
    int error;
6618
6619
0
    tcmsg = netdev_linux_tc_make_request(netdev_, RTM_DELQDISC, 0, &request);
6620
0
    if (!tcmsg) {
6621
0
        return ENODEV;
6622
0
    }
6623
0
    tcmsg->tcm_parent = TC_H_ROOT;
6624
6625
0
    error = tc_transact(&request, NULL);
6626
0
    if (error == EINVAL || error == ENOENT) {
6627
        /* EINVAL or ENOENT probably means that the default qdisc was in use,
6628
         * in which case we've accomplished our purpose. */
6629
0
        error = 0;
6630
0
    }
6631
0
    if (!error && netdev->tc) {
6632
0
        if (netdev->tc->ops->tc_destroy) {
6633
0
            netdev->tc->ops->tc_destroy(netdev->tc);
6634
0
        }
6635
0
        netdev->tc = NULL;
6636
0
    }
6637
0
    return error;
6638
0
}
6639
6640
static bool
6641
getqdisc_is_safe(void)
6642
0
{
6643
0
    static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER;
6644
0
    static bool safe = false;
6645
6646
0
    if (ovsthread_once_start(&once)) {
6647
0
        if (ovs_kernel_is_version_or_newer(2, 35)) {
6648
0
            safe = true;
6649
0
        } else {
6650
0
            VLOG_INFO("disabling unsafe RTM_GETQDISC in Linux kernel");
6651
0
        }
6652
0
        ovsthread_once_done(&once);
6653
0
    }
6654
0
    return safe;
6655
0
}
6656
6657
/* If 'netdev''s qdisc type and parameters are not yet known, queries the
6658
 * kernel to determine what they are.  Returns 0 if successful, otherwise a
6659
 * positive errno value. */
6660
static int
6661
tc_query_qdisc(const struct netdev *netdev_)
6662
0
{
6663
0
    struct netdev_linux *netdev = netdev_linux_cast(netdev_);
6664
0
    struct ofpbuf request, *qdisc;
6665
0
    const struct tc_ops *ops;
6666
0
    struct tcmsg *tcmsg;
6667
0
    int load_error;
6668
0
    int error;
6669
6670
0
    if (netdev->tc) {
6671
0
        return 0;
6672
0
    }
6673
6674
    /* This RTM_GETQDISC is crafted to avoid OOPSing kernels that do not have
6675
     * commit 53b0f08 "net_sched: Fix qdisc_notify()", which is anything before
6676
     * 2.6.35 without that fix backported to it.
6677
     *
6678
     * To avoid the OOPS, we must not make a request that would attempt to dump
6679
     * a "built-in" qdisc, that is, the default pfifo_fast qdisc or one of a
6680
     * few others.  There are a few ways that I can see to do this, but most of
6681
     * them seem to be racy (and if you lose the race the kernel OOPSes).  The
6682
     * technique chosen here is to assume that any non-default qdisc that we
6683
     * create will have a class with handle 1:0.  The built-in qdiscs only have
6684
     * a class with handle 0:0.
6685
     *
6686
     * On Linux 2.6.35+ we use the straightforward method because it allows us
6687
     * to handle non-builtin qdiscs without handle 1:0 (e.g. codel).  However,
6688
     * in such a case we get no response at all from the kernel (!) if a
6689
     * builtin qdisc is in use (which is later caught by "!error &&
6690
     * !qdisc->size"). */
6691
0
    tcmsg = netdev_linux_tc_make_request(netdev_, RTM_GETQDISC, NLM_F_ECHO,
6692
0
                                         &request);
6693
0
    if (!tcmsg) {
6694
0
        return ENODEV;
6695
0
    }
6696
0
    tcmsg->tcm_handle = tc_make_handle(getqdisc_is_safe() ? 0 : 1, 0);
6697
0
    tcmsg->tcm_parent = getqdisc_is_safe() ? TC_H_ROOT : 0;
6698
6699
    /* Figure out what tc class to instantiate. */
6700
0
    error = tc_transact(&request, &qdisc);
6701
0
    if (!error && qdisc->size) {
6702
0
        const char *kind;
6703
6704
0
        error = tc_parse_qdisc(qdisc, &kind, NULL);
6705
0
        if (error) {
6706
0
            ops = &tc_ops_other;
6707
0
        } else {
6708
0
            ops = tc_lookup_linux_name(kind);
6709
0
            if (!ops) {
6710
0
                static struct vlog_rate_limit rl2 = VLOG_RATE_LIMIT_INIT(1, 1);
6711
0
                VLOG_DBG_RL(&rl2, "unknown qdisc \"%s\"", kind);
6712
6713
0
                ops = &tc_ops_other;
6714
0
            }
6715
0
        }
6716
0
    } else if ((!error && !qdisc->size) || error == ENOENT) {
6717
        /* Either it's a built-in qdisc, or (on Linux pre-2.6.35) it's a qdisc
6718
         * set up by some other entity that doesn't have a handle 1:0.  We will
6719
         * assume that it's the system default qdisc. */
6720
0
        ops = &tc_ops_default;
6721
0
        error = 0;
6722
0
    } else {
6723
        /* Who knows?  Maybe the device got deleted. */
6724
0
        VLOG_WARN_RL(&rl, "query %s qdisc failed (%s)",
6725
0
                     netdev_get_name(netdev_), ovs_strerror(error));
6726
0
        ops = &tc_ops_other;
6727
0
    }
6728
6729
    /* Instantiate it. */
6730
0
    load_error = ops->tc_load(CONST_CAST(struct netdev *, netdev_), qdisc);
6731
0
    ovs_assert((load_error == 0) == (netdev->tc != NULL));
6732
0
    ofpbuf_delete(qdisc);
6733
6734
0
    return error ? error : load_error;
6735
0
}
6736
6737
/* Linux traffic control uses tables with 256 entries ("rtab" tables) to
6738
   approximate the time to transmit packets of various lengths.  For an MTU of
6739
   256 or less, each entry is exact; for an MTU of 257 through 512, each entry
6740
   represents two possible packet lengths; for a MTU of 513 through 1024, four
6741
   possible lengths; and so on.
6742
6743
   Returns, for the specified 'mtu', the number of bits that packet lengths
6744
   need to be shifted right to fit within such a 256-entry table. */
6745
static int
6746
tc_calc_cell_log(unsigned int mtu)
6747
0
{
6748
0
    int cell_log;
6749
6750
0
    if (!mtu) {
6751
0
        mtu = ETH_PAYLOAD_MAX;
6752
0
    }
6753
0
    mtu += ETH_HEADER_LEN + VLAN_HEADER_LEN;
6754
6755
0
    for (cell_log = 0; mtu >= 256; cell_log++) {
6756
0
        mtu >>= 1;
6757
0
    }
6758
6759
0
    return cell_log;
6760
0
}
6761
6762
/* Initializes 'rate' properly for a rate of 'Bps' bytes per second with an MTU
6763
 * of 'mtu'. */
6764
static void
6765
tc_fill_rate(struct tc_ratespec *rate, uint64_t Bps, int mtu)
6766
0
{
6767
0
    memset(rate, 0, sizeof *rate);
6768
0
    rate->cell_log = tc_calc_cell_log(mtu);
6769
    /* rate->overhead = 0; */           /* New in 2.6.24, not yet in some */
6770
    /* rate->cell_align = 0; */         /* distro headers. */
6771
0
    rate->mpu = ETH_TOTAL_MIN;
6772
0
    rate->rate = MIN(UINT32_MAX, Bps);
6773
0
}
6774
6775
/* Appends to 'msg' an "rtab" table for the specified 'rate' as a Netlink
6776
 * attribute of the specified "type".
6777
 *
6778
 * A 64-bit rate can be provided via 'rate64' in bps.
6779
 * If zero, the rate in 'rate' will be used.
6780
 *
6781
 * See tc_calc_cell_log() above for a description of "rtab"s. */
6782
void
6783
tc_put_rtab(struct ofpbuf *msg, uint16_t type, const struct tc_ratespec *rate,
6784
            uint64_t rate64)
6785
0
{
6786
0
    uint32_t *rtab;
6787
0
    unsigned int i;
6788
6789
0
    rtab = nl_msg_put_unspec_uninit(msg, type, TC_RTAB_SIZE);
6790
0
    for (i = 0; i < TC_RTAB_SIZE / sizeof *rtab; i++) {
6791
0
        unsigned packet_size = (i + 1) << rate->cell_log;
6792
0
        if (packet_size < rate->mpu) {
6793
0
            packet_size = rate->mpu;
6794
0
        }
6795
0
        rtab[i] = tc_bytes_to_ticks(rate64 ? rate64 : rate->rate, packet_size);
6796
0
    }
6797
0
}
6798
6799
/* Calculates the proper value of 'buffer' or 'cbuffer' in HTB options given a
6800
 * rate of 'Bps' bytes per second, the specified 'mtu', and a user-requested
6801
 * burst size of 'burst_bytes'.  (If no value was requested, a 'burst_bytes' of
6802
 * 0 is fine.) */
6803
static int
6804
tc_calc_buffer(uint64_t Bps, int mtu, uint64_t burst_bytes)
6805
0
{
6806
0
    unsigned int min_burst = tc_buffer_per_jiffy(Bps) + mtu;
6807
0
    return tc_bytes_to_ticks(Bps, MAX(burst_bytes, min_burst));
6808
0
}
6809

6810
/* Linux-only functions declared in netdev-linux.h  */
6811
6812
/* Modifies the 'flag' bit in ethtool's flags field for 'netdev'.  If
6813
 * 'enable' is true, the bit is set.  Otherwise, it is cleared. */
6814
int
6815
netdev_linux_ethtool_set_flag(struct netdev *netdev, uint32_t flag,
6816
                              const char *flag_name, bool enable)
6817
0
{
6818
0
    const char *netdev_name = netdev_get_name(netdev);
6819
0
    struct ethtool_value evalue;
6820
0
    uint32_t new_flags;
6821
0
    int error;
6822
6823
0
    COVERAGE_INC(netdev_get_ethtool);
6824
0
    memset(&evalue, 0, sizeof evalue);
6825
0
    error = netdev_linux_do_ethtool(netdev_name,
6826
0
                                    (struct ethtool_cmd *)&evalue,
6827
0
                                    ETHTOOL_GFLAGS, "ETHTOOL_GFLAGS");
6828
0
    if (error) {
6829
0
        return error;
6830
0
    }
6831
6832
0
    COVERAGE_INC(netdev_set_ethtool);
6833
0
    new_flags = (evalue.data & ~flag) | (enable ? flag : 0);
6834
0
    if (new_flags == evalue.data) {
6835
0
        return 0;
6836
0
    }
6837
0
    evalue.data = new_flags;
6838
0
    error = netdev_linux_do_ethtool(netdev_name,
6839
0
                                    (struct ethtool_cmd *)&evalue,
6840
0
                                    ETHTOOL_SFLAGS, "ETHTOOL_SFLAGS");
6841
0
    if (error) {
6842
0
        return error;
6843
0
    }
6844
6845
0
    COVERAGE_INC(netdev_get_ethtool);
6846
0
    memset(&evalue, 0, sizeof evalue);
6847
0
    error = netdev_linux_do_ethtool(netdev_name,
6848
0
                                    (struct ethtool_cmd *)&evalue,
6849
0
                                    ETHTOOL_GFLAGS, "ETHTOOL_GFLAGS");
6850
0
    if (error) {
6851
0
        return error;
6852
0
    }
6853
6854
0
    if (new_flags != evalue.data) {
6855
0
        VLOG_WARN_RL(&rl, "attempt to %s ethtool %s flag on network "
6856
0
                     "device %s failed", enable ? "enable" : "disable",
6857
0
                     flag_name, netdev_name);
6858
0
        return EOPNOTSUPP;
6859
0
    }
6860
6861
0
    return 0;
6862
0
}
6863

6864
/* Utility functions. */
6865
6866
/* Copies 'src' into 'dst', performing format conversion in the process. */
6867
static void
6868
netdev_stats_from_rtnl_link_stats(struct netdev_stats *dst,
6869
                                  const struct rtnl_link_stats *src)
6870
0
{
6871
0
    dst->rx_packets = src->rx_packets;
6872
0
    dst->tx_packets = src->tx_packets;
6873
0
    dst->rx_bytes = src->rx_bytes;
6874
0
    dst->tx_bytes = src->tx_bytes;
6875
0
    dst->rx_errors = src->rx_errors;
6876
0
    dst->tx_errors = src->tx_errors;
6877
0
    dst->rx_dropped = src->rx_dropped;
6878
0
    dst->tx_dropped = src->tx_dropped;
6879
0
    dst->multicast = src->multicast;
6880
0
    dst->collisions = src->collisions;
6881
0
    dst->rx_length_errors = src->rx_length_errors;
6882
0
    dst->rx_over_errors = src->rx_over_errors;
6883
0
    dst->rx_crc_errors = src->rx_crc_errors;
6884
0
    dst->rx_frame_errors = src->rx_frame_errors;
6885
0
    dst->rx_fifo_errors = src->rx_fifo_errors;
6886
0
    dst->rx_missed_errors = src->rx_missed_errors;
6887
0
    dst->tx_aborted_errors = src->tx_aborted_errors;
6888
0
    dst->tx_carrier_errors = src->tx_carrier_errors;
6889
0
    dst->tx_fifo_errors = src->tx_fifo_errors;
6890
0
    dst->tx_heartbeat_errors = src->tx_heartbeat_errors;
6891
0
    dst->tx_window_errors = src->tx_window_errors;
6892
0
}
6893
6894
/* Copies 'src' into 'dst', performing format conversion in the process. */
6895
static void
6896
netdev_stats_from_rtnl_link_stats64(struct netdev_stats *dst,
6897
                                    const struct rtnl_link_stats64 *src)
6898
0
{
6899
0
    dst->rx_packets = src->rx_packets;
6900
0
    dst->tx_packets = src->tx_packets;
6901
0
    dst->rx_bytes = src->rx_bytes;
6902
0
    dst->tx_bytes = src->tx_bytes;
6903
0
    dst->rx_errors = src->rx_errors;
6904
0
    dst->tx_errors = src->tx_errors;
6905
0
    dst->rx_dropped = src->rx_dropped;
6906
0
    dst->tx_dropped = src->tx_dropped;
6907
0
    dst->multicast = src->multicast;
6908
0
    dst->collisions = src->collisions;
6909
0
    dst->rx_length_errors = src->rx_length_errors;
6910
0
    dst->rx_over_errors = src->rx_over_errors;
6911
0
    dst->rx_crc_errors = src->rx_crc_errors;
6912
0
    dst->rx_frame_errors = src->rx_frame_errors;
6913
0
    dst->rx_fifo_errors = src->rx_fifo_errors;
6914
0
    dst->rx_missed_errors = src->rx_missed_errors;
6915
0
    dst->tx_aborted_errors = src->tx_aborted_errors;
6916
0
    dst->tx_carrier_errors = src->tx_carrier_errors;
6917
0
    dst->tx_fifo_errors = src->tx_fifo_errors;
6918
0
    dst->tx_heartbeat_errors = src->tx_heartbeat_errors;
6919
0
    dst->tx_window_errors = src->tx_window_errors;
6920
0
}
6921
6922
int
6923
get_stats_via_netlink(const struct netdev *netdev_, struct netdev_stats *stats)
6924
0
{
6925
0
    struct ofpbuf request;
6926
0
    struct ofpbuf *reply;
6927
0
    int error;
6928
6929
    /* Filtering all counters by default */
6930
0
    memset(stats, 0xFF, sizeof(struct netdev_stats));
6931
6932
0
    ofpbuf_init(&request, 0);
6933
0
    nl_msg_put_nlmsghdr(&request,
6934
0
                        sizeof(struct ifinfomsg) + NL_ATTR_SIZE(IFNAMSIZ),
6935
0
                        RTM_GETLINK, NLM_F_REQUEST);
6936
0
    ofpbuf_put_zeros(&request, sizeof(struct ifinfomsg));
6937
0
    nl_msg_put_string(&request, IFLA_IFNAME, netdev_get_name(netdev_));
6938
0
    error = nl_transact(NETLINK_ROUTE, &request, &reply);
6939
0
    ofpbuf_uninit(&request);
6940
0
    if (error) {
6941
0
        return error;
6942
0
    }
6943
6944
0
    if (ofpbuf_try_pull(reply, NLMSG_HDRLEN + sizeof(struct ifinfomsg))) {
6945
0
        const struct nlattr *a = nl_attr_find(reply, 0, IFLA_STATS64);
6946
0
        if (a && nl_attr_get_size(a) >= sizeof(struct rtnl_link_stats64)) {
6947
0
            const struct rtnl_link_stats64 *lstats = nl_attr_get(a);
6948
0
            struct rtnl_link_stats64 aligned_lstats;
6949
6950
0
            if (!IS_PTR_ALIGNED(lstats)) {
6951
0
                memcpy(&aligned_lstats, (void *) lstats,
6952
0
                       sizeof aligned_lstats);
6953
0
                lstats = &aligned_lstats;
6954
0
            }
6955
0
            netdev_stats_from_rtnl_link_stats64(stats, lstats);
6956
0
            error = 0;
6957
0
        } else {
6958
0
            a = nl_attr_find(reply, 0, IFLA_STATS);
6959
0
            if (a && nl_attr_get_size(a) >= sizeof(struct rtnl_link_stats)) {
6960
0
                netdev_stats_from_rtnl_link_stats(stats, nl_attr_get(a));
6961
0
                error = 0;
6962
0
            } else {
6963
0
                VLOG_WARN_RL(&rl, "RTM_GETLINK reply lacks stats");
6964
0
                error = EPROTO;
6965
0
            }
6966
0
        }
6967
0
    } else {
6968
0
        VLOG_WARN_RL(&rl, "short RTM_GETLINK reply");
6969
0
        error = EPROTO;
6970
0
    }
6971
6972
6973
0
    ofpbuf_delete(reply);
6974
0
    return error;
6975
0
}
6976
6977
static int
6978
get_flags(const struct netdev *dev, unsigned int *flags)
6979
0
{
6980
0
    struct ifreq ifr;
6981
0
    int error;
6982
6983
0
    memset(&ifr, 0, sizeof ifr);
6984
0
    *flags = 0;
6985
0
    error = af_inet_ifreq_ioctl(dev->name, &ifr, SIOCGIFFLAGS, "SIOCGIFFLAGS");
6986
0
    if (!error) {
6987
0
        *flags = ifr.ifr_flags;
6988
0
    }
6989
0
    return error;
6990
0
}
6991
6992
static int
6993
set_flags(const char *name, unsigned int flags)
6994
0
{
6995
0
    struct ifreq ifr;
6996
6997
0
    memset(&ifr, 0, sizeof ifr);
6998
0
    ifr.ifr_flags = flags;
6999
0
    return af_inet_ifreq_ioctl(name, &ifr, SIOCSIFFLAGS, "SIOCSIFFLAGS");
7000
0
}
7001
7002
int
7003
linux_get_ifindex(const char *netdev_name)
7004
0
{
7005
0
    struct ifreq ifr;
7006
0
    int error;
7007
7008
0
    memset(&ifr, 0, sizeof ifr);
7009
0
    ovs_strzcpy(ifr.ifr_name, netdev_name, sizeof ifr.ifr_name);
7010
0
    COVERAGE_INC(netdev_get_ifindex);
7011
7012
0
    error = af_inet_ioctl(SIOCGIFINDEX, &ifr);
7013
0
    if (error) {
7014
        /* ENODEV probably means that a vif disappeared asynchronously and
7015
         * hasn't been removed from the database yet, so reduce the log level
7016
         * to INFO for that case. */
7017
0
        VLOG_RL(&rl, error == ENODEV ? VLL_INFO : VLL_ERR,
7018
0
                "ioctl(SIOCGIFINDEX) on %s device failed: %s",
7019
0
                netdev_name, ovs_strerror(error));
7020
0
        return -error;
7021
0
    }
7022
0
    return ifr.ifr_ifindex;
7023
0
}
7024
7025
static int
7026
get_ifindex(const struct netdev *netdev_, int *ifindexp)
7027
0
{
7028
0
    struct netdev_linux *netdev = netdev_linux_cast(netdev_);
7029
7030
0
    if (!(netdev->cache_valid & VALID_IFINDEX)) {
7031
0
        netdev_linux_update_via_netlink(netdev);
7032
0
    }
7033
7034
0
    if (!(netdev->cache_valid & VALID_IFINDEX)) {
7035
        /* Fall back to ioctl if netlink fails */
7036
0
        int ifindex = linux_get_ifindex(netdev_get_name(netdev_));
7037
7038
0
        if (ifindex < 0) {
7039
0
            netdev->get_ifindex_error = -ifindex;
7040
0
            netdev->ifindex = 0;
7041
0
        } else {
7042
0
            netdev->get_ifindex_error = 0;
7043
0
            netdev->ifindex = ifindex;
7044
0
        }
7045
0
        netdev->cache_valid |= VALID_IFINDEX;
7046
0
    }
7047
7048
0
    *ifindexp = netdev->ifindex;
7049
0
    return netdev->get_ifindex_error;
7050
0
}
7051
7052
static int
7053
netdev_linux_update_via_netlink(struct netdev_linux *netdev)
7054
0
{
7055
0
    struct ofpbuf request;
7056
0
    struct ofpbuf *reply;
7057
0
    struct rtnetlink_change chg;
7058
0
    struct rtnetlink_change *change = &chg;
7059
0
    int error;
7060
7061
0
    ofpbuf_init(&request, 0);
7062
0
    nl_msg_put_nlmsghdr(&request,
7063
0
                        sizeof(struct ifinfomsg) + NL_ATTR_SIZE(IFNAMSIZ) +
7064
0
                        NL_A_U32_SIZE, RTM_GETLINK, NLM_F_REQUEST);
7065
0
    ofpbuf_put_zeros(&request, sizeof(struct ifinfomsg));
7066
7067
    /* The correct identifiers for a Linux device are netnsid and ifindex,
7068
     * but ifindex changes as the port is moved to another network namespace
7069
     * and the interface name statically stored in ovsdb. */
7070
0
    nl_msg_put_string(&request, IFLA_IFNAME, netdev_get_name(&netdev->up));
7071
0
    if (netdev_linux_netnsid_is_remote(netdev)) {
7072
0
        nl_msg_put_u32(&request, IFLA_IF_NETNSID, netdev->netnsid);
7073
0
    }
7074
7075
0
    nl_msg_put_u32(&request, IFLA_EXT_MASK, RTEXT_FILTER_SKIP_STATS);
7076
7077
0
    error = nl_transact(NETLINK_ROUTE, &request, &reply);
7078
0
    ofpbuf_uninit(&request);
7079
0
    if (error) {
7080
0
        ofpbuf_delete(reply);
7081
0
        return error;
7082
0
    }
7083
7084
0
    if (rtnetlink_parse(reply, change)
7085
0
        && !change->irrelevant
7086
0
        && change->nlmsg_type == RTM_NEWLINK) {
7087
0
        bool changed = false;
7088
0
        error = 0;
7089
7090
        /* Update netdev from rtnl msg and increment its seq if needed. */
7091
0
        if ((change->ifi_flags ^ netdev->ifi_flags) & IFF_RUNNING) {
7092
0
            netdev->carrier_resets++;
7093
0
            changed = true;
7094
0
        }
7095
0
        if (change->ifi_flags != netdev->ifi_flags) {
7096
0
            netdev->ifi_flags = change->ifi_flags;
7097
0
            changed = true;
7098
0
        }
7099
0
        if (change->mtu && change->mtu != netdev->mtu) {
7100
0
            netdev->mtu = change->mtu;
7101
0
            netdev->cache_valid |= VALID_MTU;
7102
0
            netdev->netdev_mtu_error = 0;
7103
0
            changed = true;
7104
0
        }
7105
0
        if (!eth_addr_is_zero(change->mac)
7106
0
            && !eth_addr_equals(change->mac, netdev->etheraddr)) {
7107
0
            netdev->etheraddr = change->mac;
7108
0
            netdev->cache_valid |= VALID_ETHERADDR;
7109
0
            netdev->ether_addr_error = 0;
7110
0
            changed = true;
7111
0
        }
7112
0
        if (change->if_index != netdev->ifindex) {
7113
0
            netdev->ifindex = change->if_index;
7114
0
            netdev->cache_valid |= VALID_IFINDEX;
7115
0
            netdev->get_ifindex_error = 0;
7116
0
            changed = true;
7117
0
        }
7118
0
        if (change->primary && netdev_linux_kind_is_lag(change->primary)) {
7119
0
            netdev->is_lag_primary = true;
7120
0
        }
7121
0
        if (changed) {
7122
0
            netdev_change_seq_changed(&netdev->up);
7123
0
        }
7124
0
    } else {
7125
0
        error = EINVAL;
7126
0
    }
7127
7128
0
    ofpbuf_delete(reply);
7129
0
    return error;
7130
0
}
7131
7132
static int
7133
get_etheraddr(const char *netdev_name, struct eth_addr *ea)
7134
0
{
7135
0
    struct ifreq ifr;
7136
0
    int hwaddr_family;
7137
0
    int error;
7138
7139
0
    memset(&ifr, 0, sizeof ifr);
7140
0
    ovs_strzcpy(ifr.ifr_name, netdev_name, sizeof ifr.ifr_name);
7141
0
    COVERAGE_INC(netdev_get_hwaddr);
7142
0
    error = af_inet_ioctl(SIOCGIFHWADDR, &ifr);
7143
0
    if (error) {
7144
        /* ENODEV probably means that a vif disappeared asynchronously and
7145
         * hasn't been removed from the database yet, so reduce the log level
7146
         * to INFO for that case. */
7147
0
        VLOG(error == ENODEV ? VLL_INFO : VLL_ERR,
7148
0
             "ioctl(SIOCGIFHWADDR) on %s device failed: %s",
7149
0
             netdev_name, ovs_strerror(error));
7150
0
        return error;
7151
0
    }
7152
0
    hwaddr_family = ifr.ifr_hwaddr.sa_family;
7153
0
    if (hwaddr_family != AF_UNSPEC && hwaddr_family != ARPHRD_ETHER &&
7154
0
        hwaddr_family != ARPHRD_NONE) {
7155
0
        VLOG_INFO("%s device has unknown hardware address family %d",
7156
0
                  netdev_name, hwaddr_family);
7157
0
        return EINVAL;
7158
0
    }
7159
0
    memcpy(ea, ifr.ifr_hwaddr.sa_data, ETH_ADDR_LEN);
7160
0
    return 0;
7161
0
}
7162
7163
static int
7164
set_etheraddr(const char *netdev_name, const struct eth_addr mac)
7165
0
{
7166
0
    struct ifreq ifr;
7167
0
    int error;
7168
7169
0
    memset(&ifr, 0, sizeof ifr);
7170
0
    ovs_strzcpy(ifr.ifr_name, netdev_name, sizeof ifr.ifr_name);
7171
0
    ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
7172
0
    memcpy(ifr.ifr_hwaddr.sa_data, &mac, ETH_ADDR_LEN);
7173
0
    COVERAGE_INC(netdev_set_hwaddr);
7174
0
    error = af_inet_ioctl(SIOCSIFHWADDR, &ifr);
7175
0
    if (error) {
7176
0
        VLOG_ERR("ioctl(SIOCSIFHWADDR) on %s device failed: %s",
7177
0
                 netdev_name, ovs_strerror(error));
7178
0
    }
7179
0
    return error;
7180
0
}
7181
7182
static int
7183
netdev_linux_do_ethtool(const char *name, struct ethtool_cmd *ecmd,
7184
                        int cmd, const char *cmd_name)
7185
0
{
7186
0
    struct ifreq ifr;
7187
0
    int error;
7188
7189
0
    memset(&ifr, 0, sizeof ifr);
7190
0
    ovs_strzcpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
7191
0
    ifr.ifr_data = (caddr_t) ecmd;
7192
7193
0
    ecmd->cmd = cmd;
7194
0
    error = af_inet_ioctl(SIOCETHTOOL, &ifr);
7195
0
    if (error) {
7196
0
        if (error != EOPNOTSUPP) {
7197
0
            VLOG_WARN_RL(&rl, "ethtool command %s on network device %s "
7198
0
                         "failed: %s", cmd_name, name, ovs_strerror(error));
7199
0
        } else {
7200
            /* The device doesn't support this operation.  That's pretty
7201
             * common, so there's no point in logging anything. */
7202
0
        }
7203
0
    }
7204
0
    return error;
7205
0
}
7206
7207
/* Returns an AF_PACKET raw socket or a negative errno value. */
7208
static int
7209
af_packet_sock(void)
7210
0
{
7211
0
    static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER;
7212
0
    static int sock;
7213
7214
0
    if (ovsthread_once_start(&once)) {
7215
0
        sock = socket(AF_PACKET, SOCK_RAW, 0);
7216
0
        if (sock >= 0) {
7217
0
            int error = set_nonblocking(sock);
7218
0
            if (error) {
7219
0
                close(sock);
7220
0
                sock = -error;
7221
0
            } else if (userspace_tso_enabled()) {
7222
0
                int val = 1;
7223
0
                error = setsockopt(sock, SOL_PACKET, PACKET_VNET_HDR, &val,
7224
0
                                   sizeof val);
7225
0
                if (error) {
7226
0
                    error = errno;
7227
0
                    VLOG_ERR("failed to enable vnet hdr in raw socket: %s",
7228
0
                             ovs_strerror(errno));
7229
0
                    close(sock);
7230
0
                    sock = -error;
7231
0
                }
7232
0
            }
7233
0
        } else {
7234
0
            sock = -errno;
7235
0
            VLOG_ERR("failed to create packet socket: %s",
7236
0
                     ovs_strerror(errno));
7237
0
        }
7238
0
        ovsthread_once_done(&once);
7239
0
    }
7240
7241
0
    return sock;
7242
0
}
7243
7244
/* Initializes packet 'b' with features enabled in the prepended
7245
 * struct virtio_net_hdr.  Returns 0 if successful, otherwise a
7246
 * positive errno value. */
7247
static int
7248
netdev_linux_parse_vnet_hdr(struct dp_packet *b)
7249
0
{
7250
0
    struct virtio_net_hdr *vnet = dp_packet_pull(b, sizeof *vnet);
7251
7252
0
    if (OVS_UNLIKELY(!vnet)) {
7253
0
        return EINVAL;
7254
0
    }
7255
7256
0
    if (vnet->flags == 0 && vnet->gso_type == VIRTIO_NET_HDR_GSO_NONE) {
7257
0
        return 0;
7258
0
    }
7259
7260
0
    if (vnet->flags == VIRTIO_NET_HDR_F_NEEDS_CSUM) {
7261
0
        uint16_t csum_offset = (OVS_FORCE uint16_t) vnet->csum_offset;
7262
0
        uint16_t csum_start = (OVS_FORCE uint16_t) vnet->csum_start;
7263
7264
0
        if (csum_start >= dp_packet_size(b)
7265
0
            || csum_start + csum_offset >= dp_packet_size(b)) {
7266
0
            COVERAGE_INC(netdev_linux_invalid_l4_csum);
7267
0
            return EINVAL;
7268
0
        }
7269
7270
0
        parse_tcp_flags(b, NULL, NULL, NULL);
7271
7272
0
        if (csum_start == b->l4_ofs
7273
0
            && ((csum_offset == offsetof(struct tcp_header, tcp_csum)
7274
0
                 && dp_packet_l4_proto_tcp(b))
7275
0
                || (csum_offset == offsetof(struct udp_header, udp_csum)
7276
0
                    && dp_packet_l4_proto_udp(b))
7277
0
                || (csum_offset == offsetof(struct sctp_header, sctp_csum)
7278
0
                    && dp_packet_l4_proto_sctp(b)))) {
7279
0
            dp_packet_l4_checksum_set_partial(b);
7280
0
        } else {
7281
0
            ovs_be16 *csum_l4;
7282
0
            void *l4;
7283
7284
0
            COVERAGE_INC(netdev_linux_unknown_l4_csum);
7285
7286
0
            csum_l4 = dp_packet_at(b, csum_start + csum_offset,
7287
0
                                   sizeof *csum_l4);
7288
0
            if (!csum_l4) {
7289
0
                return EINVAL;
7290
0
            }
7291
7292
0
            l4 = dp_packet_at(b, csum_start, dp_packet_size(b) - csum_start);
7293
0
            *csum_l4 = csum(l4, dp_packet_size(b) - csum_start);
7294
7295
0
            if (dp_packet_l4_proto_tcp(b)
7296
0
                || dp_packet_l4_proto_udp(b)
7297
0
                || dp_packet_l4_proto_sctp(b)) {
7298
0
                dp_packet_l4_checksum_set_good(b);
7299
0
            }
7300
0
        }
7301
0
    }
7302
7303
0
    int ret = 0;
7304
0
    switch (vnet->gso_type) {
7305
0
    case VIRTIO_NET_HDR_GSO_TCPV4:
7306
0
    case VIRTIO_NET_HDR_GSO_TCPV6:
7307
0
        dp_packet_set_tso_segsz(b, (OVS_FORCE uint16_t) vnet->gso_size);
7308
0
        break;
7309
7310
0
    case VIRTIO_NET_HDR_GSO_UDP:
7311
        /* UFO is not supported. */
7312
0
        VLOG_WARN_RL(&rl, "Received an unsupported packet with UFO enabled.");
7313
0
        ret = ENOTSUP;
7314
0
        break;
7315
7316
0
    case VIRTIO_NET_HDR_GSO_NONE:
7317
0
        break;
7318
7319
0
    default:
7320
0
        ret = ENOTSUP;
7321
0
        VLOG_WARN_RL(&rl, "Received an unsupported packet with GSO type: 0x%x",
7322
0
                     vnet->gso_type);
7323
0
    }
7324
7325
0
    return ret;
7326
0
}
7327
7328
/* Prepends struct virtio_net_hdr to packet 'b'.
7329
 * Returns 0 if successful, otherwise a positive errno value.
7330
 * Returns EMSGSIZE if the packet 'b' cannot be sent over MTU 'mtu'. */
7331
static int
7332
netdev_linux_prepend_vnet_hdr(struct dp_packet *b, int mtu)
7333
0
{
7334
0
    struct virtio_net_hdr v;
7335
0
    struct virtio_net_hdr *vnet = &v;
7336
7337
0
    if (dp_packet_get_tso_segsz(b)) {
7338
0
        uint16_t tso_segsz = dp_packet_get_tso_segsz(b);
7339
0
        const struct tcp_header *tcp;
7340
0
        const struct ip_header *ip;
7341
0
        if (dp_packet_inner_l4(b)) {
7342
0
            tcp = dp_packet_inner_l4(b);
7343
0
            ip = dp_packet_inner_l3(b);
7344
0
        } else {
7345
0
            tcp = dp_packet_l4(b);
7346
0
            ip = dp_packet_l3(b);
7347
0
        }
7348
0
        int tcp_hdr_len = TCP_OFFSET(tcp->tcp_ctl) * 4;
7349
0
        int hdr_len = ((char *) tcp - (char *) dp_packet_eth(b))
7350
0
                      + tcp_hdr_len;
7351
0
        int max_packet_len = mtu + ETH_HEADER_LEN + VLAN_HEADER_LEN;
7352
7353
0
        if (OVS_UNLIKELY((hdr_len + tso_segsz) > max_packet_len)) {
7354
0
            VLOG_WARN_RL(&rl, "Oversized TSO packet. hdr_len: %"PRIu32", "
7355
0
                         "gso: %"PRIu16", max length: %"PRIu32".", hdr_len,
7356
0
                         tso_segsz, max_packet_len);
7357
0
            return EMSGSIZE;
7358
0
        }
7359
7360
0
        vnet->hdr_len = (OVS_FORCE __virtio16)hdr_len;
7361
0
        vnet->gso_size = (OVS_FORCE __virtio16)(tso_segsz);
7362
0
        if (IP_VER(ip->ip_ihl_ver) == 4) {
7363
0
            vnet->gso_type = VIRTIO_NET_HDR_GSO_TCPV4;
7364
0
        } else if (IP_VER(ip->ip_ihl_ver) == 6) {
7365
0
            vnet->gso_type = VIRTIO_NET_HDR_GSO_TCPV6;
7366
0
        } else {
7367
0
            VLOG_ERR_RL(&rl, "Unknown gso_type for TSO packet. "
7368
0
                        "Offloads: %"PRIu32, b->offloads);
7369
0
            return EINVAL;
7370
0
        }
7371
0
    } else {
7372
0
        vnet->hdr_len = 0;
7373
0
        vnet->gso_size = 0;
7374
0
        vnet->gso_type = VIRTIO_NET_HDR_GSO_NONE;
7375
0
    }
7376
7377
0
    if (dp_packet_l4_checksum_good(b)
7378
0
        && (!dp_packet_tunnel(b)
7379
0
            || dp_packet_inner_l4_checksum_good(b))) {
7380
        /* The packet has good L4 checksum. No need to validate again. */
7381
0
        vnet->csum_start = vnet->csum_offset = (OVS_FORCE __virtio16) 0;
7382
0
        vnet->flags = VIRTIO_NET_HDR_F_DATA_VALID;
7383
0
    } else if (dp_packet_l4_checksum_partial(b)
7384
0
               || dp_packet_inner_l4_checksum_partial(b)) {
7385
0
        const struct ip_header *ip_hdr;
7386
0
        void *l3_off;
7387
0
        void *l4_off;
7388
0
        bool is_sctp;
7389
0
        bool is_tcp;
7390
0
        bool is_udp;
7391
7392
0
        if (dp_packet_inner_l4_checksum_partial(b)) {
7393
0
            l3_off = dp_packet_inner_l3(b);
7394
0
            l4_off = dp_packet_inner_l4(b);
7395
0
            is_tcp = dp_packet_inner_l4_proto_tcp(b);
7396
0
            is_udp = dp_packet_inner_l4_proto_udp(b);
7397
0
            is_sctp = dp_packet_inner_l4_proto_sctp(b);
7398
0
        } else {
7399
0
            l3_off = dp_packet_l3(b);
7400
0
            l4_off = dp_packet_l4(b);
7401
0
            is_tcp = dp_packet_l4_proto_tcp(b);
7402
0
            is_udp = dp_packet_l4_proto_udp(b);
7403
0
            is_sctp = dp_packet_l4_proto_sctp(b);
7404
0
        }
7405
0
        ip_hdr = l3_off;
7406
7407
        /* The csum calculation is offloaded. */
7408
0
        if (is_tcp) {
7409
            /* Virtual I/O Device (VIRTIO) Version 1.1
7410
             * 5.1.6.2 Packet Transmission
7411
             * If the driver negotiated VIRTIO_NET_F_CSUM, it can skip
7412
             * checksumming the packet:
7413
             *  - flags has the VIRTIO_NET_HDR_F_NEEDS_CSUM set,
7414
             *  - csum_start is set to the offset within the packet
7415
             *    to begin checksumming, and
7416
             *  - csum_offset indicates how many bytes after the
7417
             *    csum_start the new (16 bit ones complement) checksum
7418
             *    is placed by the device.
7419
             * The TCP checksum field in the packet is set to the sum of
7420
             * the TCP pseudo header, so that replacing it by the ones
7421
             * complement checksum of the TCP header and body will give
7422
             * the correct result. */
7423
0
            struct tcp_header *tcp_hdr = l4_off;
7424
0
            ovs_be16 csum = 0;
7425
7426
0
            if (IP_VER(ip_hdr->ip_ihl_ver) == 4) {
7427
0
                csum = ~csum_finish(packet_csum_pseudoheader(ip_hdr));
7428
0
            } else if (IP_VER(ip_hdr->ip_ihl_ver) == 6) {
7429
0
                const struct ovs_16aligned_ip6_hdr *ip6_hdr = l3_off;
7430
0
                csum = ~csum_finish(packet_csum_pseudoheader6(ip6_hdr));
7431
0
            }
7432
7433
0
            tcp_hdr->tcp_csum = csum;
7434
0
            vnet->flags = VIRTIO_NET_HDR_F_NEEDS_CSUM;
7435
0
            vnet->csum_start = (OVS_FORCE __virtio16) ((char *) l4_off -
7436
0
                                    (char *) dp_packet_data(b));
7437
0
            vnet->csum_offset = (OVS_FORCE __virtio16) __builtin_offsetof(
7438
0
                                    struct tcp_header, tcp_csum);
7439
0
        } else if (is_udp) {
7440
0
            struct udp_header *udp_hdr = l4_off;
7441
0
            ovs_be16 csum = 0;
7442
7443
0
            if (IP_VER(ip_hdr->ip_ihl_ver) == 4) {
7444
0
                csum = ~csum_finish(packet_csum_pseudoheader(ip_hdr));
7445
0
            } else if (IP_VER(ip_hdr->ip_ihl_ver) == 6) {
7446
0
                const struct ovs_16aligned_ip6_hdr *ip6_hdr = l3_off;
7447
0
                csum = ~csum_finish(packet_csum_pseudoheader6(ip6_hdr));
7448
0
            }
7449
7450
0
            udp_hdr->udp_csum = csum;
7451
0
            vnet->flags = VIRTIO_NET_HDR_F_NEEDS_CSUM;
7452
0
            vnet->csum_start = (OVS_FORCE __virtio16) ((char *) udp_hdr -
7453
0
                                    (char *) dp_packet_data(b));;
7454
0
            vnet->csum_offset = (OVS_FORCE __virtio16) __builtin_offsetof(
7455
0
                                    struct udp_header, udp_csum);
7456
0
        } else if (is_sctp) {
7457
            /* The Linux kernel networking stack only supports csum_start
7458
             * and csum_offset when SCTP GSO is enabled.  See kernel's
7459
             * skb_csum_hwoffload_help(). Currently there is no SCTP
7460
             * segmentation offload support in OVS. */
7461
0
            vnet->csum_start = vnet->csum_offset = (OVS_FORCE __virtio16) 0;
7462
0
            vnet->flags = 0;
7463
0
        } else {
7464
            /* This should only happen when a new L4 proto
7465
             * is not covered in above checks. */
7466
0
            VLOG_WARN_RL(&rl, "Unsupported L4 checksum offload. "
7467
0
                         "Offloads: %"PRIu32, b->offloads);
7468
0
            vnet->csum_start = vnet->csum_offset = (OVS_FORCE __virtio16) 0;
7469
0
            vnet->flags = 0;
7470
0
        }
7471
0
    } else {
7472
        /* Packet L4 csum is unknown. */
7473
0
        vnet->csum_start = vnet->csum_offset = (OVS_FORCE __virtio16) 0;
7474
0
        vnet->flags = 0;
7475
0
    }
7476
7477
0
    dp_packet_push(b, vnet, sizeof *vnet);
7478
0
    return 0;
7479
0
}