diff options
Diffstat (limited to 'net/ipv4/ip_gre.c')
-rw-r--r-- | net/ipv4/ip_gre.c | 59 |
1 files changed, 40 insertions, 19 deletions
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 02d07c6f630f..b9abf265c2f8 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c | |||
@@ -169,30 +169,49 @@ struct ipgre_net { | |||
169 | 169 | ||
170 | /* often modified stats are per cpu, other are shared (netdev->stats) */ | 170 | /* often modified stats are per cpu, other are shared (netdev->stats) */ |
171 | struct pcpu_tstats { | 171 | struct pcpu_tstats { |
172 | unsigned long rx_packets; | 172 | u64 rx_packets; |
173 | unsigned long rx_bytes; | 173 | u64 rx_bytes; |
174 | unsigned long tx_packets; | 174 | u64 tx_packets; |
175 | unsigned long tx_bytes; | 175 | u64 tx_bytes; |
176 | } __attribute__((aligned(4*sizeof(unsigned long)))); | 176 | struct u64_stats_sync syncp; |
177 | }; | ||
177 | 178 | ||
178 | static struct net_device_stats *ipgre_get_stats(struct net_device *dev) | 179 | static struct rtnl_link_stats64 *ipgre_get_stats64(struct net_device *dev, |
180 | struct rtnl_link_stats64 *tot) | ||
179 | { | 181 | { |
180 | struct pcpu_tstats sum = { 0 }; | ||
181 | int i; | 182 | int i; |
182 | 183 | ||
183 | for_each_possible_cpu(i) { | 184 | for_each_possible_cpu(i) { |
184 | const struct pcpu_tstats *tstats = per_cpu_ptr(dev->tstats, i); | 185 | const struct pcpu_tstats *tstats = per_cpu_ptr(dev->tstats, i); |
185 | 186 | u64 rx_packets, rx_bytes, tx_packets, tx_bytes; | |
186 | sum.rx_packets += tstats->rx_packets; | 187 | unsigned int start; |
187 | sum.rx_bytes += tstats->rx_bytes; | 188 | |
188 | sum.tx_packets += tstats->tx_packets; | 189 | do { |
189 | sum.tx_bytes += tstats->tx_bytes; | 190 | start = u64_stats_fetch_begin_bh(&tstats->syncp); |
191 | rx_packets = tstats->rx_packets; | ||
192 | tx_packets = tstats->tx_packets; | ||
193 | rx_bytes = tstats->rx_bytes; | ||
194 | tx_bytes = tstats->tx_bytes; | ||
195 | } while (u64_stats_fetch_retry_bh(&tstats->syncp, start)); | ||
196 | |||
197 | tot->rx_packets += rx_packets; | ||
198 | tot->tx_packets += tx_packets; | ||
199 | tot->rx_bytes += rx_bytes; | ||
200 | tot->tx_bytes += tx_bytes; | ||
190 | } | 201 | } |
191 | dev->stats.rx_packets = sum.rx_packets; | 202 | |
192 | dev->stats.rx_bytes = sum.rx_bytes; | 203 | tot->multicast = dev->stats.multicast; |
193 | dev->stats.tx_packets = sum.tx_packets; | 204 | tot->rx_crc_errors = dev->stats.rx_crc_errors; |
194 | dev->stats.tx_bytes = sum.tx_bytes; | 205 | tot->rx_fifo_errors = dev->stats.rx_fifo_errors; |
195 | return &dev->stats; | 206 | tot->rx_length_errors = dev->stats.rx_length_errors; |
207 | tot->rx_errors = dev->stats.rx_errors; | ||
208 | tot->tx_fifo_errors = dev->stats.tx_fifo_errors; | ||
209 | tot->tx_carrier_errors = dev->stats.tx_carrier_errors; | ||
210 | tot->tx_dropped = dev->stats.tx_dropped; | ||
211 | tot->tx_aborted_errors = dev->stats.tx_aborted_errors; | ||
212 | tot->tx_errors = dev->stats.tx_errors; | ||
213 | |||
214 | return tot; | ||
196 | } | 215 | } |
197 | 216 | ||
198 | /* Given src, dst and key, find appropriate for input tunnel. */ | 217 | /* Given src, dst and key, find appropriate for input tunnel. */ |
@@ -672,8 +691,10 @@ static int ipgre_rcv(struct sk_buff *skb) | |||
672 | } | 691 | } |
673 | 692 | ||
674 | tstats = this_cpu_ptr(tunnel->dev->tstats); | 693 | tstats = this_cpu_ptr(tunnel->dev->tstats); |
694 | u64_stats_update_begin(&tstats->syncp); | ||
675 | tstats->rx_packets++; | 695 | tstats->rx_packets++; |
676 | tstats->rx_bytes += skb->len; | 696 | tstats->rx_bytes += skb->len; |
697 | u64_stats_update_end(&tstats->syncp); | ||
677 | 698 | ||
678 | __skb_tunnel_rx(skb, tunnel->dev); | 699 | __skb_tunnel_rx(skb, tunnel->dev); |
679 | 700 | ||
@@ -1253,7 +1274,7 @@ static const struct net_device_ops ipgre_netdev_ops = { | |||
1253 | .ndo_start_xmit = ipgre_tunnel_xmit, | 1274 | .ndo_start_xmit = ipgre_tunnel_xmit, |
1254 | .ndo_do_ioctl = ipgre_tunnel_ioctl, | 1275 | .ndo_do_ioctl = ipgre_tunnel_ioctl, |
1255 | .ndo_change_mtu = ipgre_tunnel_change_mtu, | 1276 | .ndo_change_mtu = ipgre_tunnel_change_mtu, |
1256 | .ndo_get_stats = ipgre_get_stats, | 1277 | .ndo_get_stats64 = ipgre_get_stats64, |
1257 | }; | 1278 | }; |
1258 | 1279 | ||
1259 | static void ipgre_dev_free(struct net_device *dev) | 1280 | static void ipgre_dev_free(struct net_device *dev) |
@@ -1507,7 +1528,7 @@ static const struct net_device_ops ipgre_tap_netdev_ops = { | |||
1507 | .ndo_set_mac_address = eth_mac_addr, | 1528 | .ndo_set_mac_address = eth_mac_addr, |
1508 | .ndo_validate_addr = eth_validate_addr, | 1529 | .ndo_validate_addr = eth_validate_addr, |
1509 | .ndo_change_mtu = ipgre_tunnel_change_mtu, | 1530 | .ndo_change_mtu = ipgre_tunnel_change_mtu, |
1510 | .ndo_get_stats = ipgre_get_stats, | 1531 | .ndo_get_stats64 = ipgre_get_stats64, |
1511 | }; | 1532 | }; |
1512 | 1533 | ||
1513 | static void ipgre_tap_setup(struct net_device *dev) | 1534 | static void ipgre_tap_setup(struct net_device *dev) |