diff options
Diffstat (limited to 'drivers/net/vxlan.c')
-rw-r--r-- | drivers/net/vxlan.c | 72 |
1 files changed, 7 insertions, 65 deletions
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index fe9ea7d14951..e532b2ab5b0f 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c | |||
@@ -101,20 +101,10 @@ struct vxlan_fdb { | |||
101 | u8 eth_addr[ETH_ALEN]; | 101 | u8 eth_addr[ETH_ALEN]; |
102 | }; | 102 | }; |
103 | 103 | ||
104 | /* Per-cpu network traffic stats */ | ||
105 | struct vxlan_stats { | ||
106 | u64 rx_packets; | ||
107 | u64 rx_bytes; | ||
108 | u64 tx_packets; | ||
109 | u64 tx_bytes; | ||
110 | struct u64_stats_sync syncp; | ||
111 | }; | ||
112 | |||
113 | /* Pseudo network device */ | 104 | /* Pseudo network device */ |
114 | struct vxlan_dev { | 105 | struct vxlan_dev { |
115 | struct hlist_node hlist; | 106 | struct hlist_node hlist; |
116 | struct net_device *dev; | 107 | struct net_device *dev; |
117 | struct vxlan_stats __percpu *stats; | ||
118 | __u32 vni; /* virtual network id */ | 108 | __u32 vni; /* virtual network id */ |
119 | __be32 gaddr; /* multicast group */ | 109 | __be32 gaddr; /* multicast group */ |
120 | __be32 saddr; /* source address */ | 110 | __be32 saddr; /* source address */ |
@@ -667,7 +657,7 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb) | |||
667 | struct iphdr *oip; | 657 | struct iphdr *oip; |
668 | struct vxlanhdr *vxh; | 658 | struct vxlanhdr *vxh; |
669 | struct vxlan_dev *vxlan; | 659 | struct vxlan_dev *vxlan; |
670 | struct vxlan_stats *stats; | 660 | struct pcpu_tstats *stats; |
671 | __u32 vni; | 661 | __u32 vni; |
672 | int err; | 662 | int err; |
673 | 663 | ||
@@ -743,7 +733,7 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb) | |||
743 | } | 733 | } |
744 | } | 734 | } |
745 | 735 | ||
746 | stats = this_cpu_ptr(vxlan->stats); | 736 | stats = this_cpu_ptr(vxlan->dev->tstats); |
747 | u64_stats_update_begin(&stats->syncp); | 737 | u64_stats_update_begin(&stats->syncp); |
748 | stats->rx_packets++; | 738 | stats->rx_packets++; |
749 | stats->rx_bytes += skb->len; | 739 | stats->rx_bytes += skb->len; |
@@ -974,8 +964,7 @@ static netdev_tx_t vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, | |||
974 | 964 | ||
975 | /* short-circuited back to local bridge */ | 965 | /* short-circuited back to local bridge */ |
976 | if (netif_rx(skb) == NET_RX_SUCCESS) { | 966 | if (netif_rx(skb) == NET_RX_SUCCESS) { |
977 | struct vxlan_stats *stats = | 967 | struct pcpu_tstats *stats = this_cpu_ptr(dev->tstats); |
978 | this_cpu_ptr(vxlan->stats); | ||
979 | 968 | ||
980 | u64_stats_update_begin(&stats->syncp); | 969 | u64_stats_update_begin(&stats->syncp); |
981 | stats->tx_packets++; | 970 | stats->tx_packets++; |
@@ -1183,10 +1172,8 @@ static void vxlan_cleanup(unsigned long arg) | |||
1183 | /* Setup stats when device is created */ | 1172 | /* Setup stats when device is created */ |
1184 | static int vxlan_init(struct net_device *dev) | 1173 | static int vxlan_init(struct net_device *dev) |
1185 | { | 1174 | { |
1186 | struct vxlan_dev *vxlan = netdev_priv(dev); | 1175 | dev->tstats = alloc_percpu(struct pcpu_tstats); |
1187 | 1176 | if (!dev->tstats) | |
1188 | vxlan->stats = alloc_percpu(struct vxlan_stats); | ||
1189 | if (!vxlan->stats) | ||
1190 | return -ENOMEM; | 1177 | return -ENOMEM; |
1191 | 1178 | ||
1192 | return 0; | 1179 | return 0; |
@@ -1242,49 +1229,6 @@ static int vxlan_stop(struct net_device *dev) | |||
1242 | return 0; | 1229 | return 0; |
1243 | } | 1230 | } |
1244 | 1231 | ||
1245 | /* Merge per-cpu statistics */ | ||
1246 | static struct rtnl_link_stats64 *vxlan_stats64(struct net_device *dev, | ||
1247 | struct rtnl_link_stats64 *stats) | ||
1248 | { | ||
1249 | struct vxlan_dev *vxlan = netdev_priv(dev); | ||
1250 | struct vxlan_stats tmp, sum = { 0 }; | ||
1251 | unsigned int cpu; | ||
1252 | |||
1253 | for_each_possible_cpu(cpu) { | ||
1254 | unsigned int start; | ||
1255 | const struct vxlan_stats *stats | ||
1256 | = per_cpu_ptr(vxlan->stats, cpu); | ||
1257 | |||
1258 | do { | ||
1259 | start = u64_stats_fetch_begin_bh(&stats->syncp); | ||
1260 | memcpy(&tmp, stats, sizeof(tmp)); | ||
1261 | } while (u64_stats_fetch_retry_bh(&stats->syncp, start)); | ||
1262 | |||
1263 | sum.tx_bytes += tmp.tx_bytes; | ||
1264 | sum.tx_packets += tmp.tx_packets; | ||
1265 | sum.rx_bytes += tmp.rx_bytes; | ||
1266 | sum.rx_packets += tmp.rx_packets; | ||
1267 | } | ||
1268 | |||
1269 | stats->tx_bytes = sum.tx_bytes; | ||
1270 | stats->tx_packets = sum.tx_packets; | ||
1271 | stats->rx_bytes = sum.rx_bytes; | ||
1272 | stats->rx_packets = sum.rx_packets; | ||
1273 | |||
1274 | stats->multicast = dev->stats.multicast; | ||
1275 | stats->rx_length_errors = dev->stats.rx_length_errors; | ||
1276 | stats->rx_frame_errors = dev->stats.rx_frame_errors; | ||
1277 | stats->rx_errors = dev->stats.rx_errors; | ||
1278 | |||
1279 | stats->tx_dropped = dev->stats.tx_dropped; | ||
1280 | stats->tx_carrier_errors = dev->stats.tx_carrier_errors; | ||
1281 | stats->tx_aborted_errors = dev->stats.tx_aborted_errors; | ||
1282 | stats->collisions = dev->stats.collisions; | ||
1283 | stats->tx_errors = dev->stats.tx_errors; | ||
1284 | |||
1285 | return stats; | ||
1286 | } | ||
1287 | |||
1288 | /* Stub, nothing needs to be done. */ | 1232 | /* Stub, nothing needs to be done. */ |
1289 | static void vxlan_set_multicast_list(struct net_device *dev) | 1233 | static void vxlan_set_multicast_list(struct net_device *dev) |
1290 | { | 1234 | { |
@@ -1295,7 +1239,7 @@ static const struct net_device_ops vxlan_netdev_ops = { | |||
1295 | .ndo_open = vxlan_open, | 1239 | .ndo_open = vxlan_open, |
1296 | .ndo_stop = vxlan_stop, | 1240 | .ndo_stop = vxlan_stop, |
1297 | .ndo_start_xmit = vxlan_xmit, | 1241 | .ndo_start_xmit = vxlan_xmit, |
1298 | .ndo_get_stats64 = vxlan_stats64, | 1242 | .ndo_get_stats64 = ip_tunnel_get_stats64, |
1299 | .ndo_set_rx_mode = vxlan_set_multicast_list, | 1243 | .ndo_set_rx_mode = vxlan_set_multicast_list, |
1300 | .ndo_change_mtu = eth_change_mtu, | 1244 | .ndo_change_mtu = eth_change_mtu, |
1301 | .ndo_validate_addr = eth_validate_addr, | 1245 | .ndo_validate_addr = eth_validate_addr, |
@@ -1312,9 +1256,7 @@ static struct device_type vxlan_type = { | |||
1312 | 1256 | ||
1313 | static void vxlan_free(struct net_device *dev) | 1257 | static void vxlan_free(struct net_device *dev) |
1314 | { | 1258 | { |
1315 | struct vxlan_dev *vxlan = netdev_priv(dev); | 1259 | free_percpu(dev->tstats); |
1316 | |||
1317 | free_percpu(vxlan->stats); | ||
1318 | free_netdev(dev); | 1260 | free_netdev(dev); |
1319 | } | 1261 | } |
1320 | 1262 | ||