diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-05-20 16:43:21 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-05-20 16:43:21 -0400 |
commit | 06f4e926d256d902dd9a53dcb400fd74974ce087 (patch) | |
tree | 0b438b67f5f0eff6fd617bc497a9dace6164a488 /net/batman-adv/soft-interface.c | |
parent | 8e7bfcbab3825d1b404d615cb1b54f44ff81f981 (diff) | |
parent | d93515611bbc70c2fe4db232e5feb448ed8e4cc9 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6: (1446 commits)
macvlan: fix panic if lowerdev in a bond
tg3: Add braces around 5906 workaround.
tg3: Fix NETIF_F_LOOPBACK error
macvlan: remove one synchronize_rcu() call
networking: NET_CLS_ROUTE4 depends on INET
irda: Fix error propagation in ircomm_lmp_connect_response()
irda: Kill set but unused variable 'bytes' in irlan_check_command_param()
irda: Kill set but unused variable 'clen' in ircomm_connect_indication()
rxrpc: Fix set but unused variable 'usage' in rxrpc_get_transport()
be2net: Kill set but unused variable 'req' in lancer_fw_download()
irda: Kill set but unused vars 'saddr' and 'daddr' in irlan_provider_connect_indication()
atl1c: atl1c_resume() is only used when CONFIG_PM_SLEEP is defined.
rxrpc: Fix set but unused variable 'usage' in rxrpc_get_peer().
rxrpc: Kill set but unused variable 'local' in rxrpc_UDP_error_handler()
rxrpc: Kill set but unused variable 'sp' in rxrpc_process_connection()
rxrpc: Kill set but unused variable 'sp' in rxrpc_rotate_tx_window()
pkt_sched: Kill set but unused variable 'protocol' in tc_classify()
isdn: capi: Use pr_debug() instead of ifdefs.
tg3: Update version to 3.119
tg3: Apply rx_discards fix to 5719/5720
...
Fix up trivial conflicts in arch/x86/Kconfig and net/mac80211/agg-tx.c
as per Davem.
Diffstat (limited to 'net/batman-adv/soft-interface.c')
-rw-r--r-- | net/batman-adv/soft-interface.c | 463 |
1 files changed, 356 insertions, 107 deletions
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index 04efe022c13b..d5aa60999e83 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c | |||
@@ -43,8 +43,6 @@ static void bat_get_drvinfo(struct net_device *dev, | |||
43 | static u32 bat_get_msglevel(struct net_device *dev); | 43 | static u32 bat_get_msglevel(struct net_device *dev); |
44 | static void bat_set_msglevel(struct net_device *dev, u32 value); | 44 | static void bat_set_msglevel(struct net_device *dev, u32 value); |
45 | static u32 bat_get_link(struct net_device *dev); | 45 | static u32 bat_get_link(struct net_device *dev); |
46 | static u32 bat_get_rx_csum(struct net_device *dev); | ||
47 | static int bat_set_rx_csum(struct net_device *dev, u32 data); | ||
48 | 46 | ||
49 | static const struct ethtool_ops bat_ethtool_ops = { | 47 | static const struct ethtool_ops bat_ethtool_ops = { |
50 | .get_settings = bat_get_settings, | 48 | .get_settings = bat_get_settings, |
@@ -52,8 +50,6 @@ static const struct ethtool_ops bat_ethtool_ops = { | |||
52 | .get_msglevel = bat_get_msglevel, | 50 | .get_msglevel = bat_get_msglevel, |
53 | .set_msglevel = bat_set_msglevel, | 51 | .set_msglevel = bat_set_msglevel, |
54 | .get_link = bat_get_link, | 52 | .get_link = bat_get_link, |
55 | .get_rx_csum = bat_get_rx_csum, | ||
56 | .set_rx_csum = bat_set_rx_csum | ||
57 | }; | 53 | }; |
58 | 54 | ||
59 | int my_skb_head_push(struct sk_buff *skb, unsigned int len) | 55 | int my_skb_head_push(struct sk_buff *skb, unsigned int len) |
@@ -82,106 +78,365 @@ static void softif_neigh_free_ref(struct softif_neigh *softif_neigh) | |||
82 | kfree_rcu(softif_neigh, rcu); | 78 | kfree_rcu(softif_neigh, rcu); |
83 | } | 79 | } |
84 | 80 | ||
85 | void softif_neigh_purge(struct bat_priv *bat_priv) | 81 | static void softif_neigh_vid_free_rcu(struct rcu_head *rcu) |
86 | { | 82 | { |
87 | struct softif_neigh *softif_neigh, *softif_neigh_tmp; | 83 | struct softif_neigh_vid *softif_neigh_vid; |
84 | struct softif_neigh *softif_neigh; | ||
88 | struct hlist_node *node, *node_tmp; | 85 | struct hlist_node *node, *node_tmp; |
86 | struct bat_priv *bat_priv; | ||
89 | 87 | ||
90 | spin_lock_bh(&bat_priv->softif_neigh_lock); | 88 | softif_neigh_vid = container_of(rcu, struct softif_neigh_vid, rcu); |
89 | bat_priv = softif_neigh_vid->bat_priv; | ||
91 | 90 | ||
91 | spin_lock_bh(&bat_priv->softif_neigh_lock); | ||
92 | hlist_for_each_entry_safe(softif_neigh, node, node_tmp, | 92 | hlist_for_each_entry_safe(softif_neigh, node, node_tmp, |
93 | &bat_priv->softif_neigh_list, list) { | 93 | &softif_neigh_vid->softif_neigh_list, list) { |
94 | hlist_del_rcu(&softif_neigh->list); | ||
95 | softif_neigh_free_ref(softif_neigh); | ||
96 | } | ||
97 | spin_unlock_bh(&bat_priv->softif_neigh_lock); | ||
94 | 98 | ||
95 | if ((!time_after(jiffies, softif_neigh->last_seen + | 99 | kfree(softif_neigh_vid); |
96 | msecs_to_jiffies(SOFTIF_NEIGH_TIMEOUT))) && | 100 | } |
97 | (atomic_read(&bat_priv->mesh_state) == MESH_ACTIVE)) | ||
98 | continue; | ||
99 | 101 | ||
100 | hlist_del_rcu(&softif_neigh->list); | 102 | static void softif_neigh_vid_free_ref(struct softif_neigh_vid *softif_neigh_vid) |
103 | { | ||
104 | if (atomic_dec_and_test(&softif_neigh_vid->refcount)) | ||
105 | call_rcu(&softif_neigh_vid->rcu, softif_neigh_vid_free_rcu); | ||
106 | } | ||
101 | 107 | ||
102 | if (bat_priv->softif_neigh == softif_neigh) { | 108 | static struct softif_neigh_vid *softif_neigh_vid_get(struct bat_priv *bat_priv, |
103 | bat_dbg(DBG_ROUTES, bat_priv, | 109 | short vid) |
104 | "Current mesh exit point '%pM' vanished " | 110 | { |
105 | "(vid: %d).\n", | 111 | struct softif_neigh_vid *softif_neigh_vid; |
106 | softif_neigh->addr, softif_neigh->vid); | 112 | struct hlist_node *node; |
107 | softif_neigh_tmp = bat_priv->softif_neigh; | ||
108 | bat_priv->softif_neigh = NULL; | ||
109 | softif_neigh_free_ref(softif_neigh_tmp); | ||
110 | } | ||
111 | 113 | ||
112 | softif_neigh_free_ref(softif_neigh); | 114 | rcu_read_lock(); |
115 | hlist_for_each_entry_rcu(softif_neigh_vid, node, | ||
116 | &bat_priv->softif_neigh_vids, list) { | ||
117 | if (softif_neigh_vid->vid != vid) | ||
118 | continue; | ||
119 | |||
120 | if (!atomic_inc_not_zero(&softif_neigh_vid->refcount)) | ||
121 | continue; | ||
122 | |||
123 | goto out; | ||
113 | } | 124 | } |
114 | 125 | ||
115 | spin_unlock_bh(&bat_priv->softif_neigh_lock); | 126 | softif_neigh_vid = kzalloc(sizeof(struct softif_neigh_vid), |
127 | GFP_ATOMIC); | ||
128 | if (!softif_neigh_vid) | ||
129 | goto out; | ||
130 | |||
131 | softif_neigh_vid->vid = vid; | ||
132 | softif_neigh_vid->bat_priv = bat_priv; | ||
133 | |||
134 | /* initialize with 2 - caller decrements counter by one */ | ||
135 | atomic_set(&softif_neigh_vid->refcount, 2); | ||
136 | INIT_HLIST_HEAD(&softif_neigh_vid->softif_neigh_list); | ||
137 | INIT_HLIST_NODE(&softif_neigh_vid->list); | ||
138 | spin_lock_bh(&bat_priv->softif_neigh_vid_lock); | ||
139 | hlist_add_head_rcu(&softif_neigh_vid->list, | ||
140 | &bat_priv->softif_neigh_vids); | ||
141 | spin_unlock_bh(&bat_priv->softif_neigh_vid_lock); | ||
142 | |||
143 | out: | ||
144 | rcu_read_unlock(); | ||
145 | return softif_neigh_vid; | ||
116 | } | 146 | } |
117 | 147 | ||
118 | static struct softif_neigh *softif_neigh_get(struct bat_priv *bat_priv, | 148 | static struct softif_neigh *softif_neigh_get(struct bat_priv *bat_priv, |
119 | uint8_t *addr, short vid) | 149 | uint8_t *addr, short vid) |
120 | { | 150 | { |
121 | struct softif_neigh *softif_neigh; | 151 | struct softif_neigh_vid *softif_neigh_vid; |
152 | struct softif_neigh *softif_neigh = NULL; | ||
122 | struct hlist_node *node; | 153 | struct hlist_node *node; |
123 | 154 | ||
155 | softif_neigh_vid = softif_neigh_vid_get(bat_priv, vid); | ||
156 | if (!softif_neigh_vid) | ||
157 | goto out; | ||
158 | |||
124 | rcu_read_lock(); | 159 | rcu_read_lock(); |
125 | hlist_for_each_entry_rcu(softif_neigh, node, | 160 | hlist_for_each_entry_rcu(softif_neigh, node, |
126 | &bat_priv->softif_neigh_list, list) { | 161 | &softif_neigh_vid->softif_neigh_list, |
162 | list) { | ||
127 | if (!compare_eth(softif_neigh->addr, addr)) | 163 | if (!compare_eth(softif_neigh->addr, addr)) |
128 | continue; | 164 | continue; |
129 | 165 | ||
130 | if (softif_neigh->vid != vid) | ||
131 | continue; | ||
132 | |||
133 | if (!atomic_inc_not_zero(&softif_neigh->refcount)) | 166 | if (!atomic_inc_not_zero(&softif_neigh->refcount)) |
134 | continue; | 167 | continue; |
135 | 168 | ||
136 | softif_neigh->last_seen = jiffies; | 169 | softif_neigh->last_seen = jiffies; |
137 | goto out; | 170 | goto unlock; |
138 | } | 171 | } |
139 | 172 | ||
140 | softif_neigh = kzalloc(sizeof(struct softif_neigh), GFP_ATOMIC); | 173 | softif_neigh = kzalloc(sizeof(struct softif_neigh), GFP_ATOMIC); |
141 | if (!softif_neigh) | 174 | if (!softif_neigh) |
142 | goto out; | 175 | goto unlock; |
143 | 176 | ||
144 | memcpy(softif_neigh->addr, addr, ETH_ALEN); | 177 | memcpy(softif_neigh->addr, addr, ETH_ALEN); |
145 | softif_neigh->vid = vid; | ||
146 | softif_neigh->last_seen = jiffies; | 178 | softif_neigh->last_seen = jiffies; |
147 | /* initialize with 2 - caller decrements counter by one */ | 179 | /* initialize with 2 - caller decrements counter by one */ |
148 | atomic_set(&softif_neigh->refcount, 2); | 180 | atomic_set(&softif_neigh->refcount, 2); |
149 | 181 | ||
150 | INIT_HLIST_NODE(&softif_neigh->list); | 182 | INIT_HLIST_NODE(&softif_neigh->list); |
151 | spin_lock_bh(&bat_priv->softif_neigh_lock); | 183 | spin_lock_bh(&bat_priv->softif_neigh_lock); |
152 | hlist_add_head_rcu(&softif_neigh->list, &bat_priv->softif_neigh_list); | 184 | hlist_add_head_rcu(&softif_neigh->list, |
185 | &softif_neigh_vid->softif_neigh_list); | ||
153 | spin_unlock_bh(&bat_priv->softif_neigh_lock); | 186 | spin_unlock_bh(&bat_priv->softif_neigh_lock); |
154 | 187 | ||
188 | unlock: | ||
189 | rcu_read_unlock(); | ||
155 | out: | 190 | out: |
191 | if (softif_neigh_vid) | ||
192 | softif_neigh_vid_free_ref(softif_neigh_vid); | ||
193 | return softif_neigh; | ||
194 | } | ||
195 | |||
196 | static struct softif_neigh *softif_neigh_get_selected( | ||
197 | struct softif_neigh_vid *softif_neigh_vid) | ||
198 | { | ||
199 | struct softif_neigh *softif_neigh; | ||
200 | |||
201 | rcu_read_lock(); | ||
202 | softif_neigh = rcu_dereference(softif_neigh_vid->softif_neigh); | ||
203 | |||
204 | if (softif_neigh && !atomic_inc_not_zero(&softif_neigh->refcount)) | ||
205 | softif_neigh = NULL; | ||
206 | |||
156 | rcu_read_unlock(); | 207 | rcu_read_unlock(); |
157 | return softif_neigh; | 208 | return softif_neigh; |
158 | } | 209 | } |
159 | 210 | ||
211 | static struct softif_neigh *softif_neigh_vid_get_selected( | ||
212 | struct bat_priv *bat_priv, | ||
213 | short vid) | ||
214 | { | ||
215 | struct softif_neigh_vid *softif_neigh_vid; | ||
216 | struct softif_neigh *softif_neigh = NULL; | ||
217 | |||
218 | softif_neigh_vid = softif_neigh_vid_get(bat_priv, vid); | ||
219 | if (!softif_neigh_vid) | ||
220 | goto out; | ||
221 | |||
222 | softif_neigh = softif_neigh_get_selected(softif_neigh_vid); | ||
223 | out: | ||
224 | if (softif_neigh_vid) | ||
225 | softif_neigh_vid_free_ref(softif_neigh_vid); | ||
226 | return softif_neigh; | ||
227 | } | ||
228 | |||
229 | static void softif_neigh_vid_select(struct bat_priv *bat_priv, | ||
230 | struct softif_neigh *new_neigh, | ||
231 | short vid) | ||
232 | { | ||
233 | struct softif_neigh_vid *softif_neigh_vid; | ||
234 | struct softif_neigh *curr_neigh; | ||
235 | |||
236 | softif_neigh_vid = softif_neigh_vid_get(bat_priv, vid); | ||
237 | if (!softif_neigh_vid) | ||
238 | goto out; | ||
239 | |||
240 | spin_lock_bh(&bat_priv->softif_neigh_lock); | ||
241 | |||
242 | if (new_neigh && !atomic_inc_not_zero(&new_neigh->refcount)) | ||
243 | new_neigh = NULL; | ||
244 | |||
245 | curr_neigh = softif_neigh_vid->softif_neigh; | ||
246 | rcu_assign_pointer(softif_neigh_vid->softif_neigh, new_neigh); | ||
247 | |||
248 | if ((curr_neigh) && (!new_neigh)) | ||
249 | bat_dbg(DBG_ROUTES, bat_priv, | ||
250 | "Removing mesh exit point on vid: %d (prev: %pM).\n", | ||
251 | vid, curr_neigh->addr); | ||
252 | else if ((curr_neigh) && (new_neigh)) | ||
253 | bat_dbg(DBG_ROUTES, bat_priv, | ||
254 | "Changing mesh exit point on vid: %d from %pM " | ||
255 | "to %pM.\n", vid, curr_neigh->addr, new_neigh->addr); | ||
256 | else if ((!curr_neigh) && (new_neigh)) | ||
257 | bat_dbg(DBG_ROUTES, bat_priv, | ||
258 | "Setting mesh exit point on vid: %d to %pM.\n", | ||
259 | vid, new_neigh->addr); | ||
260 | |||
261 | if (curr_neigh) | ||
262 | softif_neigh_free_ref(curr_neigh); | ||
263 | |||
264 | spin_unlock_bh(&bat_priv->softif_neigh_lock); | ||
265 | |||
266 | out: | ||
267 | if (softif_neigh_vid) | ||
268 | softif_neigh_vid_free_ref(softif_neigh_vid); | ||
269 | } | ||
270 | |||
271 | static void softif_neigh_vid_deselect(struct bat_priv *bat_priv, | ||
272 | struct softif_neigh_vid *softif_neigh_vid) | ||
273 | { | ||
274 | struct softif_neigh *curr_neigh; | ||
275 | struct softif_neigh *softif_neigh = NULL, *softif_neigh_tmp; | ||
276 | struct hard_iface *primary_if = NULL; | ||
277 | struct hlist_node *node; | ||
278 | |||
279 | primary_if = primary_if_get_selected(bat_priv); | ||
280 | if (!primary_if) | ||
281 | goto out; | ||
282 | |||
283 | /* find new softif_neigh immediately to avoid temporary loops */ | ||
284 | rcu_read_lock(); | ||
285 | curr_neigh = rcu_dereference(softif_neigh_vid->softif_neigh); | ||
286 | |||
287 | hlist_for_each_entry_rcu(softif_neigh_tmp, node, | ||
288 | &softif_neigh_vid->softif_neigh_list, | ||
289 | list) { | ||
290 | if (softif_neigh_tmp == curr_neigh) | ||
291 | continue; | ||
292 | |||
293 | /* we got a neighbor but its mac is 'bigger' than ours */ | ||
294 | if (memcmp(primary_if->net_dev->dev_addr, | ||
295 | softif_neigh_tmp->addr, ETH_ALEN) < 0) | ||
296 | continue; | ||
297 | |||
298 | if (!atomic_inc_not_zero(&softif_neigh_tmp->refcount)) | ||
299 | continue; | ||
300 | |||
301 | softif_neigh = softif_neigh_tmp; | ||
302 | goto unlock; | ||
303 | } | ||
304 | |||
305 | unlock: | ||
306 | rcu_read_unlock(); | ||
307 | out: | ||
308 | softif_neigh_vid_select(bat_priv, softif_neigh, softif_neigh_vid->vid); | ||
309 | |||
310 | if (primary_if) | ||
311 | hardif_free_ref(primary_if); | ||
312 | if (softif_neigh) | ||
313 | softif_neigh_free_ref(softif_neigh); | ||
314 | } | ||
315 | |||
160 | int softif_neigh_seq_print_text(struct seq_file *seq, void *offset) | 316 | int softif_neigh_seq_print_text(struct seq_file *seq, void *offset) |
161 | { | 317 | { |
162 | struct net_device *net_dev = (struct net_device *)seq->private; | 318 | struct net_device *net_dev = (struct net_device *)seq->private; |
163 | struct bat_priv *bat_priv = netdev_priv(net_dev); | 319 | struct bat_priv *bat_priv = netdev_priv(net_dev); |
320 | struct softif_neigh_vid *softif_neigh_vid; | ||
164 | struct softif_neigh *softif_neigh; | 321 | struct softif_neigh *softif_neigh; |
165 | struct hlist_node *node; | 322 | struct hard_iface *primary_if; |
323 | struct hlist_node *node, *node_tmp; | ||
324 | struct softif_neigh *curr_softif_neigh; | ||
325 | int ret = 0, last_seen_secs, last_seen_msecs; | ||
326 | |||
327 | primary_if = primary_if_get_selected(bat_priv); | ||
328 | if (!primary_if) { | ||
329 | ret = seq_printf(seq, "BATMAN mesh %s disabled - " | ||
330 | "please specify interfaces to enable it\n", | ||
331 | net_dev->name); | ||
332 | goto out; | ||
333 | } | ||
166 | 334 | ||
167 | if (!bat_priv->primary_if) { | 335 | if (primary_if->if_status != IF_ACTIVE) { |
168 | return seq_printf(seq, "BATMAN mesh %s disabled - " | 336 | ret = seq_printf(seq, "BATMAN mesh %s " |
169 | "please specify interfaces to enable it\n", | 337 | "disabled - primary interface not active\n", |
170 | net_dev->name); | 338 | net_dev->name); |
339 | goto out; | ||
171 | } | 340 | } |
172 | 341 | ||
173 | seq_printf(seq, "Softif neighbor list (%s)\n", net_dev->name); | 342 | seq_printf(seq, "Softif neighbor list (%s)\n", net_dev->name); |
174 | 343 | ||
175 | rcu_read_lock(); | 344 | rcu_read_lock(); |
176 | hlist_for_each_entry_rcu(softif_neigh, node, | 345 | hlist_for_each_entry_rcu(softif_neigh_vid, node, |
177 | &bat_priv->softif_neigh_list, list) | 346 | &bat_priv->softif_neigh_vids, list) { |
178 | seq_printf(seq, "%s %pM (vid: %d)\n", | 347 | seq_printf(seq, " %-15s %s on vid: %d\n", |
179 | bat_priv->softif_neigh == softif_neigh | 348 | "Originator", "last-seen", softif_neigh_vid->vid); |
180 | ? "=>" : " ", softif_neigh->addr, | 349 | |
181 | softif_neigh->vid); | 350 | curr_softif_neigh = softif_neigh_get_selected(softif_neigh_vid); |
351 | |||
352 | hlist_for_each_entry_rcu(softif_neigh, node_tmp, | ||
353 | &softif_neigh_vid->softif_neigh_list, | ||
354 | list) { | ||
355 | last_seen_secs = jiffies_to_msecs(jiffies - | ||
356 | softif_neigh->last_seen) / 1000; | ||
357 | last_seen_msecs = jiffies_to_msecs(jiffies - | ||
358 | softif_neigh->last_seen) % 1000; | ||
359 | seq_printf(seq, "%s %pM %3i.%03is\n", | ||
360 | curr_softif_neigh == softif_neigh | ||
361 | ? "=>" : " ", softif_neigh->addr, | ||
362 | last_seen_secs, last_seen_msecs); | ||
363 | } | ||
364 | |||
365 | if (curr_softif_neigh) | ||
366 | softif_neigh_free_ref(curr_softif_neigh); | ||
367 | |||
368 | seq_printf(seq, "\n"); | ||
369 | } | ||
182 | rcu_read_unlock(); | 370 | rcu_read_unlock(); |
183 | 371 | ||
184 | return 0; | 372 | out: |
373 | if (primary_if) | ||
374 | hardif_free_ref(primary_if); | ||
375 | return ret; | ||
376 | } | ||
377 | |||
378 | void softif_neigh_purge(struct bat_priv *bat_priv) | ||
379 | { | ||
380 | struct softif_neigh *softif_neigh, *curr_softif_neigh; | ||
381 | struct softif_neigh_vid *softif_neigh_vid; | ||
382 | struct hlist_node *node, *node_tmp, *node_tmp2; | ||
383 | char do_deselect; | ||
384 | |||
385 | rcu_read_lock(); | ||
386 | hlist_for_each_entry_rcu(softif_neigh_vid, node, | ||
387 | &bat_priv->softif_neigh_vids, list) { | ||
388 | if (!atomic_inc_not_zero(&softif_neigh_vid->refcount)) | ||
389 | continue; | ||
390 | |||
391 | curr_softif_neigh = softif_neigh_get_selected(softif_neigh_vid); | ||
392 | do_deselect = 0; | ||
393 | |||
394 | spin_lock_bh(&bat_priv->softif_neigh_lock); | ||
395 | hlist_for_each_entry_safe(softif_neigh, node_tmp, node_tmp2, | ||
396 | &softif_neigh_vid->softif_neigh_list, | ||
397 | list) { | ||
398 | if ((!time_after(jiffies, softif_neigh->last_seen + | ||
399 | msecs_to_jiffies(SOFTIF_NEIGH_TIMEOUT))) && | ||
400 | (atomic_read(&bat_priv->mesh_state) == MESH_ACTIVE)) | ||
401 | continue; | ||
402 | |||
403 | if (curr_softif_neigh == softif_neigh) { | ||
404 | bat_dbg(DBG_ROUTES, bat_priv, | ||
405 | "Current mesh exit point on vid: %d " | ||
406 | "'%pM' vanished.\n", | ||
407 | softif_neigh_vid->vid, | ||
408 | softif_neigh->addr); | ||
409 | do_deselect = 1; | ||
410 | } | ||
411 | |||
412 | hlist_del_rcu(&softif_neigh->list); | ||
413 | softif_neigh_free_ref(softif_neigh); | ||
414 | } | ||
415 | spin_unlock_bh(&bat_priv->softif_neigh_lock); | ||
416 | |||
417 | /* soft_neigh_vid_deselect() needs to acquire the | ||
418 | * softif_neigh_lock */ | ||
419 | if (do_deselect) | ||
420 | softif_neigh_vid_deselect(bat_priv, softif_neigh_vid); | ||
421 | |||
422 | if (curr_softif_neigh) | ||
423 | softif_neigh_free_ref(curr_softif_neigh); | ||
424 | |||
425 | softif_neigh_vid_free_ref(softif_neigh_vid); | ||
426 | } | ||
427 | rcu_read_unlock(); | ||
428 | |||
429 | spin_lock_bh(&bat_priv->softif_neigh_vid_lock); | ||
430 | hlist_for_each_entry_safe(softif_neigh_vid, node, node_tmp, | ||
431 | &bat_priv->softif_neigh_vids, list) { | ||
432 | if (!hlist_empty(&softif_neigh_vid->softif_neigh_list)) | ||
433 | continue; | ||
434 | |||
435 | hlist_del_rcu(&softif_neigh_vid->list); | ||
436 | softif_neigh_vid_free_ref(softif_neigh_vid); | ||
437 | } | ||
438 | spin_unlock_bh(&bat_priv->softif_neigh_vid_lock); | ||
439 | |||
185 | } | 440 | } |
186 | 441 | ||
187 | static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev, | 442 | static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev, |
@@ -190,7 +445,9 @@ static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev, | |||
190 | struct bat_priv *bat_priv = netdev_priv(dev); | 445 | struct bat_priv *bat_priv = netdev_priv(dev); |
191 | struct ethhdr *ethhdr = (struct ethhdr *)skb->data; | 446 | struct ethhdr *ethhdr = (struct ethhdr *)skb->data; |
192 | struct batman_packet *batman_packet; | 447 | struct batman_packet *batman_packet; |
193 | struct softif_neigh *softif_neigh, *softif_neigh_tmp; | 448 | struct softif_neigh *softif_neigh = NULL; |
449 | struct hard_iface *primary_if = NULL; | ||
450 | struct softif_neigh *curr_softif_neigh = NULL; | ||
194 | 451 | ||
195 | if (ntohs(ethhdr->h_proto) == ETH_P_8021Q) | 452 | if (ntohs(ethhdr->h_proto) == ETH_P_8021Q) |
196 | batman_packet = (struct batman_packet *) | 453 | batman_packet = (struct batman_packet *) |
@@ -199,63 +456,52 @@ static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev, | |||
199 | batman_packet = (struct batman_packet *)(skb->data + ETH_HLEN); | 456 | batman_packet = (struct batman_packet *)(skb->data + ETH_HLEN); |
200 | 457 | ||
201 | if (batman_packet->version != COMPAT_VERSION) | 458 | if (batman_packet->version != COMPAT_VERSION) |
202 | goto err; | 459 | goto out; |
203 | 460 | ||
204 | if (batman_packet->packet_type != BAT_PACKET) | 461 | if (batman_packet->packet_type != BAT_PACKET) |
205 | goto err; | 462 | goto out; |
206 | 463 | ||
207 | if (!(batman_packet->flags & PRIMARIES_FIRST_HOP)) | 464 | if (!(batman_packet->flags & PRIMARIES_FIRST_HOP)) |
208 | goto err; | 465 | goto out; |
209 | 466 | ||
210 | if (is_my_mac(batman_packet->orig)) | 467 | if (is_my_mac(batman_packet->orig)) |
211 | goto err; | 468 | goto out; |
212 | 469 | ||
213 | softif_neigh = softif_neigh_get(bat_priv, batman_packet->orig, vid); | 470 | softif_neigh = softif_neigh_get(bat_priv, batman_packet->orig, vid); |
214 | |||
215 | if (!softif_neigh) | 471 | if (!softif_neigh) |
216 | goto err; | 472 | goto out; |
217 | 473 | ||
218 | if (bat_priv->softif_neigh == softif_neigh) | 474 | curr_softif_neigh = softif_neigh_vid_get_selected(bat_priv, vid); |
475 | if (curr_softif_neigh == softif_neigh) | ||
476 | goto out; | ||
477 | |||
478 | primary_if = primary_if_get_selected(bat_priv); | ||
479 | if (!primary_if) | ||
219 | goto out; | 480 | goto out; |
220 | 481 | ||
221 | /* we got a neighbor but its mac is 'bigger' than ours */ | 482 | /* we got a neighbor but its mac is 'bigger' than ours */ |
222 | if (memcmp(bat_priv->primary_if->net_dev->dev_addr, | 483 | if (memcmp(primary_if->net_dev->dev_addr, |
223 | softif_neigh->addr, ETH_ALEN) < 0) | 484 | softif_neigh->addr, ETH_ALEN) < 0) |
224 | goto out; | 485 | goto out; |
225 | 486 | ||
226 | /* switch to new 'smallest neighbor' */ | ||
227 | if ((bat_priv->softif_neigh) && | ||
228 | (memcmp(softif_neigh->addr, bat_priv->softif_neigh->addr, | ||
229 | ETH_ALEN) < 0)) { | ||
230 | bat_dbg(DBG_ROUTES, bat_priv, | ||
231 | "Changing mesh exit point from %pM (vid: %d) " | ||
232 | "to %pM (vid: %d).\n", | ||
233 | bat_priv->softif_neigh->addr, | ||
234 | bat_priv->softif_neigh->vid, | ||
235 | softif_neigh->addr, softif_neigh->vid); | ||
236 | softif_neigh_tmp = bat_priv->softif_neigh; | ||
237 | bat_priv->softif_neigh = softif_neigh; | ||
238 | softif_neigh_free_ref(softif_neigh_tmp); | ||
239 | /* we need to hold the additional reference */ | ||
240 | goto err; | ||
241 | } | ||
242 | |||
243 | /* close own batX device and use softif_neigh as exit node */ | 487 | /* close own batX device and use softif_neigh as exit node */ |
244 | if ((!bat_priv->softif_neigh) && | 488 | if (!curr_softif_neigh) { |
245 | (memcmp(softif_neigh->addr, | 489 | softif_neigh_vid_select(bat_priv, softif_neigh, vid); |
246 | bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN) < 0)) { | 490 | goto out; |
247 | bat_dbg(DBG_ROUTES, bat_priv, | ||
248 | "Setting mesh exit point to %pM (vid: %d).\n", | ||
249 | softif_neigh->addr, softif_neigh->vid); | ||
250 | bat_priv->softif_neigh = softif_neigh; | ||
251 | /* we need to hold the additional reference */ | ||
252 | goto err; | ||
253 | } | 491 | } |
254 | 492 | ||
493 | /* switch to new 'smallest neighbor' */ | ||
494 | if (memcmp(softif_neigh->addr, curr_softif_neigh->addr, ETH_ALEN) < 0) | ||
495 | softif_neigh_vid_select(bat_priv, softif_neigh, vid); | ||
496 | |||
255 | out: | 497 | out: |
256 | softif_neigh_free_ref(softif_neigh); | ||
257 | err: | ||
258 | kfree_skb(skb); | 498 | kfree_skb(skb); |
499 | if (softif_neigh) | ||
500 | softif_neigh_free_ref(softif_neigh); | ||
501 | if (curr_softif_neigh) | ||
502 | softif_neigh_free_ref(curr_softif_neigh); | ||
503 | if (primary_if) | ||
504 | hardif_free_ref(primary_if); | ||
259 | return; | 505 | return; |
260 | } | 506 | } |
261 | 507 | ||
@@ -285,11 +531,11 @@ static int interface_set_mac_addr(struct net_device *dev, void *p) | |||
285 | if (!is_valid_ether_addr(addr->sa_data)) | 531 | if (!is_valid_ether_addr(addr->sa_data)) |
286 | return -EADDRNOTAVAIL; | 532 | return -EADDRNOTAVAIL; |
287 | 533 | ||
288 | /* only modify hna-table if it has been initialised before */ | 534 | /* only modify transtable if it has been initialised before */ |
289 | if (atomic_read(&bat_priv->mesh_state) == MESH_ACTIVE) { | 535 | if (atomic_read(&bat_priv->mesh_state) == MESH_ACTIVE) { |
290 | hna_local_remove(bat_priv, dev->dev_addr, | 536 | tt_local_remove(bat_priv, dev->dev_addr, |
291 | "mac address changed"); | 537 | "mac address changed"); |
292 | hna_local_add(dev, addr->sa_data); | 538 | tt_local_add(dev, addr->sa_data); |
293 | } | 539 | } |
294 | 540 | ||
295 | memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); | 541 | memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); |
@@ -311,8 +557,10 @@ int interface_tx(struct sk_buff *skb, struct net_device *soft_iface) | |||
311 | { | 557 | { |
312 | struct ethhdr *ethhdr = (struct ethhdr *)skb->data; | 558 | struct ethhdr *ethhdr = (struct ethhdr *)skb->data; |
313 | struct bat_priv *bat_priv = netdev_priv(soft_iface); | 559 | struct bat_priv *bat_priv = netdev_priv(soft_iface); |
560 | struct hard_iface *primary_if = NULL; | ||
314 | struct bcast_packet *bcast_packet; | 561 | struct bcast_packet *bcast_packet; |
315 | struct vlan_ethhdr *vhdr; | 562 | struct vlan_ethhdr *vhdr; |
563 | struct softif_neigh *curr_softif_neigh = NULL; | ||
316 | int data_len = skb->len, ret; | 564 | int data_len = skb->len, ret; |
317 | short vid = -1; | 565 | short vid = -1; |
318 | bool do_bcast = false; | 566 | bool do_bcast = false; |
@@ -340,11 +588,12 @@ int interface_tx(struct sk_buff *skb, struct net_device *soft_iface) | |||
340 | * if we have a another chosen mesh exit node in range | 588 | * if we have a another chosen mesh exit node in range |
341 | * it will transport the packets to the mesh | 589 | * it will transport the packets to the mesh |
342 | */ | 590 | */ |
343 | if ((bat_priv->softif_neigh) && (bat_priv->softif_neigh->vid == vid)) | 591 | curr_softif_neigh = softif_neigh_vid_get_selected(bat_priv, vid); |
592 | if (curr_softif_neigh) | ||
344 | goto dropped; | 593 | goto dropped; |
345 | 594 | ||
346 | /* TODO: check this for locks */ | 595 | /* TODO: check this for locks */ |
347 | hna_local_add(soft_iface, ethhdr->h_source); | 596 | tt_local_add(soft_iface, ethhdr->h_source); |
348 | 597 | ||
349 | if (is_multicast_ether_addr(ethhdr->h_dest)) { | 598 | if (is_multicast_ether_addr(ethhdr->h_dest)) { |
350 | ret = gw_is_target(bat_priv, skb); | 599 | ret = gw_is_target(bat_priv, skb); |
@@ -358,7 +607,8 @@ int interface_tx(struct sk_buff *skb, struct net_device *soft_iface) | |||
358 | 607 | ||
359 | /* ethernet packet should be broadcasted */ | 608 | /* ethernet packet should be broadcasted */ |
360 | if (do_bcast) { | 609 | if (do_bcast) { |
361 | if (!bat_priv->primary_if) | 610 | primary_if = primary_if_get_selected(bat_priv); |
611 | if (!primary_if) | ||
362 | goto dropped; | 612 | goto dropped; |
363 | 613 | ||
364 | if (my_skb_head_push(skb, sizeof(struct bcast_packet)) < 0) | 614 | if (my_skb_head_push(skb, sizeof(struct bcast_packet)) < 0) |
@@ -374,7 +624,7 @@ int interface_tx(struct sk_buff *skb, struct net_device *soft_iface) | |||
374 | /* hw address of first interface is the orig mac because only | 624 | /* hw address of first interface is the orig mac because only |
375 | * this mac is known throughout the mesh */ | 625 | * this mac is known throughout the mesh */ |
376 | memcpy(bcast_packet->orig, | 626 | memcpy(bcast_packet->orig, |
377 | bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN); | 627 | primary_if->net_dev->dev_addr, ETH_ALEN); |
378 | 628 | ||
379 | /* set broadcast sequence number */ | 629 | /* set broadcast sequence number */ |
380 | bcast_packet->seqno = | 630 | bcast_packet->seqno = |
@@ -402,6 +652,10 @@ dropped: | |||
402 | dropped_freed: | 652 | dropped_freed: |
403 | bat_priv->stats.tx_dropped++; | 653 | bat_priv->stats.tx_dropped++; |
404 | end: | 654 | end: |
655 | if (curr_softif_neigh) | ||
656 | softif_neigh_free_ref(curr_softif_neigh); | ||
657 | if (primary_if) | ||
658 | hardif_free_ref(primary_if); | ||
405 | return NETDEV_TX_OK; | 659 | return NETDEV_TX_OK; |
406 | } | 660 | } |
407 | 661 | ||
@@ -413,6 +667,7 @@ void interface_rx(struct net_device *soft_iface, | |||
413 | struct unicast_packet *unicast_packet; | 667 | struct unicast_packet *unicast_packet; |
414 | struct ethhdr *ethhdr; | 668 | struct ethhdr *ethhdr; |
415 | struct vlan_ethhdr *vhdr; | 669 | struct vlan_ethhdr *vhdr; |
670 | struct softif_neigh *curr_softif_neigh = NULL; | ||
416 | short vid = -1; | 671 | short vid = -1; |
417 | int ret; | 672 | int ret; |
418 | 673 | ||
@@ -442,7 +697,8 @@ void interface_rx(struct net_device *soft_iface, | |||
442 | * if we have a another chosen mesh exit node in range | 697 | * if we have a another chosen mesh exit node in range |
443 | * it will transport the packets to the non-mesh network | 698 | * it will transport the packets to the non-mesh network |
444 | */ | 699 | */ |
445 | if ((bat_priv->softif_neigh) && (bat_priv->softif_neigh->vid == vid)) { | 700 | curr_softif_neigh = softif_neigh_vid_get_selected(bat_priv, vid); |
701 | if (curr_softif_neigh) { | ||
446 | skb_push(skb, hdr_size); | 702 | skb_push(skb, hdr_size); |
447 | unicast_packet = (struct unicast_packet *)skb->data; | 703 | unicast_packet = (struct unicast_packet *)skb->data; |
448 | 704 | ||
@@ -453,7 +709,7 @@ void interface_rx(struct net_device *soft_iface, | |||
453 | skb_reset_mac_header(skb); | 709 | skb_reset_mac_header(skb); |
454 | 710 | ||
455 | memcpy(unicast_packet->dest, | 711 | memcpy(unicast_packet->dest, |
456 | bat_priv->softif_neigh->addr, ETH_ALEN); | 712 | curr_softif_neigh->addr, ETH_ALEN); |
457 | ret = route_unicast_packet(skb, recv_if); | 713 | ret = route_unicast_packet(skb, recv_if); |
458 | if (ret == NET_RX_DROP) | 714 | if (ret == NET_RX_DROP) |
459 | goto dropped; | 715 | goto dropped; |
@@ -478,11 +734,13 @@ void interface_rx(struct net_device *soft_iface, | |||
478 | soft_iface->last_rx = jiffies; | 734 | soft_iface->last_rx = jiffies; |
479 | 735 | ||
480 | netif_rx(skb); | 736 | netif_rx(skb); |
481 | return; | 737 | goto out; |
482 | 738 | ||
483 | dropped: | 739 | dropped: |
484 | kfree_skb(skb); | 740 | kfree_skb(skb); |
485 | out: | 741 | out: |
742 | if (curr_softif_neigh) | ||
743 | softif_neigh_free_ref(curr_softif_neigh); | ||
486 | return; | 744 | return; |
487 | } | 745 | } |
488 | 746 | ||
@@ -516,14 +774,15 @@ static void interface_setup(struct net_device *dev) | |||
516 | dev->hard_start_xmit = interface_tx; | 774 | dev->hard_start_xmit = interface_tx; |
517 | #endif | 775 | #endif |
518 | dev->destructor = free_netdev; | 776 | dev->destructor = free_netdev; |
777 | dev->tx_queue_len = 0; | ||
519 | 778 | ||
520 | /** | 779 | /** |
521 | * can't call min_mtu, because the needed variables | 780 | * can't call min_mtu, because the needed variables |
522 | * have not been initialized yet | 781 | * have not been initialized yet |
523 | */ | 782 | */ |
524 | dev->mtu = ETH_DATA_LEN; | 783 | dev->mtu = ETH_DATA_LEN; |
525 | dev->hard_header_len = BAT_HEADER_LEN; /* reserve more space in the | 784 | /* reserve more space in the skbuff for our header */ |
526 | * skbuff for our header */ | 785 | dev->hard_header_len = BAT_HEADER_LEN; |
527 | 786 | ||
528 | /* generate random address */ | 787 | /* generate random address */ |
529 | random_ether_addr(dev_addr); | 788 | random_ether_addr(dev_addr); |
@@ -548,7 +807,7 @@ struct net_device *softif_create(char *name) | |||
548 | goto out; | 807 | goto out; |
549 | } | 808 | } |
550 | 809 | ||
551 | ret = register_netdev(soft_iface); | 810 | ret = register_netdevice(soft_iface); |
552 | if (ret < 0) { | 811 | if (ret < 0) { |
553 | pr_err("Unable to register the batman interface '%s': %i\n", | 812 | pr_err("Unable to register the batman interface '%s': %i\n", |
554 | name, ret); | 813 | name, ret); |
@@ -572,11 +831,10 @@ struct net_device *softif_create(char *name) | |||
572 | 831 | ||
573 | atomic_set(&bat_priv->mesh_state, MESH_INACTIVE); | 832 | atomic_set(&bat_priv->mesh_state, MESH_INACTIVE); |
574 | atomic_set(&bat_priv->bcast_seqno, 1); | 833 | atomic_set(&bat_priv->bcast_seqno, 1); |
575 | atomic_set(&bat_priv->hna_local_changed, 0); | 834 | atomic_set(&bat_priv->tt_local_changed, 0); |
576 | 835 | ||
577 | bat_priv->primary_if = NULL; | 836 | bat_priv->primary_if = NULL; |
578 | bat_priv->num_ifaces = 0; | 837 | bat_priv->num_ifaces = 0; |
579 | bat_priv->softif_neigh = NULL; | ||
580 | 838 | ||
581 | ret = sysfs_add_meshif(soft_iface); | 839 | ret = sysfs_add_meshif(soft_iface); |
582 | if (ret < 0) | 840 | if (ret < 0) |
@@ -632,7 +890,7 @@ static int bat_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) | |||
632 | { | 890 | { |
633 | cmd->supported = 0; | 891 | cmd->supported = 0; |
634 | cmd->advertising = 0; | 892 | cmd->advertising = 0; |
635 | cmd->speed = SPEED_10; | 893 | ethtool_cmd_speed_set(cmd, SPEED_10); |
636 | cmd->duplex = DUPLEX_FULL; | 894 | cmd->duplex = DUPLEX_FULL; |
637 | cmd->port = PORT_TP; | 895 | cmd->port = PORT_TP; |
638 | cmd->phy_address = 0; | 896 | cmd->phy_address = 0; |
@@ -667,12 +925,3 @@ static u32 bat_get_link(struct net_device *dev) | |||
667 | return 1; | 925 | return 1; |
668 | } | 926 | } |
669 | 927 | ||
670 | static u32 bat_get_rx_csum(struct net_device *dev) | ||
671 | { | ||
672 | return 0; | ||
673 | } | ||
674 | |||
675 | static int bat_set_rx_csum(struct net_device *dev, u32 data) | ||
676 | { | ||
677 | return -EOPNOTSUPP; | ||
678 | } | ||