aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/macvlan.c37
-rw-r--r--include/linux/if_macvlan.h19
2 files changed, 35 insertions, 21 deletions
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index e096875aa055..e6d626e78515 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -431,29 +431,38 @@ static void macvlan_uninit(struct net_device *dev)
431 free_percpu(vlan->rx_stats); 431 free_percpu(vlan->rx_stats);
432} 432}
433 433
434static struct net_device_stats *macvlan_dev_get_stats(struct net_device *dev) 434static struct rtnl_link_stats64 *macvlan_dev_get_stats64(struct net_device *dev)
435{ 435{
436 struct net_device_stats *stats = &dev->stats; 436 struct rtnl_link_stats64 *stats = &dev->stats64;
437 struct macvlan_dev *vlan = netdev_priv(dev); 437 struct macvlan_dev *vlan = netdev_priv(dev);
438 438
439 dev_txq_stats_fold(dev, stats); 439 dev_txq_stats_fold(dev, &dev->stats);
440 440
441 if (vlan->rx_stats) { 441 if (vlan->rx_stats) {
442 struct macvlan_rx_stats *p, rx = {0}; 442 struct macvlan_rx_stats *p, accum = {0};
443 u64 rx_packets, rx_bytes, rx_multicast;
444 unsigned int start;
443 int i; 445 int i;
444 446
445 for_each_possible_cpu(i) { 447 for_each_possible_cpu(i) {
446 p = per_cpu_ptr(vlan->rx_stats, i); 448 p = per_cpu_ptr(vlan->rx_stats, i);
447 rx.rx_packets += p->rx_packets; 449 do {
448 rx.rx_bytes += p->rx_bytes; 450 start = u64_stats_fetch_begin_bh(&p->syncp);
449 rx.rx_errors += p->rx_errors; 451 rx_packets = p->rx_packets;
450 rx.multicast += p->multicast; 452 rx_bytes = p->rx_bytes;
453 rx_multicast = p->rx_multicast;
454 } while (u64_stats_fetch_retry_bh(&p->syncp, start));
455 accum.rx_packets += rx_packets;
456 accum.rx_bytes += rx_bytes;
457 accum.rx_multicast += rx_multicast;
458 /* rx_errors is an ulong, updated without syncp protection */
459 accum.rx_errors += p->rx_errors;
451 } 460 }
452 stats->rx_packets = rx.rx_packets; 461 stats->rx_packets = accum.rx_packets;
453 stats->rx_bytes = rx.rx_bytes; 462 stats->rx_bytes = accum.rx_bytes;
454 stats->rx_errors = rx.rx_errors; 463 stats->rx_errors = accum.rx_errors;
455 stats->rx_dropped = rx.rx_errors; 464 stats->rx_dropped = accum.rx_errors;
456 stats->multicast = rx.multicast; 465 stats->multicast = accum.rx_multicast;
457 } 466 }
458 return stats; 467 return stats;
459} 468}
@@ -502,7 +511,7 @@ static const struct net_device_ops macvlan_netdev_ops = {
502 .ndo_change_rx_flags = macvlan_change_rx_flags, 511 .ndo_change_rx_flags = macvlan_change_rx_flags,
503 .ndo_set_mac_address = macvlan_set_mac_address, 512 .ndo_set_mac_address = macvlan_set_mac_address,
504 .ndo_set_multicast_list = macvlan_set_multicast_list, 513 .ndo_set_multicast_list = macvlan_set_multicast_list,
505 .ndo_get_stats = macvlan_dev_get_stats, 514 .ndo_get_stats64 = macvlan_dev_get_stats64,
506 .ndo_validate_addr = eth_validate_addr, 515 .ndo_validate_addr = eth_validate_addr,
507}; 516};
508 517
diff --git a/include/linux/if_macvlan.h b/include/linux/if_macvlan.h
index c26a0e4f0ce8..e24ce6ea1fa3 100644
--- a/include/linux/if_macvlan.h
+++ b/include/linux/if_macvlan.h
@@ -6,6 +6,7 @@
6#include <linux/netdevice.h> 6#include <linux/netdevice.h>
7#include <linux/netlink.h> 7#include <linux/netlink.h>
8#include <net/netlink.h> 8#include <net/netlink.h>
9#include <linux/u64_stats_sync.h>
9 10
10#if defined(CONFIG_MACVTAP) || defined(CONFIG_MACVTAP_MODULE) 11#if defined(CONFIG_MACVTAP) || defined(CONFIG_MACVTAP_MODULE)
11struct socket *macvtap_get_socket(struct file *); 12struct socket *macvtap_get_socket(struct file *);
@@ -27,14 +28,16 @@ struct macvtap_queue;
27 * struct macvlan_rx_stats - MACVLAN percpu rx stats 28 * struct macvlan_rx_stats - MACVLAN percpu rx stats
28 * @rx_packets: number of received packets 29 * @rx_packets: number of received packets
29 * @rx_bytes: number of received bytes 30 * @rx_bytes: number of received bytes
30 * @multicast: number of received multicast packets 31 * @rx_multicast: number of received multicast packets
32 * @syncp: synchronization point for 64bit counters
31 * @rx_errors: number of errors 33 * @rx_errors: number of errors
32 */ 34 */
33struct macvlan_rx_stats { 35struct macvlan_rx_stats {
34 unsigned long rx_packets; 36 u64 rx_packets;
35 unsigned long rx_bytes; 37 u64 rx_bytes;
36 unsigned long multicast; 38 u64 rx_multicast;
37 unsigned long rx_errors; 39 struct u64_stats_sync syncp;
40 unsigned long rx_errors;
38}; 41};
39 42
40struct macvlan_dev { 43struct macvlan_dev {
@@ -56,12 +59,14 @@ static inline void macvlan_count_rx(const struct macvlan_dev *vlan,
56{ 59{
57 struct macvlan_rx_stats *rx_stats; 60 struct macvlan_rx_stats *rx_stats;
58 61
59 rx_stats = per_cpu_ptr(vlan->rx_stats, smp_processor_id()); 62 rx_stats = this_cpu_ptr(vlan->rx_stats);
60 if (likely(success)) { 63 if (likely(success)) {
64 u64_stats_update_begin(&rx_stats->syncp);
61 rx_stats->rx_packets++;; 65 rx_stats->rx_packets++;;
62 rx_stats->rx_bytes += len; 66 rx_stats->rx_bytes += len;
63 if (multicast) 67 if (multicast)
64 rx_stats->multicast++; 68 rx_stats->rx_multicast++;
69 u64_stats_update_end(&rx_stats->syncp);
65 } else { 70 } else {
66 rx_stats->rx_errors++; 71 rx_stats->rx_errors++;
67 } 72 }