aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/ABI/testing/sysfs-class-net-batman-adv17
-rw-r--r--MAINTAINERS1
-rw-r--r--net/batman-adv/Kconfig14
-rw-r--r--net/batman-adv/Makefile3
-rw-r--r--net/batman-adv/bat_algo.h28
-rw-r--r--net/batman-adv/bat_iv_ogm.c2
-rw-r--r--net/batman-adv/bat_v.c347
-rw-r--r--net/batman-adv/bat_v_elp.c515
-rw-r--r--net/batman-adv/bat_v_elp.h33
-rw-r--r--net/batman-adv/bat_v_ogm.c833
-rw-r--r--net/batman-adv/bat_v_ogm.h36
-rw-r--r--net/batman-adv/distributed-arp-table.c4
-rw-r--r--net/batman-adv/fragmentation.c8
-rw-r--r--net/batman-adv/gateway_common.c4
-rw-r--r--net/batman-adv/gateway_common.h2
-rw-r--r--net/batman-adv/icmp_socket.c2
-rw-r--r--net/batman-adv/main.c7
-rw-r--r--net/batman-adv/main.h12
-rw-r--r--net/batman-adv/network-coding.c22
-rw-r--r--net/batman-adv/packet.h49
-rw-r--r--net/batman-adv/send.c55
-rw-r--r--net/batman-adv/send.h10
-rw-r--r--net/batman-adv/sysfs.c130
-rw-r--r--net/batman-adv/types.h93
24 files changed, 2190 insertions, 37 deletions
diff --git a/Documentation/ABI/testing/sysfs-class-net-batman-adv b/Documentation/ABI/testing/sysfs-class-net-batman-adv
index 7f34a95bb963..518f6a1dbc0c 100644
--- a/Documentation/ABI/testing/sysfs-class-net-batman-adv
+++ b/Documentation/ABI/testing/sysfs-class-net-batman-adv
@@ -1,4 +1,20 @@
1 1
2What: /sys/class/net/<iface>/batman-adv/throughput_override
3Date: Feb 2014
4Contact: Antonio Quartulli <antonio@meshcoding.com>
5description:
6 Defines the throughput value to be used by B.A.T.M.A.N. V
7 when estimating the link throughput using this interface.
8 If the value is set to 0 then batman-adv will try to
9 estimate the throughput by itself.
10
11What: /sys/class/net/<iface>/batman-adv/elp_interval
12Date: Feb 2014
13Contact: Linus Lüssing <linus.luessing@web.de>
14Description:
15 Defines the interval in milliseconds in which batman
16 sends its probing packets for link quality measurements.
17
2What: /sys/class/net/<iface>/batman-adv/iface_status 18What: /sys/class/net/<iface>/batman-adv/iface_status
3Date: May 2010 19Date: May 2010
4Contact: Marek Lindner <mareklindner@neomailbox.ch> 20Contact: Marek Lindner <mareklindner@neomailbox.ch>
@@ -12,4 +28,3 @@ Description:
12 The /sys/class/net/<iface>/batman-adv/mesh_iface file 28 The /sys/class/net/<iface>/batman-adv/mesh_iface file
13 displays the batman mesh interface this <iface> 29 displays the batman mesh interface this <iface>
14 currently is associated with. 30 currently is associated with.
15
diff --git a/MAINTAINERS b/MAINTAINERS
index e45682745263..0499f9ef8799 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2152,6 +2152,7 @@ M: Simon Wunderlich <sw@simonwunderlich.de>
2152M: Antonio Quartulli <a@unstable.cc> 2152M: Antonio Quartulli <a@unstable.cc>
2153L: b.a.t.m.a.n@lists.open-mesh.org 2153L: b.a.t.m.a.n@lists.open-mesh.org
2154W: https://www.open-mesh.org/ 2154W: https://www.open-mesh.org/
2155Q: https://patchwork.open-mesh.org/project/batman/list/
2155S: Maintained 2156S: Maintained
2156F: net/batman-adv/ 2157F: net/batman-adv/
2157 2158
diff --git a/net/batman-adv/Kconfig b/net/batman-adv/Kconfig
index 2dd40e5ea030..e651dc927bfd 100644
--- a/net/batman-adv/Kconfig
+++ b/net/batman-adv/Kconfig
@@ -15,6 +15,20 @@ config BATMAN_ADV
15 https://www.open-mesh.org/ for more information and user space 15 https://www.open-mesh.org/ for more information and user space
16 tools. 16 tools.
17 17
18config BATMAN_ADV_BATMAN_V
19 bool "B.A.T.M.A.N. V protocol (experimental)"
20 depends on BATMAN_ADV && CFG80211
21 default n
22 help
23 This option enables the B.A.T.M.A.N. V protocol, the successor
24 of the currently used B.A.T.M.A.N. IV protocol. The main
25 changes include splitting of the OGM protocol into a neighbor
26 discovery protocol (Echo Location Protocol, ELP) and a new OGM
27 Protocol OGMv2 for flooding protocol information through the
28 network, as well as a throughput based metric.
29 B.A.T.M.A.N. V is currently considered experimental and not
30 compatible to B.A.T.M.A.N. IV networks.
31
18config BATMAN_ADV_BLA 32config BATMAN_ADV_BLA
19 bool "Bridge Loop Avoidance" 33 bool "Bridge Loop Avoidance"
20 depends on BATMAN_ADV && INET 34 depends on BATMAN_ADV && INET
diff --git a/net/batman-adv/Makefile b/net/batman-adv/Makefile
index 207e2af316c7..797cf2fc88c1 100644
--- a/net/batman-adv/Makefile
+++ b/net/batman-adv/Makefile
@@ -18,6 +18,9 @@
18 18
19obj-$(CONFIG_BATMAN_ADV) += batman-adv.o 19obj-$(CONFIG_BATMAN_ADV) += batman-adv.o
20batman-adv-y += bat_iv_ogm.o 20batman-adv-y += bat_iv_ogm.o
21batman-adv-$(CONFIG_BATMAN_ADV_BATMAN_V) += bat_v.o
22batman-adv-$(CONFIG_BATMAN_ADV_BATMAN_V) += bat_v_elp.o
23batman-adv-$(CONFIG_BATMAN_ADV_BATMAN_V) += bat_v_ogm.o
21batman-adv-y += bitarray.o 24batman-adv-y += bitarray.o
22batman-adv-$(CONFIG_BATMAN_ADV_BLA) += bridge_loop_avoidance.o 25batman-adv-$(CONFIG_BATMAN_ADV_BLA) += bridge_loop_avoidance.o
23batman-adv-$(CONFIG_DEBUG_FS) += debugfs.o 26batman-adv-$(CONFIG_DEBUG_FS) += debugfs.o
diff --git a/net/batman-adv/bat_algo.h b/net/batman-adv/bat_algo.h
index a7485d676088..03dafd33d23b 100644
--- a/net/batman-adv/bat_algo.h
+++ b/net/batman-adv/bat_algo.h
@@ -1,6 +1,6 @@
1/* Copyright (C) 2011-2016 B.A.T.M.A.N. contributors: 1/* Copyright (C) 2011-2016 B.A.T.M.A.N. contributors:
2 * 2 *
3 * Marek Lindner 3 * Marek Lindner, Linus Lüssing
4 * 4 *
5 * This program is free software; you can redistribute it and/or 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 6 * modify it under the terms of version 2 of the GNU General Public
@@ -18,6 +18,32 @@
18#ifndef _NET_BATMAN_ADV_BAT_ALGO_H_ 18#ifndef _NET_BATMAN_ADV_BAT_ALGO_H_
19#define _NET_BATMAN_ADV_BAT_ALGO_H_ 19#define _NET_BATMAN_ADV_BAT_ALGO_H_
20 20
21struct batadv_priv;
22
21int batadv_iv_init(void); 23int batadv_iv_init(void);
22 24
25#ifdef CONFIG_BATMAN_ADV_BATMAN_V
26
27int batadv_v_init(void);
28int batadv_v_mesh_init(struct batadv_priv *bat_priv);
29void batadv_v_mesh_free(struct batadv_priv *bat_priv);
30
31#else
32
33static inline int batadv_v_init(void)
34{
35 return 0;
36}
37
38static inline int batadv_v_mesh_init(struct batadv_priv *bat_priv)
39{
40 return 0;
41}
42
43static inline void batadv_v_mesh_free(struct batadv_priv *bat_priv)
44{
45}
46
47#endif /* CONFIG_BATMAN_ADV_BATMAN_V */
48
23#endif /* _NET_BATMAN_ADV_BAT_ALGO_H_ */ 49#endif /* _NET_BATMAN_ADV_BAT_ALGO_H_ */
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
index 5651e33ca6bd..cb2d1b9b0340 100644
--- a/net/batman-adv/bat_iv_ogm.c
+++ b/net/batman-adv/bat_iv_ogm.c
@@ -478,7 +478,7 @@ static void batadv_iv_ogm_send_to_if(struct batadv_forw_packet *forw_packet,
478 batadv_inc_counter(bat_priv, BATADV_CNT_MGMT_TX); 478 batadv_inc_counter(bat_priv, BATADV_CNT_MGMT_TX);
479 batadv_add_counter(bat_priv, BATADV_CNT_MGMT_TX_BYTES, 479 batadv_add_counter(bat_priv, BATADV_CNT_MGMT_TX_BYTES,
480 skb->len + ETH_HLEN); 480 skb->len + ETH_HLEN);
481 batadv_send_skb_packet(skb, hard_iface, batadv_broadcast_addr); 481 batadv_send_broadcast_skb(skb, hard_iface);
482 } 482 }
483} 483}
484 484
diff --git a/net/batman-adv/bat_v.c b/net/batman-adv/bat_v.c
new file mode 100644
index 000000000000..3315b9a598af
--- /dev/null
+++ b/net/batman-adv/bat_v.c
@@ -0,0 +1,347 @@
1/* 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
18#include "bat_algo.h"
19#include "main.h"
20
21#include <linux/atomic.h>
22#include <linux/bug.h>
23#include <linux/cache.h>
24#include <linux/init.h>
25#include <linux/jiffies.h>
26#include <linux/netdevice.h>
27#include <linux/rculist.h>
28#include <linux/rcupdate.h>
29#include <linux/seq_file.h>
30#include <linux/types.h>
31#include <linux/workqueue.h>
32
33#include "bat_v_elp.h"
34#include "bat_v_ogm.h"
35#include "hash.h"
36#include "originator.h"
37#include "packet.h"
38
39static int batadv_v_iface_enable(struct batadv_hard_iface *hard_iface)
40{
41 int ret;
42
43 ret = batadv_v_elp_iface_enable(hard_iface);
44 if (ret < 0)
45 return ret;
46
47 ret = batadv_v_ogm_iface_enable(hard_iface);
48 if (ret < 0)
49 batadv_v_elp_iface_disable(hard_iface);
50
51 /* enable link throughput auto-detection by setting the throughput
52 * override to zero
53 */
54 atomic_set(&hard_iface->bat_v.throughput_override, 0);
55
56 return ret;
57}
58
59static void batadv_v_iface_disable(struct batadv_hard_iface *hard_iface)
60{
61 batadv_v_elp_iface_disable(hard_iface);
62}
63
64static void batadv_v_iface_update_mac(struct batadv_hard_iface *hard_iface)
65{
66}
67
68static void batadv_v_primary_iface_set(struct batadv_hard_iface *hard_iface)
69{
70 batadv_v_elp_primary_iface_set(hard_iface);
71 batadv_v_ogm_primary_iface_set(hard_iface);
72}
73
74static void
75batadv_v_hardif_neigh_init(struct batadv_hardif_neigh_node *hardif_neigh)
76{
77 ewma_throughput_init(&hardif_neigh->bat_v.throughput);
78 INIT_WORK(&hardif_neigh->bat_v.metric_work,
79 batadv_v_elp_throughput_metric_update);
80}
81
82static void batadv_v_ogm_schedule(struct batadv_hard_iface *hard_iface)
83{
84}
85
86static void batadv_v_ogm_emit(struct batadv_forw_packet *forw_packet)
87{
88}
89
90/**
91 * batadv_v_orig_print_neigh - print neighbors for the originator table
92 * @orig_node: the orig_node for which the neighbors are printed
93 * @if_outgoing: outgoing interface for these entries
94 * @seq: debugfs table seq_file struct
95 *
96 * Must be called while holding an rcu lock.
97 */
98static void
99batadv_v_orig_print_neigh(struct batadv_orig_node *orig_node,
100 struct batadv_hard_iface *if_outgoing,
101 struct seq_file *seq)
102{
103 struct batadv_neigh_node *neigh_node;
104 struct batadv_neigh_ifinfo *n_ifinfo;
105
106 hlist_for_each_entry_rcu(neigh_node, &orig_node->neigh_list, list) {
107 n_ifinfo = batadv_neigh_ifinfo_get(neigh_node, if_outgoing);
108 if (!n_ifinfo)
109 continue;
110
111 seq_printf(seq, " %pM (%9u.%1u)",
112 neigh_node->addr,
113 n_ifinfo->bat_v.throughput / 10,
114 n_ifinfo->bat_v.throughput % 10);
115
116 batadv_neigh_ifinfo_put(n_ifinfo);
117 }
118}
119
120/**
121 * batadv_v_hardif_neigh_print - print a single ELP neighbour node
122 * @seq: neighbour table seq_file struct
123 * @hardif_neigh: hardif neighbour information
124 */
125static void
126batadv_v_hardif_neigh_print(struct seq_file *seq,
127 struct batadv_hardif_neigh_node *hardif_neigh)
128{
129 int last_secs, last_msecs;
130 u32 throughput;
131
132 last_secs = jiffies_to_msecs(jiffies - hardif_neigh->last_seen) / 1000;
133 last_msecs = jiffies_to_msecs(jiffies - hardif_neigh->last_seen) % 1000;
134 throughput = ewma_throughput_read(&hardif_neigh->bat_v.throughput);
135
136 seq_printf(seq, "%pM %4i.%03is (%9u.%1u) [%10s]\n",
137 hardif_neigh->addr, last_secs, last_msecs, throughput / 10,
138 throughput % 10, hardif_neigh->if_incoming->net_dev->name);
139}
140
141/**
142 * batadv_v_neigh_print - print the single hop neighbour list
143 * @bat_priv: the bat priv with all the soft interface information
144 * @seq: neighbour table seq_file struct
145 */
146static void batadv_v_neigh_print(struct batadv_priv *bat_priv,
147 struct seq_file *seq)
148{
149 struct net_device *net_dev = (struct net_device *)seq->private;
150 struct batadv_hardif_neigh_node *hardif_neigh;
151 struct batadv_hard_iface *hard_iface;
152 int batman_count = 0;
153
154 seq_printf(seq, " %-15s %s (%11s) [%10s]\n", "Neighbor",
155 "last-seen", "throughput", "IF");
156
157 rcu_read_lock();
158 list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
159 if (hard_iface->soft_iface != net_dev)
160 continue;
161
162 hlist_for_each_entry_rcu(hardif_neigh,
163 &hard_iface->neigh_list, list) {
164 batadv_v_hardif_neigh_print(seq, hardif_neigh);
165 batman_count++;
166 }
167 }
168 rcu_read_unlock();
169
170 if (batman_count == 0)
171 seq_puts(seq, "No batman nodes in range ...\n");
172}
173
174/**
175 * batadv_v_orig_print - print the originator table
176 * @bat_priv: the bat priv with all the soft interface information
177 * @seq: debugfs table seq_file struct
178 * @if_outgoing: the outgoing interface for which this should be printed
179 */
180static void batadv_v_orig_print(struct batadv_priv *bat_priv,
181 struct seq_file *seq,
182 struct batadv_hard_iface *if_outgoing)
183{
184 struct batadv_neigh_node *neigh_node;
185 struct batadv_hashtable *hash = bat_priv->orig_hash;
186 int last_seen_msecs, last_seen_secs;
187 struct batadv_orig_node *orig_node;
188 struct batadv_neigh_ifinfo *n_ifinfo;
189 unsigned long last_seen_jiffies;
190 struct hlist_head *head;
191 int batman_count = 0;
192 u32 i;
193
194 seq_printf(seq, " %-15s %s (%11s) %17s [%10s]: %20s ...\n",
195 "Originator", "last-seen", "throughput", "Nexthop",
196 "outgoingIF", "Potential nexthops");
197
198 for (i = 0; i < hash->size; i++) {
199 head = &hash->table[i];
200
201 rcu_read_lock();
202 hlist_for_each_entry_rcu(orig_node, head, hash_entry) {
203 neigh_node = batadv_orig_router_get(orig_node,
204 if_outgoing);
205 if (!neigh_node)
206 continue;
207
208 n_ifinfo = batadv_neigh_ifinfo_get(neigh_node,
209 if_outgoing);
210 if (!n_ifinfo)
211 goto next;
212
213 last_seen_jiffies = jiffies - orig_node->last_seen;
214 last_seen_msecs = jiffies_to_msecs(last_seen_jiffies);
215 last_seen_secs = last_seen_msecs / 1000;
216 last_seen_msecs = last_seen_msecs % 1000;
217
218 seq_printf(seq, "%pM %4i.%03is (%9u.%1u) %pM [%10s]:",
219 orig_node->orig, last_seen_secs,
220 last_seen_msecs,
221 n_ifinfo->bat_v.throughput / 10,
222 n_ifinfo->bat_v.throughput % 10,
223 neigh_node->addr,
224 neigh_node->if_incoming->net_dev->name);
225
226 batadv_v_orig_print_neigh(orig_node, if_outgoing, seq);
227 seq_puts(seq, "\n");
228 batman_count++;
229
230next:
231 batadv_neigh_node_put(neigh_node);
232 if (n_ifinfo)
233 batadv_neigh_ifinfo_put(n_ifinfo);
234 }
235 rcu_read_unlock();
236 }
237
238 if (batman_count == 0)
239 seq_puts(seq, "No batman nodes in range ...\n");
240}
241
242static int batadv_v_neigh_cmp(struct batadv_neigh_node *neigh1,
243 struct batadv_hard_iface *if_outgoing1,
244 struct batadv_neigh_node *neigh2,
245 struct batadv_hard_iface *if_outgoing2)
246{
247 struct batadv_neigh_ifinfo *ifinfo1, *ifinfo2;
248
249 ifinfo1 = batadv_neigh_ifinfo_get(neigh1, if_outgoing1);
250 ifinfo2 = batadv_neigh_ifinfo_get(neigh2, if_outgoing2);
251
252 if (WARN_ON(!ifinfo1 || !ifinfo2))
253 return 0;
254
255 return ifinfo1->bat_v.throughput - ifinfo2->bat_v.throughput;
256}
257
258static bool batadv_v_neigh_is_sob(struct batadv_neigh_node *neigh1,
259 struct batadv_hard_iface *if_outgoing1,
260 struct batadv_neigh_node *neigh2,
261 struct batadv_hard_iface *if_outgoing2)
262{
263 struct batadv_neigh_ifinfo *ifinfo1, *ifinfo2;
264 u32 threshold;
265
266 ifinfo1 = batadv_neigh_ifinfo_get(neigh1, if_outgoing1);
267 ifinfo2 = batadv_neigh_ifinfo_get(neigh2, if_outgoing2);
268
269 threshold = ifinfo1->bat_v.throughput / 4;
270 threshold = ifinfo1->bat_v.throughput - threshold;
271
272 return ifinfo2->bat_v.throughput > threshold;
273}
274
275static struct batadv_algo_ops batadv_batman_v __read_mostly = {
276 .name = "BATMAN_V",
277 .bat_iface_enable = batadv_v_iface_enable,
278 .bat_iface_disable = batadv_v_iface_disable,
279 .bat_iface_update_mac = batadv_v_iface_update_mac,
280 .bat_primary_iface_set = batadv_v_primary_iface_set,
281 .bat_hardif_neigh_init = batadv_v_hardif_neigh_init,
282 .bat_ogm_emit = batadv_v_ogm_emit,
283 .bat_ogm_schedule = batadv_v_ogm_schedule,
284 .bat_orig_print = batadv_v_orig_print,
285 .bat_neigh_cmp = batadv_v_neigh_cmp,
286 .bat_neigh_is_similar_or_better = batadv_v_neigh_is_sob,
287 .bat_neigh_print = batadv_v_neigh_print,
288};
289
290/**
291 * batadv_v_mesh_init - initialize the B.A.T.M.A.N. V private resources for a
292 * mesh
293 * @bat_priv: the object representing the mesh interface to initialise
294 *
295 * Return: 0 on success or a negative error code otherwise
296 */
297int batadv_v_mesh_init(struct batadv_priv *bat_priv)
298{
299 return batadv_v_ogm_init(bat_priv);
300}
301
302/**
303 * batadv_v_mesh_free - free the B.A.T.M.A.N. V private resources for a mesh
304 * @bat_priv: the object representing the mesh interface to free
305 */
306void batadv_v_mesh_free(struct batadv_priv *bat_priv)
307{
308 batadv_v_ogm_free(bat_priv);
309}
310
311/**
312 * batadv_v_init - B.A.T.M.A.N. V initialization function
313 *
314 * Description: Takes care of initializing all the subcomponents.
315 * It is invoked upon module load only.
316 *
317 * Return: 0 on success or a negative error code otherwise
318 */
319int __init batadv_v_init(void)
320{
321 int ret;
322
323 /* B.A.T.M.A.N. V echo location protocol packet */
324 ret = batadv_recv_handler_register(BATADV_ELP,
325 batadv_v_elp_packet_recv);
326 if (ret < 0)
327 return ret;
328
329 ret = batadv_recv_handler_register(BATADV_OGM2,
330 batadv_v_ogm_packet_recv);
331 if (ret < 0)
332 goto elp_unregister;
333
334 ret = batadv_algo_register(&batadv_batman_v);
335 if (ret < 0)
336 goto ogm_unregister;
337
338 return ret;
339
340ogm_unregister:
341 batadv_recv_handler_unregister(BATADV_OGM2);
342
343elp_unregister:
344 batadv_recv_handler_unregister(BATADV_ELP);
345
346 return ret;
347}
diff --git a/net/batman-adv/bat_v_elp.c b/net/batman-adv/bat_v_elp.c
new file mode 100644
index 000000000000..3844e7efd0b0
--- /dev/null
+++ b/net/batman-adv/bat_v_elp.c
@@ -0,0 +1,515 @@
1/* Copyright (C) 2011-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
18#include "bat_v_elp.h"
19#include "main.h"
20
21#include <linux/atomic.h>
22#include <linux/byteorder/generic.h>
23#include <linux/errno.h>
24#include <linux/etherdevice.h>
25#include <linux/ethtool.h>
26#include <linux/fs.h>
27#include <linux/if_ether.h>
28#include <linux/jiffies.h>
29#include <linux/kernel.h>
30#include <linux/kref.h>
31#include <linux/netdevice.h>
32#include <linux/random.h>
33#include <linux/rculist.h>
34#include <linux/rcupdate.h>
35#include <linux/rtnetlink.h>
36#include <linux/skbuff.h>
37#include <linux/stddef.h>
38#include <linux/string.h>
39#include <linux/types.h>
40#include <linux/workqueue.h>
41#include <net/cfg80211.h>
42
43#include "bat_algo.h"
44#include "bat_v_ogm.h"
45#include "hard-interface.h"
46#include "originator.h"
47#include "packet.h"
48#include "routing.h"
49#include "send.h"
50
51/**
52 * batadv_v_elp_start_timer - restart timer for ELP periodic work
53 * @hard_iface: the interface for which the timer has to be reset
54 */
55static void batadv_v_elp_start_timer(struct batadv_hard_iface *hard_iface)
56{
57 unsigned int msecs;
58
59 msecs = atomic_read(&hard_iface->bat_v.elp_interval) - BATADV_JITTER;
60 msecs += prandom_u32() % (2 * BATADV_JITTER);
61
62 queue_delayed_work(batadv_event_workqueue, &hard_iface->bat_v.elp_wq,
63 msecs_to_jiffies(msecs));
64}
65
66/**
67 * batadv_v_elp_get_throughput - get the throughput towards a neighbour
68 * @neigh: the neighbour for which the throughput has to be obtained
69 *
70 * Return: The throughput towards the given neighbour in multiples of 100kpbs
71 * (a value of '1' equals to 0.1Mbps, '10' equals 1Mbps, etc).
72 */
73static u32 batadv_v_elp_get_throughput(struct batadv_hardif_neigh_node *neigh)
74{
75 struct batadv_hard_iface *hard_iface = neigh->if_incoming;
76 struct ethtool_link_ksettings link_settings;
77 struct station_info sinfo;
78 u32 throughput;
79 int ret;
80
81 /* if the user specified a customised value for this interface, then
82 * return it directly
83 */
84 throughput = atomic_read(&hard_iface->bat_v.throughput_override);
85 if (throughput != 0)
86 return throughput;
87
88 /* if this is a wireless device, then ask its throughput through
89 * cfg80211 API
90 */
91 if (batadv_is_wifi_netdev(hard_iface->net_dev)) {
92 if (hard_iface->net_dev->ieee80211_ptr) {
93 ret = cfg80211_get_station(hard_iface->net_dev,
94 neigh->addr, &sinfo);
95 if (ret == -ENOENT) {
96 /* Node is not associated anymore! It would be
97 * possible to delete this neighbor. For now set
98 * the throughput metric to 0.
99 */
100 return 0;
101 }
102 if (!ret)
103 return sinfo.expected_throughput / 100;
104 }
105
106 /* unsupported WiFi driver version */
107 goto default_throughput;
108 }
109
110 /* if not a wifi interface, check if this device provides data via
111 * ethtool (e.g. an Ethernet adapter)
112 */
113 memset(&link_settings, 0, sizeof(link_settings));
114 rtnl_lock();
115 ret = __ethtool_get_link_ksettings(hard_iface->net_dev, &link_settings);
116 rtnl_unlock();
117 if (ret == 0) {
118 /* link characteristics might change over time */
119 if (link_settings.base.duplex == DUPLEX_FULL)
120 hard_iface->bat_v.flags |= BATADV_FULL_DUPLEX;
121 else
122 hard_iface->bat_v.flags &= ~BATADV_FULL_DUPLEX;
123
124 throughput = link_settings.base.speed;
125 if (throughput && (throughput != SPEED_UNKNOWN))
126 return throughput * 10;
127 }
128
129default_throughput:
130 if (!(hard_iface->bat_v.flags & BATADV_WARNING_DEFAULT)) {
131 batadv_info(hard_iface->soft_iface,
132 "WiFi driver or ethtool info does not provide information about link speeds on interface %s, therefore defaulting to hardcoded throughput values of %u.%1u Mbps. Consider overriding the throughput manually or checking your driver.\n",
133 hard_iface->net_dev->name,
134 BATADV_THROUGHPUT_DEFAULT_VALUE / 10,
135 BATADV_THROUGHPUT_DEFAULT_VALUE % 10);
136 hard_iface->bat_v.flags |= BATADV_WARNING_DEFAULT;
137 }
138
139 /* if none of the above cases apply, return the base_throughput */
140 return BATADV_THROUGHPUT_DEFAULT_VALUE;
141}
142
143/**
144 * batadv_v_elp_throughput_metric_update - worker updating the throughput metric
145 * of a single hop neighbour
146 * @work: the work queue item
147 */
148void batadv_v_elp_throughput_metric_update(struct work_struct *work)
149{
150 struct batadv_hardif_neigh_node_bat_v *neigh_bat_v;
151 struct batadv_hardif_neigh_node *neigh;
152
153 neigh_bat_v = container_of(work, struct batadv_hardif_neigh_node_bat_v,
154 metric_work);
155 neigh = container_of(neigh_bat_v, struct batadv_hardif_neigh_node,
156 bat_v);
157
158 ewma_throughput_add(&neigh->bat_v.throughput,
159 batadv_v_elp_get_throughput(neigh));
160
161 /* decrement refcounter to balance increment performed before scheduling
162 * this task
163 */
164 batadv_hardif_neigh_put(neigh);
165}
166
167/**
168 * batadv_v_elp_wifi_neigh_probe - send link probing packets to a neighbour
169 * @neigh: the neighbour to probe
170 *
171 * Sends a predefined number of unicast wifi packets to a given neighbour in
172 * order to trigger the throughput estimation on this link by the RC algorithm.
173 * Packets are sent only if there there is not enough payload unicast traffic
174 * towards this neighbour..
175 *
176 * Return: True on success and false in case of error during skb preparation.
177 */
178static bool
179batadv_v_elp_wifi_neigh_probe(struct batadv_hardif_neigh_node *neigh)
180{
181 struct batadv_hard_iface *hard_iface = neigh->if_incoming;
182 struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
183 unsigned long last_tx_diff;
184 struct sk_buff *skb;
185 int probe_len, i;
186 int elp_skb_len;
187
188 /* this probing routine is for Wifi neighbours only */
189 if (!batadv_is_wifi_netdev(hard_iface->net_dev))
190 return true;
191
192 /* probe the neighbor only if no unicast packets have been sent
193 * to it in the last 100 milliseconds: this is the rate control
194 * algorithm sampling interval (minstrel). In this way, if not
195 * enough traffic has been sent to the neighbor, batman-adv can
196 * generate 2 probe packets and push the RC algorithm to perform
197 * the sampling
198 */
199 last_tx_diff = jiffies_to_msecs(jiffies - neigh->bat_v.last_unicast_tx);
200 if (last_tx_diff <= BATADV_ELP_PROBE_MAX_TX_DIFF)
201 return true;
202
203 probe_len = max_t(int, sizeof(struct batadv_elp_packet),
204 BATADV_ELP_MIN_PROBE_SIZE);
205
206 for (i = 0; i < BATADV_ELP_PROBES_PER_NODE; i++) {
207 elp_skb_len = hard_iface->bat_v.elp_skb->len;
208 skb = skb_copy_expand(hard_iface->bat_v.elp_skb, 0,
209 probe_len - elp_skb_len,
210 GFP_ATOMIC);
211 if (!skb)
212 return false;
213
214 /* Tell the skb to get as big as the allocated space (we want
215 * the packet to be exactly of that size to make the link
216 * throughput estimation effective.
217 */
218 skb_put(skb, probe_len - hard_iface->bat_v.elp_skb->len);
219
220 batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
221 "Sending unicast (probe) ELP packet on interface %s to %pM\n",
222 hard_iface->net_dev->name, neigh->addr);
223
224 batadv_send_skb_packet(skb, hard_iface, neigh->addr);
225 }
226
227 return true;
228}
229
230/**
231 * batadv_v_elp_periodic_work - ELP periodic task per interface
232 * @work: work queue item
233 *
234 * Emits broadcast ELP message in regular intervals.
235 */
236static void batadv_v_elp_periodic_work(struct work_struct *work)
237{
238 struct batadv_hardif_neigh_node *hardif_neigh;
239 struct batadv_hard_iface *hard_iface;
240 struct batadv_hard_iface_bat_v *bat_v;
241 struct batadv_elp_packet *elp_packet;
242 struct batadv_priv *bat_priv;
243 struct sk_buff *skb;
244 u32 elp_interval;
245
246 bat_v = container_of(work, struct batadv_hard_iface_bat_v, elp_wq.work);
247 hard_iface = container_of(bat_v, struct batadv_hard_iface, bat_v);
248 bat_priv = netdev_priv(hard_iface->soft_iface);
249
250 if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_DEACTIVATING)
251 goto out;
252
253 /* we are in the process of shutting this interface down */
254 if ((hard_iface->if_status == BATADV_IF_NOT_IN_USE) ||
255 (hard_iface->if_status == BATADV_IF_TO_BE_REMOVED))
256 goto out;
257
258 /* the interface was enabled but may not be ready yet */
259 if (hard_iface->if_status != BATADV_IF_ACTIVE)
260 goto restart_timer;
261
262 skb = skb_copy(hard_iface->bat_v.elp_skb, GFP_ATOMIC);
263 if (!skb)
264 goto restart_timer;
265
266 elp_packet = (struct batadv_elp_packet *)skb->data;
267 elp_packet->seqno = htonl(atomic_read(&hard_iface->bat_v.elp_seqno));
268 elp_interval = atomic_read(&hard_iface->bat_v.elp_interval);
269 elp_packet->elp_interval = htonl(elp_interval);
270
271 batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
272 "Sending broadcast ELP packet on interface %s, seqno %u\n",
273 hard_iface->net_dev->name,
274 atomic_read(&hard_iface->bat_v.elp_seqno));
275
276 batadv_send_broadcast_skb(skb, hard_iface);
277
278 atomic_inc(&hard_iface->bat_v.elp_seqno);
279
280 /* The throughput metric is updated on each sent packet. This way, if a
281 * node is dead and no longer sends packets, batman-adv is still able to
282 * react timely to its death.
283 *
284 * The throughput metric is updated by following these steps:
285 * 1) if the hard_iface is wifi => send a number of unicast ELPs for
286 * probing/sampling to each neighbor
287 * 2) update the throughput metric value of each neighbor (note that the
288 * value retrieved in this step might be 100ms old because the
289 * probing packets at point 1) could still be in the HW queue)
290 */
291 rcu_read_lock();
292 hlist_for_each_entry_rcu(hardif_neigh, &hard_iface->neigh_list, list) {
293 if (!batadv_v_elp_wifi_neigh_probe(hardif_neigh))
294 /* if something goes wrong while probing, better to stop
295 * sending packets immediately and reschedule the task
296 */
297 break;
298
299 if (!kref_get_unless_zero(&hardif_neigh->refcount))
300 continue;
301
302 /* Reading the estimated throughput from cfg80211 is a task that
303 * may sleep and that is not allowed in an rcu protected
304 * context. Therefore schedule a task for that.
305 */
306 queue_work(batadv_event_workqueue,
307 &hardif_neigh->bat_v.metric_work);
308 }
309 rcu_read_unlock();
310
311restart_timer:
312 batadv_v_elp_start_timer(hard_iface);
313out:
314 return;
315}
316
317/**
318 * batadv_v_elp_iface_enable - setup the ELP interface private resources
319 * @hard_iface: interface for which the data has to be prepared
320 *
321 * Return: 0 on success or a -ENOMEM in case of failure.
322 */
323int batadv_v_elp_iface_enable(struct batadv_hard_iface *hard_iface)
324{
325 struct batadv_elp_packet *elp_packet;
326 unsigned char *elp_buff;
327 u32 random_seqno;
328 size_t size;
329 int res = -ENOMEM;
330
331 size = ETH_HLEN + NET_IP_ALIGN + BATADV_ELP_HLEN;
332 hard_iface->bat_v.elp_skb = dev_alloc_skb(size);
333 if (!hard_iface->bat_v.elp_skb)
334 goto out;
335
336 skb_reserve(hard_iface->bat_v.elp_skb, ETH_HLEN + NET_IP_ALIGN);
337 elp_buff = skb_push(hard_iface->bat_v.elp_skb, BATADV_ELP_HLEN);
338 elp_packet = (struct batadv_elp_packet *)elp_buff;
339 memset(elp_packet, 0, BATADV_ELP_HLEN);
340
341 elp_packet->packet_type = BATADV_ELP;
342 elp_packet->version = BATADV_COMPAT_VERSION;
343
344 /* randomize initial seqno to avoid collision */
345 get_random_bytes(&random_seqno, sizeof(random_seqno));
346 atomic_set(&hard_iface->bat_v.elp_seqno, random_seqno);
347 atomic_set(&hard_iface->bat_v.elp_interval, 500);
348
349 /* assume full-duplex by default */
350 hard_iface->bat_v.flags |= BATADV_FULL_DUPLEX;
351
352 /* warn the user (again) if there is no throughput data is available */
353 hard_iface->bat_v.flags &= ~BATADV_WARNING_DEFAULT;
354
355 if (batadv_is_wifi_netdev(hard_iface->net_dev))
356 hard_iface->bat_v.flags &= ~BATADV_FULL_DUPLEX;
357
358 INIT_DELAYED_WORK(&hard_iface->bat_v.elp_wq,
359 batadv_v_elp_periodic_work);
360 batadv_v_elp_start_timer(hard_iface);
361 res = 0;
362
363out:
364 return res;
365}
366
367/**
368 * batadv_v_elp_iface_disable - release ELP interface private resources
369 * @hard_iface: interface for which the resources have to be released
370 */
371void batadv_v_elp_iface_disable(struct batadv_hard_iface *hard_iface)
372{
373 cancel_delayed_work_sync(&hard_iface->bat_v.elp_wq);
374
375 dev_kfree_skb(hard_iface->bat_v.elp_skb);
376 hard_iface->bat_v.elp_skb = NULL;
377}
378
379/**
380 * batadv_v_elp_primary_iface_set - change internal data to reflect the new
381 * primary interface
382 * @primary_iface: the new primary interface
383 */
384void batadv_v_elp_primary_iface_set(struct batadv_hard_iface *primary_iface)
385{
386 struct batadv_hard_iface *hard_iface;
387 struct batadv_elp_packet *elp_packet;
388 struct sk_buff *skb;
389
390 /* update orig field of every elp iface belonging to this mesh */
391 rcu_read_lock();
392 list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
393 if (primary_iface->soft_iface != hard_iface->soft_iface)
394 continue;
395
396 if (!hard_iface->bat_v.elp_skb)
397 continue;
398
399 skb = hard_iface->bat_v.elp_skb;
400 elp_packet = (struct batadv_elp_packet *)skb->data;
401 ether_addr_copy(elp_packet->orig,
402 primary_iface->net_dev->dev_addr);
403 }
404 rcu_read_unlock();
405}
406
407/**
408 * batadv_v_elp_neigh_update - update an ELP neighbour node
409 * @bat_priv: the bat priv with all the soft interface information
410 * @neigh_addr: the neighbour interface address
411 * @if_incoming: the interface the packet was received through
412 * @elp_packet: the received ELP packet
413 *
414 * Updates the ELP neighbour node state with the data received within the new
415 * ELP packet.
416 */
417static void batadv_v_elp_neigh_update(struct batadv_priv *bat_priv,
418 u8 *neigh_addr,
419 struct batadv_hard_iface *if_incoming,
420 struct batadv_elp_packet *elp_packet)
421
422{
423 struct batadv_neigh_node *neigh;
424 struct batadv_orig_node *orig_neigh;
425 struct batadv_hardif_neigh_node *hardif_neigh;
426 s32 seqno_diff;
427 s32 elp_latest_seqno;
428
429 orig_neigh = batadv_v_ogm_orig_get(bat_priv, elp_packet->orig);
430 if (!orig_neigh)
431 return;
432
433 neigh = batadv_neigh_node_new(orig_neigh, if_incoming, neigh_addr);
434 if (!neigh)
435 goto orig_free;
436
437 hardif_neigh = batadv_hardif_neigh_get(if_incoming, neigh_addr);
438 if (!hardif_neigh)
439 goto neigh_free;
440
441 elp_latest_seqno = hardif_neigh->bat_v.elp_latest_seqno;
442 seqno_diff = ntohl(elp_packet->seqno) - elp_latest_seqno;
443
444 /* known or older sequence numbers are ignored. However always adopt
445 * if the router seems to have been restarted.
446 */
447 if (seqno_diff < 1 && seqno_diff > -BATADV_ELP_MAX_AGE)
448 goto hardif_free;
449
450 neigh->last_seen = jiffies;
451 hardif_neigh->last_seen = jiffies;
452 hardif_neigh->bat_v.elp_latest_seqno = ntohl(elp_packet->seqno);
453 hardif_neigh->bat_v.elp_interval = ntohl(elp_packet->elp_interval);
454
455hardif_free:
456 if (hardif_neigh)
457 batadv_hardif_neigh_put(hardif_neigh);
458neigh_free:
459 if (neigh)
460 batadv_neigh_node_put(neigh);
461orig_free:
462 if (orig_neigh)
463 batadv_orig_node_put(orig_neigh);
464}
465
466/**
467 * batadv_v_elp_packet_recv - main ELP packet handler
468 * @skb: the received packet
469 * @if_incoming: the interface this packet was received through
470 *
471 * Return: NET_RX_SUCCESS and consumes the skb if the packet was peoperly
472 * processed or NET_RX_DROP in case of failure.
473 */
474int batadv_v_elp_packet_recv(struct sk_buff *skb,
475 struct batadv_hard_iface *if_incoming)
476{
477 struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
478 struct batadv_elp_packet *elp_packet;
479 struct batadv_hard_iface *primary_if;
480 struct ethhdr *ethhdr = (struct ethhdr *)skb_mac_header(skb);
481 bool ret;
482
483 ret = batadv_check_management_packet(skb, if_incoming, BATADV_ELP_HLEN);
484 if (!ret)
485 return NET_RX_DROP;
486
487 if (batadv_is_my_mac(bat_priv, ethhdr->h_source))
488 return NET_RX_DROP;
489
490 /* did we receive a B.A.T.M.A.N. V ELP packet on an interface
491 * that does not have B.A.T.M.A.N. V ELP enabled ?
492 */
493 if (strcmp(bat_priv->bat_algo_ops->name, "BATMAN_V") != 0)
494 return NET_RX_DROP;
495
496 elp_packet = (struct batadv_elp_packet *)skb->data;
497
498 batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
499 "Received ELP packet from %pM seqno %u ORIG: %pM\n",
500 ethhdr->h_source, ntohl(elp_packet->seqno),
501 elp_packet->orig);
502
503 primary_if = batadv_primary_if_get_selected(bat_priv);
504 if (!primary_if)
505 goto out;
506
507 batadv_v_elp_neigh_update(bat_priv, ethhdr->h_source, if_incoming,
508 elp_packet);
509
510out:
511 if (primary_if)
512 batadv_hardif_put(primary_if);
513 consume_skb(skb);
514 return NET_RX_SUCCESS;
515}
diff --git a/net/batman-adv/bat_v_elp.h b/net/batman-adv/bat_v_elp.h
new file mode 100644
index 000000000000..e95f1bca0785
--- /dev/null
+++ b/net/batman-adv/bat_v_elp.h
@@ -0,0 +1,33 @@
1/* 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
18#include "main.h"
19
20#ifndef _NET_BATMAN_ADV_BAT_V_ELP_H_
21#define _NET_BATMAN_ADV_BAT_V_ELP_H_
22
23struct sk_buff;
24struct work_struct;
25
26int batadv_v_elp_iface_enable(struct batadv_hard_iface *hard_iface);
27void batadv_v_elp_iface_disable(struct batadv_hard_iface *hard_iface);
28void batadv_v_elp_primary_iface_set(struct batadv_hard_iface *primary_iface);
29int batadv_v_elp_packet_recv(struct sk_buff *skb,
30 struct batadv_hard_iface *if_incoming);
31void batadv_v_elp_throughput_metric_update(struct work_struct *work);
32
33#endif /* _NET_BATMAN_ADV_BAT_V_ELP_H_ */
diff --git a/net/batman-adv/bat_v_ogm.c b/net/batman-adv/bat_v_ogm.c
new file mode 100644
index 000000000000..d9bcbe6e7d65
--- /dev/null
+++ b/net/batman-adv/bat_v_ogm.c
@@ -0,0 +1,833 @@
1/* Copyright (C) 2013-2016 B.A.T.M.A.N. contributors:
2 *
3 * Antonio Quartulli
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
18#include "bat_v_ogm.h"
19#include "main.h"
20
21#include <linux/atomic.h>
22#include <linux/byteorder/generic.h>
23#include <linux/errno.h>
24#include <linux/etherdevice.h>
25#include <linux/fs.h>
26#include <linux/if_ether.h>
27#include <linux/jiffies.h>
28#include <linux/kernel.h>
29#include <linux/list.h>
30#include <linux/netdevice.h>
31#include <linux/random.h>
32#include <linux/rculist.h>
33#include <linux/rcupdate.h>
34#include <linux/skbuff.h>
35#include <linux/slab.h>
36#include <linux/stddef.h>
37#include <linux/string.h>
38#include <linux/types.h>
39#include <linux/workqueue.h>
40
41#include "hard-interface.h"
42#include "hash.h"
43#include "originator.h"
44#include "packet.h"
45#include "routing.h"
46#include "send.h"
47#include "translation-table.h"
48
49/**
50 * batadv_v_ogm_orig_get - retrieve and possibly create an originator node
51 * @bat_priv: the bat priv with all the soft interface information
52 * @addr: the address of the originator
53 *
54 * Return: the orig_node corresponding to the specified address. If such object
55 * does not exist it is allocated here. In case of allocation failure returns
56 * NULL.
57 */
58struct batadv_orig_node *batadv_v_ogm_orig_get(struct batadv_priv *bat_priv,
59 const u8 *addr)
60{
61 struct batadv_orig_node *orig_node;
62 int hash_added;
63
64 orig_node = batadv_orig_hash_find(bat_priv, addr);
65 if (orig_node)
66 return orig_node;
67
68 orig_node = batadv_orig_node_new(bat_priv, addr);
69 if (!orig_node)
70 return NULL;
71
72 hash_added = batadv_hash_add(bat_priv->orig_hash, batadv_compare_orig,
73 batadv_choose_orig, orig_node,
74 &orig_node->hash_entry);
75 if (hash_added != 0) {
76 /* orig_node->refcounter is initialised to 2 by
77 * batadv_orig_node_new()
78 */
79 batadv_orig_node_put(orig_node);
80 batadv_orig_node_put(orig_node);
81 orig_node = NULL;
82 }
83
84 return orig_node;
85}
86
87/**
88 * batadv_v_ogm_start_timer - restart the OGM sending timer
89 * @bat_priv: the bat priv with all the soft interface information
90 */
91static void batadv_v_ogm_start_timer(struct batadv_priv *bat_priv)
92{
93 unsigned long msecs;
94 /* this function may be invoked in different contexts (ogm rescheduling
95 * or hard_iface activation), but the work timer should not be reset
96 */
97 if (delayed_work_pending(&bat_priv->bat_v.ogm_wq))
98 return;
99
100 msecs = atomic_read(&bat_priv->orig_interval) - BATADV_JITTER;
101 msecs += prandom_u32() % (2 * BATADV_JITTER);
102 queue_delayed_work(batadv_event_workqueue, &bat_priv->bat_v.ogm_wq,
103 msecs_to_jiffies(msecs));
104}
105
106/**
107 * batadv_v_ogm_send_to_if - send a batman ogm using a given interface
108 * @skb: the OGM to send
109 * @hard_iface: the interface to use to send the OGM
110 */
111static void batadv_v_ogm_send_to_if(struct sk_buff *skb,
112 struct batadv_hard_iface *hard_iface)
113{
114 struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
115
116 if (hard_iface->if_status != BATADV_IF_ACTIVE)
117 return;
118
119 batadv_inc_counter(bat_priv, BATADV_CNT_MGMT_TX);
120 batadv_add_counter(bat_priv, BATADV_CNT_MGMT_TX_BYTES,
121 skb->len + ETH_HLEN);
122
123 batadv_send_broadcast_skb(skb, hard_iface);
124}
125
126/**
127 * batadv_v_ogm_send - periodic worker broadcasting the own OGM
128 * @work: work queue item
129 */
130static void batadv_v_ogm_send(struct work_struct *work)
131{
132 struct batadv_hard_iface *hard_iface;
133 struct batadv_priv_bat_v *bat_v;
134 struct batadv_priv *bat_priv;
135 struct batadv_ogm2_packet *ogm_packet;
136 struct sk_buff *skb, *skb_tmp;
137 unsigned char *ogm_buff, *pkt_buff;
138 int ogm_buff_len;
139 u16 tvlv_len = 0;
140
141 bat_v = container_of(work, struct batadv_priv_bat_v, ogm_wq.work);
142 bat_priv = container_of(bat_v, struct batadv_priv, bat_v);
143
144 if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_DEACTIVATING)
145 goto out;
146
147 ogm_buff = bat_priv->bat_v.ogm_buff;
148 ogm_buff_len = bat_priv->bat_v.ogm_buff_len;
149 /* tt changes have to be committed before the tvlv data is
150 * appended as it may alter the tt tvlv container
151 */
152 batadv_tt_local_commit_changes(bat_priv);
153 tvlv_len = batadv_tvlv_container_ogm_append(bat_priv, &ogm_buff,
154 &ogm_buff_len,
155 BATADV_OGM2_HLEN);
156
157 bat_priv->bat_v.ogm_buff = ogm_buff;
158 bat_priv->bat_v.ogm_buff_len = ogm_buff_len;
159
160 skb = netdev_alloc_skb_ip_align(NULL, ETH_HLEN + ogm_buff_len);
161 if (!skb)
162 goto reschedule;
163
164 skb_reserve(skb, ETH_HLEN);
165 pkt_buff = skb_put(skb, ogm_buff_len);
166 memcpy(pkt_buff, ogm_buff, ogm_buff_len);
167
168 ogm_packet = (struct batadv_ogm2_packet *)skb->data;
169 ogm_packet->seqno = htonl(atomic_read(&bat_priv->bat_v.ogm_seqno));
170 atomic_inc(&bat_priv->bat_v.ogm_seqno);
171 ogm_packet->tvlv_len = htons(tvlv_len);
172
173 /* broadcast on every interface */
174 rcu_read_lock();
175 list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
176 if (hard_iface->soft_iface != bat_priv->soft_iface)
177 continue;
178
179 batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
180 "Sending own OGM2 packet (originator %pM, seqno %u, throughput %u, TTL %d) on interface %s [%pM]\n",
181 ogm_packet->orig, ntohl(ogm_packet->seqno),
182 ntohl(ogm_packet->throughput), ogm_packet->ttl,
183 hard_iface->net_dev->name,
184 hard_iface->net_dev->dev_addr);
185
186 /* this skb gets consumed by batadv_v_ogm_send_to_if() */
187 skb_tmp = skb_clone(skb, GFP_ATOMIC);
188 if (!skb_tmp)
189 break;
190
191 batadv_v_ogm_send_to_if(skb_tmp, hard_iface);
192 }
193 rcu_read_unlock();
194
195 consume_skb(skb);
196
197reschedule:
198 batadv_v_ogm_start_timer(bat_priv);
199out:
200 return;
201}
202
203/**
204 * batadv_v_ogm_iface_enable - prepare an interface for B.A.T.M.A.N. V
205 * @hard_iface: the interface to prepare
206 *
207 * Takes care of scheduling own OGM sending routine for this interface.
208 *
209 * Return: 0 on success or a negative error code otherwise
210 */
211int batadv_v_ogm_iface_enable(struct batadv_hard_iface *hard_iface)
212{
213 struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
214
215 batadv_v_ogm_start_timer(bat_priv);
216
217 return 0;
218}
219
220/**
221 * batadv_v_ogm_primary_iface_set - set a new primary interface
222 * @primary_iface: the new primary interface
223 */
224void batadv_v_ogm_primary_iface_set(struct batadv_hard_iface *primary_iface)
225{
226 struct batadv_priv *bat_priv = netdev_priv(primary_iface->soft_iface);
227 struct batadv_ogm2_packet *ogm_packet;
228
229 if (!bat_priv->bat_v.ogm_buff)
230 return;
231
232 ogm_packet = (struct batadv_ogm2_packet *)bat_priv->bat_v.ogm_buff;
233 ether_addr_copy(ogm_packet->orig, primary_iface->net_dev->dev_addr);
234}
235
236/**
237 * batadv_v_ogm_orig_update - update the originator status based on the received
238 * OGM
239 * @bat_priv: the bat priv with all the soft interface information
240 * @orig_node: the originator to update
241 * @neigh_node: the neighbour the OGM has been received from (to update)
242 * @ogm2: the received OGM
243 * @if_outgoing: the interface where this OGM is going to be forwarded through
244 */
245static void
246batadv_v_ogm_orig_update(struct batadv_priv *bat_priv,
247 struct batadv_orig_node *orig_node,
248 struct batadv_neigh_node *neigh_node,
249 const struct batadv_ogm2_packet *ogm2,
250 struct batadv_hard_iface *if_outgoing)
251{
252 struct batadv_neigh_ifinfo *router_ifinfo = NULL, *neigh_ifinfo = NULL;
253 struct batadv_neigh_node *router = NULL;
254 s32 neigh_seq_diff;
255 u32 neigh_last_seqno;
256 u32 router_last_seqno;
257 u32 router_throughput, neigh_throughput;
258
259 batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
260 "Searching and updating originator entry of received packet\n");
261
262 /* if this neighbor already is our next hop there is nothing
263 * to change
264 */
265 router = batadv_orig_router_get(orig_node, if_outgoing);
266 if (router == neigh_node)
267 goto out;
268
269 /* don't consider neighbours with worse throughput.
270 * also switch route if this seqno is BATADV_V_MAX_ORIGDIFF newer than
271 * the last received seqno from our best next hop.
272 */
273 if (router) {
274 router_ifinfo = batadv_neigh_ifinfo_get(router, if_outgoing);
275 neigh_ifinfo = batadv_neigh_ifinfo_get(neigh_node, if_outgoing);
276
277 /* if these are not allocated, something is wrong. */
278 if (!router_ifinfo || !neigh_ifinfo)
279 goto out;
280
281 neigh_last_seqno = neigh_ifinfo->bat_v.last_seqno;
282 router_last_seqno = router_ifinfo->bat_v.last_seqno;
283 neigh_seq_diff = neigh_last_seqno - router_last_seqno;
284 router_throughput = router_ifinfo->bat_v.throughput;
285 neigh_throughput = neigh_ifinfo->bat_v.throughput;
286
287 if ((neigh_seq_diff < BATADV_OGM_MAX_ORIGDIFF) &&
288 (router_throughput >= neigh_throughput))
289 goto out;
290 }
291
292 batadv_update_route(bat_priv, orig_node, if_outgoing, neigh_node);
293
294out:
295 if (router_ifinfo)
296 batadv_neigh_ifinfo_put(router_ifinfo);
297 if (neigh_ifinfo)
298 batadv_neigh_ifinfo_put(neigh_ifinfo);
299 if (router)
300 batadv_neigh_node_put(router);
301}
302
303/**
304 * batadv_v_forward_penalty - apply a penalty to the throughput metric forwarded
305 * with B.A.T.M.A.N. V OGMs
306 * @bat_priv: the bat priv with all the soft interface information
307 * @if_incoming: the interface where the OGM has been received
308 * @if_outgoing: the interface where the OGM has to be forwarded to
309 * @throughput: the current throughput
310 *
311 * Apply a penalty on the current throughput metric value based on the
312 * characteristic of the interface where the OGM has been received. The return
313 * value is computed as follows:
314 * - throughput * 50% if the incoming and outgoing interface are the
315 * same WiFi interface and the throughput is above
316 * 1MBit/s
317 * - throughput if the outgoing interface is the default
318 * interface (i.e. this OGM is processed for the
319 * internal table and not forwarded)
320 * - throughput * hop penalty otherwise
321 *
322 * Return: the penalised throughput metric.
323 */
324static u32 batadv_v_forward_penalty(struct batadv_priv *bat_priv,
325 struct batadv_hard_iface *if_incoming,
326 struct batadv_hard_iface *if_outgoing,
327 u32 throughput)
328{
329 int hop_penalty = atomic_read(&bat_priv->hop_penalty);
330 int hop_penalty_max = BATADV_TQ_MAX_VALUE;
331
332 /* Don't apply hop penalty in default originator table. */
333 if (if_outgoing == BATADV_IF_DEFAULT)
334 return throughput;
335
336 /* Forwarding on the same WiFi interface cuts the throughput in half
337 * due to the store & forward characteristics of WIFI.
338 * Very low throughput values are the exception.
339 */
340 if ((throughput > 10) &&
341 (if_incoming == if_outgoing) &&
342 !(if_incoming->bat_v.flags & BATADV_FULL_DUPLEX))
343 return throughput / 2;
344
345 /* hop penalty of 255 equals 100% */
346 return throughput * (hop_penalty_max - hop_penalty) / hop_penalty_max;
347}
348
349/**
350 * batadv_v_ogm_forward - forward an OGM to the given outgoing interface
351 * @bat_priv: the bat priv with all the soft interface information
352 * @ogm_received: previously received OGM to be forwarded
353 * @throughput: throughput to announce, may vary per outgoing interface
354 * @if_incoming: the interface on which this OGM was received on
355 * @if_outgoing: the interface to which the OGM has to be forwarded to
356 *
357 * Forward an OGM to an interface after having altered the throughput metric and
358 * the TTL value contained in it. The original OGM isn't modified.
359 */
360static void batadv_v_ogm_forward(struct batadv_priv *bat_priv,
361 const struct batadv_ogm2_packet *ogm_received,
362 u32 throughput,
363 struct batadv_hard_iface *if_incoming,
364 struct batadv_hard_iface *if_outgoing)
365{
366 struct batadv_ogm2_packet *ogm_forward;
367 unsigned char *skb_buff;
368 struct sk_buff *skb;
369 size_t packet_len;
370 u16 tvlv_len;
371
372 if (ogm_received->ttl <= 1) {
373 batadv_dbg(BATADV_DBG_BATMAN, bat_priv, "ttl exceeded\n");
374 return;
375 }
376
377 tvlv_len = ntohs(ogm_received->tvlv_len);
378
379 packet_len = BATADV_OGM2_HLEN + tvlv_len;
380 skb = netdev_alloc_skb_ip_align(if_outgoing->net_dev,
381 ETH_HLEN + packet_len);
382 if (!skb)
383 return;
384
385 skb_reserve(skb, ETH_HLEN);
386 skb_buff = skb_put(skb, packet_len);
387 memcpy(skb_buff, ogm_received, packet_len);
388
389 /* apply forward penalty */
390 ogm_forward = (struct batadv_ogm2_packet *)skb_buff;
391 ogm_forward->throughput = htonl(throughput);
392 ogm_forward->ttl--;
393
394 batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
395 "Forwarding OGM2 packet on %s: throughput %u, ttl %u, received via %s\n",
396 if_outgoing->net_dev->name, throughput, ogm_forward->ttl,
397 if_incoming->net_dev->name);
398
399 batadv_v_ogm_send_to_if(skb, if_outgoing);
400}
401
402/**
403 * batadv_v_ogm_metric_update - update route metric based on OGM
404 * @bat_priv: the bat priv with all the soft interface information
405 * @ogm2: OGM2 structure
406 * @orig_node: Originator structure for which the OGM has been received
407 * @neigh_node: the neigh_node through with the OGM has been received
408 * @if_incoming: the interface where this packet was received
409 * @if_outgoing: the interface for which the packet should be considered
410 *
411 * Return:
412 * 1 if the OGM is new,
413 * 0 if it is not new but valid,
414 * <0 on error (e.g. old OGM)
415 */
416static int batadv_v_ogm_metric_update(struct batadv_priv *bat_priv,
417 const struct batadv_ogm2_packet *ogm2,
418 struct batadv_orig_node *orig_node,
419 struct batadv_neigh_node *neigh_node,
420 struct batadv_hard_iface *if_incoming,
421 struct batadv_hard_iface *if_outgoing)
422{
423 struct batadv_orig_ifinfo *orig_ifinfo = NULL;
424 struct batadv_neigh_ifinfo *neigh_ifinfo = NULL;
425 bool protection_started = false;
426 int ret = -EINVAL;
427 u32 path_throughput;
428 s32 seq_diff;
429
430 orig_ifinfo = batadv_orig_ifinfo_new(orig_node, if_outgoing);
431 if (!orig_ifinfo)
432 goto out;
433
434 seq_diff = ntohl(ogm2->seqno) - orig_ifinfo->last_real_seqno;
435
436 if (!hlist_empty(&orig_node->neigh_list) &&
437 batadv_window_protected(bat_priv, seq_diff,
438 BATADV_OGM_MAX_AGE,
439 &orig_ifinfo->batman_seqno_reset,
440 &protection_started)) {
441 batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
442 "Drop packet: packet within window protection time from %pM\n",
443 ogm2->orig);
444 batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
445 "Last reset: %ld, %ld\n",
446 orig_ifinfo->batman_seqno_reset, jiffies);
447 goto out;
448 }
449
450 /* drop packets with old seqnos, however accept the first packet after
451 * a host has been rebooted.
452 */
453 if ((seq_diff < 0) && !protection_started)
454 goto out;
455
456 neigh_node->last_seen = jiffies;
457
458 orig_node->last_seen = jiffies;
459
460 orig_ifinfo->last_real_seqno = ntohl(ogm2->seqno);
461 orig_ifinfo->last_ttl = ogm2->ttl;
462
463 neigh_ifinfo = batadv_neigh_ifinfo_new(neigh_node, if_outgoing);
464 if (!neigh_ifinfo)
465 goto out;
466
467 path_throughput = batadv_v_forward_penalty(bat_priv, if_incoming,
468 if_outgoing,
469 ntohl(ogm2->throughput));
470 neigh_ifinfo->bat_v.throughput = path_throughput;
471 neigh_ifinfo->bat_v.last_seqno = ntohl(ogm2->seqno);
472 neigh_ifinfo->last_ttl = ogm2->ttl;
473
474 if (seq_diff > 0 || protection_started)
475 ret = 1;
476 else
477 ret = 0;
478out:
479 if (orig_ifinfo)
480 batadv_orig_ifinfo_put(orig_ifinfo);
481 if (neigh_ifinfo)
482 batadv_neigh_ifinfo_put(neigh_ifinfo);
483
484 return ret;
485}
486
487/**
488 * batadv_v_ogm_route_update - update routes based on OGM
489 * @bat_priv: the bat priv with all the soft interface information
490 * @ethhdr: the Ethernet header of the OGM2
491 * @ogm2: OGM2 structure
492 * @orig_node: Originator structure for which the OGM has been received
493 * @neigh_node: the neigh_node through with the OGM has been received
494 * @if_incoming: the interface where this packet was received
495 * @if_outgoing: the interface for which the packet should be considered
496 */
497static void batadv_v_ogm_route_update(struct batadv_priv *bat_priv,
498 const struct ethhdr *ethhdr,
499 const struct batadv_ogm2_packet *ogm2,
500 struct batadv_orig_node *orig_node,
501 struct batadv_neigh_node *neigh_node,
502 struct batadv_hard_iface *if_incoming,
503 struct batadv_hard_iface *if_outgoing)
504{
505 struct batadv_neigh_node *router = NULL;
506 struct batadv_neigh_ifinfo *neigh_ifinfo = NULL;
507 struct batadv_orig_node *orig_neigh_node = NULL;
508 struct batadv_orig_ifinfo *orig_ifinfo = NULL;
509 struct batadv_neigh_node *orig_neigh_router = NULL;
510
511 neigh_ifinfo = batadv_neigh_ifinfo_get(neigh_node, if_outgoing);
512 if (!neigh_ifinfo)
513 goto out;
514
515 orig_neigh_node = batadv_v_ogm_orig_get(bat_priv, ethhdr->h_source);
516 if (!orig_neigh_node)
517 goto out;
518
519 orig_neigh_router = batadv_orig_router_get(orig_neigh_node,
520 if_outgoing);
521
522 /* drop packet if sender is not a direct neighbor and if we
523 * don't route towards it
524 */
525 router = batadv_orig_router_get(orig_node, if_outgoing);
526 if (router && router->orig_node != orig_node && !orig_neigh_router) {
527 batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
528 "Drop packet: OGM via unknown neighbor!\n");
529 goto out;
530 }
531
532 if (router)
533 batadv_neigh_node_put(router);
534
535 /* Update routes, and check if the OGM is from the best next hop */
536 batadv_v_ogm_orig_update(bat_priv, orig_node, neigh_node, ogm2,
537 if_outgoing);
538
539 orig_ifinfo = batadv_orig_ifinfo_new(orig_node, if_outgoing);
540 if (!orig_ifinfo)
541 goto out;
542
543 /* don't forward the same seqno twice on one interface */
544 if (orig_ifinfo->last_seqno_forwarded == ntohl(ogm2->seqno))
545 goto out;
546
547 /* acquire possibly updated router */
548 router = batadv_orig_router_get(orig_node, if_outgoing);
549
550 /* strict rule: forward packets coming from the best next hop only */
551 if (neigh_node != router)
552 goto out;
553
554 /* only forward for specific interface, not for the default one. */
555 if (if_outgoing != BATADV_IF_DEFAULT) {
556 orig_ifinfo->last_seqno_forwarded = ntohl(ogm2->seqno);
557 batadv_v_ogm_forward(bat_priv, ogm2,
558 neigh_ifinfo->bat_v.throughput,
559 if_incoming, if_outgoing);
560 }
561
562out:
563 if (orig_ifinfo)
564 batadv_orig_ifinfo_put(orig_ifinfo);
565 if (router)
566 batadv_neigh_node_put(router);
567 if (orig_neigh_router)
568 batadv_neigh_node_put(orig_neigh_router);
569 if (orig_neigh_node)
570 batadv_orig_node_put(orig_neigh_node);
571 if (neigh_ifinfo)
572 batadv_neigh_ifinfo_put(neigh_ifinfo);
573}
574
575/**
576 * batadv_v_ogm_process_per_outif - process a batman v OGM for an outgoing if
577 * @bat_priv: the bat priv with all the soft interface information
578 * @ethhdr: the Ethernet header of the OGM2
579 * @ogm2: OGM2 structure
580 * @orig_node: Originator structure for which the OGM has been received
581 * @neigh_node: the neigh_node through with the OGM has been received
582 * @if_incoming: the interface where this packet was received
583 * @if_outgoing: the interface for which the packet should be considered
584 */
585static void
586batadv_v_ogm_process_per_outif(struct batadv_priv *bat_priv,
587 const struct ethhdr *ethhdr,
588 const struct batadv_ogm2_packet *ogm2,
589 struct batadv_orig_node *orig_node,
590 struct batadv_neigh_node *neigh_node,
591 struct batadv_hard_iface *if_incoming,
592 struct batadv_hard_iface *if_outgoing)
593{
594 int seqno_age;
595
596 /* first, update the metric with according sanity checks */
597 seqno_age = batadv_v_ogm_metric_update(bat_priv, ogm2, orig_node,
598 neigh_node, if_incoming,
599 if_outgoing);
600
601 /* outdated sequence numbers are to be discarded */
602 if (seqno_age < 0)
603 return;
604
605 /* only unknown & newer OGMs contain TVLVs we are interested in */
606 if ((seqno_age > 0) && (if_outgoing == BATADV_IF_DEFAULT))
607 batadv_tvlv_containers_process(bat_priv, true, orig_node,
608 NULL, NULL,
609 (unsigned char *)(ogm2 + 1),
610 ntohs(ogm2->tvlv_len));
611
612 /* if the metric update went through, update routes if needed */
613 batadv_v_ogm_route_update(bat_priv, ethhdr, ogm2, orig_node,
614 neigh_node, if_incoming, if_outgoing);
615}
616
617/**
618 * batadv_v_ogm_aggr_packet - checks if there is another OGM aggregated
619 * @buff_pos: current position in the skb
620 * @packet_len: total length of the skb
621 * @tvlv_len: tvlv length of the previously considered OGM
622 *
623 * Return: true if there is enough space for another OGM, false otherwise.
624 */
625static bool batadv_v_ogm_aggr_packet(int buff_pos, int packet_len,
626 __be16 tvlv_len)
627{
628 int next_buff_pos = 0;
629
630 next_buff_pos += buff_pos + BATADV_OGM2_HLEN;
631 next_buff_pos += ntohs(tvlv_len);
632
633 return (next_buff_pos <= packet_len) &&
634 (next_buff_pos <= BATADV_MAX_AGGREGATION_BYTES);
635}
636
637/**
638 * batadv_v_ogm_process - process an incoming batman v OGM
639 * @skb: the skb containing the OGM
640 * @ogm_offset: offset to the OGM which should be processed (for aggregates)
641 * @if_incoming: the interface where this packet was receved
642 */
643static void batadv_v_ogm_process(const struct sk_buff *skb, int ogm_offset,
644 struct batadv_hard_iface *if_incoming)
645{
646 struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
647 struct ethhdr *ethhdr;
648 struct batadv_orig_node *orig_node = NULL;
649 struct batadv_hardif_neigh_node *hardif_neigh = NULL;
650 struct batadv_neigh_node *neigh_node = NULL;
651 struct batadv_hard_iface *hard_iface;
652 struct batadv_ogm2_packet *ogm_packet;
653 u32 ogm_throughput, link_throughput, path_throughput;
654
655 ethhdr = eth_hdr(skb);
656 ogm_packet = (struct batadv_ogm2_packet *)(skb->data + ogm_offset);
657
658 ogm_throughput = ntohl(ogm_packet->throughput);
659
660 batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
661 "Received OGM2 packet via NB: %pM, IF: %s [%pM] (from OG: %pM, seqno %u, troughput %u, TTL %u, V %u, tvlv_len %u)\n",
662 ethhdr->h_source, if_incoming->net_dev->name,
663 if_incoming->net_dev->dev_addr, ogm_packet->orig,
664 ntohl(ogm_packet->seqno), ogm_throughput, ogm_packet->ttl,
665 ogm_packet->version, ntohs(ogm_packet->tvlv_len));
666
667 /* If the troughput metric is 0, immediately drop the packet. No need to
668 * create orig_node / neigh_node for an unusable route.
669 */
670 if (ogm_throughput == 0) {
671 batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
672 "Drop packet: originator packet with troughput metric of 0\n");
673 return;
674 }
675
676 /* require ELP packets be to received from this neighbor first */
677 hardif_neigh = batadv_hardif_neigh_get(if_incoming, ethhdr->h_source);
678 if (!hardif_neigh) {
679 batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
680 "Drop packet: OGM via unknown neighbor!\n");
681 goto out;
682 }
683
684 orig_node = batadv_v_ogm_orig_get(bat_priv, ogm_packet->orig);
685 if (!orig_node)
686 return;
687
688 neigh_node = batadv_neigh_node_new(orig_node, if_incoming,
689 ethhdr->h_source);
690 if (!neigh_node)
691 goto out;
692
693 /* Update the received throughput metric to match the link
694 * characteristic:
695 * - If this OGM traveled one hop so far (emitted by single hop
696 * neighbor) the path throughput metric equals the link throughput.
697 * - For OGMs traversing more than hop the path throughput metric is
698 * the smaller of the path throughput and the link throughput.
699 */
700 link_throughput = ewma_throughput_read(&hardif_neigh->bat_v.throughput);
701 path_throughput = min_t(u32, link_throughput, ogm_throughput);
702 ogm_packet->throughput = htonl(path_throughput);
703
704 batadv_v_ogm_process_per_outif(bat_priv, ethhdr, ogm_packet, orig_node,
705 neigh_node, if_incoming,
706 BATADV_IF_DEFAULT);
707
708 rcu_read_lock();
709 list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
710 if (hard_iface->if_status != BATADV_IF_ACTIVE)
711 continue;
712
713 if (hard_iface->soft_iface != bat_priv->soft_iface)
714 continue;
715
716 batadv_v_ogm_process_per_outif(bat_priv, ethhdr, ogm_packet,
717 orig_node, neigh_node,
718 if_incoming, hard_iface);
719 }
720 rcu_read_unlock();
721out:
722 if (orig_node)
723 batadv_orig_node_put(orig_node);
724 if (neigh_node)
725 batadv_neigh_node_put(neigh_node);
726 if (hardif_neigh)
727 batadv_hardif_neigh_put(hardif_neigh);
728}
729
730/**
731 * batadv_v_ogm_packet_recv - OGM2 receiving handler
732 * @skb: the received OGM
733 * @if_incoming: the interface where this OGM has been received
734 *
735 * Return: NET_RX_SUCCESS and consume the skb on success or returns NET_RX_DROP
736 * (without freeing the skb) on failure
737 */
738int batadv_v_ogm_packet_recv(struct sk_buff *skb,
739 struct batadv_hard_iface *if_incoming)
740{
741 struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
742 struct batadv_ogm2_packet *ogm_packet;
743 struct ethhdr *ethhdr = eth_hdr(skb);
744 int ogm_offset;
745 u8 *packet_pos;
746 int ret = NET_RX_DROP;
747
748 /* did we receive a OGM2 packet on an interface that does not have
749 * B.A.T.M.A.N. V enabled ?
750 */
751 if (strcmp(bat_priv->bat_algo_ops->name, "BATMAN_V") != 0)
752 return NET_RX_DROP;
753
754 if (!batadv_check_management_packet(skb, if_incoming, BATADV_OGM2_HLEN))
755 return NET_RX_DROP;
756
757 if (batadv_is_my_mac(bat_priv, ethhdr->h_source))
758 return NET_RX_DROP;
759
760 ogm_packet = (struct batadv_ogm2_packet *)skb->data;
761
762 if (batadv_is_my_mac(bat_priv, ogm_packet->orig))
763 return NET_RX_DROP;
764
765 batadv_inc_counter(bat_priv, BATADV_CNT_MGMT_RX);
766 batadv_add_counter(bat_priv, BATADV_CNT_MGMT_RX_BYTES,
767 skb->len + ETH_HLEN);
768
769 ogm_offset = 0;
770 ogm_packet = (struct batadv_ogm2_packet *)skb->data;
771
772 while (batadv_v_ogm_aggr_packet(ogm_offset, skb_headlen(skb),
773 ogm_packet->tvlv_len)) {
774 batadv_v_ogm_process(skb, ogm_offset, if_incoming);
775
776 ogm_offset += BATADV_OGM2_HLEN;
777 ogm_offset += ntohs(ogm_packet->tvlv_len);
778
779 packet_pos = skb->data + ogm_offset;
780 ogm_packet = (struct batadv_ogm2_packet *)packet_pos;
781 }
782
783 ret = NET_RX_SUCCESS;
784 consume_skb(skb);
785
786 return ret;
787}
788
789/**
790 * batadv_v_ogm_init - initialise the OGM2 engine
791 * @bat_priv: the bat priv with all the soft interface information
792 *
793 * Return: 0 on success or a negative error code in case of failure
794 */
795int batadv_v_ogm_init(struct batadv_priv *bat_priv)
796{
797 struct batadv_ogm2_packet *ogm_packet;
798 unsigned char *ogm_buff;
799 u32 random_seqno;
800
801 bat_priv->bat_v.ogm_buff_len = BATADV_OGM2_HLEN;
802 ogm_buff = kzalloc(bat_priv->bat_v.ogm_buff_len, GFP_ATOMIC);
803 if (!ogm_buff)
804 return -ENOMEM;
805
806 bat_priv->bat_v.ogm_buff = ogm_buff;
807 ogm_packet = (struct batadv_ogm2_packet *)ogm_buff;
808 ogm_packet->packet_type = BATADV_OGM2;
809 ogm_packet->version = BATADV_COMPAT_VERSION;
810 ogm_packet->ttl = BATADV_TTL;
811 ogm_packet->flags = BATADV_NO_FLAGS;
812 ogm_packet->throughput = htonl(BATADV_THROUGHPUT_MAX_VALUE);
813
814 /* randomize initial seqno to avoid collision */
815 get_random_bytes(&random_seqno, sizeof(random_seqno));
816 atomic_set(&bat_priv->bat_v.ogm_seqno, random_seqno);
817 INIT_DELAYED_WORK(&bat_priv->bat_v.ogm_wq, batadv_v_ogm_send);
818
819 return 0;
820}
821
822/**
823 * batadv_v_ogm_free - free OGM private resources
824 * @bat_priv: the bat priv with all the soft interface information
825 */
826void batadv_v_ogm_free(struct batadv_priv *bat_priv)
827{
828 cancel_delayed_work_sync(&bat_priv->bat_v.ogm_wq);
829
830 kfree(bat_priv->bat_v.ogm_buff);
831 bat_priv->bat_v.ogm_buff = NULL;
832 bat_priv->bat_v.ogm_buff_len = 0;
833}
diff --git a/net/batman-adv/bat_v_ogm.h b/net/batman-adv/bat_v_ogm.h
new file mode 100644
index 000000000000..d849c75ada0e
--- /dev/null
+++ b/net/batman-adv/bat_v_ogm.h
@@ -0,0 +1,36 @@
1/* Copyright (C) 2013-2016 B.A.T.M.A.N. contributors:
2 *
3 * Antonio Quartulli
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
18#ifndef _BATMAN_ADV_BATADV_V_OGM_H_
19#define _BATMAN_ADV_BATADV_V_OGM_H_
20
21#include <linux/types.h>
22
23struct batadv_hard_iface;
24struct batadv_priv;
25struct sk_buff;
26
27int batadv_v_ogm_init(struct batadv_priv *bat_priv);
28void batadv_v_ogm_free(struct batadv_priv *bat_priv);
29int batadv_v_ogm_iface_enable(struct batadv_hard_iface *hard_iface);
30struct batadv_orig_node *batadv_v_ogm_orig_get(struct batadv_priv *bat_priv,
31 const u8 *addr);
32void batadv_v_ogm_primary_iface_set(struct batadv_hard_iface *primary_iface);
33int batadv_v_ogm_packet_recv(struct sk_buff *skb,
34 struct batadv_hard_iface *if_incoming);
35
36#endif /* _BATMAN_ADV_BATADV_V_OGM_H_ */
diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c
index 4c9b69d465a6..e96d7c745b4a 100644
--- a/net/batman-adv/distributed-arp-table.c
+++ b/net/batman-adv/distributed-arp-table.c
@@ -654,9 +654,7 @@ static bool batadv_dat_send_data(struct batadv_priv *bat_priv,
654 goto free_neigh; 654 goto free_neigh;
655 } 655 }
656 656
657 send_status = batadv_send_skb_packet(tmp_skb, 657 send_status = batadv_send_unicast_skb(tmp_skb, neigh_node);
658 neigh_node->if_incoming,
659 neigh_node->addr);
660 if (send_status == NET_XMIT_SUCCESS) { 658 if (send_status == NET_XMIT_SUCCESS) {
661 /* count the sent packet */ 659 /* count the sent packet */
662 switch (packet_subtype) { 660 switch (packet_subtype) {
diff --git a/net/batman-adv/fragmentation.c b/net/batman-adv/fragmentation.c
index adb9c3989add..e6956d0746a2 100644
--- a/net/batman-adv/fragmentation.c
+++ b/net/batman-adv/fragmentation.c
@@ -378,8 +378,7 @@ bool batadv_frag_skb_fwd(struct sk_buff *skb,
378 skb->len + ETH_HLEN); 378 skb->len + ETH_HLEN);
379 379
380 packet->ttl--; 380 packet->ttl--;
381 batadv_send_skb_packet(skb, neigh_node->if_incoming, 381 batadv_send_unicast_skb(skb, neigh_node);
382 neigh_node->addr);
383 ret = true; 382 ret = true;
384 } 383 }
385 384
@@ -486,8 +485,7 @@ bool batadv_frag_send_packet(struct sk_buff *skb,
486 batadv_inc_counter(bat_priv, BATADV_CNT_FRAG_TX); 485 batadv_inc_counter(bat_priv, BATADV_CNT_FRAG_TX);
487 batadv_add_counter(bat_priv, BATADV_CNT_FRAG_TX_BYTES, 486 batadv_add_counter(bat_priv, BATADV_CNT_FRAG_TX_BYTES,
488 skb_fragment->len + ETH_HLEN); 487 skb_fragment->len + ETH_HLEN);
489 batadv_send_skb_packet(skb_fragment, neigh_node->if_incoming, 488 batadv_send_unicast_skb(skb_fragment, neigh_node);
490 neigh_node->addr);
491 frag_header.no++; 489 frag_header.no++;
492 490
493 /* The initial check in this function should cover this case */ 491 /* The initial check in this function should cover this case */
@@ -506,7 +504,7 @@ bool batadv_frag_send_packet(struct sk_buff *skb,
506 batadv_inc_counter(bat_priv, BATADV_CNT_FRAG_TX); 504 batadv_inc_counter(bat_priv, BATADV_CNT_FRAG_TX);
507 batadv_add_counter(bat_priv, BATADV_CNT_FRAG_TX_BYTES, 505 batadv_add_counter(bat_priv, BATADV_CNT_FRAG_TX_BYTES,
508 skb->len + ETH_HLEN); 506 skb->len + ETH_HLEN);
509 batadv_send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); 507 batadv_send_unicast_skb(skb, neigh_node);
510 508
511 ret = true; 509 ret = true;
512 510
diff --git a/net/batman-adv/gateway_common.c b/net/batman-adv/gateway_common.c
index 5ee04f7140af..4423047889e1 100644
--- a/net/batman-adv/gateway_common.c
+++ b/net/batman-adv/gateway_common.c
@@ -40,8 +40,8 @@
40 * 40 *
41 * Return: false on parse error and true otherwise. 41 * Return: false on parse error and true otherwise.
42 */ 42 */
43static bool batadv_parse_throughput(struct net_device *net_dev, char *buff, 43bool batadv_parse_throughput(struct net_device *net_dev, char *buff,
44 const char *description, u32 *throughput) 44 const char *description, u32 *throughput)
45{ 45{
46 enum batadv_bandwidth_units bw_unit_type = BATADV_BW_UNIT_KBIT; 46 enum batadv_bandwidth_units bw_unit_type = BATADV_BW_UNIT_KBIT;
47 u64 lthroughput; 47 u64 lthroughput;
diff --git a/net/batman-adv/gateway_common.h b/net/batman-adv/gateway_common.h
index b58346350024..8a5e1ddf1175 100644
--- a/net/batman-adv/gateway_common.h
+++ b/net/batman-adv/gateway_common.h
@@ -49,5 +49,7 @@ ssize_t batadv_gw_bandwidth_set(struct net_device *net_dev, char *buff,
49void batadv_gw_tvlv_container_update(struct batadv_priv *bat_priv); 49void batadv_gw_tvlv_container_update(struct batadv_priv *bat_priv);
50void batadv_gw_init(struct batadv_priv *bat_priv); 50void batadv_gw_init(struct batadv_priv *bat_priv);
51void batadv_gw_free(struct batadv_priv *bat_priv); 51void batadv_gw_free(struct batadv_priv *bat_priv);
52bool batadv_parse_throughput(struct net_device *net_dev, char *buff,
53 const char *description, u32 *throughput);
52 54
53#endif /* _NET_BATMAN_ADV_GATEWAY_COMMON_H_ */ 55#endif /* _NET_BATMAN_ADV_GATEWAY_COMMON_H_ */
diff --git a/net/batman-adv/icmp_socket.c b/net/batman-adv/icmp_socket.c
index 6268f08b7154..14d0013b387e 100644
--- a/net/batman-adv/icmp_socket.c
+++ b/net/batman-adv/icmp_socket.c
@@ -278,7 +278,7 @@ static ssize_t batadv_socket_write(struct file *file, const char __user *buff,
278 278
279 ether_addr_copy(icmp_header->orig, primary_if->net_dev->dev_addr); 279 ether_addr_copy(icmp_header->orig, primary_if->net_dev->dev_addr);
280 280
281 batadv_send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); 281 batadv_send_unicast_skb(skb, neigh_node);
282 goto out; 282 goto out;
283 283
284dst_unreach: 284dst_unreach:
diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c
index e3d7051747b0..d64ddb961979 100644
--- a/net/batman-adv/main.c
+++ b/net/batman-adv/main.c
@@ -87,6 +87,7 @@ static int __init batadv_init(void)
87 87
88 batadv_recv_handler_init(); 88 batadv_recv_handler_init();
89 89
90 batadv_v_init();
90 batadv_iv_init(); 91 batadv_iv_init();
91 batadv_nc_init(); 92 batadv_nc_init();
92 93
@@ -159,6 +160,10 @@ int batadv_mesh_init(struct net_device *soft_iface)
159 INIT_HLIST_HEAD(&bat_priv->tvlv.handler_list); 160 INIT_HLIST_HEAD(&bat_priv->tvlv.handler_list);
160 INIT_HLIST_HEAD(&bat_priv->softif_vlan_list); 161 INIT_HLIST_HEAD(&bat_priv->softif_vlan_list);
161 162
163 ret = batadv_v_mesh_init(bat_priv);
164 if (ret < 0)
165 goto err;
166
162 ret = batadv_originator_init(bat_priv); 167 ret = batadv_originator_init(bat_priv);
163 if (ret < 0) 168 if (ret < 0)
164 goto err; 169 goto err;
@@ -201,6 +206,8 @@ void batadv_mesh_free(struct net_device *soft_iface)
201 batadv_purge_outstanding_packets(bat_priv, NULL); 206 batadv_purge_outstanding_packets(bat_priv, NULL);
202 207
203 batadv_gw_node_free(bat_priv); 208 batadv_gw_node_free(bat_priv);
209
210 batadv_v_mesh_free(bat_priv);
204 batadv_nc_mesh_free(bat_priv); 211 batadv_nc_mesh_free(bat_priv);
205 batadv_dat_free(bat_priv); 212 batadv_dat_free(bat_priv);
206 batadv_bla_free(bat_priv); 213 batadv_bla_free(bat_priv);
diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h
index 8c01f54c61f3..db4533631834 100644
--- a/net/batman-adv/main.h
+++ b/net/batman-adv/main.h
@@ -24,12 +24,13 @@
24#define BATADV_DRIVER_DEVICE "batman-adv" 24#define BATADV_DRIVER_DEVICE "batman-adv"
25 25
26#ifndef BATADV_SOURCE_VERSION 26#ifndef BATADV_SOURCE_VERSION
27#define BATADV_SOURCE_VERSION "2016.0" 27#define BATADV_SOURCE_VERSION "2016.1"
28#endif 28#endif
29 29
30/* B.A.T.M.A.N. parameters */ 30/* B.A.T.M.A.N. parameters */
31 31
32#define BATADV_TQ_MAX_VALUE 255 32#define BATADV_TQ_MAX_VALUE 255
33#define BATADV_THROUGHPUT_MAX_VALUE 0xFFFFFFFF
33#define BATADV_JITTER 20 34#define BATADV_JITTER 20
34 35
35/* Time To Live of broadcast messages */ 36/* Time To Live of broadcast messages */
@@ -60,6 +61,15 @@
60#define BATADV_TQ_LOCAL_BIDRECT_RECV_MINIMUM 1 61#define BATADV_TQ_LOCAL_BIDRECT_RECV_MINIMUM 1
61#define BATADV_TQ_TOTAL_BIDRECT_LIMIT 1 62#define BATADV_TQ_TOTAL_BIDRECT_LIMIT 1
62 63
64/* B.A.T.M.A.N. V */
65#define BATADV_THROUGHPUT_DEFAULT_VALUE 10 /* 1 Mbps */
66#define BATADV_ELP_PROBES_PER_NODE 2
67#define BATADV_ELP_MIN_PROBE_SIZE 200 /* bytes */
68#define BATADV_ELP_PROBE_MAX_TX_DIFF 100 /* milliseconds */
69#define BATADV_ELP_MAX_AGE 64
70#define BATADV_OGM_MAX_ORIGDIFF 5
71#define BATADV_OGM_MAX_AGE 64
72
63/* number of OGMs sent with the last tt diff */ 73/* number of OGMs sent with the last tt diff */
64#define BATADV_TT_OGM_APPEND_MAX 3 74#define BATADV_TT_OGM_APPEND_MAX 3
65 75
diff --git a/net/batman-adv/network-coding.c b/net/batman-adv/network-coding.c
index d253bb23e2ac..b41719b6487a 100644
--- a/net/batman-adv/network-coding.c
+++ b/net/batman-adv/network-coding.c
@@ -575,9 +575,7 @@ batadv_nc_hash_find(struct batadv_hashtable *hash,
575 */ 575 */
576static void batadv_nc_send_packet(struct batadv_nc_packet *nc_packet) 576static void batadv_nc_send_packet(struct batadv_nc_packet *nc_packet)
577{ 577{
578 batadv_send_skb_packet(nc_packet->skb, 578 batadv_send_unicast_skb(nc_packet->skb, nc_packet->neigh_node);
579 nc_packet->neigh_node->if_incoming,
580 nc_packet->nc_path->next_hop);
581 nc_packet->skb = NULL; 579 nc_packet->skb = NULL;
582 batadv_nc_packet_free(nc_packet); 580 batadv_nc_packet_free(nc_packet);
583} 581}
@@ -1067,11 +1065,11 @@ static bool batadv_nc_code_packets(struct batadv_priv *bat_priv,
1067 struct batadv_unicast_packet *packet1; 1065 struct batadv_unicast_packet *packet1;
1068 struct batadv_unicast_packet *packet2; 1066 struct batadv_unicast_packet *packet2;
1069 struct batadv_coded_packet *coded_packet; 1067 struct batadv_coded_packet *coded_packet;
1070 struct batadv_neigh_node *neigh_tmp, *router_neigh; 1068 struct batadv_neigh_node *neigh_tmp, *router_neigh, *first_dest;
1071 struct batadv_neigh_node *router_coding = NULL; 1069 struct batadv_neigh_node *router_coding = NULL, *second_dest;
1072 struct batadv_neigh_ifinfo *router_neigh_ifinfo = NULL; 1070 struct batadv_neigh_ifinfo *router_neigh_ifinfo = NULL;
1073 struct batadv_neigh_ifinfo *router_coding_ifinfo = NULL; 1071 struct batadv_neigh_ifinfo *router_coding_ifinfo = NULL;
1074 u8 *first_source, *first_dest, *second_source, *second_dest; 1072 u8 *first_source, *second_source;
1075 __be32 packet_id1, packet_id2; 1073 __be32 packet_id1, packet_id2;
1076 size_t count; 1074 size_t count;
1077 bool res = false; 1075 bool res = false;
@@ -1114,9 +1112,9 @@ static bool batadv_nc_code_packets(struct batadv_priv *bat_priv,
1114 */ 1112 */
1115 if (tq_weighted_neigh >= tq_weighted_coding) { 1113 if (tq_weighted_neigh >= tq_weighted_coding) {
1116 /* Destination from nc_packet is selected for MAC-header */ 1114 /* Destination from nc_packet is selected for MAC-header */
1117 first_dest = nc_packet->nc_path->next_hop; 1115 first_dest = nc_packet->neigh_node;
1118 first_source = nc_packet->nc_path->prev_hop; 1116 first_source = nc_packet->nc_path->prev_hop;
1119 second_dest = neigh_node->addr; 1117 second_dest = neigh_node;
1120 second_source = ethhdr->h_source; 1118 second_source = ethhdr->h_source;
1121 packet1 = (struct batadv_unicast_packet *)nc_packet->skb->data; 1119 packet1 = (struct batadv_unicast_packet *)nc_packet->skb->data;
1122 packet2 = (struct batadv_unicast_packet *)skb->data; 1120 packet2 = (struct batadv_unicast_packet *)skb->data;
@@ -1125,9 +1123,9 @@ static bool batadv_nc_code_packets(struct batadv_priv *bat_priv,
1125 skb->data + sizeof(*packet2)); 1123 skb->data + sizeof(*packet2));
1126 } else { 1124 } else {
1127 /* Destination for skb is selected for MAC-header */ 1125 /* Destination for skb is selected for MAC-header */
1128 first_dest = neigh_node->addr; 1126 first_dest = neigh_node;
1129 first_source = ethhdr->h_source; 1127 first_source = ethhdr->h_source;
1130 second_dest = nc_packet->nc_path->next_hop; 1128 second_dest = nc_packet->neigh_node;
1131 second_source = nc_packet->nc_path->prev_hop; 1129 second_source = nc_packet->nc_path->prev_hop;
1132 packet1 = (struct batadv_unicast_packet *)skb->data; 1130 packet1 = (struct batadv_unicast_packet *)skb->data;
1133 packet2 = (struct batadv_unicast_packet *)nc_packet->skb->data; 1131 packet2 = (struct batadv_unicast_packet *)nc_packet->skb->data;
@@ -1169,7 +1167,7 @@ static bool batadv_nc_code_packets(struct batadv_priv *bat_priv,
1169 coded_packet->first_ttvn = packet1->ttvn; 1167 coded_packet->first_ttvn = packet1->ttvn;
1170 1168
1171 /* Info about second unicast packet */ 1169 /* Info about second unicast packet */
1172 ether_addr_copy(coded_packet->second_dest, second_dest); 1170 ether_addr_copy(coded_packet->second_dest, second_dest->addr);
1173 ether_addr_copy(coded_packet->second_source, second_source); 1171 ether_addr_copy(coded_packet->second_source, second_source);
1174 ether_addr_copy(coded_packet->second_orig_dest, packet2->dest); 1172 ether_addr_copy(coded_packet->second_orig_dest, packet2->dest);
1175 coded_packet->second_crc = packet_id2; 1173 coded_packet->second_crc = packet_id2;
@@ -1224,7 +1222,7 @@ static bool batadv_nc_code_packets(struct batadv_priv *bat_priv,
1224 batadv_nc_packet_free(nc_packet); 1222 batadv_nc_packet_free(nc_packet);
1225 1223
1226 /* Send the coded packet and return true */ 1224 /* Send the coded packet and return true */
1227 batadv_send_skb_packet(skb_dest, neigh_node->if_incoming, first_dest); 1225 batadv_send_unicast_skb(skb_dest, first_dest);
1228 res = true; 1226 res = true;
1229out: 1227out:
1230 if (router_neigh) 1228 if (router_neigh)
diff --git a/net/batman-adv/packet.h b/net/batman-adv/packet.h
index e7f915181aba..8a8d7ca1a5cf 100644
--- a/net/batman-adv/packet.h
+++ b/net/batman-adv/packet.h
@@ -26,6 +26,8 @@
26 * @BATADV_IV_OGM: originator messages for B.A.T.M.A.N. IV 26 * @BATADV_IV_OGM: originator messages for B.A.T.M.A.N. IV
27 * @BATADV_BCAST: broadcast packets carrying broadcast payload 27 * @BATADV_BCAST: broadcast packets carrying broadcast payload
28 * @BATADV_CODED: network coded packets 28 * @BATADV_CODED: network coded packets
29 * @BATADV_ELP: echo location packets for B.A.T.M.A.N. V
30 * @BATADV_OGM2: originator messages for B.A.T.M.A.N. V
29 * 31 *
30 * @BATADV_UNICAST: unicast packets carrying unicast payload traffic 32 * @BATADV_UNICAST: unicast packets carrying unicast payload traffic
31 * @BATADV_UNICAST_FRAG: unicast packets carrying a fragment of the original 33 * @BATADV_UNICAST_FRAG: unicast packets carrying a fragment of the original
@@ -40,6 +42,8 @@ enum batadv_packettype {
40 BATADV_IV_OGM = 0x00, 42 BATADV_IV_OGM = 0x00,
41 BATADV_BCAST = 0x01, 43 BATADV_BCAST = 0x01,
42 BATADV_CODED = 0x02, 44 BATADV_CODED = 0x02,
45 BATADV_ELP = 0x03,
46 BATADV_OGM2 = 0x04,
43 /* 0x40 - 0x7f: unicast */ 47 /* 0x40 - 0x7f: unicast */
44#define BATADV_UNICAST_MIN 0x40 48#define BATADV_UNICAST_MIN 0x40
45 BATADV_UNICAST = 0x40, 49 BATADV_UNICAST = 0x40,
@@ -235,6 +239,51 @@ struct batadv_ogm_packet {
235#define BATADV_OGM_HLEN sizeof(struct batadv_ogm_packet) 239#define BATADV_OGM_HLEN sizeof(struct batadv_ogm_packet)
236 240
237/** 241/**
242 * struct batadv_ogm2_packet - ogm2 (routing protocol) packet
243 * @packet_type: batman-adv packet type, part of the general header
244 * @version: batman-adv protocol version, part of the general header
245 * @ttl: time to live for this packet, part of the general header
246 * @flags: reseved for routing relevant flags - currently always 0
247 * @seqno: sequence number
248 * @orig: originator mac address
249 * @tvlv_len: length of the appended tvlv buffer (in bytes)
250 * @throughput: the currently flooded path throughput
251 */
252struct batadv_ogm2_packet {
253 u8 packet_type;
254 u8 version;
255 u8 ttl;
256 u8 flags;
257 __be32 seqno;
258 u8 orig[ETH_ALEN];
259 __be16 tvlv_len;
260 __be32 throughput;
261 /* __packed is not needed as the struct size is divisible by 4,
262 * and the largest data type in this struct has a size of 4.
263 */
264};
265
266#define BATADV_OGM2_HLEN sizeof(struct batadv_ogm2_packet)
267
268/**
269 * struct batadv_elp_packet - elp (neighbor discovery) packet
270 * @packet_type: batman-adv packet type, part of the general header
271 * @version: batman-adv protocol version, part of the genereal header
272 * @orig: originator mac address
273 * @seqno: sequence number
274 * @elp_interval: currently used ELP sending interval in ms
275 */
276struct batadv_elp_packet {
277 u8 packet_type;
278 u8 version;
279 u8 orig[ETH_ALEN];
280 __be32 seqno;
281 __be32 elp_interval;
282};
283
284#define BATADV_ELP_HLEN sizeof(struct batadv_elp_packet)
285
286/**
238 * struct batadv_icmp_header - common members among all the ICMP packets 287 * struct batadv_icmp_header - common members among all the ICMP packets
239 * @packet_type: batman-adv packet type, part of the general header 288 * @packet_type: batman-adv packet type, part of the general header
240 * @version: batman-adv protocol version, part of the genereal header 289 * @version: batman-adv protocol version, part of the genereal header
diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c
index caff32cf6fe7..3ce06e0a91b1 100644
--- a/net/batman-adv/send.c
+++ b/net/batman-adv/send.c
@@ -49,16 +49,30 @@
49 49
50static void batadv_send_outstanding_bcast_packet(struct work_struct *work); 50static void batadv_send_outstanding_bcast_packet(struct work_struct *work);
51 51
52/* send out an already prepared packet to the given address via the 52/**
53 * specified batman interface 53 * batadv_send_skb_packet - send an already prepared packet
54 * @skb: the packet to send
55 * @hard_iface: the interface to use to send the broadcast packet
56 * @dst_addr: the payload destination
57 *
58 * Send out an already prepared packet to the given neighbor or broadcast it
59 * using the specified interface. Either hard_iface or neigh_node must be not
60 * NULL.
61 * If neigh_node is NULL, then the packet is broadcasted using hard_iface,
62 * otherwise it is sent as unicast to the given neighbor.
63 *
64 * Return: NET_TX_DROP in case of error or the result of dev_queue_xmit(skb)
65 * otherwise
54 */ 66 */
55int batadv_send_skb_packet(struct sk_buff *skb, 67int batadv_send_skb_packet(struct sk_buff *skb,
56 struct batadv_hard_iface *hard_iface, 68 struct batadv_hard_iface *hard_iface,
57 const u8 *dst_addr) 69 const u8 *dst_addr)
58{ 70{
59 struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface); 71 struct batadv_priv *bat_priv;
60 struct ethhdr *ethhdr; 72 struct ethhdr *ethhdr;
61 73
74 bat_priv = netdev_priv(hard_iface->soft_iface);
75
62 if (hard_iface->if_status != BATADV_IF_ACTIVE) 76 if (hard_iface->if_status != BATADV_IF_ACTIVE)
63 goto send_skb_err; 77 goto send_skb_err;
64 78
@@ -100,6 +114,35 @@ send_skb_err:
100 return NET_XMIT_DROP; 114 return NET_XMIT_DROP;
101} 115}
102 116
117int batadv_send_broadcast_skb(struct sk_buff *skb,
118 struct batadv_hard_iface *hard_iface)
119{
120 return batadv_send_skb_packet(skb, hard_iface, batadv_broadcast_addr);
121}
122
123int batadv_send_unicast_skb(struct sk_buff *skb,
124 struct batadv_neigh_node *neigh)
125{
126#ifdef CONFIG_BATMAN_ADV_BATMAN_V
127 struct batadv_hardif_neigh_node *hardif_neigh;
128#endif
129 int ret;
130
131 ret = batadv_send_skb_packet(skb, neigh->if_incoming, neigh->addr);
132
133#ifdef CONFIG_BATMAN_ADV_BATMAN_V
134 hardif_neigh = batadv_hardif_neigh_get(neigh->if_incoming, neigh->addr);
135
136 if ((hardif_neigh) && (ret != NET_XMIT_DROP))
137 hardif_neigh->bat_v.last_unicast_tx = jiffies;
138
139 if (hardif_neigh)
140 batadv_hardif_neigh_put(hardif_neigh);
141#endif
142
143 return ret;
144}
145
103/** 146/**
104 * batadv_send_skb_to_orig - Lookup next-hop and transmit skb. 147 * batadv_send_skb_to_orig - Lookup next-hop and transmit skb.
105 * @skb: Packet to be transmitted. 148 * @skb: Packet to be transmitted.
@@ -146,8 +189,7 @@ int batadv_send_skb_to_orig(struct sk_buff *skb,
146 if (recv_if && batadv_nc_skb_forward(skb, neigh_node)) { 189 if (recv_if && batadv_nc_skb_forward(skb, neigh_node)) {
147 ret = NET_XMIT_POLICED; 190 ret = NET_XMIT_POLICED;
148 } else { 191 } else {
149 batadv_send_skb_packet(skb, neigh_node->if_incoming, 192 batadv_send_unicast_skb(skb, neigh_node);
150 neigh_node->addr);
151 ret = NET_XMIT_SUCCESS; 193 ret = NET_XMIT_SUCCESS;
152 } 194 }
153 195
@@ -538,8 +580,7 @@ static void batadv_send_outstanding_bcast_packet(struct work_struct *work)
538 /* send a copy of the saved skb */ 580 /* send a copy of the saved skb */
539 skb1 = skb_clone(forw_packet->skb, GFP_ATOMIC); 581 skb1 = skb_clone(forw_packet->skb, GFP_ATOMIC);
540 if (skb1) 582 if (skb1)
541 batadv_send_skb_packet(skb1, hard_iface, 583 batadv_send_broadcast_skb(skb1, hard_iface);
542 batadv_broadcast_addr);
543 } 584 }
544 rcu_read_unlock(); 585 rcu_read_unlock();
545 586
diff --git a/net/batman-adv/send.h b/net/batman-adv/send.h
index 7ff95cada2e7..6fd7270d8ce6 100644
--- a/net/batman-adv/send.h
+++ b/net/batman-adv/send.h
@@ -28,12 +28,16 @@
28struct sk_buff; 28struct sk_buff;
29struct work_struct; 29struct work_struct;
30 30
31int batadv_send_skb_packet(struct sk_buff *skb,
32 struct batadv_hard_iface *hard_iface,
33 const u8 *dst_addr);
34int batadv_send_skb_to_orig(struct sk_buff *skb, 31int batadv_send_skb_to_orig(struct sk_buff *skb,
35 struct batadv_orig_node *orig_node, 32 struct batadv_orig_node *orig_node,
36 struct batadv_hard_iface *recv_if); 33 struct batadv_hard_iface *recv_if);
34int batadv_send_skb_packet(struct sk_buff *skb,
35 struct batadv_hard_iface *hard_iface,
36 const u8 *dst_addr);
37int batadv_send_broadcast_skb(struct sk_buff *skb,
38 struct batadv_hard_iface *hard_iface);
39int batadv_send_unicast_skb(struct sk_buff *skb,
40 struct batadv_neigh_node *neigh_node);
37void batadv_schedule_bat_ogm(struct batadv_hard_iface *hard_iface); 41void batadv_schedule_bat_ogm(struct batadv_hard_iface *hard_iface);
38int batadv_add_bcast_packet_to_list(struct batadv_priv *bat_priv, 42int batadv_add_bcast_packet_to_list(struct batadv_priv *bat_priv,
39 const struct sk_buff *skb, 43 const struct sk_buff *skb,
diff --git a/net/batman-adv/sysfs.c b/net/batman-adv/sysfs.c
index 4d70d4413e40..e7cf51333a36 100644
--- a/net/batman-adv/sysfs.c
+++ b/net/batman-adv/sysfs.c
@@ -242,6 +242,55 @@ ssize_t batadv_show_vlan_##_name(struct kobject *kobj, \
242 static BATADV_ATTR_VLAN(_name, _mode, batadv_show_vlan_##_name, \ 242 static BATADV_ATTR_VLAN(_name, _mode, batadv_show_vlan_##_name, \
243 batadv_store_vlan_##_name) 243 batadv_store_vlan_##_name)
244 244
245#define BATADV_ATTR_HIF_STORE_UINT(_name, _var, _min, _max, _post_func) \
246ssize_t batadv_store_##_name(struct kobject *kobj, \
247 struct attribute *attr, char *buff, \
248 size_t count) \
249{ \
250 struct net_device *net_dev = batadv_kobj_to_netdev(kobj); \
251 struct batadv_hard_iface *hard_iface; \
252 ssize_t length; \
253 \
254 hard_iface = batadv_hardif_get_by_netdev(net_dev); \
255 if (!hard_iface) \
256 return 0; \
257 \
258 length = __batadv_store_uint_attr(buff, count, _min, _max, \
259 _post_func, attr, \
260 &hard_iface->_var, net_dev); \
261 \
262 batadv_hardif_put(hard_iface); \
263 return length; \
264}
265
266#define BATADV_ATTR_HIF_SHOW_UINT(_name, _var) \
267ssize_t batadv_show_##_name(struct kobject *kobj, \
268 struct attribute *attr, char *buff) \
269{ \
270 struct net_device *net_dev = batadv_kobj_to_netdev(kobj); \
271 struct batadv_hard_iface *hard_iface; \
272 ssize_t length; \
273 \
274 hard_iface = batadv_hardif_get_by_netdev(net_dev); \
275 if (!hard_iface) \
276 return 0; \
277 \
278 length = sprintf(buff, "%i\n", atomic_read(&hard_iface->_var)); \
279 \
280 batadv_hardif_put(hard_iface); \
281 return length; \
282}
283
284/* Use this, if you are going to set [name] in hard_iface to an
285 * unsigned integer value
286 */
287#define BATADV_ATTR_HIF_UINT(_name, _var, _mode, _min, _max, _post_func)\
288 static BATADV_ATTR_HIF_STORE_UINT(_name, _var, _min, \
289 _max, _post_func) \
290 static BATADV_ATTR_HIF_SHOW_UINT(_name, _var) \
291 static BATADV_ATTR(_name, _mode, batadv_show_##_name, \
292 batadv_store_##_name)
293
245static int batadv_store_bool_attr(char *buff, size_t count, 294static int batadv_store_bool_attr(char *buff, size_t count,
246 struct net_device *net_dev, 295 struct net_device *net_dev,
247 const char *attr_name, atomic_t *attr, 296 const char *attr_name, atomic_t *attr,
@@ -868,13 +917,94 @@ static ssize_t batadv_show_iface_status(struct kobject *kobj,
868 return length; 917 return length;
869} 918}
870 919
920#ifdef CONFIG_BATMAN_ADV_BATMAN_V
921
922/**
923 * batadv_store_throughput_override - parse and store throughput override
924 * entered by the user
925 * @kobj: kobject representing the private mesh sysfs directory
926 * @attr: the batman-adv attribute the user is interacting with
927 * @buff: the buffer containing the user data
928 * @count: number of bytes in the buffer
929 *
930 * Return: 'count' on success or a negative error code in case of failure
931 */
932static ssize_t batadv_store_throughput_override(struct kobject *kobj,
933 struct attribute *attr,
934 char *buff, size_t count)
935{
936 struct net_device *net_dev = batadv_kobj_to_netdev(kobj);
937 struct batadv_hard_iface *hard_iface;
938 u32 tp_override;
939 u32 old_tp_override;
940 bool ret;
941
942 hard_iface = batadv_hardif_get_by_netdev(net_dev);
943 if (!hard_iface)
944 return -EINVAL;
945
946 if (buff[count - 1] == '\n')
947 buff[count - 1] = '\0';
948
949 ret = batadv_parse_throughput(net_dev, buff, "throughput_override",
950 &tp_override);
951 if (!ret)
952 return count;
953
954 old_tp_override = atomic_read(&hard_iface->bat_v.throughput_override);
955 if (old_tp_override == tp_override)
956 goto out;
957
958 batadv_info(net_dev, "%s: Changing from: %u.%u MBit to: %u.%u MBit\n",
959 "throughput_override",
960 old_tp_override / 10, old_tp_override % 10,
961 tp_override / 10, tp_override % 10);
962
963 atomic_set(&hard_iface->bat_v.throughput_override, tp_override);
964
965out:
966 batadv_hardif_put(hard_iface);
967 return count;
968}
969
970static ssize_t batadv_show_throughput_override(struct kobject *kobj,
971 struct attribute *attr,
972 char *buff)
973{
974 struct net_device *net_dev = batadv_kobj_to_netdev(kobj);
975 struct batadv_hard_iface *hard_iface;
976 u32 tp_override;
977
978 hard_iface = batadv_hardif_get_by_netdev(net_dev);
979 if (!hard_iface)
980 return -EINVAL;
981
982 tp_override = atomic_read(&hard_iface->bat_v.throughput_override);
983
984 return sprintf(buff, "%u.%u MBit\n", tp_override / 10,
985 tp_override % 10);
986}
987
988#endif
989
871static BATADV_ATTR(mesh_iface, S_IRUGO | S_IWUSR, batadv_show_mesh_iface, 990static BATADV_ATTR(mesh_iface, S_IRUGO | S_IWUSR, batadv_show_mesh_iface,
872 batadv_store_mesh_iface); 991 batadv_store_mesh_iface);
873static BATADV_ATTR(iface_status, S_IRUGO, batadv_show_iface_status, NULL); 992static BATADV_ATTR(iface_status, S_IRUGO, batadv_show_iface_status, NULL);
993#ifdef CONFIG_BATMAN_ADV_BATMAN_V
994BATADV_ATTR_HIF_UINT(elp_interval, bat_v.elp_interval, S_IRUGO | S_IWUSR,
995 2 * BATADV_JITTER, INT_MAX, NULL);
996static BATADV_ATTR(throughput_override, S_IRUGO | S_IWUSR,
997 batadv_show_throughput_override,
998 batadv_store_throughput_override);
999#endif
874 1000
875static struct batadv_attribute *batadv_batman_attrs[] = { 1001static struct batadv_attribute *batadv_batman_attrs[] = {
876 &batadv_attr_mesh_iface, 1002 &batadv_attr_mesh_iface,
877 &batadv_attr_iface_status, 1003 &batadv_attr_iface_status,
1004#ifdef CONFIG_BATMAN_ADV_BATMAN_V
1005 &batadv_attr_elp_interval,
1006 &batadv_attr_throughput_override,
1007#endif
878 NULL, 1008 NULL,
879}; 1009};
880 1010
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index 612de23178e6..9abfb3e73c34 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -22,6 +22,7 @@
22#error only "main.h" can be included directly 22#error only "main.h" can be included directly
23#endif 23#endif
24 24
25#include <linux/average.h>
25#include <linux/bitops.h> 26#include <linux/bitops.h>
26#include <linux/compiler.h> 27#include <linux/compiler.h>
27#include <linux/if_ether.h> 28#include <linux/if_ether.h>
@@ -86,6 +87,36 @@ struct batadv_hard_iface_bat_iv {
86}; 87};
87 88
88/** 89/**
90 * enum batadv_v_hard_iface_flags - interface flags useful to B.A.T.M.A.N. V
91 * @BATADV_FULL_DUPLEX: tells if the connection over this link is full-duplex
92 * @BATADV_WARNING_DEFAULT: tells whether we have warned the user that no
93 * throughput data is available for this interface and that default values are
94 * assumed.
95 */
96enum batadv_v_hard_iface_flags {
97 BATADV_FULL_DUPLEX = BIT(0),
98 BATADV_WARNING_DEFAULT = BIT(1),
99};
100
101/**
102 * struct batadv_hard_iface_bat_v - per hard-interface B.A.T.M.A.N. V data
103 * @elp_interval: time interval between two ELP transmissions
104 * @elp_seqno: current ELP sequence number
105 * @elp_skb: base skb containing the ELP message to send
106 * @elp_wq: workqueue used to schedule ELP transmissions
107 * @throughput_override: throughput override to disable link auto-detection
108 * @flags: interface specific flags
109 */
110struct batadv_hard_iface_bat_v {
111 atomic_t elp_interval;
112 atomic_t elp_seqno;
113 struct sk_buff *elp_skb;
114 struct delayed_work elp_wq;
115 atomic_t throughput_override;
116 u8 flags;
117};
118
119/**
89 * struct batadv_hard_iface - network device known to batman-adv 120 * struct batadv_hard_iface - network device known to batman-adv
90 * @list: list node for batadv_hardif_list 121 * @list: list node for batadv_hardif_list
91 * @if_num: identificator of the interface 122 * @if_num: identificator of the interface
@@ -99,6 +130,7 @@ struct batadv_hard_iface_bat_iv {
99 * @soft_iface: the batman-adv interface which uses this network interface 130 * @soft_iface: the batman-adv interface which uses this network interface
100 * @rcu: struct used for freeing in an RCU-safe manner 131 * @rcu: struct used for freeing in an RCU-safe manner
101 * @bat_iv: per hard-interface B.A.T.M.A.N. IV data 132 * @bat_iv: per hard-interface B.A.T.M.A.N. IV data
133 * @bat_v: per hard-interface B.A.T.M.A.N. V data
102 * @cleanup_work: work queue callback item for hard-interface deinit 134 * @cleanup_work: work queue callback item for hard-interface deinit
103 * @debug_dir: dentry for nc subdir in batman-adv directory in debugfs 135 * @debug_dir: dentry for nc subdir in batman-adv directory in debugfs
104 * @neigh_list: list of unique single hop neighbors via this interface 136 * @neigh_list: list of unique single hop neighbors via this interface
@@ -116,6 +148,9 @@ struct batadv_hard_iface {
116 struct net_device *soft_iface; 148 struct net_device *soft_iface;
117 struct rcu_head rcu; 149 struct rcu_head rcu;
118 struct batadv_hard_iface_bat_iv bat_iv; 150 struct batadv_hard_iface_bat_iv bat_iv;
151#ifdef CONFIG_BATMAN_ADV_BATMAN_V
152 struct batadv_hard_iface_bat_v bat_v;
153#endif
119 struct work_struct cleanup_work; 154 struct work_struct cleanup_work;
120 struct dentry *debug_dir; 155 struct dentry *debug_dir;
121 struct hlist_head neigh_list; 156 struct hlist_head neigh_list;
@@ -130,6 +165,7 @@ struct batadv_hard_iface {
130 * @router: router that should be used to reach this originator 165 * @router: router that should be used to reach this originator
131 * @last_real_seqno: last and best known sequence number 166 * @last_real_seqno: last and best known sequence number
132 * @last_ttl: ttl of last received packet 167 * @last_ttl: ttl of last received packet
168 * @last_seqno_forwarded: seqno of the OGM which was forwarded last
133 * @batman_seqno_reset: time when the batman seqno window was reset 169 * @batman_seqno_reset: time when the batman seqno window was reset
134 * @refcount: number of contexts the object is used 170 * @refcount: number of contexts the object is used
135 * @rcu: struct used for freeing in an RCU-safe manner 171 * @rcu: struct used for freeing in an RCU-safe manner
@@ -140,6 +176,7 @@ struct batadv_orig_ifinfo {
140 struct batadv_neigh_node __rcu *router; /* rcu protected pointer */ 176 struct batadv_neigh_node __rcu *router; /* rcu protected pointer */
141 u32 last_real_seqno; 177 u32 last_real_seqno;
142 u8 last_ttl; 178 u8 last_ttl;
179 u32 last_seqno_forwarded;
143 unsigned long batman_seqno_reset; 180 unsigned long batman_seqno_reset;
144 struct kref refcount; 181 struct kref refcount;
145 struct rcu_head rcu; 182 struct rcu_head rcu;
@@ -346,12 +383,32 @@ struct batadv_gw_node {
346 struct rcu_head rcu; 383 struct rcu_head rcu;
347}; 384};
348 385
386DECLARE_EWMA(throughput, 1024, 8)
387
388/**
389 * struct batadv_hardif_neigh_node_bat_v - B.A.T.M.A.N. V private neighbor
390 * information
391 * @throughput: ewma link throughput towards this neighbor
392 * @elp_interval: time interval between two ELP transmissions
393 * @elp_latest_seqno: latest and best known ELP sequence number
394 * @last_unicast_tx: when the last unicast packet has been sent to this neighbor
395 * @metric_work: work queue callback item for metric update
396 */
397struct batadv_hardif_neigh_node_bat_v {
398 struct ewma_throughput throughput;
399 u32 elp_interval;
400 u32 elp_latest_seqno;
401 unsigned long last_unicast_tx;
402 struct work_struct metric_work;
403};
404
349/** 405/**
350 * struct batadv_hardif_neigh_node - unique neighbor per hard-interface 406 * struct batadv_hardif_neigh_node - unique neighbor per hard-interface
351 * @list: list node for batadv_hard_iface::neigh_list 407 * @list: list node for batadv_hard_iface::neigh_list
352 * @addr: the MAC address of the neighboring interface 408 * @addr: the MAC address of the neighboring interface
353 * @if_incoming: pointer to incoming hard-interface 409 * @if_incoming: pointer to incoming hard-interface
354 * @last_seen: when last packet via this neighbor was received 410 * @last_seen: when last packet via this neighbor was received
411 * @bat_v: B.A.T.M.A.N. V private data
355 * @refcount: number of contexts the object is used 412 * @refcount: number of contexts the object is used
356 * @rcu: struct used for freeing in a RCU-safe manner 413 * @rcu: struct used for freeing in a RCU-safe manner
357 */ 414 */
@@ -360,6 +417,9 @@ struct batadv_hardif_neigh_node {
360 u8 addr[ETH_ALEN]; 417 u8 addr[ETH_ALEN];
361 struct batadv_hard_iface *if_incoming; 418 struct batadv_hard_iface *if_incoming;
362 unsigned long last_seen; 419 unsigned long last_seen;
420#ifdef CONFIG_BATMAN_ADV_BATMAN_V
421 struct batadv_hardif_neigh_node_bat_v bat_v;
422#endif
363 struct kref refcount; 423 struct kref refcount;
364 struct rcu_head rcu; 424 struct rcu_head rcu;
365}; 425};
@@ -407,10 +467,22 @@ struct batadv_neigh_ifinfo_bat_iv {
407}; 467};
408 468
409/** 469/**
470 * struct batadv_neigh_ifinfo_bat_v - neighbor information per outgoing
471 * interface for B.A.T.M.A.N. V
472 * @throughput: last throughput metric received from originator via this neigh
473 * @last_seqno: last sequence number known for this neighbor
474 */
475struct batadv_neigh_ifinfo_bat_v {
476 u32 throughput;
477 u32 last_seqno;
478};
479
480/**
410 * struct batadv_neigh_ifinfo - neighbor information per outgoing interface 481 * struct batadv_neigh_ifinfo - neighbor information per outgoing interface
411 * @list: list node for batadv_neigh_node::ifinfo_list 482 * @list: list node for batadv_neigh_node::ifinfo_list
412 * @if_outgoing: pointer to outgoing hard-interface 483 * @if_outgoing: pointer to outgoing hard-interface
413 * @bat_iv: B.A.T.M.A.N. IV private structure 484 * @bat_iv: B.A.T.M.A.N. IV private structure
485 * @bat_v: B.A.T.M.A.N. V private data
414 * @last_ttl: last received ttl from this neigh node 486 * @last_ttl: last received ttl from this neigh node
415 * @refcount: number of contexts the object is used 487 * @refcount: number of contexts the object is used
416 * @rcu: struct used for freeing in a RCU-safe manner 488 * @rcu: struct used for freeing in a RCU-safe manner
@@ -419,6 +491,9 @@ struct batadv_neigh_ifinfo {
419 struct hlist_node list; 491 struct hlist_node list;
420 struct batadv_hard_iface *if_outgoing; 492 struct batadv_hard_iface *if_outgoing;
421 struct batadv_neigh_ifinfo_bat_iv bat_iv; 493 struct batadv_neigh_ifinfo_bat_iv bat_iv;
494#ifdef CONFIG_BATMAN_ADV_BATMAN_V
495 struct batadv_neigh_ifinfo_bat_v bat_v;
496#endif
422 u8 last_ttl; 497 u8 last_ttl;
423 struct kref refcount; 498 struct kref refcount;
424 struct rcu_head rcu; 499 struct rcu_head rcu;
@@ -751,6 +826,20 @@ struct batadv_softif_vlan {
751}; 826};
752 827
753/** 828/**
829 * struct batadv_priv_bat_v - B.A.T.M.A.N. V per soft-interface private data
830 * @ogm_buff: buffer holding the OGM packet
831 * @ogm_buff_len: length of the OGM packet buffer
832 * @ogm_seqno: OGM sequence number - used to identify each OGM
833 * @ogm_wq: workqueue used to schedule OGM transmissions
834 */
835struct batadv_priv_bat_v {
836 unsigned char *ogm_buff;
837 int ogm_buff_len;
838 atomic_t ogm_seqno;
839 struct delayed_work ogm_wq;
840};
841
842/**
754 * struct batadv_priv - per mesh interface data 843 * struct batadv_priv - per mesh interface data
755 * @mesh_state: current status of the mesh (inactive/active/deactivating) 844 * @mesh_state: current status of the mesh (inactive/active/deactivating)
756 * @soft_iface: net device which holds this struct as private data 845 * @soft_iface: net device which holds this struct as private data
@@ -804,6 +893,7 @@ struct batadv_softif_vlan {
804 * @mcast: multicast data 893 * @mcast: multicast data
805 * @network_coding: bool indicating whether network coding is enabled 894 * @network_coding: bool indicating whether network coding is enabled
806 * @nc: network coding data 895 * @nc: network coding data
896 * @bat_v: B.A.T.M.A.N. V per soft-interface private data
807 */ 897 */
808struct batadv_priv { 898struct batadv_priv {
809 atomic_t mesh_state; 899 atomic_t mesh_state;
@@ -869,6 +959,9 @@ struct batadv_priv {
869 atomic_t network_coding; 959 atomic_t network_coding;
870 struct batadv_priv_nc nc; 960 struct batadv_priv_nc nc;
871#endif /* CONFIG_BATMAN_ADV_NC */ 961#endif /* CONFIG_BATMAN_ADV_NC */
962#ifdef CONFIG_BATMAN_ADV_BATMAN_V
963 struct batadv_priv_bat_v bat_v;
964#endif
872}; 965};
873 966
874/** 967/**