diff options
-rw-r--r-- | drivers/net/macvlan.c | 80 | ||||
-rw-r--r-- | include/linux/if_macvlan.h | 34 |
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: | |||
243 | netdev_tx_t macvlan_start_xmit(struct sk_buff *skb, | 243 | netdev_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 | } |
260 | EXPORT_SYMBOL_GPL(macvlan_start_xmit); | 264 | EXPORT_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 | ||
437 | static struct rtnl_link_stats64 *macvlan_dev_get_stats64(struct net_device *dev, | 442 | static 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 | ||
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 | |||
623 | int macvlan_common_newlink(struct net *src_net, struct net_device *dev, | 614 | int 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; | |||
25 | struct macvtap_queue; | 25 | struct 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 | */ |
35 | struct macvlan_rx_stats { | 38 | struct 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 | ||