aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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