aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Hundebøll <martin@hundeboll.net>2012-04-20 11:02:45 -0400
committerAntonio Quartulli <ordex@autistici.org>2012-06-18 12:00:58 -0400
commitf8214865a55f805e65c33350bc0f1eb46dd8433d (patch)
tree0fb4582b2ec3b045a094acd6063f5559e6d4dcb5
parent66a1b2bcb34b0c74a3422968b15a7ea853ea5a2d (diff)
batman-adv: Add get_ethtool_stats() support
Added additional counters in a bat_stats structure, which are exported through the ethtool api. The counters are specific to batman-adv and includes: forwarded packets and bytes management packets and bytes (aggregated OGMs at this point) translation table packets New counters are added by extending "enum bat_counters" in types.h and adding corresponding descriptive string(s) to bat_counters_strings in soft-iface.c. Counters are increased by calling batadv_add_counter() and incremented by one by calling batadv_inc_counter(). Signed-off-by: Martin Hundebøll <martin@hundeboll.net> Signed-off-by: Sven Eckelmann <sven@narfation.org>
-rw-r--r--Documentation/networking/batman-adv.txt5
-rw-r--r--net/batman-adv/bat_iv_ogm.c10
-rw-r--r--net/batman-adv/main.c2
-rw-r--r--net/batman-adv/main.h27
-rw-r--r--net/batman-adv/routing.c11
-rw-r--r--net/batman-adv/soft-interface.c66
-rw-r--r--net/batman-adv/translation-table.c8
-rw-r--r--net/batman-adv/types.h17
8 files changed, 143 insertions, 3 deletions
diff --git a/Documentation/networking/batman-adv.txt b/Documentation/networking/batman-adv.txt
index 75a592365af9..8f3ae4a6147e 100644
--- a/Documentation/networking/batman-adv.txt
+++ b/Documentation/networking/batman-adv.txt
@@ -211,6 +211,11 @@ The debug output can be changed at runtime using the file
211 211
212will enable debug messages for when routes change. 212will enable debug messages for when routes change.
213 213
214Counters for different types of packets entering and leaving the
215batman-adv module are available through ethtool:
216
217# ethtool --statistics bat0
218
214 219
215BATCTL 220BATCTL
216------ 221------
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
index ec351199c652..99ec218df7f2 100644
--- a/net/batman-adv/bat_iv_ogm.c
+++ b/net/batman-adv/bat_iv_ogm.c
@@ -196,8 +196,12 @@ static void bat_iv_ogm_send_to_if(struct forw_packet *forw_packet,
196 196
197 /* create clone because function is called more than once */ 197 /* create clone because function is called more than once */
198 skb = skb_clone(forw_packet->skb, GFP_ATOMIC); 198 skb = skb_clone(forw_packet->skb, GFP_ATOMIC);
199 if (skb) 199 if (skb) {
200 batadv_inc_counter(bat_priv, BAT_CNT_MGMT_TX);
201 batadv_add_counter(bat_priv, BAT_CNT_MGMT_TX_BYTES,
202 skb->len + ETH_HLEN);
200 send_skb_packet(skb, hard_iface, broadcast_addr); 203 send_skb_packet(skb, hard_iface, broadcast_addr);
204 }
201} 205}
202 206
203/* send a batman ogm packet */ 207/* send a batman ogm packet */
@@ -1203,6 +1207,10 @@ static int bat_iv_ogm_receive(struct sk_buff *skb,
1203 if (bat_priv->bat_algo_ops->bat_ogm_emit != bat_iv_ogm_emit) 1207 if (bat_priv->bat_algo_ops->bat_ogm_emit != bat_iv_ogm_emit)
1204 return NET_RX_DROP; 1208 return NET_RX_DROP;
1205 1209
1210 batadv_inc_counter(bat_priv, BAT_CNT_MGMT_RX);
1211 batadv_add_counter(bat_priv, BAT_CNT_MGMT_RX_BYTES,
1212 skb->len + ETH_HLEN);
1213
1206 packet_len = skb_headlen(skb); 1214 packet_len = skb_headlen(skb);
1207 ethhdr = (struct ethhdr *)skb_mac_header(skb); 1215 ethhdr = (struct ethhdr *)skb_mac_header(skb);
1208 packet_buff = skb->data; 1216 packet_buff = skb->data;
diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c
index 083a2993efe4..bd83aa4e7c87 100644
--- a/net/batman-adv/main.c
+++ b/net/batman-adv/main.c
@@ -153,6 +153,8 @@ void mesh_free(struct net_device *soft_iface)
153 153
154 bla_free(bat_priv); 154 bla_free(bat_priv);
155 155
156 free_percpu(bat_priv->bat_counters);
157
156 atomic_set(&bat_priv->mesh_state, MESH_INACTIVE); 158 atomic_set(&bat_priv->mesh_state, MESH_INACTIVE);
157} 159}
158 160
diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h
index 630bbe8968ca..6e0cbdc48321 100644
--- a/net/batman-adv/main.h
+++ b/net/batman-adv/main.h
@@ -138,6 +138,7 @@ enum dbg_level {
138#include <linux/kthread.h> /* kernel threads */ 138#include <linux/kthread.h> /* kernel threads */
139#include <linux/pkt_sched.h> /* schedule types */ 139#include <linux/pkt_sched.h> /* schedule types */
140#include <linux/workqueue.h> /* workqueue */ 140#include <linux/workqueue.h> /* workqueue */
141#include <linux/percpu.h>
141#include <linux/slab.h> 142#include <linux/slab.h>
142#include <net/sock.h> /* struct sock */ 143#include <net/sock.h> /* struct sock */
143#include <linux/jiffies.h> 144#include <linux/jiffies.h>
@@ -242,4 +243,30 @@ static inline bool has_timed_out(unsigned long timestamp, unsigned int timeout)
242 _dummy > smallest_signed_int(_dummy); }) 243 _dummy > smallest_signed_int(_dummy); })
243#define seq_after(x, y) seq_before(y, x) 244#define seq_after(x, y) seq_before(y, x)
244 245
246/* Stop preemption on local cpu while incrementing the counter */
247static inline void batadv_add_counter(struct bat_priv *bat_priv, size_t idx,
248 size_t count)
249{
250 int cpu = get_cpu();
251 per_cpu_ptr(bat_priv->bat_counters, cpu)[idx] += count;
252 put_cpu();
253}
254
255#define batadv_inc_counter(b, i) batadv_add_counter(b, i, 1)
256
257/* Sum and return the cpu-local counters for index 'idx' */
258static inline uint64_t batadv_sum_counter(struct bat_priv *bat_priv, size_t idx)
259{
260 uint64_t *counters;
261 int cpu;
262 int sum = 0;
263
264 for_each_possible_cpu(cpu) {
265 counters = per_cpu_ptr(bat_priv->bat_counters, cpu);
266 sum += counters[idx];
267 }
268
269 return sum;
270}
271
245#endif /* _NET_BATMAN_ADV_MAIN_H_ */ 272#endif /* _NET_BATMAN_ADV_MAIN_H_ */
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c
index 015471d801b4..369604c99a46 100644
--- a/net/batman-adv/routing.c
+++ b/net/batman-adv/routing.c
@@ -600,6 +600,8 @@ int recv_tt_query(struct sk_buff *skb, struct hard_iface *recv_if)
600 600
601 switch (tt_query->flags & TT_QUERY_TYPE_MASK) { 601 switch (tt_query->flags & TT_QUERY_TYPE_MASK) {
602 case TT_REQUEST: 602 case TT_REQUEST:
603 batadv_inc_counter(bat_priv, BAT_CNT_TT_REQUEST_RX);
604
603 /* If we cannot provide an answer the tt_request is 605 /* If we cannot provide an answer the tt_request is
604 * forwarded */ 606 * forwarded */
605 if (!send_tt_response(bat_priv, tt_query)) { 607 if (!send_tt_response(bat_priv, tt_query)) {
@@ -612,6 +614,8 @@ int recv_tt_query(struct sk_buff *skb, struct hard_iface *recv_if)
612 } 614 }
613 break; 615 break;
614 case TT_RESPONSE: 616 case TT_RESPONSE:
617 batadv_inc_counter(bat_priv, BAT_CNT_TT_RESPONSE_RX);
618
615 if (is_my_mac(tt_query->dst)) { 619 if (is_my_mac(tt_query->dst)) {
616 /* packet needs to be linearized to access the TT 620 /* packet needs to be linearized to access the TT
617 * changes */ 621 * changes */
@@ -665,6 +669,8 @@ int recv_roam_adv(struct sk_buff *skb, struct hard_iface *recv_if)
665 if (is_broadcast_ether_addr(ethhdr->h_source)) 669 if (is_broadcast_ether_addr(ethhdr->h_source))
666 goto out; 670 goto out;
667 671
672 batadv_inc_counter(bat_priv, BAT_CNT_TT_ROAM_ADV_RX);
673
668 roam_adv_packet = (struct roam_adv_packet *)skb->data; 674 roam_adv_packet = (struct roam_adv_packet *)skb->data;
669 675
670 if (!is_my_mac(roam_adv_packet->dst)) 676 if (!is_my_mac(roam_adv_packet->dst))
@@ -872,6 +878,11 @@ static int route_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if)
872 /* decrement ttl */ 878 /* decrement ttl */
873 unicast_packet->header.ttl--; 879 unicast_packet->header.ttl--;
874 880
881 /* Update stats counter */
882 batadv_inc_counter(bat_priv, BAT_CNT_FORWARD);
883 batadv_add_counter(bat_priv, BAT_CNT_FORWARD_BYTES,
884 skb->len + ETH_HLEN);
885
875 /* route it */ 886 /* route it */
876 send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); 887 send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
877 ret = NET_RX_SUCCESS; 888 ret = NET_RX_SUCCESS;
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c
index 6e2530b02043..304a7ba09e03 100644
--- a/net/batman-adv/soft-interface.c
+++ b/net/batman-adv/soft-interface.c
@@ -45,6 +45,10 @@ static void bat_get_drvinfo(struct net_device *dev,
45static u32 bat_get_msglevel(struct net_device *dev); 45static u32 bat_get_msglevel(struct net_device *dev);
46static void bat_set_msglevel(struct net_device *dev, u32 value); 46static void bat_set_msglevel(struct net_device *dev, u32 value);
47static u32 bat_get_link(struct net_device *dev); 47static u32 bat_get_link(struct net_device *dev);
48static void batadv_get_strings(struct net_device *dev, u32 stringset, u8 *data);
49static void batadv_get_ethtool_stats(struct net_device *dev,
50 struct ethtool_stats *stats, u64 *data);
51static int batadv_get_sset_count(struct net_device *dev, int stringset);
48 52
49static const struct ethtool_ops bat_ethtool_ops = { 53static const struct ethtool_ops bat_ethtool_ops = {
50 .get_settings = bat_get_settings, 54 .get_settings = bat_get_settings,
@@ -52,6 +56,9 @@ static const struct ethtool_ops bat_ethtool_ops = {
52 .get_msglevel = bat_get_msglevel, 56 .get_msglevel = bat_get_msglevel,
53 .set_msglevel = bat_set_msglevel, 57 .set_msglevel = bat_set_msglevel,
54 .get_link = bat_get_link, 58 .get_link = bat_get_link,
59 .get_strings = batadv_get_strings,
60 .get_ethtool_stats = batadv_get_ethtool_stats,
61 .get_sset_count = batadv_get_sset_count,
55}; 62};
56 63
57int my_skb_head_push(struct sk_buff *skb, unsigned int len) 64int my_skb_head_push(struct sk_buff *skb, unsigned int len)
@@ -399,13 +406,18 @@ struct net_device *softif_create(const char *name)
399 bat_priv->primary_if = NULL; 406 bat_priv->primary_if = NULL;
400 bat_priv->num_ifaces = 0; 407 bat_priv->num_ifaces = 0;
401 408
409 bat_priv->bat_counters = __alloc_percpu(sizeof(uint64_t) * BAT_CNT_NUM,
410 __alignof__(uint64_t));
411 if (!bat_priv->bat_counters)
412 goto unreg_soft_iface;
413
402 ret = bat_algo_select(bat_priv, bat_routing_algo); 414 ret = bat_algo_select(bat_priv, bat_routing_algo);
403 if (ret < 0) 415 if (ret < 0)
404 goto unreg_soft_iface; 416 goto free_bat_counters;
405 417
406 ret = sysfs_add_meshif(soft_iface); 418 ret = sysfs_add_meshif(soft_iface);
407 if (ret < 0) 419 if (ret < 0)
408 goto unreg_soft_iface; 420 goto free_bat_counters;
409 421
410 ret = debugfs_add_meshif(soft_iface); 422 ret = debugfs_add_meshif(soft_iface);
411 if (ret < 0) 423 if (ret < 0)
@@ -421,6 +433,8 @@ unreg_debugfs:
421 debugfs_del_meshif(soft_iface); 433 debugfs_del_meshif(soft_iface);
422unreg_sysfs: 434unreg_sysfs:
423 sysfs_del_meshif(soft_iface); 435 sysfs_del_meshif(soft_iface);
436free_bat_counters:
437 free_percpu(bat_priv->bat_counters);
424unreg_soft_iface: 438unreg_soft_iface:
425 unregister_netdevice(soft_iface); 439 unregister_netdevice(soft_iface);
426 return NULL; 440 return NULL;
@@ -486,3 +500,51 @@ static u32 bat_get_link(struct net_device *dev)
486{ 500{
487 return 1; 501 return 1;
488} 502}
503
504/* Inspired by drivers/net/ethernet/dlink/sundance.c:1702
505 * Declare each description string in struct.name[] to get fixed sized buffer
506 * and compile time checking for strings longer than ETH_GSTRING_LEN.
507 */
508static const struct {
509 const char name[ETH_GSTRING_LEN];
510} bat_counters_strings[] = {
511 { "forward" },
512 { "forward_bytes" },
513 { "mgmt_tx" },
514 { "mgmt_tx_bytes" },
515 { "mgmt_rx" },
516 { "mgmt_rx_bytes" },
517 { "tt_request_tx" },
518 { "tt_request_rx" },
519 { "tt_response_tx" },
520 { "tt_response_rx" },
521 { "tt_roam_adv_tx" },
522 { "tt_roam_adv_rx" },
523};
524
525static void batadv_get_strings(struct net_device *dev, uint32_t stringset,
526 uint8_t *data)
527{
528 if (stringset == ETH_SS_STATS)
529 memcpy(data, bat_counters_strings,
530 sizeof(bat_counters_strings));
531}
532
533static void batadv_get_ethtool_stats(struct net_device *dev,
534 struct ethtool_stats *stats,
535 uint64_t *data)
536{
537 struct bat_priv *bat_priv = netdev_priv(dev);
538 int i;
539
540 for (i = 0; i < BAT_CNT_NUM; i++)
541 data[i] = batadv_sum_counter(bat_priv, i);
542}
543
544static int batadv_get_sset_count(struct net_device *dev, int stringset)
545{
546 if (stringset == ETH_SS_STATS)
547 return BAT_CNT_NUM;
548
549 return -EOPNOTSUPP;
550}
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
index a66c2dcd1088..ca53542e1e8e 100644
--- a/net/batman-adv/translation-table.c
+++ b/net/batman-adv/translation-table.c
@@ -1356,6 +1356,8 @@ static int send_tt_request(struct bat_priv *bat_priv,
1356 dst_orig_node->orig, neigh_node->addr, 1356 dst_orig_node->orig, neigh_node->addr,
1357 (full_table ? 'F' : '.')); 1357 (full_table ? 'F' : '.'));
1358 1358
1359 batadv_inc_counter(bat_priv, BAT_CNT_TT_REQUEST_TX);
1360
1359 send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); 1361 send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
1360 ret = 0; 1362 ret = 0;
1361 1363
@@ -1480,6 +1482,8 @@ static bool send_other_tt_response(struct bat_priv *bat_priv,
1480 res_dst_orig_node->orig, neigh_node->addr, 1482 res_dst_orig_node->orig, neigh_node->addr,
1481 req_dst_orig_node->orig, req_ttvn); 1483 req_dst_orig_node->orig, req_ttvn);
1482 1484
1485 batadv_inc_counter(bat_priv, BAT_CNT_TT_RESPONSE_TX);
1486
1483 send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); 1487 send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
1484 ret = true; 1488 ret = true;
1485 goto out; 1489 goto out;
@@ -1596,6 +1600,8 @@ static bool send_my_tt_response(struct bat_priv *bat_priv,
1596 orig_node->orig, neigh_node->addr, 1600 orig_node->orig, neigh_node->addr,
1597 (tt_response->flags & TT_FULL_TABLE ? 'F' : '.')); 1601 (tt_response->flags & TT_FULL_TABLE ? 'F' : '.'));
1598 1602
1603 batadv_inc_counter(bat_priv, BAT_CNT_TT_RESPONSE_TX);
1604
1599 send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); 1605 send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
1600 ret = true; 1606 ret = true;
1601 goto out; 1607 goto out;
@@ -1895,6 +1901,8 @@ static void send_roam_adv(struct bat_priv *bat_priv, uint8_t *client,
1895 "Sending ROAMING_ADV to %pM (client %pM) via %pM\n", 1901 "Sending ROAMING_ADV to %pM (client %pM) via %pM\n",
1896 orig_node->orig, client, neigh_node->addr); 1902 orig_node->orig, client, neigh_node->addr);
1897 1903
1904 batadv_inc_counter(bat_priv, BAT_CNT_TT_ROAM_ADV_TX);
1905
1898 send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); 1906 send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
1899 ret = 0; 1907 ret = 0;
1900 1908
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index 547dc339f33d..6b569debc1a6 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -148,9 +148,26 @@ struct bcast_duplist_entry {
148}; 148};
149#endif 149#endif
150 150
151enum bat_counters {
152 BAT_CNT_FORWARD,
153 BAT_CNT_FORWARD_BYTES,
154 BAT_CNT_MGMT_TX,
155 BAT_CNT_MGMT_TX_BYTES,
156 BAT_CNT_MGMT_RX,
157 BAT_CNT_MGMT_RX_BYTES,
158 BAT_CNT_TT_REQUEST_TX,
159 BAT_CNT_TT_REQUEST_RX,
160 BAT_CNT_TT_RESPONSE_TX,
161 BAT_CNT_TT_RESPONSE_RX,
162 BAT_CNT_TT_ROAM_ADV_TX,
163 BAT_CNT_TT_ROAM_ADV_RX,
164 BAT_CNT_NUM,
165};
166
151struct bat_priv { 167struct bat_priv {
152 atomic_t mesh_state; 168 atomic_t mesh_state;
153 struct net_device_stats stats; 169 struct net_device_stats stats;
170 uint64_t __percpu *bat_counters; /* Per cpu counters */
154 atomic_t aggregated_ogms; /* boolean */ 171 atomic_t aggregated_ogms; /* boolean */
155 atomic_t bonding; /* boolean */ 172 atomic_t bonding; /* boolean */
156 atomic_t fragmentation; /* boolean */ 173 atomic_t fragmentation; /* boolean */