aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Dumazet <eric.dumazet@gmail.com>2010-11-10 16:14:04 -0500
committerDavid S. Miller <davem@davemloft.net>2010-11-16 13:58:30 -0500
commit8ffab51b3dfc54876f145f15b351c41f3f703195 (patch)
tree0455321fbdb953e77fecff62345f8414553bc394
parent0e3125c755445664f00ad036e4fc2cd32fd52877 (diff)
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 2c11455321f37 (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 <eric.dumazet@gmail.com> Cc: Patrick McHardy <kaber@trash.net> Cc: Ben Greear <greearb@candelatech.com> Cc: Ben Hutchings <bhutchings@solarflare.com> Acked-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/macvlan.c80
-rw-r--r--include/linux/if_macvlan.h34
2 files changed, 55 insertions, 59 deletions
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index 0fc9dc7f20db..93f0ba25c808 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -243,18 +243,22 @@ xmit_world:
243netdev_tx_t macvlan_start_xmit(struct sk_buff *skb, 243netdev_tx_t macvlan_start_xmit(struct sk_buff *skb,
244 struct net_device *dev) 244 struct net_device *dev)
245{ 245{
246 int i = skb_get_queue_mapping(skb);
247 struct netdev_queue *txq = netdev_get_tx_queue(dev, i);
248 unsigned int len = skb->len; 246 unsigned int len = skb->len;
249 int ret; 247 int ret;
248 const struct macvlan_dev *vlan = netdev_priv(dev);
250 249
251 ret = macvlan_queue_xmit(skb, dev); 250 ret = macvlan_queue_xmit(skb, dev);
252 if (likely(ret == NET_XMIT_SUCCESS || ret == NET_XMIT_CN)) { 251 if (likely(ret == NET_XMIT_SUCCESS || ret == NET_XMIT_CN)) {
253 txq->tx_packets++; 252 struct macvlan_pcpu_stats *pcpu_stats;
254 txq->tx_bytes += len;
255 } else
256 txq->tx_dropped++;
257 253
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 }
258 return ret; 262 return ret;
259} 263}
260EXPORT_SYMBOL_GPL(macvlan_start_xmit); 264EXPORT_SYMBOL_GPL(macvlan_start_xmit);
@@ -414,14 +418,15 @@ static int macvlan_init(struct net_device *dev)
414 dev->state = (dev->state & ~MACVLAN_STATE_MASK) | 418 dev->state = (dev->state & ~MACVLAN_STATE_MASK) |
415 (lowerdev->state & MACVLAN_STATE_MASK); 419 (lowerdev->state & MACVLAN_STATE_MASK);
416 dev->features = lowerdev->features & MACVLAN_FEATURES; 420 dev->features = lowerdev->features & MACVLAN_FEATURES;
421 dev->features |= NETIF_F_LLTX;
417 dev->gso_max_size = lowerdev->gso_max_size; 422 dev->gso_max_size = lowerdev->gso_max_size;
418 dev->iflink = lowerdev->ifindex; 423 dev->iflink = lowerdev->ifindex;
419 dev->hard_header_len = lowerdev->hard_header_len; 424 dev->hard_header_len = lowerdev->hard_header_len;
420 425
421 macvlan_set_lockdep_class(dev); 426 macvlan_set_lockdep_class(dev);
422 427
423 vlan->rx_stats = alloc_percpu(struct macvlan_rx_stats); 428 vlan->pcpu_stats = alloc_percpu(struct macvlan_pcpu_stats);
424 if (!vlan->rx_stats) 429 if (!vlan->pcpu_stats)
425 return -ENOMEM; 430 return -ENOMEM;
426 431
427 return 0; 432 return 0;
@@ -431,7 +436,7 @@ static void macvlan_uninit(struct net_device *dev)
431{ 436{
432 struct macvlan_dev *vlan = netdev_priv(dev); 437 struct macvlan_dev *vlan = netdev_priv(dev);
433 438
434 free_percpu(vlan->rx_stats); 439 free_percpu(vlan->pcpu_stats);
435} 440}
436 441
437static struct rtnl_link_stats64 *macvlan_dev_get_stats64(struct net_device *dev, 442static struct rtnl_link_stats64 *macvlan_dev_get_stats64(struct net_device *dev,
@@ -439,33 +444,38 @@ static struct rtnl_link_stats64 *macvlan_dev_get_stats64(struct net_device *dev,
439{ 444{
440 struct macvlan_dev *vlan = netdev_priv(dev); 445 struct macvlan_dev *vlan = netdev_priv(dev);
441 446
442 dev_txq_stats_fold(dev, stats); 447 if (vlan->pcpu_stats) {
443 448 struct macvlan_pcpu_stats *p;
444 if (vlan->rx_stats) { 449 u64 rx_packets, rx_bytes, rx_multicast, tx_packets, tx_bytes;
445 struct macvlan_rx_stats *p, accum = {0}; 450 u32 rx_errors = 0, tx_dropped = 0;
446 u64 rx_packets, rx_bytes, rx_multicast;
447 unsigned int start; 451 unsigned int start;
448 int i; 452 int i;
449 453
450 for_each_possible_cpu(i) { 454 for_each_possible_cpu(i) {
451 p = per_cpu_ptr(vlan->rx_stats, i); 455 p = per_cpu_ptr(vlan->pcpu_stats, i);
452 do { 456 do {
453 start = u64_stats_fetch_begin_bh(&p->syncp); 457 start = u64_stats_fetch_begin_bh(&p->syncp);
454 rx_packets = p->rx_packets; 458 rx_packets = p->rx_packets;
455 rx_bytes = p->rx_bytes; 459 rx_bytes = p->rx_bytes;
456 rx_multicast = p->rx_multicast; 460 rx_multicast = p->rx_multicast;
461 tx_packets = p->tx_packets;
462 tx_bytes = p->tx_bytes;
457 } while (u64_stats_fetch_retry_bh(&p->syncp, start)); 463 } while (u64_stats_fetch_retry_bh(&p->syncp, start));
458 accum.rx_packets += rx_packets; 464
459 accum.rx_bytes += rx_bytes; 465 stats->rx_packets += rx_packets;
460 accum.rx_multicast += rx_multicast; 466 stats->rx_bytes += rx_bytes;
461 /* rx_errors is an ulong, updated without syncp protection */ 467 stats->multicast += rx_multicast;
462 accum.rx_errors += p->rx_errors; 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;
463 } 475 }
464 stats->rx_packets = accum.rx_packets; 476 stats->rx_errors = rx_errors;
465 stats->rx_bytes = accum.rx_bytes; 477 stats->rx_dropped = rx_errors;
466 stats->rx_errors = accum.rx_errors; 478 stats->tx_dropped = tx_dropped;
467 stats->rx_dropped = accum.rx_errors;
468 stats->multicast = accum.rx_multicast;
469 } 479 }
470 return stats; 480 return stats;
471} 481}
@@ -601,25 +611,6 @@ static int macvlan_validate(struct nlattr *tb[], struct nlattr *data[])
601 return 0; 611 return 0;
602} 612}
603 613
604static 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
623int macvlan_common_newlink(struct net *src_net, struct net_device *dev, 614int macvlan_common_newlink(struct net *src_net, struct net_device *dev,
624 struct nlattr *tb[], struct nlattr *data[], 615 struct nlattr *tb[], struct nlattr *data[],
625 int (*receive)(struct sk_buff *skb), 616 int (*receive)(struct sk_buff *skb),
@@ -743,7 +734,6 @@ int macvlan_link_register(struct rtnl_link_ops *ops)
743{ 734{
744 /* common fields */ 735 /* common fields */
745 ops->priv_size = sizeof(struct macvlan_dev); 736 ops->priv_size = sizeof(struct macvlan_dev);
746 ops->get_tx_queues = macvlan_get_tx_queues;
747 ops->validate = macvlan_validate; 737 ops->validate = macvlan_validate;
748 ops->maxtype = IFLA_MACVLAN_MAX; 738 ops->maxtype = IFLA_MACVLAN_MAX;
749 ops->policy = macvlan_policy; 739 ops->policy = macvlan_policy;
diff --git a/include/linux/if_macvlan.h b/include/linux/if_macvlan.h
index ac96a2d76291..e28b2e4959d4 100644
--- a/include/linux/if_macvlan.h
+++ b/include/linux/if_macvlan.h
@@ -25,19 +25,25 @@ struct macvlan_port;
25struct macvtap_queue; 25struct macvtap_queue;
26 26
27/** 27/**
28 * struct macvlan_rx_stats - MACVLAN percpu rx stats 28 * struct macvlan_pcpu_stats - MACVLAN percpu stats
29 * @rx_packets: number of received packets 29 * @rx_packets: number of received packets
30 * @rx_bytes: number of received bytes 30 * @rx_bytes: number of received bytes
31 * @rx_multicast: number of received multicast packets 31 * @rx_multicast: number of received multicast packets
32 * @tx_packets: number of transmitted packets
33 * @tx_bytes: number of transmitted bytes
32 * @syncp: synchronization point for 64bit counters 34 * @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
34 */ 37 */
35struct macvlan_rx_stats { 38struct macvlan_pcpu_stats {
36 u64 rx_packets; 39 u64 rx_packets;
37 u64 rx_bytes; 40 u64 rx_bytes;
38 u64 rx_multicast; 41 u64 rx_multicast;
42 u64 tx_packets;
43 u64 tx_bytes;
39 struct u64_stats_sync syncp; 44 struct u64_stats_sync syncp;
40 unsigned long rx_errors; 45 u32 rx_errors;
46 u32 tx_dropped;
41}; 47};
42 48
43/* 49/*
@@ -52,7 +58,7 @@ struct macvlan_dev {
52 struct hlist_node hlist; 58 struct hlist_node hlist;
53 struct macvlan_port *port; 59 struct macvlan_port *port;
54 struct net_device *lowerdev; 60 struct net_device *lowerdev;
55 struct macvlan_rx_stats __percpu *rx_stats; 61 struct macvlan_pcpu_stats __percpu *pcpu_stats;
56 enum macvlan_mode mode; 62 enum macvlan_mode mode;
57 int (*receive)(struct sk_buff *skb); 63 int (*receive)(struct sk_buff *skb);
58 int (*forward)(struct net_device *dev, struct sk_buff *skb); 64 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,
64 unsigned int len, bool success, 70 unsigned int len, bool success,
65 bool multicast) 71 bool multicast)
66{ 72{
67 struct macvlan_rx_stats *rx_stats;
68
69 rx_stats = this_cpu_ptr(vlan->rx_stats);
70 if (likely(success)) { 73 if (likely(success)) {
71 u64_stats_update_begin(&rx_stats->syncp); 74 struct macvlan_pcpu_stats *pcpu_stats;
72 rx_stats->rx_packets++; 75
73 rx_stats->rx_bytes += len; 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;
74 if (multicast) 80 if (multicast)
75 rx_stats->rx_multicast++; 81 pcpu_stats->rx_multicast++;
76 u64_stats_update_end(&rx_stats->syncp); 82 u64_stats_update_end(&pcpu_stats->syncp);
77 } else { 83 } else {
78 rx_stats->rx_errors++; 84 this_cpu_inc(vlan->pcpu_stats->rx_errors);
79 } 85 }
80} 86}
81 87