Skip to content

Commit 8ffab51

Browse files
Eric Dumazetdavem330
authored andcommitted
macvlan: lockless tx path
macvlan is a stacked device, like tunnels. We should use the lockless mechanism we are using in tunnels and loopback. This patch completely removes locking in TX path. tx stat counters are added into existing percpu stat structure, renamed from rx_stats to pcpu_stats. Note : this reverts commit 2c11455 (macvlan: add multiqueue capability) Note : rx_errors converted to a 32bit counter, like tx_dropped, since they dont need 64bit range. Signed-off-by: Eric Dumazet <[email protected]> Cc: Patrick McHardy <[email protected]> Cc: Ben Greear <[email protected]> Cc: Ben Hutchings <[email protected]> Acked-by: Patrick McHardy <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 0e3125c commit 8ffab51

File tree

2 files changed

+55
-59
lines changed

2 files changed

+55
-59
lines changed

drivers/net/macvlan.c

Lines changed: 35 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -243,18 +243,22 @@ static int macvlan_queue_xmit(struct sk_buff *skb, struct net_device *dev)
243243
netdev_tx_t macvlan_start_xmit(struct sk_buff *skb,
244244
struct net_device *dev)
245245
{
246-
int i = skb_get_queue_mapping(skb);
247-
struct netdev_queue *txq = netdev_get_tx_queue(dev, i);
248246
unsigned int len = skb->len;
249247
int ret;
248+
const struct macvlan_dev *vlan = netdev_priv(dev);
250249

251250
ret = macvlan_queue_xmit(skb, dev);
252251
if (likely(ret == NET_XMIT_SUCCESS || ret == NET_XMIT_CN)) {
253-
txq->tx_packets++;
254-
txq->tx_bytes += len;
255-
} else
256-
txq->tx_dropped++;
252+
struct macvlan_pcpu_stats *pcpu_stats;
257253

254+
pcpu_stats = this_cpu_ptr(vlan->pcpu_stats);
255+
u64_stats_update_begin(&pcpu_stats->syncp);
256+
pcpu_stats->tx_packets++;
257+
pcpu_stats->tx_bytes += len;
258+
u64_stats_update_end(&pcpu_stats->syncp);
259+
} else {
260+
this_cpu_inc(vlan->pcpu_stats->tx_dropped);
261+
}
258262
return ret;
259263
}
260264
EXPORT_SYMBOL_GPL(macvlan_start_xmit);
@@ -414,14 +418,15 @@ static int macvlan_init(struct net_device *dev)
414418
dev->state = (dev->state & ~MACVLAN_STATE_MASK) |
415419
(lowerdev->state & MACVLAN_STATE_MASK);
416420
dev->features = lowerdev->features & MACVLAN_FEATURES;
421+
dev->features |= NETIF_F_LLTX;
417422
dev->gso_max_size = lowerdev->gso_max_size;
418423
dev->iflink = lowerdev->ifindex;
419424
dev->hard_header_len = lowerdev->hard_header_len;
420425

421426
macvlan_set_lockdep_class(dev);
422427

423-
vlan->rx_stats = alloc_percpu(struct macvlan_rx_stats);
424-
if (!vlan->rx_stats)
428+
vlan->pcpu_stats = alloc_percpu(struct macvlan_pcpu_stats);
429+
if (!vlan->pcpu_stats)
425430
return -ENOMEM;
426431

427432
return 0;
@@ -431,41 +436,46 @@ static void macvlan_uninit(struct net_device *dev)
431436
{
432437
struct macvlan_dev *vlan = netdev_priv(dev);
433438

434-
free_percpu(vlan->rx_stats);
439+
free_percpu(vlan->pcpu_stats);
435440
}
436441

437442
static struct rtnl_link_stats64 *macvlan_dev_get_stats64(struct net_device *dev,
438443
struct rtnl_link_stats64 *stats)
439444
{
440445
struct macvlan_dev *vlan = netdev_priv(dev);
441446

442-
dev_txq_stats_fold(dev, stats);
443-
444-
if (vlan->rx_stats) {
445-
struct macvlan_rx_stats *p, accum = {0};
446-
u64 rx_packets, rx_bytes, rx_multicast;
447+
if (vlan->pcpu_stats) {
448+
struct macvlan_pcpu_stats *p;
449+
u64 rx_packets, rx_bytes, rx_multicast, tx_packets, tx_bytes;
450+
u32 rx_errors = 0, tx_dropped = 0;
447451
unsigned int start;
448452
int i;
449453

450454
for_each_possible_cpu(i) {
451-
p = per_cpu_ptr(vlan->rx_stats, i);
455+
p = per_cpu_ptr(vlan->pcpu_stats, i);
452456
do {
453457
start = u64_stats_fetch_begin_bh(&p->syncp);
454458
rx_packets = p->rx_packets;
455459
rx_bytes = p->rx_bytes;
456460
rx_multicast = p->rx_multicast;
461+
tx_packets = p->tx_packets;
462+
tx_bytes = p->tx_bytes;
457463
} while (u64_stats_fetch_retry_bh(&p->syncp, start));
458-
accum.rx_packets += rx_packets;
459-
accum.rx_bytes += rx_bytes;
460-
accum.rx_multicast += rx_multicast;
461-
/* rx_errors is an ulong, updated without syncp protection */
462-
accum.rx_errors += p->rx_errors;
464+
465+
stats->rx_packets += rx_packets;
466+
stats->rx_bytes += rx_bytes;
467+
stats->multicast += rx_multicast;
468+
stats->tx_packets += tx_packets;
469+
stats->tx_bytes += tx_bytes;
470+
/* rx_errors & tx_dropped are u32, updated
471+
* without syncp protection.
472+
*/
473+
rx_errors += p->rx_errors;
474+
tx_dropped += p->tx_dropped;
463475
}
464-
stats->rx_packets = accum.rx_packets;
465-
stats->rx_bytes = accum.rx_bytes;
466-
stats->rx_errors = accum.rx_errors;
467-
stats->rx_dropped = accum.rx_errors;
468-
stats->multicast = accum.rx_multicast;
476+
stats->rx_errors = rx_errors;
477+
stats->rx_dropped = rx_errors;
478+
stats->tx_dropped = tx_dropped;
469479
}
470480
return stats;
471481
}
@@ -601,25 +611,6 @@ static int macvlan_validate(struct nlattr *tb[], struct nlattr *data[])
601611
return 0;
602612
}
603613

604-
static int macvlan_get_tx_queues(struct net *net,
605-
struct nlattr *tb[],
606-
unsigned int *num_tx_queues,
607-
unsigned int *real_num_tx_queues)
608-
{
609-
struct net_device *real_dev;
610-
611-
if (!tb[IFLA_LINK])
612-
return -EINVAL;
613-
614-
real_dev = __dev_get_by_index(net, nla_get_u32(tb[IFLA_LINK]));
615-
if (!real_dev)
616-
return -ENODEV;
617-
618-
*num_tx_queues = real_dev->num_tx_queues;
619-
*real_num_tx_queues = real_dev->real_num_tx_queues;
620-
return 0;
621-
}
622-
623614
int macvlan_common_newlink(struct net *src_net, struct net_device *dev,
624615
struct nlattr *tb[], struct nlattr *data[],
625616
int (*receive)(struct sk_buff *skb),
@@ -743,7 +734,6 @@ int macvlan_link_register(struct rtnl_link_ops *ops)
743734
{
744735
/* common fields */
745736
ops->priv_size = sizeof(struct macvlan_dev);
746-
ops->get_tx_queues = macvlan_get_tx_queues;
747737
ops->validate = macvlan_validate;
748738
ops->maxtype = IFLA_MACVLAN_MAX;
749739
ops->policy = macvlan_policy;

include/linux/if_macvlan.h

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -25,19 +25,25 @@ struct macvlan_port;
2525
struct macvtap_queue;
2626

2727
/**
28-
* struct macvlan_rx_stats - MACVLAN percpu rx stats
28+
* struct macvlan_pcpu_stats - MACVLAN percpu stats
2929
* @rx_packets: number of received packets
3030
* @rx_bytes: number of received bytes
3131
* @rx_multicast: number of received multicast packets
32+
* @tx_packets: number of transmitted packets
33+
* @tx_bytes: number of transmitted bytes
3234
* @syncp: synchronization point for 64bit counters
33-
* @rx_errors: number of errors
35+
* @rx_errors: number of rx errors
36+
* @tx_dropped: number of tx dropped packets
3437
*/
35-
struct macvlan_rx_stats {
38+
struct macvlan_pcpu_stats {
3639
u64 rx_packets;
3740
u64 rx_bytes;
3841
u64 rx_multicast;
42+
u64 tx_packets;
43+
u64 tx_bytes;
3944
struct u64_stats_sync syncp;
40-
unsigned long rx_errors;
45+
u32 rx_errors;
46+
u32 tx_dropped;
4147
};
4248

4349
/*
@@ -52,7 +58,7 @@ struct macvlan_dev {
5258
struct hlist_node hlist;
5359
struct macvlan_port *port;
5460
struct net_device *lowerdev;
55-
struct macvlan_rx_stats __percpu *rx_stats;
61+
struct macvlan_pcpu_stats __percpu *pcpu_stats;
5662
enum macvlan_mode mode;
5763
int (*receive)(struct sk_buff *skb);
5864
int (*forward)(struct net_device *dev, struct sk_buff *skb);
@@ -64,18 +70,18 @@ static inline void macvlan_count_rx(const struct macvlan_dev *vlan,
6470
unsigned int len, bool success,
6571
bool multicast)
6672
{
67-
struct macvlan_rx_stats *rx_stats;
68-
69-
rx_stats = this_cpu_ptr(vlan->rx_stats);
7073
if (likely(success)) {
71-
u64_stats_update_begin(&rx_stats->syncp);
72-
rx_stats->rx_packets++;
73-
rx_stats->rx_bytes += len;
74+
struct macvlan_pcpu_stats *pcpu_stats;
75+
76+
pcpu_stats = this_cpu_ptr(vlan->pcpu_stats);
77+
u64_stats_update_begin(&pcpu_stats->syncp);
78+
pcpu_stats->rx_packets++;
79+
pcpu_stats->rx_bytes += len;
7480
if (multicast)
75-
rx_stats->rx_multicast++;
76-
u64_stats_update_end(&rx_stats->syncp);
81+
pcpu_stats->rx_multicast++;
82+
u64_stats_update_end(&pcpu_stats->syncp);
7783
} else {
78-
rx_stats->rx_errors++;
84+
this_cpu_inc(vlan->pcpu_stats->rx_errors);
7985
}
8086
}
8187

0 commit comments

Comments
 (0)