aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/vxlan.c
diff options
context:
space:
mode:
authorPravin B Shelar <pshelar@nicira.com>2013-03-25 10:49:46 -0400
committerDavid S. Miller <davem@davemloft.net>2013-03-26 12:27:18 -0400
commite817104525577413301b3cb709a6472e0cf44a6a (patch)
tree892b9597e1b4adeb0f2914cfb5dbcf0824407148 /drivers/net/vxlan.c
parentfd58156e456d9f68fe04486be378d0bc93641532 (diff)
VXLAN: Fix vxlan stats handling.
Fixes bug in VXLAN code where is iptunnel_xmit() called with NULL dev->tstats. This bug was introduced in commit 6aed0c8bf7d2f389b (tunnel: use iptunnel_xmit() again). Following patch fixes bug by setting dev->tstats. It uses ip_tunnel module code to share stats function. CC: Cong Wang <xiyou.wangcong@gmail.com> Signed-off-by: Pravin B Shelar <pshelar@nicira.com> Acked-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/vxlan.c')
-rw-r--r--drivers/net/vxlan.c72
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 */
105struct 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 */
114struct vxlan_dev { 105struct 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 */
1184static int vxlan_init(struct net_device *dev) 1173static 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 */
1246static 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. */
1289static void vxlan_set_multicast_list(struct net_device *dev) 1233static 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
1313static void vxlan_free(struct net_device *dev) 1257static 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