Merge branch 'perf/urgent' into perf/core, to pick up fixes
[linux-2.6-microblaze.git] / net / batman-adv / bat_v.c
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (C) B.A.T.M.A.N. contributors:
3  *
4  * Linus Lüssing, Marek Lindner
5  */
6
7 #include "bat_v.h"
8 #include "main.h"
9
10 #include <linux/atomic.h>
11 #include <linux/cache.h>
12 #include <linux/errno.h>
13 #include <linux/if_ether.h>
14 #include <linux/init.h>
15 #include <linux/jiffies.h>
16 #include <linux/kref.h>
17 #include <linux/list.h>
18 #include <linux/minmax.h>
19 #include <linux/netdevice.h>
20 #include <linux/netlink.h>
21 #include <linux/rculist.h>
22 #include <linux/rcupdate.h>
23 #include <linux/skbuff.h>
24 #include <linux/spinlock.h>
25 #include <linux/stddef.h>
26 #include <linux/types.h>
27 #include <linux/workqueue.h>
28 #include <net/genetlink.h>
29 #include <net/netlink.h>
30 #include <uapi/linux/batadv_packet.h>
31 #include <uapi/linux/batman_adv.h>
32
33 #include "bat_algo.h"
34 #include "bat_v_elp.h"
35 #include "bat_v_ogm.h"
36 #include "gateway_client.h"
37 #include "gateway_common.h"
38 #include "hard-interface.h"
39 #include "hash.h"
40 #include "log.h"
41 #include "netlink.h"
42 #include "originator.h"
43
44 static void batadv_v_iface_activate(struct batadv_hard_iface *hard_iface)
45 {
46         struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
47         struct batadv_hard_iface *primary_if;
48
49         primary_if = batadv_primary_if_get_selected(bat_priv);
50
51         if (primary_if) {
52                 batadv_v_elp_iface_activate(primary_if, hard_iface);
53                 batadv_hardif_put(primary_if);
54         }
55
56         /* B.A.T.M.A.N. V does not use any queuing mechanism, therefore it can
57          * set the interface as ACTIVE right away, without any risk of race
58          * condition
59          */
60         if (hard_iface->if_status == BATADV_IF_TO_BE_ACTIVATED)
61                 hard_iface->if_status = BATADV_IF_ACTIVE;
62 }
63
64 static int batadv_v_iface_enable(struct batadv_hard_iface *hard_iface)
65 {
66         int ret;
67
68         ret = batadv_v_elp_iface_enable(hard_iface);
69         if (ret < 0)
70                 return ret;
71
72         ret = batadv_v_ogm_iface_enable(hard_iface);
73         if (ret < 0)
74                 batadv_v_elp_iface_disable(hard_iface);
75
76         return ret;
77 }
78
79 static void batadv_v_iface_disable(struct batadv_hard_iface *hard_iface)
80 {
81         batadv_v_ogm_iface_disable(hard_iface);
82         batadv_v_elp_iface_disable(hard_iface);
83 }
84
85 static void batadv_v_primary_iface_set(struct batadv_hard_iface *hard_iface)
86 {
87         batadv_v_elp_primary_iface_set(hard_iface);
88         batadv_v_ogm_primary_iface_set(hard_iface);
89 }
90
91 /**
92  * batadv_v_iface_update_mac() - react to hard-interface MAC address change
93  * @hard_iface: the modified interface
94  *
95  * If the modified interface is the primary one, update the originator
96  * address in the ELP and OGM messages to reflect the new MAC address.
97  */
98 static void batadv_v_iface_update_mac(struct batadv_hard_iface *hard_iface)
99 {
100         struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
101         struct batadv_hard_iface *primary_if;
102
103         primary_if = batadv_primary_if_get_selected(bat_priv);
104         if (primary_if != hard_iface)
105                 goto out;
106
107         batadv_v_primary_iface_set(hard_iface);
108 out:
109         if (primary_if)
110                 batadv_hardif_put(primary_if);
111 }
112
113 static void
114 batadv_v_hardif_neigh_init(struct batadv_hardif_neigh_node *hardif_neigh)
115 {
116         ewma_throughput_init(&hardif_neigh->bat_v.throughput);
117         INIT_WORK(&hardif_neigh->bat_v.metric_work,
118                   batadv_v_elp_throughput_metric_update);
119 }
120
121 /**
122  * batadv_v_neigh_dump_neigh() - Dump a neighbour into a message
123  * @msg: Netlink message to dump into
124  * @portid: Port making netlink request
125  * @seq: Sequence number of netlink message
126  * @hardif_neigh: Neighbour to dump
127  *
128  * Return: Error code, or 0 on success
129  */
130 static int
131 batadv_v_neigh_dump_neigh(struct sk_buff *msg, u32 portid, u32 seq,
132                           struct batadv_hardif_neigh_node *hardif_neigh)
133 {
134         void *hdr;
135         unsigned int last_seen_msecs;
136         u32 throughput;
137
138         last_seen_msecs = jiffies_to_msecs(jiffies - hardif_neigh->last_seen);
139         throughput = ewma_throughput_read(&hardif_neigh->bat_v.throughput);
140         throughput = throughput * 100;
141
142         hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family, NLM_F_MULTI,
143                           BATADV_CMD_GET_NEIGHBORS);
144         if (!hdr)
145                 return -ENOBUFS;
146
147         if (nla_put(msg, BATADV_ATTR_NEIGH_ADDRESS, ETH_ALEN,
148                     hardif_neigh->addr) ||
149             nla_put_string(msg, BATADV_ATTR_HARD_IFNAME,
150                            hardif_neigh->if_incoming->net_dev->name) ||
151             nla_put_u32(msg, BATADV_ATTR_HARD_IFINDEX,
152                         hardif_neigh->if_incoming->net_dev->ifindex) ||
153             nla_put_u32(msg, BATADV_ATTR_LAST_SEEN_MSECS,
154                         last_seen_msecs) ||
155             nla_put_u32(msg, BATADV_ATTR_THROUGHPUT, throughput))
156                 goto nla_put_failure;
157
158         genlmsg_end(msg, hdr);
159         return 0;
160
161  nla_put_failure:
162         genlmsg_cancel(msg, hdr);
163         return -EMSGSIZE;
164 }
165
166 /**
167  * batadv_v_neigh_dump_hardif() - Dump the  neighbours of a hard interface into
168  *  a message
169  * @msg: Netlink message to dump into
170  * @portid: Port making netlink request
171  * @seq: Sequence number of netlink message
172  * @bat_priv: The bat priv with all the soft interface information
173  * @hard_iface: The hard interface to be dumped
174  * @idx_s: Entries to be skipped
175  *
176  * This function assumes the caller holds rcu_read_lock().
177  *
178  * Return: Error code, or 0 on success
179  */
180 static int
181 batadv_v_neigh_dump_hardif(struct sk_buff *msg, u32 portid, u32 seq,
182                            struct batadv_priv *bat_priv,
183                            struct batadv_hard_iface *hard_iface,
184                            int *idx_s)
185 {
186         struct batadv_hardif_neigh_node *hardif_neigh;
187         int idx = 0;
188
189         hlist_for_each_entry_rcu(hardif_neigh,
190                                  &hard_iface->neigh_list, list) {
191                 if (idx++ < *idx_s)
192                         continue;
193
194                 if (batadv_v_neigh_dump_neigh(msg, portid, seq, hardif_neigh)) {
195                         *idx_s = idx - 1;
196                         return -EMSGSIZE;
197                 }
198         }
199
200         *idx_s = 0;
201         return 0;
202 }
203
204 /**
205  * batadv_v_neigh_dump() - Dump the neighbours of a hard interface  into a
206  *  message
207  * @msg: Netlink message to dump into
208  * @cb: Control block containing additional options
209  * @bat_priv: The bat priv with all the soft interface information
210  * @single_hardif: Limit dumping to this hard interface
211  */
212 static void
213 batadv_v_neigh_dump(struct sk_buff *msg, struct netlink_callback *cb,
214                     struct batadv_priv *bat_priv,
215                     struct batadv_hard_iface *single_hardif)
216 {
217         struct batadv_hard_iface *hard_iface;
218         int i_hardif = 0;
219         int i_hardif_s = cb->args[0];
220         int idx = cb->args[1];
221         int portid = NETLINK_CB(cb->skb).portid;
222
223         rcu_read_lock();
224         if (single_hardif) {
225                 if (i_hardif_s == 0) {
226                         if (batadv_v_neigh_dump_hardif(msg, portid,
227                                                        cb->nlh->nlmsg_seq,
228                                                        bat_priv, single_hardif,
229                                                        &idx) == 0)
230                                 i_hardif++;
231                 }
232         } else {
233                 list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
234                         if (hard_iface->soft_iface != bat_priv->soft_iface)
235                                 continue;
236
237                         if (i_hardif++ < i_hardif_s)
238                                 continue;
239
240                         if (batadv_v_neigh_dump_hardif(msg, portid,
241                                                        cb->nlh->nlmsg_seq,
242                                                        bat_priv, hard_iface,
243                                                        &idx)) {
244                                 i_hardif--;
245                                 break;
246                         }
247                 }
248         }
249         rcu_read_unlock();
250
251         cb->args[0] = i_hardif;
252         cb->args[1] = idx;
253 }
254
255 /**
256  * batadv_v_orig_dump_subentry() - Dump an originator subentry into a message
257  * @msg: Netlink message to dump into
258  * @portid: Port making netlink request
259  * @seq: Sequence number of netlink message
260  * @bat_priv: The bat priv with all the soft interface information
261  * @if_outgoing: Limit dump to entries with this outgoing interface
262  * @orig_node: Originator to dump
263  * @neigh_node: Single hops neighbour
264  * @best: Is the best originator
265  *
266  * Return: Error code, or 0 on success
267  */
268 static int
269 batadv_v_orig_dump_subentry(struct sk_buff *msg, u32 portid, u32 seq,
270                             struct batadv_priv *bat_priv,
271                             struct batadv_hard_iface *if_outgoing,
272                             struct batadv_orig_node *orig_node,
273                             struct batadv_neigh_node *neigh_node,
274                             bool best)
275 {
276         struct batadv_neigh_ifinfo *n_ifinfo;
277         unsigned int last_seen_msecs;
278         u32 throughput;
279         void *hdr;
280
281         n_ifinfo = batadv_neigh_ifinfo_get(neigh_node, if_outgoing);
282         if (!n_ifinfo)
283                 return 0;
284
285         throughput = n_ifinfo->bat_v.throughput * 100;
286
287         batadv_neigh_ifinfo_put(n_ifinfo);
288
289         last_seen_msecs = jiffies_to_msecs(jiffies - orig_node->last_seen);
290
291         if (if_outgoing != BATADV_IF_DEFAULT &&
292             if_outgoing != neigh_node->if_incoming)
293                 return 0;
294
295         hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family, NLM_F_MULTI,
296                           BATADV_CMD_GET_ORIGINATORS);
297         if (!hdr)
298                 return -ENOBUFS;
299
300         if (nla_put(msg, BATADV_ATTR_ORIG_ADDRESS, ETH_ALEN, orig_node->orig) ||
301             nla_put(msg, BATADV_ATTR_NEIGH_ADDRESS, ETH_ALEN,
302                     neigh_node->addr) ||
303             nla_put_string(msg, BATADV_ATTR_HARD_IFNAME,
304                            neigh_node->if_incoming->net_dev->name) ||
305             nla_put_u32(msg, BATADV_ATTR_HARD_IFINDEX,
306                         neigh_node->if_incoming->net_dev->ifindex) ||
307             nla_put_u32(msg, BATADV_ATTR_THROUGHPUT, throughput) ||
308             nla_put_u32(msg, BATADV_ATTR_LAST_SEEN_MSECS,
309                         last_seen_msecs))
310                 goto nla_put_failure;
311
312         if (best && nla_put_flag(msg, BATADV_ATTR_FLAG_BEST))
313                 goto nla_put_failure;
314
315         genlmsg_end(msg, hdr);
316         return 0;
317
318  nla_put_failure:
319         genlmsg_cancel(msg, hdr);
320         return -EMSGSIZE;
321 }
322
323 /**
324  * batadv_v_orig_dump_entry() - Dump an originator entry into a message
325  * @msg: Netlink message to dump into
326  * @portid: Port making netlink request
327  * @seq: Sequence number of netlink message
328  * @bat_priv: The bat priv with all the soft interface information
329  * @if_outgoing: Limit dump to entries with this outgoing interface
330  * @orig_node: Originator to dump
331  * @sub_s: Number of sub entries to skip
332  *
333  * This function assumes the caller holds rcu_read_lock().
334  *
335  * Return: Error code, or 0 on success
336  */
337 static int
338 batadv_v_orig_dump_entry(struct sk_buff *msg, u32 portid, u32 seq,
339                          struct batadv_priv *bat_priv,
340                          struct batadv_hard_iface *if_outgoing,
341                          struct batadv_orig_node *orig_node, int *sub_s)
342 {
343         struct batadv_neigh_node *neigh_node_best;
344         struct batadv_neigh_node *neigh_node;
345         int sub = 0;
346         bool best;
347
348         neigh_node_best = batadv_orig_router_get(orig_node, if_outgoing);
349         if (!neigh_node_best)
350                 goto out;
351
352         hlist_for_each_entry_rcu(neigh_node, &orig_node->neigh_list, list) {
353                 if (sub++ < *sub_s)
354                         continue;
355
356                 best = (neigh_node == neigh_node_best);
357
358                 if (batadv_v_orig_dump_subentry(msg, portid, seq, bat_priv,
359                                                 if_outgoing, orig_node,
360                                                 neigh_node, best)) {
361                         batadv_neigh_node_put(neigh_node_best);
362
363                         *sub_s = sub - 1;
364                         return -EMSGSIZE;
365                 }
366         }
367
368  out:
369         if (neigh_node_best)
370                 batadv_neigh_node_put(neigh_node_best);
371
372         *sub_s = 0;
373         return 0;
374 }
375
376 /**
377  * batadv_v_orig_dump_bucket() - Dump an originator bucket into a message
378  * @msg: Netlink message to dump into
379  * @portid: Port making netlink request
380  * @seq: Sequence number of netlink message
381  * @bat_priv: The bat priv with all the soft interface information
382  * @if_outgoing: Limit dump to entries with this outgoing interface
383  * @head: Bucket to be dumped
384  * @idx_s: Number of entries to be skipped
385  * @sub: Number of sub entries to be skipped
386  *
387  * Return: Error code, or 0 on success
388  */
389 static int
390 batadv_v_orig_dump_bucket(struct sk_buff *msg, u32 portid, u32 seq,
391                           struct batadv_priv *bat_priv,
392                           struct batadv_hard_iface *if_outgoing,
393                           struct hlist_head *head, int *idx_s, int *sub)
394 {
395         struct batadv_orig_node *orig_node;
396         int idx = 0;
397
398         rcu_read_lock();
399         hlist_for_each_entry_rcu(orig_node, head, hash_entry) {
400                 if (idx++ < *idx_s)
401                         continue;
402
403                 if (batadv_v_orig_dump_entry(msg, portid, seq, bat_priv,
404                                              if_outgoing, orig_node, sub)) {
405                         rcu_read_unlock();
406                         *idx_s = idx - 1;
407                         return -EMSGSIZE;
408                 }
409         }
410         rcu_read_unlock();
411
412         *idx_s = 0;
413         *sub = 0;
414         return 0;
415 }
416
417 /**
418  * batadv_v_orig_dump() - Dump the originators into a message
419  * @msg: Netlink message to dump into
420  * @cb: Control block containing additional options
421  * @bat_priv: The bat priv with all the soft interface information
422  * @if_outgoing: Limit dump to entries with this outgoing interface
423  */
424 static void
425 batadv_v_orig_dump(struct sk_buff *msg, struct netlink_callback *cb,
426                    struct batadv_priv *bat_priv,
427                    struct batadv_hard_iface *if_outgoing)
428 {
429         struct batadv_hashtable *hash = bat_priv->orig_hash;
430         struct hlist_head *head;
431         int bucket = cb->args[0];
432         int idx = cb->args[1];
433         int sub = cb->args[2];
434         int portid = NETLINK_CB(cb->skb).portid;
435
436         while (bucket < hash->size) {
437                 head = &hash->table[bucket];
438
439                 if (batadv_v_orig_dump_bucket(msg, portid,
440                                               cb->nlh->nlmsg_seq,
441                                               bat_priv, if_outgoing, head, &idx,
442                                               &sub))
443                         break;
444
445                 bucket++;
446         }
447
448         cb->args[0] = bucket;
449         cb->args[1] = idx;
450         cb->args[2] = sub;
451 }
452
453 static int batadv_v_neigh_cmp(struct batadv_neigh_node *neigh1,
454                               struct batadv_hard_iface *if_outgoing1,
455                               struct batadv_neigh_node *neigh2,
456                               struct batadv_hard_iface *if_outgoing2)
457 {
458         struct batadv_neigh_ifinfo *ifinfo1, *ifinfo2;
459         int ret = 0;
460
461         ifinfo1 = batadv_neigh_ifinfo_get(neigh1, if_outgoing1);
462         if (!ifinfo1)
463                 goto err_ifinfo1;
464
465         ifinfo2 = batadv_neigh_ifinfo_get(neigh2, if_outgoing2);
466         if (!ifinfo2)
467                 goto err_ifinfo2;
468
469         ret = ifinfo1->bat_v.throughput - ifinfo2->bat_v.throughput;
470
471         batadv_neigh_ifinfo_put(ifinfo2);
472 err_ifinfo2:
473         batadv_neigh_ifinfo_put(ifinfo1);
474 err_ifinfo1:
475         return ret;
476 }
477
478 static bool batadv_v_neigh_is_sob(struct batadv_neigh_node *neigh1,
479                                   struct batadv_hard_iface *if_outgoing1,
480                                   struct batadv_neigh_node *neigh2,
481                                   struct batadv_hard_iface *if_outgoing2)
482 {
483         struct batadv_neigh_ifinfo *ifinfo1, *ifinfo2;
484         u32 threshold;
485         bool ret = false;
486
487         ifinfo1 = batadv_neigh_ifinfo_get(neigh1, if_outgoing1);
488         if (!ifinfo1)
489                 goto err_ifinfo1;
490
491         ifinfo2 = batadv_neigh_ifinfo_get(neigh2, if_outgoing2);
492         if (!ifinfo2)
493                 goto err_ifinfo2;
494
495         threshold = ifinfo1->bat_v.throughput / 4;
496         threshold = ifinfo1->bat_v.throughput - threshold;
497
498         ret = ifinfo2->bat_v.throughput > threshold;
499
500         batadv_neigh_ifinfo_put(ifinfo2);
501 err_ifinfo2:
502         batadv_neigh_ifinfo_put(ifinfo1);
503 err_ifinfo1:
504         return ret;
505 }
506
507 /**
508  * batadv_v_init_sel_class() - initialize GW selection class
509  * @bat_priv: the bat priv with all the soft interface information
510  */
511 static void batadv_v_init_sel_class(struct batadv_priv *bat_priv)
512 {
513         /* set default throughput difference threshold to 5Mbps */
514         atomic_set(&bat_priv->gw.sel_class, 50);
515 }
516
517 static ssize_t batadv_v_store_sel_class(struct batadv_priv *bat_priv,
518                                         char *buff, size_t count)
519 {
520         u32 old_class, class;
521
522         if (!batadv_parse_throughput(bat_priv->soft_iface, buff,
523                                      "B.A.T.M.A.N. V GW selection class",
524                                      &class))
525                 return -EINVAL;
526
527         old_class = atomic_read(&bat_priv->gw.sel_class);
528         atomic_set(&bat_priv->gw.sel_class, class);
529
530         if (old_class != class)
531                 batadv_gw_reselect(bat_priv);
532
533         return count;
534 }
535
536 /**
537  * batadv_v_gw_throughput_get() - retrieve the GW-bandwidth for a given GW
538  * @gw_node: the GW to retrieve the metric for
539  * @bw: the pointer where the metric will be stored. The metric is computed as
540  *  the minimum between the GW advertised throughput and the path throughput to
541  *  it in the mesh
542  *
543  * Return: 0 on success, -1 on failure
544  */
545 static int batadv_v_gw_throughput_get(struct batadv_gw_node *gw_node, u32 *bw)
546 {
547         struct batadv_neigh_ifinfo *router_ifinfo = NULL;
548         struct batadv_orig_node *orig_node;
549         struct batadv_neigh_node *router;
550         int ret = -1;
551
552         orig_node = gw_node->orig_node;
553         router = batadv_orig_router_get(orig_node, BATADV_IF_DEFAULT);
554         if (!router)
555                 goto out;
556
557         router_ifinfo = batadv_neigh_ifinfo_get(router, BATADV_IF_DEFAULT);
558         if (!router_ifinfo)
559                 goto out;
560
561         /* the GW metric is computed as the minimum between the path throughput
562          * to reach the GW itself and the advertised bandwidth.
563          * This gives us an approximation of the effective throughput that the
564          * client can expect via this particular GW node
565          */
566         *bw = router_ifinfo->bat_v.throughput;
567         *bw = min_t(u32, *bw, gw_node->bandwidth_down);
568
569         ret = 0;
570 out:
571         if (router)
572                 batadv_neigh_node_put(router);
573         if (router_ifinfo)
574                 batadv_neigh_ifinfo_put(router_ifinfo);
575
576         return ret;
577 }
578
579 /**
580  * batadv_v_gw_get_best_gw_node() - retrieve the best GW node
581  * @bat_priv: the bat priv with all the soft interface information
582  *
583  * Return: the GW node having the best GW-metric, NULL if no GW is known
584  */
585 static struct batadv_gw_node *
586 batadv_v_gw_get_best_gw_node(struct batadv_priv *bat_priv)
587 {
588         struct batadv_gw_node *gw_node, *curr_gw = NULL;
589         u32 max_bw = 0, bw;
590
591         rcu_read_lock();
592         hlist_for_each_entry_rcu(gw_node, &bat_priv->gw.gateway_list, list) {
593                 if (!kref_get_unless_zero(&gw_node->refcount))
594                         continue;
595
596                 if (batadv_v_gw_throughput_get(gw_node, &bw) < 0)
597                         goto next;
598
599                 if (curr_gw && bw <= max_bw)
600                         goto next;
601
602                 if (curr_gw)
603                         batadv_gw_node_put(curr_gw);
604
605                 curr_gw = gw_node;
606                 kref_get(&curr_gw->refcount);
607                 max_bw = bw;
608
609 next:
610                 batadv_gw_node_put(gw_node);
611         }
612         rcu_read_unlock();
613
614         return curr_gw;
615 }
616
617 /**
618  * batadv_v_gw_is_eligible() - check if a originator would be selected as GW
619  * @bat_priv: the bat priv with all the soft interface information
620  * @curr_gw_orig: originator representing the currently selected GW
621  * @orig_node: the originator representing the new candidate
622  *
623  * Return: true if orig_node can be selected as current GW, false otherwise
624  */
625 static bool batadv_v_gw_is_eligible(struct batadv_priv *bat_priv,
626                                     struct batadv_orig_node *curr_gw_orig,
627                                     struct batadv_orig_node *orig_node)
628 {
629         struct batadv_gw_node *curr_gw, *orig_gw = NULL;
630         u32 gw_throughput, orig_throughput, threshold;
631         bool ret = false;
632
633         threshold = atomic_read(&bat_priv->gw.sel_class);
634
635         curr_gw = batadv_gw_node_get(bat_priv, curr_gw_orig);
636         if (!curr_gw) {
637                 ret = true;
638                 goto out;
639         }
640
641         if (batadv_v_gw_throughput_get(curr_gw, &gw_throughput) < 0) {
642                 ret = true;
643                 goto out;
644         }
645
646         orig_gw = batadv_gw_node_get(bat_priv, orig_node);
647         if (!orig_gw)
648                 goto out;
649
650         if (batadv_v_gw_throughput_get(orig_gw, &orig_throughput) < 0)
651                 goto out;
652
653         if (orig_throughput < gw_throughput)
654                 goto out;
655
656         if ((orig_throughput - gw_throughput) < threshold)
657                 goto out;
658
659         batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
660                    "Restarting gateway selection: better gateway found (throughput curr: %u, throughput new: %u)\n",
661                    gw_throughput, orig_throughput);
662
663         ret = true;
664 out:
665         if (curr_gw)
666                 batadv_gw_node_put(curr_gw);
667         if (orig_gw)
668                 batadv_gw_node_put(orig_gw);
669
670         return ret;
671 }
672
673 /**
674  * batadv_v_gw_dump_entry() - Dump a gateway into a message
675  * @msg: Netlink message to dump into
676  * @portid: Port making netlink request
677  * @cb: Control block containing additional options
678  * @bat_priv: The bat priv with all the soft interface information
679  * @gw_node: Gateway to be dumped
680  *
681  * Return: Error code, or 0 on success
682  */
683 static int batadv_v_gw_dump_entry(struct sk_buff *msg, u32 portid,
684                                   struct netlink_callback *cb,
685                                   struct batadv_priv *bat_priv,
686                                   struct batadv_gw_node *gw_node)
687 {
688         struct batadv_neigh_ifinfo *router_ifinfo = NULL;
689         struct batadv_neigh_node *router;
690         struct batadv_gw_node *curr_gw = NULL;
691         int ret = 0;
692         void *hdr;
693
694         router = batadv_orig_router_get(gw_node->orig_node, BATADV_IF_DEFAULT);
695         if (!router)
696                 goto out;
697
698         router_ifinfo = batadv_neigh_ifinfo_get(router, BATADV_IF_DEFAULT);
699         if (!router_ifinfo)
700                 goto out;
701
702         curr_gw = batadv_gw_get_selected_gw_node(bat_priv);
703
704         hdr = genlmsg_put(msg, portid, cb->nlh->nlmsg_seq,
705                           &batadv_netlink_family, NLM_F_MULTI,
706                           BATADV_CMD_GET_GATEWAYS);
707         if (!hdr) {
708                 ret = -ENOBUFS;
709                 goto out;
710         }
711
712         genl_dump_check_consistent(cb, hdr);
713
714         ret = -EMSGSIZE;
715
716         if (curr_gw == gw_node) {
717                 if (nla_put_flag(msg, BATADV_ATTR_FLAG_BEST)) {
718                         genlmsg_cancel(msg, hdr);
719                         goto out;
720                 }
721         }
722
723         if (nla_put(msg, BATADV_ATTR_ORIG_ADDRESS, ETH_ALEN,
724                     gw_node->orig_node->orig)) {
725                 genlmsg_cancel(msg, hdr);
726                 goto out;
727         }
728
729         if (nla_put_u32(msg, BATADV_ATTR_THROUGHPUT,
730                         router_ifinfo->bat_v.throughput)) {
731                 genlmsg_cancel(msg, hdr);
732                 goto out;
733         }
734
735         if (nla_put(msg, BATADV_ATTR_ROUTER, ETH_ALEN, router->addr)) {
736                 genlmsg_cancel(msg, hdr);
737                 goto out;
738         }
739
740         if (nla_put_string(msg, BATADV_ATTR_HARD_IFNAME,
741                            router->if_incoming->net_dev->name)) {
742                 genlmsg_cancel(msg, hdr);
743                 goto out;
744         }
745
746         if (nla_put_u32(msg, BATADV_ATTR_HARD_IFINDEX,
747                         router->if_incoming->net_dev->ifindex)) {
748                 genlmsg_cancel(msg, hdr);
749                 goto out;
750         }
751
752         if (nla_put_u32(msg, BATADV_ATTR_BANDWIDTH_DOWN,
753                         gw_node->bandwidth_down)) {
754                 genlmsg_cancel(msg, hdr);
755                 goto out;
756         }
757
758         if (nla_put_u32(msg, BATADV_ATTR_BANDWIDTH_UP, gw_node->bandwidth_up)) {
759                 genlmsg_cancel(msg, hdr);
760                 goto out;
761         }
762
763         genlmsg_end(msg, hdr);
764         ret = 0;
765
766 out:
767         if (curr_gw)
768                 batadv_gw_node_put(curr_gw);
769         if (router_ifinfo)
770                 batadv_neigh_ifinfo_put(router_ifinfo);
771         if (router)
772                 batadv_neigh_node_put(router);
773         return ret;
774 }
775
776 /**
777  * batadv_v_gw_dump() - Dump gateways into a message
778  * @msg: Netlink message to dump into
779  * @cb: Control block containing additional options
780  * @bat_priv: The bat priv with all the soft interface information
781  */
782 static void batadv_v_gw_dump(struct sk_buff *msg, struct netlink_callback *cb,
783                              struct batadv_priv *bat_priv)
784 {
785         int portid = NETLINK_CB(cb->skb).portid;
786         struct batadv_gw_node *gw_node;
787         int idx_skip = cb->args[0];
788         int idx = 0;
789
790         spin_lock_bh(&bat_priv->gw.list_lock);
791         cb->seq = bat_priv->gw.generation << 1 | 1;
792
793         hlist_for_each_entry(gw_node, &bat_priv->gw.gateway_list, list) {
794                 if (idx++ < idx_skip)
795                         continue;
796
797                 if (batadv_v_gw_dump_entry(msg, portid, cb, bat_priv,
798                                            gw_node)) {
799                         idx_skip = idx - 1;
800                         goto unlock;
801                 }
802         }
803
804         idx_skip = idx;
805 unlock:
806         spin_unlock_bh(&bat_priv->gw.list_lock);
807
808         cb->args[0] = idx_skip;
809 }
810
811 static struct batadv_algo_ops batadv_batman_v __read_mostly = {
812         .name = "BATMAN_V",
813         .iface = {
814                 .activate = batadv_v_iface_activate,
815                 .enable = batadv_v_iface_enable,
816                 .disable = batadv_v_iface_disable,
817                 .update_mac = batadv_v_iface_update_mac,
818                 .primary_set = batadv_v_primary_iface_set,
819         },
820         .neigh = {
821                 .hardif_init = batadv_v_hardif_neigh_init,
822                 .cmp = batadv_v_neigh_cmp,
823                 .is_similar_or_better = batadv_v_neigh_is_sob,
824                 .dump = batadv_v_neigh_dump,
825         },
826         .orig = {
827                 .dump = batadv_v_orig_dump,
828         },
829         .gw = {
830                 .init_sel_class = batadv_v_init_sel_class,
831                 .store_sel_class = batadv_v_store_sel_class,
832                 .get_best_gw_node = batadv_v_gw_get_best_gw_node,
833                 .is_eligible = batadv_v_gw_is_eligible,
834                 .dump = batadv_v_gw_dump,
835         },
836 };
837
838 /**
839  * batadv_v_hardif_init() - initialize the algorithm specific fields in the
840  *  hard-interface object
841  * @hard_iface: the hard-interface to initialize
842  */
843 void batadv_v_hardif_init(struct batadv_hard_iface *hard_iface)
844 {
845         /* enable link throughput auto-detection by setting the throughput
846          * override to zero
847          */
848         atomic_set(&hard_iface->bat_v.throughput_override, 0);
849         atomic_set(&hard_iface->bat_v.elp_interval, 500);
850
851         hard_iface->bat_v.aggr_len = 0;
852         skb_queue_head_init(&hard_iface->bat_v.aggr_list);
853         INIT_DELAYED_WORK(&hard_iface->bat_v.aggr_wq,
854                           batadv_v_ogm_aggr_work);
855 }
856
857 /**
858  * batadv_v_mesh_init() - initialize the B.A.T.M.A.N. V private resources for a
859  *  mesh
860  * @bat_priv: the object representing the mesh interface to initialise
861  *
862  * Return: 0 on success or a negative error code otherwise
863  */
864 int batadv_v_mesh_init(struct batadv_priv *bat_priv)
865 {
866         int ret = 0;
867
868         ret = batadv_v_ogm_init(bat_priv);
869         if (ret < 0)
870                 return ret;
871
872         return 0;
873 }
874
875 /**
876  * batadv_v_mesh_free() - free the B.A.T.M.A.N. V private resources for a mesh
877  * @bat_priv: the object representing the mesh interface to free
878  */
879 void batadv_v_mesh_free(struct batadv_priv *bat_priv)
880 {
881         batadv_v_ogm_free(bat_priv);
882 }
883
884 /**
885  * batadv_v_init() - B.A.T.M.A.N. V initialization function
886  *
887  * Description: Takes care of initializing all the subcomponents.
888  * It is invoked upon module load only.
889  *
890  * Return: 0 on success or a negative error code otherwise
891  */
892 int __init batadv_v_init(void)
893 {
894         int ret;
895
896         /* B.A.T.M.A.N. V echo location protocol packet  */
897         ret = batadv_recv_handler_register(BATADV_ELP,
898                                            batadv_v_elp_packet_recv);
899         if (ret < 0)
900                 return ret;
901
902         ret = batadv_recv_handler_register(BATADV_OGM2,
903                                            batadv_v_ogm_packet_recv);
904         if (ret < 0)
905                 goto elp_unregister;
906
907         ret = batadv_algo_register(&batadv_batman_v);
908         if (ret < 0)
909                 goto ogm_unregister;
910
911         return ret;
912
913 ogm_unregister:
914         batadv_recv_handler_unregister(BATADV_OGM2);
915
916 elp_unregister:
917         batadv_recv_handler_unregister(BATADV_ELP);
918
919         return ret;
920 }