diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/batman-adv/bat_iv_ogm.c | 10 | ||||
-rw-r--r-- | net/batman-adv/main.c | 2 | ||||
-rw-r--r-- | net/batman-adv/main.h | 27 | ||||
-rw-r--r-- | net/batman-adv/routing.c | 11 | ||||
-rw-r--r-- | net/batman-adv/soft-interface.c | 66 | ||||
-rw-r--r-- | net/batman-adv/translation-table.c | 8 | ||||
-rw-r--r-- | net/batman-adv/types.h | 17 |
7 files changed, 138 insertions, 3 deletions
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 */ | ||
247 | static 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' */ | ||
258 | static 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, | |||
45 | static u32 bat_get_msglevel(struct net_device *dev); | 45 | static u32 bat_get_msglevel(struct net_device *dev); |
46 | static void bat_set_msglevel(struct net_device *dev, u32 value); | 46 | static void bat_set_msglevel(struct net_device *dev, u32 value); |
47 | static u32 bat_get_link(struct net_device *dev); | 47 | static u32 bat_get_link(struct net_device *dev); |
48 | static void batadv_get_strings(struct net_device *dev, u32 stringset, u8 *data); | ||
49 | static void batadv_get_ethtool_stats(struct net_device *dev, | ||
50 | struct ethtool_stats *stats, u64 *data); | ||
51 | static int batadv_get_sset_count(struct net_device *dev, int stringset); | ||
48 | 52 | ||
49 | static const struct ethtool_ops bat_ethtool_ops = { | 53 | static 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 | ||
57 | int my_skb_head_push(struct sk_buff *skb, unsigned int len) | 64 | int 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); |
422 | unreg_sysfs: | 434 | unreg_sysfs: |
423 | sysfs_del_meshif(soft_iface); | 435 | sysfs_del_meshif(soft_iface); |
436 | free_bat_counters: | ||
437 | free_percpu(bat_priv->bat_counters); | ||
424 | unreg_soft_iface: | 438 | unreg_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 | */ | ||
508 | static 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 | |||
525 | static 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 | |||
533 | static 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 | |||
544 | static 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 | ||
151 | enum 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 | |||
151 | struct bat_priv { | 167 | struct 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 */ |