diff options
Diffstat (limited to 'net/8021q/vlan_dev.c')
-rw-r--r-- | net/8021q/vlan_dev.c | 47 |
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 | ||
786 | static 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 | |||
778 | static const struct ethtool_ops vlan_ethtool_ops = { | 811 | static 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, |