aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/8021q/vlan.h17
-rw-r--r--net/8021q/vlan_core.c12
-rw-r--r--net/8021q/vlan_dev.c47
3 files changed, 65 insertions, 11 deletions
diff --git a/net/8021q/vlan.h b/net/8021q/vlan.h
index 68f9290e6837..5685296017e9 100644
--- a/net/8021q/vlan.h
+++ b/net/8021q/vlan.h
@@ -16,6 +16,21 @@ struct vlan_priority_tci_mapping {
16 struct vlan_priority_tci_mapping *next; 16 struct vlan_priority_tci_mapping *next;
17}; 17};
18 18
19
20/**
21 * struct vlan_rx_stats - VLAN percpu rx stats
22 * @rx_packets: number of received packets
23 * @rx_bytes: number of received bytes
24 * @multicast: number of received multicast packets
25 * @rx_errors: number of errors
26 */
27struct vlan_rx_stats {
28 unsigned long rx_packets;
29 unsigned long rx_bytes;
30 unsigned long multicast;
31 unsigned long rx_errors;
32};
33
19/** 34/**
20 * struct vlan_dev_info - VLAN private device data 35 * struct vlan_dev_info - VLAN private device data
21 * @nr_ingress_mappings: number of ingress priority mappings 36 * @nr_ingress_mappings: number of ingress priority mappings
@@ -29,6 +44,7 @@ struct vlan_priority_tci_mapping {
29 * @dent: proc dir entry 44 * @dent: proc dir entry
30 * @cnt_inc_headroom_on_tx: statistic - number of skb expansions on TX 45 * @cnt_inc_headroom_on_tx: statistic - number of skb expansions on TX
31 * @cnt_encap_on_xmit: statistic - number of skb encapsulations on TX 46 * @cnt_encap_on_xmit: statistic - number of skb encapsulations on TX
47 * @vlan_rx_stats: ptr to percpu rx stats
32 */ 48 */
33struct vlan_dev_info { 49struct vlan_dev_info {
34 unsigned int nr_ingress_mappings; 50 unsigned int nr_ingress_mappings;
@@ -45,6 +61,7 @@ struct vlan_dev_info {
45 struct proc_dir_entry *dent; 61 struct proc_dir_entry *dent;
46 unsigned long cnt_inc_headroom_on_tx; 62 unsigned long cnt_inc_headroom_on_tx;
47 unsigned long cnt_encap_on_xmit; 63 unsigned long cnt_encap_on_xmit;
64 struct vlan_rx_stats *vlan_rx_stats;
48}; 65};
49 66
50static inline struct vlan_dev_info *vlan_dev_info(const struct net_device *dev) 67static inline struct vlan_dev_info *vlan_dev_info(const struct net_device *dev)
diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c
index 971d3755ae87..e75a2f3b10af 100644
--- a/net/8021q/vlan_core.c
+++ b/net/8021q/vlan_core.c
@@ -31,7 +31,7 @@ EXPORT_SYMBOL(__vlan_hwaccel_rx);
31int vlan_hwaccel_do_receive(struct sk_buff *skb) 31int vlan_hwaccel_do_receive(struct sk_buff *skb)
32{ 32{
33 struct net_device *dev = skb->dev; 33 struct net_device *dev = skb->dev;
34 struct net_device_stats *stats; 34 struct vlan_rx_stats *rx_stats;
35 35
36 skb->dev = vlan_dev_info(dev)->real_dev; 36 skb->dev = vlan_dev_info(dev)->real_dev;
37 netif_nit_deliver(skb); 37 netif_nit_deliver(skb);
@@ -40,15 +40,17 @@ int vlan_hwaccel_do_receive(struct sk_buff *skb)
40 skb->priority = vlan_get_ingress_priority(dev, skb->vlan_tci); 40 skb->priority = vlan_get_ingress_priority(dev, skb->vlan_tci);
41 skb->vlan_tci = 0; 41 skb->vlan_tci = 0;
42 42
43 stats = &dev->stats; 43 rx_stats = per_cpu_ptr(vlan_dev_info(dev)->vlan_rx_stats,
44 stats->rx_packets++; 44 smp_processor_id());
45 stats->rx_bytes += skb->len; 45
46 rx_stats->rx_packets++;
47 rx_stats->rx_bytes += skb->len;
46 48
47 switch (skb->pkt_type) { 49 switch (skb->pkt_type) {
48 case PACKET_BROADCAST: 50 case PACKET_BROADCAST:
49 break; 51 break;
50 case PACKET_MULTICAST: 52 case PACKET_MULTICAST:
51 stats->multicast++; 53 rx_stats->multicast++;
52 break; 54 break;
53 case PACKET_OTHERHOST: 55 case PACKET_OTHERHOST:
54 /* Our lower layer thinks this is not local, let's make sure. 56 /* Our lower layer thinks this is not local, let's make sure.
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index 915965942139..de0dc6bacbe8 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -140,7 +140,7 @@ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev,
140 struct packet_type *ptype, struct net_device *orig_dev) 140 struct packet_type *ptype, struct net_device *orig_dev)
141{ 141{
142 struct vlan_hdr *vhdr; 142 struct vlan_hdr *vhdr;
143 struct net_device_stats *stats; 143 struct vlan_rx_stats *rx_stats;
144 u16 vlan_id; 144 u16 vlan_id;
145 u16 vlan_tci; 145 u16 vlan_tci;
146 146
@@ -163,9 +163,10 @@ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev,
163 goto err_unlock; 163 goto err_unlock;
164 } 164 }
165 165
166 stats = &skb->dev->stats; 166 rx_stats = per_cpu_ptr(vlan_dev_info(dev)->vlan_rx_stats,
167 stats->rx_packets++; 167 smp_processor_id());
168 stats->rx_bytes += skb->len; 168 rx_stats->rx_packets++;
169 rx_stats->rx_bytes += skb->len;
169 170
170 skb_pull_rcsum(skb, VLAN_HLEN); 171 skb_pull_rcsum(skb, VLAN_HLEN);
171 172
@@ -180,7 +181,7 @@ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev,
180 break; 181 break;
181 182
182 case PACKET_MULTICAST: 183 case PACKET_MULTICAST:
183 stats->multicast++; 184 rx_stats->multicast++;
184 break; 185 break;
185 186
186 case PACKET_OTHERHOST: 187 case PACKET_OTHERHOST:
@@ -200,7 +201,7 @@ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev,
200 201
201 skb = vlan_check_reorder_header(skb); 202 skb = vlan_check_reorder_header(skb);
202 if (!skb) { 203 if (!skb) {
203 stats->rx_errors++; 204 rx_stats->rx_errors++;
204 goto err_unlock; 205 goto err_unlock;
205 } 206 }
206 207
@@ -731,6 +732,11 @@ static int vlan_dev_init(struct net_device *dev)
731 subclass = 1; 732 subclass = 1;
732 733
733 vlan_dev_set_lockdep_class(dev, subclass); 734 vlan_dev_set_lockdep_class(dev, subclass);
735
736 vlan_dev_info(dev)->vlan_rx_stats = alloc_percpu(struct vlan_rx_stats);
737 if (!vlan_dev_info(dev)->vlan_rx_stats)
738 return -ENOMEM;
739
734 return 0; 740 return 0;
735} 741}
736 742
@@ -740,6 +746,8 @@ static void vlan_dev_uninit(struct net_device *dev)
740 struct vlan_dev_info *vlan = vlan_dev_info(dev); 746 struct vlan_dev_info *vlan = vlan_dev_info(dev);
741 int i; 747 int i;
742 748
749 free_percpu(vlan->vlan_rx_stats);
750 vlan->vlan_rx_stats = NULL;
743 for (i = 0; i < ARRAY_SIZE(vlan->egress_priority_map); i++) { 751 for (i = 0; i < ARRAY_SIZE(vlan->egress_priority_map); i++) {
744 while ((pm = vlan->egress_priority_map[i]) != NULL) { 752 while ((pm = vlan->egress_priority_map[i]) != NULL) {
745 vlan->egress_priority_map[i] = pm->next; 753 vlan->egress_priority_map[i] = pm->next;
@@ -775,6 +783,31 @@ static u32 vlan_ethtool_get_flags(struct net_device *dev)
775 return dev_ethtool_get_flags(vlan->real_dev); 783 return dev_ethtool_get_flags(vlan->real_dev);
776} 784}
777 785
786static struct net_device_stats *vlan_dev_get_stats(struct net_device *dev)
787{
788 struct net_device_stats *stats = &dev->stats;
789
790 dev_txq_stats_fold(dev, stats);
791
792 if (vlan_dev_info(dev)->vlan_rx_stats) {
793 struct vlan_rx_stats *p, rx = {0};
794 int i;
795
796 for_each_possible_cpu(i) {
797 p = per_cpu_ptr(vlan_dev_info(dev)->vlan_rx_stats, i);
798 rx.rx_packets += p->rx_packets;
799 rx.rx_bytes += p->rx_bytes;
800 rx.rx_errors += p->rx_errors;
801 rx.multicast += p->multicast;
802 }
803 stats->rx_packets = rx.rx_packets;
804 stats->rx_bytes = rx.rx_bytes;
805 stats->rx_errors = rx.rx_errors;
806 stats->multicast = rx.multicast;
807 }
808 return stats;
809}
810
778static const struct ethtool_ops vlan_ethtool_ops = { 811static const struct ethtool_ops vlan_ethtool_ops = {
779 .get_settings = vlan_ethtool_get_settings, 812 .get_settings = vlan_ethtool_get_settings,
780 .get_drvinfo = vlan_ethtool_get_drvinfo, 813 .get_drvinfo = vlan_ethtool_get_drvinfo,
@@ -797,6 +830,7 @@ static const struct net_device_ops vlan_netdev_ops = {
797 .ndo_change_rx_flags = vlan_dev_change_rx_flags, 830 .ndo_change_rx_flags = vlan_dev_change_rx_flags,
798 .ndo_do_ioctl = vlan_dev_ioctl, 831 .ndo_do_ioctl = vlan_dev_ioctl,
799 .ndo_neigh_setup = vlan_dev_neigh_setup, 832 .ndo_neigh_setup = vlan_dev_neigh_setup,
833 .ndo_get_stats = vlan_dev_get_stats,
800#if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE) 834#if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE)
801 .ndo_fcoe_ddp_setup = vlan_dev_fcoe_ddp_setup, 835 .ndo_fcoe_ddp_setup = vlan_dev_fcoe_ddp_setup,
802 .ndo_fcoe_ddp_done = vlan_dev_fcoe_ddp_done, 836 .ndo_fcoe_ddp_done = vlan_dev_fcoe_ddp_done,
@@ -820,6 +854,7 @@ static const struct net_device_ops vlan_netdev_accel_ops = {
820 .ndo_change_rx_flags = vlan_dev_change_rx_flags, 854 .ndo_change_rx_flags = vlan_dev_change_rx_flags,
821 .ndo_do_ioctl = vlan_dev_ioctl, 855 .ndo_do_ioctl = vlan_dev_ioctl,
822 .ndo_neigh_setup = vlan_dev_neigh_setup, 856 .ndo_neigh_setup = vlan_dev_neigh_setup,
857 .ndo_get_stats = vlan_dev_get_stats,
823#if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE) 858#if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE)
824 .ndo_fcoe_ddp_setup = vlan_dev_fcoe_ddp_setup, 859 .ndo_fcoe_ddp_setup = vlan_dev_fcoe_ddp_setup,
825 .ndo_fcoe_ddp_done = vlan_dev_fcoe_ddp_done, 860 .ndo_fcoe_ddp_done = vlan_dev_fcoe_ddp_done,