aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2016-03-01 17:48:00 -0500
committerDavid S. Miller <davem@davemloft.net>2016-03-01 17:48:00 -0500
commit7da5ee09f1fcd9c4fa95be96d3981b117c59a26b (patch)
tree757a68acabf408cebb2542af0cae064f2a5a8bc6
parentc145aeb3ff899f38bd28ccbc40dbb647dd1b1fd3 (diff)
parent8b823170550e5dcc80512143088c9f9e24598f9a (diff)
Merge tag 'batman-adv-for-davem' of git://git.open-mesh.org/linux-merge
Antonio Quartulli says: ==================== batman-adv 20160229 this is our (hopefully) latest batch of patches intended for net-next. With this patchset we finally introduce B.A.T.M.A.N. V: the latest version of our routing protocol. Technical documentation describing the protocol in more detail can be found in our wiki[1][2][3][4]. For what concerns this pull request, you can find the high level description right below. [1] https://www.open-mesh.org/projects/batman-adv/wiki/BATMAN_V [2] https://www.open-mesh.org/projects/batman-adv/wiki/OGMv2 [3] https://www.open-mesh.org/projects/batman-adv/wiki/ELP [4] https://www.open-mesh.org/projects/batman-adv/wiki/BATMAN_V_Tests ... With this patchset we finally introduce our new routing protocol: B.A.T.M.A.N. V. Its implementation started quite some years ago, but due to the big changes being introduced it took a while to be discussed, designed, worked, re-worked, tested and debugged (well, we're never done with the latest). The entire operation has basically been a team work involving all the core contributors together with other people interested in the project. The new protocol is divided into two main subcomponents, called respectively ELP and OGMv2. The former is in charge of dealing with the neighbour discovery and link quality estimation, while the latter implements the algorithm that spreads the metrics around the network and computes optimal paths. The biggest change introduced with B.A.T.M.A.N. V is the new metric: the protocol won't rely on packet loss anymore, but it will use the estimated throughput extracted directly from the wifi driver (when available) by querying cfg80211. Batman-adv will also send some unicast probing packets when an interface is not used for payload traffic to make sure that such values are current. The new protocol can be compiled-in or not like other features we have and when selected will pull in CFG80211 as dependency for the reason described above. Thanks to the big work brought up in the past by Marek Lindner, batman-adv can easily deal several protocol implementations, therefore compiling in this new version does not exclude the older. This means that the user is offered the option to choose the protocol when creating the mesh interface (default is the old one to keep backward compatibility). Along with the protocol there are some sysfs knobs that are introduced to fine tune some of its behaviours, but users are recommended to keep the default values unless they know what they are doing. The last patch is about advertising our own patchwork platform (thanks to Sven Eckelmann for having set that up!) in the MAINTAINERS file. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
-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/**