aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2016-07-03 07:31:41 -0400
committerSimon Wunderlich <sw@simonwunderlich.de>2016-08-09 01:54:39 -0400
commitf02a478f518ee5690f279c8c2d3a6222143a7b20 (patch)
treedc69ab972b0544d3434fe1b8b00b2ac7fa495e48
parent024f99cb4acc14dab5e55e1ecdf6aad31269ca98 (diff)
batman-adv: add B.A.T.M.A.N. V bat_{orig, neigh}_dump implementations
Dump the algo V originators and neighbours. Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net> Signed-off-by: Andrew Lunn <andrew@lunn.ch> [sven@narfation.org: Fix includes, fix algo_ops integration] Signed-off-by: Sven Eckelmann <sven@narfation.org> Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de> Signed-off-by: Marek Lindner <mareklindner@neomailbox.ch>
-rw-r--r--include/uapi/linux/batman_adv.h2
-rw-r--r--net/batman-adv/bat_v.c340
-rw-r--r--net/batman-adv/netlink.c1
3 files changed, 343 insertions, 0 deletions
diff --git a/include/uapi/linux/batman_adv.h b/include/uapi/linux/batman_adv.h
index ba2359a1f464..2e2747fb1311 100644
--- a/include/uapi/linux/batman_adv.h
+++ b/include/uapi/linux/batman_adv.h
@@ -87,6 +87,7 @@ enum batadv_tt_client_flags {
87 * @BATADV_ATTR_LAST_SEEN_MSECS: Time in milliseconds since last seen 87 * @BATADV_ATTR_LAST_SEEN_MSECS: Time in milliseconds since last seen
88 * @BATADV_ATTR_NEIGH_ADDRESS: Neighbour MAC address 88 * @BATADV_ATTR_NEIGH_ADDRESS: Neighbour MAC address
89 * @BATADV_ATTR_TQ: TQ to neighbour 89 * @BATADV_ATTR_TQ: TQ to neighbour
90 * @BATADV_ATTR_THROUGHPUT: Estimated throughput to Neighbour
90 * @__BATADV_ATTR_AFTER_LAST: internal use 91 * @__BATADV_ATTR_AFTER_LAST: internal use
91 * @NUM_BATADV_ATTR: total number of batadv_nl_attrs available 92 * @NUM_BATADV_ATTR: total number of batadv_nl_attrs available
92 * @BATADV_ATTR_MAX: highest attribute number currently defined 93 * @BATADV_ATTR_MAX: highest attribute number currently defined
@@ -118,6 +119,7 @@ enum batadv_nl_attrs {
118 BATADV_ATTR_LAST_SEEN_MSECS, 119 BATADV_ATTR_LAST_SEEN_MSECS,
119 BATADV_ATTR_NEIGH_ADDRESS, 120 BATADV_ATTR_NEIGH_ADDRESS,
120 BATADV_ATTR_TQ, 121 BATADV_ATTR_TQ,
122 BATADV_ATTR_THROUGHPUT,
121 /* add attributes above here, update the policy in netlink.c */ 123 /* add attributes above here, update the policy in netlink.c */
122 __BATADV_ATTR_AFTER_LAST, 124 __BATADV_ATTR_AFTER_LAST,
123 NUM_BATADV_ATTR = __BATADV_ATTR_AFTER_LAST, 125 NUM_BATADV_ATTR = __BATADV_ATTR_AFTER_LAST,
diff --git a/net/batman-adv/bat_v.c b/net/batman-adv/bat_v.c
index 1d777b171366..9dccfaf32115 100644
--- a/net/batman-adv/bat_v.c
+++ b/net/batman-adv/bat_v.c
@@ -22,17 +22,22 @@
22#include <linux/bug.h> 22#include <linux/bug.h>
23#include <linux/cache.h> 23#include <linux/cache.h>
24#include <linux/errno.h> 24#include <linux/errno.h>
25#include <linux/if_ether.h>
25#include <linux/init.h> 26#include <linux/init.h>
26#include <linux/jiffies.h> 27#include <linux/jiffies.h>
27#include <linux/kernel.h> 28#include <linux/kernel.h>
28#include <linux/kref.h> 29#include <linux/kref.h>
29#include <linux/netdevice.h> 30#include <linux/netdevice.h>
31#include <linux/netlink.h>
30#include <linux/rculist.h> 32#include <linux/rculist.h>
31#include <linux/rcupdate.h> 33#include <linux/rcupdate.h>
32#include <linux/seq_file.h> 34#include <linux/seq_file.h>
33#include <linux/stddef.h> 35#include <linux/stddef.h>
34#include <linux/types.h> 36#include <linux/types.h>
35#include <linux/workqueue.h> 37#include <linux/workqueue.h>
38#include <net/genetlink.h>
39#include <net/netlink.h>
40#include <uapi/linux/batman_adv.h>
36 41
37#include "bat_algo.h" 42#include "bat_algo.h"
38#include "bat_v_elp.h" 43#include "bat_v_elp.h"
@@ -42,9 +47,12 @@
42#include "hard-interface.h" 47#include "hard-interface.h"
43#include "hash.h" 48#include "hash.h"
44#include "log.h" 49#include "log.h"
50#include "netlink.h"
45#include "originator.h" 51#include "originator.h"
46#include "packet.h" 52#include "packet.h"
47 53
54struct sk_buff;
55
48static void batadv_v_iface_activate(struct batadv_hard_iface *hard_iface) 56static void batadv_v_iface_activate(struct batadv_hard_iface *hard_iface)
49{ 57{
50 struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface); 58 struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
@@ -206,6 +214,138 @@ static void batadv_v_neigh_print(struct batadv_priv *bat_priv,
206} 214}
207 215
208/** 216/**
217 * batadv_v_neigh_dump_neigh - Dump a neighbour into a message
218 * @msg: Netlink message to dump into
219 * @portid: Port making netlink request
220 * @seq: Sequence number of netlink message
221 * @hardif_neigh: Neighbour to dump
222 *
223 * Return: Error code, or 0 on success
224 */
225static int
226batadv_v_neigh_dump_neigh(struct sk_buff *msg, u32 portid, u32 seq,
227 struct batadv_hardif_neigh_node *hardif_neigh)
228{
229 void *hdr;
230 unsigned int last_seen_msecs;
231 u32 throughput;
232
233 last_seen_msecs = jiffies_to_msecs(jiffies - hardif_neigh->last_seen);
234 throughput = ewma_throughput_read(&hardif_neigh->bat_v.throughput);
235 throughput = throughput * 100;
236
237 hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family, NLM_F_MULTI,
238 BATADV_CMD_GET_NEIGHBORS);
239 if (!hdr)
240 return -ENOBUFS;
241
242 if (nla_put(msg, BATADV_ATTR_NEIGH_ADDRESS, ETH_ALEN,
243 hardif_neigh->addr) ||
244 nla_put_u32(msg, BATADV_ATTR_HARD_IFINDEX,
245 hardif_neigh->if_incoming->net_dev->ifindex) ||
246 nla_put_u32(msg, BATADV_ATTR_LAST_SEEN_MSECS,
247 last_seen_msecs) ||
248 nla_put_u32(msg, BATADV_ATTR_THROUGHPUT, throughput))
249 goto nla_put_failure;
250
251 genlmsg_end(msg, hdr);
252 return 0;
253
254 nla_put_failure:
255 genlmsg_cancel(msg, hdr);
256 return -EMSGSIZE;
257}
258
259/**
260 * batadv_v_neigh_dump_hardif - Dump the neighbours of a hard interface into
261 * a message
262 * @msg: Netlink message to dump into
263 * @portid: Port making netlink request
264 * @seq: Sequence number of netlink message
265 * @bat_priv: The bat priv with all the soft interface information
266 * @hard_iface: The hard interface to be dumped
267 * @idx_s: Entries to be skipped
268 *
269 * This function assumes the caller holds rcu_read_lock().
270 *
271 * Return: Error code, or 0 on success
272 */
273static int
274batadv_v_neigh_dump_hardif(struct sk_buff *msg, u32 portid, u32 seq,
275 struct batadv_priv *bat_priv,
276 struct batadv_hard_iface *hard_iface,
277 int *idx_s)
278{
279 struct batadv_hardif_neigh_node *hardif_neigh;
280 int idx = 0;
281
282 hlist_for_each_entry_rcu(hardif_neigh,
283 &hard_iface->neigh_list, list) {
284 if (idx++ < *idx_s)
285 continue;
286
287 if (batadv_v_neigh_dump_neigh(msg, portid, seq, hardif_neigh)) {
288 *idx_s = idx - 1;
289 return -EMSGSIZE;
290 }
291 }
292
293 *idx_s = 0;
294 return 0;
295}
296
297/**
298 * batadv_v_neigh_dump - Dump the neighbours of a hard interface into a
299 * message
300 * @msg: Netlink message to dump into
301 * @cb: Control block containing additional options
302 * @bat_priv: The bat priv with all the soft interface information
303 * @single_hardif: Limit dumping to this hard interface
304 */
305static void
306batadv_v_neigh_dump(struct sk_buff *msg, struct netlink_callback *cb,
307 struct batadv_priv *bat_priv,
308 struct batadv_hard_iface *single_hardif)
309{
310 struct batadv_hard_iface *hard_iface;
311 int i_hardif = 0;
312 int i_hardif_s = cb->args[0];
313 int idx = cb->args[1];
314 int portid = NETLINK_CB(cb->skb).portid;
315
316 rcu_read_lock();
317 if (single_hardif) {
318 if (i_hardif_s == 0) {
319 if (batadv_v_neigh_dump_hardif(msg, portid,
320 cb->nlh->nlmsg_seq,
321 bat_priv, single_hardif,
322 &idx) == 0)
323 i_hardif++;
324 }
325 } else {
326 list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
327 if (hard_iface->soft_iface != bat_priv->soft_iface)
328 continue;
329
330 if (i_hardif++ < i_hardif_s)
331 continue;
332
333 if (batadv_v_neigh_dump_hardif(msg, portid,
334 cb->nlh->nlmsg_seq,
335 bat_priv, hard_iface,
336 &idx)) {
337 i_hardif--;
338 break;
339 }
340 }
341 }
342 rcu_read_unlock();
343
344 cb->args[0] = i_hardif;
345 cb->args[1] = idx;
346}
347
348/**
209 * batadv_v_orig_print - print the originator table 349 * batadv_v_orig_print - print the originator table
210 * @bat_priv: the bat priv with all the soft interface information 350 * @bat_priv: the bat priv with all the soft interface information
211 * @seq: debugfs table seq_file struct 351 * @seq: debugfs table seq_file struct
@@ -272,6 +412,204 @@ next:
272 seq_puts(seq, "No batman nodes in range ...\n"); 412 seq_puts(seq, "No batman nodes in range ...\n");
273} 413}
274 414
415/**
416 * batadv_v_orig_dump_subentry - Dump an originator subentry into a
417 * message
418 * @msg: Netlink message to dump into
419 * @portid: Port making netlink request
420 * @seq: Sequence number of netlink message
421 * @bat_priv: The bat priv with all the soft interface information
422 * @if_outgoing: Limit dump to entries with this outgoing interface
423 * @orig_node: Originator to dump
424 * @neigh_node: Single hops neighbour
425 * @best: Is the best originator
426 *
427 * Return: Error code, or 0 on success
428 */
429static int
430batadv_v_orig_dump_subentry(struct sk_buff *msg, u32 portid, u32 seq,
431 struct batadv_priv *bat_priv,
432 struct batadv_hard_iface *if_outgoing,
433 struct batadv_orig_node *orig_node,
434 struct batadv_neigh_node *neigh_node,
435 bool best)
436{
437 struct batadv_neigh_ifinfo *n_ifinfo;
438 unsigned int last_seen_msecs;
439 u32 throughput;
440 void *hdr;
441
442 n_ifinfo = batadv_neigh_ifinfo_get(neigh_node, if_outgoing);
443 if (!n_ifinfo)
444 return 0;
445
446 throughput = n_ifinfo->bat_v.throughput * 100;
447
448 batadv_neigh_ifinfo_put(n_ifinfo);
449
450 last_seen_msecs = jiffies_to_msecs(jiffies - orig_node->last_seen);
451
452 if (if_outgoing != BATADV_IF_DEFAULT &&
453 if_outgoing != neigh_node->if_incoming)
454 return 0;
455
456 hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family, NLM_F_MULTI,
457 BATADV_CMD_GET_ORIGINATORS);
458 if (!hdr)
459 return -ENOBUFS;
460
461 if (nla_put(msg, BATADV_ATTR_ORIG_ADDRESS, ETH_ALEN, orig_node->orig) ||
462 nla_put(msg, BATADV_ATTR_NEIGH_ADDRESS, ETH_ALEN,
463 neigh_node->addr) ||
464 nla_put_u32(msg, BATADV_ATTR_HARD_IFINDEX,
465 neigh_node->if_incoming->net_dev->ifindex) ||
466 nla_put_u32(msg, BATADV_ATTR_THROUGHPUT, throughput) ||
467 nla_put_u32(msg, BATADV_ATTR_LAST_SEEN_MSECS,
468 last_seen_msecs))
469 goto nla_put_failure;
470
471 if (best && nla_put_flag(msg, BATADV_ATTR_FLAG_BEST))
472 goto nla_put_failure;
473
474 genlmsg_end(msg, hdr);
475 return 0;
476
477 nla_put_failure:
478 genlmsg_cancel(msg, hdr);
479 return -EMSGSIZE;
480}
481
482/**
483 * batadv_v_orig_dump_entry - Dump an originator entry into a message
484 * @msg: Netlink message to dump into
485 * @portid: Port making netlink request
486 * @seq: Sequence number of netlink message
487 * @bat_priv: The bat priv with all the soft interface information
488 * @if_outgoing: Limit dump to entries with this outgoing interface
489 * @orig_node: Originator to dump
490 * @sub_s: Number of sub entries to skip
491 *
492 * This function assumes the caller holds rcu_read_lock().
493 *
494 * Return: Error code, or 0 on success
495 */
496static int
497batadv_v_orig_dump_entry(struct sk_buff *msg, u32 portid, u32 seq,
498 struct batadv_priv *bat_priv,
499 struct batadv_hard_iface *if_outgoing,
500 struct batadv_orig_node *orig_node, int *sub_s)
501{
502 struct batadv_neigh_node *neigh_node_best;
503 struct batadv_neigh_node *neigh_node;
504 int sub = 0;
505 bool best;
506
507 neigh_node_best = batadv_orig_router_get(orig_node, if_outgoing);
508 if (!neigh_node_best)
509 goto out;
510
511 hlist_for_each_entry_rcu(neigh_node, &orig_node->neigh_list, list) {
512 if (sub++ < *sub_s)
513 continue;
514
515 best = (neigh_node == neigh_node_best);
516
517 if (batadv_v_orig_dump_subentry(msg, portid, seq, bat_priv,
518 if_outgoing, orig_node,
519 neigh_node, best)) {
520 batadv_neigh_node_put(neigh_node_best);
521
522 *sub_s = sub - 1;
523 return -EMSGSIZE;
524 }
525 }
526
527 out:
528 if (neigh_node_best)
529 batadv_neigh_node_put(neigh_node_best);
530
531 *sub_s = 0;
532 return 0;
533}
534
535/**
536 * batadv_v_orig_dump_bucket - Dump an originator bucket into a
537 * message
538 * @msg: Netlink message to dump into
539 * @portid: Port making netlink request
540 * @seq: Sequence number of netlink message
541 * @bat_priv: The bat priv with all the soft interface information
542 * @if_outgoing: Limit dump to entries with this outgoing interface
543 * @head: Bucket to be dumped
544 * @idx_s: Number of entries to be skipped
545 * @sub: Number of sub entries to be skipped
546 *
547 * Return: Error code, or 0 on success
548 */
549static int
550batadv_v_orig_dump_bucket(struct sk_buff *msg, u32 portid, u32 seq,
551 struct batadv_priv *bat_priv,
552 struct batadv_hard_iface *if_outgoing,
553 struct hlist_head *head, int *idx_s, int *sub)
554{
555 struct batadv_orig_node *orig_node;
556 int idx = 0;
557
558 rcu_read_lock();
559 hlist_for_each_entry_rcu(orig_node, head, hash_entry) {
560 if (idx++ < *idx_s)
561 continue;
562
563 if (batadv_v_orig_dump_entry(msg, portid, seq, bat_priv,
564 if_outgoing, orig_node, sub)) {
565 rcu_read_unlock();
566 *idx_s = idx - 1;
567 return -EMSGSIZE;
568 }
569 }
570 rcu_read_unlock();
571
572 *idx_s = 0;
573 *sub = 0;
574 return 0;
575}
576
577/**
578 * batadv_v_orig_dump - Dump the originators into a message
579 * @msg: Netlink message to dump into
580 * @cb: Control block containing additional options
581 * @bat_priv: The bat priv with all the soft interface information
582 * @if_outgoing: Limit dump to entries with this outgoing interface
583 */
584static void
585batadv_v_orig_dump(struct sk_buff *msg, struct netlink_callback *cb,
586 struct batadv_priv *bat_priv,
587 struct batadv_hard_iface *if_outgoing)
588{
589 struct batadv_hashtable *hash = bat_priv->orig_hash;
590 struct hlist_head *head;
591 int bucket = cb->args[0];
592 int idx = cb->args[1];
593 int sub = cb->args[2];
594 int portid = NETLINK_CB(cb->skb).portid;
595
596 while (bucket < hash->size) {
597 head = &hash->table[bucket];
598
599 if (batadv_v_orig_dump_bucket(msg, portid,
600 cb->nlh->nlmsg_seq,
601 bat_priv, if_outgoing, head, &idx,
602 &sub))
603 break;
604
605 bucket++;
606 }
607
608 cb->args[0] = bucket;
609 cb->args[1] = idx;
610 cb->args[2] = sub;
611}
612
275static int batadv_v_neigh_cmp(struct batadv_neigh_node *neigh1, 613static int batadv_v_neigh_cmp(struct batadv_neigh_node *neigh1,
276 struct batadv_hard_iface *if_outgoing1, 614 struct batadv_hard_iface *if_outgoing1,
277 struct batadv_neigh_node *neigh2, 615 struct batadv_neigh_node *neigh2,
@@ -573,9 +911,11 @@ static struct batadv_algo_ops batadv_batman_v __read_mostly = {
573 .cmp = batadv_v_neigh_cmp, 911 .cmp = batadv_v_neigh_cmp,
574 .is_similar_or_better = batadv_v_neigh_is_sob, 912 .is_similar_or_better = batadv_v_neigh_is_sob,
575 .print = batadv_v_neigh_print, 913 .print = batadv_v_neigh_print,
914 .dump = batadv_v_neigh_dump,
576 }, 915 },
577 .orig = { 916 .orig = {
578 .print = batadv_v_orig_print, 917 .print = batadv_v_orig_print,
918 .dump = batadv_v_orig_dump,
579 }, 919 },
580 .gw = { 920 .gw = {
581 .store_sel_class = batadv_v_store_sel_class, 921 .store_sel_class = batadv_v_store_sel_class,
diff --git a/net/batman-adv/netlink.c b/net/batman-adv/netlink.c
index 0c7940cc1968..025f2ec2b27e 100644
--- a/net/batman-adv/netlink.c
+++ b/net/batman-adv/netlink.c
@@ -86,6 +86,7 @@ static struct nla_policy batadv_netlink_policy[NUM_BATADV_ATTR] = {
86 [BATADV_ATTR_LAST_SEEN_MSECS] = { .type = NLA_U32 }, 86 [BATADV_ATTR_LAST_SEEN_MSECS] = { .type = NLA_U32 },
87 [BATADV_ATTR_NEIGH_ADDRESS] = { .len = ETH_ALEN }, 87 [BATADV_ATTR_NEIGH_ADDRESS] = { .len = ETH_ALEN },
88 [BATADV_ATTR_TQ] = { .type = NLA_U8 }, 88 [BATADV_ATTR_TQ] = { .type = NLA_U8 },
89 [BATADV_ATTR_THROUGHPUT] = { .type = NLA_U32 },
89}; 90};
90 91
91/** 92/**