diff options
-rw-r--r-- | Documentation/ABI/testing/sysfs-class-net-batman-adv | 17 | ||||
-rw-r--r-- | MAINTAINERS | 1 | ||||
-rw-r--r-- | net/batman-adv/Kconfig | 14 | ||||
-rw-r--r-- | net/batman-adv/Makefile | 3 | ||||
-rw-r--r-- | net/batman-adv/bat_algo.h | 28 | ||||
-rw-r--r-- | net/batman-adv/bat_iv_ogm.c | 2 | ||||
-rw-r--r-- | net/batman-adv/bat_v.c | 347 | ||||
-rw-r--r-- | net/batman-adv/bat_v_elp.c | 515 | ||||
-rw-r--r-- | net/batman-adv/bat_v_elp.h | 33 | ||||
-rw-r--r-- | net/batman-adv/bat_v_ogm.c | 833 | ||||
-rw-r--r-- | net/batman-adv/bat_v_ogm.h | 36 | ||||
-rw-r--r-- | net/batman-adv/distributed-arp-table.c | 4 | ||||
-rw-r--r-- | net/batman-adv/fragmentation.c | 8 | ||||
-rw-r--r-- | net/batman-adv/gateway_common.c | 4 | ||||
-rw-r--r-- | net/batman-adv/gateway_common.h | 2 | ||||
-rw-r--r-- | net/batman-adv/icmp_socket.c | 2 | ||||
-rw-r--r-- | net/batman-adv/main.c | 7 | ||||
-rw-r--r-- | net/batman-adv/main.h | 12 | ||||
-rw-r--r-- | net/batman-adv/network-coding.c | 22 | ||||
-rw-r--r-- | net/batman-adv/packet.h | 49 | ||||
-rw-r--r-- | net/batman-adv/send.c | 55 | ||||
-rw-r--r-- | net/batman-adv/send.h | 10 | ||||
-rw-r--r-- | net/batman-adv/sysfs.c | 130 | ||||
-rw-r--r-- | net/batman-adv/types.h | 93 |
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 | ||
2 | What: /sys/class/net/<iface>/batman-adv/throughput_override | ||
3 | Date: Feb 2014 | ||
4 | Contact: Antonio Quartulli <antonio@meshcoding.com> | ||
5 | description: | ||
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 | |||
11 | What: /sys/class/net/<iface>/batman-adv/elp_interval | ||
12 | Date: Feb 2014 | ||
13 | Contact: Linus Lüssing <linus.luessing@web.de> | ||
14 | Description: | ||
15 | Defines the interval in milliseconds in which batman | ||
16 | sends its probing packets for link quality measurements. | ||
17 | |||
2 | What: /sys/class/net/<iface>/batman-adv/iface_status | 18 | What: /sys/class/net/<iface>/batman-adv/iface_status |
3 | Date: May 2010 | 19 | Date: May 2010 |
4 | Contact: Marek Lindner <mareklindner@neomailbox.ch> | 20 | Contact: 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> | |||
2152 | M: Antonio Quartulli <a@unstable.cc> | 2152 | M: Antonio Quartulli <a@unstable.cc> |
2153 | L: b.a.t.m.a.n@lists.open-mesh.org | 2153 | L: b.a.t.m.a.n@lists.open-mesh.org |
2154 | W: https://www.open-mesh.org/ | 2154 | W: https://www.open-mesh.org/ |
2155 | Q: https://patchwork.open-mesh.org/project/batman/list/ | ||
2155 | S: Maintained | 2156 | S: Maintained |
2156 | F: net/batman-adv/ | 2157 | F: 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 | ||
18 | config 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 | |||
18 | config BATMAN_ADV_BLA | 32 | config 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 | ||
19 | obj-$(CONFIG_BATMAN_ADV) += batman-adv.o | 19 | obj-$(CONFIG_BATMAN_ADV) += batman-adv.o |
20 | batman-adv-y += bat_iv_ogm.o | 20 | batman-adv-y += bat_iv_ogm.o |
21 | batman-adv-$(CONFIG_BATMAN_ADV_BATMAN_V) += bat_v.o | ||
22 | batman-adv-$(CONFIG_BATMAN_ADV_BATMAN_V) += bat_v_elp.o | ||
23 | batman-adv-$(CONFIG_BATMAN_ADV_BATMAN_V) += bat_v_ogm.o | ||
21 | batman-adv-y += bitarray.o | 24 | batman-adv-y += bitarray.o |
22 | batman-adv-$(CONFIG_BATMAN_ADV_BLA) += bridge_loop_avoidance.o | 25 | batman-adv-$(CONFIG_BATMAN_ADV_BLA) += bridge_loop_avoidance.o |
23 | batman-adv-$(CONFIG_DEBUG_FS) += debugfs.o | 26 | batman-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 | ||
21 | struct batadv_priv; | ||
22 | |||
21 | int batadv_iv_init(void); | 23 | int batadv_iv_init(void); |
22 | 24 | ||
25 | #ifdef CONFIG_BATMAN_ADV_BATMAN_V | ||
26 | |||
27 | int batadv_v_init(void); | ||
28 | int batadv_v_mesh_init(struct batadv_priv *bat_priv); | ||
29 | void batadv_v_mesh_free(struct batadv_priv *bat_priv); | ||
30 | |||
31 | #else | ||
32 | |||
33 | static inline int batadv_v_init(void) | ||
34 | { | ||
35 | return 0; | ||
36 | } | ||
37 | |||
38 | static inline int batadv_v_mesh_init(struct batadv_priv *bat_priv) | ||
39 | { | ||
40 | return 0; | ||
41 | } | ||
42 | |||
43 | static 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 | |||
39 | static 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 | |||
59 | static void batadv_v_iface_disable(struct batadv_hard_iface *hard_iface) | ||
60 | { | ||
61 | batadv_v_elp_iface_disable(hard_iface); | ||
62 | } | ||
63 | |||
64 | static void batadv_v_iface_update_mac(struct batadv_hard_iface *hard_iface) | ||
65 | { | ||
66 | } | ||
67 | |||
68 | static 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 | |||
74 | static void | ||
75 | batadv_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 | |||
82 | static void batadv_v_ogm_schedule(struct batadv_hard_iface *hard_iface) | ||
83 | { | ||
84 | } | ||
85 | |||
86 | static 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 | */ | ||
98 | static void | ||
99 | batadv_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 | */ | ||
125 | static void | ||
126 | batadv_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 | */ | ||
146 | static 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 | */ | ||
180 | static 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 | |||
230 | next: | ||
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 | |||
242 | static 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 | |||
258 | static 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 | |||
275 | static 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 | */ | ||
297 | int 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 | */ | ||
306 | void 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 | */ | ||
319 | int __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 | |||
340 | ogm_unregister: | ||
341 | batadv_recv_handler_unregister(BATADV_OGM2); | ||
342 | |||
343 | elp_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 | */ | ||
55 | static 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 | */ | ||
73 | static 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 | |||
129 | default_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 | */ | ||
148 | void 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 | */ | ||
178 | static bool | ||
179 | batadv_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 | */ | ||
236 | static 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 | |||
311 | restart_timer: | ||
312 | batadv_v_elp_start_timer(hard_iface); | ||
313 | out: | ||
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 | */ | ||
323 | int 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 | |||
363 | out: | ||
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 | */ | ||
371 | void 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 | */ | ||
384 | void 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 | */ | ||
417 | static 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 | |||
455 | hardif_free: | ||
456 | if (hardif_neigh) | ||
457 | batadv_hardif_neigh_put(hardif_neigh); | ||
458 | neigh_free: | ||
459 | if (neigh) | ||
460 | batadv_neigh_node_put(neigh); | ||
461 | orig_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 | */ | ||
474 | int 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 | |||
510 | out: | ||
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 | |||
23 | struct sk_buff; | ||
24 | struct work_struct; | ||
25 | |||
26 | int batadv_v_elp_iface_enable(struct batadv_hard_iface *hard_iface); | ||
27 | void batadv_v_elp_iface_disable(struct batadv_hard_iface *hard_iface); | ||
28 | void batadv_v_elp_primary_iface_set(struct batadv_hard_iface *primary_iface); | ||
29 | int batadv_v_elp_packet_recv(struct sk_buff *skb, | ||
30 | struct batadv_hard_iface *if_incoming); | ||
31 | void 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 | */ | ||
58 | struct 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 | */ | ||
91 | static 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 | */ | ||
111 | static 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 | */ | ||
130 | static 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 | |||
197 | reschedule: | ||
198 | batadv_v_ogm_start_timer(bat_priv); | ||
199 | out: | ||
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 | */ | ||
211 | int 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 | */ | ||
224 | void 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 | */ | ||
245 | static void | ||
246 | batadv_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 | |||
294 | out: | ||
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 | */ | ||
324 | static 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 | */ | ||
360 | static 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 | */ | ||
416 | static 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; | ||
478 | out: | ||
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 | */ | ||
497 | static 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 | |||
562 | out: | ||
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 | */ | ||
585 | static void | ||
586 | batadv_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 | */ | ||
625 | static 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 | */ | ||
643 | static 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(); | ||
721 | out: | ||
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 | */ | ||
738 | int 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 | */ | ||
795 | int 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 | */ | ||
826 | void 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 | |||
23 | struct batadv_hard_iface; | ||
24 | struct batadv_priv; | ||
25 | struct sk_buff; | ||
26 | |||
27 | int batadv_v_ogm_init(struct batadv_priv *bat_priv); | ||
28 | void batadv_v_ogm_free(struct batadv_priv *bat_priv); | ||
29 | int batadv_v_ogm_iface_enable(struct batadv_hard_iface *hard_iface); | ||
30 | struct batadv_orig_node *batadv_v_ogm_orig_get(struct batadv_priv *bat_priv, | ||
31 | const u8 *addr); | ||
32 | void batadv_v_ogm_primary_iface_set(struct batadv_hard_iface *primary_iface); | ||
33 | int 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 | */ |
43 | static bool batadv_parse_throughput(struct net_device *net_dev, char *buff, | 43 | bool 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, | |||
49 | void batadv_gw_tvlv_container_update(struct batadv_priv *bat_priv); | 49 | void batadv_gw_tvlv_container_update(struct batadv_priv *bat_priv); |
50 | void batadv_gw_init(struct batadv_priv *bat_priv); | 50 | void batadv_gw_init(struct batadv_priv *bat_priv); |
51 | void batadv_gw_free(struct batadv_priv *bat_priv); | 51 | void batadv_gw_free(struct batadv_priv *bat_priv); |
52 | bool 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 | ||
284 | dst_unreach: | 284 | dst_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 | */ |
576 | static void batadv_nc_send_packet(struct batadv_nc_packet *nc_packet) | 576 | static 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; |
1229 | out: | 1227 | out: |
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 | */ | ||
252 | struct 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 | */ | ||
276 | struct 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 | ||
50 | static void batadv_send_outstanding_bcast_packet(struct work_struct *work); | 50 | static 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 | */ |
55 | int batadv_send_skb_packet(struct sk_buff *skb, | 67 | int 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 | ||
117 | int 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 | |||
123 | int 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 @@ | |||
28 | struct sk_buff; | 28 | struct sk_buff; |
29 | struct work_struct; | 29 | struct work_struct; |
30 | 30 | ||
31 | int batadv_send_skb_packet(struct sk_buff *skb, | ||
32 | struct batadv_hard_iface *hard_iface, | ||
33 | const u8 *dst_addr); | ||
34 | int batadv_send_skb_to_orig(struct sk_buff *skb, | 31 | int 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); |
34 | int batadv_send_skb_packet(struct sk_buff *skb, | ||
35 | struct batadv_hard_iface *hard_iface, | ||
36 | const u8 *dst_addr); | ||
37 | int batadv_send_broadcast_skb(struct sk_buff *skb, | ||
38 | struct batadv_hard_iface *hard_iface); | ||
39 | int batadv_send_unicast_skb(struct sk_buff *skb, | ||
40 | struct batadv_neigh_node *neigh_node); | ||
37 | void batadv_schedule_bat_ogm(struct batadv_hard_iface *hard_iface); | 41 | void batadv_schedule_bat_ogm(struct batadv_hard_iface *hard_iface); |
38 | int batadv_add_bcast_packet_to_list(struct batadv_priv *bat_priv, | 42 | int 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) \ | ||
246 | ssize_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) \ | ||
267 | ssize_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 | |||
245 | static int batadv_store_bool_attr(char *buff, size_t count, | 294 | static 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 | */ | ||
932 | static 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 | |||
965 | out: | ||
966 | batadv_hardif_put(hard_iface); | ||
967 | return count; | ||
968 | } | ||
969 | |||
970 | static 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 | |||
871 | static BATADV_ATTR(mesh_iface, S_IRUGO | S_IWUSR, batadv_show_mesh_iface, | 990 | static BATADV_ATTR(mesh_iface, S_IRUGO | S_IWUSR, batadv_show_mesh_iface, |
872 | batadv_store_mesh_iface); | 991 | batadv_store_mesh_iface); |
873 | static BATADV_ATTR(iface_status, S_IRUGO, batadv_show_iface_status, NULL); | 992 | static BATADV_ATTR(iface_status, S_IRUGO, batadv_show_iface_status, NULL); |
993 | #ifdef CONFIG_BATMAN_ADV_BATMAN_V | ||
994 | BATADV_ATTR_HIF_UINT(elp_interval, bat_v.elp_interval, S_IRUGO | S_IWUSR, | ||
995 | 2 * BATADV_JITTER, INT_MAX, NULL); | ||
996 | static BATADV_ATTR(throughput_override, S_IRUGO | S_IWUSR, | ||
997 | batadv_show_throughput_override, | ||
998 | batadv_store_throughput_override); | ||
999 | #endif | ||
874 | 1000 | ||
875 | static struct batadv_attribute *batadv_batman_attrs[] = { | 1001 | static 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 | */ | ||
96 | enum 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 | */ | ||
110 | struct 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 | ||
386 | DECLARE_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 | */ | ||
397 | struct 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 | */ | ||
475 | struct 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 | */ | ||
835 | struct 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 | */ |
808 | struct batadv_priv { | 898 | struct 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 | /** |