blob: 9dccfaf3211517a58d87acbdbdeb31b12b02d39e [file] [log] [blame]
Linus Luessingd6f94d92016-01-16 16:40:09 +08001/* Copyright (C) 2013-2016 B.A.T.M.A.N. contributors:
2 *
3 * Linus Lüssing, Marek Lindner
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of version 2 of the GNU General Public
7 * License as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see <http://www.gnu.org/licenses/>.
16 */
17
Sven Eckelmanna2d08162016-05-15 11:07:46 +020018#include "bat_v.h"
Linus Luessingd6f94d92016-01-16 16:40:09 +080019#include "main.h"
20
Antonio Quartulli0b5ecc62016-01-16 16:40:14 +080021#include <linux/atomic.h>
Antonio Quartulli97869062016-01-16 16:40:17 +080022#include <linux/bug.h>
Linus Luessingd6f94d92016-01-16 16:40:09 +080023#include <linux/cache.h>
Antonio Quartulli08686942016-07-03 12:46:32 +020024#include <linux/errno.h>
Matthias Schifferf02a4782016-07-03 13:31:41 +020025#include <linux/if_ether.h>
Linus Luessingd6f94d92016-01-16 16:40:09 +080026#include <linux/init.h>
Antonio Quartulli261e2642016-01-16 16:40:18 +080027#include <linux/jiffies.h>
Antonio Quartulli08686942016-07-03 12:46:32 +020028#include <linux/kernel.h>
Antonio Quartulli50164d82016-07-03 12:46:34 +020029#include <linux/kref.h>
Antonio Quartulli261e2642016-01-16 16:40:18 +080030#include <linux/netdevice.h>
Matthias Schifferf02a4782016-07-03 13:31:41 +020031#include <linux/netlink.h>
Antonio Quartulli261e2642016-01-16 16:40:18 +080032#include <linux/rculist.h>
33#include <linux/rcupdate.h>
34#include <linux/seq_file.h>
Sven Eckelmanna45e9322016-05-06 11:43:38 +020035#include <linux/stddef.h>
Antonio Quartulli97869062016-01-16 16:40:17 +080036#include <linux/types.h>
Antonio Quartullic8334842015-11-10 18:50:51 +010037#include <linux/workqueue.h>
Matthias Schifferf02a4782016-07-03 13:31:41 +020038#include <net/genetlink.h>
39#include <net/netlink.h>
40#include <uapi/linux/batman_adv.h>
Linus Luessingd6f94d92016-01-16 16:40:09 +080041
Sven Eckelmanna2d08162016-05-15 11:07:46 +020042#include "bat_algo.h"
Linus Luessingd6f94d92016-01-16 16:40:09 +080043#include "bat_v_elp.h"
Antonio Quartulli0da00352016-01-16 16:40:12 +080044#include "bat_v_ogm.h"
Antonio Quartulli08686942016-07-03 12:46:32 +020045#include "gateway_client.h"
46#include "gateway_common.h"
Antonio Quartullib6cf5d42016-04-14 09:37:05 +080047#include "hard-interface.h"
Antonio Quartulli261e2642016-01-16 16:40:18 +080048#include "hash.h"
Antonio Quartulli50164d82016-07-03 12:46:34 +020049#include "log.h"
Matthias Schifferf02a4782016-07-03 13:31:41 +020050#include "netlink.h"
Antonio Quartulli97869062016-01-16 16:40:17 +080051#include "originator.h"
Linus Luessing162bd642016-01-16 16:40:10 +080052#include "packet.h"
Linus Luessingd6f94d92016-01-16 16:40:09 +080053
Matthias Schifferf02a4782016-07-03 13:31:41 +020054struct sk_buff;
55
Antonio Quartullib6cf5d42016-04-14 09:37:05 +080056static void batadv_v_iface_activate(struct batadv_hard_iface *hard_iface)
57{
Marek Lindnerebe24ce2016-05-07 19:54:17 +080058 struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
59 struct batadv_hard_iface *primary_if;
60
61 primary_if = batadv_primary_if_get_selected(bat_priv);
62
63 if (primary_if) {
64 batadv_v_elp_iface_activate(primary_if, hard_iface);
65 batadv_hardif_put(primary_if);
66 }
67
Antonio Quartullib6cf5d42016-04-14 09:37:05 +080068 /* B.A.T.M.A.N. V does not use any queuing mechanism, therefore it can
69 * set the interface as ACTIVE right away, without any risk of race
70 * condition
71 */
72 if (hard_iface->if_status == BATADV_IF_TO_BE_ACTIVATED)
73 hard_iface->if_status = BATADV_IF_ACTIVE;
74}
75
Linus Luessingd6f94d92016-01-16 16:40:09 +080076static int batadv_v_iface_enable(struct batadv_hard_iface *hard_iface)
77{
Antonio Quartulli0da00352016-01-16 16:40:12 +080078 int ret;
79
80 ret = batadv_v_elp_iface_enable(hard_iface);
81 if (ret < 0)
82 return ret;
83
84 ret = batadv_v_ogm_iface_enable(hard_iface);
85 if (ret < 0)
86 batadv_v_elp_iface_disable(hard_iface);
87
88 return ret;
Linus Luessingd6f94d92016-01-16 16:40:09 +080089}
90
91static void batadv_v_iface_disable(struct batadv_hard_iface *hard_iface)
92{
93 batadv_v_elp_iface_disable(hard_iface);
94}
95
Linus Luessingd6f94d92016-01-16 16:40:09 +080096static void batadv_v_primary_iface_set(struct batadv_hard_iface *hard_iface)
97{
98 batadv_v_elp_primary_iface_set(hard_iface);
Antonio Quartulli0da00352016-01-16 16:40:12 +080099 batadv_v_ogm_primary_iface_set(hard_iface);
Linus Luessingd6f94d92016-01-16 16:40:09 +0800100}
101
Antonio Quartulli1653f612016-05-02 01:14:40 +0800102/**
103 * batadv_v_iface_update_mac - react to hard-interface MAC address change
104 * @hard_iface: the modified interface
105 *
106 * If the modified interface is the primary one, update the originator
107 * address in the ELP and OGM messages to reflect the new MAC address.
108 */
109static void batadv_v_iface_update_mac(struct batadv_hard_iface *hard_iface)
110{
111 struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
112 struct batadv_hard_iface *primary_if;
113
114 primary_if = batadv_primary_if_get_selected(bat_priv);
115 if (primary_if != hard_iface)
116 goto out;
117
118 batadv_v_primary_iface_set(hard_iface);
119out:
120 if (primary_if)
121 batadv_hardif_put(primary_if);
122}
123
Linus Luessing162bd642016-01-16 16:40:10 +0800124static void
125batadv_v_hardif_neigh_init(struct batadv_hardif_neigh_node *hardif_neigh)
126{
127 ewma_throughput_init(&hardif_neigh->bat_v.throughput);
Antonio Quartullic8334842015-11-10 18:50:51 +0100128 INIT_WORK(&hardif_neigh->bat_v.metric_work,
129 batadv_v_elp_throughput_metric_update);
Linus Luessing162bd642016-01-16 16:40:10 +0800130}
131
Antonio Quartulli261e2642016-01-16 16:40:18 +0800132/**
133 * batadv_v_orig_print_neigh - print neighbors for the originator table
134 * @orig_node: the orig_node for which the neighbors are printed
135 * @if_outgoing: outgoing interface for these entries
136 * @seq: debugfs table seq_file struct
137 *
138 * Must be called while holding an rcu lock.
139 */
140static void
141batadv_v_orig_print_neigh(struct batadv_orig_node *orig_node,
142 struct batadv_hard_iface *if_outgoing,
143 struct seq_file *seq)
144{
145 struct batadv_neigh_node *neigh_node;
146 struct batadv_neigh_ifinfo *n_ifinfo;
147
148 hlist_for_each_entry_rcu(neigh_node, &orig_node->neigh_list, list) {
149 n_ifinfo = batadv_neigh_ifinfo_get(neigh_node, if_outgoing);
150 if (!n_ifinfo)
151 continue;
152
153 seq_printf(seq, " %pM (%9u.%1u)",
154 neigh_node->addr,
155 n_ifinfo->bat_v.throughput / 10,
156 n_ifinfo->bat_v.throughput % 10);
157
158 batadv_neigh_ifinfo_put(n_ifinfo);
159 }
160}
161
162/**
Linus Luessing626d23e2016-01-16 16:40:19 +0800163 * batadv_v_hardif_neigh_print - print a single ELP neighbour node
164 * @seq: neighbour table seq_file struct
165 * @hardif_neigh: hardif neighbour information
166 */
167static void
168batadv_v_hardif_neigh_print(struct seq_file *seq,
169 struct batadv_hardif_neigh_node *hardif_neigh)
170{
171 int last_secs, last_msecs;
172 u32 throughput;
173
174 last_secs = jiffies_to_msecs(jiffies - hardif_neigh->last_seen) / 1000;
175 last_msecs = jiffies_to_msecs(jiffies - hardif_neigh->last_seen) % 1000;
176 throughput = ewma_throughput_read(&hardif_neigh->bat_v.throughput);
177
178 seq_printf(seq, "%pM %4i.%03is (%9u.%1u) [%10s]\n",
179 hardif_neigh->addr, last_secs, last_msecs, throughput / 10,
180 throughput % 10, hardif_neigh->if_incoming->net_dev->name);
181}
182
183/**
184 * batadv_v_neigh_print - print the single hop neighbour list
185 * @bat_priv: the bat priv with all the soft interface information
186 * @seq: neighbour table seq_file struct
187 */
188static void batadv_v_neigh_print(struct batadv_priv *bat_priv,
189 struct seq_file *seq)
190{
191 struct net_device *net_dev = (struct net_device *)seq->private;
192 struct batadv_hardif_neigh_node *hardif_neigh;
193 struct batadv_hard_iface *hard_iface;
194 int batman_count = 0;
195
Antonio Quartulli925a6f32016-03-12 10:30:18 +0100196 seq_puts(seq,
197 " Neighbor last-seen ( throughput) [ IF]\n");
Linus Luessing626d23e2016-01-16 16:40:19 +0800198
199 rcu_read_lock();
200 list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
201 if (hard_iface->soft_iface != net_dev)
202 continue;
203
204 hlist_for_each_entry_rcu(hardif_neigh,
205 &hard_iface->neigh_list, list) {
206 batadv_v_hardif_neigh_print(seq, hardif_neigh);
207 batman_count++;
208 }
209 }
210 rcu_read_unlock();
211
212 if (batman_count == 0)
213 seq_puts(seq, "No batman nodes in range ...\n");
214}
215
216/**
Matthias Schifferf02a4782016-07-03 13:31:41 +0200217 * 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/**
Antonio Quartulli261e2642016-01-16 16:40:18 +0800349 * batadv_v_orig_print - print the originator table
350 * @bat_priv: the bat priv with all the soft interface information
351 * @seq: debugfs table seq_file struct
352 * @if_outgoing: the outgoing interface for which this should be printed
353 */
354static void batadv_v_orig_print(struct batadv_priv *bat_priv,
355 struct seq_file *seq,
356 struct batadv_hard_iface *if_outgoing)
357{
358 struct batadv_neigh_node *neigh_node;
359 struct batadv_hashtable *hash = bat_priv->orig_hash;
360 int last_seen_msecs, last_seen_secs;
361 struct batadv_orig_node *orig_node;
362 struct batadv_neigh_ifinfo *n_ifinfo;
363 unsigned long last_seen_jiffies;
364 struct hlist_head *head;
365 int batman_count = 0;
366 u32 i;
367
Antonio Quartulli925a6f32016-03-12 10:30:18 +0100368 seq_puts(seq,
369 " Originator last-seen ( throughput) Nexthop [outgoingIF]: Potential nexthops ...\n");
Antonio Quartulli261e2642016-01-16 16:40:18 +0800370
371 for (i = 0; i < hash->size; i++) {
372 head = &hash->table[i];
373
374 rcu_read_lock();
375 hlist_for_each_entry_rcu(orig_node, head, hash_entry) {
376 neigh_node = batadv_orig_router_get(orig_node,
377 if_outgoing);
378 if (!neigh_node)
379 continue;
380
381 n_ifinfo = batadv_neigh_ifinfo_get(neigh_node,
382 if_outgoing);
383 if (!n_ifinfo)
384 goto next;
385
386 last_seen_jiffies = jiffies - orig_node->last_seen;
387 last_seen_msecs = jiffies_to_msecs(last_seen_jiffies);
388 last_seen_secs = last_seen_msecs / 1000;
389 last_seen_msecs = last_seen_msecs % 1000;
390
391 seq_printf(seq, "%pM %4i.%03is (%9u.%1u) %pM [%10s]:",
392 orig_node->orig, last_seen_secs,
393 last_seen_msecs,
394 n_ifinfo->bat_v.throughput / 10,
395 n_ifinfo->bat_v.throughput % 10,
396 neigh_node->addr,
397 neigh_node->if_incoming->net_dev->name);
398
399 batadv_v_orig_print_neigh(orig_node, if_outgoing, seq);
400 seq_puts(seq, "\n");
401 batman_count++;
402
403next:
404 batadv_neigh_node_put(neigh_node);
405 if (n_ifinfo)
406 batadv_neigh_ifinfo_put(n_ifinfo);
407 }
408 rcu_read_unlock();
409 }
410
411 if (batman_count == 0)
412 seq_puts(seq, "No batman nodes in range ...\n");
413}
414
Matthias Schifferf02a4782016-07-03 13:31:41 +0200415/**
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
Antonio Quartulli97869062016-01-16 16:40:17 +0800613static int batadv_v_neigh_cmp(struct batadv_neigh_node *neigh1,
614 struct batadv_hard_iface *if_outgoing1,
615 struct batadv_neigh_node *neigh2,
616 struct batadv_hard_iface *if_outgoing2)
617{
618 struct batadv_neigh_ifinfo *ifinfo1, *ifinfo2;
Sven Eckelmann71f9d272016-05-06 11:43:39 +0200619 int ret = 0;
Antonio Quartulli97869062016-01-16 16:40:17 +0800620
621 ifinfo1 = batadv_neigh_ifinfo_get(neigh1, if_outgoing1);
Sven Eckelmann71f9d272016-05-06 11:43:39 +0200622 if (WARN_ON(!ifinfo1))
623 goto err_ifinfo1;
624
Antonio Quartulli97869062016-01-16 16:40:17 +0800625 ifinfo2 = batadv_neigh_ifinfo_get(neigh2, if_outgoing2);
Sven Eckelmann71f9d272016-05-06 11:43:39 +0200626 if (WARN_ON(!ifinfo2))
627 goto err_ifinfo2;
Antonio Quartulli97869062016-01-16 16:40:17 +0800628
Sven Eckelmann71f9d272016-05-06 11:43:39 +0200629 ret = ifinfo1->bat_v.throughput - ifinfo2->bat_v.throughput;
Antonio Quartulli97869062016-01-16 16:40:17 +0800630
Sven Eckelmann71f9d272016-05-06 11:43:39 +0200631 batadv_neigh_ifinfo_put(ifinfo2);
632err_ifinfo2:
633 batadv_neigh_ifinfo_put(ifinfo1);
634err_ifinfo1:
635 return ret;
Antonio Quartulli97869062016-01-16 16:40:17 +0800636}
637
638static bool batadv_v_neigh_is_sob(struct batadv_neigh_node *neigh1,
639 struct batadv_hard_iface *if_outgoing1,
640 struct batadv_neigh_node *neigh2,
641 struct batadv_hard_iface *if_outgoing2)
642{
643 struct batadv_neigh_ifinfo *ifinfo1, *ifinfo2;
644 u32 threshold;
Sven Eckelmann71f9d272016-05-06 11:43:39 +0200645 bool ret = false;
Antonio Quartulli97869062016-01-16 16:40:17 +0800646
647 ifinfo1 = batadv_neigh_ifinfo_get(neigh1, if_outgoing1);
Sven Eckelmann71f9d272016-05-06 11:43:39 +0200648 if (WARN_ON(!ifinfo1))
649 goto err_ifinfo1;
Antonio Quartulli97869062016-01-16 16:40:17 +0800650
Sven Eckelmann71f9d272016-05-06 11:43:39 +0200651 ifinfo2 = batadv_neigh_ifinfo_get(neigh2, if_outgoing2);
652 if (WARN_ON(!ifinfo2))
653 goto err_ifinfo2;
Sven Eckelmanna45e9322016-05-06 11:43:38 +0200654
Antonio Quartulli97869062016-01-16 16:40:17 +0800655 threshold = ifinfo1->bat_v.throughput / 4;
656 threshold = ifinfo1->bat_v.throughput - threshold;
657
Sven Eckelmann71f9d272016-05-06 11:43:39 +0200658 ret = ifinfo2->bat_v.throughput > threshold;
659
660 batadv_neigh_ifinfo_put(ifinfo2);
661err_ifinfo2:
662 batadv_neigh_ifinfo_put(ifinfo1);
663err_ifinfo1:
664 return ret;
Antonio Quartulli97869062016-01-16 16:40:17 +0800665}
666
Antonio Quartulli08686942016-07-03 12:46:32 +0200667static ssize_t batadv_v_store_sel_class(struct batadv_priv *bat_priv,
668 char *buff, size_t count)
669{
670 u32 old_class, class;
671
672 if (!batadv_parse_throughput(bat_priv->soft_iface, buff,
673 "B.A.T.M.A.N. V GW selection class",
674 &class))
675 return -EINVAL;
676
677 old_class = atomic_read(&bat_priv->gw.sel_class);
678 atomic_set(&bat_priv->gw.sel_class, class);
679
680 if (old_class != class)
681 batadv_gw_reselect(bat_priv);
682
683 return count;
684}
685
686static ssize_t batadv_v_show_sel_class(struct batadv_priv *bat_priv, char *buff)
687{
688 u32 class = atomic_read(&bat_priv->gw.sel_class);
689
690 return sprintf(buff, "%u.%u MBit\n", class / 10, class % 10);
691}
692
Antonio Quartulli50164d82016-07-03 12:46:34 +0200693/**
694 * batadv_v_gw_throughput_get - retrieve the GW-bandwidth for a given GW
695 * @gw_node: the GW to retrieve the metric for
696 * @bw: the pointer where the metric will be stored. The metric is computed as
697 * the minimum between the GW advertised throughput and the path throughput to
698 * it in the mesh
699 *
700 * Return: 0 on success, -1 on failure
701 */
702static int batadv_v_gw_throughput_get(struct batadv_gw_node *gw_node, u32 *bw)
703{
704 struct batadv_neigh_ifinfo *router_ifinfo = NULL;
705 struct batadv_orig_node *orig_node;
706 struct batadv_neigh_node *router;
707 int ret = -1;
708
709 orig_node = gw_node->orig_node;
710 router = batadv_orig_router_get(orig_node, BATADV_IF_DEFAULT);
711 if (!router)
712 goto out;
713
714 router_ifinfo = batadv_neigh_ifinfo_get(router, BATADV_IF_DEFAULT);
715 if (!router_ifinfo)
716 goto out;
717
718 /* the GW metric is computed as the minimum between the path throughput
719 * to reach the GW itself and the advertised bandwidth.
720 * This gives us an approximation of the effective throughput that the
721 * client can expect via this particular GW node
722 */
723 *bw = router_ifinfo->bat_v.throughput;
724 *bw = min_t(u32, *bw, gw_node->bandwidth_down);
725
726 ret = 0;
727out:
728 if (router)
729 batadv_neigh_node_put(router);
730 if (router_ifinfo)
731 batadv_neigh_ifinfo_put(router_ifinfo);
732
733 return ret;
734}
735
736/**
737 * batadv_v_gw_get_best_gw_node - retrieve the best GW node
738 * @bat_priv: the bat priv with all the soft interface information
739 *
740 * Return: the GW node having the best GW-metric, NULL if no GW is known
741 */
742static struct batadv_gw_node *
743batadv_v_gw_get_best_gw_node(struct batadv_priv *bat_priv)
744{
745 struct batadv_gw_node *gw_node, *curr_gw = NULL;
746 u32 max_bw = 0, bw;
747
748 rcu_read_lock();
749 hlist_for_each_entry_rcu(gw_node, &bat_priv->gw.list, list) {
750 if (!kref_get_unless_zero(&gw_node->refcount))
751 continue;
752
753 if (batadv_v_gw_throughput_get(gw_node, &bw) < 0)
754 goto next;
755
756 if (curr_gw && (bw <= max_bw))
757 goto next;
758
759 if (curr_gw)
760 batadv_gw_node_put(curr_gw);
761
762 curr_gw = gw_node;
763 kref_get(&curr_gw->refcount);
764 max_bw = bw;
765
766next:
767 batadv_gw_node_put(gw_node);
768 }
769 rcu_read_unlock();
770
771 return curr_gw;
772}
773
774/**
775 * batadv_v_gw_is_eligible - check if a originator would be selected as GW
776 * @bat_priv: the bat priv with all the soft interface information
777 * @curr_gw_orig: originator representing the currently selected GW
778 * @orig_node: the originator representing the new candidate
779 *
780 * Return: true if orig_node can be selected as current GW, false otherwise
781 */
782static bool batadv_v_gw_is_eligible(struct batadv_priv *bat_priv,
783 struct batadv_orig_node *curr_gw_orig,
784 struct batadv_orig_node *orig_node)
785{
786 struct batadv_gw_node *curr_gw = NULL, *orig_gw = NULL;
787 u32 gw_throughput, orig_throughput, threshold;
788 bool ret = false;
789
790 threshold = atomic_read(&bat_priv->gw.sel_class);
791
792 curr_gw = batadv_gw_node_get(bat_priv, curr_gw_orig);
793 if (!curr_gw) {
794 ret = true;
795 goto out;
796 }
797
798 if (batadv_v_gw_throughput_get(curr_gw, &gw_throughput) < 0) {
799 ret = true;
800 goto out;
801 }
802
803 orig_gw = batadv_gw_node_get(bat_priv, orig_node);
804 if (!orig_node)
805 goto out;
806
807 if (batadv_v_gw_throughput_get(orig_gw, &orig_throughput) < 0)
808 goto out;
809
810 if (orig_throughput < gw_throughput)
811 goto out;
812
813 if ((orig_throughput - gw_throughput) < threshold)
814 goto out;
815
816 batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
817 "Restarting gateway selection: better gateway found (throughput curr: %u, throughput new: %u)\n",
818 gw_throughput, orig_throughput);
819
820 ret = true;
821out:
822 if (curr_gw)
823 batadv_gw_node_put(curr_gw);
824 if (orig_gw)
825 batadv_gw_node_put(orig_gw);
826
827 return ret;
828}
829
830/* fails if orig_node has no router */
831static int batadv_v_gw_write_buffer_text(struct batadv_priv *bat_priv,
832 struct seq_file *seq,
833 const struct batadv_gw_node *gw_node)
834{
835 struct batadv_gw_node *curr_gw;
836 struct batadv_neigh_node *router;
837 struct batadv_neigh_ifinfo *router_ifinfo = NULL;
838 int ret = -1;
839
840 router = batadv_orig_router_get(gw_node->orig_node, BATADV_IF_DEFAULT);
841 if (!router)
842 goto out;
843
844 router_ifinfo = batadv_neigh_ifinfo_get(router, BATADV_IF_DEFAULT);
845 if (!router_ifinfo)
846 goto out;
847
848 curr_gw = batadv_gw_get_selected_gw_node(bat_priv);
849
850 seq_printf(seq, "%s %pM (%9u.%1u) %pM [%10s]: %u.%u/%u.%u MBit\n",
851 (curr_gw == gw_node ? "=>" : " "),
852 gw_node->orig_node->orig,
853 router_ifinfo->bat_v.throughput / 10,
854 router_ifinfo->bat_v.throughput % 10, router->addr,
855 router->if_incoming->net_dev->name,
856 gw_node->bandwidth_down / 10,
857 gw_node->bandwidth_down % 10,
858 gw_node->bandwidth_up / 10,
859 gw_node->bandwidth_up % 10);
860 ret = seq_has_overflowed(seq) ? -1 : 0;
861
862 if (curr_gw)
863 batadv_gw_node_put(curr_gw);
864out:
865 if (router_ifinfo)
866 batadv_neigh_ifinfo_put(router_ifinfo);
867 if (router)
868 batadv_neigh_node_put(router);
869 return ret;
870}
871
872/**
873 * batadv_v_gw_print - print the gateway list
874 * @bat_priv: the bat priv with all the soft interface information
875 * @seq: gateway table seq_file struct
876 */
877static void batadv_v_gw_print(struct batadv_priv *bat_priv,
878 struct seq_file *seq)
879{
880 struct batadv_gw_node *gw_node;
881 int gw_count = 0;
882
883 seq_puts(seq,
884 " Gateway ( throughput) Nexthop [outgoingIF]: advertised uplink bandwidth\n");
885
886 rcu_read_lock();
887 hlist_for_each_entry_rcu(gw_node, &bat_priv->gw.list, list) {
888 /* fails if orig_node has no router */
889 if (batadv_v_gw_write_buffer_text(bat_priv, seq, gw_node) < 0)
890 continue;
891
892 gw_count++;
893 }
894 rcu_read_unlock();
895
896 if (gw_count == 0)
897 seq_puts(seq, "No gateways in range ...\n");
898}
899
Linus Luessingd6f94d92016-01-16 16:40:09 +0800900static struct batadv_algo_ops batadv_batman_v __read_mostly = {
901 .name = "BATMAN_V",
Antonio Quartulli29824a52016-05-25 23:27:31 +0800902 .iface = {
903 .activate = batadv_v_iface_activate,
904 .enable = batadv_v_iface_enable,
905 .disable = batadv_v_iface_disable,
906 .update_mac = batadv_v_iface_update_mac,
907 .primary_set = batadv_v_primary_iface_set,
908 },
909 .neigh = {
910 .hardif_init = batadv_v_hardif_neigh_init,
911 .cmp = batadv_v_neigh_cmp,
912 .is_similar_or_better = batadv_v_neigh_is_sob,
913 .print = batadv_v_neigh_print,
Matthias Schifferf02a4782016-07-03 13:31:41 +0200914 .dump = batadv_v_neigh_dump,
Antonio Quartulli29824a52016-05-25 23:27:31 +0800915 },
916 .orig = {
917 .print = batadv_v_orig_print,
Matthias Schifferf02a4782016-07-03 13:31:41 +0200918 .dump = batadv_v_orig_dump,
Antonio Quartulli29824a52016-05-25 23:27:31 +0800919 },
Antonio Quartulli08686942016-07-03 12:46:32 +0200920 .gw = {
921 .store_sel_class = batadv_v_store_sel_class,
922 .show_sel_class = batadv_v_show_sel_class,
Antonio Quartulli50164d82016-07-03 12:46:34 +0200923 .get_best_gw_node = batadv_v_gw_get_best_gw_node,
924 .is_eligible = batadv_v_gw_is_eligible,
925 .print = batadv_v_gw_print,
Antonio Quartulli08686942016-07-03 12:46:32 +0200926 },
Linus Luessingd6f94d92016-01-16 16:40:09 +0800927};
928
929/**
Marek Lindner7db682d2016-05-10 22:31:59 +0800930 * batadv_v_hardif_init - initialize the algorithm specific fields in the
931 * hard-interface object
932 * @hard_iface: the hard-interface to initialize
933 */
934void batadv_v_hardif_init(struct batadv_hard_iface *hard_iface)
935{
936 /* enable link throughput auto-detection by setting the throughput
937 * override to zero
938 */
939 atomic_set(&hard_iface->bat_v.throughput_override, 0);
940 atomic_set(&hard_iface->bat_v.elp_interval, 500);
941}
942
943/**
Antonio Quartulli0da00352016-01-16 16:40:12 +0800944 * batadv_v_mesh_init - initialize the B.A.T.M.A.N. V private resources for a
945 * mesh
946 * @bat_priv: the object representing the mesh interface to initialise
947 *
948 * Return: 0 on success or a negative error code otherwise
949 */
950int batadv_v_mesh_init(struct batadv_priv *bat_priv)
951{
Antonio Quartulli50164d82016-07-03 12:46:34 +0200952 int ret = 0;
953
954 ret = batadv_v_ogm_init(bat_priv);
955 if (ret < 0)
956 return ret;
957
958 /* set default throughput difference threshold to 5Mbps */
959 atomic_set(&bat_priv->gw.sel_class, 50);
960
961 return 0;
Antonio Quartulli0da00352016-01-16 16:40:12 +0800962}
963
964/**
965 * batadv_v_mesh_free - free the B.A.T.M.A.N. V private resources for a mesh
966 * @bat_priv: the object representing the mesh interface to free
967 */
968void batadv_v_mesh_free(struct batadv_priv *bat_priv)
969{
970 batadv_v_ogm_free(bat_priv);
971}
972
973/**
Linus Luessingd6f94d92016-01-16 16:40:09 +0800974 * batadv_v_init - B.A.T.M.A.N. V initialization function
975 *
976 * Description: Takes care of initializing all the subcomponents.
977 * It is invoked upon module load only.
978 *
979 * Return: 0 on success or a negative error code otherwise
980 */
981int __init batadv_v_init(void)
982{
Linus Luessing162bd642016-01-16 16:40:10 +0800983 int ret;
984
985 /* B.A.T.M.A.N. V echo location protocol packet */
986 ret = batadv_recv_handler_register(BATADV_ELP,
987 batadv_v_elp_packet_recv);
988 if (ret < 0)
989 return ret;
990
Antonio Quartulli0da00352016-01-16 16:40:12 +0800991 ret = batadv_recv_handler_register(BATADV_OGM2,
992 batadv_v_ogm_packet_recv);
Linus Luessing162bd642016-01-16 16:40:10 +0800993 if (ret < 0)
Antonio Quartulli0da00352016-01-16 16:40:12 +0800994 goto elp_unregister;
995
996 ret = batadv_algo_register(&batadv_batman_v);
997 if (ret < 0)
998 goto ogm_unregister;
999
1000 return ret;
1001
1002ogm_unregister:
1003 batadv_recv_handler_unregister(BATADV_OGM2);
1004
1005elp_unregister:
1006 batadv_recv_handler_unregister(BATADV_ELP);
Linus Luessing162bd642016-01-16 16:40:10 +08001007
1008 return ret;
Linus Luessingd6f94d92016-01-16 16:40:09 +08001009}