aboutsummaryrefslogtreecommitdiffstats
path: root/net/8021q/vlan_dev.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/8021q/vlan_dev.c')
-rw-r--r--net/8021q/vlan_dev.c47
1 files changed, 41 insertions, 6 deletions
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,