Commit 3a24a63e74af1bffc7aeb5d83adcd63b37e38425
Committed by
Simon Wunderlich
1 parent
c149ca72e5
batman-adv: move GW mode and selection class to private data structure
To reduce the field pollution in our main batadv_priv data structure we've already created some substructures so that we could group fields in a convenient manner. However gw_mode and gw_sel_class are still part of the main object. More both fields to the GW private substructure. Signed-off-by: Antonio Quartulli <a@unstable.cc> Signed-off-by: Marek Lindner <mareklindner@neomailbox.ch> Signed-off-by: Sven Eckelmann <sven@narfation.org> Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>
Showing 5 changed files with 21 additions and 21 deletions Inline Diff
net/batman-adv/gateway_client.c
1 | /* Copyright (C) 2009-2016 B.A.T.M.A.N. contributors: | 1 | /* Copyright (C) 2009-2016 B.A.T.M.A.N. contributors: |
2 | * | 2 | * |
3 | * Marek Lindner | 3 | * Marek Lindner |
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 |
7 | * License as published by the Free Software Foundation. | 7 | * License as published by the Free Software Foundation. |
8 | * | 8 | * |
9 | * This program is distributed in the hope that it will be useful, but | 9 | * This program is distributed in the hope that it will be useful, but |
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of | 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 | * General Public License for more details. | 12 | * General Public License for more details. |
13 | * | 13 | * |
14 | * You should have received a copy of the GNU General Public License | 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/>. | 15 | * along with this program; if not, see <http://www.gnu.org/licenses/>. |
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include "gateway_client.h" | 18 | #include "gateway_client.h" |
19 | #include "main.h" | 19 | #include "main.h" |
20 | 20 | ||
21 | #include <linux/atomic.h> | 21 | #include <linux/atomic.h> |
22 | #include <linux/byteorder/generic.h> | 22 | #include <linux/byteorder/generic.h> |
23 | #include <linux/etherdevice.h> | 23 | #include <linux/etherdevice.h> |
24 | #include <linux/fs.h> | 24 | #include <linux/fs.h> |
25 | #include <linux/if_ether.h> | 25 | #include <linux/if_ether.h> |
26 | #include <linux/if_vlan.h> | 26 | #include <linux/if_vlan.h> |
27 | #include <linux/in.h> | 27 | #include <linux/in.h> |
28 | #include <linux/ip.h> | 28 | #include <linux/ip.h> |
29 | #include <linux/ipv6.h> | 29 | #include <linux/ipv6.h> |
30 | #include <linux/kernel.h> | 30 | #include <linux/kernel.h> |
31 | #include <linux/kref.h> | 31 | #include <linux/kref.h> |
32 | #include <linux/list.h> | 32 | #include <linux/list.h> |
33 | #include <linux/netdevice.h> | 33 | #include <linux/netdevice.h> |
34 | #include <linux/rculist.h> | 34 | #include <linux/rculist.h> |
35 | #include <linux/rcupdate.h> | 35 | #include <linux/rcupdate.h> |
36 | #include <linux/seq_file.h> | 36 | #include <linux/seq_file.h> |
37 | #include <linux/skbuff.h> | 37 | #include <linux/skbuff.h> |
38 | #include <linux/slab.h> | 38 | #include <linux/slab.h> |
39 | #include <linux/spinlock.h> | 39 | #include <linux/spinlock.h> |
40 | #include <linux/stddef.h> | 40 | #include <linux/stddef.h> |
41 | #include <linux/udp.h> | 41 | #include <linux/udp.h> |
42 | 42 | ||
43 | #include "gateway_common.h" | 43 | #include "gateway_common.h" |
44 | #include "hard-interface.h" | 44 | #include "hard-interface.h" |
45 | #include "originator.h" | 45 | #include "originator.h" |
46 | #include "packet.h" | 46 | #include "packet.h" |
47 | #include "routing.h" | 47 | #include "routing.h" |
48 | #include "sysfs.h" | 48 | #include "sysfs.h" |
49 | #include "translation-table.h" | 49 | #include "translation-table.h" |
50 | 50 | ||
51 | /* These are the offsets of the "hw type" and "hw address length" in the dhcp | 51 | /* These are the offsets of the "hw type" and "hw address length" in the dhcp |
52 | * packet starting at the beginning of the dhcp header | 52 | * packet starting at the beginning of the dhcp header |
53 | */ | 53 | */ |
54 | #define BATADV_DHCP_HTYPE_OFFSET 1 | 54 | #define BATADV_DHCP_HTYPE_OFFSET 1 |
55 | #define BATADV_DHCP_HLEN_OFFSET 2 | 55 | #define BATADV_DHCP_HLEN_OFFSET 2 |
56 | /* Value of htype representing Ethernet */ | 56 | /* Value of htype representing Ethernet */ |
57 | #define BATADV_DHCP_HTYPE_ETHERNET 0x01 | 57 | #define BATADV_DHCP_HTYPE_ETHERNET 0x01 |
58 | /* This is the offset of the "chaddr" field in the dhcp packet starting at the | 58 | /* This is the offset of the "chaddr" field in the dhcp packet starting at the |
59 | * beginning of the dhcp header | 59 | * beginning of the dhcp header |
60 | */ | 60 | */ |
61 | #define BATADV_DHCP_CHADDR_OFFSET 28 | 61 | #define BATADV_DHCP_CHADDR_OFFSET 28 |
62 | 62 | ||
63 | /** | 63 | /** |
64 | * batadv_gw_node_release - release gw_node from lists and queue for free after | 64 | * batadv_gw_node_release - release gw_node from lists and queue for free after |
65 | * rcu grace period | 65 | * rcu grace period |
66 | * @ref: kref pointer of the gw_node | 66 | * @ref: kref pointer of the gw_node |
67 | */ | 67 | */ |
68 | static void batadv_gw_node_release(struct kref *ref) | 68 | static void batadv_gw_node_release(struct kref *ref) |
69 | { | 69 | { |
70 | struct batadv_gw_node *gw_node; | 70 | struct batadv_gw_node *gw_node; |
71 | 71 | ||
72 | gw_node = container_of(ref, struct batadv_gw_node, refcount); | 72 | gw_node = container_of(ref, struct batadv_gw_node, refcount); |
73 | 73 | ||
74 | batadv_orig_node_put(gw_node->orig_node); | 74 | batadv_orig_node_put(gw_node->orig_node); |
75 | kfree_rcu(gw_node, rcu); | 75 | kfree_rcu(gw_node, rcu); |
76 | } | 76 | } |
77 | 77 | ||
78 | /** | 78 | /** |
79 | * batadv_gw_node_put - decrement the gw_node refcounter and possibly release it | 79 | * batadv_gw_node_put - decrement the gw_node refcounter and possibly release it |
80 | * @gw_node: gateway node to free | 80 | * @gw_node: gateway node to free |
81 | */ | 81 | */ |
82 | static void batadv_gw_node_put(struct batadv_gw_node *gw_node) | 82 | static void batadv_gw_node_put(struct batadv_gw_node *gw_node) |
83 | { | 83 | { |
84 | kref_put(&gw_node->refcount, batadv_gw_node_release); | 84 | kref_put(&gw_node->refcount, batadv_gw_node_release); |
85 | } | 85 | } |
86 | 86 | ||
87 | static struct batadv_gw_node * | 87 | static struct batadv_gw_node * |
88 | batadv_gw_get_selected_gw_node(struct batadv_priv *bat_priv) | 88 | batadv_gw_get_selected_gw_node(struct batadv_priv *bat_priv) |
89 | { | 89 | { |
90 | struct batadv_gw_node *gw_node; | 90 | struct batadv_gw_node *gw_node; |
91 | 91 | ||
92 | rcu_read_lock(); | 92 | rcu_read_lock(); |
93 | gw_node = rcu_dereference(bat_priv->gw.curr_gw); | 93 | gw_node = rcu_dereference(bat_priv->gw.curr_gw); |
94 | if (!gw_node) | 94 | if (!gw_node) |
95 | goto out; | 95 | goto out; |
96 | 96 | ||
97 | if (!kref_get_unless_zero(&gw_node->refcount)) | 97 | if (!kref_get_unless_zero(&gw_node->refcount)) |
98 | gw_node = NULL; | 98 | gw_node = NULL; |
99 | 99 | ||
100 | out: | 100 | out: |
101 | rcu_read_unlock(); | 101 | rcu_read_unlock(); |
102 | return gw_node; | 102 | return gw_node; |
103 | } | 103 | } |
104 | 104 | ||
105 | struct batadv_orig_node * | 105 | struct batadv_orig_node * |
106 | batadv_gw_get_selected_orig(struct batadv_priv *bat_priv) | 106 | batadv_gw_get_selected_orig(struct batadv_priv *bat_priv) |
107 | { | 107 | { |
108 | struct batadv_gw_node *gw_node; | 108 | struct batadv_gw_node *gw_node; |
109 | struct batadv_orig_node *orig_node = NULL; | 109 | struct batadv_orig_node *orig_node = NULL; |
110 | 110 | ||
111 | gw_node = batadv_gw_get_selected_gw_node(bat_priv); | 111 | gw_node = batadv_gw_get_selected_gw_node(bat_priv); |
112 | if (!gw_node) | 112 | if (!gw_node) |
113 | goto out; | 113 | goto out; |
114 | 114 | ||
115 | rcu_read_lock(); | 115 | rcu_read_lock(); |
116 | orig_node = gw_node->orig_node; | 116 | orig_node = gw_node->orig_node; |
117 | if (!orig_node) | 117 | if (!orig_node) |
118 | goto unlock; | 118 | goto unlock; |
119 | 119 | ||
120 | if (!kref_get_unless_zero(&orig_node->refcount)) | 120 | if (!kref_get_unless_zero(&orig_node->refcount)) |
121 | orig_node = NULL; | 121 | orig_node = NULL; |
122 | 122 | ||
123 | unlock: | 123 | unlock: |
124 | rcu_read_unlock(); | 124 | rcu_read_unlock(); |
125 | out: | 125 | out: |
126 | if (gw_node) | 126 | if (gw_node) |
127 | batadv_gw_node_put(gw_node); | 127 | batadv_gw_node_put(gw_node); |
128 | return orig_node; | 128 | return orig_node; |
129 | } | 129 | } |
130 | 130 | ||
131 | static void batadv_gw_select(struct batadv_priv *bat_priv, | 131 | static void batadv_gw_select(struct batadv_priv *bat_priv, |
132 | struct batadv_gw_node *new_gw_node) | 132 | struct batadv_gw_node *new_gw_node) |
133 | { | 133 | { |
134 | struct batadv_gw_node *curr_gw_node; | 134 | struct batadv_gw_node *curr_gw_node; |
135 | 135 | ||
136 | spin_lock_bh(&bat_priv->gw.list_lock); | 136 | spin_lock_bh(&bat_priv->gw.list_lock); |
137 | 137 | ||
138 | if (new_gw_node) | 138 | if (new_gw_node) |
139 | kref_get(&new_gw_node->refcount); | 139 | kref_get(&new_gw_node->refcount); |
140 | 140 | ||
141 | curr_gw_node = rcu_dereference_protected(bat_priv->gw.curr_gw, 1); | 141 | curr_gw_node = rcu_dereference_protected(bat_priv->gw.curr_gw, 1); |
142 | rcu_assign_pointer(bat_priv->gw.curr_gw, new_gw_node); | 142 | rcu_assign_pointer(bat_priv->gw.curr_gw, new_gw_node); |
143 | 143 | ||
144 | if (curr_gw_node) | 144 | if (curr_gw_node) |
145 | batadv_gw_node_put(curr_gw_node); | 145 | batadv_gw_node_put(curr_gw_node); |
146 | 146 | ||
147 | spin_unlock_bh(&bat_priv->gw.list_lock); | 147 | spin_unlock_bh(&bat_priv->gw.list_lock); |
148 | } | 148 | } |
149 | 149 | ||
150 | /** | 150 | /** |
151 | * batadv_gw_reselect - force a gateway reselection | 151 | * batadv_gw_reselect - force a gateway reselection |
152 | * @bat_priv: the bat priv with all the soft interface information | 152 | * @bat_priv: the bat priv with all the soft interface information |
153 | * | 153 | * |
154 | * Set a flag to remind the GW component to perform a new gateway reselection. | 154 | * Set a flag to remind the GW component to perform a new gateway reselection. |
155 | * However this function does not ensure that the current gateway is going to be | 155 | * However this function does not ensure that the current gateway is going to be |
156 | * deselected. The reselection mechanism may elect the same gateway once again. | 156 | * deselected. The reselection mechanism may elect the same gateway once again. |
157 | * | 157 | * |
158 | * This means that invoking batadv_gw_reselect() does not guarantee a gateway | 158 | * This means that invoking batadv_gw_reselect() does not guarantee a gateway |
159 | * change and therefore a uevent is not necessarily expected. | 159 | * change and therefore a uevent is not necessarily expected. |
160 | */ | 160 | */ |
161 | void batadv_gw_reselect(struct batadv_priv *bat_priv) | 161 | void batadv_gw_reselect(struct batadv_priv *bat_priv) |
162 | { | 162 | { |
163 | atomic_set(&bat_priv->gw.reselect, 1); | 163 | atomic_set(&bat_priv->gw.reselect, 1); |
164 | } | 164 | } |
165 | 165 | ||
166 | static struct batadv_gw_node * | 166 | static struct batadv_gw_node * |
167 | batadv_gw_get_best_gw_node(struct batadv_priv *bat_priv) | 167 | batadv_gw_get_best_gw_node(struct batadv_priv *bat_priv) |
168 | { | 168 | { |
169 | struct batadv_neigh_node *router; | 169 | struct batadv_neigh_node *router; |
170 | struct batadv_neigh_ifinfo *router_ifinfo; | 170 | struct batadv_neigh_ifinfo *router_ifinfo; |
171 | struct batadv_gw_node *gw_node, *curr_gw = NULL; | 171 | struct batadv_gw_node *gw_node, *curr_gw = NULL; |
172 | u64 max_gw_factor = 0; | 172 | u64 max_gw_factor = 0; |
173 | u64 tmp_gw_factor = 0; | 173 | u64 tmp_gw_factor = 0; |
174 | u8 max_tq = 0; | 174 | u8 max_tq = 0; |
175 | u8 tq_avg; | 175 | u8 tq_avg; |
176 | struct batadv_orig_node *orig_node; | 176 | struct batadv_orig_node *orig_node; |
177 | 177 | ||
178 | rcu_read_lock(); | 178 | rcu_read_lock(); |
179 | hlist_for_each_entry_rcu(gw_node, &bat_priv->gw.list, list) { | 179 | hlist_for_each_entry_rcu(gw_node, &bat_priv->gw.list, list) { |
180 | orig_node = gw_node->orig_node; | 180 | orig_node = gw_node->orig_node; |
181 | router = batadv_orig_router_get(orig_node, BATADV_IF_DEFAULT); | 181 | router = batadv_orig_router_get(orig_node, BATADV_IF_DEFAULT); |
182 | if (!router) | 182 | if (!router) |
183 | continue; | 183 | continue; |
184 | 184 | ||
185 | router_ifinfo = batadv_neigh_ifinfo_get(router, | 185 | router_ifinfo = batadv_neigh_ifinfo_get(router, |
186 | BATADV_IF_DEFAULT); | 186 | BATADV_IF_DEFAULT); |
187 | if (!router_ifinfo) | 187 | if (!router_ifinfo) |
188 | goto next; | 188 | goto next; |
189 | 189 | ||
190 | if (!kref_get_unless_zero(&gw_node->refcount)) | 190 | if (!kref_get_unless_zero(&gw_node->refcount)) |
191 | goto next; | 191 | goto next; |
192 | 192 | ||
193 | tq_avg = router_ifinfo->bat_iv.tq_avg; | 193 | tq_avg = router_ifinfo->bat_iv.tq_avg; |
194 | 194 | ||
195 | switch (atomic_read(&bat_priv->gw_sel_class)) { | 195 | switch (atomic_read(&bat_priv->gw.sel_class)) { |
196 | case 1: /* fast connection */ | 196 | case 1: /* fast connection */ |
197 | tmp_gw_factor = tq_avg * tq_avg; | 197 | tmp_gw_factor = tq_avg * tq_avg; |
198 | tmp_gw_factor *= gw_node->bandwidth_down; | 198 | tmp_gw_factor *= gw_node->bandwidth_down; |
199 | tmp_gw_factor *= 100 * 100; | 199 | tmp_gw_factor *= 100 * 100; |
200 | tmp_gw_factor >>= 18; | 200 | tmp_gw_factor >>= 18; |
201 | 201 | ||
202 | if ((tmp_gw_factor > max_gw_factor) || | 202 | if ((tmp_gw_factor > max_gw_factor) || |
203 | ((tmp_gw_factor == max_gw_factor) && | 203 | ((tmp_gw_factor == max_gw_factor) && |
204 | (tq_avg > max_tq))) { | 204 | (tq_avg > max_tq))) { |
205 | if (curr_gw) | 205 | if (curr_gw) |
206 | batadv_gw_node_put(curr_gw); | 206 | batadv_gw_node_put(curr_gw); |
207 | curr_gw = gw_node; | 207 | curr_gw = gw_node; |
208 | kref_get(&curr_gw->refcount); | 208 | kref_get(&curr_gw->refcount); |
209 | } | 209 | } |
210 | break; | 210 | break; |
211 | 211 | ||
212 | default: /* 2: stable connection (use best statistic) | 212 | default: /* 2: stable connection (use best statistic) |
213 | * 3: fast-switch (use best statistic but change as | 213 | * 3: fast-switch (use best statistic but change as |
214 | * soon as a better gateway appears) | 214 | * soon as a better gateway appears) |
215 | * XX: late-switch (use best statistic but change as | 215 | * XX: late-switch (use best statistic but change as |
216 | * soon as a better gateway appears which has | 216 | * soon as a better gateway appears which has |
217 | * $routing_class more tq points) | 217 | * $routing_class more tq points) |
218 | */ | 218 | */ |
219 | if (tq_avg > max_tq) { | 219 | if (tq_avg > max_tq) { |
220 | if (curr_gw) | 220 | if (curr_gw) |
221 | batadv_gw_node_put(curr_gw); | 221 | batadv_gw_node_put(curr_gw); |
222 | curr_gw = gw_node; | 222 | curr_gw = gw_node; |
223 | kref_get(&curr_gw->refcount); | 223 | kref_get(&curr_gw->refcount); |
224 | } | 224 | } |
225 | break; | 225 | break; |
226 | } | 226 | } |
227 | 227 | ||
228 | if (tq_avg > max_tq) | 228 | if (tq_avg > max_tq) |
229 | max_tq = tq_avg; | 229 | max_tq = tq_avg; |
230 | 230 | ||
231 | if (tmp_gw_factor > max_gw_factor) | 231 | if (tmp_gw_factor > max_gw_factor) |
232 | max_gw_factor = tmp_gw_factor; | 232 | max_gw_factor = tmp_gw_factor; |
233 | 233 | ||
234 | batadv_gw_node_put(gw_node); | 234 | batadv_gw_node_put(gw_node); |
235 | 235 | ||
236 | next: | 236 | next: |
237 | batadv_neigh_node_put(router); | 237 | batadv_neigh_node_put(router); |
238 | if (router_ifinfo) | 238 | if (router_ifinfo) |
239 | batadv_neigh_ifinfo_put(router_ifinfo); | 239 | batadv_neigh_ifinfo_put(router_ifinfo); |
240 | } | 240 | } |
241 | rcu_read_unlock(); | 241 | rcu_read_unlock(); |
242 | 242 | ||
243 | return curr_gw; | 243 | return curr_gw; |
244 | } | 244 | } |
245 | 245 | ||
246 | /** | 246 | /** |
247 | * batadv_gw_check_client_stop - check if client mode has been switched off | 247 | * batadv_gw_check_client_stop - check if client mode has been switched off |
248 | * @bat_priv: the bat priv with all the soft interface information | 248 | * @bat_priv: the bat priv with all the soft interface information |
249 | * | 249 | * |
250 | * This function assumes the caller has checked that the gw state *is actually | 250 | * This function assumes the caller has checked that the gw state *is actually |
251 | * changing*. This function is not supposed to be called when there is no state | 251 | * changing*. This function is not supposed to be called when there is no state |
252 | * change. | 252 | * change. |
253 | */ | 253 | */ |
254 | void batadv_gw_check_client_stop(struct batadv_priv *bat_priv) | 254 | void batadv_gw_check_client_stop(struct batadv_priv *bat_priv) |
255 | { | 255 | { |
256 | struct batadv_gw_node *curr_gw; | 256 | struct batadv_gw_node *curr_gw; |
257 | 257 | ||
258 | if (atomic_read(&bat_priv->gw_mode) != BATADV_GW_MODE_CLIENT) | 258 | if (atomic_read(&bat_priv->gw.mode) != BATADV_GW_MODE_CLIENT) |
259 | return; | 259 | return; |
260 | 260 | ||
261 | curr_gw = batadv_gw_get_selected_gw_node(bat_priv); | 261 | curr_gw = batadv_gw_get_selected_gw_node(bat_priv); |
262 | if (!curr_gw) | 262 | if (!curr_gw) |
263 | return; | 263 | return; |
264 | 264 | ||
265 | /* deselect the current gateway so that next time that client mode is | 265 | /* deselect the current gateway so that next time that client mode is |
266 | * enabled a proper GW_ADD event can be sent | 266 | * enabled a proper GW_ADD event can be sent |
267 | */ | 267 | */ |
268 | batadv_gw_select(bat_priv, NULL); | 268 | batadv_gw_select(bat_priv, NULL); |
269 | 269 | ||
270 | /* if batman-adv is switching the gw client mode off and a gateway was | 270 | /* if batman-adv is switching the gw client mode off and a gateway was |
271 | * already selected, send a DEL uevent | 271 | * already selected, send a DEL uevent |
272 | */ | 272 | */ |
273 | batadv_throw_uevent(bat_priv, BATADV_UEV_GW, BATADV_UEV_DEL, NULL); | 273 | batadv_throw_uevent(bat_priv, BATADV_UEV_GW, BATADV_UEV_DEL, NULL); |
274 | 274 | ||
275 | batadv_gw_node_put(curr_gw); | 275 | batadv_gw_node_put(curr_gw); |
276 | } | 276 | } |
277 | 277 | ||
278 | void batadv_gw_election(struct batadv_priv *bat_priv) | 278 | void batadv_gw_election(struct batadv_priv *bat_priv) |
279 | { | 279 | { |
280 | struct batadv_gw_node *curr_gw = NULL; | 280 | struct batadv_gw_node *curr_gw = NULL; |
281 | struct batadv_gw_node *next_gw = NULL; | 281 | struct batadv_gw_node *next_gw = NULL; |
282 | struct batadv_neigh_node *router = NULL; | 282 | struct batadv_neigh_node *router = NULL; |
283 | struct batadv_neigh_ifinfo *router_ifinfo = NULL; | 283 | struct batadv_neigh_ifinfo *router_ifinfo = NULL; |
284 | char gw_addr[18] = { '\0' }; | 284 | char gw_addr[18] = { '\0' }; |
285 | 285 | ||
286 | if (atomic_read(&bat_priv->gw_mode) != BATADV_GW_MODE_CLIENT) | 286 | if (atomic_read(&bat_priv->gw.mode) != BATADV_GW_MODE_CLIENT) |
287 | goto out; | 287 | goto out; |
288 | 288 | ||
289 | curr_gw = batadv_gw_get_selected_gw_node(bat_priv); | 289 | curr_gw = batadv_gw_get_selected_gw_node(bat_priv); |
290 | 290 | ||
291 | if (!batadv_atomic_dec_not_zero(&bat_priv->gw.reselect) && curr_gw) | 291 | if (!batadv_atomic_dec_not_zero(&bat_priv->gw.reselect) && curr_gw) |
292 | goto out; | 292 | goto out; |
293 | 293 | ||
294 | next_gw = batadv_gw_get_best_gw_node(bat_priv); | 294 | next_gw = batadv_gw_get_best_gw_node(bat_priv); |
295 | 295 | ||
296 | if (curr_gw == next_gw) | 296 | if (curr_gw == next_gw) |
297 | goto out; | 297 | goto out; |
298 | 298 | ||
299 | if (next_gw) { | 299 | if (next_gw) { |
300 | sprintf(gw_addr, "%pM", next_gw->orig_node->orig); | 300 | sprintf(gw_addr, "%pM", next_gw->orig_node->orig); |
301 | 301 | ||
302 | router = batadv_orig_router_get(next_gw->orig_node, | 302 | router = batadv_orig_router_get(next_gw->orig_node, |
303 | BATADV_IF_DEFAULT); | 303 | BATADV_IF_DEFAULT); |
304 | if (!router) { | 304 | if (!router) { |
305 | batadv_gw_reselect(bat_priv); | 305 | batadv_gw_reselect(bat_priv); |
306 | goto out; | 306 | goto out; |
307 | } | 307 | } |
308 | 308 | ||
309 | router_ifinfo = batadv_neigh_ifinfo_get(router, | 309 | router_ifinfo = batadv_neigh_ifinfo_get(router, |
310 | BATADV_IF_DEFAULT); | 310 | BATADV_IF_DEFAULT); |
311 | if (!router_ifinfo) { | 311 | if (!router_ifinfo) { |
312 | batadv_gw_reselect(bat_priv); | 312 | batadv_gw_reselect(bat_priv); |
313 | goto out; | 313 | goto out; |
314 | } | 314 | } |
315 | } | 315 | } |
316 | 316 | ||
317 | if ((curr_gw) && (!next_gw)) { | 317 | if ((curr_gw) && (!next_gw)) { |
318 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, | 318 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, |
319 | "Removing selected gateway - no gateway in range\n"); | 319 | "Removing selected gateway - no gateway in range\n"); |
320 | batadv_throw_uevent(bat_priv, BATADV_UEV_GW, BATADV_UEV_DEL, | 320 | batadv_throw_uevent(bat_priv, BATADV_UEV_GW, BATADV_UEV_DEL, |
321 | NULL); | 321 | NULL); |
322 | } else if ((!curr_gw) && (next_gw)) { | 322 | } else if ((!curr_gw) && (next_gw)) { |
323 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, | 323 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, |
324 | "Adding route to gateway %pM (bandwidth: %u.%u/%u.%u MBit, tq: %i)\n", | 324 | "Adding route to gateway %pM (bandwidth: %u.%u/%u.%u MBit, tq: %i)\n", |
325 | next_gw->orig_node->orig, | 325 | next_gw->orig_node->orig, |
326 | next_gw->bandwidth_down / 10, | 326 | next_gw->bandwidth_down / 10, |
327 | next_gw->bandwidth_down % 10, | 327 | next_gw->bandwidth_down % 10, |
328 | next_gw->bandwidth_up / 10, | 328 | next_gw->bandwidth_up / 10, |
329 | next_gw->bandwidth_up % 10, | 329 | next_gw->bandwidth_up % 10, |
330 | router_ifinfo->bat_iv.tq_avg); | 330 | router_ifinfo->bat_iv.tq_avg); |
331 | batadv_throw_uevent(bat_priv, BATADV_UEV_GW, BATADV_UEV_ADD, | 331 | batadv_throw_uevent(bat_priv, BATADV_UEV_GW, BATADV_UEV_ADD, |
332 | gw_addr); | 332 | gw_addr); |
333 | } else { | 333 | } else { |
334 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, | 334 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, |
335 | "Changing route to gateway %pM (bandwidth: %u.%u/%u.%u MBit, tq: %i)\n", | 335 | "Changing route to gateway %pM (bandwidth: %u.%u/%u.%u MBit, tq: %i)\n", |
336 | next_gw->orig_node->orig, | 336 | next_gw->orig_node->orig, |
337 | next_gw->bandwidth_down / 10, | 337 | next_gw->bandwidth_down / 10, |
338 | next_gw->bandwidth_down % 10, | 338 | next_gw->bandwidth_down % 10, |
339 | next_gw->bandwidth_up / 10, | 339 | next_gw->bandwidth_up / 10, |
340 | next_gw->bandwidth_up % 10, | 340 | next_gw->bandwidth_up % 10, |
341 | router_ifinfo->bat_iv.tq_avg); | 341 | router_ifinfo->bat_iv.tq_avg); |
342 | batadv_throw_uevent(bat_priv, BATADV_UEV_GW, BATADV_UEV_CHANGE, | 342 | batadv_throw_uevent(bat_priv, BATADV_UEV_GW, BATADV_UEV_CHANGE, |
343 | gw_addr); | 343 | gw_addr); |
344 | } | 344 | } |
345 | 345 | ||
346 | batadv_gw_select(bat_priv, next_gw); | 346 | batadv_gw_select(bat_priv, next_gw); |
347 | 347 | ||
348 | out: | 348 | out: |
349 | if (curr_gw) | 349 | if (curr_gw) |
350 | batadv_gw_node_put(curr_gw); | 350 | batadv_gw_node_put(curr_gw); |
351 | if (next_gw) | 351 | if (next_gw) |
352 | batadv_gw_node_put(next_gw); | 352 | batadv_gw_node_put(next_gw); |
353 | if (router) | 353 | if (router) |
354 | batadv_neigh_node_put(router); | 354 | batadv_neigh_node_put(router); |
355 | if (router_ifinfo) | 355 | if (router_ifinfo) |
356 | batadv_neigh_ifinfo_put(router_ifinfo); | 356 | batadv_neigh_ifinfo_put(router_ifinfo); |
357 | } | 357 | } |
358 | 358 | ||
359 | void batadv_gw_check_election(struct batadv_priv *bat_priv, | 359 | void batadv_gw_check_election(struct batadv_priv *bat_priv, |
360 | struct batadv_orig_node *orig_node) | 360 | struct batadv_orig_node *orig_node) |
361 | { | 361 | { |
362 | struct batadv_neigh_ifinfo *router_orig_tq = NULL; | 362 | struct batadv_neigh_ifinfo *router_orig_tq = NULL; |
363 | struct batadv_neigh_ifinfo *router_gw_tq = NULL; | 363 | struct batadv_neigh_ifinfo *router_gw_tq = NULL; |
364 | struct batadv_orig_node *curr_gw_orig; | 364 | struct batadv_orig_node *curr_gw_orig; |
365 | struct batadv_neigh_node *router_gw = NULL; | 365 | struct batadv_neigh_node *router_gw = NULL; |
366 | struct batadv_neigh_node *router_orig = NULL; | 366 | struct batadv_neigh_node *router_orig = NULL; |
367 | u8 gw_tq_avg, orig_tq_avg; | 367 | u8 gw_tq_avg, orig_tq_avg; |
368 | 368 | ||
369 | curr_gw_orig = batadv_gw_get_selected_orig(bat_priv); | 369 | curr_gw_orig = batadv_gw_get_selected_orig(bat_priv); |
370 | if (!curr_gw_orig) | 370 | if (!curr_gw_orig) |
371 | goto reselect; | 371 | goto reselect; |
372 | 372 | ||
373 | router_gw = batadv_orig_router_get(curr_gw_orig, BATADV_IF_DEFAULT); | 373 | router_gw = batadv_orig_router_get(curr_gw_orig, BATADV_IF_DEFAULT); |
374 | if (!router_gw) | 374 | if (!router_gw) |
375 | goto reselect; | 375 | goto reselect; |
376 | 376 | ||
377 | router_gw_tq = batadv_neigh_ifinfo_get(router_gw, | 377 | router_gw_tq = batadv_neigh_ifinfo_get(router_gw, |
378 | BATADV_IF_DEFAULT); | 378 | BATADV_IF_DEFAULT); |
379 | if (!router_gw_tq) | 379 | if (!router_gw_tq) |
380 | goto reselect; | 380 | goto reselect; |
381 | 381 | ||
382 | /* this node already is the gateway */ | 382 | /* this node already is the gateway */ |
383 | if (curr_gw_orig == orig_node) | 383 | if (curr_gw_orig == orig_node) |
384 | goto out; | 384 | goto out; |
385 | 385 | ||
386 | router_orig = batadv_orig_router_get(orig_node, BATADV_IF_DEFAULT); | 386 | router_orig = batadv_orig_router_get(orig_node, BATADV_IF_DEFAULT); |
387 | if (!router_orig) | 387 | if (!router_orig) |
388 | goto out; | 388 | goto out; |
389 | 389 | ||
390 | router_orig_tq = batadv_neigh_ifinfo_get(router_orig, | 390 | router_orig_tq = batadv_neigh_ifinfo_get(router_orig, |
391 | BATADV_IF_DEFAULT); | 391 | BATADV_IF_DEFAULT); |
392 | if (!router_orig_tq) | 392 | if (!router_orig_tq) |
393 | goto out; | 393 | goto out; |
394 | 394 | ||
395 | gw_tq_avg = router_gw_tq->bat_iv.tq_avg; | 395 | gw_tq_avg = router_gw_tq->bat_iv.tq_avg; |
396 | orig_tq_avg = router_orig_tq->bat_iv.tq_avg; | 396 | orig_tq_avg = router_orig_tq->bat_iv.tq_avg; |
397 | 397 | ||
398 | /* the TQ value has to be better */ | 398 | /* the TQ value has to be better */ |
399 | if (orig_tq_avg < gw_tq_avg) | 399 | if (orig_tq_avg < gw_tq_avg) |
400 | goto out; | 400 | goto out; |
401 | 401 | ||
402 | /* if the routing class is greater than 3 the value tells us how much | 402 | /* if the routing class is greater than 3 the value tells us how much |
403 | * greater the TQ value of the new gateway must be | 403 | * greater the TQ value of the new gateway must be |
404 | */ | 404 | */ |
405 | if ((atomic_read(&bat_priv->gw_sel_class) > 3) && | 405 | if ((atomic_read(&bat_priv->gw.sel_class) > 3) && |
406 | (orig_tq_avg - gw_tq_avg < atomic_read(&bat_priv->gw_sel_class))) | 406 | (orig_tq_avg - gw_tq_avg < atomic_read(&bat_priv->gw.sel_class))) |
407 | goto out; | 407 | goto out; |
408 | 408 | ||
409 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, | 409 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, |
410 | "Restarting gateway selection: better gateway found (tq curr: %i, tq new: %i)\n", | 410 | "Restarting gateway selection: better gateway found (tq curr: %i, tq new: %i)\n", |
411 | gw_tq_avg, orig_tq_avg); | 411 | gw_tq_avg, orig_tq_avg); |
412 | 412 | ||
413 | reselect: | 413 | reselect: |
414 | batadv_gw_reselect(bat_priv); | 414 | batadv_gw_reselect(bat_priv); |
415 | out: | 415 | out: |
416 | if (curr_gw_orig) | 416 | if (curr_gw_orig) |
417 | batadv_orig_node_put(curr_gw_orig); | 417 | batadv_orig_node_put(curr_gw_orig); |
418 | if (router_gw) | 418 | if (router_gw) |
419 | batadv_neigh_node_put(router_gw); | 419 | batadv_neigh_node_put(router_gw); |
420 | if (router_orig) | 420 | if (router_orig) |
421 | batadv_neigh_node_put(router_orig); | 421 | batadv_neigh_node_put(router_orig); |
422 | if (router_gw_tq) | 422 | if (router_gw_tq) |
423 | batadv_neigh_ifinfo_put(router_gw_tq); | 423 | batadv_neigh_ifinfo_put(router_gw_tq); |
424 | if (router_orig_tq) | 424 | if (router_orig_tq) |
425 | batadv_neigh_ifinfo_put(router_orig_tq); | 425 | batadv_neigh_ifinfo_put(router_orig_tq); |
426 | } | 426 | } |
427 | 427 | ||
428 | /** | 428 | /** |
429 | * batadv_gw_node_add - add gateway node to list of available gateways | 429 | * batadv_gw_node_add - add gateway node to list of available gateways |
430 | * @bat_priv: the bat priv with all the soft interface information | 430 | * @bat_priv: the bat priv with all the soft interface information |
431 | * @orig_node: originator announcing gateway capabilities | 431 | * @orig_node: originator announcing gateway capabilities |
432 | * @gateway: announced bandwidth information | 432 | * @gateway: announced bandwidth information |
433 | */ | 433 | */ |
434 | static void batadv_gw_node_add(struct batadv_priv *bat_priv, | 434 | static void batadv_gw_node_add(struct batadv_priv *bat_priv, |
435 | struct batadv_orig_node *orig_node, | 435 | struct batadv_orig_node *orig_node, |
436 | struct batadv_tvlv_gateway_data *gateway) | 436 | struct batadv_tvlv_gateway_data *gateway) |
437 | { | 437 | { |
438 | struct batadv_gw_node *gw_node; | 438 | struct batadv_gw_node *gw_node; |
439 | 439 | ||
440 | if (gateway->bandwidth_down == 0) | 440 | if (gateway->bandwidth_down == 0) |
441 | return; | 441 | return; |
442 | 442 | ||
443 | gw_node = kzalloc(sizeof(*gw_node), GFP_ATOMIC); | 443 | gw_node = kzalloc(sizeof(*gw_node), GFP_ATOMIC); |
444 | if (!gw_node) | 444 | if (!gw_node) |
445 | return; | 445 | return; |
446 | 446 | ||
447 | kref_get(&orig_node->refcount); | 447 | kref_get(&orig_node->refcount); |
448 | INIT_HLIST_NODE(&gw_node->list); | 448 | INIT_HLIST_NODE(&gw_node->list); |
449 | gw_node->orig_node = orig_node; | 449 | gw_node->orig_node = orig_node; |
450 | gw_node->bandwidth_down = ntohl(gateway->bandwidth_down); | 450 | gw_node->bandwidth_down = ntohl(gateway->bandwidth_down); |
451 | gw_node->bandwidth_up = ntohl(gateway->bandwidth_up); | 451 | gw_node->bandwidth_up = ntohl(gateway->bandwidth_up); |
452 | kref_init(&gw_node->refcount); | 452 | kref_init(&gw_node->refcount); |
453 | 453 | ||
454 | spin_lock_bh(&bat_priv->gw.list_lock); | 454 | spin_lock_bh(&bat_priv->gw.list_lock); |
455 | hlist_add_head_rcu(&gw_node->list, &bat_priv->gw.list); | 455 | hlist_add_head_rcu(&gw_node->list, &bat_priv->gw.list); |
456 | spin_unlock_bh(&bat_priv->gw.list_lock); | 456 | spin_unlock_bh(&bat_priv->gw.list_lock); |
457 | 457 | ||
458 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, | 458 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, |
459 | "Found new gateway %pM -> gw bandwidth: %u.%u/%u.%u MBit\n", | 459 | "Found new gateway %pM -> gw bandwidth: %u.%u/%u.%u MBit\n", |
460 | orig_node->orig, | 460 | orig_node->orig, |
461 | ntohl(gateway->bandwidth_down) / 10, | 461 | ntohl(gateway->bandwidth_down) / 10, |
462 | ntohl(gateway->bandwidth_down) % 10, | 462 | ntohl(gateway->bandwidth_down) % 10, |
463 | ntohl(gateway->bandwidth_up) / 10, | 463 | ntohl(gateway->bandwidth_up) / 10, |
464 | ntohl(gateway->bandwidth_up) % 10); | 464 | ntohl(gateway->bandwidth_up) % 10); |
465 | } | 465 | } |
466 | 466 | ||
467 | /** | 467 | /** |
468 | * batadv_gw_node_get - retrieve gateway node from list of available gateways | 468 | * batadv_gw_node_get - retrieve gateway node from list of available gateways |
469 | * @bat_priv: the bat priv with all the soft interface information | 469 | * @bat_priv: the bat priv with all the soft interface information |
470 | * @orig_node: originator announcing gateway capabilities | 470 | * @orig_node: originator announcing gateway capabilities |
471 | * | 471 | * |
472 | * Return: gateway node if found or NULL otherwise. | 472 | * Return: gateway node if found or NULL otherwise. |
473 | */ | 473 | */ |
474 | static struct batadv_gw_node * | 474 | static struct batadv_gw_node * |
475 | batadv_gw_node_get(struct batadv_priv *bat_priv, | 475 | batadv_gw_node_get(struct batadv_priv *bat_priv, |
476 | struct batadv_orig_node *orig_node) | 476 | struct batadv_orig_node *orig_node) |
477 | { | 477 | { |
478 | struct batadv_gw_node *gw_node_tmp, *gw_node = NULL; | 478 | struct batadv_gw_node *gw_node_tmp, *gw_node = NULL; |
479 | 479 | ||
480 | rcu_read_lock(); | 480 | rcu_read_lock(); |
481 | hlist_for_each_entry_rcu(gw_node_tmp, &bat_priv->gw.list, list) { | 481 | hlist_for_each_entry_rcu(gw_node_tmp, &bat_priv->gw.list, list) { |
482 | if (gw_node_tmp->orig_node != orig_node) | 482 | if (gw_node_tmp->orig_node != orig_node) |
483 | continue; | 483 | continue; |
484 | 484 | ||
485 | if (!kref_get_unless_zero(&gw_node_tmp->refcount)) | 485 | if (!kref_get_unless_zero(&gw_node_tmp->refcount)) |
486 | continue; | 486 | continue; |
487 | 487 | ||
488 | gw_node = gw_node_tmp; | 488 | gw_node = gw_node_tmp; |
489 | break; | 489 | break; |
490 | } | 490 | } |
491 | rcu_read_unlock(); | 491 | rcu_read_unlock(); |
492 | 492 | ||
493 | return gw_node; | 493 | return gw_node; |
494 | } | 494 | } |
495 | 495 | ||
496 | /** | 496 | /** |
497 | * batadv_gw_node_update - update list of available gateways with changed | 497 | * batadv_gw_node_update - update list of available gateways with changed |
498 | * bandwidth information | 498 | * bandwidth information |
499 | * @bat_priv: the bat priv with all the soft interface information | 499 | * @bat_priv: the bat priv with all the soft interface information |
500 | * @orig_node: originator announcing gateway capabilities | 500 | * @orig_node: originator announcing gateway capabilities |
501 | * @gateway: announced bandwidth information | 501 | * @gateway: announced bandwidth information |
502 | */ | 502 | */ |
503 | void batadv_gw_node_update(struct batadv_priv *bat_priv, | 503 | void batadv_gw_node_update(struct batadv_priv *bat_priv, |
504 | struct batadv_orig_node *orig_node, | 504 | struct batadv_orig_node *orig_node, |
505 | struct batadv_tvlv_gateway_data *gateway) | 505 | struct batadv_tvlv_gateway_data *gateway) |
506 | { | 506 | { |
507 | struct batadv_gw_node *gw_node, *curr_gw = NULL; | 507 | struct batadv_gw_node *gw_node, *curr_gw = NULL; |
508 | 508 | ||
509 | gw_node = batadv_gw_node_get(bat_priv, orig_node); | 509 | gw_node = batadv_gw_node_get(bat_priv, orig_node); |
510 | if (!gw_node) { | 510 | if (!gw_node) { |
511 | batadv_gw_node_add(bat_priv, orig_node, gateway); | 511 | batadv_gw_node_add(bat_priv, orig_node, gateway); |
512 | goto out; | 512 | goto out; |
513 | } | 513 | } |
514 | 514 | ||
515 | if ((gw_node->bandwidth_down == ntohl(gateway->bandwidth_down)) && | 515 | if ((gw_node->bandwidth_down == ntohl(gateway->bandwidth_down)) && |
516 | (gw_node->bandwidth_up == ntohl(gateway->bandwidth_up))) | 516 | (gw_node->bandwidth_up == ntohl(gateway->bandwidth_up))) |
517 | goto out; | 517 | goto out; |
518 | 518 | ||
519 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, | 519 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, |
520 | "Gateway bandwidth of originator %pM changed from %u.%u/%u.%u MBit to %u.%u/%u.%u MBit\n", | 520 | "Gateway bandwidth of originator %pM changed from %u.%u/%u.%u MBit to %u.%u/%u.%u MBit\n", |
521 | orig_node->orig, | 521 | orig_node->orig, |
522 | gw_node->bandwidth_down / 10, | 522 | gw_node->bandwidth_down / 10, |
523 | gw_node->bandwidth_down % 10, | 523 | gw_node->bandwidth_down % 10, |
524 | gw_node->bandwidth_up / 10, | 524 | gw_node->bandwidth_up / 10, |
525 | gw_node->bandwidth_up % 10, | 525 | gw_node->bandwidth_up % 10, |
526 | ntohl(gateway->bandwidth_down) / 10, | 526 | ntohl(gateway->bandwidth_down) / 10, |
527 | ntohl(gateway->bandwidth_down) % 10, | 527 | ntohl(gateway->bandwidth_down) % 10, |
528 | ntohl(gateway->bandwidth_up) / 10, | 528 | ntohl(gateway->bandwidth_up) / 10, |
529 | ntohl(gateway->bandwidth_up) % 10); | 529 | ntohl(gateway->bandwidth_up) % 10); |
530 | 530 | ||
531 | gw_node->bandwidth_down = ntohl(gateway->bandwidth_down); | 531 | gw_node->bandwidth_down = ntohl(gateway->bandwidth_down); |
532 | gw_node->bandwidth_up = ntohl(gateway->bandwidth_up); | 532 | gw_node->bandwidth_up = ntohl(gateway->bandwidth_up); |
533 | 533 | ||
534 | if (ntohl(gateway->bandwidth_down) == 0) { | 534 | if (ntohl(gateway->bandwidth_down) == 0) { |
535 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, | 535 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, |
536 | "Gateway %pM removed from gateway list\n", | 536 | "Gateway %pM removed from gateway list\n", |
537 | orig_node->orig); | 537 | orig_node->orig); |
538 | 538 | ||
539 | /* Note: We don't need a NULL check here, since curr_gw never | 539 | /* Note: We don't need a NULL check here, since curr_gw never |
540 | * gets dereferenced. | 540 | * gets dereferenced. |
541 | */ | 541 | */ |
542 | spin_lock_bh(&bat_priv->gw.list_lock); | 542 | spin_lock_bh(&bat_priv->gw.list_lock); |
543 | if (!hlist_unhashed(&gw_node->list)) { | 543 | if (!hlist_unhashed(&gw_node->list)) { |
544 | hlist_del_init_rcu(&gw_node->list); | 544 | hlist_del_init_rcu(&gw_node->list); |
545 | batadv_gw_node_put(gw_node); | 545 | batadv_gw_node_put(gw_node); |
546 | } | 546 | } |
547 | spin_unlock_bh(&bat_priv->gw.list_lock); | 547 | spin_unlock_bh(&bat_priv->gw.list_lock); |
548 | 548 | ||
549 | curr_gw = batadv_gw_get_selected_gw_node(bat_priv); | 549 | curr_gw = batadv_gw_get_selected_gw_node(bat_priv); |
550 | if (gw_node == curr_gw) | 550 | if (gw_node == curr_gw) |
551 | batadv_gw_reselect(bat_priv); | 551 | batadv_gw_reselect(bat_priv); |
552 | 552 | ||
553 | if (curr_gw) | 553 | if (curr_gw) |
554 | batadv_gw_node_put(curr_gw); | 554 | batadv_gw_node_put(curr_gw); |
555 | } | 555 | } |
556 | 556 | ||
557 | out: | 557 | out: |
558 | if (gw_node) | 558 | if (gw_node) |
559 | batadv_gw_node_put(gw_node); | 559 | batadv_gw_node_put(gw_node); |
560 | } | 560 | } |
561 | 561 | ||
562 | void batadv_gw_node_delete(struct batadv_priv *bat_priv, | 562 | void batadv_gw_node_delete(struct batadv_priv *bat_priv, |
563 | struct batadv_orig_node *orig_node) | 563 | struct batadv_orig_node *orig_node) |
564 | { | 564 | { |
565 | struct batadv_tvlv_gateway_data gateway; | 565 | struct batadv_tvlv_gateway_data gateway; |
566 | 566 | ||
567 | gateway.bandwidth_down = 0; | 567 | gateway.bandwidth_down = 0; |
568 | gateway.bandwidth_up = 0; | 568 | gateway.bandwidth_up = 0; |
569 | 569 | ||
570 | batadv_gw_node_update(bat_priv, orig_node, &gateway); | 570 | batadv_gw_node_update(bat_priv, orig_node, &gateway); |
571 | } | 571 | } |
572 | 572 | ||
573 | void batadv_gw_node_free(struct batadv_priv *bat_priv) | 573 | void batadv_gw_node_free(struct batadv_priv *bat_priv) |
574 | { | 574 | { |
575 | struct batadv_gw_node *gw_node; | 575 | struct batadv_gw_node *gw_node; |
576 | struct hlist_node *node_tmp; | 576 | struct hlist_node *node_tmp; |
577 | 577 | ||
578 | spin_lock_bh(&bat_priv->gw.list_lock); | 578 | spin_lock_bh(&bat_priv->gw.list_lock); |
579 | hlist_for_each_entry_safe(gw_node, node_tmp, | 579 | hlist_for_each_entry_safe(gw_node, node_tmp, |
580 | &bat_priv->gw.list, list) { | 580 | &bat_priv->gw.list, list) { |
581 | hlist_del_init_rcu(&gw_node->list); | 581 | hlist_del_init_rcu(&gw_node->list); |
582 | batadv_gw_node_put(gw_node); | 582 | batadv_gw_node_put(gw_node); |
583 | } | 583 | } |
584 | spin_unlock_bh(&bat_priv->gw.list_lock); | 584 | spin_unlock_bh(&bat_priv->gw.list_lock); |
585 | } | 585 | } |
586 | 586 | ||
587 | /* fails if orig_node has no router */ | 587 | /* fails if orig_node has no router */ |
588 | static int batadv_write_buffer_text(struct batadv_priv *bat_priv, | 588 | static int batadv_write_buffer_text(struct batadv_priv *bat_priv, |
589 | struct seq_file *seq, | 589 | struct seq_file *seq, |
590 | const struct batadv_gw_node *gw_node) | 590 | const struct batadv_gw_node *gw_node) |
591 | { | 591 | { |
592 | struct batadv_gw_node *curr_gw; | 592 | struct batadv_gw_node *curr_gw; |
593 | struct batadv_neigh_node *router; | 593 | struct batadv_neigh_node *router; |
594 | struct batadv_neigh_ifinfo *router_ifinfo = NULL; | 594 | struct batadv_neigh_ifinfo *router_ifinfo = NULL; |
595 | int ret = -1; | 595 | int ret = -1; |
596 | 596 | ||
597 | router = batadv_orig_router_get(gw_node->orig_node, BATADV_IF_DEFAULT); | 597 | router = batadv_orig_router_get(gw_node->orig_node, BATADV_IF_DEFAULT); |
598 | if (!router) | 598 | if (!router) |
599 | goto out; | 599 | goto out; |
600 | 600 | ||
601 | router_ifinfo = batadv_neigh_ifinfo_get(router, BATADV_IF_DEFAULT); | 601 | router_ifinfo = batadv_neigh_ifinfo_get(router, BATADV_IF_DEFAULT); |
602 | if (!router_ifinfo) | 602 | if (!router_ifinfo) |
603 | goto out; | 603 | goto out; |
604 | 604 | ||
605 | curr_gw = batadv_gw_get_selected_gw_node(bat_priv); | 605 | curr_gw = batadv_gw_get_selected_gw_node(bat_priv); |
606 | 606 | ||
607 | seq_printf(seq, "%s %pM (%3i) %pM [%10s]: %u.%u/%u.%u MBit\n", | 607 | seq_printf(seq, "%s %pM (%3i) %pM [%10s]: %u.%u/%u.%u MBit\n", |
608 | (curr_gw == gw_node ? "=>" : " "), | 608 | (curr_gw == gw_node ? "=>" : " "), |
609 | gw_node->orig_node->orig, | 609 | gw_node->orig_node->orig, |
610 | router_ifinfo->bat_iv.tq_avg, router->addr, | 610 | router_ifinfo->bat_iv.tq_avg, router->addr, |
611 | router->if_incoming->net_dev->name, | 611 | router->if_incoming->net_dev->name, |
612 | gw_node->bandwidth_down / 10, | 612 | gw_node->bandwidth_down / 10, |
613 | gw_node->bandwidth_down % 10, | 613 | gw_node->bandwidth_down % 10, |
614 | gw_node->bandwidth_up / 10, | 614 | gw_node->bandwidth_up / 10, |
615 | gw_node->bandwidth_up % 10); | 615 | gw_node->bandwidth_up % 10); |
616 | ret = seq_has_overflowed(seq) ? -1 : 0; | 616 | ret = seq_has_overflowed(seq) ? -1 : 0; |
617 | 617 | ||
618 | if (curr_gw) | 618 | if (curr_gw) |
619 | batadv_gw_node_put(curr_gw); | 619 | batadv_gw_node_put(curr_gw); |
620 | out: | 620 | out: |
621 | if (router_ifinfo) | 621 | if (router_ifinfo) |
622 | batadv_neigh_ifinfo_put(router_ifinfo); | 622 | batadv_neigh_ifinfo_put(router_ifinfo); |
623 | if (router) | 623 | if (router) |
624 | batadv_neigh_node_put(router); | 624 | batadv_neigh_node_put(router); |
625 | return ret; | 625 | return ret; |
626 | } | 626 | } |
627 | 627 | ||
628 | int batadv_gw_client_seq_print_text(struct seq_file *seq, void *offset) | 628 | int batadv_gw_client_seq_print_text(struct seq_file *seq, void *offset) |
629 | { | 629 | { |
630 | struct net_device *net_dev = (struct net_device *)seq->private; | 630 | struct net_device *net_dev = (struct net_device *)seq->private; |
631 | struct batadv_priv *bat_priv = netdev_priv(net_dev); | 631 | struct batadv_priv *bat_priv = netdev_priv(net_dev); |
632 | struct batadv_hard_iface *primary_if; | 632 | struct batadv_hard_iface *primary_if; |
633 | struct batadv_gw_node *gw_node; | 633 | struct batadv_gw_node *gw_node; |
634 | int gw_count = 0; | 634 | int gw_count = 0; |
635 | 635 | ||
636 | primary_if = batadv_seq_print_text_primary_if_get(seq); | 636 | primary_if = batadv_seq_print_text_primary_if_get(seq); |
637 | if (!primary_if) | 637 | if (!primary_if) |
638 | goto out; | 638 | goto out; |
639 | 639 | ||
640 | seq_printf(seq, | 640 | seq_printf(seq, |
641 | " Gateway (#/255) Nexthop [outgoingIF]: advertised uplink bandwidth ... [B.A.T.M.A.N. adv %s, MainIF/MAC: %s/%pM (%s)]\n", | 641 | " Gateway (#/255) Nexthop [outgoingIF]: advertised uplink bandwidth ... [B.A.T.M.A.N. adv %s, MainIF/MAC: %s/%pM (%s)]\n", |
642 | BATADV_SOURCE_VERSION, primary_if->net_dev->name, | 642 | BATADV_SOURCE_VERSION, primary_if->net_dev->name, |
643 | primary_if->net_dev->dev_addr, net_dev->name); | 643 | primary_if->net_dev->dev_addr, net_dev->name); |
644 | 644 | ||
645 | rcu_read_lock(); | 645 | rcu_read_lock(); |
646 | hlist_for_each_entry_rcu(gw_node, &bat_priv->gw.list, list) { | 646 | hlist_for_each_entry_rcu(gw_node, &bat_priv->gw.list, list) { |
647 | /* fails if orig_node has no router */ | 647 | /* fails if orig_node has no router */ |
648 | if (batadv_write_buffer_text(bat_priv, seq, gw_node) < 0) | 648 | if (batadv_write_buffer_text(bat_priv, seq, gw_node) < 0) |
649 | continue; | 649 | continue; |
650 | 650 | ||
651 | gw_count++; | 651 | gw_count++; |
652 | } | 652 | } |
653 | rcu_read_unlock(); | 653 | rcu_read_unlock(); |
654 | 654 | ||
655 | if (gw_count == 0) | 655 | if (gw_count == 0) |
656 | seq_puts(seq, "No gateways in range ...\n"); | 656 | seq_puts(seq, "No gateways in range ...\n"); |
657 | 657 | ||
658 | out: | 658 | out: |
659 | if (primary_if) | 659 | if (primary_if) |
660 | batadv_hardif_put(primary_if); | 660 | batadv_hardif_put(primary_if); |
661 | return 0; | 661 | return 0; |
662 | } | 662 | } |
663 | 663 | ||
664 | /** | 664 | /** |
665 | * batadv_gw_dhcp_recipient_get - check if a packet is a DHCP message | 665 | * batadv_gw_dhcp_recipient_get - check if a packet is a DHCP message |
666 | * @skb: the packet to check | 666 | * @skb: the packet to check |
667 | * @header_len: a pointer to the batman-adv header size | 667 | * @header_len: a pointer to the batman-adv header size |
668 | * @chaddr: buffer where the client address will be stored. Valid | 668 | * @chaddr: buffer where the client address will be stored. Valid |
669 | * only if the function returns BATADV_DHCP_TO_CLIENT | 669 | * only if the function returns BATADV_DHCP_TO_CLIENT |
670 | * | 670 | * |
671 | * This function may re-allocate the data buffer of the skb passed as argument. | 671 | * This function may re-allocate the data buffer of the skb passed as argument. |
672 | * | 672 | * |
673 | * Return: | 673 | * Return: |
674 | * - BATADV_DHCP_NO if the packet is not a dhcp message or if there was an error | 674 | * - BATADV_DHCP_NO if the packet is not a dhcp message or if there was an error |
675 | * while parsing it | 675 | * while parsing it |
676 | * - BATADV_DHCP_TO_SERVER if this is a message going to the DHCP server | 676 | * - BATADV_DHCP_TO_SERVER if this is a message going to the DHCP server |
677 | * - BATADV_DHCP_TO_CLIENT if this is a message going to a DHCP client | 677 | * - BATADV_DHCP_TO_CLIENT if this is a message going to a DHCP client |
678 | */ | 678 | */ |
679 | enum batadv_dhcp_recipient | 679 | enum batadv_dhcp_recipient |
680 | batadv_gw_dhcp_recipient_get(struct sk_buff *skb, unsigned int *header_len, | 680 | batadv_gw_dhcp_recipient_get(struct sk_buff *skb, unsigned int *header_len, |
681 | u8 *chaddr) | 681 | u8 *chaddr) |
682 | { | 682 | { |
683 | enum batadv_dhcp_recipient ret = BATADV_DHCP_NO; | 683 | enum batadv_dhcp_recipient ret = BATADV_DHCP_NO; |
684 | struct ethhdr *ethhdr; | 684 | struct ethhdr *ethhdr; |
685 | struct iphdr *iphdr; | 685 | struct iphdr *iphdr; |
686 | struct ipv6hdr *ipv6hdr; | 686 | struct ipv6hdr *ipv6hdr; |
687 | struct udphdr *udphdr; | 687 | struct udphdr *udphdr; |
688 | struct vlan_ethhdr *vhdr; | 688 | struct vlan_ethhdr *vhdr; |
689 | int chaddr_offset; | 689 | int chaddr_offset; |
690 | __be16 proto; | 690 | __be16 proto; |
691 | u8 *p; | 691 | u8 *p; |
692 | 692 | ||
693 | /* check for ethernet header */ | 693 | /* check for ethernet header */ |
694 | if (!pskb_may_pull(skb, *header_len + ETH_HLEN)) | 694 | if (!pskb_may_pull(skb, *header_len + ETH_HLEN)) |
695 | return BATADV_DHCP_NO; | 695 | return BATADV_DHCP_NO; |
696 | 696 | ||
697 | ethhdr = eth_hdr(skb); | 697 | ethhdr = eth_hdr(skb); |
698 | proto = ethhdr->h_proto; | 698 | proto = ethhdr->h_proto; |
699 | *header_len += ETH_HLEN; | 699 | *header_len += ETH_HLEN; |
700 | 700 | ||
701 | /* check for initial vlan header */ | 701 | /* check for initial vlan header */ |
702 | if (proto == htons(ETH_P_8021Q)) { | 702 | if (proto == htons(ETH_P_8021Q)) { |
703 | if (!pskb_may_pull(skb, *header_len + VLAN_HLEN)) | 703 | if (!pskb_may_pull(skb, *header_len + VLAN_HLEN)) |
704 | return BATADV_DHCP_NO; | 704 | return BATADV_DHCP_NO; |
705 | 705 | ||
706 | vhdr = vlan_eth_hdr(skb); | 706 | vhdr = vlan_eth_hdr(skb); |
707 | proto = vhdr->h_vlan_encapsulated_proto; | 707 | proto = vhdr->h_vlan_encapsulated_proto; |
708 | *header_len += VLAN_HLEN; | 708 | *header_len += VLAN_HLEN; |
709 | } | 709 | } |
710 | 710 | ||
711 | /* check for ip header */ | 711 | /* check for ip header */ |
712 | switch (proto) { | 712 | switch (proto) { |
713 | case htons(ETH_P_IP): | 713 | case htons(ETH_P_IP): |
714 | if (!pskb_may_pull(skb, *header_len + sizeof(*iphdr))) | 714 | if (!pskb_may_pull(skb, *header_len + sizeof(*iphdr))) |
715 | return BATADV_DHCP_NO; | 715 | return BATADV_DHCP_NO; |
716 | 716 | ||
717 | iphdr = (struct iphdr *)(skb->data + *header_len); | 717 | iphdr = (struct iphdr *)(skb->data + *header_len); |
718 | *header_len += iphdr->ihl * 4; | 718 | *header_len += iphdr->ihl * 4; |
719 | 719 | ||
720 | /* check for udp header */ | 720 | /* check for udp header */ |
721 | if (iphdr->protocol != IPPROTO_UDP) | 721 | if (iphdr->protocol != IPPROTO_UDP) |
722 | return BATADV_DHCP_NO; | 722 | return BATADV_DHCP_NO; |
723 | 723 | ||
724 | break; | 724 | break; |
725 | case htons(ETH_P_IPV6): | 725 | case htons(ETH_P_IPV6): |
726 | if (!pskb_may_pull(skb, *header_len + sizeof(*ipv6hdr))) | 726 | if (!pskb_may_pull(skb, *header_len + sizeof(*ipv6hdr))) |
727 | return BATADV_DHCP_NO; | 727 | return BATADV_DHCP_NO; |
728 | 728 | ||
729 | ipv6hdr = (struct ipv6hdr *)(skb->data + *header_len); | 729 | ipv6hdr = (struct ipv6hdr *)(skb->data + *header_len); |
730 | *header_len += sizeof(*ipv6hdr); | 730 | *header_len += sizeof(*ipv6hdr); |
731 | 731 | ||
732 | /* check for udp header */ | 732 | /* check for udp header */ |
733 | if (ipv6hdr->nexthdr != IPPROTO_UDP) | 733 | if (ipv6hdr->nexthdr != IPPROTO_UDP) |
734 | return BATADV_DHCP_NO; | 734 | return BATADV_DHCP_NO; |
735 | 735 | ||
736 | break; | 736 | break; |
737 | default: | 737 | default: |
738 | return BATADV_DHCP_NO; | 738 | return BATADV_DHCP_NO; |
739 | } | 739 | } |
740 | 740 | ||
741 | if (!pskb_may_pull(skb, *header_len + sizeof(*udphdr))) | 741 | if (!pskb_may_pull(skb, *header_len + sizeof(*udphdr))) |
742 | return BATADV_DHCP_NO; | 742 | return BATADV_DHCP_NO; |
743 | 743 | ||
744 | udphdr = (struct udphdr *)(skb->data + *header_len); | 744 | udphdr = (struct udphdr *)(skb->data + *header_len); |
745 | *header_len += sizeof(*udphdr); | 745 | *header_len += sizeof(*udphdr); |
746 | 746 | ||
747 | /* check for bootp port */ | 747 | /* check for bootp port */ |
748 | switch (proto) { | 748 | switch (proto) { |
749 | case htons(ETH_P_IP): | 749 | case htons(ETH_P_IP): |
750 | if (udphdr->dest == htons(67)) | 750 | if (udphdr->dest == htons(67)) |
751 | ret = BATADV_DHCP_TO_SERVER; | 751 | ret = BATADV_DHCP_TO_SERVER; |
752 | else if (udphdr->source == htons(67)) | 752 | else if (udphdr->source == htons(67)) |
753 | ret = BATADV_DHCP_TO_CLIENT; | 753 | ret = BATADV_DHCP_TO_CLIENT; |
754 | break; | 754 | break; |
755 | case htons(ETH_P_IPV6): | 755 | case htons(ETH_P_IPV6): |
756 | if (udphdr->dest == htons(547)) | 756 | if (udphdr->dest == htons(547)) |
757 | ret = BATADV_DHCP_TO_SERVER; | 757 | ret = BATADV_DHCP_TO_SERVER; |
758 | else if (udphdr->source == htons(547)) | 758 | else if (udphdr->source == htons(547)) |
759 | ret = BATADV_DHCP_TO_CLIENT; | 759 | ret = BATADV_DHCP_TO_CLIENT; |
760 | break; | 760 | break; |
761 | } | 761 | } |
762 | 762 | ||
763 | chaddr_offset = *header_len + BATADV_DHCP_CHADDR_OFFSET; | 763 | chaddr_offset = *header_len + BATADV_DHCP_CHADDR_OFFSET; |
764 | /* store the client address if the message is going to a client */ | 764 | /* store the client address if the message is going to a client */ |
765 | if (ret == BATADV_DHCP_TO_CLIENT && | 765 | if (ret == BATADV_DHCP_TO_CLIENT && |
766 | pskb_may_pull(skb, chaddr_offset + ETH_ALEN)) { | 766 | pskb_may_pull(skb, chaddr_offset + ETH_ALEN)) { |
767 | /* check if the DHCP packet carries an Ethernet DHCP */ | 767 | /* check if the DHCP packet carries an Ethernet DHCP */ |
768 | p = skb->data + *header_len + BATADV_DHCP_HTYPE_OFFSET; | 768 | p = skb->data + *header_len + BATADV_DHCP_HTYPE_OFFSET; |
769 | if (*p != BATADV_DHCP_HTYPE_ETHERNET) | 769 | if (*p != BATADV_DHCP_HTYPE_ETHERNET) |
770 | return BATADV_DHCP_NO; | 770 | return BATADV_DHCP_NO; |
771 | 771 | ||
772 | /* check if the DHCP packet carries a valid Ethernet address */ | 772 | /* check if the DHCP packet carries a valid Ethernet address */ |
773 | p = skb->data + *header_len + BATADV_DHCP_HLEN_OFFSET; | 773 | p = skb->data + *header_len + BATADV_DHCP_HLEN_OFFSET; |
774 | if (*p != ETH_ALEN) | 774 | if (*p != ETH_ALEN) |
775 | return BATADV_DHCP_NO; | 775 | return BATADV_DHCP_NO; |
776 | 776 | ||
777 | ether_addr_copy(chaddr, skb->data + chaddr_offset); | 777 | ether_addr_copy(chaddr, skb->data + chaddr_offset); |
778 | } | 778 | } |
779 | 779 | ||
780 | return ret; | 780 | return ret; |
781 | } | 781 | } |
782 | 782 | ||
783 | /** | 783 | /** |
784 | * batadv_gw_out_of_range - check if the dhcp request destination is the best gw | 784 | * batadv_gw_out_of_range - check if the dhcp request destination is the best gw |
785 | * @bat_priv: the bat priv with all the soft interface information | 785 | * @bat_priv: the bat priv with all the soft interface information |
786 | * @skb: the outgoing packet | 786 | * @skb: the outgoing packet |
787 | * | 787 | * |
788 | * Check if the skb is a DHCP request and if it is sent to the current best GW | 788 | * Check if the skb is a DHCP request and if it is sent to the current best GW |
789 | * server. Due to topology changes it may be the case that the GW server | 789 | * server. Due to topology changes it may be the case that the GW server |
790 | * previously selected is not the best one anymore. | 790 | * previously selected is not the best one anymore. |
791 | * | 791 | * |
792 | * This call might reallocate skb data. | 792 | * This call might reallocate skb data. |
793 | * Must be invoked only when the DHCP packet is going TO a DHCP SERVER. | 793 | * Must be invoked only when the DHCP packet is going TO a DHCP SERVER. |
794 | * | 794 | * |
795 | * Return: true if the packet destination is unicast and it is not the best gw, | 795 | * Return: true if the packet destination is unicast and it is not the best gw, |
796 | * false otherwise. | 796 | * false otherwise. |
797 | */ | 797 | */ |
798 | bool batadv_gw_out_of_range(struct batadv_priv *bat_priv, | 798 | bool batadv_gw_out_of_range(struct batadv_priv *bat_priv, |
799 | struct sk_buff *skb) | 799 | struct sk_buff *skb) |
800 | { | 800 | { |
801 | struct batadv_neigh_node *neigh_curr = NULL; | 801 | struct batadv_neigh_node *neigh_curr = NULL; |
802 | struct batadv_neigh_node *neigh_old = NULL; | 802 | struct batadv_neigh_node *neigh_old = NULL; |
803 | struct batadv_orig_node *orig_dst_node = NULL; | 803 | struct batadv_orig_node *orig_dst_node = NULL; |
804 | struct batadv_gw_node *gw_node = NULL; | 804 | struct batadv_gw_node *gw_node = NULL; |
805 | struct batadv_gw_node *curr_gw = NULL; | 805 | struct batadv_gw_node *curr_gw = NULL; |
806 | struct batadv_neigh_ifinfo *curr_ifinfo, *old_ifinfo; | 806 | struct batadv_neigh_ifinfo *curr_ifinfo, *old_ifinfo; |
807 | struct ethhdr *ethhdr = (struct ethhdr *)skb->data; | 807 | struct ethhdr *ethhdr = (struct ethhdr *)skb->data; |
808 | bool out_of_range = false; | 808 | bool out_of_range = false; |
809 | u8 curr_tq_avg; | 809 | u8 curr_tq_avg; |
810 | unsigned short vid; | 810 | unsigned short vid; |
811 | 811 | ||
812 | vid = batadv_get_vid(skb, 0); | 812 | vid = batadv_get_vid(skb, 0); |
813 | 813 | ||
814 | orig_dst_node = batadv_transtable_search(bat_priv, ethhdr->h_source, | 814 | orig_dst_node = batadv_transtable_search(bat_priv, ethhdr->h_source, |
815 | ethhdr->h_dest, vid); | 815 | ethhdr->h_dest, vid); |
816 | if (!orig_dst_node) | 816 | if (!orig_dst_node) |
817 | goto out; | 817 | goto out; |
818 | 818 | ||
819 | gw_node = batadv_gw_node_get(bat_priv, orig_dst_node); | 819 | gw_node = batadv_gw_node_get(bat_priv, orig_dst_node); |
820 | if (!gw_node) | 820 | if (!gw_node) |
821 | goto out; | 821 | goto out; |
822 | 822 | ||
823 | switch (atomic_read(&bat_priv->gw_mode)) { | 823 | switch (atomic_read(&bat_priv->gw.mode)) { |
824 | case BATADV_GW_MODE_SERVER: | 824 | case BATADV_GW_MODE_SERVER: |
825 | /* If we are a GW then we are our best GW. We can artificially | 825 | /* If we are a GW then we are our best GW. We can artificially |
826 | * set the tq towards ourself as the maximum value | 826 | * set the tq towards ourself as the maximum value |
827 | */ | 827 | */ |
828 | curr_tq_avg = BATADV_TQ_MAX_VALUE; | 828 | curr_tq_avg = BATADV_TQ_MAX_VALUE; |
829 | break; | 829 | break; |
830 | case BATADV_GW_MODE_CLIENT: | 830 | case BATADV_GW_MODE_CLIENT: |
831 | curr_gw = batadv_gw_get_selected_gw_node(bat_priv); | 831 | curr_gw = batadv_gw_get_selected_gw_node(bat_priv); |
832 | if (!curr_gw) | 832 | if (!curr_gw) |
833 | goto out; | 833 | goto out; |
834 | 834 | ||
835 | /* packet is going to our gateway */ | 835 | /* packet is going to our gateway */ |
836 | if (curr_gw->orig_node == orig_dst_node) | 836 | if (curr_gw->orig_node == orig_dst_node) |
837 | goto out; | 837 | goto out; |
838 | 838 | ||
839 | /* If the dhcp packet has been sent to a different gw, | 839 | /* If the dhcp packet has been sent to a different gw, |
840 | * we have to evaluate whether the old gw is still | 840 | * we have to evaluate whether the old gw is still |
841 | * reliable enough | 841 | * reliable enough |
842 | */ | 842 | */ |
843 | neigh_curr = batadv_find_router(bat_priv, curr_gw->orig_node, | 843 | neigh_curr = batadv_find_router(bat_priv, curr_gw->orig_node, |
844 | NULL); | 844 | NULL); |
845 | if (!neigh_curr) | 845 | if (!neigh_curr) |
846 | goto out; | 846 | goto out; |
847 | 847 | ||
848 | curr_ifinfo = batadv_neigh_ifinfo_get(neigh_curr, | 848 | curr_ifinfo = batadv_neigh_ifinfo_get(neigh_curr, |
849 | BATADV_IF_DEFAULT); | 849 | BATADV_IF_DEFAULT); |
850 | if (!curr_ifinfo) | 850 | if (!curr_ifinfo) |
851 | goto out; | 851 | goto out; |
852 | 852 | ||
853 | curr_tq_avg = curr_ifinfo->bat_iv.tq_avg; | 853 | curr_tq_avg = curr_ifinfo->bat_iv.tq_avg; |
854 | batadv_neigh_ifinfo_put(curr_ifinfo); | 854 | batadv_neigh_ifinfo_put(curr_ifinfo); |
855 | 855 | ||
856 | break; | 856 | break; |
857 | case BATADV_GW_MODE_OFF: | 857 | case BATADV_GW_MODE_OFF: |
858 | default: | 858 | default: |
859 | goto out; | 859 | goto out; |
860 | } | 860 | } |
861 | 861 | ||
862 | neigh_old = batadv_find_router(bat_priv, orig_dst_node, NULL); | 862 | neigh_old = batadv_find_router(bat_priv, orig_dst_node, NULL); |
863 | if (!neigh_old) | 863 | if (!neigh_old) |
864 | goto out; | 864 | goto out; |
865 | 865 | ||
866 | old_ifinfo = batadv_neigh_ifinfo_get(neigh_old, BATADV_IF_DEFAULT); | 866 | old_ifinfo = batadv_neigh_ifinfo_get(neigh_old, BATADV_IF_DEFAULT); |
867 | if (!old_ifinfo) | 867 | if (!old_ifinfo) |
868 | goto out; | 868 | goto out; |
869 | 869 | ||
870 | if ((curr_tq_avg - old_ifinfo->bat_iv.tq_avg) > BATADV_GW_THRESHOLD) | 870 | if ((curr_tq_avg - old_ifinfo->bat_iv.tq_avg) > BATADV_GW_THRESHOLD) |
871 | out_of_range = true; | 871 | out_of_range = true; |
872 | batadv_neigh_ifinfo_put(old_ifinfo); | 872 | batadv_neigh_ifinfo_put(old_ifinfo); |
873 | 873 | ||
874 | out: | 874 | out: |
875 | if (orig_dst_node) | 875 | if (orig_dst_node) |
876 | batadv_orig_node_put(orig_dst_node); | 876 | batadv_orig_node_put(orig_dst_node); |
877 | if (curr_gw) | 877 | if (curr_gw) |
878 | batadv_gw_node_put(curr_gw); | 878 | batadv_gw_node_put(curr_gw); |
879 | if (gw_node) | 879 | if (gw_node) |
880 | batadv_gw_node_put(gw_node); | 880 | batadv_gw_node_put(gw_node); |
881 | if (neigh_old) | 881 | if (neigh_old) |
882 | batadv_neigh_node_put(neigh_old); | 882 | batadv_neigh_node_put(neigh_old); |
883 | if (neigh_curr) | 883 | if (neigh_curr) |
884 | batadv_neigh_node_put(neigh_curr); | 884 | batadv_neigh_node_put(neigh_curr); |
885 | return out_of_range; | 885 | return out_of_range; |
886 | } | 886 | } |
887 | 887 |
net/batman-adv/gateway_common.c
1 | /* Copyright (C) 2009-2016 B.A.T.M.A.N. contributors: | 1 | /* Copyright (C) 2009-2016 B.A.T.M.A.N. contributors: |
2 | * | 2 | * |
3 | * Marek Lindner | 3 | * Marek Lindner |
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 |
7 | * License as published by the Free Software Foundation. | 7 | * License as published by the Free Software Foundation. |
8 | * | 8 | * |
9 | * This program is distributed in the hope that it will be useful, but | 9 | * This program is distributed in the hope that it will be useful, but |
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of | 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 | * General Public License for more details. | 12 | * General Public License for more details. |
13 | * | 13 | * |
14 | * You should have received a copy of the GNU General Public License | 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/>. | 15 | * along with this program; if not, see <http://www.gnu.org/licenses/>. |
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include "gateway_common.h" | 18 | #include "gateway_common.h" |
19 | #include "main.h" | 19 | #include "main.h" |
20 | 20 | ||
21 | #include <linux/atomic.h> | 21 | #include <linux/atomic.h> |
22 | #include <linux/errno.h> | 22 | #include <linux/errno.h> |
23 | #include <linux/byteorder/generic.h> | 23 | #include <linux/byteorder/generic.h> |
24 | #include <linux/kernel.h> | 24 | #include <linux/kernel.h> |
25 | #include <linux/math64.h> | 25 | #include <linux/math64.h> |
26 | #include <linux/netdevice.h> | 26 | #include <linux/netdevice.h> |
27 | #include <linux/stddef.h> | 27 | #include <linux/stddef.h> |
28 | #include <linux/string.h> | 28 | #include <linux/string.h> |
29 | 29 | ||
30 | #include "gateway_client.h" | 30 | #include "gateway_client.h" |
31 | #include "packet.h" | 31 | #include "packet.h" |
32 | 32 | ||
33 | /** | 33 | /** |
34 | * batadv_parse_throughput - parse supplied string buffer to extract throughput | 34 | * batadv_parse_throughput - parse supplied string buffer to extract throughput |
35 | * information | 35 | * information |
36 | * @net_dev: the soft interface net device | 36 | * @net_dev: the soft interface net device |
37 | * @buff: string buffer to parse | 37 | * @buff: string buffer to parse |
38 | * @description: text shown when throughput string cannot be parsed | 38 | * @description: text shown when throughput string cannot be parsed |
39 | * @throughput: pointer holding the returned throughput information | 39 | * @throughput: pointer holding the returned throughput information |
40 | * | 40 | * |
41 | * Return: false on parse error and true otherwise. | 41 | * Return: false on parse error and true otherwise. |
42 | */ | 42 | */ |
43 | 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; |
48 | char *tmp_ptr; | 48 | char *tmp_ptr; |
49 | int ret; | 49 | int ret; |
50 | 50 | ||
51 | if (strlen(buff) > 4) { | 51 | if (strlen(buff) > 4) { |
52 | tmp_ptr = buff + strlen(buff) - 4; | 52 | tmp_ptr = buff + strlen(buff) - 4; |
53 | 53 | ||
54 | if (strncasecmp(tmp_ptr, "mbit", 4) == 0) | 54 | if (strncasecmp(tmp_ptr, "mbit", 4) == 0) |
55 | bw_unit_type = BATADV_BW_UNIT_MBIT; | 55 | bw_unit_type = BATADV_BW_UNIT_MBIT; |
56 | 56 | ||
57 | if ((strncasecmp(tmp_ptr, "kbit", 4) == 0) || | 57 | if ((strncasecmp(tmp_ptr, "kbit", 4) == 0) || |
58 | (bw_unit_type == BATADV_BW_UNIT_MBIT)) | 58 | (bw_unit_type == BATADV_BW_UNIT_MBIT)) |
59 | *tmp_ptr = '\0'; | 59 | *tmp_ptr = '\0'; |
60 | } | 60 | } |
61 | 61 | ||
62 | ret = kstrtou64(buff, 10, <hroughput); | 62 | ret = kstrtou64(buff, 10, <hroughput); |
63 | if (ret) { | 63 | if (ret) { |
64 | batadv_err(net_dev, | 64 | batadv_err(net_dev, |
65 | "Invalid throughput speed for %s: %s\n", | 65 | "Invalid throughput speed for %s: %s\n", |
66 | description, buff); | 66 | description, buff); |
67 | return false; | 67 | return false; |
68 | } | 68 | } |
69 | 69 | ||
70 | switch (bw_unit_type) { | 70 | switch (bw_unit_type) { |
71 | case BATADV_BW_UNIT_MBIT: | 71 | case BATADV_BW_UNIT_MBIT: |
72 | /* prevent overflow */ | 72 | /* prevent overflow */ |
73 | if (U64_MAX / 10 < lthroughput) { | 73 | if (U64_MAX / 10 < lthroughput) { |
74 | batadv_err(net_dev, | 74 | batadv_err(net_dev, |
75 | "Throughput speed for %s too large: %s\n", | 75 | "Throughput speed for %s too large: %s\n", |
76 | description, buff); | 76 | description, buff); |
77 | return false; | 77 | return false; |
78 | } | 78 | } |
79 | 79 | ||
80 | lthroughput *= 10; | 80 | lthroughput *= 10; |
81 | break; | 81 | break; |
82 | case BATADV_BW_UNIT_KBIT: | 82 | case BATADV_BW_UNIT_KBIT: |
83 | default: | 83 | default: |
84 | lthroughput = div_u64(lthroughput, 100); | 84 | lthroughput = div_u64(lthroughput, 100); |
85 | break; | 85 | break; |
86 | } | 86 | } |
87 | 87 | ||
88 | if (lthroughput > U32_MAX) { | 88 | if (lthroughput > U32_MAX) { |
89 | batadv_err(net_dev, | 89 | batadv_err(net_dev, |
90 | "Throughput speed for %s too large: %s\n", | 90 | "Throughput speed for %s too large: %s\n", |
91 | description, buff); | 91 | description, buff); |
92 | return false; | 92 | return false; |
93 | } | 93 | } |
94 | 94 | ||
95 | *throughput = lthroughput; | 95 | *throughput = lthroughput; |
96 | 96 | ||
97 | return true; | 97 | return true; |
98 | } | 98 | } |
99 | 99 | ||
100 | /** | 100 | /** |
101 | * batadv_parse_gw_bandwidth - parse supplied string buffer to extract download | 101 | * batadv_parse_gw_bandwidth - parse supplied string buffer to extract download |
102 | * and upload bandwidth information | 102 | * and upload bandwidth information |
103 | * @net_dev: the soft interface net device | 103 | * @net_dev: the soft interface net device |
104 | * @buff: string buffer to parse | 104 | * @buff: string buffer to parse |
105 | * @down: pointer holding the returned download bandwidth information | 105 | * @down: pointer holding the returned download bandwidth information |
106 | * @up: pointer holding the returned upload bandwidth information | 106 | * @up: pointer holding the returned upload bandwidth information |
107 | * | 107 | * |
108 | * Return: false on parse error and true otherwise. | 108 | * Return: false on parse error and true otherwise. |
109 | */ | 109 | */ |
110 | static bool batadv_parse_gw_bandwidth(struct net_device *net_dev, char *buff, | 110 | static bool batadv_parse_gw_bandwidth(struct net_device *net_dev, char *buff, |
111 | u32 *down, u32 *up) | 111 | u32 *down, u32 *up) |
112 | { | 112 | { |
113 | char *slash_ptr; | 113 | char *slash_ptr; |
114 | bool ret; | 114 | bool ret; |
115 | 115 | ||
116 | slash_ptr = strchr(buff, '/'); | 116 | slash_ptr = strchr(buff, '/'); |
117 | if (slash_ptr) | 117 | if (slash_ptr) |
118 | *slash_ptr = 0; | 118 | *slash_ptr = 0; |
119 | 119 | ||
120 | ret = batadv_parse_throughput(net_dev, buff, "download gateway speed", | 120 | ret = batadv_parse_throughput(net_dev, buff, "download gateway speed", |
121 | down); | 121 | down); |
122 | if (!ret) | 122 | if (!ret) |
123 | return false; | 123 | return false; |
124 | 124 | ||
125 | /* we also got some upload info */ | 125 | /* we also got some upload info */ |
126 | if (slash_ptr) { | 126 | if (slash_ptr) { |
127 | ret = batadv_parse_throughput(net_dev, slash_ptr + 1, | 127 | ret = batadv_parse_throughput(net_dev, slash_ptr + 1, |
128 | "upload gateway speed", up); | 128 | "upload gateway speed", up); |
129 | if (!ret) | 129 | if (!ret) |
130 | return false; | 130 | return false; |
131 | } | 131 | } |
132 | 132 | ||
133 | return true; | 133 | return true; |
134 | } | 134 | } |
135 | 135 | ||
136 | /** | 136 | /** |
137 | * batadv_gw_tvlv_container_update - update the gw tvlv container after gateway | 137 | * batadv_gw_tvlv_container_update - update the gw tvlv container after gateway |
138 | * setting change | 138 | * setting change |
139 | * @bat_priv: the bat priv with all the soft interface information | 139 | * @bat_priv: the bat priv with all the soft interface information |
140 | */ | 140 | */ |
141 | void batadv_gw_tvlv_container_update(struct batadv_priv *bat_priv) | 141 | void batadv_gw_tvlv_container_update(struct batadv_priv *bat_priv) |
142 | { | 142 | { |
143 | struct batadv_tvlv_gateway_data gw; | 143 | struct batadv_tvlv_gateway_data gw; |
144 | u32 down, up; | 144 | u32 down, up; |
145 | char gw_mode; | 145 | char gw_mode; |
146 | 146 | ||
147 | gw_mode = atomic_read(&bat_priv->gw_mode); | 147 | gw_mode = atomic_read(&bat_priv->gw.mode); |
148 | 148 | ||
149 | switch (gw_mode) { | 149 | switch (gw_mode) { |
150 | case BATADV_GW_MODE_OFF: | 150 | case BATADV_GW_MODE_OFF: |
151 | case BATADV_GW_MODE_CLIENT: | 151 | case BATADV_GW_MODE_CLIENT: |
152 | batadv_tvlv_container_unregister(bat_priv, BATADV_TVLV_GW, 1); | 152 | batadv_tvlv_container_unregister(bat_priv, BATADV_TVLV_GW, 1); |
153 | break; | 153 | break; |
154 | case BATADV_GW_MODE_SERVER: | 154 | case BATADV_GW_MODE_SERVER: |
155 | down = atomic_read(&bat_priv->gw.bandwidth_down); | 155 | down = atomic_read(&bat_priv->gw.bandwidth_down); |
156 | up = atomic_read(&bat_priv->gw.bandwidth_up); | 156 | up = atomic_read(&bat_priv->gw.bandwidth_up); |
157 | gw.bandwidth_down = htonl(down); | 157 | gw.bandwidth_down = htonl(down); |
158 | gw.bandwidth_up = htonl(up); | 158 | gw.bandwidth_up = htonl(up); |
159 | batadv_tvlv_container_register(bat_priv, BATADV_TVLV_GW, 1, | 159 | batadv_tvlv_container_register(bat_priv, BATADV_TVLV_GW, 1, |
160 | &gw, sizeof(gw)); | 160 | &gw, sizeof(gw)); |
161 | break; | 161 | break; |
162 | } | 162 | } |
163 | } | 163 | } |
164 | 164 | ||
165 | ssize_t batadv_gw_bandwidth_set(struct net_device *net_dev, char *buff, | 165 | ssize_t batadv_gw_bandwidth_set(struct net_device *net_dev, char *buff, |
166 | size_t count) | 166 | size_t count) |
167 | { | 167 | { |
168 | struct batadv_priv *bat_priv = netdev_priv(net_dev); | 168 | struct batadv_priv *bat_priv = netdev_priv(net_dev); |
169 | u32 down_curr; | 169 | u32 down_curr; |
170 | u32 up_curr; | 170 | u32 up_curr; |
171 | u32 down_new = 0; | 171 | u32 down_new = 0; |
172 | u32 up_new = 0; | 172 | u32 up_new = 0; |
173 | bool ret; | 173 | bool ret; |
174 | 174 | ||
175 | down_curr = (unsigned int)atomic_read(&bat_priv->gw.bandwidth_down); | 175 | down_curr = (unsigned int)atomic_read(&bat_priv->gw.bandwidth_down); |
176 | up_curr = (unsigned int)atomic_read(&bat_priv->gw.bandwidth_up); | 176 | up_curr = (unsigned int)atomic_read(&bat_priv->gw.bandwidth_up); |
177 | 177 | ||
178 | ret = batadv_parse_gw_bandwidth(net_dev, buff, &down_new, &up_new); | 178 | ret = batadv_parse_gw_bandwidth(net_dev, buff, &down_new, &up_new); |
179 | if (!ret) | 179 | if (!ret) |
180 | return -EINVAL; | 180 | return -EINVAL; |
181 | 181 | ||
182 | if (!down_new) | 182 | if (!down_new) |
183 | down_new = 1; | 183 | down_new = 1; |
184 | 184 | ||
185 | if (!up_new) | 185 | if (!up_new) |
186 | up_new = down_new / 5; | 186 | up_new = down_new / 5; |
187 | 187 | ||
188 | if (!up_new) | 188 | if (!up_new) |
189 | up_new = 1; | 189 | up_new = 1; |
190 | 190 | ||
191 | if ((down_curr == down_new) && (up_curr == up_new)) | 191 | if ((down_curr == down_new) && (up_curr == up_new)) |
192 | return count; | 192 | return count; |
193 | 193 | ||
194 | batadv_gw_reselect(bat_priv); | 194 | batadv_gw_reselect(bat_priv); |
195 | batadv_info(net_dev, | 195 | batadv_info(net_dev, |
196 | "Changing gateway bandwidth from: '%u.%u/%u.%u MBit' to: '%u.%u/%u.%u MBit'\n", | 196 | "Changing gateway bandwidth from: '%u.%u/%u.%u MBit' to: '%u.%u/%u.%u MBit'\n", |
197 | down_curr / 10, down_curr % 10, up_curr / 10, up_curr % 10, | 197 | down_curr / 10, down_curr % 10, up_curr / 10, up_curr % 10, |
198 | down_new / 10, down_new % 10, up_new / 10, up_new % 10); | 198 | down_new / 10, down_new % 10, up_new / 10, up_new % 10); |
199 | 199 | ||
200 | atomic_set(&bat_priv->gw.bandwidth_down, down_new); | 200 | atomic_set(&bat_priv->gw.bandwidth_down, down_new); |
201 | atomic_set(&bat_priv->gw.bandwidth_up, up_new); | 201 | atomic_set(&bat_priv->gw.bandwidth_up, up_new); |
202 | batadv_gw_tvlv_container_update(bat_priv); | 202 | batadv_gw_tvlv_container_update(bat_priv); |
203 | 203 | ||
204 | return count; | 204 | return count; |
205 | } | 205 | } |
206 | 206 | ||
207 | /** | 207 | /** |
208 | * batadv_gw_tvlv_ogm_handler_v1 - process incoming gateway tvlv container | 208 | * batadv_gw_tvlv_ogm_handler_v1 - process incoming gateway tvlv container |
209 | * @bat_priv: the bat priv with all the soft interface information | 209 | * @bat_priv: the bat priv with all the soft interface information |
210 | * @orig: the orig_node of the ogm | 210 | * @orig: the orig_node of the ogm |
211 | * @flags: flags indicating the tvlv state (see batadv_tvlv_handler_flags) | 211 | * @flags: flags indicating the tvlv state (see batadv_tvlv_handler_flags) |
212 | * @tvlv_value: tvlv buffer containing the gateway data | 212 | * @tvlv_value: tvlv buffer containing the gateway data |
213 | * @tvlv_value_len: tvlv buffer length | 213 | * @tvlv_value_len: tvlv buffer length |
214 | */ | 214 | */ |
215 | static void batadv_gw_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv, | 215 | static void batadv_gw_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv, |
216 | struct batadv_orig_node *orig, | 216 | struct batadv_orig_node *orig, |
217 | u8 flags, | 217 | u8 flags, |
218 | void *tvlv_value, u16 tvlv_value_len) | 218 | void *tvlv_value, u16 tvlv_value_len) |
219 | { | 219 | { |
220 | struct batadv_tvlv_gateway_data gateway, *gateway_ptr; | 220 | struct batadv_tvlv_gateway_data gateway, *gateway_ptr; |
221 | 221 | ||
222 | /* only fetch the tvlv value if the handler wasn't called via the | 222 | /* only fetch the tvlv value if the handler wasn't called via the |
223 | * CIFNOTFND flag and if there is data to fetch | 223 | * CIFNOTFND flag and if there is data to fetch |
224 | */ | 224 | */ |
225 | if ((flags & BATADV_TVLV_HANDLER_OGM_CIFNOTFND) || | 225 | if ((flags & BATADV_TVLV_HANDLER_OGM_CIFNOTFND) || |
226 | (tvlv_value_len < sizeof(gateway))) { | 226 | (tvlv_value_len < sizeof(gateway))) { |
227 | gateway.bandwidth_down = 0; | 227 | gateway.bandwidth_down = 0; |
228 | gateway.bandwidth_up = 0; | 228 | gateway.bandwidth_up = 0; |
229 | } else { | 229 | } else { |
230 | gateway_ptr = tvlv_value; | 230 | gateway_ptr = tvlv_value; |
231 | gateway.bandwidth_down = gateway_ptr->bandwidth_down; | 231 | gateway.bandwidth_down = gateway_ptr->bandwidth_down; |
232 | gateway.bandwidth_up = gateway_ptr->bandwidth_up; | 232 | gateway.bandwidth_up = gateway_ptr->bandwidth_up; |
233 | if ((gateway.bandwidth_down == 0) || | 233 | if ((gateway.bandwidth_down == 0) || |
234 | (gateway.bandwidth_up == 0)) { | 234 | (gateway.bandwidth_up == 0)) { |
235 | gateway.bandwidth_down = 0; | 235 | gateway.bandwidth_down = 0; |
236 | gateway.bandwidth_up = 0; | 236 | gateway.bandwidth_up = 0; |
237 | } | 237 | } |
238 | } | 238 | } |
239 | 239 | ||
240 | batadv_gw_node_update(bat_priv, orig, &gateway); | 240 | batadv_gw_node_update(bat_priv, orig, &gateway); |
241 | 241 | ||
242 | /* restart gateway selection if fast or late switching was enabled */ | 242 | /* restart gateway selection if fast or late switching was enabled */ |
243 | if ((gateway.bandwidth_down != 0) && | 243 | if ((gateway.bandwidth_down != 0) && |
244 | (atomic_read(&bat_priv->gw_mode) == BATADV_GW_MODE_CLIENT) && | 244 | (atomic_read(&bat_priv->gw.mode) == BATADV_GW_MODE_CLIENT) && |
245 | (atomic_read(&bat_priv->gw_sel_class) > 2)) | 245 | (atomic_read(&bat_priv->gw.sel_class) > 2)) |
246 | batadv_gw_check_election(bat_priv, orig); | 246 | batadv_gw_check_election(bat_priv, orig); |
247 | } | 247 | } |
248 | 248 | ||
249 | /** | 249 | /** |
250 | * batadv_gw_init - initialise the gateway handling internals | 250 | * batadv_gw_init - initialise the gateway handling internals |
251 | * @bat_priv: the bat priv with all the soft interface information | 251 | * @bat_priv: the bat priv with all the soft interface information |
252 | */ | 252 | */ |
253 | void batadv_gw_init(struct batadv_priv *bat_priv) | 253 | void batadv_gw_init(struct batadv_priv *bat_priv) |
254 | { | 254 | { |
255 | batadv_tvlv_handler_register(bat_priv, batadv_gw_tvlv_ogm_handler_v1, | 255 | batadv_tvlv_handler_register(bat_priv, batadv_gw_tvlv_ogm_handler_v1, |
256 | NULL, BATADV_TVLV_GW, 1, | 256 | NULL, BATADV_TVLV_GW, 1, |
257 | BATADV_TVLV_HANDLER_OGM_CIFNOTFND); | 257 | BATADV_TVLV_HANDLER_OGM_CIFNOTFND); |
258 | } | 258 | } |
259 | 259 | ||
260 | /** | 260 | /** |
261 | * batadv_gw_free - free the gateway handling internals | 261 | * batadv_gw_free - free the gateway handling internals |
262 | * @bat_priv: the bat priv with all the soft interface information | 262 | * @bat_priv: the bat priv with all the soft interface information |
263 | */ | 263 | */ |
264 | void batadv_gw_free(struct batadv_priv *bat_priv) | 264 | void batadv_gw_free(struct batadv_priv *bat_priv) |
265 | { | 265 | { |
266 | batadv_tvlv_container_unregister(bat_priv, BATADV_TVLV_GW, 1); | 266 | batadv_tvlv_container_unregister(bat_priv, BATADV_TVLV_GW, 1); |
267 | batadv_tvlv_handler_unregister(bat_priv, BATADV_TVLV_GW, 1); | 267 | batadv_tvlv_handler_unregister(bat_priv, BATADV_TVLV_GW, 1); |
268 | } | 268 | } |
269 | 269 |
net/batman-adv/soft-interface.c
1 | /* Copyright (C) 2007-2016 B.A.T.M.A.N. contributors: | 1 | /* Copyright (C) 2007-2016 B.A.T.M.A.N. contributors: |
2 | * | 2 | * |
3 | * Marek Lindner, Simon Wunderlich | 3 | * Marek Lindner, Simon Wunderlich |
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 |
7 | * License as published by the Free Software Foundation. | 7 | * License as published by the Free Software Foundation. |
8 | * | 8 | * |
9 | * This program is distributed in the hope that it will be useful, but | 9 | * This program is distributed in the hope that it will be useful, but |
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of | 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 | * General Public License for more details. | 12 | * General Public License for more details. |
13 | * | 13 | * |
14 | * You should have received a copy of the GNU General Public License | 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/>. | 15 | * along with this program; if not, see <http://www.gnu.org/licenses/>. |
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include "soft-interface.h" | 18 | #include "soft-interface.h" |
19 | #include "main.h" | 19 | #include "main.h" |
20 | 20 | ||
21 | #include <linux/atomic.h> | 21 | #include <linux/atomic.h> |
22 | #include <linux/byteorder/generic.h> | 22 | #include <linux/byteorder/generic.h> |
23 | #include <linux/cache.h> | 23 | #include <linux/cache.h> |
24 | #include <linux/compiler.h> | 24 | #include <linux/compiler.h> |
25 | #include <linux/errno.h> | 25 | #include <linux/errno.h> |
26 | #include <linux/etherdevice.h> | 26 | #include <linux/etherdevice.h> |
27 | #include <linux/ethtool.h> | 27 | #include <linux/ethtool.h> |
28 | #include <linux/fs.h> | 28 | #include <linux/fs.h> |
29 | #include <linux/if_ether.h> | 29 | #include <linux/if_ether.h> |
30 | #include <linux/if_vlan.h> | 30 | #include <linux/if_vlan.h> |
31 | #include <linux/jiffies.h> | 31 | #include <linux/jiffies.h> |
32 | #include <linux/kernel.h> | 32 | #include <linux/kernel.h> |
33 | #include <linux/kref.h> | 33 | #include <linux/kref.h> |
34 | #include <linux/list.h> | 34 | #include <linux/list.h> |
35 | #include <linux/lockdep.h> | 35 | #include <linux/lockdep.h> |
36 | #include <linux/netdevice.h> | 36 | #include <linux/netdevice.h> |
37 | #include <linux/percpu.h> | 37 | #include <linux/percpu.h> |
38 | #include <linux/printk.h> | 38 | #include <linux/printk.h> |
39 | #include <linux/random.h> | 39 | #include <linux/random.h> |
40 | #include <linux/rculist.h> | 40 | #include <linux/rculist.h> |
41 | #include <linux/rcupdate.h> | 41 | #include <linux/rcupdate.h> |
42 | #include <linux/skbuff.h> | 42 | #include <linux/skbuff.h> |
43 | #include <linux/slab.h> | 43 | #include <linux/slab.h> |
44 | #include <linux/socket.h> | 44 | #include <linux/socket.h> |
45 | #include <linux/spinlock.h> | 45 | #include <linux/spinlock.h> |
46 | #include <linux/stddef.h> | 46 | #include <linux/stddef.h> |
47 | #include <linux/string.h> | 47 | #include <linux/string.h> |
48 | #include <linux/types.h> | 48 | #include <linux/types.h> |
49 | #include <linux/workqueue.h> | 49 | #include <linux/workqueue.h> |
50 | 50 | ||
51 | #include "bridge_loop_avoidance.h" | 51 | #include "bridge_loop_avoidance.h" |
52 | #include "debugfs.h" | 52 | #include "debugfs.h" |
53 | #include "distributed-arp-table.h" | 53 | #include "distributed-arp-table.h" |
54 | #include "gateway_client.h" | 54 | #include "gateway_client.h" |
55 | #include "gateway_common.h" | 55 | #include "gateway_common.h" |
56 | #include "hard-interface.h" | 56 | #include "hard-interface.h" |
57 | #include "multicast.h" | 57 | #include "multicast.h" |
58 | #include "network-coding.h" | 58 | #include "network-coding.h" |
59 | #include "packet.h" | 59 | #include "packet.h" |
60 | #include "send.h" | 60 | #include "send.h" |
61 | #include "sysfs.h" | 61 | #include "sysfs.h" |
62 | #include "translation-table.h" | 62 | #include "translation-table.h" |
63 | 63 | ||
64 | static int batadv_get_settings(struct net_device *dev, struct ethtool_cmd *cmd); | 64 | static int batadv_get_settings(struct net_device *dev, struct ethtool_cmd *cmd); |
65 | static void batadv_get_drvinfo(struct net_device *dev, | 65 | static void batadv_get_drvinfo(struct net_device *dev, |
66 | struct ethtool_drvinfo *info); | 66 | struct ethtool_drvinfo *info); |
67 | static u32 batadv_get_msglevel(struct net_device *dev); | 67 | static u32 batadv_get_msglevel(struct net_device *dev); |
68 | static void batadv_set_msglevel(struct net_device *dev, u32 value); | 68 | static void batadv_set_msglevel(struct net_device *dev, u32 value); |
69 | static u32 batadv_get_link(struct net_device *dev); | 69 | static u32 batadv_get_link(struct net_device *dev); |
70 | static void batadv_get_strings(struct net_device *dev, u32 stringset, u8 *data); | 70 | static void batadv_get_strings(struct net_device *dev, u32 stringset, u8 *data); |
71 | static void batadv_get_ethtool_stats(struct net_device *dev, | 71 | static void batadv_get_ethtool_stats(struct net_device *dev, |
72 | struct ethtool_stats *stats, u64 *data); | 72 | struct ethtool_stats *stats, u64 *data); |
73 | static int batadv_get_sset_count(struct net_device *dev, int stringset); | 73 | static int batadv_get_sset_count(struct net_device *dev, int stringset); |
74 | 74 | ||
75 | static const struct ethtool_ops batadv_ethtool_ops = { | 75 | static const struct ethtool_ops batadv_ethtool_ops = { |
76 | .get_settings = batadv_get_settings, | 76 | .get_settings = batadv_get_settings, |
77 | .get_drvinfo = batadv_get_drvinfo, | 77 | .get_drvinfo = batadv_get_drvinfo, |
78 | .get_msglevel = batadv_get_msglevel, | 78 | .get_msglevel = batadv_get_msglevel, |
79 | .set_msglevel = batadv_set_msglevel, | 79 | .set_msglevel = batadv_set_msglevel, |
80 | .get_link = batadv_get_link, | 80 | .get_link = batadv_get_link, |
81 | .get_strings = batadv_get_strings, | 81 | .get_strings = batadv_get_strings, |
82 | .get_ethtool_stats = batadv_get_ethtool_stats, | 82 | .get_ethtool_stats = batadv_get_ethtool_stats, |
83 | .get_sset_count = batadv_get_sset_count, | 83 | .get_sset_count = batadv_get_sset_count, |
84 | }; | 84 | }; |
85 | 85 | ||
86 | int batadv_skb_head_push(struct sk_buff *skb, unsigned int len) | 86 | int batadv_skb_head_push(struct sk_buff *skb, unsigned int len) |
87 | { | 87 | { |
88 | int result; | 88 | int result; |
89 | 89 | ||
90 | /* TODO: We must check if we can release all references to non-payload | 90 | /* TODO: We must check if we can release all references to non-payload |
91 | * data using skb_header_release in our skbs to allow skb_cow_header to | 91 | * data using skb_header_release in our skbs to allow skb_cow_header to |
92 | * work optimally. This means that those skbs are not allowed to read | 92 | * work optimally. This means that those skbs are not allowed to read |
93 | * or write any data which is before the current position of skb->data | 93 | * or write any data which is before the current position of skb->data |
94 | * after that call and thus allow other skbs with the same data buffer | 94 | * after that call and thus allow other skbs with the same data buffer |
95 | * to write freely in that area. | 95 | * to write freely in that area. |
96 | */ | 96 | */ |
97 | result = skb_cow_head(skb, len); | 97 | result = skb_cow_head(skb, len); |
98 | if (result < 0) | 98 | if (result < 0) |
99 | return result; | 99 | return result; |
100 | 100 | ||
101 | skb_push(skb, len); | 101 | skb_push(skb, len); |
102 | return 0; | 102 | return 0; |
103 | } | 103 | } |
104 | 104 | ||
105 | static int batadv_interface_open(struct net_device *dev) | 105 | static int batadv_interface_open(struct net_device *dev) |
106 | { | 106 | { |
107 | netif_start_queue(dev); | 107 | netif_start_queue(dev); |
108 | return 0; | 108 | return 0; |
109 | } | 109 | } |
110 | 110 | ||
111 | static int batadv_interface_release(struct net_device *dev) | 111 | static int batadv_interface_release(struct net_device *dev) |
112 | { | 112 | { |
113 | netif_stop_queue(dev); | 113 | netif_stop_queue(dev); |
114 | return 0; | 114 | return 0; |
115 | } | 115 | } |
116 | 116 | ||
117 | static struct net_device_stats *batadv_interface_stats(struct net_device *dev) | 117 | static struct net_device_stats *batadv_interface_stats(struct net_device *dev) |
118 | { | 118 | { |
119 | struct batadv_priv *bat_priv = netdev_priv(dev); | 119 | struct batadv_priv *bat_priv = netdev_priv(dev); |
120 | struct net_device_stats *stats = &bat_priv->stats; | 120 | struct net_device_stats *stats = &bat_priv->stats; |
121 | 121 | ||
122 | stats->tx_packets = batadv_sum_counter(bat_priv, BATADV_CNT_TX); | 122 | stats->tx_packets = batadv_sum_counter(bat_priv, BATADV_CNT_TX); |
123 | stats->tx_bytes = batadv_sum_counter(bat_priv, BATADV_CNT_TX_BYTES); | 123 | stats->tx_bytes = batadv_sum_counter(bat_priv, BATADV_CNT_TX_BYTES); |
124 | stats->tx_dropped = batadv_sum_counter(bat_priv, BATADV_CNT_TX_DROPPED); | 124 | stats->tx_dropped = batadv_sum_counter(bat_priv, BATADV_CNT_TX_DROPPED); |
125 | stats->rx_packets = batadv_sum_counter(bat_priv, BATADV_CNT_RX); | 125 | stats->rx_packets = batadv_sum_counter(bat_priv, BATADV_CNT_RX); |
126 | stats->rx_bytes = batadv_sum_counter(bat_priv, BATADV_CNT_RX_BYTES); | 126 | stats->rx_bytes = batadv_sum_counter(bat_priv, BATADV_CNT_RX_BYTES); |
127 | return stats; | 127 | return stats; |
128 | } | 128 | } |
129 | 129 | ||
130 | static int batadv_interface_set_mac_addr(struct net_device *dev, void *p) | 130 | static int batadv_interface_set_mac_addr(struct net_device *dev, void *p) |
131 | { | 131 | { |
132 | struct batadv_priv *bat_priv = netdev_priv(dev); | 132 | struct batadv_priv *bat_priv = netdev_priv(dev); |
133 | struct batadv_softif_vlan *vlan; | 133 | struct batadv_softif_vlan *vlan; |
134 | struct sockaddr *addr = p; | 134 | struct sockaddr *addr = p; |
135 | u8 old_addr[ETH_ALEN]; | 135 | u8 old_addr[ETH_ALEN]; |
136 | 136 | ||
137 | if (!is_valid_ether_addr(addr->sa_data)) | 137 | if (!is_valid_ether_addr(addr->sa_data)) |
138 | return -EADDRNOTAVAIL; | 138 | return -EADDRNOTAVAIL; |
139 | 139 | ||
140 | ether_addr_copy(old_addr, dev->dev_addr); | 140 | ether_addr_copy(old_addr, dev->dev_addr); |
141 | ether_addr_copy(dev->dev_addr, addr->sa_data); | 141 | ether_addr_copy(dev->dev_addr, addr->sa_data); |
142 | 142 | ||
143 | /* only modify transtable if it has been initialized before */ | 143 | /* only modify transtable if it has been initialized before */ |
144 | if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE) | 144 | if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE) |
145 | return 0; | 145 | return 0; |
146 | 146 | ||
147 | rcu_read_lock(); | 147 | rcu_read_lock(); |
148 | hlist_for_each_entry_rcu(vlan, &bat_priv->softif_vlan_list, list) { | 148 | hlist_for_each_entry_rcu(vlan, &bat_priv->softif_vlan_list, list) { |
149 | batadv_tt_local_remove(bat_priv, old_addr, vlan->vid, | 149 | batadv_tt_local_remove(bat_priv, old_addr, vlan->vid, |
150 | "mac address changed", false); | 150 | "mac address changed", false); |
151 | batadv_tt_local_add(dev, addr->sa_data, vlan->vid, | 151 | batadv_tt_local_add(dev, addr->sa_data, vlan->vid, |
152 | BATADV_NULL_IFINDEX, BATADV_NO_MARK); | 152 | BATADV_NULL_IFINDEX, BATADV_NO_MARK); |
153 | } | 153 | } |
154 | rcu_read_unlock(); | 154 | rcu_read_unlock(); |
155 | 155 | ||
156 | return 0; | 156 | return 0; |
157 | } | 157 | } |
158 | 158 | ||
159 | static int batadv_interface_change_mtu(struct net_device *dev, int new_mtu) | 159 | static int batadv_interface_change_mtu(struct net_device *dev, int new_mtu) |
160 | { | 160 | { |
161 | /* check ranges */ | 161 | /* check ranges */ |
162 | if ((new_mtu < 68) || (new_mtu > batadv_hardif_min_mtu(dev))) | 162 | if ((new_mtu < 68) || (new_mtu > batadv_hardif_min_mtu(dev))) |
163 | return -EINVAL; | 163 | return -EINVAL; |
164 | 164 | ||
165 | dev->mtu = new_mtu; | 165 | dev->mtu = new_mtu; |
166 | 166 | ||
167 | return 0; | 167 | return 0; |
168 | } | 168 | } |
169 | 169 | ||
170 | /** | 170 | /** |
171 | * batadv_interface_set_rx_mode - set the rx mode of a device | 171 | * batadv_interface_set_rx_mode - set the rx mode of a device |
172 | * @dev: registered network device to modify | 172 | * @dev: registered network device to modify |
173 | * | 173 | * |
174 | * We do not actually need to set any rx filters for the virtual batman | 174 | * We do not actually need to set any rx filters for the virtual batman |
175 | * soft interface. However a dummy handler enables a user to set static | 175 | * soft interface. However a dummy handler enables a user to set static |
176 | * multicast listeners for instance. | 176 | * multicast listeners for instance. |
177 | */ | 177 | */ |
178 | static void batadv_interface_set_rx_mode(struct net_device *dev) | 178 | static void batadv_interface_set_rx_mode(struct net_device *dev) |
179 | { | 179 | { |
180 | } | 180 | } |
181 | 181 | ||
182 | static int batadv_interface_tx(struct sk_buff *skb, | 182 | static int batadv_interface_tx(struct sk_buff *skb, |
183 | struct net_device *soft_iface) | 183 | struct net_device *soft_iface) |
184 | { | 184 | { |
185 | struct ethhdr *ethhdr; | 185 | struct ethhdr *ethhdr; |
186 | struct batadv_priv *bat_priv = netdev_priv(soft_iface); | 186 | struct batadv_priv *bat_priv = netdev_priv(soft_iface); |
187 | struct batadv_hard_iface *primary_if = NULL; | 187 | struct batadv_hard_iface *primary_if = NULL; |
188 | struct batadv_bcast_packet *bcast_packet; | 188 | struct batadv_bcast_packet *bcast_packet; |
189 | static const u8 stp_addr[ETH_ALEN] = {0x01, 0x80, 0xC2, 0x00, | 189 | static const u8 stp_addr[ETH_ALEN] = {0x01, 0x80, 0xC2, 0x00, |
190 | 0x00, 0x00}; | 190 | 0x00, 0x00}; |
191 | static const u8 ectp_addr[ETH_ALEN] = {0xCF, 0x00, 0x00, 0x00, | 191 | static const u8 ectp_addr[ETH_ALEN] = {0xCF, 0x00, 0x00, 0x00, |
192 | 0x00, 0x00}; | 192 | 0x00, 0x00}; |
193 | enum batadv_dhcp_recipient dhcp_rcp = BATADV_DHCP_NO; | 193 | enum batadv_dhcp_recipient dhcp_rcp = BATADV_DHCP_NO; |
194 | u8 *dst_hint = NULL, chaddr[ETH_ALEN]; | 194 | u8 *dst_hint = NULL, chaddr[ETH_ALEN]; |
195 | struct vlan_ethhdr *vhdr; | 195 | struct vlan_ethhdr *vhdr; |
196 | unsigned int header_len = 0; | 196 | unsigned int header_len = 0; |
197 | int data_len = skb->len, ret; | 197 | int data_len = skb->len, ret; |
198 | unsigned long brd_delay = 1; | 198 | unsigned long brd_delay = 1; |
199 | bool do_bcast = false, client_added; | 199 | bool do_bcast = false, client_added; |
200 | unsigned short vid; | 200 | unsigned short vid; |
201 | u32 seqno; | 201 | u32 seqno; |
202 | int gw_mode; | 202 | int gw_mode; |
203 | enum batadv_forw_mode forw_mode; | 203 | enum batadv_forw_mode forw_mode; |
204 | struct batadv_orig_node *mcast_single_orig = NULL; | 204 | struct batadv_orig_node *mcast_single_orig = NULL; |
205 | int network_offset = ETH_HLEN; | 205 | int network_offset = ETH_HLEN; |
206 | 206 | ||
207 | if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE) | 207 | if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE) |
208 | goto dropped; | 208 | goto dropped; |
209 | 209 | ||
210 | netif_trans_update(soft_iface); | 210 | netif_trans_update(soft_iface); |
211 | vid = batadv_get_vid(skb, 0); | 211 | vid = batadv_get_vid(skb, 0); |
212 | ethhdr = eth_hdr(skb); | 212 | ethhdr = eth_hdr(skb); |
213 | 213 | ||
214 | switch (ntohs(ethhdr->h_proto)) { | 214 | switch (ntohs(ethhdr->h_proto)) { |
215 | case ETH_P_8021Q: | 215 | case ETH_P_8021Q: |
216 | vhdr = vlan_eth_hdr(skb); | 216 | vhdr = vlan_eth_hdr(skb); |
217 | 217 | ||
218 | /* drop batman-in-batman packets to prevent loops */ | 218 | /* drop batman-in-batman packets to prevent loops */ |
219 | if (vhdr->h_vlan_encapsulated_proto != htons(ETH_P_BATMAN)) { | 219 | if (vhdr->h_vlan_encapsulated_proto != htons(ETH_P_BATMAN)) { |
220 | network_offset += VLAN_HLEN; | 220 | network_offset += VLAN_HLEN; |
221 | break; | 221 | break; |
222 | } | 222 | } |
223 | 223 | ||
224 | /* fall through */ | 224 | /* fall through */ |
225 | case ETH_P_BATMAN: | 225 | case ETH_P_BATMAN: |
226 | goto dropped; | 226 | goto dropped; |
227 | } | 227 | } |
228 | 228 | ||
229 | skb_set_network_header(skb, network_offset); | 229 | skb_set_network_header(skb, network_offset); |
230 | 230 | ||
231 | if (batadv_bla_tx(bat_priv, skb, vid)) | 231 | if (batadv_bla_tx(bat_priv, skb, vid)) |
232 | goto dropped; | 232 | goto dropped; |
233 | 233 | ||
234 | /* skb->data might have been reallocated by batadv_bla_tx() */ | 234 | /* skb->data might have been reallocated by batadv_bla_tx() */ |
235 | ethhdr = eth_hdr(skb); | 235 | ethhdr = eth_hdr(skb); |
236 | 236 | ||
237 | /* Register the client MAC in the transtable */ | 237 | /* Register the client MAC in the transtable */ |
238 | if (!is_multicast_ether_addr(ethhdr->h_source)) { | 238 | if (!is_multicast_ether_addr(ethhdr->h_source)) { |
239 | client_added = batadv_tt_local_add(soft_iface, ethhdr->h_source, | 239 | client_added = batadv_tt_local_add(soft_iface, ethhdr->h_source, |
240 | vid, skb->skb_iif, | 240 | vid, skb->skb_iif, |
241 | skb->mark); | 241 | skb->mark); |
242 | if (!client_added) | 242 | if (!client_added) |
243 | goto dropped; | 243 | goto dropped; |
244 | } | 244 | } |
245 | 245 | ||
246 | /* don't accept stp packets. STP does not help in meshes. | 246 | /* don't accept stp packets. STP does not help in meshes. |
247 | * better use the bridge loop avoidance ... | 247 | * better use the bridge loop avoidance ... |
248 | * | 248 | * |
249 | * The same goes for ECTP sent at least by some Cisco Switches, | 249 | * The same goes for ECTP sent at least by some Cisco Switches, |
250 | * it might confuse the mesh when used with bridge loop avoidance. | 250 | * it might confuse the mesh when used with bridge loop avoidance. |
251 | */ | 251 | */ |
252 | if (batadv_compare_eth(ethhdr->h_dest, stp_addr)) | 252 | if (batadv_compare_eth(ethhdr->h_dest, stp_addr)) |
253 | goto dropped; | 253 | goto dropped; |
254 | 254 | ||
255 | if (batadv_compare_eth(ethhdr->h_dest, ectp_addr)) | 255 | if (batadv_compare_eth(ethhdr->h_dest, ectp_addr)) |
256 | goto dropped; | 256 | goto dropped; |
257 | 257 | ||
258 | gw_mode = atomic_read(&bat_priv->gw_mode); | 258 | gw_mode = atomic_read(&bat_priv->gw.mode); |
259 | if (is_multicast_ether_addr(ethhdr->h_dest)) { | 259 | if (is_multicast_ether_addr(ethhdr->h_dest)) { |
260 | /* if gw mode is off, broadcast every packet */ | 260 | /* if gw mode is off, broadcast every packet */ |
261 | if (gw_mode == BATADV_GW_MODE_OFF) { | 261 | if (gw_mode == BATADV_GW_MODE_OFF) { |
262 | do_bcast = true; | 262 | do_bcast = true; |
263 | goto send; | 263 | goto send; |
264 | } | 264 | } |
265 | 265 | ||
266 | dhcp_rcp = batadv_gw_dhcp_recipient_get(skb, &header_len, | 266 | dhcp_rcp = batadv_gw_dhcp_recipient_get(skb, &header_len, |
267 | chaddr); | 267 | chaddr); |
268 | /* skb->data may have been modified by | 268 | /* skb->data may have been modified by |
269 | * batadv_gw_dhcp_recipient_get() | 269 | * batadv_gw_dhcp_recipient_get() |
270 | */ | 270 | */ |
271 | ethhdr = eth_hdr(skb); | 271 | ethhdr = eth_hdr(skb); |
272 | /* if gw_mode is on, broadcast any non-DHCP message. | 272 | /* if gw_mode is on, broadcast any non-DHCP message. |
273 | * All the DHCP packets are going to be sent as unicast | 273 | * All the DHCP packets are going to be sent as unicast |
274 | */ | 274 | */ |
275 | if (dhcp_rcp == BATADV_DHCP_NO) { | 275 | if (dhcp_rcp == BATADV_DHCP_NO) { |
276 | do_bcast = true; | 276 | do_bcast = true; |
277 | goto send; | 277 | goto send; |
278 | } | 278 | } |
279 | 279 | ||
280 | if (dhcp_rcp == BATADV_DHCP_TO_CLIENT) | 280 | if (dhcp_rcp == BATADV_DHCP_TO_CLIENT) |
281 | dst_hint = chaddr; | 281 | dst_hint = chaddr; |
282 | else if ((gw_mode == BATADV_GW_MODE_SERVER) && | 282 | else if ((gw_mode == BATADV_GW_MODE_SERVER) && |
283 | (dhcp_rcp == BATADV_DHCP_TO_SERVER)) | 283 | (dhcp_rcp == BATADV_DHCP_TO_SERVER)) |
284 | /* gateways should not forward any DHCP message if | 284 | /* gateways should not forward any DHCP message if |
285 | * directed to a DHCP server | 285 | * directed to a DHCP server |
286 | */ | 286 | */ |
287 | goto dropped; | 287 | goto dropped; |
288 | 288 | ||
289 | send: | 289 | send: |
290 | if (do_bcast && !is_broadcast_ether_addr(ethhdr->h_dest)) { | 290 | if (do_bcast && !is_broadcast_ether_addr(ethhdr->h_dest)) { |
291 | forw_mode = batadv_mcast_forw_mode(bat_priv, skb, | 291 | forw_mode = batadv_mcast_forw_mode(bat_priv, skb, |
292 | &mcast_single_orig); | 292 | &mcast_single_orig); |
293 | if (forw_mode == BATADV_FORW_NONE) | 293 | if (forw_mode == BATADV_FORW_NONE) |
294 | goto dropped; | 294 | goto dropped; |
295 | 295 | ||
296 | if (forw_mode == BATADV_FORW_SINGLE) | 296 | if (forw_mode == BATADV_FORW_SINGLE) |
297 | do_bcast = false; | 297 | do_bcast = false; |
298 | } | 298 | } |
299 | } | 299 | } |
300 | 300 | ||
301 | batadv_skb_set_priority(skb, 0); | 301 | batadv_skb_set_priority(skb, 0); |
302 | 302 | ||
303 | /* ethernet packet should be broadcasted */ | 303 | /* ethernet packet should be broadcasted */ |
304 | if (do_bcast) { | 304 | if (do_bcast) { |
305 | primary_if = batadv_primary_if_get_selected(bat_priv); | 305 | primary_if = batadv_primary_if_get_selected(bat_priv); |
306 | if (!primary_if) | 306 | if (!primary_if) |
307 | goto dropped; | 307 | goto dropped; |
308 | 308 | ||
309 | /* in case of ARP request, we do not immediately broadcasti the | 309 | /* in case of ARP request, we do not immediately broadcasti the |
310 | * packet, instead we first wait for DAT to try to retrieve the | 310 | * packet, instead we first wait for DAT to try to retrieve the |
311 | * correct ARP entry | 311 | * correct ARP entry |
312 | */ | 312 | */ |
313 | if (batadv_dat_snoop_outgoing_arp_request(bat_priv, skb)) | 313 | if (batadv_dat_snoop_outgoing_arp_request(bat_priv, skb)) |
314 | brd_delay = msecs_to_jiffies(ARP_REQ_DELAY); | 314 | brd_delay = msecs_to_jiffies(ARP_REQ_DELAY); |
315 | 315 | ||
316 | if (batadv_skb_head_push(skb, sizeof(*bcast_packet)) < 0) | 316 | if (batadv_skb_head_push(skb, sizeof(*bcast_packet)) < 0) |
317 | goto dropped; | 317 | goto dropped; |
318 | 318 | ||
319 | bcast_packet = (struct batadv_bcast_packet *)skb->data; | 319 | bcast_packet = (struct batadv_bcast_packet *)skb->data; |
320 | bcast_packet->version = BATADV_COMPAT_VERSION; | 320 | bcast_packet->version = BATADV_COMPAT_VERSION; |
321 | bcast_packet->ttl = BATADV_TTL; | 321 | bcast_packet->ttl = BATADV_TTL; |
322 | 322 | ||
323 | /* batman packet type: broadcast */ | 323 | /* batman packet type: broadcast */ |
324 | bcast_packet->packet_type = BATADV_BCAST; | 324 | bcast_packet->packet_type = BATADV_BCAST; |
325 | bcast_packet->reserved = 0; | 325 | bcast_packet->reserved = 0; |
326 | 326 | ||
327 | /* hw address of first interface is the orig mac because only | 327 | /* hw address of first interface is the orig mac because only |
328 | * this mac is known throughout the mesh | 328 | * this mac is known throughout the mesh |
329 | */ | 329 | */ |
330 | ether_addr_copy(bcast_packet->orig, | 330 | ether_addr_copy(bcast_packet->orig, |
331 | primary_if->net_dev->dev_addr); | 331 | primary_if->net_dev->dev_addr); |
332 | 332 | ||
333 | /* set broadcast sequence number */ | 333 | /* set broadcast sequence number */ |
334 | seqno = atomic_inc_return(&bat_priv->bcast_seqno); | 334 | seqno = atomic_inc_return(&bat_priv->bcast_seqno); |
335 | bcast_packet->seqno = htonl(seqno); | 335 | bcast_packet->seqno = htonl(seqno); |
336 | 336 | ||
337 | batadv_add_bcast_packet_to_list(bat_priv, skb, brd_delay); | 337 | batadv_add_bcast_packet_to_list(bat_priv, skb, brd_delay); |
338 | 338 | ||
339 | /* a copy is stored in the bcast list, therefore removing | 339 | /* a copy is stored in the bcast list, therefore removing |
340 | * the original skb. | 340 | * the original skb. |
341 | */ | 341 | */ |
342 | kfree_skb(skb); | 342 | kfree_skb(skb); |
343 | 343 | ||
344 | /* unicast packet */ | 344 | /* unicast packet */ |
345 | } else { | 345 | } else { |
346 | /* DHCP packets going to a server will use the GW feature */ | 346 | /* DHCP packets going to a server will use the GW feature */ |
347 | if (dhcp_rcp == BATADV_DHCP_TO_SERVER) { | 347 | if (dhcp_rcp == BATADV_DHCP_TO_SERVER) { |
348 | ret = batadv_gw_out_of_range(bat_priv, skb); | 348 | ret = batadv_gw_out_of_range(bat_priv, skb); |
349 | if (ret) | 349 | if (ret) |
350 | goto dropped; | 350 | goto dropped; |
351 | ret = batadv_send_skb_via_gw(bat_priv, skb, vid); | 351 | ret = batadv_send_skb_via_gw(bat_priv, skb, vid); |
352 | } else if (mcast_single_orig) { | 352 | } else if (mcast_single_orig) { |
353 | ret = batadv_send_skb_unicast(bat_priv, skb, | 353 | ret = batadv_send_skb_unicast(bat_priv, skb, |
354 | BATADV_UNICAST, 0, | 354 | BATADV_UNICAST, 0, |
355 | mcast_single_orig, vid); | 355 | mcast_single_orig, vid); |
356 | } else { | 356 | } else { |
357 | if (batadv_dat_snoop_outgoing_arp_request(bat_priv, | 357 | if (batadv_dat_snoop_outgoing_arp_request(bat_priv, |
358 | skb)) | 358 | skb)) |
359 | goto dropped; | 359 | goto dropped; |
360 | 360 | ||
361 | batadv_dat_snoop_outgoing_arp_reply(bat_priv, skb); | 361 | batadv_dat_snoop_outgoing_arp_reply(bat_priv, skb); |
362 | 362 | ||
363 | ret = batadv_send_skb_via_tt(bat_priv, skb, dst_hint, | 363 | ret = batadv_send_skb_via_tt(bat_priv, skb, dst_hint, |
364 | vid); | 364 | vid); |
365 | } | 365 | } |
366 | if (ret == NET_XMIT_DROP) | 366 | if (ret == NET_XMIT_DROP) |
367 | goto dropped_freed; | 367 | goto dropped_freed; |
368 | } | 368 | } |
369 | 369 | ||
370 | batadv_inc_counter(bat_priv, BATADV_CNT_TX); | 370 | batadv_inc_counter(bat_priv, BATADV_CNT_TX); |
371 | batadv_add_counter(bat_priv, BATADV_CNT_TX_BYTES, data_len); | 371 | batadv_add_counter(bat_priv, BATADV_CNT_TX_BYTES, data_len); |
372 | goto end; | 372 | goto end; |
373 | 373 | ||
374 | dropped: | 374 | dropped: |
375 | kfree_skb(skb); | 375 | kfree_skb(skb); |
376 | dropped_freed: | 376 | dropped_freed: |
377 | batadv_inc_counter(bat_priv, BATADV_CNT_TX_DROPPED); | 377 | batadv_inc_counter(bat_priv, BATADV_CNT_TX_DROPPED); |
378 | end: | 378 | end: |
379 | if (primary_if) | 379 | if (primary_if) |
380 | batadv_hardif_put(primary_if); | 380 | batadv_hardif_put(primary_if); |
381 | return NETDEV_TX_OK; | 381 | return NETDEV_TX_OK; |
382 | } | 382 | } |
383 | 383 | ||
384 | /** | 384 | /** |
385 | * batadv_interface_rx - receive ethernet frame on local batman-adv interface | 385 | * batadv_interface_rx - receive ethernet frame on local batman-adv interface |
386 | * @soft_iface: local interface which will receive the ethernet frame | 386 | * @soft_iface: local interface which will receive the ethernet frame |
387 | * @skb: ethernet frame for @soft_iface | 387 | * @skb: ethernet frame for @soft_iface |
388 | * @hdr_size: size of already parsed batman-adv header | 388 | * @hdr_size: size of already parsed batman-adv header |
389 | * @orig_node: originator from which the batman-adv packet was sent | 389 | * @orig_node: originator from which the batman-adv packet was sent |
390 | * | 390 | * |
391 | * Sends a ethernet frame to the receive path of the local @soft_iface. | 391 | * Sends a ethernet frame to the receive path of the local @soft_iface. |
392 | * skb->data has still point to the batman-adv header with the size @hdr_size. | 392 | * skb->data has still point to the batman-adv header with the size @hdr_size. |
393 | * The caller has to have parsed this header already and made sure that at least | 393 | * The caller has to have parsed this header already and made sure that at least |
394 | * @hdr_size bytes are still available for pull in @skb. | 394 | * @hdr_size bytes are still available for pull in @skb. |
395 | * | 395 | * |
396 | * The packet may still get dropped. This can happen when the encapsulated | 396 | * The packet may still get dropped. This can happen when the encapsulated |
397 | * ethernet frame is invalid or contains again an batman-adv packet. Also | 397 | * ethernet frame is invalid or contains again an batman-adv packet. Also |
398 | * unicast packets will be dropped directly when it was sent between two | 398 | * unicast packets will be dropped directly when it was sent between two |
399 | * isolated clients. | 399 | * isolated clients. |
400 | */ | 400 | */ |
401 | void batadv_interface_rx(struct net_device *soft_iface, | 401 | void batadv_interface_rx(struct net_device *soft_iface, |
402 | struct sk_buff *skb, int hdr_size, | 402 | struct sk_buff *skb, int hdr_size, |
403 | struct batadv_orig_node *orig_node) | 403 | struct batadv_orig_node *orig_node) |
404 | { | 404 | { |
405 | struct batadv_bcast_packet *batadv_bcast_packet; | 405 | struct batadv_bcast_packet *batadv_bcast_packet; |
406 | struct batadv_priv *bat_priv = netdev_priv(soft_iface); | 406 | struct batadv_priv *bat_priv = netdev_priv(soft_iface); |
407 | struct vlan_ethhdr *vhdr; | 407 | struct vlan_ethhdr *vhdr; |
408 | struct ethhdr *ethhdr; | 408 | struct ethhdr *ethhdr; |
409 | unsigned short vid; | 409 | unsigned short vid; |
410 | bool is_bcast; | 410 | bool is_bcast; |
411 | 411 | ||
412 | batadv_bcast_packet = (struct batadv_bcast_packet *)skb->data; | 412 | batadv_bcast_packet = (struct batadv_bcast_packet *)skb->data; |
413 | is_bcast = (batadv_bcast_packet->packet_type == BATADV_BCAST); | 413 | is_bcast = (batadv_bcast_packet->packet_type == BATADV_BCAST); |
414 | 414 | ||
415 | skb_pull_rcsum(skb, hdr_size); | 415 | skb_pull_rcsum(skb, hdr_size); |
416 | skb_reset_mac_header(skb); | 416 | skb_reset_mac_header(skb); |
417 | 417 | ||
418 | /* clean the netfilter state now that the batman-adv header has been | 418 | /* clean the netfilter state now that the batman-adv header has been |
419 | * removed | 419 | * removed |
420 | */ | 420 | */ |
421 | nf_reset(skb); | 421 | nf_reset(skb); |
422 | 422 | ||
423 | if (unlikely(!pskb_may_pull(skb, ETH_HLEN))) | 423 | if (unlikely(!pskb_may_pull(skb, ETH_HLEN))) |
424 | goto dropped; | 424 | goto dropped; |
425 | 425 | ||
426 | vid = batadv_get_vid(skb, 0); | 426 | vid = batadv_get_vid(skb, 0); |
427 | ethhdr = eth_hdr(skb); | 427 | ethhdr = eth_hdr(skb); |
428 | 428 | ||
429 | switch (ntohs(ethhdr->h_proto)) { | 429 | switch (ntohs(ethhdr->h_proto)) { |
430 | case ETH_P_8021Q: | 430 | case ETH_P_8021Q: |
431 | if (!pskb_may_pull(skb, VLAN_ETH_HLEN)) | 431 | if (!pskb_may_pull(skb, VLAN_ETH_HLEN)) |
432 | goto dropped; | 432 | goto dropped; |
433 | 433 | ||
434 | vhdr = (struct vlan_ethhdr *)skb->data; | 434 | vhdr = (struct vlan_ethhdr *)skb->data; |
435 | 435 | ||
436 | /* drop batman-in-batman packets to prevent loops */ | 436 | /* drop batman-in-batman packets to prevent loops */ |
437 | if (vhdr->h_vlan_encapsulated_proto != htons(ETH_P_BATMAN)) | 437 | if (vhdr->h_vlan_encapsulated_proto != htons(ETH_P_BATMAN)) |
438 | break; | 438 | break; |
439 | 439 | ||
440 | /* fall through */ | 440 | /* fall through */ |
441 | case ETH_P_BATMAN: | 441 | case ETH_P_BATMAN: |
442 | goto dropped; | 442 | goto dropped; |
443 | } | 443 | } |
444 | 444 | ||
445 | /* skb->dev & skb->pkt_type are set here */ | 445 | /* skb->dev & skb->pkt_type are set here */ |
446 | skb->protocol = eth_type_trans(skb, soft_iface); | 446 | skb->protocol = eth_type_trans(skb, soft_iface); |
447 | 447 | ||
448 | /* should not be necessary anymore as we use skb_pull_rcsum() | 448 | /* should not be necessary anymore as we use skb_pull_rcsum() |
449 | * TODO: please verify this and remove this TODO | 449 | * TODO: please verify this and remove this TODO |
450 | * -- Dec 21st 2009, Simon Wunderlich | 450 | * -- Dec 21st 2009, Simon Wunderlich |
451 | */ | 451 | */ |
452 | 452 | ||
453 | /* skb->ip_summed = CHECKSUM_UNNECESSARY; */ | 453 | /* skb->ip_summed = CHECKSUM_UNNECESSARY; */ |
454 | 454 | ||
455 | batadv_inc_counter(bat_priv, BATADV_CNT_RX); | 455 | batadv_inc_counter(bat_priv, BATADV_CNT_RX); |
456 | batadv_add_counter(bat_priv, BATADV_CNT_RX_BYTES, | 456 | batadv_add_counter(bat_priv, BATADV_CNT_RX_BYTES, |
457 | skb->len + ETH_HLEN); | 457 | skb->len + ETH_HLEN); |
458 | 458 | ||
459 | soft_iface->last_rx = jiffies; | 459 | soft_iface->last_rx = jiffies; |
460 | 460 | ||
461 | /* Let the bridge loop avoidance check the packet. If will | 461 | /* Let the bridge loop avoidance check the packet. If will |
462 | * not handle it, we can safely push it up. | 462 | * not handle it, we can safely push it up. |
463 | */ | 463 | */ |
464 | if (batadv_bla_rx(bat_priv, skb, vid, is_bcast)) | 464 | if (batadv_bla_rx(bat_priv, skb, vid, is_bcast)) |
465 | goto out; | 465 | goto out; |
466 | 466 | ||
467 | if (orig_node) | 467 | if (orig_node) |
468 | batadv_tt_add_temporary_global_entry(bat_priv, orig_node, | 468 | batadv_tt_add_temporary_global_entry(bat_priv, orig_node, |
469 | ethhdr->h_source, vid); | 469 | ethhdr->h_source, vid); |
470 | 470 | ||
471 | if (is_multicast_ether_addr(ethhdr->h_dest)) { | 471 | if (is_multicast_ether_addr(ethhdr->h_dest)) { |
472 | /* set the mark on broadcast packets if AP isolation is ON and | 472 | /* set the mark on broadcast packets if AP isolation is ON and |
473 | * the packet is coming from an "isolated" client | 473 | * the packet is coming from an "isolated" client |
474 | */ | 474 | */ |
475 | if (batadv_vlan_ap_isola_get(bat_priv, vid) && | 475 | if (batadv_vlan_ap_isola_get(bat_priv, vid) && |
476 | batadv_tt_global_is_isolated(bat_priv, ethhdr->h_source, | 476 | batadv_tt_global_is_isolated(bat_priv, ethhdr->h_source, |
477 | vid)) { | 477 | vid)) { |
478 | /* save bits in skb->mark not covered by the mask and | 478 | /* save bits in skb->mark not covered by the mask and |
479 | * apply the mark on the rest | 479 | * apply the mark on the rest |
480 | */ | 480 | */ |
481 | skb->mark &= ~bat_priv->isolation_mark_mask; | 481 | skb->mark &= ~bat_priv->isolation_mark_mask; |
482 | skb->mark |= bat_priv->isolation_mark; | 482 | skb->mark |= bat_priv->isolation_mark; |
483 | } | 483 | } |
484 | } else if (batadv_is_ap_isolated(bat_priv, ethhdr->h_source, | 484 | } else if (batadv_is_ap_isolated(bat_priv, ethhdr->h_source, |
485 | ethhdr->h_dest, vid)) { | 485 | ethhdr->h_dest, vid)) { |
486 | goto dropped; | 486 | goto dropped; |
487 | } | 487 | } |
488 | 488 | ||
489 | netif_rx(skb); | 489 | netif_rx(skb); |
490 | goto out; | 490 | goto out; |
491 | 491 | ||
492 | dropped: | 492 | dropped: |
493 | kfree_skb(skb); | 493 | kfree_skb(skb); |
494 | out: | 494 | out: |
495 | return; | 495 | return; |
496 | } | 496 | } |
497 | 497 | ||
498 | /** | 498 | /** |
499 | * batadv_softif_vlan_release - release vlan from lists and queue for free after | 499 | * batadv_softif_vlan_release - release vlan from lists and queue for free after |
500 | * rcu grace period | 500 | * rcu grace period |
501 | * @ref: kref pointer of the vlan object | 501 | * @ref: kref pointer of the vlan object |
502 | */ | 502 | */ |
503 | static void batadv_softif_vlan_release(struct kref *ref) | 503 | static void batadv_softif_vlan_release(struct kref *ref) |
504 | { | 504 | { |
505 | struct batadv_softif_vlan *vlan; | 505 | struct batadv_softif_vlan *vlan; |
506 | 506 | ||
507 | vlan = container_of(ref, struct batadv_softif_vlan, refcount); | 507 | vlan = container_of(ref, struct batadv_softif_vlan, refcount); |
508 | 508 | ||
509 | spin_lock_bh(&vlan->bat_priv->softif_vlan_list_lock); | 509 | spin_lock_bh(&vlan->bat_priv->softif_vlan_list_lock); |
510 | hlist_del_rcu(&vlan->list); | 510 | hlist_del_rcu(&vlan->list); |
511 | spin_unlock_bh(&vlan->bat_priv->softif_vlan_list_lock); | 511 | spin_unlock_bh(&vlan->bat_priv->softif_vlan_list_lock); |
512 | 512 | ||
513 | kfree_rcu(vlan, rcu); | 513 | kfree_rcu(vlan, rcu); |
514 | } | 514 | } |
515 | 515 | ||
516 | /** | 516 | /** |
517 | * batadv_softif_vlan_put - decrease the vlan object refcounter and | 517 | * batadv_softif_vlan_put - decrease the vlan object refcounter and |
518 | * possibly release it | 518 | * possibly release it |
519 | * @vlan: the vlan object to release | 519 | * @vlan: the vlan object to release |
520 | */ | 520 | */ |
521 | void batadv_softif_vlan_put(struct batadv_softif_vlan *vlan) | 521 | void batadv_softif_vlan_put(struct batadv_softif_vlan *vlan) |
522 | { | 522 | { |
523 | if (!vlan) | 523 | if (!vlan) |
524 | return; | 524 | return; |
525 | 525 | ||
526 | kref_put(&vlan->refcount, batadv_softif_vlan_release); | 526 | kref_put(&vlan->refcount, batadv_softif_vlan_release); |
527 | } | 527 | } |
528 | 528 | ||
529 | /** | 529 | /** |
530 | * batadv_softif_vlan_get - get the vlan object for a specific vid | 530 | * batadv_softif_vlan_get - get the vlan object for a specific vid |
531 | * @bat_priv: the bat priv with all the soft interface information | 531 | * @bat_priv: the bat priv with all the soft interface information |
532 | * @vid: the identifier of the vlan object to retrieve | 532 | * @vid: the identifier of the vlan object to retrieve |
533 | * | 533 | * |
534 | * Return: the private data of the vlan matching the vid passed as argument or | 534 | * Return: the private data of the vlan matching the vid passed as argument or |
535 | * NULL otherwise. The refcounter of the returned object is incremented by 1. | 535 | * NULL otherwise. The refcounter of the returned object is incremented by 1. |
536 | */ | 536 | */ |
537 | struct batadv_softif_vlan *batadv_softif_vlan_get(struct batadv_priv *bat_priv, | 537 | struct batadv_softif_vlan *batadv_softif_vlan_get(struct batadv_priv *bat_priv, |
538 | unsigned short vid) | 538 | unsigned short vid) |
539 | { | 539 | { |
540 | struct batadv_softif_vlan *vlan_tmp, *vlan = NULL; | 540 | struct batadv_softif_vlan *vlan_tmp, *vlan = NULL; |
541 | 541 | ||
542 | rcu_read_lock(); | 542 | rcu_read_lock(); |
543 | hlist_for_each_entry_rcu(vlan_tmp, &bat_priv->softif_vlan_list, list) { | 543 | hlist_for_each_entry_rcu(vlan_tmp, &bat_priv->softif_vlan_list, list) { |
544 | if (vlan_tmp->vid != vid) | 544 | if (vlan_tmp->vid != vid) |
545 | continue; | 545 | continue; |
546 | 546 | ||
547 | if (!kref_get_unless_zero(&vlan_tmp->refcount)) | 547 | if (!kref_get_unless_zero(&vlan_tmp->refcount)) |
548 | continue; | 548 | continue; |
549 | 549 | ||
550 | vlan = vlan_tmp; | 550 | vlan = vlan_tmp; |
551 | break; | 551 | break; |
552 | } | 552 | } |
553 | rcu_read_unlock(); | 553 | rcu_read_unlock(); |
554 | 554 | ||
555 | return vlan; | 555 | return vlan; |
556 | } | 556 | } |
557 | 557 | ||
558 | /** | 558 | /** |
559 | * batadv_softif_create_vlan - allocate the needed resources for a new vlan | 559 | * batadv_softif_create_vlan - allocate the needed resources for a new vlan |
560 | * @bat_priv: the bat priv with all the soft interface information | 560 | * @bat_priv: the bat priv with all the soft interface information |
561 | * @vid: the VLAN identifier | 561 | * @vid: the VLAN identifier |
562 | * | 562 | * |
563 | * Return: 0 on success, a negative error otherwise. | 563 | * Return: 0 on success, a negative error otherwise. |
564 | */ | 564 | */ |
565 | int batadv_softif_create_vlan(struct batadv_priv *bat_priv, unsigned short vid) | 565 | int batadv_softif_create_vlan(struct batadv_priv *bat_priv, unsigned short vid) |
566 | { | 566 | { |
567 | struct batadv_softif_vlan *vlan; | 567 | struct batadv_softif_vlan *vlan; |
568 | int err; | 568 | int err; |
569 | 569 | ||
570 | vlan = batadv_softif_vlan_get(bat_priv, vid); | 570 | vlan = batadv_softif_vlan_get(bat_priv, vid); |
571 | if (vlan) { | 571 | if (vlan) { |
572 | batadv_softif_vlan_put(vlan); | 572 | batadv_softif_vlan_put(vlan); |
573 | return -EEXIST; | 573 | return -EEXIST; |
574 | } | 574 | } |
575 | 575 | ||
576 | vlan = kzalloc(sizeof(*vlan), GFP_ATOMIC); | 576 | vlan = kzalloc(sizeof(*vlan), GFP_ATOMIC); |
577 | if (!vlan) | 577 | if (!vlan) |
578 | return -ENOMEM; | 578 | return -ENOMEM; |
579 | 579 | ||
580 | vlan->bat_priv = bat_priv; | 580 | vlan->bat_priv = bat_priv; |
581 | vlan->vid = vid; | 581 | vlan->vid = vid; |
582 | kref_init(&vlan->refcount); | 582 | kref_init(&vlan->refcount); |
583 | 583 | ||
584 | atomic_set(&vlan->ap_isolation, 0); | 584 | atomic_set(&vlan->ap_isolation, 0); |
585 | 585 | ||
586 | err = batadv_sysfs_add_vlan(bat_priv->soft_iface, vlan); | 586 | err = batadv_sysfs_add_vlan(bat_priv->soft_iface, vlan); |
587 | if (err) { | 587 | if (err) { |
588 | kfree(vlan); | 588 | kfree(vlan); |
589 | return err; | 589 | return err; |
590 | } | 590 | } |
591 | 591 | ||
592 | spin_lock_bh(&bat_priv->softif_vlan_list_lock); | 592 | spin_lock_bh(&bat_priv->softif_vlan_list_lock); |
593 | hlist_add_head_rcu(&vlan->list, &bat_priv->softif_vlan_list); | 593 | hlist_add_head_rcu(&vlan->list, &bat_priv->softif_vlan_list); |
594 | spin_unlock_bh(&bat_priv->softif_vlan_list_lock); | 594 | spin_unlock_bh(&bat_priv->softif_vlan_list_lock); |
595 | 595 | ||
596 | /* add a new TT local entry. This one will be marked with the NOPURGE | 596 | /* add a new TT local entry. This one will be marked with the NOPURGE |
597 | * flag | 597 | * flag |
598 | */ | 598 | */ |
599 | batadv_tt_local_add(bat_priv->soft_iface, | 599 | batadv_tt_local_add(bat_priv->soft_iface, |
600 | bat_priv->soft_iface->dev_addr, vid, | 600 | bat_priv->soft_iface->dev_addr, vid, |
601 | BATADV_NULL_IFINDEX, BATADV_NO_MARK); | 601 | BATADV_NULL_IFINDEX, BATADV_NO_MARK); |
602 | 602 | ||
603 | return 0; | 603 | return 0; |
604 | } | 604 | } |
605 | 605 | ||
606 | /** | 606 | /** |
607 | * batadv_softif_destroy_vlan - remove and destroy a softif_vlan object | 607 | * batadv_softif_destroy_vlan - remove and destroy a softif_vlan object |
608 | * @bat_priv: the bat priv with all the soft interface information | 608 | * @bat_priv: the bat priv with all the soft interface information |
609 | * @vlan: the object to remove | 609 | * @vlan: the object to remove |
610 | */ | 610 | */ |
611 | static void batadv_softif_destroy_vlan(struct batadv_priv *bat_priv, | 611 | static void batadv_softif_destroy_vlan(struct batadv_priv *bat_priv, |
612 | struct batadv_softif_vlan *vlan) | 612 | struct batadv_softif_vlan *vlan) |
613 | { | 613 | { |
614 | /* explicitly remove the associated TT local entry because it is marked | 614 | /* explicitly remove the associated TT local entry because it is marked |
615 | * with the NOPURGE flag | 615 | * with the NOPURGE flag |
616 | */ | 616 | */ |
617 | batadv_tt_local_remove(bat_priv, bat_priv->soft_iface->dev_addr, | 617 | batadv_tt_local_remove(bat_priv, bat_priv->soft_iface->dev_addr, |
618 | vlan->vid, "vlan interface destroyed", false); | 618 | vlan->vid, "vlan interface destroyed", false); |
619 | 619 | ||
620 | batadv_sysfs_del_vlan(bat_priv, vlan); | 620 | batadv_sysfs_del_vlan(bat_priv, vlan); |
621 | batadv_softif_vlan_put(vlan); | 621 | batadv_softif_vlan_put(vlan); |
622 | } | 622 | } |
623 | 623 | ||
624 | /** | 624 | /** |
625 | * batadv_interface_add_vid - ndo_add_vid API implementation | 625 | * batadv_interface_add_vid - ndo_add_vid API implementation |
626 | * @dev: the netdev of the mesh interface | 626 | * @dev: the netdev of the mesh interface |
627 | * @proto: protocol of the the vlan id | 627 | * @proto: protocol of the the vlan id |
628 | * @vid: identifier of the new vlan | 628 | * @vid: identifier of the new vlan |
629 | * | 629 | * |
630 | * Set up all the internal structures for handling the new vlan on top of the | 630 | * Set up all the internal structures for handling the new vlan on top of the |
631 | * mesh interface | 631 | * mesh interface |
632 | * | 632 | * |
633 | * Return: 0 on success or a negative error code in case of failure. | 633 | * Return: 0 on success or a negative error code in case of failure. |
634 | */ | 634 | */ |
635 | static int batadv_interface_add_vid(struct net_device *dev, __be16 proto, | 635 | static int batadv_interface_add_vid(struct net_device *dev, __be16 proto, |
636 | unsigned short vid) | 636 | unsigned short vid) |
637 | { | 637 | { |
638 | struct batadv_priv *bat_priv = netdev_priv(dev); | 638 | struct batadv_priv *bat_priv = netdev_priv(dev); |
639 | struct batadv_softif_vlan *vlan; | 639 | struct batadv_softif_vlan *vlan; |
640 | int ret; | 640 | int ret; |
641 | 641 | ||
642 | /* only 802.1Q vlans are supported. | 642 | /* only 802.1Q vlans are supported. |
643 | * batman-adv does not know how to handle other types | 643 | * batman-adv does not know how to handle other types |
644 | */ | 644 | */ |
645 | if (proto != htons(ETH_P_8021Q)) | 645 | if (proto != htons(ETH_P_8021Q)) |
646 | return -EINVAL; | 646 | return -EINVAL; |
647 | 647 | ||
648 | vid |= BATADV_VLAN_HAS_TAG; | 648 | vid |= BATADV_VLAN_HAS_TAG; |
649 | 649 | ||
650 | /* if a new vlan is getting created and it already exists, it means that | 650 | /* if a new vlan is getting created and it already exists, it means that |
651 | * it was not deleted yet. batadv_softif_vlan_get() increases the | 651 | * it was not deleted yet. batadv_softif_vlan_get() increases the |
652 | * refcount in order to revive the object. | 652 | * refcount in order to revive the object. |
653 | * | 653 | * |
654 | * if it does not exist then create it. | 654 | * if it does not exist then create it. |
655 | */ | 655 | */ |
656 | vlan = batadv_softif_vlan_get(bat_priv, vid); | 656 | vlan = batadv_softif_vlan_get(bat_priv, vid); |
657 | if (!vlan) | 657 | if (!vlan) |
658 | return batadv_softif_create_vlan(bat_priv, vid); | 658 | return batadv_softif_create_vlan(bat_priv, vid); |
659 | 659 | ||
660 | /* recreate the sysfs object if it was already destroyed (and it should | 660 | /* recreate the sysfs object if it was already destroyed (and it should |
661 | * be since we received a kill_vid() for this vlan | 661 | * be since we received a kill_vid() for this vlan |
662 | */ | 662 | */ |
663 | if (!vlan->kobj) { | 663 | if (!vlan->kobj) { |
664 | ret = batadv_sysfs_add_vlan(bat_priv->soft_iface, vlan); | 664 | ret = batadv_sysfs_add_vlan(bat_priv->soft_iface, vlan); |
665 | if (ret) { | 665 | if (ret) { |
666 | batadv_softif_vlan_put(vlan); | 666 | batadv_softif_vlan_put(vlan); |
667 | return ret; | 667 | return ret; |
668 | } | 668 | } |
669 | } | 669 | } |
670 | 670 | ||
671 | /* add a new TT local entry. This one will be marked with the NOPURGE | 671 | /* add a new TT local entry. This one will be marked with the NOPURGE |
672 | * flag. This must be added again, even if the vlan object already | 672 | * flag. This must be added again, even if the vlan object already |
673 | * exists, because the entry was deleted by kill_vid() | 673 | * exists, because the entry was deleted by kill_vid() |
674 | */ | 674 | */ |
675 | batadv_tt_local_add(bat_priv->soft_iface, | 675 | batadv_tt_local_add(bat_priv->soft_iface, |
676 | bat_priv->soft_iface->dev_addr, vid, | 676 | bat_priv->soft_iface->dev_addr, vid, |
677 | BATADV_NULL_IFINDEX, BATADV_NO_MARK); | 677 | BATADV_NULL_IFINDEX, BATADV_NO_MARK); |
678 | 678 | ||
679 | return 0; | 679 | return 0; |
680 | } | 680 | } |
681 | 681 | ||
682 | /** | 682 | /** |
683 | * batadv_interface_kill_vid - ndo_kill_vid API implementation | 683 | * batadv_interface_kill_vid - ndo_kill_vid API implementation |
684 | * @dev: the netdev of the mesh interface | 684 | * @dev: the netdev of the mesh interface |
685 | * @proto: protocol of the the vlan id | 685 | * @proto: protocol of the the vlan id |
686 | * @vid: identifier of the deleted vlan | 686 | * @vid: identifier of the deleted vlan |
687 | * | 687 | * |
688 | * Destroy all the internal structures used to handle the vlan identified by vid | 688 | * Destroy all the internal structures used to handle the vlan identified by vid |
689 | * on top of the mesh interface | 689 | * on top of the mesh interface |
690 | * | 690 | * |
691 | * Return: 0 on success, -EINVAL if the specified prototype is not ETH_P_8021Q | 691 | * Return: 0 on success, -EINVAL if the specified prototype is not ETH_P_8021Q |
692 | * or -ENOENT if the specified vlan id wasn't registered. | 692 | * or -ENOENT if the specified vlan id wasn't registered. |
693 | */ | 693 | */ |
694 | static int batadv_interface_kill_vid(struct net_device *dev, __be16 proto, | 694 | static int batadv_interface_kill_vid(struct net_device *dev, __be16 proto, |
695 | unsigned short vid) | 695 | unsigned short vid) |
696 | { | 696 | { |
697 | struct batadv_priv *bat_priv = netdev_priv(dev); | 697 | struct batadv_priv *bat_priv = netdev_priv(dev); |
698 | struct batadv_softif_vlan *vlan; | 698 | struct batadv_softif_vlan *vlan; |
699 | 699 | ||
700 | /* only 802.1Q vlans are supported. batman-adv does not know how to | 700 | /* only 802.1Q vlans are supported. batman-adv does not know how to |
701 | * handle other types | 701 | * handle other types |
702 | */ | 702 | */ |
703 | if (proto != htons(ETH_P_8021Q)) | 703 | if (proto != htons(ETH_P_8021Q)) |
704 | return -EINVAL; | 704 | return -EINVAL; |
705 | 705 | ||
706 | vlan = batadv_softif_vlan_get(bat_priv, vid | BATADV_VLAN_HAS_TAG); | 706 | vlan = batadv_softif_vlan_get(bat_priv, vid | BATADV_VLAN_HAS_TAG); |
707 | if (!vlan) | 707 | if (!vlan) |
708 | return -ENOENT; | 708 | return -ENOENT; |
709 | 709 | ||
710 | batadv_softif_destroy_vlan(bat_priv, vlan); | 710 | batadv_softif_destroy_vlan(bat_priv, vlan); |
711 | 711 | ||
712 | /* finally free the vlan object */ | 712 | /* finally free the vlan object */ |
713 | batadv_softif_vlan_put(vlan); | 713 | batadv_softif_vlan_put(vlan); |
714 | 714 | ||
715 | return 0; | 715 | return 0; |
716 | } | 716 | } |
717 | 717 | ||
718 | /* batman-adv network devices have devices nesting below it and are a special | 718 | /* batman-adv network devices have devices nesting below it and are a special |
719 | * "super class" of normal network devices; split their locks off into a | 719 | * "super class" of normal network devices; split their locks off into a |
720 | * separate class since they always nest. | 720 | * separate class since they always nest. |
721 | */ | 721 | */ |
722 | static struct lock_class_key batadv_netdev_xmit_lock_key; | 722 | static struct lock_class_key batadv_netdev_xmit_lock_key; |
723 | static struct lock_class_key batadv_netdev_addr_lock_key; | 723 | static struct lock_class_key batadv_netdev_addr_lock_key; |
724 | 724 | ||
725 | /** | 725 | /** |
726 | * batadv_set_lockdep_class_one - Set lockdep class for a single tx queue | 726 | * batadv_set_lockdep_class_one - Set lockdep class for a single tx queue |
727 | * @dev: device which owns the tx queue | 727 | * @dev: device which owns the tx queue |
728 | * @txq: tx queue to modify | 728 | * @txq: tx queue to modify |
729 | * @_unused: always NULL | 729 | * @_unused: always NULL |
730 | */ | 730 | */ |
731 | static void batadv_set_lockdep_class_one(struct net_device *dev, | 731 | static void batadv_set_lockdep_class_one(struct net_device *dev, |
732 | struct netdev_queue *txq, | 732 | struct netdev_queue *txq, |
733 | void *_unused) | 733 | void *_unused) |
734 | { | 734 | { |
735 | lockdep_set_class(&txq->_xmit_lock, &batadv_netdev_xmit_lock_key); | 735 | lockdep_set_class(&txq->_xmit_lock, &batadv_netdev_xmit_lock_key); |
736 | } | 736 | } |
737 | 737 | ||
738 | /** | 738 | /** |
739 | * batadv_set_lockdep_class - Set txq and addr_list lockdep class | 739 | * batadv_set_lockdep_class - Set txq and addr_list lockdep class |
740 | * @dev: network device to modify | 740 | * @dev: network device to modify |
741 | */ | 741 | */ |
742 | static void batadv_set_lockdep_class(struct net_device *dev) | 742 | static void batadv_set_lockdep_class(struct net_device *dev) |
743 | { | 743 | { |
744 | lockdep_set_class(&dev->addr_list_lock, &batadv_netdev_addr_lock_key); | 744 | lockdep_set_class(&dev->addr_list_lock, &batadv_netdev_addr_lock_key); |
745 | netdev_for_each_tx_queue(dev, batadv_set_lockdep_class_one, NULL); | 745 | netdev_for_each_tx_queue(dev, batadv_set_lockdep_class_one, NULL); |
746 | } | 746 | } |
747 | 747 | ||
748 | /** | 748 | /** |
749 | * batadv_softif_destroy_finish - cleans up the remains of a softif | 749 | * batadv_softif_destroy_finish - cleans up the remains of a softif |
750 | * @work: work queue item | 750 | * @work: work queue item |
751 | * | 751 | * |
752 | * Free the parts of the soft interface which can not be removed under | 752 | * Free the parts of the soft interface which can not be removed under |
753 | * rtnl lock (to prevent deadlock situations). | 753 | * rtnl lock (to prevent deadlock situations). |
754 | */ | 754 | */ |
755 | static void batadv_softif_destroy_finish(struct work_struct *work) | 755 | static void batadv_softif_destroy_finish(struct work_struct *work) |
756 | { | 756 | { |
757 | struct batadv_softif_vlan *vlan; | 757 | struct batadv_softif_vlan *vlan; |
758 | struct batadv_priv *bat_priv; | 758 | struct batadv_priv *bat_priv; |
759 | struct net_device *soft_iface; | 759 | struct net_device *soft_iface; |
760 | 760 | ||
761 | bat_priv = container_of(work, struct batadv_priv, | 761 | bat_priv = container_of(work, struct batadv_priv, |
762 | cleanup_work); | 762 | cleanup_work); |
763 | soft_iface = bat_priv->soft_iface; | 763 | soft_iface = bat_priv->soft_iface; |
764 | 764 | ||
765 | /* destroy the "untagged" VLAN */ | 765 | /* destroy the "untagged" VLAN */ |
766 | vlan = batadv_softif_vlan_get(bat_priv, BATADV_NO_FLAGS); | 766 | vlan = batadv_softif_vlan_get(bat_priv, BATADV_NO_FLAGS); |
767 | if (vlan) { | 767 | if (vlan) { |
768 | batadv_softif_destroy_vlan(bat_priv, vlan); | 768 | batadv_softif_destroy_vlan(bat_priv, vlan); |
769 | batadv_softif_vlan_put(vlan); | 769 | batadv_softif_vlan_put(vlan); |
770 | } | 770 | } |
771 | 771 | ||
772 | batadv_sysfs_del_meshif(soft_iface); | 772 | batadv_sysfs_del_meshif(soft_iface); |
773 | unregister_netdev(soft_iface); | 773 | unregister_netdev(soft_iface); |
774 | } | 774 | } |
775 | 775 | ||
776 | /** | 776 | /** |
777 | * batadv_softif_init_late - late stage initialization of soft interface | 777 | * batadv_softif_init_late - late stage initialization of soft interface |
778 | * @dev: registered network device to modify | 778 | * @dev: registered network device to modify |
779 | * | 779 | * |
780 | * Return: error code on failures | 780 | * Return: error code on failures |
781 | */ | 781 | */ |
782 | static int batadv_softif_init_late(struct net_device *dev) | 782 | static int batadv_softif_init_late(struct net_device *dev) |
783 | { | 783 | { |
784 | struct batadv_priv *bat_priv; | 784 | struct batadv_priv *bat_priv; |
785 | u32 random_seqno; | 785 | u32 random_seqno; |
786 | int ret; | 786 | int ret; |
787 | size_t cnt_len = sizeof(u64) * BATADV_CNT_NUM; | 787 | size_t cnt_len = sizeof(u64) * BATADV_CNT_NUM; |
788 | 788 | ||
789 | batadv_set_lockdep_class(dev); | 789 | batadv_set_lockdep_class(dev); |
790 | 790 | ||
791 | bat_priv = netdev_priv(dev); | 791 | bat_priv = netdev_priv(dev); |
792 | bat_priv->soft_iface = dev; | 792 | bat_priv->soft_iface = dev; |
793 | INIT_WORK(&bat_priv->cleanup_work, batadv_softif_destroy_finish); | 793 | INIT_WORK(&bat_priv->cleanup_work, batadv_softif_destroy_finish); |
794 | 794 | ||
795 | /* batadv_interface_stats() needs to be available as soon as | 795 | /* batadv_interface_stats() needs to be available as soon as |
796 | * register_netdevice() has been called | 796 | * register_netdevice() has been called |
797 | */ | 797 | */ |
798 | bat_priv->bat_counters = __alloc_percpu(cnt_len, __alignof__(u64)); | 798 | bat_priv->bat_counters = __alloc_percpu(cnt_len, __alignof__(u64)); |
799 | if (!bat_priv->bat_counters) | 799 | if (!bat_priv->bat_counters) |
800 | return -ENOMEM; | 800 | return -ENOMEM; |
801 | 801 | ||
802 | atomic_set(&bat_priv->aggregated_ogms, 1); | 802 | atomic_set(&bat_priv->aggregated_ogms, 1); |
803 | atomic_set(&bat_priv->bonding, 0); | 803 | atomic_set(&bat_priv->bonding, 0); |
804 | #ifdef CONFIG_BATMAN_ADV_BLA | 804 | #ifdef CONFIG_BATMAN_ADV_BLA |
805 | atomic_set(&bat_priv->bridge_loop_avoidance, 1); | 805 | atomic_set(&bat_priv->bridge_loop_avoidance, 1); |
806 | #endif | 806 | #endif |
807 | #ifdef CONFIG_BATMAN_ADV_DAT | 807 | #ifdef CONFIG_BATMAN_ADV_DAT |
808 | atomic_set(&bat_priv->distributed_arp_table, 1); | 808 | atomic_set(&bat_priv->distributed_arp_table, 1); |
809 | #endif | 809 | #endif |
810 | #ifdef CONFIG_BATMAN_ADV_MCAST | 810 | #ifdef CONFIG_BATMAN_ADV_MCAST |
811 | bat_priv->mcast.flags = BATADV_NO_FLAGS; | 811 | bat_priv->mcast.flags = BATADV_NO_FLAGS; |
812 | atomic_set(&bat_priv->multicast_mode, 1); | 812 | atomic_set(&bat_priv->multicast_mode, 1); |
813 | atomic_set(&bat_priv->mcast.num_disabled, 0); | 813 | atomic_set(&bat_priv->mcast.num_disabled, 0); |
814 | atomic_set(&bat_priv->mcast.num_want_all_unsnoopables, 0); | 814 | atomic_set(&bat_priv->mcast.num_want_all_unsnoopables, 0); |
815 | atomic_set(&bat_priv->mcast.num_want_all_ipv4, 0); | 815 | atomic_set(&bat_priv->mcast.num_want_all_ipv4, 0); |
816 | atomic_set(&bat_priv->mcast.num_want_all_ipv6, 0); | 816 | atomic_set(&bat_priv->mcast.num_want_all_ipv6, 0); |
817 | #endif | 817 | #endif |
818 | atomic_set(&bat_priv->gw_mode, BATADV_GW_MODE_OFF); | 818 | atomic_set(&bat_priv->gw.mode, BATADV_GW_MODE_OFF); |
819 | atomic_set(&bat_priv->gw_sel_class, 20); | 819 | atomic_set(&bat_priv->gw.sel_class, 20); |
820 | atomic_set(&bat_priv->gw.bandwidth_down, 100); | 820 | atomic_set(&bat_priv->gw.bandwidth_down, 100); |
821 | atomic_set(&bat_priv->gw.bandwidth_up, 20); | 821 | atomic_set(&bat_priv->gw.bandwidth_up, 20); |
822 | atomic_set(&bat_priv->orig_interval, 1000); | 822 | atomic_set(&bat_priv->orig_interval, 1000); |
823 | atomic_set(&bat_priv->hop_penalty, 30); | 823 | atomic_set(&bat_priv->hop_penalty, 30); |
824 | #ifdef CONFIG_BATMAN_ADV_DEBUG | 824 | #ifdef CONFIG_BATMAN_ADV_DEBUG |
825 | atomic_set(&bat_priv->log_level, 0); | 825 | atomic_set(&bat_priv->log_level, 0); |
826 | #endif | 826 | #endif |
827 | atomic_set(&bat_priv->fragmentation, 1); | 827 | atomic_set(&bat_priv->fragmentation, 1); |
828 | atomic_set(&bat_priv->packet_size_max, ETH_DATA_LEN); | 828 | atomic_set(&bat_priv->packet_size_max, ETH_DATA_LEN); |
829 | atomic_set(&bat_priv->bcast_queue_left, BATADV_BCAST_QUEUE_LEN); | 829 | atomic_set(&bat_priv->bcast_queue_left, BATADV_BCAST_QUEUE_LEN); |
830 | atomic_set(&bat_priv->batman_queue_left, BATADV_BATMAN_QUEUE_LEN); | 830 | atomic_set(&bat_priv->batman_queue_left, BATADV_BATMAN_QUEUE_LEN); |
831 | 831 | ||
832 | atomic_set(&bat_priv->mesh_state, BATADV_MESH_INACTIVE); | 832 | atomic_set(&bat_priv->mesh_state, BATADV_MESH_INACTIVE); |
833 | atomic_set(&bat_priv->bcast_seqno, 1); | 833 | atomic_set(&bat_priv->bcast_seqno, 1); |
834 | atomic_set(&bat_priv->tt.vn, 0); | 834 | atomic_set(&bat_priv->tt.vn, 0); |
835 | atomic_set(&bat_priv->tt.local_changes, 0); | 835 | atomic_set(&bat_priv->tt.local_changes, 0); |
836 | atomic_set(&bat_priv->tt.ogm_append_cnt, 0); | 836 | atomic_set(&bat_priv->tt.ogm_append_cnt, 0); |
837 | #ifdef CONFIG_BATMAN_ADV_BLA | 837 | #ifdef CONFIG_BATMAN_ADV_BLA |
838 | atomic_set(&bat_priv->bla.num_requests, 0); | 838 | atomic_set(&bat_priv->bla.num_requests, 0); |
839 | #endif | 839 | #endif |
840 | bat_priv->tt.last_changeset = NULL; | 840 | bat_priv->tt.last_changeset = NULL; |
841 | bat_priv->tt.last_changeset_len = 0; | 841 | bat_priv->tt.last_changeset_len = 0; |
842 | bat_priv->isolation_mark = 0; | 842 | bat_priv->isolation_mark = 0; |
843 | bat_priv->isolation_mark_mask = 0; | 843 | bat_priv->isolation_mark_mask = 0; |
844 | 844 | ||
845 | /* randomize initial seqno to avoid collision */ | 845 | /* randomize initial seqno to avoid collision */ |
846 | get_random_bytes(&random_seqno, sizeof(random_seqno)); | 846 | get_random_bytes(&random_seqno, sizeof(random_seqno)); |
847 | atomic_set(&bat_priv->frag_seqno, random_seqno); | 847 | atomic_set(&bat_priv->frag_seqno, random_seqno); |
848 | 848 | ||
849 | bat_priv->primary_if = NULL; | 849 | bat_priv->primary_if = NULL; |
850 | bat_priv->num_ifaces = 0; | 850 | bat_priv->num_ifaces = 0; |
851 | 851 | ||
852 | batadv_nc_init_bat_priv(bat_priv); | 852 | batadv_nc_init_bat_priv(bat_priv); |
853 | 853 | ||
854 | ret = batadv_algo_select(bat_priv, batadv_routing_algo); | 854 | ret = batadv_algo_select(bat_priv, batadv_routing_algo); |
855 | if (ret < 0) | 855 | if (ret < 0) |
856 | goto free_bat_counters; | 856 | goto free_bat_counters; |
857 | 857 | ||
858 | ret = batadv_debugfs_add_meshif(dev); | 858 | ret = batadv_debugfs_add_meshif(dev); |
859 | if (ret < 0) | 859 | if (ret < 0) |
860 | goto free_bat_counters; | 860 | goto free_bat_counters; |
861 | 861 | ||
862 | ret = batadv_mesh_init(dev); | 862 | ret = batadv_mesh_init(dev); |
863 | if (ret < 0) | 863 | if (ret < 0) |
864 | goto unreg_debugfs; | 864 | goto unreg_debugfs; |
865 | 865 | ||
866 | return 0; | 866 | return 0; |
867 | 867 | ||
868 | unreg_debugfs: | 868 | unreg_debugfs: |
869 | batadv_debugfs_del_meshif(dev); | 869 | batadv_debugfs_del_meshif(dev); |
870 | free_bat_counters: | 870 | free_bat_counters: |
871 | free_percpu(bat_priv->bat_counters); | 871 | free_percpu(bat_priv->bat_counters); |
872 | bat_priv->bat_counters = NULL; | 872 | bat_priv->bat_counters = NULL; |
873 | 873 | ||
874 | return ret; | 874 | return ret; |
875 | } | 875 | } |
876 | 876 | ||
877 | /** | 877 | /** |
878 | * batadv_softif_slave_add - Add a slave interface to a batadv_soft_interface | 878 | * batadv_softif_slave_add - Add a slave interface to a batadv_soft_interface |
879 | * @dev: batadv_soft_interface used as master interface | 879 | * @dev: batadv_soft_interface used as master interface |
880 | * @slave_dev: net_device which should become the slave interface | 880 | * @slave_dev: net_device which should become the slave interface |
881 | * | 881 | * |
882 | * Return: 0 if successful or error otherwise. | 882 | * Return: 0 if successful or error otherwise. |
883 | */ | 883 | */ |
884 | static int batadv_softif_slave_add(struct net_device *dev, | 884 | static int batadv_softif_slave_add(struct net_device *dev, |
885 | struct net_device *slave_dev) | 885 | struct net_device *slave_dev) |
886 | { | 886 | { |
887 | struct batadv_hard_iface *hard_iface; | 887 | struct batadv_hard_iface *hard_iface; |
888 | struct net *net = dev_net(dev); | 888 | struct net *net = dev_net(dev); |
889 | int ret = -EINVAL; | 889 | int ret = -EINVAL; |
890 | 890 | ||
891 | hard_iface = batadv_hardif_get_by_netdev(slave_dev); | 891 | hard_iface = batadv_hardif_get_by_netdev(slave_dev); |
892 | if (!hard_iface || hard_iface->soft_iface) | 892 | if (!hard_iface || hard_iface->soft_iface) |
893 | goto out; | 893 | goto out; |
894 | 894 | ||
895 | ret = batadv_hardif_enable_interface(hard_iface, net, dev->name); | 895 | ret = batadv_hardif_enable_interface(hard_iface, net, dev->name); |
896 | 896 | ||
897 | out: | 897 | out: |
898 | if (hard_iface) | 898 | if (hard_iface) |
899 | batadv_hardif_put(hard_iface); | 899 | batadv_hardif_put(hard_iface); |
900 | return ret; | 900 | return ret; |
901 | } | 901 | } |
902 | 902 | ||
903 | /** | 903 | /** |
904 | * batadv_softif_slave_del - Delete a slave iface from a batadv_soft_interface | 904 | * batadv_softif_slave_del - Delete a slave iface from a batadv_soft_interface |
905 | * @dev: batadv_soft_interface used as master interface | 905 | * @dev: batadv_soft_interface used as master interface |
906 | * @slave_dev: net_device which should be removed from the master interface | 906 | * @slave_dev: net_device which should be removed from the master interface |
907 | * | 907 | * |
908 | * Return: 0 if successful or error otherwise. | 908 | * Return: 0 if successful or error otherwise. |
909 | */ | 909 | */ |
910 | static int batadv_softif_slave_del(struct net_device *dev, | 910 | static int batadv_softif_slave_del(struct net_device *dev, |
911 | struct net_device *slave_dev) | 911 | struct net_device *slave_dev) |
912 | { | 912 | { |
913 | struct batadv_hard_iface *hard_iface; | 913 | struct batadv_hard_iface *hard_iface; |
914 | int ret = -EINVAL; | 914 | int ret = -EINVAL; |
915 | 915 | ||
916 | hard_iface = batadv_hardif_get_by_netdev(slave_dev); | 916 | hard_iface = batadv_hardif_get_by_netdev(slave_dev); |
917 | 917 | ||
918 | if (!hard_iface || hard_iface->soft_iface != dev) | 918 | if (!hard_iface || hard_iface->soft_iface != dev) |
919 | goto out; | 919 | goto out; |
920 | 920 | ||
921 | batadv_hardif_disable_interface(hard_iface, BATADV_IF_CLEANUP_KEEP); | 921 | batadv_hardif_disable_interface(hard_iface, BATADV_IF_CLEANUP_KEEP); |
922 | ret = 0; | 922 | ret = 0; |
923 | 923 | ||
924 | out: | 924 | out: |
925 | if (hard_iface) | 925 | if (hard_iface) |
926 | batadv_hardif_put(hard_iface); | 926 | batadv_hardif_put(hard_iface); |
927 | return ret; | 927 | return ret; |
928 | } | 928 | } |
929 | 929 | ||
930 | static const struct net_device_ops batadv_netdev_ops = { | 930 | static const struct net_device_ops batadv_netdev_ops = { |
931 | .ndo_init = batadv_softif_init_late, | 931 | .ndo_init = batadv_softif_init_late, |
932 | .ndo_open = batadv_interface_open, | 932 | .ndo_open = batadv_interface_open, |
933 | .ndo_stop = batadv_interface_release, | 933 | .ndo_stop = batadv_interface_release, |
934 | .ndo_get_stats = batadv_interface_stats, | 934 | .ndo_get_stats = batadv_interface_stats, |
935 | .ndo_vlan_rx_add_vid = batadv_interface_add_vid, | 935 | .ndo_vlan_rx_add_vid = batadv_interface_add_vid, |
936 | .ndo_vlan_rx_kill_vid = batadv_interface_kill_vid, | 936 | .ndo_vlan_rx_kill_vid = batadv_interface_kill_vid, |
937 | .ndo_set_mac_address = batadv_interface_set_mac_addr, | 937 | .ndo_set_mac_address = batadv_interface_set_mac_addr, |
938 | .ndo_change_mtu = batadv_interface_change_mtu, | 938 | .ndo_change_mtu = batadv_interface_change_mtu, |
939 | .ndo_set_rx_mode = batadv_interface_set_rx_mode, | 939 | .ndo_set_rx_mode = batadv_interface_set_rx_mode, |
940 | .ndo_start_xmit = batadv_interface_tx, | 940 | .ndo_start_xmit = batadv_interface_tx, |
941 | .ndo_validate_addr = eth_validate_addr, | 941 | .ndo_validate_addr = eth_validate_addr, |
942 | .ndo_add_slave = batadv_softif_slave_add, | 942 | .ndo_add_slave = batadv_softif_slave_add, |
943 | .ndo_del_slave = batadv_softif_slave_del, | 943 | .ndo_del_slave = batadv_softif_slave_del, |
944 | }; | 944 | }; |
945 | 945 | ||
946 | /** | 946 | /** |
947 | * batadv_softif_free - Deconstructor of batadv_soft_interface | 947 | * batadv_softif_free - Deconstructor of batadv_soft_interface |
948 | * @dev: Device to cleanup and remove | 948 | * @dev: Device to cleanup and remove |
949 | */ | 949 | */ |
950 | static void batadv_softif_free(struct net_device *dev) | 950 | static void batadv_softif_free(struct net_device *dev) |
951 | { | 951 | { |
952 | batadv_debugfs_del_meshif(dev); | 952 | batadv_debugfs_del_meshif(dev); |
953 | batadv_mesh_free(dev); | 953 | batadv_mesh_free(dev); |
954 | 954 | ||
955 | /* some scheduled RCU callbacks need the bat_priv struct to accomplish | 955 | /* some scheduled RCU callbacks need the bat_priv struct to accomplish |
956 | * their tasks. Wait for them all to be finished before freeing the | 956 | * their tasks. Wait for them all to be finished before freeing the |
957 | * netdev and its private data (bat_priv) | 957 | * netdev and its private data (bat_priv) |
958 | */ | 958 | */ |
959 | rcu_barrier(); | 959 | rcu_barrier(); |
960 | 960 | ||
961 | free_netdev(dev); | 961 | free_netdev(dev); |
962 | } | 962 | } |
963 | 963 | ||
964 | /** | 964 | /** |
965 | * batadv_softif_init_early - early stage initialization of soft interface | 965 | * batadv_softif_init_early - early stage initialization of soft interface |
966 | * @dev: registered network device to modify | 966 | * @dev: registered network device to modify |
967 | */ | 967 | */ |
968 | static void batadv_softif_init_early(struct net_device *dev) | 968 | static void batadv_softif_init_early(struct net_device *dev) |
969 | { | 969 | { |
970 | struct batadv_priv *priv = netdev_priv(dev); | 970 | struct batadv_priv *priv = netdev_priv(dev); |
971 | 971 | ||
972 | ether_setup(dev); | 972 | ether_setup(dev); |
973 | 973 | ||
974 | dev->netdev_ops = &batadv_netdev_ops; | 974 | dev->netdev_ops = &batadv_netdev_ops; |
975 | dev->destructor = batadv_softif_free; | 975 | dev->destructor = batadv_softif_free; |
976 | dev->features |= NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_NETNS_LOCAL; | 976 | dev->features |= NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_NETNS_LOCAL; |
977 | dev->priv_flags |= IFF_NO_QUEUE; | 977 | dev->priv_flags |= IFF_NO_QUEUE; |
978 | 978 | ||
979 | /* can't call min_mtu, because the needed variables | 979 | /* can't call min_mtu, because the needed variables |
980 | * have not been initialized yet | 980 | * have not been initialized yet |
981 | */ | 981 | */ |
982 | dev->mtu = ETH_DATA_LEN; | 982 | dev->mtu = ETH_DATA_LEN; |
983 | 983 | ||
984 | /* generate random address */ | 984 | /* generate random address */ |
985 | eth_hw_addr_random(dev); | 985 | eth_hw_addr_random(dev); |
986 | 986 | ||
987 | dev->ethtool_ops = &batadv_ethtool_ops; | 987 | dev->ethtool_ops = &batadv_ethtool_ops; |
988 | 988 | ||
989 | memset(priv, 0, sizeof(*priv)); | 989 | memset(priv, 0, sizeof(*priv)); |
990 | } | 990 | } |
991 | 991 | ||
992 | struct net_device *batadv_softif_create(struct net *net, const char *name) | 992 | struct net_device *batadv_softif_create(struct net *net, const char *name) |
993 | { | 993 | { |
994 | struct net_device *soft_iface; | 994 | struct net_device *soft_iface; |
995 | int ret; | 995 | int ret; |
996 | 996 | ||
997 | soft_iface = alloc_netdev(sizeof(struct batadv_priv), name, | 997 | soft_iface = alloc_netdev(sizeof(struct batadv_priv), name, |
998 | NET_NAME_UNKNOWN, batadv_softif_init_early); | 998 | NET_NAME_UNKNOWN, batadv_softif_init_early); |
999 | if (!soft_iface) | 999 | if (!soft_iface) |
1000 | return NULL; | 1000 | return NULL; |
1001 | 1001 | ||
1002 | dev_net_set(soft_iface, net); | 1002 | dev_net_set(soft_iface, net); |
1003 | 1003 | ||
1004 | soft_iface->rtnl_link_ops = &batadv_link_ops; | 1004 | soft_iface->rtnl_link_ops = &batadv_link_ops; |
1005 | 1005 | ||
1006 | ret = register_netdevice(soft_iface); | 1006 | ret = register_netdevice(soft_iface); |
1007 | if (ret < 0) { | 1007 | if (ret < 0) { |
1008 | pr_err("Unable to register the batman interface '%s': %i\n", | 1008 | pr_err("Unable to register the batman interface '%s': %i\n", |
1009 | name, ret); | 1009 | name, ret); |
1010 | free_netdev(soft_iface); | 1010 | free_netdev(soft_iface); |
1011 | return NULL; | 1011 | return NULL; |
1012 | } | 1012 | } |
1013 | 1013 | ||
1014 | return soft_iface; | 1014 | return soft_iface; |
1015 | } | 1015 | } |
1016 | 1016 | ||
1017 | /** | 1017 | /** |
1018 | * batadv_softif_destroy_sysfs - deletion of batadv_soft_interface via sysfs | 1018 | * batadv_softif_destroy_sysfs - deletion of batadv_soft_interface via sysfs |
1019 | * @soft_iface: the to-be-removed batman-adv interface | 1019 | * @soft_iface: the to-be-removed batman-adv interface |
1020 | */ | 1020 | */ |
1021 | void batadv_softif_destroy_sysfs(struct net_device *soft_iface) | 1021 | void batadv_softif_destroy_sysfs(struct net_device *soft_iface) |
1022 | { | 1022 | { |
1023 | struct batadv_priv *bat_priv = netdev_priv(soft_iface); | 1023 | struct batadv_priv *bat_priv = netdev_priv(soft_iface); |
1024 | 1024 | ||
1025 | queue_work(batadv_event_workqueue, &bat_priv->cleanup_work); | 1025 | queue_work(batadv_event_workqueue, &bat_priv->cleanup_work); |
1026 | } | 1026 | } |
1027 | 1027 | ||
1028 | /** | 1028 | /** |
1029 | * batadv_softif_destroy_netlink - deletion of batadv_soft_interface via netlink | 1029 | * batadv_softif_destroy_netlink - deletion of batadv_soft_interface via netlink |
1030 | * @soft_iface: the to-be-removed batman-adv interface | 1030 | * @soft_iface: the to-be-removed batman-adv interface |
1031 | * @head: list pointer | 1031 | * @head: list pointer |
1032 | */ | 1032 | */ |
1033 | static void batadv_softif_destroy_netlink(struct net_device *soft_iface, | 1033 | static void batadv_softif_destroy_netlink(struct net_device *soft_iface, |
1034 | struct list_head *head) | 1034 | struct list_head *head) |
1035 | { | 1035 | { |
1036 | struct batadv_hard_iface *hard_iface; | 1036 | struct batadv_hard_iface *hard_iface; |
1037 | 1037 | ||
1038 | list_for_each_entry(hard_iface, &batadv_hardif_list, list) { | 1038 | list_for_each_entry(hard_iface, &batadv_hardif_list, list) { |
1039 | if (hard_iface->soft_iface == soft_iface) | 1039 | if (hard_iface->soft_iface == soft_iface) |
1040 | batadv_hardif_disable_interface(hard_iface, | 1040 | batadv_hardif_disable_interface(hard_iface, |
1041 | BATADV_IF_CLEANUP_KEEP); | 1041 | BATADV_IF_CLEANUP_KEEP); |
1042 | } | 1042 | } |
1043 | 1043 | ||
1044 | batadv_sysfs_del_meshif(soft_iface); | 1044 | batadv_sysfs_del_meshif(soft_iface); |
1045 | unregister_netdevice_queue(soft_iface, head); | 1045 | unregister_netdevice_queue(soft_iface, head); |
1046 | } | 1046 | } |
1047 | 1047 | ||
1048 | bool batadv_softif_is_valid(const struct net_device *net_dev) | 1048 | bool batadv_softif_is_valid(const struct net_device *net_dev) |
1049 | { | 1049 | { |
1050 | if (net_dev->netdev_ops->ndo_start_xmit == batadv_interface_tx) | 1050 | if (net_dev->netdev_ops->ndo_start_xmit == batadv_interface_tx) |
1051 | return true; | 1051 | return true; |
1052 | 1052 | ||
1053 | return false; | 1053 | return false; |
1054 | } | 1054 | } |
1055 | 1055 | ||
1056 | struct rtnl_link_ops batadv_link_ops __read_mostly = { | 1056 | struct rtnl_link_ops batadv_link_ops __read_mostly = { |
1057 | .kind = "batadv", | 1057 | .kind = "batadv", |
1058 | .priv_size = sizeof(struct batadv_priv), | 1058 | .priv_size = sizeof(struct batadv_priv), |
1059 | .setup = batadv_softif_init_early, | 1059 | .setup = batadv_softif_init_early, |
1060 | .dellink = batadv_softif_destroy_netlink, | 1060 | .dellink = batadv_softif_destroy_netlink, |
1061 | }; | 1061 | }; |
1062 | 1062 | ||
1063 | /* ethtool */ | 1063 | /* ethtool */ |
1064 | static int batadv_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) | 1064 | static int batadv_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) |
1065 | { | 1065 | { |
1066 | cmd->supported = 0; | 1066 | cmd->supported = 0; |
1067 | cmd->advertising = 0; | 1067 | cmd->advertising = 0; |
1068 | ethtool_cmd_speed_set(cmd, SPEED_10); | 1068 | ethtool_cmd_speed_set(cmd, SPEED_10); |
1069 | cmd->duplex = DUPLEX_FULL; | 1069 | cmd->duplex = DUPLEX_FULL; |
1070 | cmd->port = PORT_TP; | 1070 | cmd->port = PORT_TP; |
1071 | cmd->phy_address = 0; | 1071 | cmd->phy_address = 0; |
1072 | cmd->transceiver = XCVR_INTERNAL; | 1072 | cmd->transceiver = XCVR_INTERNAL; |
1073 | cmd->autoneg = AUTONEG_DISABLE; | 1073 | cmd->autoneg = AUTONEG_DISABLE; |
1074 | cmd->maxtxpkt = 0; | 1074 | cmd->maxtxpkt = 0; |
1075 | cmd->maxrxpkt = 0; | 1075 | cmd->maxrxpkt = 0; |
1076 | 1076 | ||
1077 | return 0; | 1077 | return 0; |
1078 | } | 1078 | } |
1079 | 1079 | ||
1080 | static void batadv_get_drvinfo(struct net_device *dev, | 1080 | static void batadv_get_drvinfo(struct net_device *dev, |
1081 | struct ethtool_drvinfo *info) | 1081 | struct ethtool_drvinfo *info) |
1082 | { | 1082 | { |
1083 | strlcpy(info->driver, "B.A.T.M.A.N. advanced", sizeof(info->driver)); | 1083 | strlcpy(info->driver, "B.A.T.M.A.N. advanced", sizeof(info->driver)); |
1084 | strlcpy(info->version, BATADV_SOURCE_VERSION, sizeof(info->version)); | 1084 | strlcpy(info->version, BATADV_SOURCE_VERSION, sizeof(info->version)); |
1085 | strlcpy(info->fw_version, "N/A", sizeof(info->fw_version)); | 1085 | strlcpy(info->fw_version, "N/A", sizeof(info->fw_version)); |
1086 | strlcpy(info->bus_info, "batman", sizeof(info->bus_info)); | 1086 | strlcpy(info->bus_info, "batman", sizeof(info->bus_info)); |
1087 | } | 1087 | } |
1088 | 1088 | ||
1089 | static u32 batadv_get_msglevel(struct net_device *dev) | 1089 | static u32 batadv_get_msglevel(struct net_device *dev) |
1090 | { | 1090 | { |
1091 | return -EOPNOTSUPP; | 1091 | return -EOPNOTSUPP; |
1092 | } | 1092 | } |
1093 | 1093 | ||
1094 | static void batadv_set_msglevel(struct net_device *dev, u32 value) | 1094 | static void batadv_set_msglevel(struct net_device *dev, u32 value) |
1095 | { | 1095 | { |
1096 | } | 1096 | } |
1097 | 1097 | ||
1098 | static u32 batadv_get_link(struct net_device *dev) | 1098 | static u32 batadv_get_link(struct net_device *dev) |
1099 | { | 1099 | { |
1100 | return 1; | 1100 | return 1; |
1101 | } | 1101 | } |
1102 | 1102 | ||
1103 | /* Inspired by drivers/net/ethernet/dlink/sundance.c:1702 | 1103 | /* Inspired by drivers/net/ethernet/dlink/sundance.c:1702 |
1104 | * Declare each description string in struct.name[] to get fixed sized buffer | 1104 | * Declare each description string in struct.name[] to get fixed sized buffer |
1105 | * and compile time checking for strings longer than ETH_GSTRING_LEN. | 1105 | * and compile time checking for strings longer than ETH_GSTRING_LEN. |
1106 | */ | 1106 | */ |
1107 | static const struct { | 1107 | static const struct { |
1108 | const char name[ETH_GSTRING_LEN]; | 1108 | const char name[ETH_GSTRING_LEN]; |
1109 | } batadv_counters_strings[] = { | 1109 | } batadv_counters_strings[] = { |
1110 | { "tx" }, | 1110 | { "tx" }, |
1111 | { "tx_bytes" }, | 1111 | { "tx_bytes" }, |
1112 | { "tx_dropped" }, | 1112 | { "tx_dropped" }, |
1113 | { "rx" }, | 1113 | { "rx" }, |
1114 | { "rx_bytes" }, | 1114 | { "rx_bytes" }, |
1115 | { "forward" }, | 1115 | { "forward" }, |
1116 | { "forward_bytes" }, | 1116 | { "forward_bytes" }, |
1117 | { "mgmt_tx" }, | 1117 | { "mgmt_tx" }, |
1118 | { "mgmt_tx_bytes" }, | 1118 | { "mgmt_tx_bytes" }, |
1119 | { "mgmt_rx" }, | 1119 | { "mgmt_rx" }, |
1120 | { "mgmt_rx_bytes" }, | 1120 | { "mgmt_rx_bytes" }, |
1121 | { "frag_tx" }, | 1121 | { "frag_tx" }, |
1122 | { "frag_tx_bytes" }, | 1122 | { "frag_tx_bytes" }, |
1123 | { "frag_rx" }, | 1123 | { "frag_rx" }, |
1124 | { "frag_rx_bytes" }, | 1124 | { "frag_rx_bytes" }, |
1125 | { "frag_fwd" }, | 1125 | { "frag_fwd" }, |
1126 | { "frag_fwd_bytes" }, | 1126 | { "frag_fwd_bytes" }, |
1127 | { "tt_request_tx" }, | 1127 | { "tt_request_tx" }, |
1128 | { "tt_request_rx" }, | 1128 | { "tt_request_rx" }, |
1129 | { "tt_response_tx" }, | 1129 | { "tt_response_tx" }, |
1130 | { "tt_response_rx" }, | 1130 | { "tt_response_rx" }, |
1131 | { "tt_roam_adv_tx" }, | 1131 | { "tt_roam_adv_tx" }, |
1132 | { "tt_roam_adv_rx" }, | 1132 | { "tt_roam_adv_rx" }, |
1133 | #ifdef CONFIG_BATMAN_ADV_DAT | 1133 | #ifdef CONFIG_BATMAN_ADV_DAT |
1134 | { "dat_get_tx" }, | 1134 | { "dat_get_tx" }, |
1135 | { "dat_get_rx" }, | 1135 | { "dat_get_rx" }, |
1136 | { "dat_put_tx" }, | 1136 | { "dat_put_tx" }, |
1137 | { "dat_put_rx" }, | 1137 | { "dat_put_rx" }, |
1138 | { "dat_cached_reply_tx" }, | 1138 | { "dat_cached_reply_tx" }, |
1139 | #endif | 1139 | #endif |
1140 | #ifdef CONFIG_BATMAN_ADV_NC | 1140 | #ifdef CONFIG_BATMAN_ADV_NC |
1141 | { "nc_code" }, | 1141 | { "nc_code" }, |
1142 | { "nc_code_bytes" }, | 1142 | { "nc_code_bytes" }, |
1143 | { "nc_recode" }, | 1143 | { "nc_recode" }, |
1144 | { "nc_recode_bytes" }, | 1144 | { "nc_recode_bytes" }, |
1145 | { "nc_buffer" }, | 1145 | { "nc_buffer" }, |
1146 | { "nc_decode" }, | 1146 | { "nc_decode" }, |
1147 | { "nc_decode_bytes" }, | 1147 | { "nc_decode_bytes" }, |
1148 | { "nc_decode_failed" }, | 1148 | { "nc_decode_failed" }, |
1149 | { "nc_sniffed" }, | 1149 | { "nc_sniffed" }, |
1150 | #endif | 1150 | #endif |
1151 | }; | 1151 | }; |
1152 | 1152 | ||
1153 | static void batadv_get_strings(struct net_device *dev, u32 stringset, u8 *data) | 1153 | static void batadv_get_strings(struct net_device *dev, u32 stringset, u8 *data) |
1154 | { | 1154 | { |
1155 | if (stringset == ETH_SS_STATS) | 1155 | if (stringset == ETH_SS_STATS) |
1156 | memcpy(data, batadv_counters_strings, | 1156 | memcpy(data, batadv_counters_strings, |
1157 | sizeof(batadv_counters_strings)); | 1157 | sizeof(batadv_counters_strings)); |
1158 | } | 1158 | } |
1159 | 1159 | ||
1160 | static void batadv_get_ethtool_stats(struct net_device *dev, | 1160 | static void batadv_get_ethtool_stats(struct net_device *dev, |
1161 | struct ethtool_stats *stats, u64 *data) | 1161 | struct ethtool_stats *stats, u64 *data) |
1162 | { | 1162 | { |
1163 | struct batadv_priv *bat_priv = netdev_priv(dev); | 1163 | struct batadv_priv *bat_priv = netdev_priv(dev); |
1164 | int i; | 1164 | int i; |
1165 | 1165 | ||
1166 | for (i = 0; i < BATADV_CNT_NUM; i++) | 1166 | for (i = 0; i < BATADV_CNT_NUM; i++) |
1167 | data[i] = batadv_sum_counter(bat_priv, i); | 1167 | data[i] = batadv_sum_counter(bat_priv, i); |
1168 | } | 1168 | } |
1169 | 1169 | ||
1170 | static int batadv_get_sset_count(struct net_device *dev, int stringset) | 1170 | static int batadv_get_sset_count(struct net_device *dev, int stringset) |
1171 | { | 1171 | { |
1172 | if (stringset == ETH_SS_STATS) | 1172 | if (stringset == ETH_SS_STATS) |
1173 | return BATADV_CNT_NUM; | 1173 | return BATADV_CNT_NUM; |
1174 | 1174 | ||
1175 | return -EOPNOTSUPP; | 1175 | return -EOPNOTSUPP; |
1176 | } | 1176 | } |
1177 | 1177 |
net/batman-adv/sysfs.c
1 | /* Copyright (C) 2010-2016 B.A.T.M.A.N. contributors: | 1 | /* Copyright (C) 2010-2016 B.A.T.M.A.N. contributors: |
2 | * | 2 | * |
3 | * Marek Lindner | 3 | * Marek Lindner |
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 |
7 | * License as published by the Free Software Foundation. | 7 | * License as published by the Free Software Foundation. |
8 | * | 8 | * |
9 | * This program is distributed in the hope that it will be useful, but | 9 | * This program is distributed in the hope that it will be useful, but |
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of | 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 | * General Public License for more details. | 12 | * General Public License for more details. |
13 | * | 13 | * |
14 | * You should have received a copy of the GNU General Public License | 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/>. | 15 | * along with this program; if not, see <http://www.gnu.org/licenses/>. |
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include "sysfs.h" | 18 | #include "sysfs.h" |
19 | #include "main.h" | 19 | #include "main.h" |
20 | 20 | ||
21 | #include <linux/atomic.h> | 21 | #include <linux/atomic.h> |
22 | #include <linux/compiler.h> | 22 | #include <linux/compiler.h> |
23 | #include <linux/device.h> | 23 | #include <linux/device.h> |
24 | #include <linux/errno.h> | 24 | #include <linux/errno.h> |
25 | #include <linux/fs.h> | 25 | #include <linux/fs.h> |
26 | #include <linux/if.h> | 26 | #include <linux/if.h> |
27 | #include <linux/if_vlan.h> | 27 | #include <linux/if_vlan.h> |
28 | #include <linux/kref.h> | 28 | #include <linux/kref.h> |
29 | #include <linux/kernel.h> | 29 | #include <linux/kernel.h> |
30 | #include <linux/netdevice.h> | 30 | #include <linux/netdevice.h> |
31 | #include <linux/printk.h> | 31 | #include <linux/printk.h> |
32 | #include <linux/rculist.h> | 32 | #include <linux/rculist.h> |
33 | #include <linux/rcupdate.h> | 33 | #include <linux/rcupdate.h> |
34 | #include <linux/rtnetlink.h> | 34 | #include <linux/rtnetlink.h> |
35 | #include <linux/slab.h> | 35 | #include <linux/slab.h> |
36 | #include <linux/stat.h> | 36 | #include <linux/stat.h> |
37 | #include <linux/stddef.h> | 37 | #include <linux/stddef.h> |
38 | #include <linux/string.h> | 38 | #include <linux/string.h> |
39 | #include <linux/stringify.h> | 39 | #include <linux/stringify.h> |
40 | 40 | ||
41 | #include "distributed-arp-table.h" | 41 | #include "distributed-arp-table.h" |
42 | #include "gateway_client.h" | 42 | #include "gateway_client.h" |
43 | #include "gateway_common.h" | 43 | #include "gateway_common.h" |
44 | #include "bridge_loop_avoidance.h" | 44 | #include "bridge_loop_avoidance.h" |
45 | #include "hard-interface.h" | 45 | #include "hard-interface.h" |
46 | #include "network-coding.h" | 46 | #include "network-coding.h" |
47 | #include "packet.h" | 47 | #include "packet.h" |
48 | #include "soft-interface.h" | 48 | #include "soft-interface.h" |
49 | 49 | ||
50 | static struct net_device *batadv_kobj_to_netdev(struct kobject *obj) | 50 | static struct net_device *batadv_kobj_to_netdev(struct kobject *obj) |
51 | { | 51 | { |
52 | struct device *dev = container_of(obj->parent, struct device, kobj); | 52 | struct device *dev = container_of(obj->parent, struct device, kobj); |
53 | 53 | ||
54 | return to_net_dev(dev); | 54 | return to_net_dev(dev); |
55 | } | 55 | } |
56 | 56 | ||
57 | static struct batadv_priv *batadv_kobj_to_batpriv(struct kobject *obj) | 57 | static struct batadv_priv *batadv_kobj_to_batpriv(struct kobject *obj) |
58 | { | 58 | { |
59 | struct net_device *net_dev = batadv_kobj_to_netdev(obj); | 59 | struct net_device *net_dev = batadv_kobj_to_netdev(obj); |
60 | 60 | ||
61 | return netdev_priv(net_dev); | 61 | return netdev_priv(net_dev); |
62 | } | 62 | } |
63 | 63 | ||
64 | /** | 64 | /** |
65 | * batadv_vlan_kobj_to_batpriv - convert a vlan kobj in the associated batpriv | 65 | * batadv_vlan_kobj_to_batpriv - convert a vlan kobj in the associated batpriv |
66 | * @obj: kobject to covert | 66 | * @obj: kobject to covert |
67 | * | 67 | * |
68 | * Return: the associated batadv_priv struct. | 68 | * Return: the associated batadv_priv struct. |
69 | */ | 69 | */ |
70 | static struct batadv_priv *batadv_vlan_kobj_to_batpriv(struct kobject *obj) | 70 | static struct batadv_priv *batadv_vlan_kobj_to_batpriv(struct kobject *obj) |
71 | { | 71 | { |
72 | /* VLAN specific attributes are located in the root sysfs folder if they | 72 | /* VLAN specific attributes are located in the root sysfs folder if they |
73 | * refer to the untagged VLAN.. | 73 | * refer to the untagged VLAN.. |
74 | */ | 74 | */ |
75 | if (!strcmp(BATADV_SYSFS_IF_MESH_SUBDIR, obj->name)) | 75 | if (!strcmp(BATADV_SYSFS_IF_MESH_SUBDIR, obj->name)) |
76 | return batadv_kobj_to_batpriv(obj); | 76 | return batadv_kobj_to_batpriv(obj); |
77 | 77 | ||
78 | /* ..while the attributes for the tagged vlans are located in | 78 | /* ..while the attributes for the tagged vlans are located in |
79 | * the in the corresponding "vlan%VID" subfolder | 79 | * the in the corresponding "vlan%VID" subfolder |
80 | */ | 80 | */ |
81 | return batadv_kobj_to_batpriv(obj->parent); | 81 | return batadv_kobj_to_batpriv(obj->parent); |
82 | } | 82 | } |
83 | 83 | ||
84 | /** | 84 | /** |
85 | * batadv_kobj_to_vlan - convert a kobj in the associated softif_vlan struct | 85 | * batadv_kobj_to_vlan - convert a kobj in the associated softif_vlan struct |
86 | * @bat_priv: the bat priv with all the soft interface information | 86 | * @bat_priv: the bat priv with all the soft interface information |
87 | * @obj: kobject to covert | 87 | * @obj: kobject to covert |
88 | * | 88 | * |
89 | * Return: the associated softif_vlan struct if found, NULL otherwise. | 89 | * Return: the associated softif_vlan struct if found, NULL otherwise. |
90 | */ | 90 | */ |
91 | static struct batadv_softif_vlan * | 91 | static struct batadv_softif_vlan * |
92 | batadv_kobj_to_vlan(struct batadv_priv *bat_priv, struct kobject *obj) | 92 | batadv_kobj_to_vlan(struct batadv_priv *bat_priv, struct kobject *obj) |
93 | { | 93 | { |
94 | struct batadv_softif_vlan *vlan_tmp, *vlan = NULL; | 94 | struct batadv_softif_vlan *vlan_tmp, *vlan = NULL; |
95 | 95 | ||
96 | rcu_read_lock(); | 96 | rcu_read_lock(); |
97 | hlist_for_each_entry_rcu(vlan_tmp, &bat_priv->softif_vlan_list, list) { | 97 | hlist_for_each_entry_rcu(vlan_tmp, &bat_priv->softif_vlan_list, list) { |
98 | if (vlan_tmp->kobj != obj) | 98 | if (vlan_tmp->kobj != obj) |
99 | continue; | 99 | continue; |
100 | 100 | ||
101 | if (!kref_get_unless_zero(&vlan_tmp->refcount)) | 101 | if (!kref_get_unless_zero(&vlan_tmp->refcount)) |
102 | continue; | 102 | continue; |
103 | 103 | ||
104 | vlan = vlan_tmp; | 104 | vlan = vlan_tmp; |
105 | break; | 105 | break; |
106 | } | 106 | } |
107 | rcu_read_unlock(); | 107 | rcu_read_unlock(); |
108 | 108 | ||
109 | return vlan; | 109 | return vlan; |
110 | } | 110 | } |
111 | 111 | ||
112 | #define BATADV_UEV_TYPE_VAR "BATTYPE=" | 112 | #define BATADV_UEV_TYPE_VAR "BATTYPE=" |
113 | #define BATADV_UEV_ACTION_VAR "BATACTION=" | 113 | #define BATADV_UEV_ACTION_VAR "BATACTION=" |
114 | #define BATADV_UEV_DATA_VAR "BATDATA=" | 114 | #define BATADV_UEV_DATA_VAR "BATDATA=" |
115 | 115 | ||
116 | static char *batadv_uev_action_str[] = { | 116 | static char *batadv_uev_action_str[] = { |
117 | "add", | 117 | "add", |
118 | "del", | 118 | "del", |
119 | "change", | 119 | "change", |
120 | "loopdetect", | 120 | "loopdetect", |
121 | }; | 121 | }; |
122 | 122 | ||
123 | static char *batadv_uev_type_str[] = { | 123 | static char *batadv_uev_type_str[] = { |
124 | "gw", | 124 | "gw", |
125 | "bla", | 125 | "bla", |
126 | }; | 126 | }; |
127 | 127 | ||
128 | /* Use this, if you have customized show and store functions for vlan attrs */ | 128 | /* Use this, if you have customized show and store functions for vlan attrs */ |
129 | #define BATADV_ATTR_VLAN(_name, _mode, _show, _store) \ | 129 | #define BATADV_ATTR_VLAN(_name, _mode, _show, _store) \ |
130 | struct batadv_attribute batadv_attr_vlan_##_name = { \ | 130 | struct batadv_attribute batadv_attr_vlan_##_name = { \ |
131 | .attr = {.name = __stringify(_name), \ | 131 | .attr = {.name = __stringify(_name), \ |
132 | .mode = _mode }, \ | 132 | .mode = _mode }, \ |
133 | .show = _show, \ | 133 | .show = _show, \ |
134 | .store = _store, \ | 134 | .store = _store, \ |
135 | } | 135 | } |
136 | 136 | ||
137 | /* Use this, if you have customized show and store functions */ | 137 | /* Use this, if you have customized show and store functions */ |
138 | #define BATADV_ATTR(_name, _mode, _show, _store) \ | 138 | #define BATADV_ATTR(_name, _mode, _show, _store) \ |
139 | struct batadv_attribute batadv_attr_##_name = { \ | 139 | struct batadv_attribute batadv_attr_##_name = { \ |
140 | .attr = {.name = __stringify(_name), \ | 140 | .attr = {.name = __stringify(_name), \ |
141 | .mode = _mode }, \ | 141 | .mode = _mode }, \ |
142 | .show = _show, \ | 142 | .show = _show, \ |
143 | .store = _store, \ | 143 | .store = _store, \ |
144 | } | 144 | } |
145 | 145 | ||
146 | #define BATADV_ATTR_SIF_STORE_BOOL(_name, _post_func) \ | 146 | #define BATADV_ATTR_SIF_STORE_BOOL(_name, _post_func) \ |
147 | ssize_t batadv_store_##_name(struct kobject *kobj, \ | 147 | ssize_t batadv_store_##_name(struct kobject *kobj, \ |
148 | struct attribute *attr, char *buff, \ | 148 | struct attribute *attr, char *buff, \ |
149 | size_t count) \ | 149 | size_t count) \ |
150 | { \ | 150 | { \ |
151 | struct net_device *net_dev = batadv_kobj_to_netdev(kobj); \ | 151 | struct net_device *net_dev = batadv_kobj_to_netdev(kobj); \ |
152 | struct batadv_priv *bat_priv = netdev_priv(net_dev); \ | 152 | struct batadv_priv *bat_priv = netdev_priv(net_dev); \ |
153 | \ | 153 | \ |
154 | return __batadv_store_bool_attr(buff, count, _post_func, attr, \ | 154 | return __batadv_store_bool_attr(buff, count, _post_func, attr, \ |
155 | &bat_priv->_name, net_dev); \ | 155 | &bat_priv->_name, net_dev); \ |
156 | } | 156 | } |
157 | 157 | ||
158 | #define BATADV_ATTR_SIF_SHOW_BOOL(_name) \ | 158 | #define BATADV_ATTR_SIF_SHOW_BOOL(_name) \ |
159 | ssize_t batadv_show_##_name(struct kobject *kobj, \ | 159 | ssize_t batadv_show_##_name(struct kobject *kobj, \ |
160 | struct attribute *attr, char *buff) \ | 160 | struct attribute *attr, char *buff) \ |
161 | { \ | 161 | { \ |
162 | struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj); \ | 162 | struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj); \ |
163 | \ | 163 | \ |
164 | return sprintf(buff, "%s\n", \ | 164 | return sprintf(buff, "%s\n", \ |
165 | atomic_read(&bat_priv->_name) == 0 ? \ | 165 | atomic_read(&bat_priv->_name) == 0 ? \ |
166 | "disabled" : "enabled"); \ | 166 | "disabled" : "enabled"); \ |
167 | } \ | 167 | } \ |
168 | 168 | ||
169 | /* Use this, if you are going to turn a [name] in the soft-interface | 169 | /* Use this, if you are going to turn a [name] in the soft-interface |
170 | * (bat_priv) on or off | 170 | * (bat_priv) on or off |
171 | */ | 171 | */ |
172 | #define BATADV_ATTR_SIF_BOOL(_name, _mode, _post_func) \ | 172 | #define BATADV_ATTR_SIF_BOOL(_name, _mode, _post_func) \ |
173 | static BATADV_ATTR_SIF_STORE_BOOL(_name, _post_func) \ | 173 | static BATADV_ATTR_SIF_STORE_BOOL(_name, _post_func) \ |
174 | static BATADV_ATTR_SIF_SHOW_BOOL(_name) \ | 174 | static BATADV_ATTR_SIF_SHOW_BOOL(_name) \ |
175 | static BATADV_ATTR(_name, _mode, batadv_show_##_name, \ | 175 | static BATADV_ATTR(_name, _mode, batadv_show_##_name, \ |
176 | batadv_store_##_name) | 176 | batadv_store_##_name) |
177 | 177 | ||
178 | #define BATADV_ATTR_SIF_STORE_UINT(_name, _var, _min, _max, _post_func) \ | 178 | #define BATADV_ATTR_SIF_STORE_UINT(_name, _var, _min, _max, _post_func) \ |
179 | ssize_t batadv_store_##_name(struct kobject *kobj, \ | 179 | ssize_t batadv_store_##_name(struct kobject *kobj, \ |
180 | struct attribute *attr, char *buff, \ | 180 | struct attribute *attr, char *buff, \ |
181 | size_t count) \ | 181 | size_t count) \ |
182 | { \ | 182 | { \ |
183 | struct net_device *net_dev = batadv_kobj_to_netdev(kobj); \ | 183 | struct net_device *net_dev = batadv_kobj_to_netdev(kobj); \ |
184 | struct batadv_priv *bat_priv = netdev_priv(net_dev); \ | 184 | struct batadv_priv *bat_priv = netdev_priv(net_dev); \ |
185 | \ | 185 | \ |
186 | return __batadv_store_uint_attr(buff, count, _min, _max, \ | 186 | return __batadv_store_uint_attr(buff, count, _min, _max, \ |
187 | _post_func, attr, \ | 187 | _post_func, attr, \ |
188 | &bat_priv->_var, net_dev); \ | 188 | &bat_priv->_var, net_dev); \ |
189 | } | 189 | } |
190 | 190 | ||
191 | #define BATADV_ATTR_SIF_SHOW_UINT(_name, _var) \ | 191 | #define BATADV_ATTR_SIF_SHOW_UINT(_name, _var) \ |
192 | ssize_t batadv_show_##_name(struct kobject *kobj, \ | 192 | ssize_t batadv_show_##_name(struct kobject *kobj, \ |
193 | struct attribute *attr, char *buff) \ | 193 | struct attribute *attr, char *buff) \ |
194 | { \ | 194 | { \ |
195 | struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj); \ | 195 | struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj); \ |
196 | \ | 196 | \ |
197 | return sprintf(buff, "%i\n", atomic_read(&bat_priv->_var)); \ | 197 | return sprintf(buff, "%i\n", atomic_read(&bat_priv->_var)); \ |
198 | } \ | 198 | } \ |
199 | 199 | ||
200 | /* Use this, if you are going to set [name] in the soft-interface | 200 | /* Use this, if you are going to set [name] in the soft-interface |
201 | * (bat_priv) to an unsigned integer value | 201 | * (bat_priv) to an unsigned integer value |
202 | */ | 202 | */ |
203 | #define BATADV_ATTR_SIF_UINT(_name, _var, _mode, _min, _max, _post_func)\ | 203 | #define BATADV_ATTR_SIF_UINT(_name, _var, _mode, _min, _max, _post_func)\ |
204 | static BATADV_ATTR_SIF_STORE_UINT(_name, _var, _min, _max, _post_func)\ | 204 | static BATADV_ATTR_SIF_STORE_UINT(_name, _var, _min, _max, _post_func)\ |
205 | static BATADV_ATTR_SIF_SHOW_UINT(_name, _var) \ | 205 | static BATADV_ATTR_SIF_SHOW_UINT(_name, _var) \ |
206 | static BATADV_ATTR(_name, _mode, batadv_show_##_name, \ | 206 | static BATADV_ATTR(_name, _mode, batadv_show_##_name, \ |
207 | batadv_store_##_name) | 207 | batadv_store_##_name) |
208 | 208 | ||
209 | #define BATADV_ATTR_VLAN_STORE_BOOL(_name, _post_func) \ | 209 | #define BATADV_ATTR_VLAN_STORE_BOOL(_name, _post_func) \ |
210 | ssize_t batadv_store_vlan_##_name(struct kobject *kobj, \ | 210 | ssize_t batadv_store_vlan_##_name(struct kobject *kobj, \ |
211 | struct attribute *attr, char *buff, \ | 211 | struct attribute *attr, char *buff, \ |
212 | size_t count) \ | 212 | size_t count) \ |
213 | { \ | 213 | { \ |
214 | struct batadv_priv *bat_priv = batadv_vlan_kobj_to_batpriv(kobj);\ | 214 | struct batadv_priv *bat_priv = batadv_vlan_kobj_to_batpriv(kobj);\ |
215 | struct batadv_softif_vlan *vlan = batadv_kobj_to_vlan(bat_priv, \ | 215 | struct batadv_softif_vlan *vlan = batadv_kobj_to_vlan(bat_priv, \ |
216 | kobj); \ | 216 | kobj); \ |
217 | size_t res = __batadv_store_bool_attr(buff, count, _post_func, \ | 217 | size_t res = __batadv_store_bool_attr(buff, count, _post_func, \ |
218 | attr, &vlan->_name, \ | 218 | attr, &vlan->_name, \ |
219 | bat_priv->soft_iface); \ | 219 | bat_priv->soft_iface); \ |
220 | \ | 220 | \ |
221 | batadv_softif_vlan_put(vlan); \ | 221 | batadv_softif_vlan_put(vlan); \ |
222 | return res; \ | 222 | return res; \ |
223 | } | 223 | } |
224 | 224 | ||
225 | #define BATADV_ATTR_VLAN_SHOW_BOOL(_name) \ | 225 | #define BATADV_ATTR_VLAN_SHOW_BOOL(_name) \ |
226 | ssize_t batadv_show_vlan_##_name(struct kobject *kobj, \ | 226 | ssize_t batadv_show_vlan_##_name(struct kobject *kobj, \ |
227 | struct attribute *attr, char *buff) \ | 227 | struct attribute *attr, char *buff) \ |
228 | { \ | 228 | { \ |
229 | struct batadv_priv *bat_priv = batadv_vlan_kobj_to_batpriv(kobj);\ | 229 | struct batadv_priv *bat_priv = batadv_vlan_kobj_to_batpriv(kobj);\ |
230 | struct batadv_softif_vlan *vlan = batadv_kobj_to_vlan(bat_priv, \ | 230 | struct batadv_softif_vlan *vlan = batadv_kobj_to_vlan(bat_priv, \ |
231 | kobj); \ | 231 | kobj); \ |
232 | size_t res = sprintf(buff, "%s\n", \ | 232 | size_t res = sprintf(buff, "%s\n", \ |
233 | atomic_read(&vlan->_name) == 0 ? \ | 233 | atomic_read(&vlan->_name) == 0 ? \ |
234 | "disabled" : "enabled"); \ | 234 | "disabled" : "enabled"); \ |
235 | \ | 235 | \ |
236 | batadv_softif_vlan_put(vlan); \ | 236 | batadv_softif_vlan_put(vlan); \ |
237 | return res; \ | 237 | return res; \ |
238 | } | 238 | } |
239 | 239 | ||
240 | /* Use this, if you are going to turn a [name] in the vlan struct on or off */ | 240 | /* Use this, if you are going to turn a [name] in the vlan struct on or off */ |
241 | #define BATADV_ATTR_VLAN_BOOL(_name, _mode, _post_func) \ | 241 | #define BATADV_ATTR_VLAN_BOOL(_name, _mode, _post_func) \ |
242 | static BATADV_ATTR_VLAN_STORE_BOOL(_name, _post_func) \ | 242 | static BATADV_ATTR_VLAN_STORE_BOOL(_name, _post_func) \ |
243 | static BATADV_ATTR_VLAN_SHOW_BOOL(_name) \ | 243 | static BATADV_ATTR_VLAN_SHOW_BOOL(_name) \ |
244 | static BATADV_ATTR_VLAN(_name, _mode, batadv_show_vlan_##_name, \ | 244 | static BATADV_ATTR_VLAN(_name, _mode, batadv_show_vlan_##_name, \ |
245 | batadv_store_vlan_##_name) | 245 | batadv_store_vlan_##_name) |
246 | 246 | ||
247 | #define BATADV_ATTR_HIF_STORE_UINT(_name, _var, _min, _max, _post_func) \ | 247 | #define BATADV_ATTR_HIF_STORE_UINT(_name, _var, _min, _max, _post_func) \ |
248 | ssize_t batadv_store_##_name(struct kobject *kobj, \ | 248 | ssize_t batadv_store_##_name(struct kobject *kobj, \ |
249 | struct attribute *attr, char *buff, \ | 249 | struct attribute *attr, char *buff, \ |
250 | size_t count) \ | 250 | size_t count) \ |
251 | { \ | 251 | { \ |
252 | struct net_device *net_dev = batadv_kobj_to_netdev(kobj); \ | 252 | struct net_device *net_dev = batadv_kobj_to_netdev(kobj); \ |
253 | struct batadv_hard_iface *hard_iface; \ | 253 | struct batadv_hard_iface *hard_iface; \ |
254 | ssize_t length; \ | 254 | ssize_t length; \ |
255 | \ | 255 | \ |
256 | hard_iface = batadv_hardif_get_by_netdev(net_dev); \ | 256 | hard_iface = batadv_hardif_get_by_netdev(net_dev); \ |
257 | if (!hard_iface) \ | 257 | if (!hard_iface) \ |
258 | return 0; \ | 258 | return 0; \ |
259 | \ | 259 | \ |
260 | length = __batadv_store_uint_attr(buff, count, _min, _max, \ | 260 | length = __batadv_store_uint_attr(buff, count, _min, _max, \ |
261 | _post_func, attr, \ | 261 | _post_func, attr, \ |
262 | &hard_iface->_var, net_dev); \ | 262 | &hard_iface->_var, net_dev); \ |
263 | \ | 263 | \ |
264 | batadv_hardif_put(hard_iface); \ | 264 | batadv_hardif_put(hard_iface); \ |
265 | return length; \ | 265 | return length; \ |
266 | } | 266 | } |
267 | 267 | ||
268 | #define BATADV_ATTR_HIF_SHOW_UINT(_name, _var) \ | 268 | #define BATADV_ATTR_HIF_SHOW_UINT(_name, _var) \ |
269 | ssize_t batadv_show_##_name(struct kobject *kobj, \ | 269 | ssize_t batadv_show_##_name(struct kobject *kobj, \ |
270 | struct attribute *attr, char *buff) \ | 270 | struct attribute *attr, char *buff) \ |
271 | { \ | 271 | { \ |
272 | struct net_device *net_dev = batadv_kobj_to_netdev(kobj); \ | 272 | struct net_device *net_dev = batadv_kobj_to_netdev(kobj); \ |
273 | struct batadv_hard_iface *hard_iface; \ | 273 | struct batadv_hard_iface *hard_iface; \ |
274 | ssize_t length; \ | 274 | ssize_t length; \ |
275 | \ | 275 | \ |
276 | hard_iface = batadv_hardif_get_by_netdev(net_dev); \ | 276 | hard_iface = batadv_hardif_get_by_netdev(net_dev); \ |
277 | if (!hard_iface) \ | 277 | if (!hard_iface) \ |
278 | return 0; \ | 278 | return 0; \ |
279 | \ | 279 | \ |
280 | length = sprintf(buff, "%i\n", atomic_read(&hard_iface->_var)); \ | 280 | length = sprintf(buff, "%i\n", atomic_read(&hard_iface->_var)); \ |
281 | \ | 281 | \ |
282 | batadv_hardif_put(hard_iface); \ | 282 | batadv_hardif_put(hard_iface); \ |
283 | return length; \ | 283 | return length; \ |
284 | } | 284 | } |
285 | 285 | ||
286 | /* Use this, if you are going to set [name] in hard_iface to an | 286 | /* Use this, if you are going to set [name] in hard_iface to an |
287 | * unsigned integer value | 287 | * unsigned integer value |
288 | */ | 288 | */ |
289 | #define BATADV_ATTR_HIF_UINT(_name, _var, _mode, _min, _max, _post_func)\ | 289 | #define BATADV_ATTR_HIF_UINT(_name, _var, _mode, _min, _max, _post_func)\ |
290 | static BATADV_ATTR_HIF_STORE_UINT(_name, _var, _min, \ | 290 | static BATADV_ATTR_HIF_STORE_UINT(_name, _var, _min, \ |
291 | _max, _post_func) \ | 291 | _max, _post_func) \ |
292 | static BATADV_ATTR_HIF_SHOW_UINT(_name, _var) \ | 292 | static BATADV_ATTR_HIF_SHOW_UINT(_name, _var) \ |
293 | static BATADV_ATTR(_name, _mode, batadv_show_##_name, \ | 293 | static BATADV_ATTR(_name, _mode, batadv_show_##_name, \ |
294 | batadv_store_##_name) | 294 | batadv_store_##_name) |
295 | 295 | ||
296 | static int batadv_store_bool_attr(char *buff, size_t count, | 296 | static int batadv_store_bool_attr(char *buff, size_t count, |
297 | struct net_device *net_dev, | 297 | struct net_device *net_dev, |
298 | const char *attr_name, atomic_t *attr, | 298 | const char *attr_name, atomic_t *attr, |
299 | bool *changed) | 299 | bool *changed) |
300 | { | 300 | { |
301 | int enabled = -1; | 301 | int enabled = -1; |
302 | 302 | ||
303 | *changed = false; | 303 | *changed = false; |
304 | 304 | ||
305 | if (buff[count - 1] == '\n') | 305 | if (buff[count - 1] == '\n') |
306 | buff[count - 1] = '\0'; | 306 | buff[count - 1] = '\0'; |
307 | 307 | ||
308 | if ((strncmp(buff, "1", 2) == 0) || | 308 | if ((strncmp(buff, "1", 2) == 0) || |
309 | (strncmp(buff, "enable", 7) == 0) || | 309 | (strncmp(buff, "enable", 7) == 0) || |
310 | (strncmp(buff, "enabled", 8) == 0)) | 310 | (strncmp(buff, "enabled", 8) == 0)) |
311 | enabled = 1; | 311 | enabled = 1; |
312 | 312 | ||
313 | if ((strncmp(buff, "0", 2) == 0) || | 313 | if ((strncmp(buff, "0", 2) == 0) || |
314 | (strncmp(buff, "disable", 8) == 0) || | 314 | (strncmp(buff, "disable", 8) == 0) || |
315 | (strncmp(buff, "disabled", 9) == 0)) | 315 | (strncmp(buff, "disabled", 9) == 0)) |
316 | enabled = 0; | 316 | enabled = 0; |
317 | 317 | ||
318 | if (enabled < 0) { | 318 | if (enabled < 0) { |
319 | batadv_info(net_dev, "%s: Invalid parameter received: %s\n", | 319 | batadv_info(net_dev, "%s: Invalid parameter received: %s\n", |
320 | attr_name, buff); | 320 | attr_name, buff); |
321 | return -EINVAL; | 321 | return -EINVAL; |
322 | } | 322 | } |
323 | 323 | ||
324 | if (atomic_read(attr) == enabled) | 324 | if (atomic_read(attr) == enabled) |
325 | return count; | 325 | return count; |
326 | 326 | ||
327 | batadv_info(net_dev, "%s: Changing from: %s to: %s\n", attr_name, | 327 | batadv_info(net_dev, "%s: Changing from: %s to: %s\n", attr_name, |
328 | atomic_read(attr) == 1 ? "enabled" : "disabled", | 328 | atomic_read(attr) == 1 ? "enabled" : "disabled", |
329 | enabled == 1 ? "enabled" : "disabled"); | 329 | enabled == 1 ? "enabled" : "disabled"); |
330 | 330 | ||
331 | *changed = true; | 331 | *changed = true; |
332 | 332 | ||
333 | atomic_set(attr, (unsigned int)enabled); | 333 | atomic_set(attr, (unsigned int)enabled); |
334 | return count; | 334 | return count; |
335 | } | 335 | } |
336 | 336 | ||
337 | static inline ssize_t | 337 | static inline ssize_t |
338 | __batadv_store_bool_attr(char *buff, size_t count, | 338 | __batadv_store_bool_attr(char *buff, size_t count, |
339 | void (*post_func)(struct net_device *), | 339 | void (*post_func)(struct net_device *), |
340 | struct attribute *attr, | 340 | struct attribute *attr, |
341 | atomic_t *attr_store, struct net_device *net_dev) | 341 | atomic_t *attr_store, struct net_device *net_dev) |
342 | { | 342 | { |
343 | bool changed; | 343 | bool changed; |
344 | int ret; | 344 | int ret; |
345 | 345 | ||
346 | ret = batadv_store_bool_attr(buff, count, net_dev, attr->name, | 346 | ret = batadv_store_bool_attr(buff, count, net_dev, attr->name, |
347 | attr_store, &changed); | 347 | attr_store, &changed); |
348 | if (post_func && changed) | 348 | if (post_func && changed) |
349 | post_func(net_dev); | 349 | post_func(net_dev); |
350 | 350 | ||
351 | return ret; | 351 | return ret; |
352 | } | 352 | } |
353 | 353 | ||
354 | static int batadv_store_uint_attr(const char *buff, size_t count, | 354 | static int batadv_store_uint_attr(const char *buff, size_t count, |
355 | struct net_device *net_dev, | 355 | struct net_device *net_dev, |
356 | const char *attr_name, | 356 | const char *attr_name, |
357 | unsigned int min, unsigned int max, | 357 | unsigned int min, unsigned int max, |
358 | atomic_t *attr) | 358 | atomic_t *attr) |
359 | { | 359 | { |
360 | unsigned long uint_val; | 360 | unsigned long uint_val; |
361 | int ret; | 361 | int ret; |
362 | 362 | ||
363 | ret = kstrtoul(buff, 10, &uint_val); | 363 | ret = kstrtoul(buff, 10, &uint_val); |
364 | if (ret) { | 364 | if (ret) { |
365 | batadv_info(net_dev, "%s: Invalid parameter received: %s\n", | 365 | batadv_info(net_dev, "%s: Invalid parameter received: %s\n", |
366 | attr_name, buff); | 366 | attr_name, buff); |
367 | return -EINVAL; | 367 | return -EINVAL; |
368 | } | 368 | } |
369 | 369 | ||
370 | if (uint_val < min) { | 370 | if (uint_val < min) { |
371 | batadv_info(net_dev, "%s: Value is too small: %lu min: %u\n", | 371 | batadv_info(net_dev, "%s: Value is too small: %lu min: %u\n", |
372 | attr_name, uint_val, min); | 372 | attr_name, uint_val, min); |
373 | return -EINVAL; | 373 | return -EINVAL; |
374 | } | 374 | } |
375 | 375 | ||
376 | if (uint_val > max) { | 376 | if (uint_val > max) { |
377 | batadv_info(net_dev, "%s: Value is too big: %lu max: %u\n", | 377 | batadv_info(net_dev, "%s: Value is too big: %lu max: %u\n", |
378 | attr_name, uint_val, max); | 378 | attr_name, uint_val, max); |
379 | return -EINVAL; | 379 | return -EINVAL; |
380 | } | 380 | } |
381 | 381 | ||
382 | if (atomic_read(attr) == uint_val) | 382 | if (atomic_read(attr) == uint_val) |
383 | return count; | 383 | return count; |
384 | 384 | ||
385 | batadv_info(net_dev, "%s: Changing from: %i to: %lu\n", | 385 | batadv_info(net_dev, "%s: Changing from: %i to: %lu\n", |
386 | attr_name, atomic_read(attr), uint_val); | 386 | attr_name, atomic_read(attr), uint_val); |
387 | 387 | ||
388 | atomic_set(attr, uint_val); | 388 | atomic_set(attr, uint_val); |
389 | return count; | 389 | return count; |
390 | } | 390 | } |
391 | 391 | ||
392 | static ssize_t __batadv_store_uint_attr(const char *buff, size_t count, | 392 | static ssize_t __batadv_store_uint_attr(const char *buff, size_t count, |
393 | int min, int max, | 393 | int min, int max, |
394 | void (*post_func)(struct net_device *), | 394 | void (*post_func)(struct net_device *), |
395 | const struct attribute *attr, | 395 | const struct attribute *attr, |
396 | atomic_t *attr_store, | 396 | atomic_t *attr_store, |
397 | struct net_device *net_dev) | 397 | struct net_device *net_dev) |
398 | { | 398 | { |
399 | int ret; | 399 | int ret; |
400 | 400 | ||
401 | ret = batadv_store_uint_attr(buff, count, net_dev, attr->name, min, max, | 401 | ret = batadv_store_uint_attr(buff, count, net_dev, attr->name, min, max, |
402 | attr_store); | 402 | attr_store); |
403 | if (post_func && ret) | 403 | if (post_func && ret) |
404 | post_func(net_dev); | 404 | post_func(net_dev); |
405 | 405 | ||
406 | return ret; | 406 | return ret; |
407 | } | 407 | } |
408 | 408 | ||
409 | static ssize_t batadv_show_bat_algo(struct kobject *kobj, | 409 | static ssize_t batadv_show_bat_algo(struct kobject *kobj, |
410 | struct attribute *attr, char *buff) | 410 | struct attribute *attr, char *buff) |
411 | { | 411 | { |
412 | struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj); | 412 | struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj); |
413 | 413 | ||
414 | return sprintf(buff, "%s\n", bat_priv->bat_algo_ops->name); | 414 | return sprintf(buff, "%s\n", bat_priv->bat_algo_ops->name); |
415 | } | 415 | } |
416 | 416 | ||
417 | static void batadv_post_gw_reselect(struct net_device *net_dev) | 417 | static void batadv_post_gw_reselect(struct net_device *net_dev) |
418 | { | 418 | { |
419 | struct batadv_priv *bat_priv = netdev_priv(net_dev); | 419 | struct batadv_priv *bat_priv = netdev_priv(net_dev); |
420 | 420 | ||
421 | batadv_gw_reselect(bat_priv); | 421 | batadv_gw_reselect(bat_priv); |
422 | } | 422 | } |
423 | 423 | ||
424 | static ssize_t batadv_show_gw_mode(struct kobject *kobj, struct attribute *attr, | 424 | static ssize_t batadv_show_gw_mode(struct kobject *kobj, struct attribute *attr, |
425 | char *buff) | 425 | char *buff) |
426 | { | 426 | { |
427 | struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj); | 427 | struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj); |
428 | int bytes_written; | 428 | int bytes_written; |
429 | 429 | ||
430 | switch (atomic_read(&bat_priv->gw_mode)) { | 430 | switch (atomic_read(&bat_priv->gw.mode)) { |
431 | case BATADV_GW_MODE_CLIENT: | 431 | case BATADV_GW_MODE_CLIENT: |
432 | bytes_written = sprintf(buff, "%s\n", | 432 | bytes_written = sprintf(buff, "%s\n", |
433 | BATADV_GW_MODE_CLIENT_NAME); | 433 | BATADV_GW_MODE_CLIENT_NAME); |
434 | break; | 434 | break; |
435 | case BATADV_GW_MODE_SERVER: | 435 | case BATADV_GW_MODE_SERVER: |
436 | bytes_written = sprintf(buff, "%s\n", | 436 | bytes_written = sprintf(buff, "%s\n", |
437 | BATADV_GW_MODE_SERVER_NAME); | 437 | BATADV_GW_MODE_SERVER_NAME); |
438 | break; | 438 | break; |
439 | default: | 439 | default: |
440 | bytes_written = sprintf(buff, "%s\n", | 440 | bytes_written = sprintf(buff, "%s\n", |
441 | BATADV_GW_MODE_OFF_NAME); | 441 | BATADV_GW_MODE_OFF_NAME); |
442 | break; | 442 | break; |
443 | } | 443 | } |
444 | 444 | ||
445 | return bytes_written; | 445 | return bytes_written; |
446 | } | 446 | } |
447 | 447 | ||
448 | static ssize_t batadv_store_gw_mode(struct kobject *kobj, | 448 | static ssize_t batadv_store_gw_mode(struct kobject *kobj, |
449 | struct attribute *attr, char *buff, | 449 | struct attribute *attr, char *buff, |
450 | size_t count) | 450 | size_t count) |
451 | { | 451 | { |
452 | struct net_device *net_dev = batadv_kobj_to_netdev(kobj); | 452 | struct net_device *net_dev = batadv_kobj_to_netdev(kobj); |
453 | struct batadv_priv *bat_priv = netdev_priv(net_dev); | 453 | struct batadv_priv *bat_priv = netdev_priv(net_dev); |
454 | char *curr_gw_mode_str; | 454 | char *curr_gw_mode_str; |
455 | int gw_mode_tmp = -1; | 455 | int gw_mode_tmp = -1; |
456 | 456 | ||
457 | if (buff[count - 1] == '\n') | 457 | if (buff[count - 1] == '\n') |
458 | buff[count - 1] = '\0'; | 458 | buff[count - 1] = '\0'; |
459 | 459 | ||
460 | if (strncmp(buff, BATADV_GW_MODE_OFF_NAME, | 460 | if (strncmp(buff, BATADV_GW_MODE_OFF_NAME, |
461 | strlen(BATADV_GW_MODE_OFF_NAME)) == 0) | 461 | strlen(BATADV_GW_MODE_OFF_NAME)) == 0) |
462 | gw_mode_tmp = BATADV_GW_MODE_OFF; | 462 | gw_mode_tmp = BATADV_GW_MODE_OFF; |
463 | 463 | ||
464 | if (strncmp(buff, BATADV_GW_MODE_CLIENT_NAME, | 464 | if (strncmp(buff, BATADV_GW_MODE_CLIENT_NAME, |
465 | strlen(BATADV_GW_MODE_CLIENT_NAME)) == 0) | 465 | strlen(BATADV_GW_MODE_CLIENT_NAME)) == 0) |
466 | gw_mode_tmp = BATADV_GW_MODE_CLIENT; | 466 | gw_mode_tmp = BATADV_GW_MODE_CLIENT; |
467 | 467 | ||
468 | if (strncmp(buff, BATADV_GW_MODE_SERVER_NAME, | 468 | if (strncmp(buff, BATADV_GW_MODE_SERVER_NAME, |
469 | strlen(BATADV_GW_MODE_SERVER_NAME)) == 0) | 469 | strlen(BATADV_GW_MODE_SERVER_NAME)) == 0) |
470 | gw_mode_tmp = BATADV_GW_MODE_SERVER; | 470 | gw_mode_tmp = BATADV_GW_MODE_SERVER; |
471 | 471 | ||
472 | if (gw_mode_tmp < 0) { | 472 | if (gw_mode_tmp < 0) { |
473 | batadv_info(net_dev, | 473 | batadv_info(net_dev, |
474 | "Invalid parameter for 'gw mode' setting received: %s\n", | 474 | "Invalid parameter for 'gw mode' setting received: %s\n", |
475 | buff); | 475 | buff); |
476 | return -EINVAL; | 476 | return -EINVAL; |
477 | } | 477 | } |
478 | 478 | ||
479 | if (atomic_read(&bat_priv->gw_mode) == gw_mode_tmp) | 479 | if (atomic_read(&bat_priv->gw.mode) == gw_mode_tmp) |
480 | return count; | 480 | return count; |
481 | 481 | ||
482 | switch (atomic_read(&bat_priv->gw_mode)) { | 482 | switch (atomic_read(&bat_priv->gw.mode)) { |
483 | case BATADV_GW_MODE_CLIENT: | 483 | case BATADV_GW_MODE_CLIENT: |
484 | curr_gw_mode_str = BATADV_GW_MODE_CLIENT_NAME; | 484 | curr_gw_mode_str = BATADV_GW_MODE_CLIENT_NAME; |
485 | break; | 485 | break; |
486 | case BATADV_GW_MODE_SERVER: | 486 | case BATADV_GW_MODE_SERVER: |
487 | curr_gw_mode_str = BATADV_GW_MODE_SERVER_NAME; | 487 | curr_gw_mode_str = BATADV_GW_MODE_SERVER_NAME; |
488 | break; | 488 | break; |
489 | default: | 489 | default: |
490 | curr_gw_mode_str = BATADV_GW_MODE_OFF_NAME; | 490 | curr_gw_mode_str = BATADV_GW_MODE_OFF_NAME; |
491 | break; | 491 | break; |
492 | } | 492 | } |
493 | 493 | ||
494 | batadv_info(net_dev, "Changing gw mode from: %s to: %s\n", | 494 | batadv_info(net_dev, "Changing gw mode from: %s to: %s\n", |
495 | curr_gw_mode_str, buff); | 495 | curr_gw_mode_str, buff); |
496 | 496 | ||
497 | /* Invoking batadv_gw_reselect() is not enough to really de-select the | 497 | /* Invoking batadv_gw_reselect() is not enough to really de-select the |
498 | * current GW. It will only instruct the gateway client code to perform | 498 | * current GW. It will only instruct the gateway client code to perform |
499 | * a re-election the next time that this is needed. | 499 | * a re-election the next time that this is needed. |
500 | * | 500 | * |
501 | * When gw client mode is being switched off the current GW must be | 501 | * When gw client mode is being switched off the current GW must be |
502 | * de-selected explicitly otherwise no GW_ADD uevent is thrown on | 502 | * de-selected explicitly otherwise no GW_ADD uevent is thrown on |
503 | * client mode re-activation. This is operation is performed in | 503 | * client mode re-activation. This is operation is performed in |
504 | * batadv_gw_check_client_stop(). | 504 | * batadv_gw_check_client_stop(). |
505 | */ | 505 | */ |
506 | batadv_gw_reselect(bat_priv); | 506 | batadv_gw_reselect(bat_priv); |
507 | /* always call batadv_gw_check_client_stop() before changing the gateway | 507 | /* always call batadv_gw_check_client_stop() before changing the gateway |
508 | * state | 508 | * state |
509 | */ | 509 | */ |
510 | batadv_gw_check_client_stop(bat_priv); | 510 | batadv_gw_check_client_stop(bat_priv); |
511 | atomic_set(&bat_priv->gw_mode, (unsigned int)gw_mode_tmp); | 511 | atomic_set(&bat_priv->gw.mode, (unsigned int)gw_mode_tmp); |
512 | batadv_gw_tvlv_container_update(bat_priv); | 512 | batadv_gw_tvlv_container_update(bat_priv); |
513 | return count; | 513 | return count; |
514 | } | 514 | } |
515 | 515 | ||
516 | static ssize_t batadv_show_gw_bwidth(struct kobject *kobj, | 516 | static ssize_t batadv_show_gw_bwidth(struct kobject *kobj, |
517 | struct attribute *attr, char *buff) | 517 | struct attribute *attr, char *buff) |
518 | { | 518 | { |
519 | struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj); | 519 | struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj); |
520 | u32 down, up; | 520 | u32 down, up; |
521 | 521 | ||
522 | down = atomic_read(&bat_priv->gw.bandwidth_down); | 522 | down = atomic_read(&bat_priv->gw.bandwidth_down); |
523 | up = atomic_read(&bat_priv->gw.bandwidth_up); | 523 | up = atomic_read(&bat_priv->gw.bandwidth_up); |
524 | 524 | ||
525 | return sprintf(buff, "%u.%u/%u.%u MBit\n", down / 10, | 525 | return sprintf(buff, "%u.%u/%u.%u MBit\n", down / 10, |
526 | down % 10, up / 10, up % 10); | 526 | down % 10, up / 10, up % 10); |
527 | } | 527 | } |
528 | 528 | ||
529 | static ssize_t batadv_store_gw_bwidth(struct kobject *kobj, | 529 | static ssize_t batadv_store_gw_bwidth(struct kobject *kobj, |
530 | struct attribute *attr, char *buff, | 530 | struct attribute *attr, char *buff, |
531 | size_t count) | 531 | size_t count) |
532 | { | 532 | { |
533 | struct net_device *net_dev = batadv_kobj_to_netdev(kobj); | 533 | struct net_device *net_dev = batadv_kobj_to_netdev(kobj); |
534 | 534 | ||
535 | if (buff[count - 1] == '\n') | 535 | if (buff[count - 1] == '\n') |
536 | buff[count - 1] = '\0'; | 536 | buff[count - 1] = '\0'; |
537 | 537 | ||
538 | return batadv_gw_bandwidth_set(net_dev, buff, count); | 538 | return batadv_gw_bandwidth_set(net_dev, buff, count); |
539 | } | 539 | } |
540 | 540 | ||
541 | /** | 541 | /** |
542 | * batadv_show_isolation_mark - print the current isolation mark/mask | 542 | * batadv_show_isolation_mark - print the current isolation mark/mask |
543 | * @kobj: kobject representing the private mesh sysfs directory | 543 | * @kobj: kobject representing the private mesh sysfs directory |
544 | * @attr: the batman-adv attribute the user is interacting with | 544 | * @attr: the batman-adv attribute the user is interacting with |
545 | * @buff: the buffer that will contain the data to send back to the user | 545 | * @buff: the buffer that will contain the data to send back to the user |
546 | * | 546 | * |
547 | * Return: the number of bytes written into 'buff' on success or a negative | 547 | * Return: the number of bytes written into 'buff' on success or a negative |
548 | * error code in case of failure | 548 | * error code in case of failure |
549 | */ | 549 | */ |
550 | static ssize_t batadv_show_isolation_mark(struct kobject *kobj, | 550 | static ssize_t batadv_show_isolation_mark(struct kobject *kobj, |
551 | struct attribute *attr, char *buff) | 551 | struct attribute *attr, char *buff) |
552 | { | 552 | { |
553 | struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj); | 553 | struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj); |
554 | 554 | ||
555 | return sprintf(buff, "%#.8x/%#.8x\n", bat_priv->isolation_mark, | 555 | return sprintf(buff, "%#.8x/%#.8x\n", bat_priv->isolation_mark, |
556 | bat_priv->isolation_mark_mask); | 556 | bat_priv->isolation_mark_mask); |
557 | } | 557 | } |
558 | 558 | ||
559 | /** | 559 | /** |
560 | * batadv_store_isolation_mark - parse and store the isolation mark/mask entered | 560 | * batadv_store_isolation_mark - parse and store the isolation mark/mask entered |
561 | * by the user | 561 | * by the user |
562 | * @kobj: kobject representing the private mesh sysfs directory | 562 | * @kobj: kobject representing the private mesh sysfs directory |
563 | * @attr: the batman-adv attribute the user is interacting with | 563 | * @attr: the batman-adv attribute the user is interacting with |
564 | * @buff: the buffer containing the user data | 564 | * @buff: the buffer containing the user data |
565 | * @count: number of bytes in the buffer | 565 | * @count: number of bytes in the buffer |
566 | * | 566 | * |
567 | * Return: 'count' on success or a negative error code in case of failure | 567 | * Return: 'count' on success or a negative error code in case of failure |
568 | */ | 568 | */ |
569 | static ssize_t batadv_store_isolation_mark(struct kobject *kobj, | 569 | static ssize_t batadv_store_isolation_mark(struct kobject *kobj, |
570 | struct attribute *attr, char *buff, | 570 | struct attribute *attr, char *buff, |
571 | size_t count) | 571 | size_t count) |
572 | { | 572 | { |
573 | struct net_device *net_dev = batadv_kobj_to_netdev(kobj); | 573 | struct net_device *net_dev = batadv_kobj_to_netdev(kobj); |
574 | struct batadv_priv *bat_priv = netdev_priv(net_dev); | 574 | struct batadv_priv *bat_priv = netdev_priv(net_dev); |
575 | u32 mark, mask; | 575 | u32 mark, mask; |
576 | char *mask_ptr; | 576 | char *mask_ptr; |
577 | 577 | ||
578 | /* parse the mask if it has been specified, otherwise assume the mask is | 578 | /* parse the mask if it has been specified, otherwise assume the mask is |
579 | * the biggest possible | 579 | * the biggest possible |
580 | */ | 580 | */ |
581 | mask = 0xFFFFFFFF; | 581 | mask = 0xFFFFFFFF; |
582 | mask_ptr = strchr(buff, '/'); | 582 | mask_ptr = strchr(buff, '/'); |
583 | if (mask_ptr) { | 583 | if (mask_ptr) { |
584 | *mask_ptr = '\0'; | 584 | *mask_ptr = '\0'; |
585 | mask_ptr++; | 585 | mask_ptr++; |
586 | 586 | ||
587 | /* the mask must be entered in hex base as it is going to be a | 587 | /* the mask must be entered in hex base as it is going to be a |
588 | * bitmask and not a prefix length | 588 | * bitmask and not a prefix length |
589 | */ | 589 | */ |
590 | if (kstrtou32(mask_ptr, 16, &mask) < 0) | 590 | if (kstrtou32(mask_ptr, 16, &mask) < 0) |
591 | return -EINVAL; | 591 | return -EINVAL; |
592 | } | 592 | } |
593 | 593 | ||
594 | /* the mark can be entered in any base */ | 594 | /* the mark can be entered in any base */ |
595 | if (kstrtou32(buff, 0, &mark) < 0) | 595 | if (kstrtou32(buff, 0, &mark) < 0) |
596 | return -EINVAL; | 596 | return -EINVAL; |
597 | 597 | ||
598 | bat_priv->isolation_mark_mask = mask; | 598 | bat_priv->isolation_mark_mask = mask; |
599 | /* erase bits not covered by the mask */ | 599 | /* erase bits not covered by the mask */ |
600 | bat_priv->isolation_mark = mark & bat_priv->isolation_mark_mask; | 600 | bat_priv->isolation_mark = mark & bat_priv->isolation_mark_mask; |
601 | 601 | ||
602 | batadv_info(net_dev, | 602 | batadv_info(net_dev, |
603 | "New skb mark for extended isolation: %#.8x/%#.8x\n", | 603 | "New skb mark for extended isolation: %#.8x/%#.8x\n", |
604 | bat_priv->isolation_mark, bat_priv->isolation_mark_mask); | 604 | bat_priv->isolation_mark, bat_priv->isolation_mark_mask); |
605 | 605 | ||
606 | return count; | 606 | return count; |
607 | } | 607 | } |
608 | 608 | ||
609 | BATADV_ATTR_SIF_BOOL(aggregated_ogms, S_IRUGO | S_IWUSR, NULL); | 609 | BATADV_ATTR_SIF_BOOL(aggregated_ogms, S_IRUGO | S_IWUSR, NULL); |
610 | BATADV_ATTR_SIF_BOOL(bonding, S_IRUGO | S_IWUSR, NULL); | 610 | BATADV_ATTR_SIF_BOOL(bonding, S_IRUGO | S_IWUSR, NULL); |
611 | #ifdef CONFIG_BATMAN_ADV_BLA | 611 | #ifdef CONFIG_BATMAN_ADV_BLA |
612 | BATADV_ATTR_SIF_BOOL(bridge_loop_avoidance, S_IRUGO | S_IWUSR, | 612 | BATADV_ATTR_SIF_BOOL(bridge_loop_avoidance, S_IRUGO | S_IWUSR, |
613 | batadv_bla_status_update); | 613 | batadv_bla_status_update); |
614 | #endif | 614 | #endif |
615 | #ifdef CONFIG_BATMAN_ADV_DAT | 615 | #ifdef CONFIG_BATMAN_ADV_DAT |
616 | BATADV_ATTR_SIF_BOOL(distributed_arp_table, S_IRUGO | S_IWUSR, | 616 | BATADV_ATTR_SIF_BOOL(distributed_arp_table, S_IRUGO | S_IWUSR, |
617 | batadv_dat_status_update); | 617 | batadv_dat_status_update); |
618 | #endif | 618 | #endif |
619 | BATADV_ATTR_SIF_BOOL(fragmentation, S_IRUGO | S_IWUSR, batadv_update_min_mtu); | 619 | BATADV_ATTR_SIF_BOOL(fragmentation, S_IRUGO | S_IWUSR, batadv_update_min_mtu); |
620 | static BATADV_ATTR(routing_algo, S_IRUGO, batadv_show_bat_algo, NULL); | 620 | static BATADV_ATTR(routing_algo, S_IRUGO, batadv_show_bat_algo, NULL); |
621 | static BATADV_ATTR(gw_mode, S_IRUGO | S_IWUSR, batadv_show_gw_mode, | 621 | static BATADV_ATTR(gw_mode, S_IRUGO | S_IWUSR, batadv_show_gw_mode, |
622 | batadv_store_gw_mode); | 622 | batadv_store_gw_mode); |
623 | BATADV_ATTR_SIF_UINT(orig_interval, orig_interval, S_IRUGO | S_IWUSR, | 623 | BATADV_ATTR_SIF_UINT(orig_interval, orig_interval, S_IRUGO | S_IWUSR, |
624 | 2 * BATADV_JITTER, INT_MAX, NULL); | 624 | 2 * BATADV_JITTER, INT_MAX, NULL); |
625 | BATADV_ATTR_SIF_UINT(hop_penalty, hop_penalty, S_IRUGO | S_IWUSR, 0, | 625 | BATADV_ATTR_SIF_UINT(hop_penalty, hop_penalty, S_IRUGO | S_IWUSR, 0, |
626 | BATADV_TQ_MAX_VALUE, NULL); | 626 | BATADV_TQ_MAX_VALUE, NULL); |
627 | BATADV_ATTR_SIF_UINT(gw_sel_class, gw_sel_class, S_IRUGO | S_IWUSR, 1, | 627 | BATADV_ATTR_SIF_UINT(gw_sel_class, gw.sel_class, S_IRUGO | S_IWUSR, 1, |
628 | BATADV_TQ_MAX_VALUE, batadv_post_gw_reselect); | 628 | BATADV_TQ_MAX_VALUE, batadv_post_gw_reselect); |
629 | static BATADV_ATTR(gw_bandwidth, S_IRUGO | S_IWUSR, batadv_show_gw_bwidth, | 629 | static BATADV_ATTR(gw_bandwidth, S_IRUGO | S_IWUSR, batadv_show_gw_bwidth, |
630 | batadv_store_gw_bwidth); | 630 | batadv_store_gw_bwidth); |
631 | #ifdef CONFIG_BATMAN_ADV_MCAST | 631 | #ifdef CONFIG_BATMAN_ADV_MCAST |
632 | BATADV_ATTR_SIF_BOOL(multicast_mode, S_IRUGO | S_IWUSR, NULL); | 632 | BATADV_ATTR_SIF_BOOL(multicast_mode, S_IRUGO | S_IWUSR, NULL); |
633 | #endif | 633 | #endif |
634 | #ifdef CONFIG_BATMAN_ADV_DEBUG | 634 | #ifdef CONFIG_BATMAN_ADV_DEBUG |
635 | BATADV_ATTR_SIF_UINT(log_level, log_level, S_IRUGO | S_IWUSR, 0, | 635 | BATADV_ATTR_SIF_UINT(log_level, log_level, S_IRUGO | S_IWUSR, 0, |
636 | BATADV_DBG_ALL, NULL); | 636 | BATADV_DBG_ALL, NULL); |
637 | #endif | 637 | #endif |
638 | #ifdef CONFIG_BATMAN_ADV_NC | 638 | #ifdef CONFIG_BATMAN_ADV_NC |
639 | BATADV_ATTR_SIF_BOOL(network_coding, S_IRUGO | S_IWUSR, | 639 | BATADV_ATTR_SIF_BOOL(network_coding, S_IRUGO | S_IWUSR, |
640 | batadv_nc_status_update); | 640 | batadv_nc_status_update); |
641 | #endif | 641 | #endif |
642 | static BATADV_ATTR(isolation_mark, S_IRUGO | S_IWUSR, | 642 | static BATADV_ATTR(isolation_mark, S_IRUGO | S_IWUSR, |
643 | batadv_show_isolation_mark, batadv_store_isolation_mark); | 643 | batadv_show_isolation_mark, batadv_store_isolation_mark); |
644 | 644 | ||
645 | static struct batadv_attribute *batadv_mesh_attrs[] = { | 645 | static struct batadv_attribute *batadv_mesh_attrs[] = { |
646 | &batadv_attr_aggregated_ogms, | 646 | &batadv_attr_aggregated_ogms, |
647 | &batadv_attr_bonding, | 647 | &batadv_attr_bonding, |
648 | #ifdef CONFIG_BATMAN_ADV_BLA | 648 | #ifdef CONFIG_BATMAN_ADV_BLA |
649 | &batadv_attr_bridge_loop_avoidance, | 649 | &batadv_attr_bridge_loop_avoidance, |
650 | #endif | 650 | #endif |
651 | #ifdef CONFIG_BATMAN_ADV_DAT | 651 | #ifdef CONFIG_BATMAN_ADV_DAT |
652 | &batadv_attr_distributed_arp_table, | 652 | &batadv_attr_distributed_arp_table, |
653 | #endif | 653 | #endif |
654 | #ifdef CONFIG_BATMAN_ADV_MCAST | 654 | #ifdef CONFIG_BATMAN_ADV_MCAST |
655 | &batadv_attr_multicast_mode, | 655 | &batadv_attr_multicast_mode, |
656 | #endif | 656 | #endif |
657 | &batadv_attr_fragmentation, | 657 | &batadv_attr_fragmentation, |
658 | &batadv_attr_routing_algo, | 658 | &batadv_attr_routing_algo, |
659 | &batadv_attr_gw_mode, | 659 | &batadv_attr_gw_mode, |
660 | &batadv_attr_orig_interval, | 660 | &batadv_attr_orig_interval, |
661 | &batadv_attr_hop_penalty, | 661 | &batadv_attr_hop_penalty, |
662 | &batadv_attr_gw_sel_class, | 662 | &batadv_attr_gw_sel_class, |
663 | &batadv_attr_gw_bandwidth, | 663 | &batadv_attr_gw_bandwidth, |
664 | #ifdef CONFIG_BATMAN_ADV_DEBUG | 664 | #ifdef CONFIG_BATMAN_ADV_DEBUG |
665 | &batadv_attr_log_level, | 665 | &batadv_attr_log_level, |
666 | #endif | 666 | #endif |
667 | #ifdef CONFIG_BATMAN_ADV_NC | 667 | #ifdef CONFIG_BATMAN_ADV_NC |
668 | &batadv_attr_network_coding, | 668 | &batadv_attr_network_coding, |
669 | #endif | 669 | #endif |
670 | &batadv_attr_isolation_mark, | 670 | &batadv_attr_isolation_mark, |
671 | NULL, | 671 | NULL, |
672 | }; | 672 | }; |
673 | 673 | ||
674 | BATADV_ATTR_VLAN_BOOL(ap_isolation, S_IRUGO | S_IWUSR, NULL); | 674 | BATADV_ATTR_VLAN_BOOL(ap_isolation, S_IRUGO | S_IWUSR, NULL); |
675 | 675 | ||
676 | /* array of vlan specific sysfs attributes */ | 676 | /* array of vlan specific sysfs attributes */ |
677 | static struct batadv_attribute *batadv_vlan_attrs[] = { | 677 | static struct batadv_attribute *batadv_vlan_attrs[] = { |
678 | &batadv_attr_vlan_ap_isolation, | 678 | &batadv_attr_vlan_ap_isolation, |
679 | NULL, | 679 | NULL, |
680 | }; | 680 | }; |
681 | 681 | ||
682 | int batadv_sysfs_add_meshif(struct net_device *dev) | 682 | int batadv_sysfs_add_meshif(struct net_device *dev) |
683 | { | 683 | { |
684 | struct kobject *batif_kobject = &dev->dev.kobj; | 684 | struct kobject *batif_kobject = &dev->dev.kobj; |
685 | struct batadv_priv *bat_priv = netdev_priv(dev); | 685 | struct batadv_priv *bat_priv = netdev_priv(dev); |
686 | struct batadv_attribute **bat_attr; | 686 | struct batadv_attribute **bat_attr; |
687 | int err; | 687 | int err; |
688 | 688 | ||
689 | bat_priv->mesh_obj = kobject_create_and_add(BATADV_SYSFS_IF_MESH_SUBDIR, | 689 | bat_priv->mesh_obj = kobject_create_and_add(BATADV_SYSFS_IF_MESH_SUBDIR, |
690 | batif_kobject); | 690 | batif_kobject); |
691 | if (!bat_priv->mesh_obj) { | 691 | if (!bat_priv->mesh_obj) { |
692 | batadv_err(dev, "Can't add sysfs directory: %s/%s\n", dev->name, | 692 | batadv_err(dev, "Can't add sysfs directory: %s/%s\n", dev->name, |
693 | BATADV_SYSFS_IF_MESH_SUBDIR); | 693 | BATADV_SYSFS_IF_MESH_SUBDIR); |
694 | goto out; | 694 | goto out; |
695 | } | 695 | } |
696 | 696 | ||
697 | for (bat_attr = batadv_mesh_attrs; *bat_attr; ++bat_attr) { | 697 | for (bat_attr = batadv_mesh_attrs; *bat_attr; ++bat_attr) { |
698 | err = sysfs_create_file(bat_priv->mesh_obj, | 698 | err = sysfs_create_file(bat_priv->mesh_obj, |
699 | &((*bat_attr)->attr)); | 699 | &((*bat_attr)->attr)); |
700 | if (err) { | 700 | if (err) { |
701 | batadv_err(dev, "Can't add sysfs file: %s/%s/%s\n", | 701 | batadv_err(dev, "Can't add sysfs file: %s/%s/%s\n", |
702 | dev->name, BATADV_SYSFS_IF_MESH_SUBDIR, | 702 | dev->name, BATADV_SYSFS_IF_MESH_SUBDIR, |
703 | ((*bat_attr)->attr).name); | 703 | ((*bat_attr)->attr).name); |
704 | goto rem_attr; | 704 | goto rem_attr; |
705 | } | 705 | } |
706 | } | 706 | } |
707 | 707 | ||
708 | return 0; | 708 | return 0; |
709 | 709 | ||
710 | rem_attr: | 710 | rem_attr: |
711 | for (bat_attr = batadv_mesh_attrs; *bat_attr; ++bat_attr) | 711 | for (bat_attr = batadv_mesh_attrs; *bat_attr; ++bat_attr) |
712 | sysfs_remove_file(bat_priv->mesh_obj, &((*bat_attr)->attr)); | 712 | sysfs_remove_file(bat_priv->mesh_obj, &((*bat_attr)->attr)); |
713 | 713 | ||
714 | kobject_put(bat_priv->mesh_obj); | 714 | kobject_put(bat_priv->mesh_obj); |
715 | bat_priv->mesh_obj = NULL; | 715 | bat_priv->mesh_obj = NULL; |
716 | out: | 716 | out: |
717 | return -ENOMEM; | 717 | return -ENOMEM; |
718 | } | 718 | } |
719 | 719 | ||
720 | void batadv_sysfs_del_meshif(struct net_device *dev) | 720 | void batadv_sysfs_del_meshif(struct net_device *dev) |
721 | { | 721 | { |
722 | struct batadv_priv *bat_priv = netdev_priv(dev); | 722 | struct batadv_priv *bat_priv = netdev_priv(dev); |
723 | struct batadv_attribute **bat_attr; | 723 | struct batadv_attribute **bat_attr; |
724 | 724 | ||
725 | for (bat_attr = batadv_mesh_attrs; *bat_attr; ++bat_attr) | 725 | for (bat_attr = batadv_mesh_attrs; *bat_attr; ++bat_attr) |
726 | sysfs_remove_file(bat_priv->mesh_obj, &((*bat_attr)->attr)); | 726 | sysfs_remove_file(bat_priv->mesh_obj, &((*bat_attr)->attr)); |
727 | 727 | ||
728 | kobject_put(bat_priv->mesh_obj); | 728 | kobject_put(bat_priv->mesh_obj); |
729 | bat_priv->mesh_obj = NULL; | 729 | bat_priv->mesh_obj = NULL; |
730 | } | 730 | } |
731 | 731 | ||
732 | /** | 732 | /** |
733 | * batadv_sysfs_add_vlan - add all the needed sysfs objects for the new vlan | 733 | * batadv_sysfs_add_vlan - add all the needed sysfs objects for the new vlan |
734 | * @dev: netdev of the mesh interface | 734 | * @dev: netdev of the mesh interface |
735 | * @vlan: private data of the newly added VLAN interface | 735 | * @vlan: private data of the newly added VLAN interface |
736 | * | 736 | * |
737 | * Return: 0 on success and -ENOMEM if any of the structure allocations fails. | 737 | * Return: 0 on success and -ENOMEM if any of the structure allocations fails. |
738 | */ | 738 | */ |
739 | int batadv_sysfs_add_vlan(struct net_device *dev, | 739 | int batadv_sysfs_add_vlan(struct net_device *dev, |
740 | struct batadv_softif_vlan *vlan) | 740 | struct batadv_softif_vlan *vlan) |
741 | { | 741 | { |
742 | char vlan_subdir[sizeof(BATADV_SYSFS_VLAN_SUBDIR_PREFIX) + 5]; | 742 | char vlan_subdir[sizeof(BATADV_SYSFS_VLAN_SUBDIR_PREFIX) + 5]; |
743 | struct batadv_priv *bat_priv = netdev_priv(dev); | 743 | struct batadv_priv *bat_priv = netdev_priv(dev); |
744 | struct batadv_attribute **bat_attr; | 744 | struct batadv_attribute **bat_attr; |
745 | int err; | 745 | int err; |
746 | 746 | ||
747 | if (vlan->vid & BATADV_VLAN_HAS_TAG) { | 747 | if (vlan->vid & BATADV_VLAN_HAS_TAG) { |
748 | sprintf(vlan_subdir, BATADV_SYSFS_VLAN_SUBDIR_PREFIX "%hu", | 748 | sprintf(vlan_subdir, BATADV_SYSFS_VLAN_SUBDIR_PREFIX "%hu", |
749 | vlan->vid & VLAN_VID_MASK); | 749 | vlan->vid & VLAN_VID_MASK); |
750 | 750 | ||
751 | vlan->kobj = kobject_create_and_add(vlan_subdir, | 751 | vlan->kobj = kobject_create_and_add(vlan_subdir, |
752 | bat_priv->mesh_obj); | 752 | bat_priv->mesh_obj); |
753 | if (!vlan->kobj) { | 753 | if (!vlan->kobj) { |
754 | batadv_err(dev, "Can't add sysfs directory: %s/%s\n", | 754 | batadv_err(dev, "Can't add sysfs directory: %s/%s\n", |
755 | dev->name, vlan_subdir); | 755 | dev->name, vlan_subdir); |
756 | goto out; | 756 | goto out; |
757 | } | 757 | } |
758 | } else { | 758 | } else { |
759 | /* the untagged LAN uses the root folder to store its "VLAN | 759 | /* the untagged LAN uses the root folder to store its "VLAN |
760 | * specific attributes" | 760 | * specific attributes" |
761 | */ | 761 | */ |
762 | vlan->kobj = bat_priv->mesh_obj; | 762 | vlan->kobj = bat_priv->mesh_obj; |
763 | kobject_get(bat_priv->mesh_obj); | 763 | kobject_get(bat_priv->mesh_obj); |
764 | } | 764 | } |
765 | 765 | ||
766 | for (bat_attr = batadv_vlan_attrs; *bat_attr; ++bat_attr) { | 766 | for (bat_attr = batadv_vlan_attrs; *bat_attr; ++bat_attr) { |
767 | err = sysfs_create_file(vlan->kobj, | 767 | err = sysfs_create_file(vlan->kobj, |
768 | &((*bat_attr)->attr)); | 768 | &((*bat_attr)->attr)); |
769 | if (err) { | 769 | if (err) { |
770 | batadv_err(dev, "Can't add sysfs file: %s/%s/%s\n", | 770 | batadv_err(dev, "Can't add sysfs file: %s/%s/%s\n", |
771 | dev->name, vlan_subdir, | 771 | dev->name, vlan_subdir, |
772 | ((*bat_attr)->attr).name); | 772 | ((*bat_attr)->attr).name); |
773 | goto rem_attr; | 773 | goto rem_attr; |
774 | } | 774 | } |
775 | } | 775 | } |
776 | 776 | ||
777 | return 0; | 777 | return 0; |
778 | 778 | ||
779 | rem_attr: | 779 | rem_attr: |
780 | for (bat_attr = batadv_vlan_attrs; *bat_attr; ++bat_attr) | 780 | for (bat_attr = batadv_vlan_attrs; *bat_attr; ++bat_attr) |
781 | sysfs_remove_file(vlan->kobj, &((*bat_attr)->attr)); | 781 | sysfs_remove_file(vlan->kobj, &((*bat_attr)->attr)); |
782 | 782 | ||
783 | kobject_put(vlan->kobj); | 783 | kobject_put(vlan->kobj); |
784 | vlan->kobj = NULL; | 784 | vlan->kobj = NULL; |
785 | out: | 785 | out: |
786 | return -ENOMEM; | 786 | return -ENOMEM; |
787 | } | 787 | } |
788 | 788 | ||
789 | /** | 789 | /** |
790 | * batadv_sysfs_del_vlan - remove all the sysfs objects for a given VLAN | 790 | * batadv_sysfs_del_vlan - remove all the sysfs objects for a given VLAN |
791 | * @bat_priv: the bat priv with all the soft interface information | 791 | * @bat_priv: the bat priv with all the soft interface information |
792 | * @vlan: the private data of the VLAN to destroy | 792 | * @vlan: the private data of the VLAN to destroy |
793 | */ | 793 | */ |
794 | void batadv_sysfs_del_vlan(struct batadv_priv *bat_priv, | 794 | void batadv_sysfs_del_vlan(struct batadv_priv *bat_priv, |
795 | struct batadv_softif_vlan *vlan) | 795 | struct batadv_softif_vlan *vlan) |
796 | { | 796 | { |
797 | struct batadv_attribute **bat_attr; | 797 | struct batadv_attribute **bat_attr; |
798 | 798 | ||
799 | for (bat_attr = batadv_vlan_attrs; *bat_attr; ++bat_attr) | 799 | for (bat_attr = batadv_vlan_attrs; *bat_attr; ++bat_attr) |
800 | sysfs_remove_file(vlan->kobj, &((*bat_attr)->attr)); | 800 | sysfs_remove_file(vlan->kobj, &((*bat_attr)->attr)); |
801 | 801 | ||
802 | kobject_put(vlan->kobj); | 802 | kobject_put(vlan->kobj); |
803 | vlan->kobj = NULL; | 803 | vlan->kobj = NULL; |
804 | } | 804 | } |
805 | 805 | ||
806 | static ssize_t batadv_show_mesh_iface(struct kobject *kobj, | 806 | static ssize_t batadv_show_mesh_iface(struct kobject *kobj, |
807 | struct attribute *attr, char *buff) | 807 | struct attribute *attr, char *buff) |
808 | { | 808 | { |
809 | struct net_device *net_dev = batadv_kobj_to_netdev(kobj); | 809 | struct net_device *net_dev = batadv_kobj_to_netdev(kobj); |
810 | struct batadv_hard_iface *hard_iface; | 810 | struct batadv_hard_iface *hard_iface; |
811 | ssize_t length; | 811 | ssize_t length; |
812 | const char *ifname; | 812 | const char *ifname; |
813 | 813 | ||
814 | hard_iface = batadv_hardif_get_by_netdev(net_dev); | 814 | hard_iface = batadv_hardif_get_by_netdev(net_dev); |
815 | if (!hard_iface) | 815 | if (!hard_iface) |
816 | return 0; | 816 | return 0; |
817 | 817 | ||
818 | if (hard_iface->if_status == BATADV_IF_NOT_IN_USE) | 818 | if (hard_iface->if_status == BATADV_IF_NOT_IN_USE) |
819 | ifname = "none"; | 819 | ifname = "none"; |
820 | else | 820 | else |
821 | ifname = hard_iface->soft_iface->name; | 821 | ifname = hard_iface->soft_iface->name; |
822 | 822 | ||
823 | length = sprintf(buff, "%s\n", ifname); | 823 | length = sprintf(buff, "%s\n", ifname); |
824 | 824 | ||
825 | batadv_hardif_put(hard_iface); | 825 | batadv_hardif_put(hard_iface); |
826 | 826 | ||
827 | return length; | 827 | return length; |
828 | } | 828 | } |
829 | 829 | ||
830 | static ssize_t batadv_store_mesh_iface(struct kobject *kobj, | 830 | static ssize_t batadv_store_mesh_iface(struct kobject *kobj, |
831 | struct attribute *attr, char *buff, | 831 | struct attribute *attr, char *buff, |
832 | size_t count) | 832 | size_t count) |
833 | { | 833 | { |
834 | struct net_device *net_dev = batadv_kobj_to_netdev(kobj); | 834 | struct net_device *net_dev = batadv_kobj_to_netdev(kobj); |
835 | struct net *net = dev_net(net_dev); | 835 | struct net *net = dev_net(net_dev); |
836 | struct batadv_hard_iface *hard_iface; | 836 | struct batadv_hard_iface *hard_iface; |
837 | int status_tmp = -1; | 837 | int status_tmp = -1; |
838 | int ret = count; | 838 | int ret = count; |
839 | 839 | ||
840 | hard_iface = batadv_hardif_get_by_netdev(net_dev); | 840 | hard_iface = batadv_hardif_get_by_netdev(net_dev); |
841 | if (!hard_iface) | 841 | if (!hard_iface) |
842 | return count; | 842 | return count; |
843 | 843 | ||
844 | if (buff[count - 1] == '\n') | 844 | if (buff[count - 1] == '\n') |
845 | buff[count - 1] = '\0'; | 845 | buff[count - 1] = '\0'; |
846 | 846 | ||
847 | if (strlen(buff) >= IFNAMSIZ) { | 847 | if (strlen(buff) >= IFNAMSIZ) { |
848 | pr_err("Invalid parameter for 'mesh_iface' setting received: interface name too long '%s'\n", | 848 | pr_err("Invalid parameter for 'mesh_iface' setting received: interface name too long '%s'\n", |
849 | buff); | 849 | buff); |
850 | batadv_hardif_put(hard_iface); | 850 | batadv_hardif_put(hard_iface); |
851 | return -EINVAL; | 851 | return -EINVAL; |
852 | } | 852 | } |
853 | 853 | ||
854 | if (strncmp(buff, "none", 4) == 0) | 854 | if (strncmp(buff, "none", 4) == 0) |
855 | status_tmp = BATADV_IF_NOT_IN_USE; | 855 | status_tmp = BATADV_IF_NOT_IN_USE; |
856 | else | 856 | else |
857 | status_tmp = BATADV_IF_I_WANT_YOU; | 857 | status_tmp = BATADV_IF_I_WANT_YOU; |
858 | 858 | ||
859 | if (hard_iface->if_status == status_tmp) | 859 | if (hard_iface->if_status == status_tmp) |
860 | goto out; | 860 | goto out; |
861 | 861 | ||
862 | if ((hard_iface->soft_iface) && | 862 | if ((hard_iface->soft_iface) && |
863 | (strncmp(hard_iface->soft_iface->name, buff, IFNAMSIZ) == 0)) | 863 | (strncmp(hard_iface->soft_iface->name, buff, IFNAMSIZ) == 0)) |
864 | goto out; | 864 | goto out; |
865 | 865 | ||
866 | rtnl_lock(); | 866 | rtnl_lock(); |
867 | 867 | ||
868 | if (status_tmp == BATADV_IF_NOT_IN_USE) { | 868 | if (status_tmp == BATADV_IF_NOT_IN_USE) { |
869 | batadv_hardif_disable_interface(hard_iface, | 869 | batadv_hardif_disable_interface(hard_iface, |
870 | BATADV_IF_CLEANUP_AUTO); | 870 | BATADV_IF_CLEANUP_AUTO); |
871 | goto unlock; | 871 | goto unlock; |
872 | } | 872 | } |
873 | 873 | ||
874 | /* if the interface already is in use */ | 874 | /* if the interface already is in use */ |
875 | if (hard_iface->if_status != BATADV_IF_NOT_IN_USE) | 875 | if (hard_iface->if_status != BATADV_IF_NOT_IN_USE) |
876 | batadv_hardif_disable_interface(hard_iface, | 876 | batadv_hardif_disable_interface(hard_iface, |
877 | BATADV_IF_CLEANUP_AUTO); | 877 | BATADV_IF_CLEANUP_AUTO); |
878 | 878 | ||
879 | ret = batadv_hardif_enable_interface(hard_iface, net, buff); | 879 | ret = batadv_hardif_enable_interface(hard_iface, net, buff); |
880 | 880 | ||
881 | unlock: | 881 | unlock: |
882 | rtnl_unlock(); | 882 | rtnl_unlock(); |
883 | out: | 883 | out: |
884 | batadv_hardif_put(hard_iface); | 884 | batadv_hardif_put(hard_iface); |
885 | return ret; | 885 | return ret; |
886 | } | 886 | } |
887 | 887 | ||
888 | static ssize_t batadv_show_iface_status(struct kobject *kobj, | 888 | static ssize_t batadv_show_iface_status(struct kobject *kobj, |
889 | struct attribute *attr, char *buff) | 889 | struct attribute *attr, char *buff) |
890 | { | 890 | { |
891 | struct net_device *net_dev = batadv_kobj_to_netdev(kobj); | 891 | struct net_device *net_dev = batadv_kobj_to_netdev(kobj); |
892 | struct batadv_hard_iface *hard_iface; | 892 | struct batadv_hard_iface *hard_iface; |
893 | ssize_t length; | 893 | ssize_t length; |
894 | 894 | ||
895 | hard_iface = batadv_hardif_get_by_netdev(net_dev); | 895 | hard_iface = batadv_hardif_get_by_netdev(net_dev); |
896 | if (!hard_iface) | 896 | if (!hard_iface) |
897 | return 0; | 897 | return 0; |
898 | 898 | ||
899 | switch (hard_iface->if_status) { | 899 | switch (hard_iface->if_status) { |
900 | case BATADV_IF_TO_BE_REMOVED: | 900 | case BATADV_IF_TO_BE_REMOVED: |
901 | length = sprintf(buff, "disabling\n"); | 901 | length = sprintf(buff, "disabling\n"); |
902 | break; | 902 | break; |
903 | case BATADV_IF_INACTIVE: | 903 | case BATADV_IF_INACTIVE: |
904 | length = sprintf(buff, "inactive\n"); | 904 | length = sprintf(buff, "inactive\n"); |
905 | break; | 905 | break; |
906 | case BATADV_IF_ACTIVE: | 906 | case BATADV_IF_ACTIVE: |
907 | length = sprintf(buff, "active\n"); | 907 | length = sprintf(buff, "active\n"); |
908 | break; | 908 | break; |
909 | case BATADV_IF_TO_BE_ACTIVATED: | 909 | case BATADV_IF_TO_BE_ACTIVATED: |
910 | length = sprintf(buff, "enabling\n"); | 910 | length = sprintf(buff, "enabling\n"); |
911 | break; | 911 | break; |
912 | case BATADV_IF_NOT_IN_USE: | 912 | case BATADV_IF_NOT_IN_USE: |
913 | default: | 913 | default: |
914 | length = sprintf(buff, "not in use\n"); | 914 | length = sprintf(buff, "not in use\n"); |
915 | break; | 915 | break; |
916 | } | 916 | } |
917 | 917 | ||
918 | batadv_hardif_put(hard_iface); | 918 | batadv_hardif_put(hard_iface); |
919 | 919 | ||
920 | return length; | 920 | return length; |
921 | } | 921 | } |
922 | 922 | ||
923 | #ifdef CONFIG_BATMAN_ADV_BATMAN_V | 923 | #ifdef CONFIG_BATMAN_ADV_BATMAN_V |
924 | 924 | ||
925 | /** | 925 | /** |
926 | * batadv_store_throughput_override - parse and store throughput override | 926 | * batadv_store_throughput_override - parse and store throughput override |
927 | * entered by the user | 927 | * entered by the user |
928 | * @kobj: kobject representing the private mesh sysfs directory | 928 | * @kobj: kobject representing the private mesh sysfs directory |
929 | * @attr: the batman-adv attribute the user is interacting with | 929 | * @attr: the batman-adv attribute the user is interacting with |
930 | * @buff: the buffer containing the user data | 930 | * @buff: the buffer containing the user data |
931 | * @count: number of bytes in the buffer | 931 | * @count: number of bytes in the buffer |
932 | * | 932 | * |
933 | * Return: 'count' on success or a negative error code in case of failure | 933 | * Return: 'count' on success or a negative error code in case of failure |
934 | */ | 934 | */ |
935 | static ssize_t batadv_store_throughput_override(struct kobject *kobj, | 935 | static ssize_t batadv_store_throughput_override(struct kobject *kobj, |
936 | struct attribute *attr, | 936 | struct attribute *attr, |
937 | char *buff, size_t count) | 937 | char *buff, size_t count) |
938 | { | 938 | { |
939 | struct net_device *net_dev = batadv_kobj_to_netdev(kobj); | 939 | struct net_device *net_dev = batadv_kobj_to_netdev(kobj); |
940 | struct batadv_hard_iface *hard_iface; | 940 | struct batadv_hard_iface *hard_iface; |
941 | u32 tp_override; | 941 | u32 tp_override; |
942 | u32 old_tp_override; | 942 | u32 old_tp_override; |
943 | bool ret; | 943 | bool ret; |
944 | 944 | ||
945 | hard_iface = batadv_hardif_get_by_netdev(net_dev); | 945 | hard_iface = batadv_hardif_get_by_netdev(net_dev); |
946 | if (!hard_iface) | 946 | if (!hard_iface) |
947 | return -EINVAL; | 947 | return -EINVAL; |
948 | 948 | ||
949 | if (buff[count - 1] == '\n') | 949 | if (buff[count - 1] == '\n') |
950 | buff[count - 1] = '\0'; | 950 | buff[count - 1] = '\0'; |
951 | 951 | ||
952 | ret = batadv_parse_throughput(net_dev, buff, "throughput_override", | 952 | ret = batadv_parse_throughput(net_dev, buff, "throughput_override", |
953 | &tp_override); | 953 | &tp_override); |
954 | if (!ret) | 954 | if (!ret) |
955 | return count; | 955 | return count; |
956 | 956 | ||
957 | old_tp_override = atomic_read(&hard_iface->bat_v.throughput_override); | 957 | old_tp_override = atomic_read(&hard_iface->bat_v.throughput_override); |
958 | if (old_tp_override == tp_override) | 958 | if (old_tp_override == tp_override) |
959 | goto out; | 959 | goto out; |
960 | 960 | ||
961 | batadv_info(net_dev, "%s: Changing from: %u.%u MBit to: %u.%u MBit\n", | 961 | batadv_info(net_dev, "%s: Changing from: %u.%u MBit to: %u.%u MBit\n", |
962 | "throughput_override", | 962 | "throughput_override", |
963 | old_tp_override / 10, old_tp_override % 10, | 963 | old_tp_override / 10, old_tp_override % 10, |
964 | tp_override / 10, tp_override % 10); | 964 | tp_override / 10, tp_override % 10); |
965 | 965 | ||
966 | atomic_set(&hard_iface->bat_v.throughput_override, tp_override); | 966 | atomic_set(&hard_iface->bat_v.throughput_override, tp_override); |
967 | 967 | ||
968 | out: | 968 | out: |
969 | batadv_hardif_put(hard_iface); | 969 | batadv_hardif_put(hard_iface); |
970 | return count; | 970 | return count; |
971 | } | 971 | } |
972 | 972 | ||
973 | static ssize_t batadv_show_throughput_override(struct kobject *kobj, | 973 | static ssize_t batadv_show_throughput_override(struct kobject *kobj, |
974 | struct attribute *attr, | 974 | struct attribute *attr, |
975 | char *buff) | 975 | char *buff) |
976 | { | 976 | { |
977 | struct net_device *net_dev = batadv_kobj_to_netdev(kobj); | 977 | struct net_device *net_dev = batadv_kobj_to_netdev(kobj); |
978 | struct batadv_hard_iface *hard_iface; | 978 | struct batadv_hard_iface *hard_iface; |
979 | u32 tp_override; | 979 | u32 tp_override; |
980 | 980 | ||
981 | hard_iface = batadv_hardif_get_by_netdev(net_dev); | 981 | hard_iface = batadv_hardif_get_by_netdev(net_dev); |
982 | if (!hard_iface) | 982 | if (!hard_iface) |
983 | return -EINVAL; | 983 | return -EINVAL; |
984 | 984 | ||
985 | tp_override = atomic_read(&hard_iface->bat_v.throughput_override); | 985 | tp_override = atomic_read(&hard_iface->bat_v.throughput_override); |
986 | 986 | ||
987 | return sprintf(buff, "%u.%u MBit\n", tp_override / 10, | 987 | return sprintf(buff, "%u.%u MBit\n", tp_override / 10, |
988 | tp_override % 10); | 988 | tp_override % 10); |
989 | } | 989 | } |
990 | 990 | ||
991 | #endif | 991 | #endif |
992 | 992 | ||
993 | static BATADV_ATTR(mesh_iface, S_IRUGO | S_IWUSR, batadv_show_mesh_iface, | 993 | static BATADV_ATTR(mesh_iface, S_IRUGO | S_IWUSR, batadv_show_mesh_iface, |
994 | batadv_store_mesh_iface); | 994 | batadv_store_mesh_iface); |
995 | static BATADV_ATTR(iface_status, S_IRUGO, batadv_show_iface_status, NULL); | 995 | static BATADV_ATTR(iface_status, S_IRUGO, batadv_show_iface_status, NULL); |
996 | #ifdef CONFIG_BATMAN_ADV_BATMAN_V | 996 | #ifdef CONFIG_BATMAN_ADV_BATMAN_V |
997 | BATADV_ATTR_HIF_UINT(elp_interval, bat_v.elp_interval, S_IRUGO | S_IWUSR, | 997 | BATADV_ATTR_HIF_UINT(elp_interval, bat_v.elp_interval, S_IRUGO | S_IWUSR, |
998 | 2 * BATADV_JITTER, INT_MAX, NULL); | 998 | 2 * BATADV_JITTER, INT_MAX, NULL); |
999 | static BATADV_ATTR(throughput_override, S_IRUGO | S_IWUSR, | 999 | static BATADV_ATTR(throughput_override, S_IRUGO | S_IWUSR, |
1000 | batadv_show_throughput_override, | 1000 | batadv_show_throughput_override, |
1001 | batadv_store_throughput_override); | 1001 | batadv_store_throughput_override); |
1002 | #endif | 1002 | #endif |
1003 | 1003 | ||
1004 | static struct batadv_attribute *batadv_batman_attrs[] = { | 1004 | static struct batadv_attribute *batadv_batman_attrs[] = { |
1005 | &batadv_attr_mesh_iface, | 1005 | &batadv_attr_mesh_iface, |
1006 | &batadv_attr_iface_status, | 1006 | &batadv_attr_iface_status, |
1007 | #ifdef CONFIG_BATMAN_ADV_BATMAN_V | 1007 | #ifdef CONFIG_BATMAN_ADV_BATMAN_V |
1008 | &batadv_attr_elp_interval, | 1008 | &batadv_attr_elp_interval, |
1009 | &batadv_attr_throughput_override, | 1009 | &batadv_attr_throughput_override, |
1010 | #endif | 1010 | #endif |
1011 | NULL, | 1011 | NULL, |
1012 | }; | 1012 | }; |
1013 | 1013 | ||
1014 | int batadv_sysfs_add_hardif(struct kobject **hardif_obj, struct net_device *dev) | 1014 | int batadv_sysfs_add_hardif(struct kobject **hardif_obj, struct net_device *dev) |
1015 | { | 1015 | { |
1016 | struct kobject *hardif_kobject = &dev->dev.kobj; | 1016 | struct kobject *hardif_kobject = &dev->dev.kobj; |
1017 | struct batadv_attribute **bat_attr; | 1017 | struct batadv_attribute **bat_attr; |
1018 | int err; | 1018 | int err; |
1019 | 1019 | ||
1020 | *hardif_obj = kobject_create_and_add(BATADV_SYSFS_IF_BAT_SUBDIR, | 1020 | *hardif_obj = kobject_create_and_add(BATADV_SYSFS_IF_BAT_SUBDIR, |
1021 | hardif_kobject); | 1021 | hardif_kobject); |
1022 | 1022 | ||
1023 | if (!*hardif_obj) { | 1023 | if (!*hardif_obj) { |
1024 | batadv_err(dev, "Can't add sysfs directory: %s/%s\n", dev->name, | 1024 | batadv_err(dev, "Can't add sysfs directory: %s/%s\n", dev->name, |
1025 | BATADV_SYSFS_IF_BAT_SUBDIR); | 1025 | BATADV_SYSFS_IF_BAT_SUBDIR); |
1026 | goto out; | 1026 | goto out; |
1027 | } | 1027 | } |
1028 | 1028 | ||
1029 | for (bat_attr = batadv_batman_attrs; *bat_attr; ++bat_attr) { | 1029 | for (bat_attr = batadv_batman_attrs; *bat_attr; ++bat_attr) { |
1030 | err = sysfs_create_file(*hardif_obj, &((*bat_attr)->attr)); | 1030 | err = sysfs_create_file(*hardif_obj, &((*bat_attr)->attr)); |
1031 | if (err) { | 1031 | if (err) { |
1032 | batadv_err(dev, "Can't add sysfs file: %s/%s/%s\n", | 1032 | batadv_err(dev, "Can't add sysfs file: %s/%s/%s\n", |
1033 | dev->name, BATADV_SYSFS_IF_BAT_SUBDIR, | 1033 | dev->name, BATADV_SYSFS_IF_BAT_SUBDIR, |
1034 | ((*bat_attr)->attr).name); | 1034 | ((*bat_attr)->attr).name); |
1035 | goto rem_attr; | 1035 | goto rem_attr; |
1036 | } | 1036 | } |
1037 | } | 1037 | } |
1038 | 1038 | ||
1039 | return 0; | 1039 | return 0; |
1040 | 1040 | ||
1041 | rem_attr: | 1041 | rem_attr: |
1042 | for (bat_attr = batadv_batman_attrs; *bat_attr; ++bat_attr) | 1042 | for (bat_attr = batadv_batman_attrs; *bat_attr; ++bat_attr) |
1043 | sysfs_remove_file(*hardif_obj, &((*bat_attr)->attr)); | 1043 | sysfs_remove_file(*hardif_obj, &((*bat_attr)->attr)); |
1044 | out: | 1044 | out: |
1045 | return -ENOMEM; | 1045 | return -ENOMEM; |
1046 | } | 1046 | } |
1047 | 1047 | ||
1048 | void batadv_sysfs_del_hardif(struct kobject **hardif_obj) | 1048 | void batadv_sysfs_del_hardif(struct kobject **hardif_obj) |
1049 | { | 1049 | { |
1050 | kobject_put(*hardif_obj); | 1050 | kobject_put(*hardif_obj); |
1051 | *hardif_obj = NULL; | 1051 | *hardif_obj = NULL; |
1052 | } | 1052 | } |
1053 | 1053 | ||
1054 | int batadv_throw_uevent(struct batadv_priv *bat_priv, enum batadv_uev_type type, | 1054 | int batadv_throw_uevent(struct batadv_priv *bat_priv, enum batadv_uev_type type, |
1055 | enum batadv_uev_action action, const char *data) | 1055 | enum batadv_uev_action action, const char *data) |
1056 | { | 1056 | { |
1057 | int ret = -ENOMEM; | 1057 | int ret = -ENOMEM; |
1058 | struct kobject *bat_kobj; | 1058 | struct kobject *bat_kobj; |
1059 | char *uevent_env[4] = { NULL, NULL, NULL, NULL }; | 1059 | char *uevent_env[4] = { NULL, NULL, NULL, NULL }; |
1060 | 1060 | ||
1061 | bat_kobj = &bat_priv->soft_iface->dev.kobj; | 1061 | bat_kobj = &bat_priv->soft_iface->dev.kobj; |
1062 | 1062 | ||
1063 | uevent_env[0] = kasprintf(GFP_ATOMIC, | 1063 | uevent_env[0] = kasprintf(GFP_ATOMIC, |
1064 | "%s%s", BATADV_UEV_TYPE_VAR, | 1064 | "%s%s", BATADV_UEV_TYPE_VAR, |
1065 | batadv_uev_type_str[type]); | 1065 | batadv_uev_type_str[type]); |
1066 | if (!uevent_env[0]) | 1066 | if (!uevent_env[0]) |
1067 | goto out; | 1067 | goto out; |
1068 | 1068 | ||
1069 | uevent_env[1] = kasprintf(GFP_ATOMIC, | 1069 | uevent_env[1] = kasprintf(GFP_ATOMIC, |
1070 | "%s%s", BATADV_UEV_ACTION_VAR, | 1070 | "%s%s", BATADV_UEV_ACTION_VAR, |
1071 | batadv_uev_action_str[action]); | 1071 | batadv_uev_action_str[action]); |
1072 | if (!uevent_env[1]) | 1072 | if (!uevent_env[1]) |
1073 | goto out; | 1073 | goto out; |
1074 | 1074 | ||
1075 | /* If the event is DEL, ignore the data field */ | 1075 | /* If the event is DEL, ignore the data field */ |
1076 | if (action != BATADV_UEV_DEL) { | 1076 | if (action != BATADV_UEV_DEL) { |
1077 | uevent_env[2] = kasprintf(GFP_ATOMIC, | 1077 | uevent_env[2] = kasprintf(GFP_ATOMIC, |
1078 | "%s%s", BATADV_UEV_DATA_VAR, data); | 1078 | "%s%s", BATADV_UEV_DATA_VAR, data); |
1079 | if (!uevent_env[2]) | 1079 | if (!uevent_env[2]) |
1080 | goto out; | 1080 | goto out; |
1081 | } | 1081 | } |
1082 | 1082 | ||
1083 | ret = kobject_uevent_env(bat_kobj, KOBJ_CHANGE, uevent_env); | 1083 | ret = kobject_uevent_env(bat_kobj, KOBJ_CHANGE, uevent_env); |
1084 | out: | 1084 | out: |
1085 | kfree(uevent_env[0]); | 1085 | kfree(uevent_env[0]); |
1086 | kfree(uevent_env[1]); | 1086 | kfree(uevent_env[1]); |
1087 | kfree(uevent_env[2]); | 1087 | kfree(uevent_env[2]); |
1088 | 1088 | ||
1089 | if (ret) | 1089 | if (ret) |
1090 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, | 1090 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, |
1091 | "Impossible to send uevent for (%s,%s,%s) event (err: %d)\n", | 1091 | "Impossible to send uevent for (%s,%s,%s) event (err: %d)\n", |
1092 | batadv_uev_type_str[type], | 1092 | batadv_uev_type_str[type], |
1093 | batadv_uev_action_str[action], | 1093 | batadv_uev_action_str[action], |
1094 | (action == BATADV_UEV_DEL ? "NULL" : data), ret); | 1094 | (action == BATADV_UEV_DEL ? "NULL" : data), ret); |
1095 | return ret; | 1095 | return ret; |
1096 | } | 1096 | } |
1097 | 1097 |
net/batman-adv/types.h
1 | /* Copyright (C) 2007-2016 B.A.T.M.A.N. contributors: | 1 | /* Copyright (C) 2007-2016 B.A.T.M.A.N. contributors: |
2 | * | 2 | * |
3 | * Marek Lindner, Simon Wunderlich | 3 | * Marek Lindner, Simon Wunderlich |
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 |
7 | * License as published by the Free Software Foundation. | 7 | * License as published by the Free Software Foundation. |
8 | * | 8 | * |
9 | * This program is distributed in the hope that it will be useful, but | 9 | * This program is distributed in the hope that it will be useful, but |
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of | 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 | * General Public License for more details. | 12 | * General Public License for more details. |
13 | * | 13 | * |
14 | * You should have received a copy of the GNU General Public License | 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/>. | 15 | * along with this program; if not, see <http://www.gnu.org/licenses/>. |
16 | */ | 16 | */ |
17 | 17 | ||
18 | #ifndef _NET_BATMAN_ADV_TYPES_H_ | 18 | #ifndef _NET_BATMAN_ADV_TYPES_H_ |
19 | #define _NET_BATMAN_ADV_TYPES_H_ | 19 | #define _NET_BATMAN_ADV_TYPES_H_ |
20 | 20 | ||
21 | #ifndef _NET_BATMAN_ADV_MAIN_H_ | 21 | #ifndef _NET_BATMAN_ADV_MAIN_H_ |
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/average.h> |
26 | #include <linux/bitops.h> | 26 | #include <linux/bitops.h> |
27 | #include <linux/compiler.h> | 27 | #include <linux/compiler.h> |
28 | #include <linux/if_ether.h> | 28 | #include <linux/if_ether.h> |
29 | #include <linux/kref.h> | 29 | #include <linux/kref.h> |
30 | #include <linux/netdevice.h> | 30 | #include <linux/netdevice.h> |
31 | #include <linux/sched.h> /* for linux/wait.h */ | 31 | #include <linux/sched.h> /* for linux/wait.h */ |
32 | #include <linux/spinlock.h> | 32 | #include <linux/spinlock.h> |
33 | #include <linux/types.h> | 33 | #include <linux/types.h> |
34 | #include <linux/wait.h> | 34 | #include <linux/wait.h> |
35 | #include <linux/workqueue.h> | 35 | #include <linux/workqueue.h> |
36 | 36 | ||
37 | #include "packet.h" | 37 | #include "packet.h" |
38 | 38 | ||
39 | struct seq_file; | 39 | struct seq_file; |
40 | 40 | ||
41 | #ifdef CONFIG_BATMAN_ADV_DAT | 41 | #ifdef CONFIG_BATMAN_ADV_DAT |
42 | 42 | ||
43 | /** | 43 | /** |
44 | * batadv_dat_addr_t - it is the type used for all DHT addresses. If it is | 44 | * batadv_dat_addr_t - it is the type used for all DHT addresses. If it is |
45 | * changed, BATADV_DAT_ADDR_MAX is changed as well. | 45 | * changed, BATADV_DAT_ADDR_MAX is changed as well. |
46 | * | 46 | * |
47 | * *Please be careful: batadv_dat_addr_t must be UNSIGNED* | 47 | * *Please be careful: batadv_dat_addr_t must be UNSIGNED* |
48 | */ | 48 | */ |
49 | #define batadv_dat_addr_t u16 | 49 | #define batadv_dat_addr_t u16 |
50 | 50 | ||
51 | #endif /* CONFIG_BATMAN_ADV_DAT */ | 51 | #endif /* CONFIG_BATMAN_ADV_DAT */ |
52 | 52 | ||
53 | /** | 53 | /** |
54 | * enum batadv_dhcp_recipient - dhcp destination | 54 | * enum batadv_dhcp_recipient - dhcp destination |
55 | * @BATADV_DHCP_NO: packet is not a dhcp message | 55 | * @BATADV_DHCP_NO: packet is not a dhcp message |
56 | * @BATADV_DHCP_TO_SERVER: dhcp message is directed to a server | 56 | * @BATADV_DHCP_TO_SERVER: dhcp message is directed to a server |
57 | * @BATADV_DHCP_TO_CLIENT: dhcp message is directed to a client | 57 | * @BATADV_DHCP_TO_CLIENT: dhcp message is directed to a client |
58 | */ | 58 | */ |
59 | enum batadv_dhcp_recipient { | 59 | enum batadv_dhcp_recipient { |
60 | BATADV_DHCP_NO = 0, | 60 | BATADV_DHCP_NO = 0, |
61 | BATADV_DHCP_TO_SERVER, | 61 | BATADV_DHCP_TO_SERVER, |
62 | BATADV_DHCP_TO_CLIENT, | 62 | BATADV_DHCP_TO_CLIENT, |
63 | }; | 63 | }; |
64 | 64 | ||
65 | /** | 65 | /** |
66 | * BATADV_TT_REMOTE_MASK - bitmask selecting the flags that are sent over the | 66 | * BATADV_TT_REMOTE_MASK - bitmask selecting the flags that are sent over the |
67 | * wire only | 67 | * wire only |
68 | */ | 68 | */ |
69 | #define BATADV_TT_REMOTE_MASK 0x00FF | 69 | #define BATADV_TT_REMOTE_MASK 0x00FF |
70 | 70 | ||
71 | /** | 71 | /** |
72 | * BATADV_TT_SYNC_MASK - bitmask of the flags that need to be kept in sync | 72 | * BATADV_TT_SYNC_MASK - bitmask of the flags that need to be kept in sync |
73 | * among the nodes. These flags are used to compute the global/local CRC | 73 | * among the nodes. These flags are used to compute the global/local CRC |
74 | */ | 74 | */ |
75 | #define BATADV_TT_SYNC_MASK 0x00F0 | 75 | #define BATADV_TT_SYNC_MASK 0x00F0 |
76 | 76 | ||
77 | /** | 77 | /** |
78 | * struct batadv_hard_iface_bat_iv - per hard-interface B.A.T.M.A.N. IV data | 78 | * struct batadv_hard_iface_bat_iv - per hard-interface B.A.T.M.A.N. IV data |
79 | * @ogm_buff: buffer holding the OGM packet | 79 | * @ogm_buff: buffer holding the OGM packet |
80 | * @ogm_buff_len: length of the OGM packet buffer | 80 | * @ogm_buff_len: length of the OGM packet buffer |
81 | * @ogm_seqno: OGM sequence number - used to identify each OGM | 81 | * @ogm_seqno: OGM sequence number - used to identify each OGM |
82 | */ | 82 | */ |
83 | struct batadv_hard_iface_bat_iv { | 83 | struct batadv_hard_iface_bat_iv { |
84 | unsigned char *ogm_buff; | 84 | unsigned char *ogm_buff; |
85 | int ogm_buff_len; | 85 | int ogm_buff_len; |
86 | atomic_t ogm_seqno; | 86 | atomic_t ogm_seqno; |
87 | }; | 87 | }; |
88 | 88 | ||
89 | /** | 89 | /** |
90 | * enum batadv_v_hard_iface_flags - interface flags useful to B.A.T.M.A.N. V | 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 | 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 | 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 | 93 | * throughput data is available for this interface and that default values are |
94 | * assumed. | 94 | * assumed. |
95 | */ | 95 | */ |
96 | enum batadv_v_hard_iface_flags { | 96 | enum batadv_v_hard_iface_flags { |
97 | BATADV_FULL_DUPLEX = BIT(0), | 97 | BATADV_FULL_DUPLEX = BIT(0), |
98 | BATADV_WARNING_DEFAULT = BIT(1), | 98 | BATADV_WARNING_DEFAULT = BIT(1), |
99 | }; | 99 | }; |
100 | 100 | ||
101 | /** | 101 | /** |
102 | * struct batadv_hard_iface_bat_v - per hard-interface B.A.T.M.A.N. V data | 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 | 103 | * @elp_interval: time interval between two ELP transmissions |
104 | * @elp_seqno: current ELP sequence number | 104 | * @elp_seqno: current ELP sequence number |
105 | * @elp_skb: base skb containing the ELP message to send | 105 | * @elp_skb: base skb containing the ELP message to send |
106 | * @elp_wq: workqueue used to schedule ELP transmissions | 106 | * @elp_wq: workqueue used to schedule ELP transmissions |
107 | * @throughput_override: throughput override to disable link auto-detection | 107 | * @throughput_override: throughput override to disable link auto-detection |
108 | * @flags: interface specific flags | 108 | * @flags: interface specific flags |
109 | */ | 109 | */ |
110 | struct batadv_hard_iface_bat_v { | 110 | struct batadv_hard_iface_bat_v { |
111 | atomic_t elp_interval; | 111 | atomic_t elp_interval; |
112 | atomic_t elp_seqno; | 112 | atomic_t elp_seqno; |
113 | struct sk_buff *elp_skb; | 113 | struct sk_buff *elp_skb; |
114 | struct delayed_work elp_wq; | 114 | struct delayed_work elp_wq; |
115 | atomic_t throughput_override; | 115 | atomic_t throughput_override; |
116 | u8 flags; | 116 | u8 flags; |
117 | }; | 117 | }; |
118 | 118 | ||
119 | /** | 119 | /** |
120 | * struct batadv_hard_iface - network device known to batman-adv | 120 | * struct batadv_hard_iface - network device known to batman-adv |
121 | * @list: list node for batadv_hardif_list | 121 | * @list: list node for batadv_hardif_list |
122 | * @if_num: identificator of the interface | 122 | * @if_num: identificator of the interface |
123 | * @if_status: status of the interface for batman-adv | 123 | * @if_status: status of the interface for batman-adv |
124 | * @net_dev: pointer to the net_device | 124 | * @net_dev: pointer to the net_device |
125 | * @num_bcasts: number of payload re-broadcasts on this interface (ARQ) | 125 | * @num_bcasts: number of payload re-broadcasts on this interface (ARQ) |
126 | * @hardif_obj: kobject of the per interface sysfs "mesh" directory | 126 | * @hardif_obj: kobject of the per interface sysfs "mesh" directory |
127 | * @refcount: number of contexts the object is used | 127 | * @refcount: number of contexts the object is used |
128 | * @batman_adv_ptype: packet type describing packets that should be processed by | 128 | * @batman_adv_ptype: packet type describing packets that should be processed by |
129 | * batman-adv for this interface | 129 | * batman-adv for this interface |
130 | * @soft_iface: the batman-adv interface which uses this network interface | 130 | * @soft_iface: the batman-adv interface which uses this network interface |
131 | * @rcu: struct used for freeing in an RCU-safe manner | 131 | * @rcu: struct used for freeing in an RCU-safe manner |
132 | * @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 | 133 | * @bat_v: per hard-interface B.A.T.M.A.N. V data |
134 | * @cleanup_work: work queue callback item for hard-interface deinit | 134 | * @cleanup_work: work queue callback item for hard-interface deinit |
135 | * @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 |
136 | * @neigh_list: list of unique single hop neighbors via this interface | 136 | * @neigh_list: list of unique single hop neighbors via this interface |
137 | * @neigh_list_lock: lock protecting neigh_list | 137 | * @neigh_list_lock: lock protecting neigh_list |
138 | */ | 138 | */ |
139 | struct batadv_hard_iface { | 139 | struct batadv_hard_iface { |
140 | struct list_head list; | 140 | struct list_head list; |
141 | s16 if_num; | 141 | s16 if_num; |
142 | char if_status; | 142 | char if_status; |
143 | struct net_device *net_dev; | 143 | struct net_device *net_dev; |
144 | u8 num_bcasts; | 144 | u8 num_bcasts; |
145 | struct kobject *hardif_obj; | 145 | struct kobject *hardif_obj; |
146 | struct kref refcount; | 146 | struct kref refcount; |
147 | struct packet_type batman_adv_ptype; | 147 | struct packet_type batman_adv_ptype; |
148 | struct net_device *soft_iface; | 148 | struct net_device *soft_iface; |
149 | struct rcu_head rcu; | 149 | struct rcu_head rcu; |
150 | struct batadv_hard_iface_bat_iv bat_iv; | 150 | struct batadv_hard_iface_bat_iv bat_iv; |
151 | #ifdef CONFIG_BATMAN_ADV_BATMAN_V | 151 | #ifdef CONFIG_BATMAN_ADV_BATMAN_V |
152 | struct batadv_hard_iface_bat_v bat_v; | 152 | struct batadv_hard_iface_bat_v bat_v; |
153 | #endif | 153 | #endif |
154 | struct work_struct cleanup_work; | 154 | struct work_struct cleanup_work; |
155 | struct dentry *debug_dir; | 155 | struct dentry *debug_dir; |
156 | struct hlist_head neigh_list; | 156 | struct hlist_head neigh_list; |
157 | /* neigh_list_lock protects: neigh_list */ | 157 | /* neigh_list_lock protects: neigh_list */ |
158 | spinlock_t neigh_list_lock; | 158 | spinlock_t neigh_list_lock; |
159 | }; | 159 | }; |
160 | 160 | ||
161 | /** | 161 | /** |
162 | * struct batadv_orig_ifinfo - originator info per outgoing interface | 162 | * struct batadv_orig_ifinfo - originator info per outgoing interface |
163 | * @list: list node for orig_node::ifinfo_list | 163 | * @list: list node for orig_node::ifinfo_list |
164 | * @if_outgoing: pointer to outgoing hard-interface | 164 | * @if_outgoing: pointer to outgoing hard-interface |
165 | * @router: router that should be used to reach this originator | 165 | * @router: router that should be used to reach this originator |
166 | * @last_real_seqno: last and best known sequence number | 166 | * @last_real_seqno: last and best known sequence number |
167 | * @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 | 168 | * @last_seqno_forwarded: seqno of the OGM which was forwarded last |
169 | * @batman_seqno_reset: time when the batman seqno window was reset | 169 | * @batman_seqno_reset: time when the batman seqno window was reset |
170 | * @refcount: number of contexts the object is used | 170 | * @refcount: number of contexts the object is used |
171 | * @rcu: struct used for freeing in an RCU-safe manner | 171 | * @rcu: struct used for freeing in an RCU-safe manner |
172 | */ | 172 | */ |
173 | struct batadv_orig_ifinfo { | 173 | struct batadv_orig_ifinfo { |
174 | struct hlist_node list; | 174 | struct hlist_node list; |
175 | struct batadv_hard_iface *if_outgoing; | 175 | struct batadv_hard_iface *if_outgoing; |
176 | struct batadv_neigh_node __rcu *router; /* rcu protected pointer */ | 176 | struct batadv_neigh_node __rcu *router; /* rcu protected pointer */ |
177 | u32 last_real_seqno; | 177 | u32 last_real_seqno; |
178 | u8 last_ttl; | 178 | u8 last_ttl; |
179 | u32 last_seqno_forwarded; | 179 | u32 last_seqno_forwarded; |
180 | unsigned long batman_seqno_reset; | 180 | unsigned long batman_seqno_reset; |
181 | struct kref refcount; | 181 | struct kref refcount; |
182 | struct rcu_head rcu; | 182 | struct rcu_head rcu; |
183 | }; | 183 | }; |
184 | 184 | ||
185 | /** | 185 | /** |
186 | * struct batadv_frag_table_entry - head in the fragment buffer table | 186 | * struct batadv_frag_table_entry - head in the fragment buffer table |
187 | * @head: head of list with fragments | 187 | * @head: head of list with fragments |
188 | * @lock: lock to protect the list of fragments | 188 | * @lock: lock to protect the list of fragments |
189 | * @timestamp: time (jiffie) of last received fragment | 189 | * @timestamp: time (jiffie) of last received fragment |
190 | * @seqno: sequence number of the fragments in the list | 190 | * @seqno: sequence number of the fragments in the list |
191 | * @size: accumulated size of packets in list | 191 | * @size: accumulated size of packets in list |
192 | * @total_size: expected size of the assembled packet | 192 | * @total_size: expected size of the assembled packet |
193 | */ | 193 | */ |
194 | struct batadv_frag_table_entry { | 194 | struct batadv_frag_table_entry { |
195 | struct hlist_head head; | 195 | struct hlist_head head; |
196 | spinlock_t lock; /* protects head */ | 196 | spinlock_t lock; /* protects head */ |
197 | unsigned long timestamp; | 197 | unsigned long timestamp; |
198 | u16 seqno; | 198 | u16 seqno; |
199 | u16 size; | 199 | u16 size; |
200 | u16 total_size; | 200 | u16 total_size; |
201 | }; | 201 | }; |
202 | 202 | ||
203 | /** | 203 | /** |
204 | * struct batadv_frag_list_entry - entry in a list of fragments | 204 | * struct batadv_frag_list_entry - entry in a list of fragments |
205 | * @list: list node information | 205 | * @list: list node information |
206 | * @skb: fragment | 206 | * @skb: fragment |
207 | * @no: fragment number in the set | 207 | * @no: fragment number in the set |
208 | */ | 208 | */ |
209 | struct batadv_frag_list_entry { | 209 | struct batadv_frag_list_entry { |
210 | struct hlist_node list; | 210 | struct hlist_node list; |
211 | struct sk_buff *skb; | 211 | struct sk_buff *skb; |
212 | u8 no; | 212 | u8 no; |
213 | }; | 213 | }; |
214 | 214 | ||
215 | /** | 215 | /** |
216 | * struct batadv_vlan_tt - VLAN specific TT attributes | 216 | * struct batadv_vlan_tt - VLAN specific TT attributes |
217 | * @crc: CRC32 checksum of the entries belonging to this vlan | 217 | * @crc: CRC32 checksum of the entries belonging to this vlan |
218 | * @num_entries: number of TT entries for this VLAN | 218 | * @num_entries: number of TT entries for this VLAN |
219 | */ | 219 | */ |
220 | struct batadv_vlan_tt { | 220 | struct batadv_vlan_tt { |
221 | u32 crc; | 221 | u32 crc; |
222 | atomic_t num_entries; | 222 | atomic_t num_entries; |
223 | }; | 223 | }; |
224 | 224 | ||
225 | /** | 225 | /** |
226 | * struct batadv_orig_node_vlan - VLAN specific data per orig_node | 226 | * struct batadv_orig_node_vlan - VLAN specific data per orig_node |
227 | * @vid: the VLAN identifier | 227 | * @vid: the VLAN identifier |
228 | * @tt: VLAN specific TT attributes | 228 | * @tt: VLAN specific TT attributes |
229 | * @list: list node for orig_node::vlan_list | 229 | * @list: list node for orig_node::vlan_list |
230 | * @refcount: number of context where this object is currently in use | 230 | * @refcount: number of context where this object is currently in use |
231 | * @rcu: struct used for freeing in a RCU-safe manner | 231 | * @rcu: struct used for freeing in a RCU-safe manner |
232 | */ | 232 | */ |
233 | struct batadv_orig_node_vlan { | 233 | struct batadv_orig_node_vlan { |
234 | unsigned short vid; | 234 | unsigned short vid; |
235 | struct batadv_vlan_tt tt; | 235 | struct batadv_vlan_tt tt; |
236 | struct hlist_node list; | 236 | struct hlist_node list; |
237 | struct kref refcount; | 237 | struct kref refcount; |
238 | struct rcu_head rcu; | 238 | struct rcu_head rcu; |
239 | }; | 239 | }; |
240 | 240 | ||
241 | /** | 241 | /** |
242 | * struct batadv_orig_bat_iv - B.A.T.M.A.N. IV private orig_node members | 242 | * struct batadv_orig_bat_iv - B.A.T.M.A.N. IV private orig_node members |
243 | * @bcast_own: set of bitfields (one per hard-interface) where each one counts | 243 | * @bcast_own: set of bitfields (one per hard-interface) where each one counts |
244 | * the number of our OGMs this orig_node rebroadcasted "back" to us (relative | 244 | * the number of our OGMs this orig_node rebroadcasted "back" to us (relative |
245 | * to last_real_seqno). Every bitfield is BATADV_TQ_LOCAL_WINDOW_SIZE bits long. | 245 | * to last_real_seqno). Every bitfield is BATADV_TQ_LOCAL_WINDOW_SIZE bits long. |
246 | * @bcast_own_sum: sum of bcast_own | 246 | * @bcast_own_sum: sum of bcast_own |
247 | * @ogm_cnt_lock: lock protecting bcast_own, bcast_own_sum, | 247 | * @ogm_cnt_lock: lock protecting bcast_own, bcast_own_sum, |
248 | * neigh_node->bat_iv.real_bits & neigh_node->bat_iv.real_packet_count | 248 | * neigh_node->bat_iv.real_bits & neigh_node->bat_iv.real_packet_count |
249 | */ | 249 | */ |
250 | struct batadv_orig_bat_iv { | 250 | struct batadv_orig_bat_iv { |
251 | unsigned long *bcast_own; | 251 | unsigned long *bcast_own; |
252 | u8 *bcast_own_sum; | 252 | u8 *bcast_own_sum; |
253 | /* ogm_cnt_lock protects: bcast_own, bcast_own_sum, | 253 | /* ogm_cnt_lock protects: bcast_own, bcast_own_sum, |
254 | * neigh_node->bat_iv.real_bits & neigh_node->bat_iv.real_packet_count | 254 | * neigh_node->bat_iv.real_bits & neigh_node->bat_iv.real_packet_count |
255 | */ | 255 | */ |
256 | spinlock_t ogm_cnt_lock; | 256 | spinlock_t ogm_cnt_lock; |
257 | }; | 257 | }; |
258 | 258 | ||
259 | /** | 259 | /** |
260 | * struct batadv_orig_node - structure for orig_list maintaining nodes of mesh | 260 | * struct batadv_orig_node - structure for orig_list maintaining nodes of mesh |
261 | * @orig: originator ethernet address | 261 | * @orig: originator ethernet address |
262 | * @ifinfo_list: list for routers per outgoing interface | 262 | * @ifinfo_list: list for routers per outgoing interface |
263 | * @last_bonding_candidate: pointer to last ifinfo of last used router | 263 | * @last_bonding_candidate: pointer to last ifinfo of last used router |
264 | * @dat_addr: address of the orig node in the distributed hash | 264 | * @dat_addr: address of the orig node in the distributed hash |
265 | * @last_seen: time when last packet from this node was received | 265 | * @last_seen: time when last packet from this node was received |
266 | * @bcast_seqno_reset: time when the broadcast seqno window was reset | 266 | * @bcast_seqno_reset: time when the broadcast seqno window was reset |
267 | * @mcast_handler_lock: synchronizes mcast-capability and -flag changes | 267 | * @mcast_handler_lock: synchronizes mcast-capability and -flag changes |
268 | * @mcast_flags: multicast flags announced by the orig node | 268 | * @mcast_flags: multicast flags announced by the orig node |
269 | * @mcast_want_all_unsnoopables_node: a list node for the | 269 | * @mcast_want_all_unsnoopables_node: a list node for the |
270 | * mcast.want_all_unsnoopables list | 270 | * mcast.want_all_unsnoopables list |
271 | * @mcast_want_all_ipv4_node: a list node for the mcast.want_all_ipv4 list | 271 | * @mcast_want_all_ipv4_node: a list node for the mcast.want_all_ipv4 list |
272 | * @mcast_want_all_ipv6_node: a list node for the mcast.want_all_ipv6 list | 272 | * @mcast_want_all_ipv6_node: a list node for the mcast.want_all_ipv6 list |
273 | * @capabilities: announced capabilities of this originator | 273 | * @capabilities: announced capabilities of this originator |
274 | * @capa_initialized: bitfield to remember whether a capability was initialized | 274 | * @capa_initialized: bitfield to remember whether a capability was initialized |
275 | * @last_ttvn: last seen translation table version number | 275 | * @last_ttvn: last seen translation table version number |
276 | * @tt_buff: last tt changeset this node received from the orig node | 276 | * @tt_buff: last tt changeset this node received from the orig node |
277 | * @tt_buff_len: length of the last tt changeset this node received from the | 277 | * @tt_buff_len: length of the last tt changeset this node received from the |
278 | * orig node | 278 | * orig node |
279 | * @tt_buff_lock: lock that protects tt_buff and tt_buff_len | 279 | * @tt_buff_lock: lock that protects tt_buff and tt_buff_len |
280 | * @tt_lock: prevents from updating the table while reading it. Table update is | 280 | * @tt_lock: prevents from updating the table while reading it. Table update is |
281 | * made up by two operations (data structure update and metdata -CRC/TTVN- | 281 | * made up by two operations (data structure update and metdata -CRC/TTVN- |
282 | * recalculation) and they have to be executed atomically in order to avoid | 282 | * recalculation) and they have to be executed atomically in order to avoid |
283 | * another thread to read the table/metadata between those. | 283 | * another thread to read the table/metadata between those. |
284 | * @bcast_bits: bitfield containing the info which payload broadcast originated | 284 | * @bcast_bits: bitfield containing the info which payload broadcast originated |
285 | * from this orig node this host already has seen (relative to | 285 | * from this orig node this host already has seen (relative to |
286 | * last_bcast_seqno) | 286 | * last_bcast_seqno) |
287 | * @last_bcast_seqno: last broadcast sequence number received by this host | 287 | * @last_bcast_seqno: last broadcast sequence number received by this host |
288 | * @neigh_list: list of potential next hop neighbor towards this orig node | 288 | * @neigh_list: list of potential next hop neighbor towards this orig node |
289 | * @neigh_list_lock: lock protecting neigh_list and router | 289 | * @neigh_list_lock: lock protecting neigh_list and router |
290 | * @hash_entry: hlist node for batadv_priv::orig_hash | 290 | * @hash_entry: hlist node for batadv_priv::orig_hash |
291 | * @bat_priv: pointer to soft_iface this orig node belongs to | 291 | * @bat_priv: pointer to soft_iface this orig node belongs to |
292 | * @bcast_seqno_lock: lock protecting bcast_bits & last_bcast_seqno | 292 | * @bcast_seqno_lock: lock protecting bcast_bits & last_bcast_seqno |
293 | * @refcount: number of contexts the object is used | 293 | * @refcount: number of contexts the object is used |
294 | * @rcu: struct used for freeing in an RCU-safe manner | 294 | * @rcu: struct used for freeing in an RCU-safe manner |
295 | * @in_coding_list: list of nodes this orig can hear | 295 | * @in_coding_list: list of nodes this orig can hear |
296 | * @out_coding_list: list of nodes that can hear this orig | 296 | * @out_coding_list: list of nodes that can hear this orig |
297 | * @in_coding_list_lock: protects in_coding_list | 297 | * @in_coding_list_lock: protects in_coding_list |
298 | * @out_coding_list_lock: protects out_coding_list | 298 | * @out_coding_list_lock: protects out_coding_list |
299 | * @fragments: array with heads for fragment chains | 299 | * @fragments: array with heads for fragment chains |
300 | * @vlan_list: a list of orig_node_vlan structs, one per VLAN served by the | 300 | * @vlan_list: a list of orig_node_vlan structs, one per VLAN served by the |
301 | * originator represented by this object | 301 | * originator represented by this object |
302 | * @vlan_list_lock: lock protecting vlan_list | 302 | * @vlan_list_lock: lock protecting vlan_list |
303 | * @bat_iv: B.A.T.M.A.N. IV private structure | 303 | * @bat_iv: B.A.T.M.A.N. IV private structure |
304 | */ | 304 | */ |
305 | struct batadv_orig_node { | 305 | struct batadv_orig_node { |
306 | u8 orig[ETH_ALEN]; | 306 | u8 orig[ETH_ALEN]; |
307 | struct hlist_head ifinfo_list; | 307 | struct hlist_head ifinfo_list; |
308 | struct batadv_orig_ifinfo *last_bonding_candidate; | 308 | struct batadv_orig_ifinfo *last_bonding_candidate; |
309 | #ifdef CONFIG_BATMAN_ADV_DAT | 309 | #ifdef CONFIG_BATMAN_ADV_DAT |
310 | batadv_dat_addr_t dat_addr; | 310 | batadv_dat_addr_t dat_addr; |
311 | #endif | 311 | #endif |
312 | unsigned long last_seen; | 312 | unsigned long last_seen; |
313 | unsigned long bcast_seqno_reset; | 313 | unsigned long bcast_seqno_reset; |
314 | #ifdef CONFIG_BATMAN_ADV_MCAST | 314 | #ifdef CONFIG_BATMAN_ADV_MCAST |
315 | /* synchronizes mcast tvlv specific orig changes */ | 315 | /* synchronizes mcast tvlv specific orig changes */ |
316 | spinlock_t mcast_handler_lock; | 316 | spinlock_t mcast_handler_lock; |
317 | u8 mcast_flags; | 317 | u8 mcast_flags; |
318 | struct hlist_node mcast_want_all_unsnoopables_node; | 318 | struct hlist_node mcast_want_all_unsnoopables_node; |
319 | struct hlist_node mcast_want_all_ipv4_node; | 319 | struct hlist_node mcast_want_all_ipv4_node; |
320 | struct hlist_node mcast_want_all_ipv6_node; | 320 | struct hlist_node mcast_want_all_ipv6_node; |
321 | #endif | 321 | #endif |
322 | unsigned long capabilities; | 322 | unsigned long capabilities; |
323 | unsigned long capa_initialized; | 323 | unsigned long capa_initialized; |
324 | atomic_t last_ttvn; | 324 | atomic_t last_ttvn; |
325 | unsigned char *tt_buff; | 325 | unsigned char *tt_buff; |
326 | s16 tt_buff_len; | 326 | s16 tt_buff_len; |
327 | spinlock_t tt_buff_lock; /* protects tt_buff & tt_buff_len */ | 327 | spinlock_t tt_buff_lock; /* protects tt_buff & tt_buff_len */ |
328 | /* prevents from changing the table while reading it */ | 328 | /* prevents from changing the table while reading it */ |
329 | spinlock_t tt_lock; | 329 | spinlock_t tt_lock; |
330 | DECLARE_BITMAP(bcast_bits, BATADV_TQ_LOCAL_WINDOW_SIZE); | 330 | DECLARE_BITMAP(bcast_bits, BATADV_TQ_LOCAL_WINDOW_SIZE); |
331 | u32 last_bcast_seqno; | 331 | u32 last_bcast_seqno; |
332 | struct hlist_head neigh_list; | 332 | struct hlist_head neigh_list; |
333 | /* neigh_list_lock protects: neigh_list and router */ | 333 | /* neigh_list_lock protects: neigh_list and router */ |
334 | spinlock_t neigh_list_lock; | 334 | spinlock_t neigh_list_lock; |
335 | struct hlist_node hash_entry; | 335 | struct hlist_node hash_entry; |
336 | struct batadv_priv *bat_priv; | 336 | struct batadv_priv *bat_priv; |
337 | /* bcast_seqno_lock protects: bcast_bits & last_bcast_seqno */ | 337 | /* bcast_seqno_lock protects: bcast_bits & last_bcast_seqno */ |
338 | spinlock_t bcast_seqno_lock; | 338 | spinlock_t bcast_seqno_lock; |
339 | struct kref refcount; | 339 | struct kref refcount; |
340 | struct rcu_head rcu; | 340 | struct rcu_head rcu; |
341 | #ifdef CONFIG_BATMAN_ADV_NC | 341 | #ifdef CONFIG_BATMAN_ADV_NC |
342 | struct list_head in_coding_list; | 342 | struct list_head in_coding_list; |
343 | struct list_head out_coding_list; | 343 | struct list_head out_coding_list; |
344 | spinlock_t in_coding_list_lock; /* Protects in_coding_list */ | 344 | spinlock_t in_coding_list_lock; /* Protects in_coding_list */ |
345 | spinlock_t out_coding_list_lock; /* Protects out_coding_list */ | 345 | spinlock_t out_coding_list_lock; /* Protects out_coding_list */ |
346 | #endif | 346 | #endif |
347 | struct batadv_frag_table_entry fragments[BATADV_FRAG_BUFFER_COUNT]; | 347 | struct batadv_frag_table_entry fragments[BATADV_FRAG_BUFFER_COUNT]; |
348 | struct hlist_head vlan_list; | 348 | struct hlist_head vlan_list; |
349 | spinlock_t vlan_list_lock; /* protects vlan_list */ | 349 | spinlock_t vlan_list_lock; /* protects vlan_list */ |
350 | struct batadv_orig_bat_iv bat_iv; | 350 | struct batadv_orig_bat_iv bat_iv; |
351 | }; | 351 | }; |
352 | 352 | ||
353 | /** | 353 | /** |
354 | * enum batadv_orig_capabilities - orig node capabilities | 354 | * enum batadv_orig_capabilities - orig node capabilities |
355 | * @BATADV_ORIG_CAPA_HAS_DAT: orig node has distributed arp table enabled | 355 | * @BATADV_ORIG_CAPA_HAS_DAT: orig node has distributed arp table enabled |
356 | * @BATADV_ORIG_CAPA_HAS_NC: orig node has network coding enabled | 356 | * @BATADV_ORIG_CAPA_HAS_NC: orig node has network coding enabled |
357 | * @BATADV_ORIG_CAPA_HAS_TT: orig node has tt capability | 357 | * @BATADV_ORIG_CAPA_HAS_TT: orig node has tt capability |
358 | * @BATADV_ORIG_CAPA_HAS_MCAST: orig node has some multicast capability | 358 | * @BATADV_ORIG_CAPA_HAS_MCAST: orig node has some multicast capability |
359 | * (= orig node announces a tvlv of type BATADV_TVLV_MCAST) | 359 | * (= orig node announces a tvlv of type BATADV_TVLV_MCAST) |
360 | */ | 360 | */ |
361 | enum batadv_orig_capabilities { | 361 | enum batadv_orig_capabilities { |
362 | BATADV_ORIG_CAPA_HAS_DAT, | 362 | BATADV_ORIG_CAPA_HAS_DAT, |
363 | BATADV_ORIG_CAPA_HAS_NC, | 363 | BATADV_ORIG_CAPA_HAS_NC, |
364 | BATADV_ORIG_CAPA_HAS_TT, | 364 | BATADV_ORIG_CAPA_HAS_TT, |
365 | BATADV_ORIG_CAPA_HAS_MCAST, | 365 | BATADV_ORIG_CAPA_HAS_MCAST, |
366 | }; | 366 | }; |
367 | 367 | ||
368 | /** | 368 | /** |
369 | * struct batadv_gw_node - structure for orig nodes announcing gw capabilities | 369 | * struct batadv_gw_node - structure for orig nodes announcing gw capabilities |
370 | * @list: list node for batadv_priv_gw::list | 370 | * @list: list node for batadv_priv_gw::list |
371 | * @orig_node: pointer to corresponding orig node | 371 | * @orig_node: pointer to corresponding orig node |
372 | * @bandwidth_down: advertised uplink download bandwidth | 372 | * @bandwidth_down: advertised uplink download bandwidth |
373 | * @bandwidth_up: advertised uplink upload bandwidth | 373 | * @bandwidth_up: advertised uplink upload bandwidth |
374 | * @refcount: number of contexts the object is used | 374 | * @refcount: number of contexts the object is used |
375 | * @rcu: struct used for freeing in an RCU-safe manner | 375 | * @rcu: struct used for freeing in an RCU-safe manner |
376 | */ | 376 | */ |
377 | struct batadv_gw_node { | 377 | struct batadv_gw_node { |
378 | struct hlist_node list; | 378 | struct hlist_node list; |
379 | struct batadv_orig_node *orig_node; | 379 | struct batadv_orig_node *orig_node; |
380 | u32 bandwidth_down; | 380 | u32 bandwidth_down; |
381 | u32 bandwidth_up; | 381 | u32 bandwidth_up; |
382 | struct kref refcount; | 382 | struct kref refcount; |
383 | struct rcu_head rcu; | 383 | struct rcu_head rcu; |
384 | }; | 384 | }; |
385 | 385 | ||
386 | DECLARE_EWMA(throughput, 1024, 8) | 386 | DECLARE_EWMA(throughput, 1024, 8) |
387 | 387 | ||
388 | /** | 388 | /** |
389 | * struct batadv_hardif_neigh_node_bat_v - B.A.T.M.A.N. V private neighbor | 389 | * struct batadv_hardif_neigh_node_bat_v - B.A.T.M.A.N. V private neighbor |
390 | * information | 390 | * information |
391 | * @throughput: ewma link throughput towards this neighbor | 391 | * @throughput: ewma link throughput towards this neighbor |
392 | * @elp_interval: time interval between two ELP transmissions | 392 | * @elp_interval: time interval between two ELP transmissions |
393 | * @elp_latest_seqno: latest and best known ELP sequence number | 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 | 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 | 395 | * @metric_work: work queue callback item for metric update |
396 | */ | 396 | */ |
397 | struct batadv_hardif_neigh_node_bat_v { | 397 | struct batadv_hardif_neigh_node_bat_v { |
398 | struct ewma_throughput throughput; | 398 | struct ewma_throughput throughput; |
399 | u32 elp_interval; | 399 | u32 elp_interval; |
400 | u32 elp_latest_seqno; | 400 | u32 elp_latest_seqno; |
401 | unsigned long last_unicast_tx; | 401 | unsigned long last_unicast_tx; |
402 | struct work_struct metric_work; | 402 | struct work_struct metric_work; |
403 | }; | 403 | }; |
404 | 404 | ||
405 | /** | 405 | /** |
406 | * struct batadv_hardif_neigh_node - unique neighbor per hard-interface | 406 | * struct batadv_hardif_neigh_node - unique neighbor per hard-interface |
407 | * @list: list node for batadv_hard_iface::neigh_list | 407 | * @list: list node for batadv_hard_iface::neigh_list |
408 | * @addr: the MAC address of the neighboring interface | 408 | * @addr: the MAC address of the neighboring interface |
409 | * @if_incoming: pointer to incoming hard-interface | 409 | * @if_incoming: pointer to incoming hard-interface |
410 | * @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 | 411 | * @bat_v: B.A.T.M.A.N. V private data |
412 | * @refcount: number of contexts the object is used | 412 | * @refcount: number of contexts the object is used |
413 | * @rcu: struct used for freeing in a RCU-safe manner | 413 | * @rcu: struct used for freeing in a RCU-safe manner |
414 | */ | 414 | */ |
415 | struct batadv_hardif_neigh_node { | 415 | struct batadv_hardif_neigh_node { |
416 | struct hlist_node list; | 416 | struct hlist_node list; |
417 | u8 addr[ETH_ALEN]; | 417 | u8 addr[ETH_ALEN]; |
418 | struct batadv_hard_iface *if_incoming; | 418 | struct batadv_hard_iface *if_incoming; |
419 | unsigned long last_seen; | 419 | unsigned long last_seen; |
420 | #ifdef CONFIG_BATMAN_ADV_BATMAN_V | 420 | #ifdef CONFIG_BATMAN_ADV_BATMAN_V |
421 | struct batadv_hardif_neigh_node_bat_v bat_v; | 421 | struct batadv_hardif_neigh_node_bat_v bat_v; |
422 | #endif | 422 | #endif |
423 | struct kref refcount; | 423 | struct kref refcount; |
424 | struct rcu_head rcu; | 424 | struct rcu_head rcu; |
425 | }; | 425 | }; |
426 | 426 | ||
427 | /** | 427 | /** |
428 | * struct batadv_neigh_node - structure for single hops neighbors | 428 | * struct batadv_neigh_node - structure for single hops neighbors |
429 | * @list: list node for batadv_orig_node::neigh_list | 429 | * @list: list node for batadv_orig_node::neigh_list |
430 | * @orig_node: pointer to corresponding orig_node | 430 | * @orig_node: pointer to corresponding orig_node |
431 | * @addr: the MAC address of the neighboring interface | 431 | * @addr: the MAC address of the neighboring interface |
432 | * @ifinfo_list: list for routing metrics per outgoing interface | 432 | * @ifinfo_list: list for routing metrics per outgoing interface |
433 | * @ifinfo_lock: lock protecting private ifinfo members and list | 433 | * @ifinfo_lock: lock protecting private ifinfo members and list |
434 | * @if_incoming: pointer to incoming hard-interface | 434 | * @if_incoming: pointer to incoming hard-interface |
435 | * @last_seen: when last packet via this neighbor was received | 435 | * @last_seen: when last packet via this neighbor was received |
436 | * @hardif_neigh: hardif_neigh of this neighbor | 436 | * @hardif_neigh: hardif_neigh of this neighbor |
437 | * @refcount: number of contexts the object is used | 437 | * @refcount: number of contexts the object is used |
438 | * @rcu: struct used for freeing in an RCU-safe manner | 438 | * @rcu: struct used for freeing in an RCU-safe manner |
439 | */ | 439 | */ |
440 | struct batadv_neigh_node { | 440 | struct batadv_neigh_node { |
441 | struct hlist_node list; | 441 | struct hlist_node list; |
442 | struct batadv_orig_node *orig_node; | 442 | struct batadv_orig_node *orig_node; |
443 | u8 addr[ETH_ALEN]; | 443 | u8 addr[ETH_ALEN]; |
444 | struct hlist_head ifinfo_list; | 444 | struct hlist_head ifinfo_list; |
445 | spinlock_t ifinfo_lock; /* protects ifinfo_list and its members */ | 445 | spinlock_t ifinfo_lock; /* protects ifinfo_list and its members */ |
446 | struct batadv_hard_iface *if_incoming; | 446 | struct batadv_hard_iface *if_incoming; |
447 | unsigned long last_seen; | 447 | unsigned long last_seen; |
448 | struct batadv_hardif_neigh_node *hardif_neigh; | 448 | struct batadv_hardif_neigh_node *hardif_neigh; |
449 | struct kref refcount; | 449 | struct kref refcount; |
450 | struct rcu_head rcu; | 450 | struct rcu_head rcu; |
451 | }; | 451 | }; |
452 | 452 | ||
453 | /** | 453 | /** |
454 | * struct batadv_neigh_ifinfo_bat_iv - neighbor information per outgoing | 454 | * struct batadv_neigh_ifinfo_bat_iv - neighbor information per outgoing |
455 | * interface for B.A.T.M.A.N. IV | 455 | * interface for B.A.T.M.A.N. IV |
456 | * @tq_recv: ring buffer of received TQ values from this neigh node | 456 | * @tq_recv: ring buffer of received TQ values from this neigh node |
457 | * @tq_index: ring buffer index | 457 | * @tq_index: ring buffer index |
458 | * @tq_avg: averaged tq of all tq values in the ring buffer (tq_recv) | 458 | * @tq_avg: averaged tq of all tq values in the ring buffer (tq_recv) |
459 | * @real_bits: bitfield containing the number of OGMs received from this neigh | 459 | * @real_bits: bitfield containing the number of OGMs received from this neigh |
460 | * node (relative to orig_node->last_real_seqno) | 460 | * node (relative to orig_node->last_real_seqno) |
461 | * @real_packet_count: counted result of real_bits | 461 | * @real_packet_count: counted result of real_bits |
462 | */ | 462 | */ |
463 | struct batadv_neigh_ifinfo_bat_iv { | 463 | struct batadv_neigh_ifinfo_bat_iv { |
464 | u8 tq_recv[BATADV_TQ_GLOBAL_WINDOW_SIZE]; | 464 | u8 tq_recv[BATADV_TQ_GLOBAL_WINDOW_SIZE]; |
465 | u8 tq_index; | 465 | u8 tq_index; |
466 | u8 tq_avg; | 466 | u8 tq_avg; |
467 | DECLARE_BITMAP(real_bits, BATADV_TQ_LOCAL_WINDOW_SIZE); | 467 | DECLARE_BITMAP(real_bits, BATADV_TQ_LOCAL_WINDOW_SIZE); |
468 | u8 real_packet_count; | 468 | u8 real_packet_count; |
469 | }; | 469 | }; |
470 | 470 | ||
471 | /** | 471 | /** |
472 | * struct batadv_neigh_ifinfo_bat_v - neighbor information per outgoing | 472 | * struct batadv_neigh_ifinfo_bat_v - neighbor information per outgoing |
473 | * interface for B.A.T.M.A.N. V | 473 | * interface for B.A.T.M.A.N. V |
474 | * @throughput: last throughput metric received from originator via this neigh | 474 | * @throughput: last throughput metric received from originator via this neigh |
475 | * @last_seqno: last sequence number known for this neighbor | 475 | * @last_seqno: last sequence number known for this neighbor |
476 | */ | 476 | */ |
477 | struct batadv_neigh_ifinfo_bat_v { | 477 | struct batadv_neigh_ifinfo_bat_v { |
478 | u32 throughput; | 478 | u32 throughput; |
479 | u32 last_seqno; | 479 | u32 last_seqno; |
480 | }; | 480 | }; |
481 | 481 | ||
482 | /** | 482 | /** |
483 | * struct batadv_neigh_ifinfo - neighbor information per outgoing interface | 483 | * struct batadv_neigh_ifinfo - neighbor information per outgoing interface |
484 | * @list: list node for batadv_neigh_node::ifinfo_list | 484 | * @list: list node for batadv_neigh_node::ifinfo_list |
485 | * @if_outgoing: pointer to outgoing hard-interface | 485 | * @if_outgoing: pointer to outgoing hard-interface |
486 | * @bat_iv: B.A.T.M.A.N. IV private structure | 486 | * @bat_iv: B.A.T.M.A.N. IV private structure |
487 | * @bat_v: B.A.T.M.A.N. V private data | 487 | * @bat_v: B.A.T.M.A.N. V private data |
488 | * @last_ttl: last received ttl from this neigh node | 488 | * @last_ttl: last received ttl from this neigh node |
489 | * @refcount: number of contexts the object is used | 489 | * @refcount: number of contexts the object is used |
490 | * @rcu: struct used for freeing in a RCU-safe manner | 490 | * @rcu: struct used for freeing in a RCU-safe manner |
491 | */ | 491 | */ |
492 | struct batadv_neigh_ifinfo { | 492 | struct batadv_neigh_ifinfo { |
493 | struct hlist_node list; | 493 | struct hlist_node list; |
494 | struct batadv_hard_iface *if_outgoing; | 494 | struct batadv_hard_iface *if_outgoing; |
495 | struct batadv_neigh_ifinfo_bat_iv bat_iv; | 495 | struct batadv_neigh_ifinfo_bat_iv bat_iv; |
496 | #ifdef CONFIG_BATMAN_ADV_BATMAN_V | 496 | #ifdef CONFIG_BATMAN_ADV_BATMAN_V |
497 | struct batadv_neigh_ifinfo_bat_v bat_v; | 497 | struct batadv_neigh_ifinfo_bat_v bat_v; |
498 | #endif | 498 | #endif |
499 | u8 last_ttl; | 499 | u8 last_ttl; |
500 | struct kref refcount; | 500 | struct kref refcount; |
501 | struct rcu_head rcu; | 501 | struct rcu_head rcu; |
502 | }; | 502 | }; |
503 | 503 | ||
504 | #ifdef CONFIG_BATMAN_ADV_BLA | 504 | #ifdef CONFIG_BATMAN_ADV_BLA |
505 | 505 | ||
506 | /** | 506 | /** |
507 | * struct batadv_bcast_duplist_entry - structure for LAN broadcast suppression | 507 | * struct batadv_bcast_duplist_entry - structure for LAN broadcast suppression |
508 | * @orig: mac address of orig node orginating the broadcast | 508 | * @orig: mac address of orig node orginating the broadcast |
509 | * @crc: crc32 checksum of broadcast payload | 509 | * @crc: crc32 checksum of broadcast payload |
510 | * @entrytime: time when the broadcast packet was received | 510 | * @entrytime: time when the broadcast packet was received |
511 | */ | 511 | */ |
512 | struct batadv_bcast_duplist_entry { | 512 | struct batadv_bcast_duplist_entry { |
513 | u8 orig[ETH_ALEN]; | 513 | u8 orig[ETH_ALEN]; |
514 | __be32 crc; | 514 | __be32 crc; |
515 | unsigned long entrytime; | 515 | unsigned long entrytime; |
516 | }; | 516 | }; |
517 | #endif | 517 | #endif |
518 | 518 | ||
519 | /** | 519 | /** |
520 | * enum batadv_counters - indices for traffic counters | 520 | * enum batadv_counters - indices for traffic counters |
521 | * @BATADV_CNT_TX: transmitted payload traffic packet counter | 521 | * @BATADV_CNT_TX: transmitted payload traffic packet counter |
522 | * @BATADV_CNT_TX_BYTES: transmitted payload traffic bytes counter | 522 | * @BATADV_CNT_TX_BYTES: transmitted payload traffic bytes counter |
523 | * @BATADV_CNT_TX_DROPPED: dropped transmission payload traffic packet counter | 523 | * @BATADV_CNT_TX_DROPPED: dropped transmission payload traffic packet counter |
524 | * @BATADV_CNT_RX: received payload traffic packet counter | 524 | * @BATADV_CNT_RX: received payload traffic packet counter |
525 | * @BATADV_CNT_RX_BYTES: received payload traffic bytes counter | 525 | * @BATADV_CNT_RX_BYTES: received payload traffic bytes counter |
526 | * @BATADV_CNT_FORWARD: forwarded payload traffic packet counter | 526 | * @BATADV_CNT_FORWARD: forwarded payload traffic packet counter |
527 | * @BATADV_CNT_FORWARD_BYTES: forwarded payload traffic bytes counter | 527 | * @BATADV_CNT_FORWARD_BYTES: forwarded payload traffic bytes counter |
528 | * @BATADV_CNT_MGMT_TX: transmitted routing protocol traffic packet counter | 528 | * @BATADV_CNT_MGMT_TX: transmitted routing protocol traffic packet counter |
529 | * @BATADV_CNT_MGMT_TX_BYTES: transmitted routing protocol traffic bytes counter | 529 | * @BATADV_CNT_MGMT_TX_BYTES: transmitted routing protocol traffic bytes counter |
530 | * @BATADV_CNT_MGMT_RX: received routing protocol traffic packet counter | 530 | * @BATADV_CNT_MGMT_RX: received routing protocol traffic packet counter |
531 | * @BATADV_CNT_MGMT_RX_BYTES: received routing protocol traffic bytes counter | 531 | * @BATADV_CNT_MGMT_RX_BYTES: received routing protocol traffic bytes counter |
532 | * @BATADV_CNT_FRAG_TX: transmitted fragment traffic packet counter | 532 | * @BATADV_CNT_FRAG_TX: transmitted fragment traffic packet counter |
533 | * @BATADV_CNT_FRAG_TX_BYTES: transmitted fragment traffic bytes counter | 533 | * @BATADV_CNT_FRAG_TX_BYTES: transmitted fragment traffic bytes counter |
534 | * @BATADV_CNT_FRAG_RX: received fragment traffic packet counter | 534 | * @BATADV_CNT_FRAG_RX: received fragment traffic packet counter |
535 | * @BATADV_CNT_FRAG_RX_BYTES: received fragment traffic bytes counter | 535 | * @BATADV_CNT_FRAG_RX_BYTES: received fragment traffic bytes counter |
536 | * @BATADV_CNT_FRAG_FWD: forwarded fragment traffic packet counter | 536 | * @BATADV_CNT_FRAG_FWD: forwarded fragment traffic packet counter |
537 | * @BATADV_CNT_FRAG_FWD_BYTES: forwarded fragment traffic bytes counter | 537 | * @BATADV_CNT_FRAG_FWD_BYTES: forwarded fragment traffic bytes counter |
538 | * @BATADV_CNT_TT_REQUEST_TX: transmitted tt req traffic packet counter | 538 | * @BATADV_CNT_TT_REQUEST_TX: transmitted tt req traffic packet counter |
539 | * @BATADV_CNT_TT_REQUEST_RX: received tt req traffic packet counter | 539 | * @BATADV_CNT_TT_REQUEST_RX: received tt req traffic packet counter |
540 | * @BATADV_CNT_TT_RESPONSE_TX: transmitted tt resp traffic packet counter | 540 | * @BATADV_CNT_TT_RESPONSE_TX: transmitted tt resp traffic packet counter |
541 | * @BATADV_CNT_TT_RESPONSE_RX: received tt resp traffic packet counter | 541 | * @BATADV_CNT_TT_RESPONSE_RX: received tt resp traffic packet counter |
542 | * @BATADV_CNT_TT_ROAM_ADV_TX: transmitted tt roam traffic packet counter | 542 | * @BATADV_CNT_TT_ROAM_ADV_TX: transmitted tt roam traffic packet counter |
543 | * @BATADV_CNT_TT_ROAM_ADV_RX: received tt roam traffic packet counter | 543 | * @BATADV_CNT_TT_ROAM_ADV_RX: received tt roam traffic packet counter |
544 | * @BATADV_CNT_DAT_GET_TX: transmitted dht GET traffic packet counter | 544 | * @BATADV_CNT_DAT_GET_TX: transmitted dht GET traffic packet counter |
545 | * @BATADV_CNT_DAT_GET_RX: received dht GET traffic packet counter | 545 | * @BATADV_CNT_DAT_GET_RX: received dht GET traffic packet counter |
546 | * @BATADV_CNT_DAT_PUT_TX: transmitted dht PUT traffic packet counter | 546 | * @BATADV_CNT_DAT_PUT_TX: transmitted dht PUT traffic packet counter |
547 | * @BATADV_CNT_DAT_PUT_RX: received dht PUT traffic packet counter | 547 | * @BATADV_CNT_DAT_PUT_RX: received dht PUT traffic packet counter |
548 | * @BATADV_CNT_DAT_CACHED_REPLY_TX: transmitted dat cache reply traffic packet | 548 | * @BATADV_CNT_DAT_CACHED_REPLY_TX: transmitted dat cache reply traffic packet |
549 | * counter | 549 | * counter |
550 | * @BATADV_CNT_NC_CODE: transmitted nc-combined traffic packet counter | 550 | * @BATADV_CNT_NC_CODE: transmitted nc-combined traffic packet counter |
551 | * @BATADV_CNT_NC_CODE_BYTES: transmitted nc-combined traffic bytes counter | 551 | * @BATADV_CNT_NC_CODE_BYTES: transmitted nc-combined traffic bytes counter |
552 | * @BATADV_CNT_NC_RECODE: transmitted nc-recombined traffic packet counter | 552 | * @BATADV_CNT_NC_RECODE: transmitted nc-recombined traffic packet counter |
553 | * @BATADV_CNT_NC_RECODE_BYTES: transmitted nc-recombined traffic bytes counter | 553 | * @BATADV_CNT_NC_RECODE_BYTES: transmitted nc-recombined traffic bytes counter |
554 | * @BATADV_CNT_NC_BUFFER: counter for packets buffered for later nc decoding | 554 | * @BATADV_CNT_NC_BUFFER: counter for packets buffered for later nc decoding |
555 | * @BATADV_CNT_NC_DECODE: received and nc-decoded traffic packet counter | 555 | * @BATADV_CNT_NC_DECODE: received and nc-decoded traffic packet counter |
556 | * @BATADV_CNT_NC_DECODE_BYTES: received and nc-decoded traffic bytes counter | 556 | * @BATADV_CNT_NC_DECODE_BYTES: received and nc-decoded traffic bytes counter |
557 | * @BATADV_CNT_NC_DECODE_FAILED: received and decode-failed traffic packet | 557 | * @BATADV_CNT_NC_DECODE_FAILED: received and decode-failed traffic packet |
558 | * counter | 558 | * counter |
559 | * @BATADV_CNT_NC_SNIFFED: counter for nc-decoded packets received in promisc | 559 | * @BATADV_CNT_NC_SNIFFED: counter for nc-decoded packets received in promisc |
560 | * mode. | 560 | * mode. |
561 | * @BATADV_CNT_NUM: number of traffic counters | 561 | * @BATADV_CNT_NUM: number of traffic counters |
562 | */ | 562 | */ |
563 | enum batadv_counters { | 563 | enum batadv_counters { |
564 | BATADV_CNT_TX, | 564 | BATADV_CNT_TX, |
565 | BATADV_CNT_TX_BYTES, | 565 | BATADV_CNT_TX_BYTES, |
566 | BATADV_CNT_TX_DROPPED, | 566 | BATADV_CNT_TX_DROPPED, |
567 | BATADV_CNT_RX, | 567 | BATADV_CNT_RX, |
568 | BATADV_CNT_RX_BYTES, | 568 | BATADV_CNT_RX_BYTES, |
569 | BATADV_CNT_FORWARD, | 569 | BATADV_CNT_FORWARD, |
570 | BATADV_CNT_FORWARD_BYTES, | 570 | BATADV_CNT_FORWARD_BYTES, |
571 | BATADV_CNT_MGMT_TX, | 571 | BATADV_CNT_MGMT_TX, |
572 | BATADV_CNT_MGMT_TX_BYTES, | 572 | BATADV_CNT_MGMT_TX_BYTES, |
573 | BATADV_CNT_MGMT_RX, | 573 | BATADV_CNT_MGMT_RX, |
574 | BATADV_CNT_MGMT_RX_BYTES, | 574 | BATADV_CNT_MGMT_RX_BYTES, |
575 | BATADV_CNT_FRAG_TX, | 575 | BATADV_CNT_FRAG_TX, |
576 | BATADV_CNT_FRAG_TX_BYTES, | 576 | BATADV_CNT_FRAG_TX_BYTES, |
577 | BATADV_CNT_FRAG_RX, | 577 | BATADV_CNT_FRAG_RX, |
578 | BATADV_CNT_FRAG_RX_BYTES, | 578 | BATADV_CNT_FRAG_RX_BYTES, |
579 | BATADV_CNT_FRAG_FWD, | 579 | BATADV_CNT_FRAG_FWD, |
580 | BATADV_CNT_FRAG_FWD_BYTES, | 580 | BATADV_CNT_FRAG_FWD_BYTES, |
581 | BATADV_CNT_TT_REQUEST_TX, | 581 | BATADV_CNT_TT_REQUEST_TX, |
582 | BATADV_CNT_TT_REQUEST_RX, | 582 | BATADV_CNT_TT_REQUEST_RX, |
583 | BATADV_CNT_TT_RESPONSE_TX, | 583 | BATADV_CNT_TT_RESPONSE_TX, |
584 | BATADV_CNT_TT_RESPONSE_RX, | 584 | BATADV_CNT_TT_RESPONSE_RX, |
585 | BATADV_CNT_TT_ROAM_ADV_TX, | 585 | BATADV_CNT_TT_ROAM_ADV_TX, |
586 | BATADV_CNT_TT_ROAM_ADV_RX, | 586 | BATADV_CNT_TT_ROAM_ADV_RX, |
587 | #ifdef CONFIG_BATMAN_ADV_DAT | 587 | #ifdef CONFIG_BATMAN_ADV_DAT |
588 | BATADV_CNT_DAT_GET_TX, | 588 | BATADV_CNT_DAT_GET_TX, |
589 | BATADV_CNT_DAT_GET_RX, | 589 | BATADV_CNT_DAT_GET_RX, |
590 | BATADV_CNT_DAT_PUT_TX, | 590 | BATADV_CNT_DAT_PUT_TX, |
591 | BATADV_CNT_DAT_PUT_RX, | 591 | BATADV_CNT_DAT_PUT_RX, |
592 | BATADV_CNT_DAT_CACHED_REPLY_TX, | 592 | BATADV_CNT_DAT_CACHED_REPLY_TX, |
593 | #endif | 593 | #endif |
594 | #ifdef CONFIG_BATMAN_ADV_NC | 594 | #ifdef CONFIG_BATMAN_ADV_NC |
595 | BATADV_CNT_NC_CODE, | 595 | BATADV_CNT_NC_CODE, |
596 | BATADV_CNT_NC_CODE_BYTES, | 596 | BATADV_CNT_NC_CODE_BYTES, |
597 | BATADV_CNT_NC_RECODE, | 597 | BATADV_CNT_NC_RECODE, |
598 | BATADV_CNT_NC_RECODE_BYTES, | 598 | BATADV_CNT_NC_RECODE_BYTES, |
599 | BATADV_CNT_NC_BUFFER, | 599 | BATADV_CNT_NC_BUFFER, |
600 | BATADV_CNT_NC_DECODE, | 600 | BATADV_CNT_NC_DECODE, |
601 | BATADV_CNT_NC_DECODE_BYTES, | 601 | BATADV_CNT_NC_DECODE_BYTES, |
602 | BATADV_CNT_NC_DECODE_FAILED, | 602 | BATADV_CNT_NC_DECODE_FAILED, |
603 | BATADV_CNT_NC_SNIFFED, | 603 | BATADV_CNT_NC_SNIFFED, |
604 | #endif | 604 | #endif |
605 | BATADV_CNT_NUM, | 605 | BATADV_CNT_NUM, |
606 | }; | 606 | }; |
607 | 607 | ||
608 | /** | 608 | /** |
609 | * struct batadv_priv_tt - per mesh interface translation table data | 609 | * struct batadv_priv_tt - per mesh interface translation table data |
610 | * @vn: translation table version number | 610 | * @vn: translation table version number |
611 | * @ogm_append_cnt: counter of number of OGMs containing the local tt diff | 611 | * @ogm_append_cnt: counter of number of OGMs containing the local tt diff |
612 | * @local_changes: changes registered in an originator interval | 612 | * @local_changes: changes registered in an originator interval |
613 | * @changes_list: tracks tt local changes within an originator interval | 613 | * @changes_list: tracks tt local changes within an originator interval |
614 | * @local_hash: local translation table hash table | 614 | * @local_hash: local translation table hash table |
615 | * @global_hash: global translation table hash table | 615 | * @global_hash: global translation table hash table |
616 | * @req_list: list of pending & unanswered tt_requests | 616 | * @req_list: list of pending & unanswered tt_requests |
617 | * @roam_list: list of the last roaming events of each client limiting the | 617 | * @roam_list: list of the last roaming events of each client limiting the |
618 | * number of roaming events to avoid route flapping | 618 | * number of roaming events to avoid route flapping |
619 | * @changes_list_lock: lock protecting changes_list | 619 | * @changes_list_lock: lock protecting changes_list |
620 | * @req_list_lock: lock protecting req_list | 620 | * @req_list_lock: lock protecting req_list |
621 | * @roam_list_lock: lock protecting roam_list | 621 | * @roam_list_lock: lock protecting roam_list |
622 | * @last_changeset: last tt changeset this host has generated | 622 | * @last_changeset: last tt changeset this host has generated |
623 | * @last_changeset_len: length of last tt changeset this host has generated | 623 | * @last_changeset_len: length of last tt changeset this host has generated |
624 | * @last_changeset_lock: lock protecting last_changeset & last_changeset_len | 624 | * @last_changeset_lock: lock protecting last_changeset & last_changeset_len |
625 | * @commit_lock: prevents from executing a local TT commit while reading the | 625 | * @commit_lock: prevents from executing a local TT commit while reading the |
626 | * local table. The local TT commit is made up by two operations (data | 626 | * local table. The local TT commit is made up by two operations (data |
627 | * structure update and metdata -CRC/TTVN- recalculation) and they have to be | 627 | * structure update and metdata -CRC/TTVN- recalculation) and they have to be |
628 | * executed atomically in order to avoid another thread to read the | 628 | * executed atomically in order to avoid another thread to read the |
629 | * table/metadata between those. | 629 | * table/metadata between those. |
630 | * @work: work queue callback item for translation table purging | 630 | * @work: work queue callback item for translation table purging |
631 | */ | 631 | */ |
632 | struct batadv_priv_tt { | 632 | struct batadv_priv_tt { |
633 | atomic_t vn; | 633 | atomic_t vn; |
634 | atomic_t ogm_append_cnt; | 634 | atomic_t ogm_append_cnt; |
635 | atomic_t local_changes; | 635 | atomic_t local_changes; |
636 | struct list_head changes_list; | 636 | struct list_head changes_list; |
637 | struct batadv_hashtable *local_hash; | 637 | struct batadv_hashtable *local_hash; |
638 | struct batadv_hashtable *global_hash; | 638 | struct batadv_hashtable *global_hash; |
639 | struct hlist_head req_list; | 639 | struct hlist_head req_list; |
640 | struct list_head roam_list; | 640 | struct list_head roam_list; |
641 | spinlock_t changes_list_lock; /* protects changes */ | 641 | spinlock_t changes_list_lock; /* protects changes */ |
642 | spinlock_t req_list_lock; /* protects req_list */ | 642 | spinlock_t req_list_lock; /* protects req_list */ |
643 | spinlock_t roam_list_lock; /* protects roam_list */ | 643 | spinlock_t roam_list_lock; /* protects roam_list */ |
644 | unsigned char *last_changeset; | 644 | unsigned char *last_changeset; |
645 | s16 last_changeset_len; | 645 | s16 last_changeset_len; |
646 | /* protects last_changeset & last_changeset_len */ | 646 | /* protects last_changeset & last_changeset_len */ |
647 | spinlock_t last_changeset_lock; | 647 | spinlock_t last_changeset_lock; |
648 | /* prevents from executing a commit while reading the table */ | 648 | /* prevents from executing a commit while reading the table */ |
649 | spinlock_t commit_lock; | 649 | spinlock_t commit_lock; |
650 | struct delayed_work work; | 650 | struct delayed_work work; |
651 | }; | 651 | }; |
652 | 652 | ||
653 | #ifdef CONFIG_BATMAN_ADV_BLA | 653 | #ifdef CONFIG_BATMAN_ADV_BLA |
654 | 654 | ||
655 | /** | 655 | /** |
656 | * struct batadv_priv_bla - per mesh interface bridge loope avoidance data | 656 | * struct batadv_priv_bla - per mesh interface bridge loope avoidance data |
657 | * @num_requests: number of bla requests in flight | 657 | * @num_requests: number of bla requests in flight |
658 | * @claim_hash: hash table containing mesh nodes this host has claimed | 658 | * @claim_hash: hash table containing mesh nodes this host has claimed |
659 | * @backbone_hash: hash table containing all detected backbone gateways | 659 | * @backbone_hash: hash table containing all detected backbone gateways |
660 | * @loopdetect_addr: MAC address used for own loopdetection frames | 660 | * @loopdetect_addr: MAC address used for own loopdetection frames |
661 | * @loopdetect_lasttime: time when the loopdetection frames were sent | 661 | * @loopdetect_lasttime: time when the loopdetection frames were sent |
662 | * @loopdetect_next: how many periods to wait for the next loopdetect process | 662 | * @loopdetect_next: how many periods to wait for the next loopdetect process |
663 | * @bcast_duplist: recently received broadcast packets array (for broadcast | 663 | * @bcast_duplist: recently received broadcast packets array (for broadcast |
664 | * duplicate suppression) | 664 | * duplicate suppression) |
665 | * @bcast_duplist_curr: index of last broadcast packet added to bcast_duplist | 665 | * @bcast_duplist_curr: index of last broadcast packet added to bcast_duplist |
666 | * @bcast_duplist_lock: lock protecting bcast_duplist & bcast_duplist_curr | 666 | * @bcast_duplist_lock: lock protecting bcast_duplist & bcast_duplist_curr |
667 | * @claim_dest: local claim data (e.g. claim group) | 667 | * @claim_dest: local claim data (e.g. claim group) |
668 | * @work: work queue callback item for cleanups & bla announcements | 668 | * @work: work queue callback item for cleanups & bla announcements |
669 | */ | 669 | */ |
670 | struct batadv_priv_bla { | 670 | struct batadv_priv_bla { |
671 | atomic_t num_requests; | 671 | atomic_t num_requests; |
672 | struct batadv_hashtable *claim_hash; | 672 | struct batadv_hashtable *claim_hash; |
673 | struct batadv_hashtable *backbone_hash; | 673 | struct batadv_hashtable *backbone_hash; |
674 | u8 loopdetect_addr[ETH_ALEN]; | 674 | u8 loopdetect_addr[ETH_ALEN]; |
675 | unsigned long loopdetect_lasttime; | 675 | unsigned long loopdetect_lasttime; |
676 | atomic_t loopdetect_next; | 676 | atomic_t loopdetect_next; |
677 | struct batadv_bcast_duplist_entry bcast_duplist[BATADV_DUPLIST_SIZE]; | 677 | struct batadv_bcast_duplist_entry bcast_duplist[BATADV_DUPLIST_SIZE]; |
678 | int bcast_duplist_curr; | 678 | int bcast_duplist_curr; |
679 | /* protects bcast_duplist & bcast_duplist_curr */ | 679 | /* protects bcast_duplist & bcast_duplist_curr */ |
680 | spinlock_t bcast_duplist_lock; | 680 | spinlock_t bcast_duplist_lock; |
681 | struct batadv_bla_claim_dst claim_dest; | 681 | struct batadv_bla_claim_dst claim_dest; |
682 | struct delayed_work work; | 682 | struct delayed_work work; |
683 | }; | 683 | }; |
684 | #endif | 684 | #endif |
685 | 685 | ||
686 | #ifdef CONFIG_BATMAN_ADV_DEBUG | 686 | #ifdef CONFIG_BATMAN_ADV_DEBUG |
687 | 687 | ||
688 | /** | 688 | /** |
689 | * struct batadv_priv_debug_log - debug logging data | 689 | * struct batadv_priv_debug_log - debug logging data |
690 | * @log_buff: buffer holding the logs (ring bufer) | 690 | * @log_buff: buffer holding the logs (ring bufer) |
691 | * @log_start: index of next character to read | 691 | * @log_start: index of next character to read |
692 | * @log_end: index of next character to write | 692 | * @log_end: index of next character to write |
693 | * @lock: lock protecting log_buff, log_start & log_end | 693 | * @lock: lock protecting log_buff, log_start & log_end |
694 | * @queue_wait: log reader's wait queue | 694 | * @queue_wait: log reader's wait queue |
695 | */ | 695 | */ |
696 | struct batadv_priv_debug_log { | 696 | struct batadv_priv_debug_log { |
697 | char log_buff[BATADV_LOG_BUF_LEN]; | 697 | char log_buff[BATADV_LOG_BUF_LEN]; |
698 | unsigned long log_start; | 698 | unsigned long log_start; |
699 | unsigned long log_end; | 699 | unsigned long log_end; |
700 | spinlock_t lock; /* protects log_buff, log_start and log_end */ | 700 | spinlock_t lock; /* protects log_buff, log_start and log_end */ |
701 | wait_queue_head_t queue_wait; | 701 | wait_queue_head_t queue_wait; |
702 | }; | 702 | }; |
703 | #endif | 703 | #endif |
704 | 704 | ||
705 | /** | 705 | /** |
706 | * struct batadv_priv_gw - per mesh interface gateway data | 706 | * struct batadv_priv_gw - per mesh interface gateway data |
707 | * @list: list of available gateway nodes | 707 | * @list: list of available gateway nodes |
708 | * @list_lock: lock protecting gw_list & curr_gw | 708 | * @list_lock: lock protecting gw_list & curr_gw |
709 | * @curr_gw: pointer to currently selected gateway node | 709 | * @curr_gw: pointer to currently selected gateway node |
710 | * @mode: gateway operation: off, client or server (see batadv_gw_modes) | ||
711 | * @sel_class: gateway selection class (applies if gw_mode client) | ||
710 | * @bandwidth_down: advertised uplink download bandwidth (if gw_mode server) | 712 | * @bandwidth_down: advertised uplink download bandwidth (if gw_mode server) |
711 | * @bandwidth_up: advertised uplink upload bandwidth (if gw_mode server) | 713 | * @bandwidth_up: advertised uplink upload bandwidth (if gw_mode server) |
712 | * @reselect: bool indicating a gateway re-selection is in progress | 714 | * @reselect: bool indicating a gateway re-selection is in progress |
713 | */ | 715 | */ |
714 | struct batadv_priv_gw { | 716 | struct batadv_priv_gw { |
715 | struct hlist_head list; | 717 | struct hlist_head list; |
716 | spinlock_t list_lock; /* protects gw_list & curr_gw */ | 718 | spinlock_t list_lock; /* protects gw_list & curr_gw */ |
717 | struct batadv_gw_node __rcu *curr_gw; /* rcu protected pointer */ | 719 | struct batadv_gw_node __rcu *curr_gw; /* rcu protected pointer */ |
720 | atomic_t mode; | ||
721 | atomic_t sel_class; | ||
718 | atomic_t bandwidth_down; | 722 | atomic_t bandwidth_down; |
719 | atomic_t bandwidth_up; | 723 | atomic_t bandwidth_up; |
720 | atomic_t reselect; | 724 | atomic_t reselect; |
721 | }; | 725 | }; |
722 | 726 | ||
723 | /** | 727 | /** |
724 | * struct batadv_priv_tvlv - per mesh interface tvlv data | 728 | * struct batadv_priv_tvlv - per mesh interface tvlv data |
725 | * @container_list: list of registered tvlv containers to be sent with each OGM | 729 | * @container_list: list of registered tvlv containers to be sent with each OGM |
726 | * @handler_list: list of the various tvlv content handlers | 730 | * @handler_list: list of the various tvlv content handlers |
727 | * @container_list_lock: protects tvlv container list access | 731 | * @container_list_lock: protects tvlv container list access |
728 | * @handler_list_lock: protects handler list access | 732 | * @handler_list_lock: protects handler list access |
729 | */ | 733 | */ |
730 | struct batadv_priv_tvlv { | 734 | struct batadv_priv_tvlv { |
731 | struct hlist_head container_list; | 735 | struct hlist_head container_list; |
732 | struct hlist_head handler_list; | 736 | struct hlist_head handler_list; |
733 | spinlock_t container_list_lock; /* protects container_list */ | 737 | spinlock_t container_list_lock; /* protects container_list */ |
734 | spinlock_t handler_list_lock; /* protects handler_list */ | 738 | spinlock_t handler_list_lock; /* protects handler_list */ |
735 | }; | 739 | }; |
736 | 740 | ||
737 | #ifdef CONFIG_BATMAN_ADV_DAT | 741 | #ifdef CONFIG_BATMAN_ADV_DAT |
738 | 742 | ||
739 | /** | 743 | /** |
740 | * struct batadv_priv_dat - per mesh interface DAT private data | 744 | * struct batadv_priv_dat - per mesh interface DAT private data |
741 | * @addr: node DAT address | 745 | * @addr: node DAT address |
742 | * @hash: hashtable representing the local ARP cache | 746 | * @hash: hashtable representing the local ARP cache |
743 | * @work: work queue callback item for cache purging | 747 | * @work: work queue callback item for cache purging |
744 | */ | 748 | */ |
745 | struct batadv_priv_dat { | 749 | struct batadv_priv_dat { |
746 | batadv_dat_addr_t addr; | 750 | batadv_dat_addr_t addr; |
747 | struct batadv_hashtable *hash; | 751 | struct batadv_hashtable *hash; |
748 | struct delayed_work work; | 752 | struct delayed_work work; |
749 | }; | 753 | }; |
750 | #endif | 754 | #endif |
751 | 755 | ||
752 | #ifdef CONFIG_BATMAN_ADV_MCAST | 756 | #ifdef CONFIG_BATMAN_ADV_MCAST |
753 | /** | 757 | /** |
754 | * struct batadv_priv_mcast - per mesh interface mcast data | 758 | * struct batadv_priv_mcast - per mesh interface mcast data |
755 | * @mla_list: list of multicast addresses we are currently announcing via TT | 759 | * @mla_list: list of multicast addresses we are currently announcing via TT |
756 | * @want_all_unsnoopables_list: a list of orig_nodes wanting all unsnoopable | 760 | * @want_all_unsnoopables_list: a list of orig_nodes wanting all unsnoopable |
757 | * multicast traffic | 761 | * multicast traffic |
758 | * @want_all_ipv4_list: a list of orig_nodes wanting all IPv4 multicast traffic | 762 | * @want_all_ipv4_list: a list of orig_nodes wanting all IPv4 multicast traffic |
759 | * @want_all_ipv6_list: a list of orig_nodes wanting all IPv6 multicast traffic | 763 | * @want_all_ipv6_list: a list of orig_nodes wanting all IPv6 multicast traffic |
760 | * @flags: the flags we have last sent in our mcast tvlv | 764 | * @flags: the flags we have last sent in our mcast tvlv |
761 | * @enabled: whether the multicast tvlv is currently enabled | 765 | * @enabled: whether the multicast tvlv is currently enabled |
762 | * @num_disabled: number of nodes that have no mcast tvlv | 766 | * @num_disabled: number of nodes that have no mcast tvlv |
763 | * @num_want_all_unsnoopables: number of nodes wanting unsnoopable IP traffic | 767 | * @num_want_all_unsnoopables: number of nodes wanting unsnoopable IP traffic |
764 | * @num_want_all_ipv4: counter for items in want_all_ipv4_list | 768 | * @num_want_all_ipv4: counter for items in want_all_ipv4_list |
765 | * @num_want_all_ipv6: counter for items in want_all_ipv6_list | 769 | * @num_want_all_ipv6: counter for items in want_all_ipv6_list |
766 | * @want_lists_lock: lock for protecting modifications to mcast want lists | 770 | * @want_lists_lock: lock for protecting modifications to mcast want lists |
767 | * (traversals are rcu-locked) | 771 | * (traversals are rcu-locked) |
768 | */ | 772 | */ |
769 | struct batadv_priv_mcast { | 773 | struct batadv_priv_mcast { |
770 | struct hlist_head mla_list; | 774 | struct hlist_head mla_list; |
771 | struct hlist_head want_all_unsnoopables_list; | 775 | struct hlist_head want_all_unsnoopables_list; |
772 | struct hlist_head want_all_ipv4_list; | 776 | struct hlist_head want_all_ipv4_list; |
773 | struct hlist_head want_all_ipv6_list; | 777 | struct hlist_head want_all_ipv6_list; |
774 | u8 flags; | 778 | u8 flags; |
775 | bool enabled; | 779 | bool enabled; |
776 | atomic_t num_disabled; | 780 | atomic_t num_disabled; |
777 | atomic_t num_want_all_unsnoopables; | 781 | atomic_t num_want_all_unsnoopables; |
778 | atomic_t num_want_all_ipv4; | 782 | atomic_t num_want_all_ipv4; |
779 | atomic_t num_want_all_ipv6; | 783 | atomic_t num_want_all_ipv6; |
780 | /* protects want_all_{unsnoopables,ipv4,ipv6}_list */ | 784 | /* protects want_all_{unsnoopables,ipv4,ipv6}_list */ |
781 | spinlock_t want_lists_lock; | 785 | spinlock_t want_lists_lock; |
782 | }; | 786 | }; |
783 | #endif | 787 | #endif |
784 | 788 | ||
785 | /** | 789 | /** |
786 | * struct batadv_priv_nc - per mesh interface network coding private data | 790 | * struct batadv_priv_nc - per mesh interface network coding private data |
787 | * @work: work queue callback item for cleanup | 791 | * @work: work queue callback item for cleanup |
788 | * @debug_dir: dentry for nc subdir in batman-adv directory in debugfs | 792 | * @debug_dir: dentry for nc subdir in batman-adv directory in debugfs |
789 | * @min_tq: only consider neighbors for encoding if neigh_tq > min_tq | 793 | * @min_tq: only consider neighbors for encoding if neigh_tq > min_tq |
790 | * @max_fwd_delay: maximum packet forward delay to allow coding of packets | 794 | * @max_fwd_delay: maximum packet forward delay to allow coding of packets |
791 | * @max_buffer_time: buffer time for sniffed packets used to decoding | 795 | * @max_buffer_time: buffer time for sniffed packets used to decoding |
792 | * @timestamp_fwd_flush: timestamp of last forward packet queue flush | 796 | * @timestamp_fwd_flush: timestamp of last forward packet queue flush |
793 | * @timestamp_sniffed_purge: timestamp of last sniffed packet queue purge | 797 | * @timestamp_sniffed_purge: timestamp of last sniffed packet queue purge |
794 | * @coding_hash: Hash table used to buffer skbs while waiting for another | 798 | * @coding_hash: Hash table used to buffer skbs while waiting for another |
795 | * incoming skb to code it with. Skbs are added to the buffer just before being | 799 | * incoming skb to code it with. Skbs are added to the buffer just before being |
796 | * forwarded in routing.c | 800 | * forwarded in routing.c |
797 | * @decoding_hash: Hash table used to buffer skbs that might be needed to decode | 801 | * @decoding_hash: Hash table used to buffer skbs that might be needed to decode |
798 | * a received coded skb. The buffer is used for 1) skbs arriving on the | 802 | * a received coded skb. The buffer is used for 1) skbs arriving on the |
799 | * soft-interface; 2) skbs overheard on the hard-interface; and 3) skbs | 803 | * soft-interface; 2) skbs overheard on the hard-interface; and 3) skbs |
800 | * forwarded by batman-adv. | 804 | * forwarded by batman-adv. |
801 | */ | 805 | */ |
802 | struct batadv_priv_nc { | 806 | struct batadv_priv_nc { |
803 | struct delayed_work work; | 807 | struct delayed_work work; |
804 | struct dentry *debug_dir; | 808 | struct dentry *debug_dir; |
805 | u8 min_tq; | 809 | u8 min_tq; |
806 | u32 max_fwd_delay; | 810 | u32 max_fwd_delay; |
807 | u32 max_buffer_time; | 811 | u32 max_buffer_time; |
808 | unsigned long timestamp_fwd_flush; | 812 | unsigned long timestamp_fwd_flush; |
809 | unsigned long timestamp_sniffed_purge; | 813 | unsigned long timestamp_sniffed_purge; |
810 | struct batadv_hashtable *coding_hash; | 814 | struct batadv_hashtable *coding_hash; |
811 | struct batadv_hashtable *decoding_hash; | 815 | struct batadv_hashtable *decoding_hash; |
812 | }; | 816 | }; |
813 | 817 | ||
814 | /** | 818 | /** |
815 | * struct batadv_softif_vlan - per VLAN attributes set | 819 | * struct batadv_softif_vlan - per VLAN attributes set |
816 | * @bat_priv: pointer to the mesh object | 820 | * @bat_priv: pointer to the mesh object |
817 | * @vid: VLAN identifier | 821 | * @vid: VLAN identifier |
818 | * @kobj: kobject for sysfs vlan subdirectory | 822 | * @kobj: kobject for sysfs vlan subdirectory |
819 | * @ap_isolation: AP isolation state | 823 | * @ap_isolation: AP isolation state |
820 | * @tt: TT private attributes (VLAN specific) | 824 | * @tt: TT private attributes (VLAN specific) |
821 | * @list: list node for bat_priv::softif_vlan_list | 825 | * @list: list node for bat_priv::softif_vlan_list |
822 | * @refcount: number of context where this object is currently in use | 826 | * @refcount: number of context where this object is currently in use |
823 | * @rcu: struct used for freeing in a RCU-safe manner | 827 | * @rcu: struct used for freeing in a RCU-safe manner |
824 | */ | 828 | */ |
825 | struct batadv_softif_vlan { | 829 | struct batadv_softif_vlan { |
826 | struct batadv_priv *bat_priv; | 830 | struct batadv_priv *bat_priv; |
827 | unsigned short vid; | 831 | unsigned short vid; |
828 | struct kobject *kobj; | 832 | struct kobject *kobj; |
829 | atomic_t ap_isolation; /* boolean */ | 833 | atomic_t ap_isolation; /* boolean */ |
830 | struct batadv_vlan_tt tt; | 834 | struct batadv_vlan_tt tt; |
831 | struct hlist_node list; | 835 | struct hlist_node list; |
832 | struct kref refcount; | 836 | struct kref refcount; |
833 | struct rcu_head rcu; | 837 | struct rcu_head rcu; |
834 | }; | 838 | }; |
835 | 839 | ||
836 | /** | 840 | /** |
837 | * struct batadv_priv_bat_v - B.A.T.M.A.N. V per soft-interface private data | 841 | * struct batadv_priv_bat_v - B.A.T.M.A.N. V per soft-interface private data |
838 | * @ogm_buff: buffer holding the OGM packet | 842 | * @ogm_buff: buffer holding the OGM packet |
839 | * @ogm_buff_len: length of the OGM packet buffer | 843 | * @ogm_buff_len: length of the OGM packet buffer |
840 | * @ogm_seqno: OGM sequence number - used to identify each OGM | 844 | * @ogm_seqno: OGM sequence number - used to identify each OGM |
841 | * @ogm_wq: workqueue used to schedule OGM transmissions | 845 | * @ogm_wq: workqueue used to schedule OGM transmissions |
842 | */ | 846 | */ |
843 | struct batadv_priv_bat_v { | 847 | struct batadv_priv_bat_v { |
844 | unsigned char *ogm_buff; | 848 | unsigned char *ogm_buff; |
845 | int ogm_buff_len; | 849 | int ogm_buff_len; |
846 | atomic_t ogm_seqno; | 850 | atomic_t ogm_seqno; |
847 | struct delayed_work ogm_wq; | 851 | struct delayed_work ogm_wq; |
848 | }; | 852 | }; |
849 | 853 | ||
850 | /** | 854 | /** |
851 | * struct batadv_priv - per mesh interface data | 855 | * struct batadv_priv - per mesh interface data |
852 | * @mesh_state: current status of the mesh (inactive/active/deactivating) | 856 | * @mesh_state: current status of the mesh (inactive/active/deactivating) |
853 | * @soft_iface: net device which holds this struct as private data | 857 | * @soft_iface: net device which holds this struct as private data |
854 | * @stats: structure holding the data for the ndo_get_stats() call | 858 | * @stats: structure holding the data for the ndo_get_stats() call |
855 | * @bat_counters: mesh internal traffic statistic counters (see batadv_counters) | 859 | * @bat_counters: mesh internal traffic statistic counters (see batadv_counters) |
856 | * @aggregated_ogms: bool indicating whether OGM aggregation is enabled | 860 | * @aggregated_ogms: bool indicating whether OGM aggregation is enabled |
857 | * @bonding: bool indicating whether traffic bonding is enabled | 861 | * @bonding: bool indicating whether traffic bonding is enabled |
858 | * @fragmentation: bool indicating whether traffic fragmentation is enabled | 862 | * @fragmentation: bool indicating whether traffic fragmentation is enabled |
859 | * @packet_size_max: max packet size that can be transmitted via | 863 | * @packet_size_max: max packet size that can be transmitted via |
860 | * multiple fragmented skbs or a single frame if fragmentation is disabled | 864 | * multiple fragmented skbs or a single frame if fragmentation is disabled |
861 | * @frag_seqno: incremental counter to identify chains of egress fragments | 865 | * @frag_seqno: incremental counter to identify chains of egress fragments |
862 | * @bridge_loop_avoidance: bool indicating whether bridge loop avoidance is | 866 | * @bridge_loop_avoidance: bool indicating whether bridge loop avoidance is |
863 | * enabled | 867 | * enabled |
864 | * @distributed_arp_table: bool indicating whether distributed ARP table is | 868 | * @distributed_arp_table: bool indicating whether distributed ARP table is |
865 | * enabled | 869 | * enabled |
866 | * @multicast_mode: Enable or disable multicast optimizations on this node's | 870 | * @multicast_mode: Enable or disable multicast optimizations on this node's |
867 | * sender/originating side | 871 | * sender/originating side |
868 | * @gw_mode: gateway operation: off, client or server (see batadv_gw_modes) | ||
869 | * @gw_sel_class: gateway selection class (applies if gw_mode client) | ||
870 | * @orig_interval: OGM broadcast interval in milliseconds | 872 | * @orig_interval: OGM broadcast interval in milliseconds |
871 | * @hop_penalty: penalty which will be applied to an OGM's tq-field on every hop | 873 | * @hop_penalty: penalty which will be applied to an OGM's tq-field on every hop |
872 | * @log_level: configured log level (see batadv_dbg_level) | 874 | * @log_level: configured log level (see batadv_dbg_level) |
873 | * @isolation_mark: the skb->mark value used to match packets for AP isolation | 875 | * @isolation_mark: the skb->mark value used to match packets for AP isolation |
874 | * @isolation_mark_mask: bitmask identifying the bits in skb->mark to be used | 876 | * @isolation_mark_mask: bitmask identifying the bits in skb->mark to be used |
875 | * for the isolation mark | 877 | * for the isolation mark |
876 | * @bcast_seqno: last sent broadcast packet sequence number | 878 | * @bcast_seqno: last sent broadcast packet sequence number |
877 | * @bcast_queue_left: number of remaining buffered broadcast packet slots | 879 | * @bcast_queue_left: number of remaining buffered broadcast packet slots |
878 | * @batman_queue_left: number of remaining OGM packet slots | 880 | * @batman_queue_left: number of remaining OGM packet slots |
879 | * @num_ifaces: number of interfaces assigned to this mesh interface | 881 | * @num_ifaces: number of interfaces assigned to this mesh interface |
880 | * @mesh_obj: kobject for sysfs mesh subdirectory | 882 | * @mesh_obj: kobject for sysfs mesh subdirectory |
881 | * @debug_dir: dentry for debugfs batman-adv subdirectory | 883 | * @debug_dir: dentry for debugfs batman-adv subdirectory |
882 | * @forw_bat_list: list of aggregated OGMs that will be forwarded | 884 | * @forw_bat_list: list of aggregated OGMs that will be forwarded |
883 | * @forw_bcast_list: list of broadcast packets that will be rebroadcasted | 885 | * @forw_bcast_list: list of broadcast packets that will be rebroadcasted |
884 | * @orig_hash: hash table containing mesh participants (orig nodes) | 886 | * @orig_hash: hash table containing mesh participants (orig nodes) |
885 | * @forw_bat_list_lock: lock protecting forw_bat_list | 887 | * @forw_bat_list_lock: lock protecting forw_bat_list |
886 | * @forw_bcast_list_lock: lock protecting forw_bcast_list | 888 | * @forw_bcast_list_lock: lock protecting forw_bcast_list |
887 | * @orig_work: work queue callback item for orig node purging | 889 | * @orig_work: work queue callback item for orig node purging |
888 | * @cleanup_work: work queue callback item for soft-interface deinit | 890 | * @cleanup_work: work queue callback item for soft-interface deinit |
889 | * @primary_if: one of the hard-interfaces assigned to this mesh interface | 891 | * @primary_if: one of the hard-interfaces assigned to this mesh interface |
890 | * becomes the primary interface | 892 | * becomes the primary interface |
891 | * @bat_algo_ops: routing algorithm used by this mesh interface | 893 | * @bat_algo_ops: routing algorithm used by this mesh interface |
892 | * @softif_vlan_list: a list of softif_vlan structs, one per VLAN created on top | 894 | * @softif_vlan_list: a list of softif_vlan structs, one per VLAN created on top |
893 | * of the mesh interface represented by this object | 895 | * of the mesh interface represented by this object |
894 | * @softif_vlan_list_lock: lock protecting softif_vlan_list | 896 | * @softif_vlan_list_lock: lock protecting softif_vlan_list |
895 | * @bla: bridge loope avoidance data | 897 | * @bla: bridge loope avoidance data |
896 | * @debug_log: holding debug logging relevant data | 898 | * @debug_log: holding debug logging relevant data |
897 | * @gw: gateway data | 899 | * @gw: gateway data |
898 | * @tt: translation table data | 900 | * @tt: translation table data |
899 | * @tvlv: type-version-length-value data | 901 | * @tvlv: type-version-length-value data |
900 | * @dat: distributed arp table data | 902 | * @dat: distributed arp table data |
901 | * @mcast: multicast data | 903 | * @mcast: multicast data |
902 | * @network_coding: bool indicating whether network coding is enabled | 904 | * @network_coding: bool indicating whether network coding is enabled |
903 | * @nc: network coding data | 905 | * @nc: network coding data |
904 | * @bat_v: B.A.T.M.A.N. V per soft-interface private data | 906 | * @bat_v: B.A.T.M.A.N. V per soft-interface private data |
905 | */ | 907 | */ |
906 | struct batadv_priv { | 908 | struct batadv_priv { |
907 | atomic_t mesh_state; | 909 | atomic_t mesh_state; |
908 | struct net_device *soft_iface; | 910 | struct net_device *soft_iface; |
909 | struct net_device_stats stats; | 911 | struct net_device_stats stats; |
910 | u64 __percpu *bat_counters; /* Per cpu counters */ | 912 | u64 __percpu *bat_counters; /* Per cpu counters */ |
911 | atomic_t aggregated_ogms; | 913 | atomic_t aggregated_ogms; |
912 | atomic_t bonding; | 914 | atomic_t bonding; |
913 | atomic_t fragmentation; | 915 | atomic_t fragmentation; |
914 | atomic_t packet_size_max; | 916 | atomic_t packet_size_max; |
915 | atomic_t frag_seqno; | 917 | atomic_t frag_seqno; |
916 | #ifdef CONFIG_BATMAN_ADV_BLA | 918 | #ifdef CONFIG_BATMAN_ADV_BLA |
917 | atomic_t bridge_loop_avoidance; | 919 | atomic_t bridge_loop_avoidance; |
918 | #endif | 920 | #endif |
919 | #ifdef CONFIG_BATMAN_ADV_DAT | 921 | #ifdef CONFIG_BATMAN_ADV_DAT |
920 | atomic_t distributed_arp_table; | 922 | atomic_t distributed_arp_table; |
921 | #endif | 923 | #endif |
922 | #ifdef CONFIG_BATMAN_ADV_MCAST | 924 | #ifdef CONFIG_BATMAN_ADV_MCAST |
923 | atomic_t multicast_mode; | 925 | atomic_t multicast_mode; |
924 | #endif | 926 | #endif |
925 | atomic_t gw_mode; | ||
926 | atomic_t gw_sel_class; | ||
927 | atomic_t orig_interval; | 927 | atomic_t orig_interval; |
928 | atomic_t hop_penalty; | 928 | atomic_t hop_penalty; |
929 | #ifdef CONFIG_BATMAN_ADV_DEBUG | 929 | #ifdef CONFIG_BATMAN_ADV_DEBUG |
930 | atomic_t log_level; | 930 | atomic_t log_level; |
931 | #endif | 931 | #endif |
932 | u32 isolation_mark; | 932 | u32 isolation_mark; |
933 | u32 isolation_mark_mask; | 933 | u32 isolation_mark_mask; |
934 | atomic_t bcast_seqno; | 934 | atomic_t bcast_seqno; |
935 | atomic_t bcast_queue_left; | 935 | atomic_t bcast_queue_left; |
936 | atomic_t batman_queue_left; | 936 | atomic_t batman_queue_left; |
937 | char num_ifaces; | 937 | char num_ifaces; |
938 | struct kobject *mesh_obj; | 938 | struct kobject *mesh_obj; |
939 | struct dentry *debug_dir; | 939 | struct dentry *debug_dir; |
940 | struct hlist_head forw_bat_list; | 940 | struct hlist_head forw_bat_list; |
941 | struct hlist_head forw_bcast_list; | 941 | struct hlist_head forw_bcast_list; |
942 | struct batadv_hashtable *orig_hash; | 942 | struct batadv_hashtable *orig_hash; |
943 | spinlock_t forw_bat_list_lock; /* protects forw_bat_list */ | 943 | spinlock_t forw_bat_list_lock; /* protects forw_bat_list */ |
944 | spinlock_t forw_bcast_list_lock; /* protects forw_bcast_list */ | 944 | spinlock_t forw_bcast_list_lock; /* protects forw_bcast_list */ |
945 | struct delayed_work orig_work; | 945 | struct delayed_work orig_work; |
946 | struct work_struct cleanup_work; | 946 | struct work_struct cleanup_work; |
947 | struct batadv_hard_iface __rcu *primary_if; /* rcu protected pointer */ | 947 | struct batadv_hard_iface __rcu *primary_if; /* rcu protected pointer */ |
948 | struct batadv_algo_ops *bat_algo_ops; | 948 | struct batadv_algo_ops *bat_algo_ops; |
949 | struct hlist_head softif_vlan_list; | 949 | struct hlist_head softif_vlan_list; |
950 | spinlock_t softif_vlan_list_lock; /* protects softif_vlan_list */ | 950 | spinlock_t softif_vlan_list_lock; /* protects softif_vlan_list */ |
951 | #ifdef CONFIG_BATMAN_ADV_BLA | 951 | #ifdef CONFIG_BATMAN_ADV_BLA |
952 | struct batadv_priv_bla bla; | 952 | struct batadv_priv_bla bla; |
953 | #endif | 953 | #endif |
954 | #ifdef CONFIG_BATMAN_ADV_DEBUG | 954 | #ifdef CONFIG_BATMAN_ADV_DEBUG |
955 | struct batadv_priv_debug_log *debug_log; | 955 | struct batadv_priv_debug_log *debug_log; |
956 | #endif | 956 | #endif |
957 | struct batadv_priv_gw gw; | 957 | struct batadv_priv_gw gw; |
958 | struct batadv_priv_tt tt; | 958 | struct batadv_priv_tt tt; |
959 | struct batadv_priv_tvlv tvlv; | 959 | struct batadv_priv_tvlv tvlv; |
960 | #ifdef CONFIG_BATMAN_ADV_DAT | 960 | #ifdef CONFIG_BATMAN_ADV_DAT |
961 | struct batadv_priv_dat dat; | 961 | struct batadv_priv_dat dat; |
962 | #endif | 962 | #endif |
963 | #ifdef CONFIG_BATMAN_ADV_MCAST | 963 | #ifdef CONFIG_BATMAN_ADV_MCAST |
964 | struct batadv_priv_mcast mcast; | 964 | struct batadv_priv_mcast mcast; |
965 | #endif | 965 | #endif |
966 | #ifdef CONFIG_BATMAN_ADV_NC | 966 | #ifdef CONFIG_BATMAN_ADV_NC |
967 | atomic_t network_coding; | 967 | atomic_t network_coding; |
968 | struct batadv_priv_nc nc; | 968 | struct batadv_priv_nc nc; |
969 | #endif /* CONFIG_BATMAN_ADV_NC */ | 969 | #endif /* CONFIG_BATMAN_ADV_NC */ |
970 | #ifdef CONFIG_BATMAN_ADV_BATMAN_V | 970 | #ifdef CONFIG_BATMAN_ADV_BATMAN_V |
971 | struct batadv_priv_bat_v bat_v; | 971 | struct batadv_priv_bat_v bat_v; |
972 | #endif | 972 | #endif |
973 | }; | 973 | }; |
974 | 974 | ||
975 | /** | 975 | /** |
976 | * struct batadv_socket_client - layer2 icmp socket client data | 976 | * struct batadv_socket_client - layer2 icmp socket client data |
977 | * @queue_list: packet queue for packets destined for this socket client | 977 | * @queue_list: packet queue for packets destined for this socket client |
978 | * @queue_len: number of packets in the packet queue (queue_list) | 978 | * @queue_len: number of packets in the packet queue (queue_list) |
979 | * @index: socket client's index in the batadv_socket_client_hash | 979 | * @index: socket client's index in the batadv_socket_client_hash |
980 | * @lock: lock protecting queue_list, queue_len & index | 980 | * @lock: lock protecting queue_list, queue_len & index |
981 | * @queue_wait: socket client's wait queue | 981 | * @queue_wait: socket client's wait queue |
982 | * @bat_priv: pointer to soft_iface this client belongs to | 982 | * @bat_priv: pointer to soft_iface this client belongs to |
983 | */ | 983 | */ |
984 | struct batadv_socket_client { | 984 | struct batadv_socket_client { |
985 | struct list_head queue_list; | 985 | struct list_head queue_list; |
986 | unsigned int queue_len; | 986 | unsigned int queue_len; |
987 | unsigned char index; | 987 | unsigned char index; |
988 | spinlock_t lock; /* protects queue_list, queue_len & index */ | 988 | spinlock_t lock; /* protects queue_list, queue_len & index */ |
989 | wait_queue_head_t queue_wait; | 989 | wait_queue_head_t queue_wait; |
990 | struct batadv_priv *bat_priv; | 990 | struct batadv_priv *bat_priv; |
991 | }; | 991 | }; |
992 | 992 | ||
993 | /** | 993 | /** |
994 | * struct batadv_socket_packet - layer2 icmp packet for socket client | 994 | * struct batadv_socket_packet - layer2 icmp packet for socket client |
995 | * @list: list node for batadv_socket_client::queue_list | 995 | * @list: list node for batadv_socket_client::queue_list |
996 | * @icmp_len: size of the layer2 icmp packet | 996 | * @icmp_len: size of the layer2 icmp packet |
997 | * @icmp_packet: layer2 icmp packet | 997 | * @icmp_packet: layer2 icmp packet |
998 | */ | 998 | */ |
999 | struct batadv_socket_packet { | 999 | struct batadv_socket_packet { |
1000 | struct list_head list; | 1000 | struct list_head list; |
1001 | size_t icmp_len; | 1001 | size_t icmp_len; |
1002 | u8 icmp_packet[BATADV_ICMP_MAX_PACKET_SIZE]; | 1002 | u8 icmp_packet[BATADV_ICMP_MAX_PACKET_SIZE]; |
1003 | }; | 1003 | }; |
1004 | 1004 | ||
1005 | #ifdef CONFIG_BATMAN_ADV_BLA | 1005 | #ifdef CONFIG_BATMAN_ADV_BLA |
1006 | 1006 | ||
1007 | /** | 1007 | /** |
1008 | * struct batadv_bla_backbone_gw - batman-adv gateway bridged into the LAN | 1008 | * struct batadv_bla_backbone_gw - batman-adv gateway bridged into the LAN |
1009 | * @orig: originator address of backbone node (mac address of primary iface) | 1009 | * @orig: originator address of backbone node (mac address of primary iface) |
1010 | * @vid: vlan id this gateway was detected on | 1010 | * @vid: vlan id this gateway was detected on |
1011 | * @hash_entry: hlist node for batadv_priv_bla::backbone_hash | 1011 | * @hash_entry: hlist node for batadv_priv_bla::backbone_hash |
1012 | * @bat_priv: pointer to soft_iface this backbone gateway belongs to | 1012 | * @bat_priv: pointer to soft_iface this backbone gateway belongs to |
1013 | * @lasttime: last time we heard of this backbone gw | 1013 | * @lasttime: last time we heard of this backbone gw |
1014 | * @wait_periods: grace time for bridge forward delays and bla group forming at | 1014 | * @wait_periods: grace time for bridge forward delays and bla group forming at |
1015 | * bootup phase - no bcast traffic is formwared until it has elapsed | 1015 | * bootup phase - no bcast traffic is formwared until it has elapsed |
1016 | * @request_sent: if this bool is set to true we are out of sync with this | 1016 | * @request_sent: if this bool is set to true we are out of sync with this |
1017 | * backbone gateway - no bcast traffic is formwared until the situation was | 1017 | * backbone gateway - no bcast traffic is formwared until the situation was |
1018 | * resolved | 1018 | * resolved |
1019 | * @crc: crc16 checksum over all claims | 1019 | * @crc: crc16 checksum over all claims |
1020 | * @crc_lock: lock protecting crc | 1020 | * @crc_lock: lock protecting crc |
1021 | * @report_work: work struct for reporting detected loops | 1021 | * @report_work: work struct for reporting detected loops |
1022 | * @refcount: number of contexts the object is used | 1022 | * @refcount: number of contexts the object is used |
1023 | * @rcu: struct used for freeing in an RCU-safe manner | 1023 | * @rcu: struct used for freeing in an RCU-safe manner |
1024 | */ | 1024 | */ |
1025 | struct batadv_bla_backbone_gw { | 1025 | struct batadv_bla_backbone_gw { |
1026 | u8 orig[ETH_ALEN]; | 1026 | u8 orig[ETH_ALEN]; |
1027 | unsigned short vid; | 1027 | unsigned short vid; |
1028 | struct hlist_node hash_entry; | 1028 | struct hlist_node hash_entry; |
1029 | struct batadv_priv *bat_priv; | 1029 | struct batadv_priv *bat_priv; |
1030 | unsigned long lasttime; | 1030 | unsigned long lasttime; |
1031 | atomic_t wait_periods; | 1031 | atomic_t wait_periods; |
1032 | atomic_t request_sent; | 1032 | atomic_t request_sent; |
1033 | u16 crc; | 1033 | u16 crc; |
1034 | spinlock_t crc_lock; /* protects crc */ | 1034 | spinlock_t crc_lock; /* protects crc */ |
1035 | struct work_struct report_work; | 1035 | struct work_struct report_work; |
1036 | struct kref refcount; | 1036 | struct kref refcount; |
1037 | struct rcu_head rcu; | 1037 | struct rcu_head rcu; |
1038 | }; | 1038 | }; |
1039 | 1039 | ||
1040 | /** | 1040 | /** |
1041 | * struct batadv_bla_claim - claimed non-mesh client structure | 1041 | * struct batadv_bla_claim - claimed non-mesh client structure |
1042 | * @addr: mac address of claimed non-mesh client | 1042 | * @addr: mac address of claimed non-mesh client |
1043 | * @vid: vlan id this client was detected on | 1043 | * @vid: vlan id this client was detected on |
1044 | * @backbone_gw: pointer to backbone gw claiming this client | 1044 | * @backbone_gw: pointer to backbone gw claiming this client |
1045 | * @lasttime: last time we heard of claim (locals only) | 1045 | * @lasttime: last time we heard of claim (locals only) |
1046 | * @hash_entry: hlist node for batadv_priv_bla::claim_hash | 1046 | * @hash_entry: hlist node for batadv_priv_bla::claim_hash |
1047 | * @refcount: number of contexts the object is used | 1047 | * @refcount: number of contexts the object is used |
1048 | * @rcu: struct used for freeing in an RCU-safe manner | 1048 | * @rcu: struct used for freeing in an RCU-safe manner |
1049 | */ | 1049 | */ |
1050 | struct batadv_bla_claim { | 1050 | struct batadv_bla_claim { |
1051 | u8 addr[ETH_ALEN]; | 1051 | u8 addr[ETH_ALEN]; |
1052 | unsigned short vid; | 1052 | unsigned short vid; |
1053 | struct batadv_bla_backbone_gw *backbone_gw; | 1053 | struct batadv_bla_backbone_gw *backbone_gw; |
1054 | unsigned long lasttime; | 1054 | unsigned long lasttime; |
1055 | struct hlist_node hash_entry; | 1055 | struct hlist_node hash_entry; |
1056 | struct rcu_head rcu; | 1056 | struct rcu_head rcu; |
1057 | struct kref refcount; | 1057 | struct kref refcount; |
1058 | }; | 1058 | }; |
1059 | #endif | 1059 | #endif |
1060 | 1060 | ||
1061 | /** | 1061 | /** |
1062 | * struct batadv_tt_common_entry - tt local & tt global common data | 1062 | * struct batadv_tt_common_entry - tt local & tt global common data |
1063 | * @addr: mac address of non-mesh client | 1063 | * @addr: mac address of non-mesh client |
1064 | * @vid: VLAN identifier | 1064 | * @vid: VLAN identifier |
1065 | * @hash_entry: hlist node for batadv_priv_tt::local_hash or for | 1065 | * @hash_entry: hlist node for batadv_priv_tt::local_hash or for |
1066 | * batadv_priv_tt::global_hash | 1066 | * batadv_priv_tt::global_hash |
1067 | * @flags: various state handling flags (see batadv_tt_client_flags) | 1067 | * @flags: various state handling flags (see batadv_tt_client_flags) |
1068 | * @added_at: timestamp used for purging stale tt common entries | 1068 | * @added_at: timestamp used for purging stale tt common entries |
1069 | * @refcount: number of contexts the object is used | 1069 | * @refcount: number of contexts the object is used |
1070 | * @rcu: struct used for freeing in an RCU-safe manner | 1070 | * @rcu: struct used for freeing in an RCU-safe manner |
1071 | */ | 1071 | */ |
1072 | struct batadv_tt_common_entry { | 1072 | struct batadv_tt_common_entry { |
1073 | u8 addr[ETH_ALEN]; | 1073 | u8 addr[ETH_ALEN]; |
1074 | unsigned short vid; | 1074 | unsigned short vid; |
1075 | struct hlist_node hash_entry; | 1075 | struct hlist_node hash_entry; |
1076 | u16 flags; | 1076 | u16 flags; |
1077 | unsigned long added_at; | 1077 | unsigned long added_at; |
1078 | struct kref refcount; | 1078 | struct kref refcount; |
1079 | struct rcu_head rcu; | 1079 | struct rcu_head rcu; |
1080 | }; | 1080 | }; |
1081 | 1081 | ||
1082 | /** | 1082 | /** |
1083 | * struct batadv_tt_local_entry - translation table local entry data | 1083 | * struct batadv_tt_local_entry - translation table local entry data |
1084 | * @common: general translation table data | 1084 | * @common: general translation table data |
1085 | * @last_seen: timestamp used for purging stale tt local entries | 1085 | * @last_seen: timestamp used for purging stale tt local entries |
1086 | * @vlan: soft-interface vlan of the entry | 1086 | * @vlan: soft-interface vlan of the entry |
1087 | */ | 1087 | */ |
1088 | struct batadv_tt_local_entry { | 1088 | struct batadv_tt_local_entry { |
1089 | struct batadv_tt_common_entry common; | 1089 | struct batadv_tt_common_entry common; |
1090 | unsigned long last_seen; | 1090 | unsigned long last_seen; |
1091 | struct batadv_softif_vlan *vlan; | 1091 | struct batadv_softif_vlan *vlan; |
1092 | }; | 1092 | }; |
1093 | 1093 | ||
1094 | /** | 1094 | /** |
1095 | * struct batadv_tt_global_entry - translation table global entry data | 1095 | * struct batadv_tt_global_entry - translation table global entry data |
1096 | * @common: general translation table data | 1096 | * @common: general translation table data |
1097 | * @orig_list: list of orig nodes announcing this non-mesh client | 1097 | * @orig_list: list of orig nodes announcing this non-mesh client |
1098 | * @orig_list_count: number of items in the orig_list | 1098 | * @orig_list_count: number of items in the orig_list |
1099 | * @list_lock: lock protecting orig_list | 1099 | * @list_lock: lock protecting orig_list |
1100 | * @roam_at: time at which TT_GLOBAL_ROAM was set | 1100 | * @roam_at: time at which TT_GLOBAL_ROAM was set |
1101 | */ | 1101 | */ |
1102 | struct batadv_tt_global_entry { | 1102 | struct batadv_tt_global_entry { |
1103 | struct batadv_tt_common_entry common; | 1103 | struct batadv_tt_common_entry common; |
1104 | struct hlist_head orig_list; | 1104 | struct hlist_head orig_list; |
1105 | atomic_t orig_list_count; | 1105 | atomic_t orig_list_count; |
1106 | spinlock_t list_lock; /* protects orig_list */ | 1106 | spinlock_t list_lock; /* protects orig_list */ |
1107 | unsigned long roam_at; | 1107 | unsigned long roam_at; |
1108 | }; | 1108 | }; |
1109 | 1109 | ||
1110 | /** | 1110 | /** |
1111 | * struct batadv_tt_orig_list_entry - orig node announcing a non-mesh client | 1111 | * struct batadv_tt_orig_list_entry - orig node announcing a non-mesh client |
1112 | * @orig_node: pointer to orig node announcing this non-mesh client | 1112 | * @orig_node: pointer to orig node announcing this non-mesh client |
1113 | * @ttvn: translation table version number which added the non-mesh client | 1113 | * @ttvn: translation table version number which added the non-mesh client |
1114 | * @list: list node for batadv_tt_global_entry::orig_list | 1114 | * @list: list node for batadv_tt_global_entry::orig_list |
1115 | * @refcount: number of contexts the object is used | 1115 | * @refcount: number of contexts the object is used |
1116 | * @rcu: struct used for freeing in an RCU-safe manner | 1116 | * @rcu: struct used for freeing in an RCU-safe manner |
1117 | */ | 1117 | */ |
1118 | struct batadv_tt_orig_list_entry { | 1118 | struct batadv_tt_orig_list_entry { |
1119 | struct batadv_orig_node *orig_node; | 1119 | struct batadv_orig_node *orig_node; |
1120 | u8 ttvn; | 1120 | u8 ttvn; |
1121 | struct hlist_node list; | 1121 | struct hlist_node list; |
1122 | struct kref refcount; | 1122 | struct kref refcount; |
1123 | struct rcu_head rcu; | 1123 | struct rcu_head rcu; |
1124 | }; | 1124 | }; |
1125 | 1125 | ||
1126 | /** | 1126 | /** |
1127 | * struct batadv_tt_change_node - structure for tt changes occurred | 1127 | * struct batadv_tt_change_node - structure for tt changes occurred |
1128 | * @list: list node for batadv_priv_tt::changes_list | 1128 | * @list: list node for batadv_priv_tt::changes_list |
1129 | * @change: holds the actual translation table diff data | 1129 | * @change: holds the actual translation table diff data |
1130 | */ | 1130 | */ |
1131 | struct batadv_tt_change_node { | 1131 | struct batadv_tt_change_node { |
1132 | struct list_head list; | 1132 | struct list_head list; |
1133 | struct batadv_tvlv_tt_change change; | 1133 | struct batadv_tvlv_tt_change change; |
1134 | }; | 1134 | }; |
1135 | 1135 | ||
1136 | /** | 1136 | /** |
1137 | * struct batadv_tt_req_node - data to keep track of the tt requests in flight | 1137 | * struct batadv_tt_req_node - data to keep track of the tt requests in flight |
1138 | * @addr: mac address address of the originator this request was sent to | 1138 | * @addr: mac address address of the originator this request was sent to |
1139 | * @issued_at: timestamp used for purging stale tt requests | 1139 | * @issued_at: timestamp used for purging stale tt requests |
1140 | * @list: list node for batadv_priv_tt::req_list | 1140 | * @list: list node for batadv_priv_tt::req_list |
1141 | */ | 1141 | */ |
1142 | struct batadv_tt_req_node { | 1142 | struct batadv_tt_req_node { |
1143 | u8 addr[ETH_ALEN]; | 1143 | u8 addr[ETH_ALEN]; |
1144 | unsigned long issued_at; | 1144 | unsigned long issued_at; |
1145 | struct hlist_node list; | 1145 | struct hlist_node list; |
1146 | }; | 1146 | }; |
1147 | 1147 | ||
1148 | /** | 1148 | /** |
1149 | * struct batadv_tt_roam_node - roaming client data | 1149 | * struct batadv_tt_roam_node - roaming client data |
1150 | * @addr: mac address of the client in the roaming phase | 1150 | * @addr: mac address of the client in the roaming phase |
1151 | * @counter: number of allowed roaming events per client within a single | 1151 | * @counter: number of allowed roaming events per client within a single |
1152 | * OGM interval (changes are committed with each OGM) | 1152 | * OGM interval (changes are committed with each OGM) |
1153 | * @first_time: timestamp used for purging stale roaming node entries | 1153 | * @first_time: timestamp used for purging stale roaming node entries |
1154 | * @list: list node for batadv_priv_tt::roam_list | 1154 | * @list: list node for batadv_priv_tt::roam_list |
1155 | */ | 1155 | */ |
1156 | struct batadv_tt_roam_node { | 1156 | struct batadv_tt_roam_node { |
1157 | u8 addr[ETH_ALEN]; | 1157 | u8 addr[ETH_ALEN]; |
1158 | atomic_t counter; | 1158 | atomic_t counter; |
1159 | unsigned long first_time; | 1159 | unsigned long first_time; |
1160 | struct list_head list; | 1160 | struct list_head list; |
1161 | }; | 1161 | }; |
1162 | 1162 | ||
1163 | /** | 1163 | /** |
1164 | * struct batadv_nc_node - network coding node | 1164 | * struct batadv_nc_node - network coding node |
1165 | * @list: next and prev pointer for the list handling | 1165 | * @list: next and prev pointer for the list handling |
1166 | * @addr: the node's mac address | 1166 | * @addr: the node's mac address |
1167 | * @refcount: number of contexts the object is used by | 1167 | * @refcount: number of contexts the object is used by |
1168 | * @rcu: struct used for freeing in an RCU-safe manner | 1168 | * @rcu: struct used for freeing in an RCU-safe manner |
1169 | * @orig_node: pointer to corresponding orig node struct | 1169 | * @orig_node: pointer to corresponding orig node struct |
1170 | * @last_seen: timestamp of last ogm received from this node | 1170 | * @last_seen: timestamp of last ogm received from this node |
1171 | */ | 1171 | */ |
1172 | struct batadv_nc_node { | 1172 | struct batadv_nc_node { |
1173 | struct list_head list; | 1173 | struct list_head list; |
1174 | u8 addr[ETH_ALEN]; | 1174 | u8 addr[ETH_ALEN]; |
1175 | struct kref refcount; | 1175 | struct kref refcount; |
1176 | struct rcu_head rcu; | 1176 | struct rcu_head rcu; |
1177 | struct batadv_orig_node *orig_node; | 1177 | struct batadv_orig_node *orig_node; |
1178 | unsigned long last_seen; | 1178 | unsigned long last_seen; |
1179 | }; | 1179 | }; |
1180 | 1180 | ||
1181 | /** | 1181 | /** |
1182 | * struct batadv_nc_path - network coding path | 1182 | * struct batadv_nc_path - network coding path |
1183 | * @hash_entry: next and prev pointer for the list handling | 1183 | * @hash_entry: next and prev pointer for the list handling |
1184 | * @rcu: struct used for freeing in an RCU-safe manner | 1184 | * @rcu: struct used for freeing in an RCU-safe manner |
1185 | * @refcount: number of contexts the object is used by | 1185 | * @refcount: number of contexts the object is used by |
1186 | * @packet_list: list of buffered packets for this path | 1186 | * @packet_list: list of buffered packets for this path |
1187 | * @packet_list_lock: access lock for packet list | 1187 | * @packet_list_lock: access lock for packet list |
1188 | * @next_hop: next hop (destination) of path | 1188 | * @next_hop: next hop (destination) of path |
1189 | * @prev_hop: previous hop (source) of path | 1189 | * @prev_hop: previous hop (source) of path |
1190 | * @last_valid: timestamp for last validation of path | 1190 | * @last_valid: timestamp for last validation of path |
1191 | */ | 1191 | */ |
1192 | struct batadv_nc_path { | 1192 | struct batadv_nc_path { |
1193 | struct hlist_node hash_entry; | 1193 | struct hlist_node hash_entry; |
1194 | struct rcu_head rcu; | 1194 | struct rcu_head rcu; |
1195 | struct kref refcount; | 1195 | struct kref refcount; |
1196 | struct list_head packet_list; | 1196 | struct list_head packet_list; |
1197 | spinlock_t packet_list_lock; /* Protects packet_list */ | 1197 | spinlock_t packet_list_lock; /* Protects packet_list */ |
1198 | u8 next_hop[ETH_ALEN]; | 1198 | u8 next_hop[ETH_ALEN]; |
1199 | u8 prev_hop[ETH_ALEN]; | 1199 | u8 prev_hop[ETH_ALEN]; |
1200 | unsigned long last_valid; | 1200 | unsigned long last_valid; |
1201 | }; | 1201 | }; |
1202 | 1202 | ||
1203 | /** | 1203 | /** |
1204 | * struct batadv_nc_packet - network coding packet used when coding and | 1204 | * struct batadv_nc_packet - network coding packet used when coding and |
1205 | * decoding packets | 1205 | * decoding packets |
1206 | * @list: next and prev pointer for the list handling | 1206 | * @list: next and prev pointer for the list handling |
1207 | * @packet_id: crc32 checksum of skb data | 1207 | * @packet_id: crc32 checksum of skb data |
1208 | * @timestamp: field containing the info when the packet was added to path | 1208 | * @timestamp: field containing the info when the packet was added to path |
1209 | * @neigh_node: pointer to original next hop neighbor of skb | 1209 | * @neigh_node: pointer to original next hop neighbor of skb |
1210 | * @skb: skb which can be encoded or used for decoding | 1210 | * @skb: skb which can be encoded or used for decoding |
1211 | * @nc_path: pointer to path this nc packet is attached to | 1211 | * @nc_path: pointer to path this nc packet is attached to |
1212 | */ | 1212 | */ |
1213 | struct batadv_nc_packet { | 1213 | struct batadv_nc_packet { |
1214 | struct list_head list; | 1214 | struct list_head list; |
1215 | __be32 packet_id; | 1215 | __be32 packet_id; |
1216 | unsigned long timestamp; | 1216 | unsigned long timestamp; |
1217 | struct batadv_neigh_node *neigh_node; | 1217 | struct batadv_neigh_node *neigh_node; |
1218 | struct sk_buff *skb; | 1218 | struct sk_buff *skb; |
1219 | struct batadv_nc_path *nc_path; | 1219 | struct batadv_nc_path *nc_path; |
1220 | }; | 1220 | }; |
1221 | 1221 | ||
1222 | /** | 1222 | /** |
1223 | * struct batadv_skb_cb - control buffer structure used to store private data | 1223 | * struct batadv_skb_cb - control buffer structure used to store private data |
1224 | * relevant to batman-adv in the skb->cb buffer in skbs. | 1224 | * relevant to batman-adv in the skb->cb buffer in skbs. |
1225 | * @decoded: Marks a skb as decoded, which is checked when searching for coding | 1225 | * @decoded: Marks a skb as decoded, which is checked when searching for coding |
1226 | * opportunities in network-coding.c | 1226 | * opportunities in network-coding.c |
1227 | */ | 1227 | */ |
1228 | struct batadv_skb_cb { | 1228 | struct batadv_skb_cb { |
1229 | bool decoded; | 1229 | bool decoded; |
1230 | }; | 1230 | }; |
1231 | 1231 | ||
1232 | /** | 1232 | /** |
1233 | * struct batadv_forw_packet - structure for bcast packets to be sent/forwarded | 1233 | * struct batadv_forw_packet - structure for bcast packets to be sent/forwarded |
1234 | * @list: list node for batadv_socket_client::queue_list | 1234 | * @list: list node for batadv_socket_client::queue_list |
1235 | * @send_time: execution time for delayed_work (packet sending) | 1235 | * @send_time: execution time for delayed_work (packet sending) |
1236 | * @own: bool for locally generated packets (local OGMs are re-scheduled after | 1236 | * @own: bool for locally generated packets (local OGMs are re-scheduled after |
1237 | * sending) | 1237 | * sending) |
1238 | * @skb: bcast packet's skb buffer | 1238 | * @skb: bcast packet's skb buffer |
1239 | * @packet_len: size of aggregated OGM packet inside the skb buffer | 1239 | * @packet_len: size of aggregated OGM packet inside the skb buffer |
1240 | * @direct_link_flags: direct link flags for aggregated OGM packets | 1240 | * @direct_link_flags: direct link flags for aggregated OGM packets |
1241 | * @num_packets: counter for bcast packet retransmission | 1241 | * @num_packets: counter for bcast packet retransmission |
1242 | * @delayed_work: work queue callback item for packet sending | 1242 | * @delayed_work: work queue callback item for packet sending |
1243 | * @if_incoming: pointer to incoming hard-iface or primary iface if | 1243 | * @if_incoming: pointer to incoming hard-iface or primary iface if |
1244 | * locally generated packet | 1244 | * locally generated packet |
1245 | * @if_outgoing: packet where the packet should be sent to, or NULL if | 1245 | * @if_outgoing: packet where the packet should be sent to, or NULL if |
1246 | * unspecified | 1246 | * unspecified |
1247 | */ | 1247 | */ |
1248 | struct batadv_forw_packet { | 1248 | struct batadv_forw_packet { |
1249 | struct hlist_node list; | 1249 | struct hlist_node list; |
1250 | unsigned long send_time; | 1250 | unsigned long send_time; |
1251 | u8 own; | 1251 | u8 own; |
1252 | struct sk_buff *skb; | 1252 | struct sk_buff *skb; |
1253 | u16 packet_len; | 1253 | u16 packet_len; |
1254 | u32 direct_link_flags; | 1254 | u32 direct_link_flags; |
1255 | u8 num_packets; | 1255 | u8 num_packets; |
1256 | struct delayed_work delayed_work; | 1256 | struct delayed_work delayed_work; |
1257 | struct batadv_hard_iface *if_incoming; | 1257 | struct batadv_hard_iface *if_incoming; |
1258 | struct batadv_hard_iface *if_outgoing; | 1258 | struct batadv_hard_iface *if_outgoing; |
1259 | }; | 1259 | }; |
1260 | 1260 | ||
1261 | /** | 1261 | /** |
1262 | * struct batadv_algo_ops - mesh algorithm callbacks | 1262 | * struct batadv_algo_ops - mesh algorithm callbacks |
1263 | * @list: list node for the batadv_algo_list | 1263 | * @list: list node for the batadv_algo_list |
1264 | * @name: name of the algorithm | 1264 | * @name: name of the algorithm |
1265 | * @bat_iface_activate: start routing mechanisms when hard-interface is brought | 1265 | * @bat_iface_activate: start routing mechanisms when hard-interface is brought |
1266 | * up | 1266 | * up |
1267 | * @bat_iface_enable: init routing info when hard-interface is enabled | 1267 | * @bat_iface_enable: init routing info when hard-interface is enabled |
1268 | * @bat_iface_disable: de-init routing info when hard-interface is disabled | 1268 | * @bat_iface_disable: de-init routing info when hard-interface is disabled |
1269 | * @bat_iface_update_mac: (re-)init mac addresses of the protocol information | 1269 | * @bat_iface_update_mac: (re-)init mac addresses of the protocol information |
1270 | * belonging to this hard-interface | 1270 | * belonging to this hard-interface |
1271 | * @bat_primary_iface_set: called when primary interface is selected / changed | 1271 | * @bat_primary_iface_set: called when primary interface is selected / changed |
1272 | * @bat_hardif_neigh_init: called on creation of single hop entry | 1272 | * @bat_hardif_neigh_init: called on creation of single hop entry |
1273 | * @bat_neigh_cmp: compare the metrics of two neighbors for their respective | 1273 | * @bat_neigh_cmp: compare the metrics of two neighbors for their respective |
1274 | * outgoing interfaces | 1274 | * outgoing interfaces |
1275 | * @bat_neigh_is_similar_or_better: check if neigh1 is equally similar or | 1275 | * @bat_neigh_is_similar_or_better: check if neigh1 is equally similar or |
1276 | * better than neigh2 for their respective outgoing interface from the metric | 1276 | * better than neigh2 for their respective outgoing interface from the metric |
1277 | * prospective | 1277 | * prospective |
1278 | * @bat_neigh_print: print the single hop neighbor list (optional) | 1278 | * @bat_neigh_print: print the single hop neighbor list (optional) |
1279 | * @bat_orig_print: print the originator table (optional) | 1279 | * @bat_orig_print: print the originator table (optional) |
1280 | * @bat_orig_free: free the resources allocated by the routing algorithm for an | 1280 | * @bat_orig_free: free the resources allocated by the routing algorithm for an |
1281 | * orig_node object | 1281 | * orig_node object |
1282 | * @bat_orig_add_if: ask the routing algorithm to apply the needed changes to | 1282 | * @bat_orig_add_if: ask the routing algorithm to apply the needed changes to |
1283 | * the orig_node due to a new hard-interface being added into the mesh | 1283 | * the orig_node due to a new hard-interface being added into the mesh |
1284 | * @bat_orig_del_if: ask the routing algorithm to apply the needed changes to | 1284 | * @bat_orig_del_if: ask the routing algorithm to apply the needed changes to |
1285 | * the orig_node due to an hard-interface being removed from the mesh | 1285 | * the orig_node due to an hard-interface being removed from the mesh |
1286 | */ | 1286 | */ |
1287 | struct batadv_algo_ops { | 1287 | struct batadv_algo_ops { |
1288 | struct hlist_node list; | 1288 | struct hlist_node list; |
1289 | char *name; | 1289 | char *name; |
1290 | void (*bat_iface_activate)(struct batadv_hard_iface *hard_iface); | 1290 | void (*bat_iface_activate)(struct batadv_hard_iface *hard_iface); |
1291 | int (*bat_iface_enable)(struct batadv_hard_iface *hard_iface); | 1291 | int (*bat_iface_enable)(struct batadv_hard_iface *hard_iface); |
1292 | void (*bat_iface_disable)(struct batadv_hard_iface *hard_iface); | 1292 | void (*bat_iface_disable)(struct batadv_hard_iface *hard_iface); |
1293 | void (*bat_iface_update_mac)(struct batadv_hard_iface *hard_iface); | 1293 | void (*bat_iface_update_mac)(struct batadv_hard_iface *hard_iface); |
1294 | void (*bat_primary_iface_set)(struct batadv_hard_iface *hard_iface); | 1294 | void (*bat_primary_iface_set)(struct batadv_hard_iface *hard_iface); |
1295 | /* neigh_node handling API */ | 1295 | /* neigh_node handling API */ |
1296 | void (*bat_hardif_neigh_init)(struct batadv_hardif_neigh_node *neigh); | 1296 | void (*bat_hardif_neigh_init)(struct batadv_hardif_neigh_node *neigh); |
1297 | int (*bat_neigh_cmp)(struct batadv_neigh_node *neigh1, | 1297 | int (*bat_neigh_cmp)(struct batadv_neigh_node *neigh1, |
1298 | struct batadv_hard_iface *if_outgoing1, | 1298 | struct batadv_hard_iface *if_outgoing1, |
1299 | struct batadv_neigh_node *neigh2, | 1299 | struct batadv_neigh_node *neigh2, |
1300 | struct batadv_hard_iface *if_outgoing2); | 1300 | struct batadv_hard_iface *if_outgoing2); |
1301 | bool (*bat_neigh_is_similar_or_better) | 1301 | bool (*bat_neigh_is_similar_or_better) |
1302 | (struct batadv_neigh_node *neigh1, | 1302 | (struct batadv_neigh_node *neigh1, |
1303 | struct batadv_hard_iface *if_outgoing1, | 1303 | struct batadv_hard_iface *if_outgoing1, |
1304 | struct batadv_neigh_node *neigh2, | 1304 | struct batadv_neigh_node *neigh2, |
1305 | struct batadv_hard_iface *if_outgoing2); | 1305 | struct batadv_hard_iface *if_outgoing2); |
1306 | void (*bat_neigh_print)(struct batadv_priv *priv, struct seq_file *seq); | 1306 | void (*bat_neigh_print)(struct batadv_priv *priv, struct seq_file *seq); |
1307 | /* orig_node handling API */ | 1307 | /* orig_node handling API */ |
1308 | void (*bat_orig_print)(struct batadv_priv *priv, struct seq_file *seq, | 1308 | void (*bat_orig_print)(struct batadv_priv *priv, struct seq_file *seq, |
1309 | struct batadv_hard_iface *hard_iface); | 1309 | struct batadv_hard_iface *hard_iface); |
1310 | void (*bat_orig_free)(struct batadv_orig_node *orig_node); | 1310 | void (*bat_orig_free)(struct batadv_orig_node *orig_node); |
1311 | int (*bat_orig_add_if)(struct batadv_orig_node *orig_node, | 1311 | int (*bat_orig_add_if)(struct batadv_orig_node *orig_node, |
1312 | int max_if_num); | 1312 | int max_if_num); |
1313 | int (*bat_orig_del_if)(struct batadv_orig_node *orig_node, | 1313 | int (*bat_orig_del_if)(struct batadv_orig_node *orig_node, |
1314 | int max_if_num, int del_if_num); | 1314 | int max_if_num, int del_if_num); |
1315 | }; | 1315 | }; |
1316 | 1316 | ||
1317 | /** | 1317 | /** |
1318 | * struct batadv_dat_entry - it is a single entry of batman-adv ARP backend. It | 1318 | * struct batadv_dat_entry - it is a single entry of batman-adv ARP backend. It |
1319 | * is used to stored ARP entries needed for the global DAT cache | 1319 | * is used to stored ARP entries needed for the global DAT cache |
1320 | * @ip: the IPv4 corresponding to this DAT/ARP entry | 1320 | * @ip: the IPv4 corresponding to this DAT/ARP entry |
1321 | * @mac_addr: the MAC address associated to the stored IPv4 | 1321 | * @mac_addr: the MAC address associated to the stored IPv4 |
1322 | * @vid: the vlan ID associated to this entry | 1322 | * @vid: the vlan ID associated to this entry |
1323 | * @last_update: time in jiffies when this entry was refreshed last time | 1323 | * @last_update: time in jiffies when this entry was refreshed last time |
1324 | * @hash_entry: hlist node for batadv_priv_dat::hash | 1324 | * @hash_entry: hlist node for batadv_priv_dat::hash |
1325 | * @refcount: number of contexts the object is used | 1325 | * @refcount: number of contexts the object is used |
1326 | * @rcu: struct used for freeing in an RCU-safe manner | 1326 | * @rcu: struct used for freeing in an RCU-safe manner |
1327 | */ | 1327 | */ |
1328 | struct batadv_dat_entry { | 1328 | struct batadv_dat_entry { |
1329 | __be32 ip; | 1329 | __be32 ip; |
1330 | u8 mac_addr[ETH_ALEN]; | 1330 | u8 mac_addr[ETH_ALEN]; |
1331 | unsigned short vid; | 1331 | unsigned short vid; |
1332 | unsigned long last_update; | 1332 | unsigned long last_update; |
1333 | struct hlist_node hash_entry; | 1333 | struct hlist_node hash_entry; |
1334 | struct kref refcount; | 1334 | struct kref refcount; |
1335 | struct rcu_head rcu; | 1335 | struct rcu_head rcu; |
1336 | }; | 1336 | }; |
1337 | 1337 | ||
1338 | /** | 1338 | /** |
1339 | * struct batadv_hw_addr - a list entry for a MAC address | 1339 | * struct batadv_hw_addr - a list entry for a MAC address |
1340 | * @list: list node for the linking of entries | 1340 | * @list: list node for the linking of entries |
1341 | * @addr: the MAC address of this list entry | 1341 | * @addr: the MAC address of this list entry |
1342 | */ | 1342 | */ |
1343 | struct batadv_hw_addr { | 1343 | struct batadv_hw_addr { |
1344 | struct hlist_node list; | 1344 | struct hlist_node list; |
1345 | unsigned char addr[ETH_ALEN]; | 1345 | unsigned char addr[ETH_ALEN]; |
1346 | }; | 1346 | }; |
1347 | 1347 | ||
1348 | /** | 1348 | /** |
1349 | * struct batadv_dat_candidate - candidate destination for DAT operations | 1349 | * struct batadv_dat_candidate - candidate destination for DAT operations |
1350 | * @type: the type of the selected candidate. It can one of the following: | 1350 | * @type: the type of the selected candidate. It can one of the following: |
1351 | * - BATADV_DAT_CANDIDATE_NOT_FOUND | 1351 | * - BATADV_DAT_CANDIDATE_NOT_FOUND |
1352 | * - BATADV_DAT_CANDIDATE_ORIG | 1352 | * - BATADV_DAT_CANDIDATE_ORIG |
1353 | * @orig_node: if type is BATADV_DAT_CANDIDATE_ORIG this field points to the | 1353 | * @orig_node: if type is BATADV_DAT_CANDIDATE_ORIG this field points to the |
1354 | * corresponding originator node structure | 1354 | * corresponding originator node structure |
1355 | */ | 1355 | */ |
1356 | struct batadv_dat_candidate { | 1356 | struct batadv_dat_candidate { |
1357 | int type; | 1357 | int type; |
1358 | struct batadv_orig_node *orig_node; | 1358 | struct batadv_orig_node *orig_node; |
1359 | }; | 1359 | }; |
1360 | 1360 | ||
1361 | /** | 1361 | /** |
1362 | * struct batadv_tvlv_container - container for tvlv appended to OGMs | 1362 | * struct batadv_tvlv_container - container for tvlv appended to OGMs |
1363 | * @list: hlist node for batadv_priv_tvlv::container_list | 1363 | * @list: hlist node for batadv_priv_tvlv::container_list |
1364 | * @tvlv_hdr: tvlv header information needed to construct the tvlv | 1364 | * @tvlv_hdr: tvlv header information needed to construct the tvlv |
1365 | * @refcount: number of contexts the object is used | 1365 | * @refcount: number of contexts the object is used |
1366 | */ | 1366 | */ |
1367 | struct batadv_tvlv_container { | 1367 | struct batadv_tvlv_container { |
1368 | struct hlist_node list; | 1368 | struct hlist_node list; |
1369 | struct batadv_tvlv_hdr tvlv_hdr; | 1369 | struct batadv_tvlv_hdr tvlv_hdr; |
1370 | struct kref refcount; | 1370 | struct kref refcount; |
1371 | }; | 1371 | }; |
1372 | 1372 | ||
1373 | /** | 1373 | /** |
1374 | * struct batadv_tvlv_handler - handler for specific tvlv type and version | 1374 | * struct batadv_tvlv_handler - handler for specific tvlv type and version |
1375 | * @list: hlist node for batadv_priv_tvlv::handler_list | 1375 | * @list: hlist node for batadv_priv_tvlv::handler_list |
1376 | * @ogm_handler: handler callback which is given the tvlv payload to process on | 1376 | * @ogm_handler: handler callback which is given the tvlv payload to process on |
1377 | * incoming OGM packets | 1377 | * incoming OGM packets |
1378 | * @unicast_handler: handler callback which is given the tvlv payload to process | 1378 | * @unicast_handler: handler callback which is given the tvlv payload to process |
1379 | * on incoming unicast tvlv packets | 1379 | * on incoming unicast tvlv packets |
1380 | * @type: tvlv type this handler feels responsible for | 1380 | * @type: tvlv type this handler feels responsible for |
1381 | * @version: tvlv version this handler feels responsible for | 1381 | * @version: tvlv version this handler feels responsible for |
1382 | * @flags: tvlv handler flags | 1382 | * @flags: tvlv handler flags |
1383 | * @refcount: number of contexts the object is used | 1383 | * @refcount: number of contexts the object is used |
1384 | * @rcu: struct used for freeing in an RCU-safe manner | 1384 | * @rcu: struct used for freeing in an RCU-safe manner |
1385 | */ | 1385 | */ |
1386 | struct batadv_tvlv_handler { | 1386 | struct batadv_tvlv_handler { |
1387 | struct hlist_node list; | 1387 | struct hlist_node list; |
1388 | void (*ogm_handler)(struct batadv_priv *bat_priv, | 1388 | void (*ogm_handler)(struct batadv_priv *bat_priv, |
1389 | struct batadv_orig_node *orig, | 1389 | struct batadv_orig_node *orig, |
1390 | u8 flags, void *tvlv_value, u16 tvlv_value_len); | 1390 | u8 flags, void *tvlv_value, u16 tvlv_value_len); |
1391 | int (*unicast_handler)(struct batadv_priv *bat_priv, | 1391 | int (*unicast_handler)(struct batadv_priv *bat_priv, |
1392 | u8 *src, u8 *dst, | 1392 | u8 *src, u8 *dst, |
1393 | void *tvlv_value, u16 tvlv_value_len); | 1393 | void *tvlv_value, u16 tvlv_value_len); |
1394 | u8 type; | 1394 | u8 type; |
1395 | u8 version; | 1395 | u8 version; |
1396 | u8 flags; | 1396 | u8 flags; |
1397 | struct kref refcount; | 1397 | struct kref refcount; |
1398 | struct rcu_head rcu; | 1398 | struct rcu_head rcu; |
1399 | }; | 1399 | }; |
1400 | 1400 | ||
1401 | /** | 1401 | /** |
1402 | * enum batadv_tvlv_handler_flags - tvlv handler flags definitions | 1402 | * enum batadv_tvlv_handler_flags - tvlv handler flags definitions |
1403 | * @BATADV_TVLV_HANDLER_OGM_CIFNOTFND: tvlv ogm processing function will call | 1403 | * @BATADV_TVLV_HANDLER_OGM_CIFNOTFND: tvlv ogm processing function will call |
1404 | * this handler even if its type was not found (with no data) | 1404 | * this handler even if its type was not found (with no data) |
1405 | * @BATADV_TVLV_HANDLER_OGM_CALLED: interval tvlv handling flag - the API marks | 1405 | * @BATADV_TVLV_HANDLER_OGM_CALLED: interval tvlv handling flag - the API marks |
1406 | * a handler as being called, so it won't be called if the | 1406 | * a handler as being called, so it won't be called if the |
1407 | * BATADV_TVLV_HANDLER_OGM_CIFNOTFND flag was set | 1407 | * BATADV_TVLV_HANDLER_OGM_CIFNOTFND flag was set |
1408 | */ | 1408 | */ |
1409 | enum batadv_tvlv_handler_flags { | 1409 | enum batadv_tvlv_handler_flags { |
1410 | BATADV_TVLV_HANDLER_OGM_CIFNOTFND = BIT(1), | 1410 | BATADV_TVLV_HANDLER_OGM_CIFNOTFND = BIT(1), |
1411 | BATADV_TVLV_HANDLER_OGM_CALLED = BIT(2), | 1411 | BATADV_TVLV_HANDLER_OGM_CALLED = BIT(2), |