diff options
author | Johannes Berg <johannes@sipsolutions.net> | 2008-09-10 18:01:49 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-09-15 16:48:20 -0400 |
commit | 472dbc45dc1966284de72d7de15690c17ed2cf33 (patch) | |
tree | e8bfb88067f7fd8845978d1613f868e6a4499999 | |
parent | 7c95069522d02ff144cd421be6618dce619caf7e (diff) |
mac80211: split off mesh handling entirely
This patch splits off mesh handling from the STA/IBSS.
Unfortunately it increases mesh code size a bit, but I
think it makes things clearer. The patch also reduces
per-interface run-time memory usage.
Also clean up a few places where ifdef is not required.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | net/mac80211/cfg.c | 6 | ||||
-rw-r--r-- | net/mac80211/debugfs_netdev.c | 38 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 101 | ||||
-rw-r--r-- | net/mac80211/iface.c | 13 | ||||
-rw-r--r-- | net/mac80211/main.c | 13 | ||||
-rw-r--r-- | net/mac80211/mesh.c | 328 | ||||
-rw-r--r-- | net/mac80211/mesh.h | 15 | ||||
-rw-r--r-- | net/mac80211/mesh_hwmp.c | 98 | ||||
-rw-r--r-- | net/mac80211/mesh_pathtbl.c | 8 | ||||
-rw-r--r-- | net/mac80211/mesh_plink.c | 18 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 83 | ||||
-rw-r--r-- | net/mac80211/rc80211_pid_algo.c | 7 | ||||
-rw-r--r-- | net/mac80211/rx.c | 8 | ||||
-rw-r--r-- | net/mac80211/scan.c | 1 | ||||
-rw-r--r-- | net/mac80211/tx.c | 15 |
15 files changed, 457 insertions, 295 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 5a3bdaad6c19..6ec2127f9a60 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -116,9 +116,9 @@ static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex, | |||
116 | return ret; | 116 | return ret; |
117 | 117 | ||
118 | if (ieee80211_vif_is_mesh(&sdata->vif) && params->mesh_id_len) | 118 | if (ieee80211_vif_is_mesh(&sdata->vif) && params->mesh_id_len) |
119 | ieee80211_if_sta_set_mesh_id(&sdata->u.sta, | 119 | ieee80211_sdata_set_mesh_id(sdata, |
120 | params->mesh_id_len, | 120 | params->mesh_id_len, |
121 | params->mesh_id); | 121 | params->mesh_id); |
122 | 122 | ||
123 | if (sdata->vif.type != IEEE80211_IF_TYPE_MNTR || !flags) | 123 | if (sdata->vif.type != IEEE80211_IF_TYPE_MNTR || !flags) |
124 | return 0; | 124 | return 0; |
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index 8165df578c92..0fa7681a3d20 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c | |||
@@ -207,37 +207,37 @@ IEEE80211_IF_FILE(peer, u.wds.remote_addr, MAC); | |||
207 | 207 | ||
208 | #ifdef CONFIG_MAC80211_MESH | 208 | #ifdef CONFIG_MAC80211_MESH |
209 | /* Mesh stats attributes */ | 209 | /* Mesh stats attributes */ |
210 | IEEE80211_IF_FILE(fwded_frames, u.sta.mshstats.fwded_frames, DEC); | 210 | IEEE80211_IF_FILE(fwded_frames, u.mesh.mshstats.fwded_frames, DEC); |
211 | IEEE80211_IF_FILE(dropped_frames_ttl, u.sta.mshstats.dropped_frames_ttl, DEC); | 211 | IEEE80211_IF_FILE(dropped_frames_ttl, u.mesh.mshstats.dropped_frames_ttl, DEC); |
212 | IEEE80211_IF_FILE(dropped_frames_no_route, | 212 | IEEE80211_IF_FILE(dropped_frames_no_route, |
213 | u.sta.mshstats.dropped_frames_no_route, DEC); | 213 | u.mesh.mshstats.dropped_frames_no_route, DEC); |
214 | IEEE80211_IF_FILE(estab_plinks, u.sta.mshstats.estab_plinks, ATOMIC); | 214 | IEEE80211_IF_FILE(estab_plinks, u.mesh.mshstats.estab_plinks, ATOMIC); |
215 | 215 | ||
216 | /* Mesh parameters */ | 216 | /* Mesh parameters */ |
217 | IEEE80211_IF_WFILE(dot11MeshMaxRetries, | 217 | IEEE80211_IF_WFILE(dot11MeshMaxRetries, |
218 | u.sta.mshcfg.dot11MeshMaxRetries, DEC, u8); | 218 | u.mesh.mshcfg.dot11MeshMaxRetries, DEC, u8); |
219 | IEEE80211_IF_WFILE(dot11MeshRetryTimeout, | 219 | IEEE80211_IF_WFILE(dot11MeshRetryTimeout, |
220 | u.sta.mshcfg.dot11MeshRetryTimeout, DEC, u16); | 220 | u.mesh.mshcfg.dot11MeshRetryTimeout, DEC, u16); |
221 | IEEE80211_IF_WFILE(dot11MeshConfirmTimeout, | 221 | IEEE80211_IF_WFILE(dot11MeshConfirmTimeout, |
222 | u.sta.mshcfg.dot11MeshConfirmTimeout, DEC, u16); | 222 | u.mesh.mshcfg.dot11MeshConfirmTimeout, DEC, u16); |
223 | IEEE80211_IF_WFILE(dot11MeshHoldingTimeout, | 223 | IEEE80211_IF_WFILE(dot11MeshHoldingTimeout, |
224 | u.sta.mshcfg.dot11MeshHoldingTimeout, DEC, u16); | 224 | u.mesh.mshcfg.dot11MeshHoldingTimeout, DEC, u16); |
225 | IEEE80211_IF_WFILE(dot11MeshTTL, u.sta.mshcfg.dot11MeshTTL, DEC, u8); | 225 | IEEE80211_IF_WFILE(dot11MeshTTL, u.mesh.mshcfg.dot11MeshTTL, DEC, u8); |
226 | IEEE80211_IF_WFILE(auto_open_plinks, u.sta.mshcfg.auto_open_plinks, DEC, u8); | 226 | IEEE80211_IF_WFILE(auto_open_plinks, u.mesh.mshcfg.auto_open_plinks, DEC, u8); |
227 | IEEE80211_IF_WFILE(dot11MeshMaxPeerLinks, | 227 | IEEE80211_IF_WFILE(dot11MeshMaxPeerLinks, |
228 | u.sta.mshcfg.dot11MeshMaxPeerLinks, DEC, u16); | 228 | u.mesh.mshcfg.dot11MeshMaxPeerLinks, DEC, u16); |
229 | IEEE80211_IF_WFILE(dot11MeshHWMPactivePathTimeout, | 229 | IEEE80211_IF_WFILE(dot11MeshHWMPactivePathTimeout, |
230 | u.sta.mshcfg.dot11MeshHWMPactivePathTimeout, DEC, u32); | 230 | u.mesh.mshcfg.dot11MeshHWMPactivePathTimeout, DEC, u32); |
231 | IEEE80211_IF_WFILE(dot11MeshHWMPpreqMinInterval, | 231 | IEEE80211_IF_WFILE(dot11MeshHWMPpreqMinInterval, |
232 | u.sta.mshcfg.dot11MeshHWMPpreqMinInterval, DEC, u16); | 232 | u.mesh.mshcfg.dot11MeshHWMPpreqMinInterval, DEC, u16); |
233 | IEEE80211_IF_WFILE(dot11MeshHWMPnetDiameterTraversalTime, | 233 | IEEE80211_IF_WFILE(dot11MeshHWMPnetDiameterTraversalTime, |
234 | u.sta.mshcfg.dot11MeshHWMPnetDiameterTraversalTime, DEC, u16); | 234 | u.mesh.mshcfg.dot11MeshHWMPnetDiameterTraversalTime, DEC, u16); |
235 | IEEE80211_IF_WFILE(dot11MeshHWMPmaxPREQretries, | 235 | IEEE80211_IF_WFILE(dot11MeshHWMPmaxPREQretries, |
236 | u.sta.mshcfg.dot11MeshHWMPmaxPREQretries, DEC, u8); | 236 | u.mesh.mshcfg.dot11MeshHWMPmaxPREQretries, DEC, u8); |
237 | IEEE80211_IF_WFILE(path_refresh_time, | 237 | IEEE80211_IF_WFILE(path_refresh_time, |
238 | u.sta.mshcfg.path_refresh_time, DEC, u32); | 238 | u.mesh.mshcfg.path_refresh_time, DEC, u32); |
239 | IEEE80211_IF_WFILE(min_discovery_timeout, | 239 | IEEE80211_IF_WFILE(min_discovery_timeout, |
240 | u.sta.mshcfg.min_discovery_timeout, DEC, u16); | 240 | u.mesh.mshcfg.min_discovery_timeout, DEC, u16); |
241 | #endif | 241 | #endif |
242 | 242 | ||
243 | 243 | ||
@@ -350,7 +350,7 @@ static void add_files(struct ieee80211_sub_if_data *sdata) | |||
350 | add_mesh_stats(sdata); | 350 | add_mesh_stats(sdata); |
351 | add_mesh_config(sdata); | 351 | add_mesh_config(sdata); |
352 | #endif | 352 | #endif |
353 | /* fall through */ | 353 | break; |
354 | case IEEE80211_IF_TYPE_STA: | 354 | case IEEE80211_IF_TYPE_STA: |
355 | case IEEE80211_IF_TYPE_IBSS: | 355 | case IEEE80211_IF_TYPE_IBSS: |
356 | add_sta_files(sdata); | 356 | add_sta_files(sdata); |
@@ -487,7 +487,7 @@ static void del_files(struct ieee80211_sub_if_data *sdata) | |||
487 | del_mesh_stats(sdata); | 487 | del_mesh_stats(sdata); |
488 | del_mesh_config(sdata); | 488 | del_mesh_config(sdata); |
489 | #endif | 489 | #endif |
490 | /* fall through */ | 490 | break; |
491 | case IEEE80211_IF_TYPE_STA: | 491 | case IEEE80211_IF_TYPE_STA: |
492 | case IEEE80211_IF_TYPE_IBSS: | 492 | case IEEE80211_IF_TYPE_IBSS: |
493 | del_sta_files(sdata); | 493 | del_sta_files(sdata); |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 6f334e4c3d66..cac0b1334548 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -308,7 +308,6 @@ enum ieee80211_sta_mlme_state { | |||
308 | IEEE80211_STA_MLME_ASSOCIATED, | 308 | IEEE80211_STA_MLME_ASSOCIATED, |
309 | IEEE80211_STA_MLME_IBSS_SEARCH, | 309 | IEEE80211_STA_MLME_IBSS_SEARCH, |
310 | IEEE80211_STA_MLME_IBSS_JOINED, | 310 | IEEE80211_STA_MLME_IBSS_JOINED, |
311 | IEEE80211_STA_MLME_MESH_UP | ||
312 | }; | 311 | }; |
313 | 312 | ||
314 | /* bitfield of allowed auth algs */ | 313 | /* bitfield of allowed auth algs */ |
@@ -325,34 +324,6 @@ struct ieee80211_if_sta { | |||
325 | size_t ssid_len; | 324 | size_t ssid_len; |
326 | u8 scan_ssid[IEEE80211_MAX_SSID_LEN]; | 325 | u8 scan_ssid[IEEE80211_MAX_SSID_LEN]; |
327 | size_t scan_ssid_len; | 326 | size_t scan_ssid_len; |
328 | #ifdef CONFIG_MAC80211_MESH | ||
329 | struct timer_list mesh_path_timer; | ||
330 | u8 mesh_id[IEEE80211_MAX_MESH_ID_LEN]; | ||
331 | size_t mesh_id_len; | ||
332 | /* Active Path Selection Protocol Identifier */ | ||
333 | u8 mesh_pp_id[4]; | ||
334 | /* Active Path Selection Metric Identifier */ | ||
335 | u8 mesh_pm_id[4]; | ||
336 | /* Congestion Control Mode Identifier */ | ||
337 | u8 mesh_cc_id[4]; | ||
338 | /* Local mesh Destination Sequence Number */ | ||
339 | u32 dsn; | ||
340 | /* Last used PREQ ID */ | ||
341 | u32 preq_id; | ||
342 | atomic_t mpaths; | ||
343 | /* Timestamp of last DSN update */ | ||
344 | unsigned long last_dsn_update; | ||
345 | /* Timestamp of last DSN sent */ | ||
346 | unsigned long last_preq; | ||
347 | struct mesh_rmc *rmc; | ||
348 | spinlock_t mesh_preq_queue_lock; | ||
349 | struct mesh_preq_queue preq_queue; | ||
350 | int preq_queue_len; | ||
351 | struct mesh_stats mshstats; | ||
352 | struct mesh_config mshcfg; | ||
353 | u32 mesh_seqnum; | ||
354 | bool accepting_plinks; | ||
355 | #endif | ||
356 | u16 aid; | 327 | u16 aid; |
357 | u16 ap_capab, capab; | 328 | u16 ap_capab, capab; |
358 | u8 *extra_ie; /* to be added to the end of AssocReq */ | 329 | u8 *extra_ie; /* to be added to the end of AssocReq */ |
@@ -387,20 +358,47 @@ struct ieee80211_if_sta { | |||
387 | int num_beacons; /* number of TXed beacon frames by this STA */ | 358 | int num_beacons; /* number of TXed beacon frames by this STA */ |
388 | }; | 359 | }; |
389 | 360 | ||
390 | static inline void ieee80211_if_sta_set_mesh_id(struct ieee80211_if_sta *ifsta, | 361 | struct ieee80211_if_mesh { |
391 | u8 mesh_id_len, u8 *mesh_id) | 362 | struct work_struct work; |
392 | { | 363 | struct timer_list housekeeping_timer; |
393 | #ifdef CONFIG_MAC80211_MESH | 364 | struct timer_list mesh_path_timer; |
394 | ifsta->mesh_id_len = mesh_id_len; | 365 | struct sk_buff_head skb_queue; |
395 | memcpy(ifsta->mesh_id, mesh_id, mesh_id_len); | 366 | |
396 | #endif | 367 | bool housekeeping; |
397 | } | 368 | |
369 | u8 mesh_id[IEEE80211_MAX_MESH_ID_LEN]; | ||
370 | size_t mesh_id_len; | ||
371 | /* Active Path Selection Protocol Identifier */ | ||
372 | u8 mesh_pp_id[4]; | ||
373 | /* Active Path Selection Metric Identifier */ | ||
374 | u8 mesh_pm_id[4]; | ||
375 | /* Congestion Control Mode Identifier */ | ||
376 | u8 mesh_cc_id[4]; | ||
377 | /* Local mesh Destination Sequence Number */ | ||
378 | u32 dsn; | ||
379 | /* Last used PREQ ID */ | ||
380 | u32 preq_id; | ||
381 | atomic_t mpaths; | ||
382 | /* Timestamp of last DSN update */ | ||
383 | unsigned long last_dsn_update; | ||
384 | /* Timestamp of last DSN sent */ | ||
385 | unsigned long last_preq; | ||
386 | struct mesh_rmc *rmc; | ||
387 | spinlock_t mesh_preq_queue_lock; | ||
388 | struct mesh_preq_queue preq_queue; | ||
389 | int preq_queue_len; | ||
390 | struct mesh_stats mshstats; | ||
391 | struct mesh_config mshcfg; | ||
392 | u32 mesh_seqnum; | ||
393 | bool accepting_plinks; | ||
394 | int num_beacons; | ||
395 | }; | ||
398 | 396 | ||
399 | #ifdef CONFIG_MAC80211_MESH | 397 | #ifdef CONFIG_MAC80211_MESH |
400 | #define IEEE80211_IFSTA_MESH_CTR_INC(sta, name) \ | 398 | #define IEEE80211_IFSTA_MESH_CTR_INC(msh, name) \ |
401 | do { (sta)->mshstats.name++; } while (0) | 399 | do { (msh)->mshstats.name++; } while (0) |
402 | #else | 400 | #else |
403 | #define IEEE80211_IFSTA_MESH_CTR_INC(sta, name) \ | 401 | #define IEEE80211_IFSTA_MESH_CTR_INC(msh, name) \ |
404 | do { } while (0) | 402 | do { } while (0) |
405 | #endif | 403 | #endif |
406 | 404 | ||
@@ -455,6 +453,9 @@ struct ieee80211_sub_if_data { | |||
455 | struct ieee80211_if_wds wds; | 453 | struct ieee80211_if_wds wds; |
456 | struct ieee80211_if_vlan vlan; | 454 | struct ieee80211_if_vlan vlan; |
457 | struct ieee80211_if_sta sta; | 455 | struct ieee80211_if_sta sta; |
456 | #ifdef CONFIG_MAC80211_MESH | ||
457 | struct ieee80211_if_mesh mesh; | ||
458 | #endif | ||
458 | u32 mntr_flags; | 459 | u32 mntr_flags; |
459 | } u; | 460 | } u; |
460 | 461 | ||
@@ -548,6 +549,19 @@ struct ieee80211_sub_if_data *vif_to_sdata(struct ieee80211_vif *p) | |||
548 | return container_of(p, struct ieee80211_sub_if_data, vif); | 549 | return container_of(p, struct ieee80211_sub_if_data, vif); |
549 | } | 550 | } |
550 | 551 | ||
552 | static inline void | ||
553 | ieee80211_sdata_set_mesh_id(struct ieee80211_sub_if_data *sdata, | ||
554 | u8 mesh_id_len, u8 *mesh_id) | ||
555 | { | ||
556 | #ifdef CONFIG_MAC80211_MESH | ||
557 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | ||
558 | ifmsh->mesh_id_len = mesh_id_len; | ||
559 | memcpy(ifmsh->mesh_id, mesh_id, mesh_id_len); | ||
560 | #else | ||
561 | WARN_ON(1); | ||
562 | #endif | ||
563 | } | ||
564 | |||
551 | enum { | 565 | enum { |
552 | IEEE80211_RX_MSG = 1, | 566 | IEEE80211_RX_MSG = 1, |
553 | IEEE80211_TX_STATUS_MSG = 2, | 567 | IEEE80211_TX_STATUS_MSG = 2, |
@@ -935,13 +949,6 @@ ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq, | |||
935 | void ieee80211_rx_bss_put(struct ieee80211_local *local, | 949 | void ieee80211_rx_bss_put(struct ieee80211_local *local, |
936 | struct ieee80211_sta_bss *bss); | 950 | struct ieee80211_sta_bss *bss); |
937 | 951 | ||
938 | #ifdef CONFIG_MAC80211_MESH | ||
939 | void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata); | ||
940 | #else | ||
941 | static inline void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) | ||
942 | {} | ||
943 | #endif | ||
944 | |||
945 | /* interface handling */ | 952 | /* interface handling */ |
946 | void ieee80211_if_setup(struct net_device *dev); | 953 | void ieee80211_if_setup(struct net_device *dev); |
947 | int ieee80211_if_add(struct ieee80211_local *local, const char *name, | 954 | int ieee80211_if_add(struct ieee80211_local *local, const char *name, |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 672cec60a2fb..ddbaa417e2ec 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -54,10 +54,9 @@ static void ieee80211_teardown_sdata(struct net_device *dev) | |||
54 | 54 | ||
55 | break; | 55 | break; |
56 | case IEEE80211_IF_TYPE_MESH_POINT: | 56 | case IEEE80211_IF_TYPE_MESH_POINT: |
57 | /* Allow compiler to elide mesh_rmc_free call. */ | ||
58 | if (ieee80211_vif_is_mesh(&sdata->vif)) | 57 | if (ieee80211_vif_is_mesh(&sdata->vif)) |
59 | mesh_rmc_free(sdata); | 58 | mesh_rmc_free(sdata); |
60 | /* fall through */ | 59 | break; |
61 | case IEEE80211_IF_TYPE_STA: | 60 | case IEEE80211_IF_TYPE_STA: |
62 | case IEEE80211_IF_TYPE_IBSS: | 61 | case IEEE80211_IF_TYPE_IBSS: |
63 | kfree(sdata->u.sta.extra_ie); | 62 | kfree(sdata->u.sta.extra_ie); |
@@ -100,7 +99,6 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, | |||
100 | skb_queue_head_init(&sdata->u.ap.ps_bc_buf); | 99 | skb_queue_head_init(&sdata->u.ap.ps_bc_buf); |
101 | INIT_LIST_HEAD(&sdata->u.ap.vlans); | 100 | INIT_LIST_HEAD(&sdata->u.ap.vlans); |
102 | break; | 101 | break; |
103 | case IEEE80211_IF_TYPE_MESH_POINT: | ||
104 | case IEEE80211_IF_TYPE_STA: | 102 | case IEEE80211_IF_TYPE_STA: |
105 | case IEEE80211_IF_TYPE_IBSS: | 103 | case IEEE80211_IF_TYPE_IBSS: |
106 | ifsta = &sdata->u.sta; | 104 | ifsta = &sdata->u.sta; |
@@ -117,7 +115,8 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, | |||
117 | IEEE80211_STA_AUTO_CHANNEL_SEL; | 115 | IEEE80211_STA_AUTO_CHANNEL_SEL; |
118 | if (ieee80211_num_regular_queues(&sdata->local->hw) >= 4) | 116 | if (ieee80211_num_regular_queues(&sdata->local->hw) >= 4) |
119 | ifsta->flags |= IEEE80211_STA_WMM_ENABLED; | 117 | ifsta->flags |= IEEE80211_STA_WMM_ENABLED; |
120 | 118 | break; | |
119 | case IEEE80211_IF_TYPE_MESH_POINT: | ||
121 | if (ieee80211_vif_is_mesh(&sdata->vif)) | 120 | if (ieee80211_vif_is_mesh(&sdata->vif)) |
122 | ieee80211_mesh_init_sdata(sdata); | 121 | ieee80211_mesh_init_sdata(sdata); |
123 | break; | 122 | break; |
@@ -225,9 +224,9 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
225 | 224 | ||
226 | if (ieee80211_vif_is_mesh(&sdata->vif) && | 225 | if (ieee80211_vif_is_mesh(&sdata->vif) && |
227 | params && params->mesh_id_len) | 226 | params && params->mesh_id_len) |
228 | ieee80211_if_sta_set_mesh_id(&sdata->u.sta, | 227 | ieee80211_sdata_set_mesh_id(sdata, |
229 | params->mesh_id_len, | 228 | params->mesh_id_len, |
230 | params->mesh_id); | 229 | params->mesh_id); |
231 | 230 | ||
232 | list_add_tail_rcu(&sdata->list, &local->interfaces); | 231 | list_add_tail_rcu(&sdata->list, &local->interfaces); |
233 | 232 | ||
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 6a7f4fae18c2..522fe6176485 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -252,6 +252,8 @@ static int ieee80211_open(struct net_device *dev) | |||
252 | sdata->bss = &sdata->u.ap; | 252 | sdata->bss = &sdata->u.ap; |
253 | break; | 253 | break; |
254 | case IEEE80211_IF_TYPE_MESH_POINT: | 254 | case IEEE80211_IF_TYPE_MESH_POINT: |
255 | if (!ieee80211_vif_is_mesh(&sdata->vif)) | ||
256 | break; | ||
255 | /* mesh ifaces must set allmulti to forward mcast traffic */ | 257 | /* mesh ifaces must set allmulti to forward mcast traffic */ |
256 | atomic_inc(&local->iff_allmultis); | 258 | atomic_inc(&local->iff_allmultis); |
257 | break; | 259 | break; |
@@ -540,10 +542,6 @@ static int ieee80211_stop(struct net_device *dev) | |||
540 | ieee80211_configure_filter(local); | 542 | ieee80211_configure_filter(local); |
541 | netif_addr_unlock_bh(local->mdev); | 543 | netif_addr_unlock_bh(local->mdev); |
542 | break; | 544 | break; |
543 | case IEEE80211_IF_TYPE_MESH_POINT: | ||
544 | /* allmulti is always set on mesh ifaces */ | ||
545 | atomic_dec(&local->iff_allmultis); | ||
546 | /* fall through */ | ||
547 | case IEEE80211_IF_TYPE_STA: | 545 | case IEEE80211_IF_TYPE_STA: |
548 | case IEEE80211_IF_TYPE_IBSS: | 546 | case IEEE80211_IF_TYPE_IBSS: |
549 | sdata->u.sta.state = IEEE80211_STA_MLME_DISABLED; | 547 | sdata->u.sta.state = IEEE80211_STA_MLME_DISABLED; |
@@ -571,6 +569,13 @@ static int ieee80211_stop(struct net_device *dev) | |||
571 | sdata->u.sta.extra_ie = NULL; | 569 | sdata->u.sta.extra_ie = NULL; |
572 | sdata->u.sta.extra_ie_len = 0; | 570 | sdata->u.sta.extra_ie_len = 0; |
573 | /* fall through */ | 571 | /* fall through */ |
572 | case IEEE80211_IF_TYPE_MESH_POINT: | ||
573 | if (ieee80211_vif_is_mesh(&sdata->vif)) { | ||
574 | /* allmulti is always set on mesh ifaces */ | ||
575 | atomic_dec(&local->iff_allmultis); | ||
576 | ieee80211_stop_mesh(sdata); | ||
577 | } | ||
578 | /* fall through */ | ||
574 | default: | 579 | default: |
575 | conf.vif = &sdata->vif; | 580 | conf.vif = &sdata->vif; |
576 | conf.type = sdata->vif.type; | 581 | conf.type = sdata->vif.type; |
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 3ccb3599c04f..9e47725cc592 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -12,6 +12,9 @@ | |||
12 | #include "ieee80211_i.h" | 12 | #include "ieee80211_i.h" |
13 | #include "mesh.h" | 13 | #include "mesh.h" |
14 | 14 | ||
15 | #define IEEE80211_MESH_PEER_INACTIVITY_LIMIT (1800 * HZ) | ||
16 | #define IEEE80211_MESH_HOUSEKEEPING_INTERVAL (60 * HZ) | ||
17 | |||
15 | #define PP_OFFSET 1 /* Path Selection Protocol */ | 18 | #define PP_OFFSET 1 /* Path Selection Protocol */ |
16 | #define PM_OFFSET 5 /* Path Selection Metric */ | 19 | #define PM_OFFSET 5 /* Path Selection Metric */ |
17 | #define CC_OFFSET 9 /* Congestion Control Mode */ | 20 | #define CC_OFFSET 9 /* Congestion Control Mode */ |
@@ -35,6 +38,16 @@ void ieee80211s_stop(void) | |||
35 | kmem_cache_destroy(rm_cache); | 38 | kmem_cache_destroy(rm_cache); |
36 | } | 39 | } |
37 | 40 | ||
41 | static void ieee80211_mesh_housekeeping_timer(unsigned long data) | ||
42 | { | ||
43 | struct ieee80211_sub_if_data *sdata = (void *) data; | ||
44 | struct ieee80211_local *local = sdata->local; | ||
45 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | ||
46 | |||
47 | ifmsh->housekeeping = true; | ||
48 | queue_work(local->hw.workqueue, &ifmsh->work); | ||
49 | } | ||
50 | |||
38 | /** | 51 | /** |
39 | * mesh_matches_local - check if the config of a mesh point matches ours | 52 | * mesh_matches_local - check if the config of a mesh point matches ours |
40 | * | 53 | * |
@@ -46,7 +59,7 @@ void ieee80211s_stop(void) | |||
46 | */ | 59 | */ |
47 | bool mesh_matches_local(struct ieee802_11_elems *ie, struct ieee80211_sub_if_data *sdata) | 60 | bool mesh_matches_local(struct ieee802_11_elems *ie, struct ieee80211_sub_if_data *sdata) |
48 | { | 61 | { |
49 | struct ieee80211_if_sta *sta = &sdata->u.sta; | 62 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
50 | 63 | ||
51 | /* | 64 | /* |
52 | * As support for each feature is added, check for matching | 65 | * As support for each feature is added, check for matching |
@@ -58,11 +71,11 @@ bool mesh_matches_local(struct ieee802_11_elems *ie, struct ieee80211_sub_if_dat | |||
58 | * - MDA enabled | 71 | * - MDA enabled |
59 | * - Power management control on fc | 72 | * - Power management control on fc |
60 | */ | 73 | */ |
61 | if (sta->mesh_id_len == ie->mesh_id_len && | 74 | if (ifmsh->mesh_id_len == ie->mesh_id_len && |
62 | memcmp(sta->mesh_id, ie->mesh_id, ie->mesh_id_len) == 0 && | 75 | memcmp(ifmsh->mesh_id, ie->mesh_id, ie->mesh_id_len) == 0 && |
63 | memcmp(sta->mesh_pp_id, ie->mesh_config + PP_OFFSET, 4) == 0 && | 76 | memcmp(ifmsh->mesh_pp_id, ie->mesh_config + PP_OFFSET, 4) == 0 && |
64 | memcmp(sta->mesh_pm_id, ie->mesh_config + PM_OFFSET, 4) == 0 && | 77 | memcmp(ifmsh->mesh_pm_id, ie->mesh_config + PM_OFFSET, 4) == 0 && |
65 | memcmp(sta->mesh_cc_id, ie->mesh_config + CC_OFFSET, 4) == 0) | 78 | memcmp(ifmsh->mesh_cc_id, ie->mesh_config + CC_OFFSET, 4) == 0) |
66 | return true; | 79 | return true; |
67 | 80 | ||
68 | return false; | 81 | return false; |
@@ -95,11 +108,11 @@ void mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata) | |||
95 | */ | 108 | */ |
96 | free_plinks = mesh_plink_availables(sdata); | 109 | free_plinks = mesh_plink_availables(sdata); |
97 | 110 | ||
98 | if (free_plinks != sdata->u.sta.accepting_plinks) | 111 | if (free_plinks != sdata->u.mesh.accepting_plinks) |
99 | ieee80211_sta_timer((unsigned long) sdata); | 112 | ieee80211_mesh_housekeeping_timer((unsigned long) sdata); |
100 | } | 113 | } |
101 | 114 | ||
102 | void mesh_ids_set_default(struct ieee80211_if_sta *sta) | 115 | void mesh_ids_set_default(struct ieee80211_if_mesh *sta) |
103 | { | 116 | { |
104 | u8 def_id[4] = {0x00, 0x0F, 0xAC, 0xff}; | 117 | u8 def_id[4] = {0x00, 0x0F, 0xAC, 0xff}; |
105 | 118 | ||
@@ -112,22 +125,22 @@ int mesh_rmc_init(struct ieee80211_sub_if_data *sdata) | |||
112 | { | 125 | { |
113 | int i; | 126 | int i; |
114 | 127 | ||
115 | sdata->u.sta.rmc = kmalloc(sizeof(struct mesh_rmc), GFP_KERNEL); | 128 | sdata->u.mesh.rmc = kmalloc(sizeof(struct mesh_rmc), GFP_KERNEL); |
116 | if (!sdata->u.sta.rmc) | 129 | if (!sdata->u.mesh.rmc) |
117 | return -ENOMEM; | 130 | return -ENOMEM; |
118 | sdata->u.sta.rmc->idx_mask = RMC_BUCKETS - 1; | 131 | sdata->u.mesh.rmc->idx_mask = RMC_BUCKETS - 1; |
119 | for (i = 0; i < RMC_BUCKETS; i++) | 132 | for (i = 0; i < RMC_BUCKETS; i++) |
120 | INIT_LIST_HEAD(&sdata->u.sta.rmc->bucket[i].list); | 133 | INIT_LIST_HEAD(&sdata->u.mesh.rmc->bucket[i].list); |
121 | return 0; | 134 | return 0; |
122 | } | 135 | } |
123 | 136 | ||
124 | void mesh_rmc_free(struct ieee80211_sub_if_data *sdata) | 137 | void mesh_rmc_free(struct ieee80211_sub_if_data *sdata) |
125 | { | 138 | { |
126 | struct mesh_rmc *rmc = sdata->u.sta.rmc; | 139 | struct mesh_rmc *rmc = sdata->u.mesh.rmc; |
127 | struct rmc_entry *p, *n; | 140 | struct rmc_entry *p, *n; |
128 | int i; | 141 | int i; |
129 | 142 | ||
130 | if (!sdata->u.sta.rmc) | 143 | if (!sdata->u.mesh.rmc) |
131 | return; | 144 | return; |
132 | 145 | ||
133 | for (i = 0; i < RMC_BUCKETS; i++) | 146 | for (i = 0; i < RMC_BUCKETS; i++) |
@@ -137,7 +150,7 @@ void mesh_rmc_free(struct ieee80211_sub_if_data *sdata) | |||
137 | } | 150 | } |
138 | 151 | ||
139 | kfree(rmc); | 152 | kfree(rmc); |
140 | sdata->u.sta.rmc = NULL; | 153 | sdata->u.mesh.rmc = NULL; |
141 | } | 154 | } |
142 | 155 | ||
143 | /** | 156 | /** |
@@ -155,7 +168,7 @@ void mesh_rmc_free(struct ieee80211_sub_if_data *sdata) | |||
155 | int mesh_rmc_check(u8 *sa, struct ieee80211s_hdr *mesh_hdr, | 168 | int mesh_rmc_check(u8 *sa, struct ieee80211s_hdr *mesh_hdr, |
156 | struct ieee80211_sub_if_data *sdata) | 169 | struct ieee80211_sub_if_data *sdata) |
157 | { | 170 | { |
158 | struct mesh_rmc *rmc = sdata->u.sta.rmc; | 171 | struct mesh_rmc *rmc = sdata->u.mesh.rmc; |
159 | u32 seqnum = 0; | 172 | u32 seqnum = 0; |
160 | int entries = 0; | 173 | int entries = 0; |
161 | u8 idx; | 174 | u8 idx; |
@@ -217,11 +230,11 @@ void mesh_mgmt_ies_add(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) | |||
217 | } | 230 | } |
218 | } | 231 | } |
219 | 232 | ||
220 | pos = skb_put(skb, 2 + sdata->u.sta.mesh_id_len); | 233 | pos = skb_put(skb, 2 + sdata->u.mesh.mesh_id_len); |
221 | *pos++ = WLAN_EID_MESH_ID; | 234 | *pos++ = WLAN_EID_MESH_ID; |
222 | *pos++ = sdata->u.sta.mesh_id_len; | 235 | *pos++ = sdata->u.mesh.mesh_id_len; |
223 | if (sdata->u.sta.mesh_id_len) | 236 | if (sdata->u.mesh.mesh_id_len) |
224 | memcpy(pos, sdata->u.sta.mesh_id, sdata->u.sta.mesh_id_len); | 237 | memcpy(pos, sdata->u.mesh.mesh_id, sdata->u.mesh.mesh_id_len); |
225 | 238 | ||
226 | pos = skb_put(skb, 21); | 239 | pos = skb_put(skb, 21); |
227 | *pos++ = WLAN_EID_MESH_CONFIG; | 240 | *pos++ = WLAN_EID_MESH_CONFIG; |
@@ -230,15 +243,15 @@ void mesh_mgmt_ies_add(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) | |||
230 | *pos++ = 1; | 243 | *pos++ = 1; |
231 | 244 | ||
232 | /* Active path selection protocol ID */ | 245 | /* Active path selection protocol ID */ |
233 | memcpy(pos, sdata->u.sta.mesh_pp_id, 4); | 246 | memcpy(pos, sdata->u.mesh.mesh_pp_id, 4); |
234 | pos += 4; | 247 | pos += 4; |
235 | 248 | ||
236 | /* Active path selection metric ID */ | 249 | /* Active path selection metric ID */ |
237 | memcpy(pos, sdata->u.sta.mesh_pm_id, 4); | 250 | memcpy(pos, sdata->u.mesh.mesh_pm_id, 4); |
238 | pos += 4; | 251 | pos += 4; |
239 | 252 | ||
240 | /* Congestion control mode identifier */ | 253 | /* Congestion control mode identifier */ |
241 | memcpy(pos, sdata->u.sta.mesh_cc_id, 4); | 254 | memcpy(pos, sdata->u.mesh.mesh_cc_id, 4); |
242 | pos += 4; | 255 | pos += 4; |
243 | 256 | ||
244 | /* Channel precedence: | 257 | /* Channel precedence: |
@@ -248,8 +261,8 @@ void mesh_mgmt_ies_add(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) | |||
248 | pos += 4; | 261 | pos += 4; |
249 | 262 | ||
250 | /* Mesh capability */ | 263 | /* Mesh capability */ |
251 | sdata->u.sta.accepting_plinks = mesh_plink_availables(sdata); | 264 | sdata->u.mesh.accepting_plinks = mesh_plink_availables(sdata); |
252 | *pos++ = sdata->u.sta.accepting_plinks ? ACCEPT_PLINKS : 0x00; | 265 | *pos++ = sdata->u.mesh.accepting_plinks ? ACCEPT_PLINKS : 0x00; |
253 | *pos++ = 0x00; | 266 | *pos++ = 0x00; |
254 | 267 | ||
255 | return; | 268 | return; |
@@ -337,10 +350,10 @@ static void ieee80211_mesh_path_timer(unsigned long data) | |||
337 | { | 350 | { |
338 | struct ieee80211_sub_if_data *sdata = | 351 | struct ieee80211_sub_if_data *sdata = |
339 | (struct ieee80211_sub_if_data *) data; | 352 | (struct ieee80211_sub_if_data *) data; |
340 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | 353 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
341 | struct ieee80211_local *local = wdev_priv(&sdata->wdev); | 354 | struct ieee80211_local *local = wdev_priv(&sdata->wdev); |
342 | 355 | ||
343 | queue_work(local->hw.workqueue, &ifsta->work); | 356 | queue_work(local->hw.workqueue, &ifmsh->work); |
344 | } | 357 | } |
345 | 358 | ||
346 | struct mesh_table *mesh_table_grow(struct mesh_table *tbl) | 359 | struct mesh_table *mesh_table_grow(struct mesh_table *tbl) |
@@ -392,50 +405,255 @@ int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr, | |||
392 | struct ieee80211_sub_if_data *sdata) | 405 | struct ieee80211_sub_if_data *sdata) |
393 | { | 406 | { |
394 | meshhdr->flags = 0; | 407 | meshhdr->flags = 0; |
395 | meshhdr->ttl = sdata->u.sta.mshcfg.dot11MeshTTL; | 408 | meshhdr->ttl = sdata->u.mesh.mshcfg.dot11MeshTTL; |
396 | put_unaligned(cpu_to_le32(sdata->u.sta.mesh_seqnum), &meshhdr->seqnum); | 409 | put_unaligned(cpu_to_le32(sdata->u.mesh.mesh_seqnum), &meshhdr->seqnum); |
397 | sdata->u.sta.mesh_seqnum++; | 410 | sdata->u.mesh.mesh_seqnum++; |
398 | 411 | ||
399 | return 6; | 412 | return 6; |
400 | } | 413 | } |
401 | 414 | ||
415 | static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata, | ||
416 | struct ieee80211_if_mesh *ifmsh) | ||
417 | { | ||
418 | bool free_plinks; | ||
419 | |||
420 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
421 | printk(KERN_DEBUG "%s: running mesh housekeeping\n", | ||
422 | sdata->dev->name); | ||
423 | #endif | ||
424 | |||
425 | ieee80211_sta_expire(sdata, IEEE80211_MESH_PEER_INACTIVITY_LIMIT); | ||
426 | mesh_path_expire(sdata); | ||
427 | |||
428 | free_plinks = mesh_plink_availables(sdata); | ||
429 | if (free_plinks != sdata->u.mesh.accepting_plinks) | ||
430 | ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); | ||
431 | |||
432 | ifmsh->housekeeping = false; | ||
433 | mod_timer(&ifmsh->housekeeping_timer, | ||
434 | round_jiffies(jiffies + IEEE80211_MESH_HOUSEKEEPING_INTERVAL)); | ||
435 | } | ||
436 | |||
437 | |||
438 | void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) | ||
439 | { | ||
440 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | ||
441 | struct ieee80211_local *local = sdata->local; | ||
442 | |||
443 | ifmsh->housekeeping = true; | ||
444 | queue_work(local->hw.workqueue, &ifmsh->work); | ||
445 | ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); | ||
446 | } | ||
447 | |||
448 | void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) | ||
449 | { | ||
450 | del_timer_sync(&sdata->u.mesh.housekeeping_timer); | ||
451 | /* | ||
452 | * When we get here, the interface is marked down. | ||
453 | * Call synchronize_rcu() to wait for the RX path | ||
454 | * should it be using the interface and enqueuing | ||
455 | * frames at this very time on another CPU. | ||
456 | */ | ||
457 | synchronize_rcu(); | ||
458 | skb_queue_purge(&sdata->u.mesh.skb_queue); | ||
459 | } | ||
460 | |||
461 | static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, | ||
462 | u16 stype, | ||
463 | struct ieee80211_mgmt *mgmt, | ||
464 | size_t len, | ||
465 | struct ieee80211_rx_status *rx_status) | ||
466 | { | ||
467 | struct ieee80211_local *local= sdata->local; | ||
468 | struct ieee802_11_elems elems; | ||
469 | struct ieee80211_channel *channel; | ||
470 | u64 supp_rates = 0; | ||
471 | size_t baselen; | ||
472 | int freq; | ||
473 | enum ieee80211_band band = rx_status->band; | ||
474 | |||
475 | /* ignore ProbeResp to foreign address */ | ||
476 | if (stype == IEEE80211_STYPE_PROBE_RESP && | ||
477 | compare_ether_addr(mgmt->da, sdata->dev->dev_addr)) | ||
478 | return; | ||
479 | |||
480 | baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt; | ||
481 | if (baselen > len) | ||
482 | return; | ||
483 | |||
484 | ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen, | ||
485 | &elems); | ||
486 | |||
487 | if (elems.ds_params && elems.ds_params_len == 1) | ||
488 | freq = ieee80211_channel_to_frequency(elems.ds_params[0]); | ||
489 | else | ||
490 | freq = rx_status->freq; | ||
491 | |||
492 | channel = ieee80211_get_channel(local->hw.wiphy, freq); | ||
493 | |||
494 | if (!channel || channel->flags & IEEE80211_CHAN_DISABLED) | ||
495 | return; | ||
496 | |||
497 | if (elems.mesh_id && elems.mesh_config && | ||
498 | mesh_matches_local(&elems, sdata)) { | ||
499 | supp_rates = ieee80211_sta_get_rates(local, &elems, band); | ||
500 | |||
501 | mesh_neighbour_update(mgmt->sa, supp_rates, sdata, | ||
502 | mesh_peer_accepts_plinks(&elems)); | ||
503 | } | ||
504 | } | ||
505 | |||
506 | static void ieee80211_mesh_rx_mgmt_action(struct ieee80211_sub_if_data *sdata, | ||
507 | struct ieee80211_mgmt *mgmt, | ||
508 | size_t len, | ||
509 | struct ieee80211_rx_status *rx_status) | ||
510 | { | ||
511 | switch (mgmt->u.action.category) { | ||
512 | case PLINK_CATEGORY: | ||
513 | mesh_rx_plink_frame(sdata, mgmt, len, rx_status); | ||
514 | break; | ||
515 | case MESH_PATH_SEL_CATEGORY: | ||
516 | mesh_rx_path_sel_frame(sdata, mgmt, len); | ||
517 | break; | ||
518 | } | ||
519 | } | ||
520 | |||
521 | static void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | ||
522 | struct sk_buff *skb) | ||
523 | { | ||
524 | struct ieee80211_rx_status *rx_status; | ||
525 | struct ieee80211_if_mesh *ifmsh; | ||
526 | struct ieee80211_mgmt *mgmt; | ||
527 | u16 stype; | ||
528 | |||
529 | ifmsh = &sdata->u.mesh; | ||
530 | |||
531 | rx_status = (struct ieee80211_rx_status *) skb->cb; | ||
532 | mgmt = (struct ieee80211_mgmt *) skb->data; | ||
533 | stype = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE; | ||
534 | |||
535 | switch (stype) { | ||
536 | case IEEE80211_STYPE_PROBE_RESP: | ||
537 | case IEEE80211_STYPE_BEACON: | ||
538 | ieee80211_mesh_rx_bcn_presp(sdata, stype, mgmt, skb->len, | ||
539 | rx_status); | ||
540 | break; | ||
541 | case IEEE80211_STYPE_ACTION: | ||
542 | ieee80211_mesh_rx_mgmt_action(sdata, mgmt, skb->len, rx_status); | ||
543 | break; | ||
544 | } | ||
545 | |||
546 | kfree_skb(skb); | ||
547 | } | ||
548 | |||
549 | static void ieee80211_mesh_work(struct work_struct *work) | ||
550 | { | ||
551 | struct ieee80211_sub_if_data *sdata = | ||
552 | container_of(work, struct ieee80211_sub_if_data, u.mesh.work); | ||
553 | struct ieee80211_local *local = sdata->local; | ||
554 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | ||
555 | struct sk_buff *skb; | ||
556 | |||
557 | if (!netif_running(sdata->dev)) | ||
558 | return; | ||
559 | |||
560 | if (local->sta_sw_scanning || local->sta_hw_scanning) | ||
561 | return; | ||
562 | |||
563 | while ((skb = skb_dequeue(&ifmsh->skb_queue))) | ||
564 | ieee80211_mesh_rx_queued_mgmt(sdata, skb); | ||
565 | |||
566 | if (ifmsh->preq_queue_len && | ||
567 | time_after(jiffies, | ||
568 | ifmsh->last_preq + msecs_to_jiffies(ifmsh->mshcfg.dot11MeshHWMPpreqMinInterval))) | ||
569 | mesh_path_start_discovery(sdata); | ||
570 | |||
571 | if (ifmsh->housekeeping) | ||
572 | ieee80211_mesh_housekeeping(sdata, ifmsh); | ||
573 | } | ||
574 | |||
575 | void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local) | ||
576 | { | ||
577 | struct ieee80211_sub_if_data *sdata; | ||
578 | |||
579 | rcu_read_lock(); | ||
580 | list_for_each_entry_rcu(sdata, &local->interfaces, list) | ||
581 | if (ieee80211_vif_is_mesh(&sdata->vif)) | ||
582 | queue_work(local->hw.workqueue, &sdata->u.mesh.work); | ||
583 | rcu_read_unlock(); | ||
584 | } | ||
585 | |||
402 | void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata) | 586 | void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata) |
403 | { | 587 | { |
404 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | 588 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
405 | 589 | ||
406 | ifsta->mshcfg.dot11MeshRetryTimeout = MESH_RET_T; | 590 | INIT_WORK(&ifmsh->work, ieee80211_mesh_work); |
407 | ifsta->mshcfg.dot11MeshConfirmTimeout = MESH_CONF_T; | 591 | setup_timer(&ifmsh->housekeeping_timer, |
408 | ifsta->mshcfg.dot11MeshHoldingTimeout = MESH_HOLD_T; | 592 | ieee80211_mesh_housekeeping_timer, |
409 | ifsta->mshcfg.dot11MeshMaxRetries = MESH_MAX_RETR; | 593 | (unsigned long) sdata); |
410 | ifsta->mshcfg.dot11MeshTTL = MESH_TTL; | 594 | skb_queue_head_init(&sdata->u.mesh.skb_queue); |
411 | ifsta->mshcfg.auto_open_plinks = true; | 595 | |
412 | ifsta->mshcfg.dot11MeshMaxPeerLinks = | 596 | ifmsh->mshcfg.dot11MeshRetryTimeout = MESH_RET_T; |
597 | ifmsh->mshcfg.dot11MeshConfirmTimeout = MESH_CONF_T; | ||
598 | ifmsh->mshcfg.dot11MeshHoldingTimeout = MESH_HOLD_T; | ||
599 | ifmsh->mshcfg.dot11MeshMaxRetries = MESH_MAX_RETR; | ||
600 | ifmsh->mshcfg.dot11MeshTTL = MESH_TTL; | ||
601 | ifmsh->mshcfg.auto_open_plinks = true; | ||
602 | ifmsh->mshcfg.dot11MeshMaxPeerLinks = | ||
413 | MESH_MAX_ESTAB_PLINKS; | 603 | MESH_MAX_ESTAB_PLINKS; |
414 | ifsta->mshcfg.dot11MeshHWMPactivePathTimeout = | 604 | ifmsh->mshcfg.dot11MeshHWMPactivePathTimeout = |
415 | MESH_PATH_TIMEOUT; | 605 | MESH_PATH_TIMEOUT; |
416 | ifsta->mshcfg.dot11MeshHWMPpreqMinInterval = | 606 | ifmsh->mshcfg.dot11MeshHWMPpreqMinInterval = |
417 | MESH_PREQ_MIN_INT; | 607 | MESH_PREQ_MIN_INT; |
418 | ifsta->mshcfg.dot11MeshHWMPnetDiameterTraversalTime = | 608 | ifmsh->mshcfg.dot11MeshHWMPnetDiameterTraversalTime = |
419 | MESH_DIAM_TRAVERSAL_TIME; | 609 | MESH_DIAM_TRAVERSAL_TIME; |
420 | ifsta->mshcfg.dot11MeshHWMPmaxPREQretries = | 610 | ifmsh->mshcfg.dot11MeshHWMPmaxPREQretries = |
421 | MESH_MAX_PREQ_RETRIES; | 611 | MESH_MAX_PREQ_RETRIES; |
422 | ifsta->mshcfg.path_refresh_time = | 612 | ifmsh->mshcfg.path_refresh_time = |
423 | MESH_PATH_REFRESH_TIME; | 613 | MESH_PATH_REFRESH_TIME; |
424 | ifsta->mshcfg.min_discovery_timeout = | 614 | ifmsh->mshcfg.min_discovery_timeout = |
425 | MESH_MIN_DISCOVERY_TIMEOUT; | 615 | MESH_MIN_DISCOVERY_TIMEOUT; |
426 | ifsta->accepting_plinks = true; | 616 | ifmsh->accepting_plinks = true; |
427 | ifsta->preq_id = 0; | 617 | ifmsh->preq_id = 0; |
428 | ifsta->dsn = 0; | 618 | ifmsh->dsn = 0; |
429 | atomic_set(&ifsta->mpaths, 0); | 619 | atomic_set(&ifmsh->mpaths, 0); |
430 | mesh_rmc_init(sdata); | 620 | mesh_rmc_init(sdata); |
431 | ifsta->last_preq = jiffies; | 621 | ifmsh->last_preq = jiffies; |
432 | /* Allocate all mesh structures when creating the first mesh interface. */ | 622 | /* Allocate all mesh structures when creating the first mesh interface. */ |
433 | if (!mesh_allocated) | 623 | if (!mesh_allocated) |
434 | ieee80211s_init(); | 624 | ieee80211s_init(); |
435 | mesh_ids_set_default(ifsta); | 625 | mesh_ids_set_default(ifmsh); |
436 | setup_timer(&ifsta->mesh_path_timer, | 626 | setup_timer(&ifmsh->mesh_path_timer, |
437 | ieee80211_mesh_path_timer, | 627 | ieee80211_mesh_path_timer, |
438 | (unsigned long) sdata); | 628 | (unsigned long) sdata); |
439 | INIT_LIST_HEAD(&ifsta->preq_queue.list); | 629 | INIT_LIST_HEAD(&ifmsh->preq_queue.list); |
440 | spin_lock_init(&ifsta->mesh_preq_queue_lock); | 630 | spin_lock_init(&ifmsh->mesh_preq_queue_lock); |
631 | } | ||
632 | |||
633 | ieee80211_rx_result | ||
634 | ieee80211_mesh_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, | ||
635 | struct ieee80211_rx_status *rx_status) | ||
636 | { | ||
637 | struct ieee80211_local *local = sdata->local; | ||
638 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | ||
639 | struct ieee80211_mgmt *mgmt; | ||
640 | u16 fc; | ||
641 | |||
642 | if (skb->len < 24) | ||
643 | return RX_DROP_MONITOR; | ||
644 | |||
645 | mgmt = (struct ieee80211_mgmt *) skb->data; | ||
646 | fc = le16_to_cpu(mgmt->frame_control); | ||
647 | |||
648 | switch (fc & IEEE80211_FCTL_STYPE) { | ||
649 | case IEEE80211_STYPE_PROBE_RESP: | ||
650 | case IEEE80211_STYPE_BEACON: | ||
651 | case IEEE80211_STYPE_ACTION: | ||
652 | memcpy(skb->cb, rx_status, sizeof(*rx_status)); | ||
653 | skb_queue_tail(&ifmsh->skb_queue, skb); | ||
654 | queue_work(local->hw.workqueue, &ifmsh->work); | ||
655 | return RX_QUEUED; | ||
656 | } | ||
657 | |||
658 | return RX_CONTINUE; | ||
441 | } | 659 | } |
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index 84ff5d828fdb..8ee414a0447c 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h | |||
@@ -206,7 +206,7 @@ int mesh_rmc_check(u8 *addr, struct ieee80211s_hdr *mesh_hdr, | |||
206 | struct ieee80211_sub_if_data *sdata); | 206 | struct ieee80211_sub_if_data *sdata); |
207 | bool mesh_matches_local(struct ieee802_11_elems *ie, | 207 | bool mesh_matches_local(struct ieee802_11_elems *ie, |
208 | struct ieee80211_sub_if_data *sdata); | 208 | struct ieee80211_sub_if_data *sdata); |
209 | void mesh_ids_set_default(struct ieee80211_if_sta *sta); | 209 | void mesh_ids_set_default(struct ieee80211_if_mesh *mesh); |
210 | void mesh_mgmt_ies_add(struct sk_buff *skb, | 210 | void mesh_mgmt_ies_add(struct sk_buff *skb, |
211 | struct ieee80211_sub_if_data *sdata); | 211 | struct ieee80211_sub_if_data *sdata); |
212 | void mesh_rmc_free(struct ieee80211_sub_if_data *sdata); | 212 | void mesh_rmc_free(struct ieee80211_sub_if_data *sdata); |
@@ -214,6 +214,11 @@ int mesh_rmc_init(struct ieee80211_sub_if_data *sdata); | |||
214 | void ieee80211s_init(void); | 214 | void ieee80211s_init(void); |
215 | void ieee80211s_stop(void); | 215 | void ieee80211s_stop(void); |
216 | void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata); | 216 | void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata); |
217 | ieee80211_rx_result | ||
218 | ieee80211_mesh_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, | ||
219 | struct ieee80211_rx_status *rx_status); | ||
220 | void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata); | ||
221 | void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata); | ||
217 | 222 | ||
218 | /* Mesh paths */ | 223 | /* Mesh paths */ |
219 | int mesh_nexthop_lookup(struct sk_buff *skb, | 224 | int mesh_nexthop_lookup(struct sk_buff *skb, |
@@ -269,8 +274,8 @@ extern int mesh_allocated; | |||
269 | 274 | ||
270 | static inline int mesh_plink_free_count(struct ieee80211_sub_if_data *sdata) | 275 | static inline int mesh_plink_free_count(struct ieee80211_sub_if_data *sdata) |
271 | { | 276 | { |
272 | return sdata->u.sta.mshcfg.dot11MeshMaxPeerLinks - | 277 | return sdata->u.mesh.mshcfg.dot11MeshMaxPeerLinks - |
273 | atomic_read(&sdata->u.sta.mshstats.estab_plinks); | 278 | atomic_read(&sdata->u.mesh.mshstats.estab_plinks); |
274 | } | 279 | } |
275 | 280 | ||
276 | static inline bool mesh_plink_availables(struct ieee80211_sub_if_data *sdata) | 281 | static inline bool mesh_plink_availables(struct ieee80211_sub_if_data *sdata) |
@@ -288,8 +293,12 @@ static inline void mesh_path_activate(struct mesh_path *mpath) | |||
288 | for (i = 0; i <= x->hash_mask; i++) \ | 293 | for (i = 0; i <= x->hash_mask; i++) \ |
289 | hlist_for_each_entry_rcu(node, p, &x->hash_buckets[i], list) | 294 | hlist_for_each_entry_rcu(node, p, &x->hash_buckets[i], list) |
290 | 295 | ||
296 | void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local); | ||
297 | |||
291 | #else | 298 | #else |
292 | #define mesh_allocated 0 | 299 | #define mesh_allocated 0 |
300 | static inline void | ||
301 | ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local) {} | ||
293 | #endif | 302 | #endif |
294 | 303 | ||
295 | #endif /* IEEE80211S_H */ | 304 | #endif /* IEEE80211S_H */ |
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 210d6b852406..1fad792ad258 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c | |||
@@ -64,14 +64,14 @@ static inline u32 u32_field_get(u8 *preq_elem, int offset, bool ae) | |||
64 | #define DSN_LT(x, y) ((long) (x) - (long) (y) < 0) | 64 | #define DSN_LT(x, y) ((long) (x) - (long) (y) < 0) |
65 | 65 | ||
66 | #define net_traversal_jiffies(s) \ | 66 | #define net_traversal_jiffies(s) \ |
67 | msecs_to_jiffies(s->u.sta.mshcfg.dot11MeshHWMPnetDiameterTraversalTime) | 67 | msecs_to_jiffies(s->u.mesh.mshcfg.dot11MeshHWMPnetDiameterTraversalTime) |
68 | #define default_lifetime(s) \ | 68 | #define default_lifetime(s) \ |
69 | MSEC_TO_TU(s->u.sta.mshcfg.dot11MeshHWMPactivePathTimeout) | 69 | MSEC_TO_TU(s->u.mesh.mshcfg.dot11MeshHWMPactivePathTimeout) |
70 | #define min_preq_int_jiff(s) \ | 70 | #define min_preq_int_jiff(s) \ |
71 | (msecs_to_jiffies(s->u.sta.mshcfg.dot11MeshHWMPpreqMinInterval)) | 71 | (msecs_to_jiffies(s->u.mesh.mshcfg.dot11MeshHWMPpreqMinInterval)) |
72 | #define max_preq_retries(s) (s->u.sta.mshcfg.dot11MeshHWMPmaxPREQretries) | 72 | #define max_preq_retries(s) (s->u.mesh.mshcfg.dot11MeshHWMPmaxPREQretries) |
73 | #define disc_timeout_jiff(s) \ | 73 | #define disc_timeout_jiff(s) \ |
74 | msecs_to_jiffies(sdata->u.sta.mshcfg.min_discovery_timeout) | 74 | msecs_to_jiffies(sdata->u.mesh.mshcfg.min_discovery_timeout) |
75 | 75 | ||
76 | enum mpath_frame_type { | 76 | enum mpath_frame_type { |
77 | MPATH_PREQ = 0, | 77 | MPATH_PREQ = 0, |
@@ -395,7 +395,7 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata, | |||
395 | static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata, | 395 | static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata, |
396 | struct ieee80211_mgmt *mgmt, | 396 | struct ieee80211_mgmt *mgmt, |
397 | u8 *preq_elem, u32 metric) { | 397 | u8 *preq_elem, u32 metric) { |
398 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | 398 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
399 | struct mesh_path *mpath; | 399 | struct mesh_path *mpath; |
400 | u8 *dst_addr, *orig_addr; | 400 | u8 *dst_addr, *orig_addr; |
401 | u8 dst_flags, ttl; | 401 | u8 dst_flags, ttl; |
@@ -414,11 +414,11 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata, | |||
414 | forward = false; | 414 | forward = false; |
415 | reply = true; | 415 | reply = true; |
416 | metric = 0; | 416 | metric = 0; |
417 | if (time_after(jiffies, ifsta->last_dsn_update + | 417 | if (time_after(jiffies, ifmsh->last_dsn_update + |
418 | net_traversal_jiffies(sdata)) || | 418 | net_traversal_jiffies(sdata)) || |
419 | time_before(jiffies, ifsta->last_dsn_update)) { | 419 | time_before(jiffies, ifmsh->last_dsn_update)) { |
420 | dst_dsn = ++ifsta->dsn; | 420 | dst_dsn = ++ifmsh->dsn; |
421 | ifsta->last_dsn_update = jiffies; | 421 | ifmsh->last_dsn_update = jiffies; |
422 | } | 422 | } |
423 | } else { | 423 | } else { |
424 | rcu_read_lock(); | 424 | rcu_read_lock(); |
@@ -444,7 +444,7 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata, | |||
444 | 444 | ||
445 | if (reply) { | 445 | if (reply) { |
446 | lifetime = PREQ_IE_LIFETIME(preq_elem); | 446 | lifetime = PREQ_IE_LIFETIME(preq_elem); |
447 | ttl = ifsta->mshcfg.dot11MeshTTL; | 447 | ttl = ifmsh->mshcfg.dot11MeshTTL; |
448 | if (ttl != 0) | 448 | if (ttl != 0) |
449 | mesh_path_sel_frame_tx(MPATH_PREP, 0, dst_addr, | 449 | mesh_path_sel_frame_tx(MPATH_PREP, 0, dst_addr, |
450 | cpu_to_le32(dst_dsn), 0, orig_addr, | 450 | cpu_to_le32(dst_dsn), 0, orig_addr, |
@@ -452,7 +452,7 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata, | |||
452 | cpu_to_le32(lifetime), cpu_to_le32(metric), | 452 | cpu_to_le32(lifetime), cpu_to_le32(metric), |
453 | 0, sdata); | 453 | 0, sdata); |
454 | else | 454 | else |
455 | ifsta->mshstats.dropped_frames_ttl++; | 455 | ifmsh->mshstats.dropped_frames_ttl++; |
456 | } | 456 | } |
457 | 457 | ||
458 | if (forward) { | 458 | if (forward) { |
@@ -462,7 +462,7 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata, | |||
462 | ttl = PREQ_IE_TTL(preq_elem); | 462 | ttl = PREQ_IE_TTL(preq_elem); |
463 | lifetime = PREQ_IE_LIFETIME(preq_elem); | 463 | lifetime = PREQ_IE_LIFETIME(preq_elem); |
464 | if (ttl <= 1) { | 464 | if (ttl <= 1) { |
465 | ifsta->mshstats.dropped_frames_ttl++; | 465 | ifmsh->mshstats.dropped_frames_ttl++; |
466 | return; | 466 | return; |
467 | } | 467 | } |
468 | --ttl; | 468 | --ttl; |
@@ -475,7 +475,7 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata, | |||
475 | hopcount, ttl, cpu_to_le32(lifetime), | 475 | hopcount, ttl, cpu_to_le32(lifetime), |
476 | cpu_to_le32(metric), cpu_to_le32(preq_id), | 476 | cpu_to_le32(metric), cpu_to_le32(preq_id), |
477 | sdata); | 477 | sdata); |
478 | ifsta->mshstats.fwded_frames++; | 478 | ifmsh->mshstats.fwded_frames++; |
479 | } | 479 | } |
480 | } | 480 | } |
481 | 481 | ||
@@ -503,7 +503,7 @@ static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata, | |||
503 | 503 | ||
504 | ttl = PREP_IE_TTL(prep_elem); | 504 | ttl = PREP_IE_TTL(prep_elem); |
505 | if (ttl <= 1) { | 505 | if (ttl <= 1) { |
506 | sdata->u.sta.mshstats.dropped_frames_ttl++; | 506 | sdata->u.mesh.mshstats.dropped_frames_ttl++; |
507 | return; | 507 | return; |
508 | } | 508 | } |
509 | 509 | ||
@@ -533,12 +533,12 @@ static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata, | |||
533 | cpu_to_le32(lifetime), cpu_to_le32(metric), | 533 | cpu_to_le32(lifetime), cpu_to_le32(metric), |
534 | 0, sdata); | 534 | 0, sdata); |
535 | rcu_read_unlock(); | 535 | rcu_read_unlock(); |
536 | sdata->u.sta.mshstats.fwded_frames++; | 536 | sdata->u.mesh.mshstats.fwded_frames++; |
537 | return; | 537 | return; |
538 | 538 | ||
539 | fail: | 539 | fail: |
540 | rcu_read_unlock(); | 540 | rcu_read_unlock(); |
541 | sdata->u.sta.mshstats.dropped_frames_no_route++; | 541 | sdata->u.mesh.mshstats.dropped_frames_no_route++; |
542 | return; | 542 | return; |
543 | } | 543 | } |
544 | 544 | ||
@@ -631,7 +631,7 @@ void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata, | |||
631 | static void mesh_queue_preq(struct mesh_path *mpath, u8 flags) | 631 | static void mesh_queue_preq(struct mesh_path *mpath, u8 flags) |
632 | { | 632 | { |
633 | struct ieee80211_sub_if_data *sdata = mpath->sdata; | 633 | struct ieee80211_sub_if_data *sdata = mpath->sdata; |
634 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | 634 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
635 | struct mesh_preq_queue *preq_node; | 635 | struct mesh_preq_queue *preq_node; |
636 | 636 | ||
637 | preq_node = kmalloc(sizeof(struct mesh_preq_queue), GFP_KERNEL); | 637 | preq_node = kmalloc(sizeof(struct mesh_preq_queue), GFP_KERNEL); |
@@ -640,9 +640,9 @@ static void mesh_queue_preq(struct mesh_path *mpath, u8 flags) | |||
640 | return; | 640 | return; |
641 | } | 641 | } |
642 | 642 | ||
643 | spin_lock(&ifsta->mesh_preq_queue_lock); | 643 | spin_lock(&ifmsh->mesh_preq_queue_lock); |
644 | if (ifsta->preq_queue_len == MAX_PREQ_QUEUE_LEN) { | 644 | if (ifmsh->preq_queue_len == MAX_PREQ_QUEUE_LEN) { |
645 | spin_unlock(&ifsta->mesh_preq_queue_lock); | 645 | spin_unlock(&ifmsh->mesh_preq_queue_lock); |
646 | kfree(preq_node); | 646 | kfree(preq_node); |
647 | if (printk_ratelimit()) | 647 | if (printk_ratelimit()) |
648 | printk(KERN_DEBUG "Mesh HWMP: PREQ node queue full\n"); | 648 | printk(KERN_DEBUG "Mesh HWMP: PREQ node queue full\n"); |
@@ -652,21 +652,21 @@ static void mesh_queue_preq(struct mesh_path *mpath, u8 flags) | |||
652 | memcpy(preq_node->dst, mpath->dst, ETH_ALEN); | 652 | memcpy(preq_node->dst, mpath->dst, ETH_ALEN); |
653 | preq_node->flags = flags; | 653 | preq_node->flags = flags; |
654 | 654 | ||
655 | list_add_tail(&preq_node->list, &ifsta->preq_queue.list); | 655 | list_add_tail(&preq_node->list, &ifmsh->preq_queue.list); |
656 | ++ifsta->preq_queue_len; | 656 | ++ifmsh->preq_queue_len; |
657 | spin_unlock(&ifsta->mesh_preq_queue_lock); | 657 | spin_unlock(&ifmsh->mesh_preq_queue_lock); |
658 | 658 | ||
659 | if (time_after(jiffies, ifsta->last_preq + min_preq_int_jiff(sdata))) | 659 | if (time_after(jiffies, ifmsh->last_preq + min_preq_int_jiff(sdata))) |
660 | queue_work(sdata->local->hw.workqueue, &ifsta->work); | 660 | queue_work(sdata->local->hw.workqueue, &ifmsh->work); |
661 | 661 | ||
662 | else if (time_before(jiffies, ifsta->last_preq)) { | 662 | else if (time_before(jiffies, ifmsh->last_preq)) { |
663 | /* avoid long wait if did not send preqs for a long time | 663 | /* avoid long wait if did not send preqs for a long time |
664 | * and jiffies wrapped around | 664 | * and jiffies wrapped around |
665 | */ | 665 | */ |
666 | ifsta->last_preq = jiffies - min_preq_int_jiff(sdata) - 1; | 666 | ifmsh->last_preq = jiffies - min_preq_int_jiff(sdata) - 1; |
667 | queue_work(sdata->local->hw.workqueue, &ifsta->work); | 667 | queue_work(sdata->local->hw.workqueue, &ifmsh->work); |
668 | } else | 668 | } else |
669 | mod_timer(&ifsta->mesh_path_timer, ifsta->last_preq + | 669 | mod_timer(&ifmsh->mesh_path_timer, ifmsh->last_preq + |
670 | min_preq_int_jiff(sdata)); | 670 | min_preq_int_jiff(sdata)); |
671 | } | 671 | } |
672 | 672 | ||
@@ -677,25 +677,25 @@ static void mesh_queue_preq(struct mesh_path *mpath, u8 flags) | |||
677 | */ | 677 | */ |
678 | void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata) | 678 | void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata) |
679 | { | 679 | { |
680 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | 680 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
681 | struct mesh_preq_queue *preq_node; | 681 | struct mesh_preq_queue *preq_node; |
682 | struct mesh_path *mpath; | 682 | struct mesh_path *mpath; |
683 | u8 ttl, dst_flags; | 683 | u8 ttl, dst_flags; |
684 | u32 lifetime; | 684 | u32 lifetime; |
685 | 685 | ||
686 | spin_lock(&ifsta->mesh_preq_queue_lock); | 686 | spin_lock(&ifmsh->mesh_preq_queue_lock); |
687 | if (!ifsta->preq_queue_len || | 687 | if (!ifmsh->preq_queue_len || |
688 | time_before(jiffies, ifsta->last_preq + | 688 | time_before(jiffies, ifmsh->last_preq + |
689 | min_preq_int_jiff(sdata))) { | 689 | min_preq_int_jiff(sdata))) { |
690 | spin_unlock(&ifsta->mesh_preq_queue_lock); | 690 | spin_unlock(&ifmsh->mesh_preq_queue_lock); |
691 | return; | 691 | return; |
692 | } | 692 | } |
693 | 693 | ||
694 | preq_node = list_first_entry(&ifsta->preq_queue.list, | 694 | preq_node = list_first_entry(&ifmsh->preq_queue.list, |
695 | struct mesh_preq_queue, list); | 695 | struct mesh_preq_queue, list); |
696 | list_del(&preq_node->list); | 696 | list_del(&preq_node->list); |
697 | --ifsta->preq_queue_len; | 697 | --ifmsh->preq_queue_len; |
698 | spin_unlock(&ifsta->mesh_preq_queue_lock); | 698 | spin_unlock(&ifmsh->mesh_preq_queue_lock); |
699 | 699 | ||
700 | rcu_read_lock(); | 700 | rcu_read_lock(); |
701 | mpath = mesh_path_lookup(preq_node->dst, sdata); | 701 | mpath = mesh_path_lookup(preq_node->dst, sdata); |
@@ -720,18 +720,18 @@ void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata) | |||
720 | goto enddiscovery; | 720 | goto enddiscovery; |
721 | } | 721 | } |
722 | 722 | ||
723 | ifsta->last_preq = jiffies; | 723 | ifmsh->last_preq = jiffies; |
724 | 724 | ||
725 | if (time_after(jiffies, ifsta->last_dsn_update + | 725 | if (time_after(jiffies, ifmsh->last_dsn_update + |
726 | net_traversal_jiffies(sdata)) || | 726 | net_traversal_jiffies(sdata)) || |
727 | time_before(jiffies, ifsta->last_dsn_update)) { | 727 | time_before(jiffies, ifmsh->last_dsn_update)) { |
728 | ++ifsta->dsn; | 728 | ++ifmsh->dsn; |
729 | sdata->u.sta.last_dsn_update = jiffies; | 729 | sdata->u.mesh.last_dsn_update = jiffies; |
730 | } | 730 | } |
731 | lifetime = default_lifetime(sdata); | 731 | lifetime = default_lifetime(sdata); |
732 | ttl = sdata->u.sta.mshcfg.dot11MeshTTL; | 732 | ttl = sdata->u.mesh.mshcfg.dot11MeshTTL; |
733 | if (ttl == 0) { | 733 | if (ttl == 0) { |
734 | sdata->u.sta.mshstats.dropped_frames_ttl++; | 734 | sdata->u.mesh.mshstats.dropped_frames_ttl++; |
735 | spin_unlock_bh(&mpath->state_lock); | 735 | spin_unlock_bh(&mpath->state_lock); |
736 | goto enddiscovery; | 736 | goto enddiscovery; |
737 | } | 737 | } |
@@ -743,10 +743,10 @@ void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata) | |||
743 | 743 | ||
744 | spin_unlock_bh(&mpath->state_lock); | 744 | spin_unlock_bh(&mpath->state_lock); |
745 | mesh_path_sel_frame_tx(MPATH_PREQ, 0, sdata->dev->dev_addr, | 745 | mesh_path_sel_frame_tx(MPATH_PREQ, 0, sdata->dev->dev_addr, |
746 | cpu_to_le32(ifsta->dsn), dst_flags, mpath->dst, | 746 | cpu_to_le32(ifmsh->dsn), dst_flags, mpath->dst, |
747 | cpu_to_le32(mpath->dsn), sdata->dev->broadcast, 0, | 747 | cpu_to_le32(mpath->dsn), sdata->dev->broadcast, 0, |
748 | ttl, cpu_to_le32(lifetime), 0, | 748 | ttl, cpu_to_le32(lifetime), 0, |
749 | cpu_to_le32(ifsta->preq_id++), sdata); | 749 | cpu_to_le32(ifmsh->preq_id++), sdata); |
750 | mod_timer(&mpath->timer, jiffies + mpath->discovery_timeout); | 750 | mod_timer(&mpath->timer, jiffies + mpath->discovery_timeout); |
751 | 751 | ||
752 | enddiscovery: | 752 | enddiscovery: |
@@ -783,7 +783,7 @@ int mesh_nexthop_lookup(struct sk_buff *skb, | |||
783 | mpath = mesh_path_lookup(dst_addr, sdata); | 783 | mpath = mesh_path_lookup(dst_addr, sdata); |
784 | if (!mpath) { | 784 | if (!mpath) { |
785 | dev_kfree_skb(skb); | 785 | dev_kfree_skb(skb); |
786 | sdata->u.sta.mshstats.dropped_frames_no_route++; | 786 | sdata->u.mesh.mshstats.dropped_frames_no_route++; |
787 | err = -ENOSPC; | 787 | err = -ENOSPC; |
788 | goto endlookup; | 788 | goto endlookup; |
789 | } | 789 | } |
@@ -791,7 +791,7 @@ int mesh_nexthop_lookup(struct sk_buff *skb, | |||
791 | 791 | ||
792 | if (mpath->flags & MESH_PATH_ACTIVE) { | 792 | if (mpath->flags & MESH_PATH_ACTIVE) { |
793 | if (time_after(jiffies, mpath->exp_time - | 793 | if (time_after(jiffies, mpath->exp_time - |
794 | msecs_to_jiffies(sdata->u.sta.mshcfg.path_refresh_time)) | 794 | msecs_to_jiffies(sdata->u.mesh.mshcfg.path_refresh_time)) |
795 | && !memcmp(sdata->dev->dev_addr, hdr->addr4, | 795 | && !memcmp(sdata->dev->dev_addr, hdr->addr4, |
796 | ETH_ALEN) | 796 | ETH_ALEN) |
797 | && !(mpath->flags & MESH_PATH_RESOLVING) | 797 | && !(mpath->flags & MESH_PATH_RESOLVING) |
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index 0a60f55f32ab..e4fa2905fadc 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c | |||
@@ -153,7 +153,7 @@ int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata) | |||
153 | if (is_multicast_ether_addr(dst)) | 153 | if (is_multicast_ether_addr(dst)) |
154 | return -ENOTSUPP; | 154 | return -ENOTSUPP; |
155 | 155 | ||
156 | if (atomic_add_unless(&sdata->u.sta.mpaths, 1, MESH_MAX_MPATHS) == 0) | 156 | if (atomic_add_unless(&sdata->u.mesh.mpaths, 1, MESH_MAX_MPATHS) == 0) |
157 | return -ENOSPC; | 157 | return -ENOSPC; |
158 | 158 | ||
159 | err = -ENOMEM; | 159 | err = -ENOMEM; |
@@ -221,7 +221,7 @@ err_exists: | |||
221 | err_node_alloc: | 221 | err_node_alloc: |
222 | kfree(new_mpath); | 222 | kfree(new_mpath); |
223 | err_path_alloc: | 223 | err_path_alloc: |
224 | atomic_dec(&sdata->u.sta.mpaths); | 224 | atomic_dec(&sdata->u.mesh.mpaths); |
225 | return err; | 225 | return err; |
226 | } | 226 | } |
227 | 227 | ||
@@ -306,7 +306,7 @@ static void mesh_path_node_reclaim(struct rcu_head *rp) | |||
306 | struct ieee80211_sub_if_data *sdata = node->mpath->sdata; | 306 | struct ieee80211_sub_if_data *sdata = node->mpath->sdata; |
307 | 307 | ||
308 | del_timer_sync(&node->mpath->timer); | 308 | del_timer_sync(&node->mpath->timer); |
309 | atomic_dec(&sdata->u.sta.mpaths); | 309 | atomic_dec(&sdata->u.mesh.mpaths); |
310 | kfree(node->mpath); | 310 | kfree(node->mpath); |
311 | kfree(node); | 311 | kfree(node); |
312 | } | 312 | } |
@@ -401,7 +401,7 @@ void mesh_path_discard_frame(struct sk_buff *skb, | |||
401 | } | 401 | } |
402 | 402 | ||
403 | kfree_skb(skb); | 403 | kfree_skb(skb); |
404 | sdata->u.sta.mshstats.dropped_frames_no_route++; | 404 | sdata->u.mesh.mshstats.dropped_frames_no_route++; |
405 | } | 405 | } |
406 | 406 | ||
407 | /** | 407 | /** |
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 7356462dee96..990a4b7f6bcc 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c | |||
@@ -36,11 +36,11 @@ | |||
36 | #define MESH_SECURITY_AUTHENTICATION_IMPOSSIBLE 9 | 36 | #define MESH_SECURITY_AUTHENTICATION_IMPOSSIBLE 9 |
37 | #define MESH_SECURITY_FAILED_VERIFICATION 10 | 37 | #define MESH_SECURITY_FAILED_VERIFICATION 10 |
38 | 38 | ||
39 | #define dot11MeshMaxRetries(s) (s->u.sta.mshcfg.dot11MeshMaxRetries) | 39 | #define dot11MeshMaxRetries(s) (s->u.mesh.mshcfg.dot11MeshMaxRetries) |
40 | #define dot11MeshRetryTimeout(s) (s->u.sta.mshcfg.dot11MeshRetryTimeout) | 40 | #define dot11MeshRetryTimeout(s) (s->u.mesh.mshcfg.dot11MeshRetryTimeout) |
41 | #define dot11MeshConfirmTimeout(s) (s->u.sta.mshcfg.dot11MeshConfirmTimeout) | 41 | #define dot11MeshConfirmTimeout(s) (s->u.mesh.mshcfg.dot11MeshConfirmTimeout) |
42 | #define dot11MeshHoldingTimeout(s) (s->u.sta.mshcfg.dot11MeshHoldingTimeout) | 42 | #define dot11MeshHoldingTimeout(s) (s->u.mesh.mshcfg.dot11MeshHoldingTimeout) |
43 | #define dot11MeshMaxPeerLinks(s) (s->u.sta.mshcfg.dot11MeshMaxPeerLinks) | 43 | #define dot11MeshMaxPeerLinks(s) (s->u.mesh.mshcfg.dot11MeshMaxPeerLinks) |
44 | 44 | ||
45 | enum plink_frame_type { | 45 | enum plink_frame_type { |
46 | PLINK_OPEN = 0, | 46 | PLINK_OPEN = 0, |
@@ -63,14 +63,14 @@ enum plink_event { | |||
63 | static inline | 63 | static inline |
64 | void mesh_plink_inc_estab_count(struct ieee80211_sub_if_data *sdata) | 64 | void mesh_plink_inc_estab_count(struct ieee80211_sub_if_data *sdata) |
65 | { | 65 | { |
66 | atomic_inc(&sdata->u.sta.mshstats.estab_plinks); | 66 | atomic_inc(&sdata->u.mesh.mshstats.estab_plinks); |
67 | mesh_accept_plinks_update(sdata); | 67 | mesh_accept_plinks_update(sdata); |
68 | } | 68 | } |
69 | 69 | ||
70 | static inline | 70 | static inline |
71 | void mesh_plink_dec_estab_count(struct ieee80211_sub_if_data *sdata) | 71 | void mesh_plink_dec_estab_count(struct ieee80211_sub_if_data *sdata) |
72 | { | 72 | { |
73 | atomic_dec(&sdata->u.sta.mshstats.estab_plinks); | 73 | atomic_dec(&sdata->u.mesh.mshstats.estab_plinks); |
74 | mesh_accept_plinks_update(sdata); | 74 | mesh_accept_plinks_update(sdata); |
75 | } | 75 | } |
76 | 76 | ||
@@ -245,8 +245,8 @@ void mesh_neighbour_update(u8 *hw_addr, u64 rates, struct ieee80211_sub_if_data | |||
245 | sta->last_rx = jiffies; | 245 | sta->last_rx = jiffies; |
246 | sta->supp_rates[local->hw.conf.channel->band] = rates; | 246 | sta->supp_rates[local->hw.conf.channel->band] = rates; |
247 | if (peer_accepting_plinks && sta->plink_state == PLINK_LISTEN && | 247 | if (peer_accepting_plinks && sta->plink_state == PLINK_LISTEN && |
248 | sdata->u.sta.accepting_plinks && | 248 | sdata->u.mesh.accepting_plinks && |
249 | sdata->u.sta.mshcfg.auto_open_plinks) | 249 | sdata->u.mesh.mshcfg.auto_open_plinks) |
250 | mesh_plink_open(sta); | 250 | mesh_plink_open(sta); |
251 | 251 | ||
252 | rcu_read_unlock(); | 252 | rcu_read_unlock(); |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index ef73f8953724..9e20a0c20a46 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -22,11 +22,11 @@ | |||
22 | #include <linux/rtnetlink.h> | 22 | #include <linux/rtnetlink.h> |
23 | #include <net/iw_handler.h> | 23 | #include <net/iw_handler.h> |
24 | #include <net/mac80211.h> | 24 | #include <net/mac80211.h> |
25 | #include <asm/unaligned.h> | ||
25 | 26 | ||
26 | #include "ieee80211_i.h" | 27 | #include "ieee80211_i.h" |
27 | #include "rate.h" | 28 | #include "rate.h" |
28 | #include "led.h" | 29 | #include "led.h" |
29 | #include "mesh.h" | ||
30 | 30 | ||
31 | #define IEEE80211_ASSOC_SCANS_MAX_TRIES 2 | 31 | #define IEEE80211_ASSOC_SCANS_MAX_TRIES 2 |
32 | #define IEEE80211_AUTH_TIMEOUT (HZ / 5) | 32 | #define IEEE80211_AUTH_TIMEOUT (HZ / 5) |
@@ -34,7 +34,6 @@ | |||
34 | #define IEEE80211_ASSOC_TIMEOUT (HZ / 5) | 34 | #define IEEE80211_ASSOC_TIMEOUT (HZ / 5) |
35 | #define IEEE80211_ASSOC_MAX_TRIES 3 | 35 | #define IEEE80211_ASSOC_MAX_TRIES 3 |
36 | #define IEEE80211_MONITORING_INTERVAL (2 * HZ) | 36 | #define IEEE80211_MONITORING_INTERVAL (2 * HZ) |
37 | #define IEEE80211_MESH_HOUSEKEEPING_INTERVAL (60 * HZ) | ||
38 | #define IEEE80211_PROBE_INTERVAL (60 * HZ) | 37 | #define IEEE80211_PROBE_INTERVAL (60 * HZ) |
39 | #define IEEE80211_RETRY_AUTH_INTERVAL (1 * HZ) | 38 | #define IEEE80211_RETRY_AUTH_INTERVAL (1 * HZ) |
40 | #define IEEE80211_SCAN_INTERVAL (2 * HZ) | 39 | #define IEEE80211_SCAN_INTERVAL (2 * HZ) |
@@ -43,7 +42,6 @@ | |||
43 | 42 | ||
44 | #define IEEE80211_IBSS_MERGE_INTERVAL (30 * HZ) | 43 | #define IEEE80211_IBSS_MERGE_INTERVAL (30 * HZ) |
45 | #define IEEE80211_IBSS_INACTIVITY_LIMIT (60 * HZ) | 44 | #define IEEE80211_IBSS_INACTIVITY_LIMIT (60 * HZ) |
46 | #define IEEE80211_MESH_PEER_INACTIVITY_LIMIT (1800 * HZ) | ||
47 | 45 | ||
48 | #define IEEE80211_IBSS_MAX_STA_ENTRIES 128 | 46 | #define IEEE80211_IBSS_MAX_STA_ENTRIES 128 |
49 | 47 | ||
@@ -1508,14 +1506,6 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
1508 | if (!channel || channel->flags & IEEE80211_CHAN_DISABLED) | 1506 | if (!channel || channel->flags & IEEE80211_CHAN_DISABLED) |
1509 | return; | 1507 | return; |
1510 | 1508 | ||
1511 | if (ieee80211_vif_is_mesh(&sdata->vif) && elems->mesh_id && | ||
1512 | elems->mesh_config && mesh_matches_local(elems, sdata)) { | ||
1513 | supp_rates = ieee80211_sta_get_rates(local, elems, band); | ||
1514 | |||
1515 | mesh_neighbour_update(mgmt->sa, supp_rates, sdata, | ||
1516 | mesh_peer_accepts_plinks(elems)); | ||
1517 | } | ||
1518 | |||
1519 | if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && elems->supp_rates && | 1509 | if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && elems->supp_rates && |
1520 | memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0) { | 1510 | memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0) { |
1521 | supp_rates = ieee80211_sta_get_rates(local, elems, band); | 1511 | supp_rates = ieee80211_sta_get_rates(local, elems, band); |
@@ -1785,26 +1775,6 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, | |||
1785 | ieee80211_tx_skb(sdata, skb, 0); | 1775 | ieee80211_tx_skb(sdata, skb, 0); |
1786 | } | 1776 | } |
1787 | 1777 | ||
1788 | static void ieee80211_rx_mgmt_action(struct ieee80211_sub_if_data *sdata, | ||
1789 | struct ieee80211_if_sta *ifsta, | ||
1790 | struct ieee80211_mgmt *mgmt, | ||
1791 | size_t len, | ||
1792 | struct ieee80211_rx_status *rx_status) | ||
1793 | { | ||
1794 | /* currently we only handle mesh interface action frames here */ | ||
1795 | if (!ieee80211_vif_is_mesh(&sdata->vif)) | ||
1796 | return; | ||
1797 | |||
1798 | switch (mgmt->u.action.category) { | ||
1799 | case PLINK_CATEGORY: | ||
1800 | mesh_rx_plink_frame(sdata, mgmt, len, rx_status); | ||
1801 | break; | ||
1802 | case MESH_PATH_SEL_CATEGORY: | ||
1803 | mesh_rx_path_sel_frame(sdata, mgmt, len); | ||
1804 | break; | ||
1805 | } | ||
1806 | } | ||
1807 | |||
1808 | void ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, | 1778 | void ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, |
1809 | struct ieee80211_rx_status *rx_status) | 1779 | struct ieee80211_rx_status *rx_status) |
1810 | { | 1780 | { |
@@ -1825,7 +1795,6 @@ void ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff * | |||
1825 | case IEEE80211_STYPE_PROBE_REQ: | 1795 | case IEEE80211_STYPE_PROBE_REQ: |
1826 | case IEEE80211_STYPE_PROBE_RESP: | 1796 | case IEEE80211_STYPE_PROBE_RESP: |
1827 | case IEEE80211_STYPE_BEACON: | 1797 | case IEEE80211_STYPE_BEACON: |
1828 | case IEEE80211_STYPE_ACTION: | ||
1829 | memcpy(skb->cb, rx_status, sizeof(*rx_status)); | 1798 | memcpy(skb->cb, rx_status, sizeof(*rx_status)); |
1830 | case IEEE80211_STYPE_AUTH: | 1799 | case IEEE80211_STYPE_AUTH: |
1831 | case IEEE80211_STYPE_ASSOC_RESP: | 1800 | case IEEE80211_STYPE_ASSOC_RESP: |
@@ -1881,9 +1850,6 @@ static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | |||
1881 | case IEEE80211_STYPE_DISASSOC: | 1850 | case IEEE80211_STYPE_DISASSOC: |
1882 | ieee80211_rx_mgmt_disassoc(sdata, ifsta, mgmt, skb->len); | 1851 | ieee80211_rx_mgmt_disassoc(sdata, ifsta, mgmt, skb->len); |
1883 | break; | 1852 | break; |
1884 | case IEEE80211_STYPE_ACTION: | ||
1885 | ieee80211_rx_mgmt_action(sdata, ifsta, mgmt, skb->len, rx_status); | ||
1886 | break; | ||
1887 | } | 1853 | } |
1888 | 1854 | ||
1889 | kfree_skb(skb); | 1855 | kfree_skb(skb); |
@@ -1928,35 +1894,6 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata, | |||
1928 | } | 1894 | } |
1929 | 1895 | ||
1930 | 1896 | ||
1931 | #ifdef CONFIG_MAC80211_MESH | ||
1932 | static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata, | ||
1933 | struct ieee80211_if_sta *ifsta) | ||
1934 | { | ||
1935 | bool free_plinks; | ||
1936 | |||
1937 | ieee80211_sta_expire(sdata, IEEE80211_MESH_PEER_INACTIVITY_LIMIT); | ||
1938 | mesh_path_expire(sdata); | ||
1939 | |||
1940 | free_plinks = mesh_plink_availables(sdata); | ||
1941 | if (free_plinks != sdata->u.sta.accepting_plinks) | ||
1942 | ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); | ||
1943 | |||
1944 | mod_timer(&ifsta->timer, jiffies + | ||
1945 | IEEE80211_MESH_HOUSEKEEPING_INTERVAL); | ||
1946 | } | ||
1947 | |||
1948 | |||
1949 | void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) | ||
1950 | { | ||
1951 | struct ieee80211_if_sta *ifsta; | ||
1952 | ifsta = &sdata->u.sta; | ||
1953 | ifsta->state = IEEE80211_STA_MLME_MESH_UP; | ||
1954 | ieee80211_sta_timer((unsigned long)sdata); | ||
1955 | ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); | ||
1956 | } | ||
1957 | #endif | ||
1958 | |||
1959 | |||
1960 | void ieee80211_sta_timer(unsigned long data) | 1897 | void ieee80211_sta_timer(unsigned long data) |
1961 | { | 1898 | { |
1962 | struct ieee80211_sub_if_data *sdata = | 1899 | struct ieee80211_sub_if_data *sdata = |
@@ -2524,21 +2461,13 @@ void ieee80211_sta_work(struct work_struct *work) | |||
2524 | return; | 2461 | return; |
2525 | 2462 | ||
2526 | if (WARN_ON(sdata->vif.type != IEEE80211_IF_TYPE_STA && | 2463 | if (WARN_ON(sdata->vif.type != IEEE80211_IF_TYPE_STA && |
2527 | sdata->vif.type != IEEE80211_IF_TYPE_IBSS && | 2464 | sdata->vif.type != IEEE80211_IF_TYPE_IBSS)) |
2528 | sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT)) | ||
2529 | return; | 2465 | return; |
2530 | ifsta = &sdata->u.sta; | 2466 | ifsta = &sdata->u.sta; |
2531 | 2467 | ||
2532 | while ((skb = skb_dequeue(&ifsta->skb_queue))) | 2468 | while ((skb = skb_dequeue(&ifsta->skb_queue))) |
2533 | ieee80211_sta_rx_queued_mgmt(sdata, skb); | 2469 | ieee80211_sta_rx_queued_mgmt(sdata, skb); |
2534 | 2470 | ||
2535 | #ifdef CONFIG_MAC80211_MESH | ||
2536 | if (ifsta->preq_queue_len && | ||
2537 | time_after(jiffies, | ||
2538 | ifsta->last_preq + msecs_to_jiffies(ifsta->mshcfg.dot11MeshHWMPpreqMinInterval))) | ||
2539 | mesh_path_start_discovery(sdata); | ||
2540 | #endif | ||
2541 | |||
2542 | if (ifsta->state != IEEE80211_STA_MLME_DIRECT_PROBE && | 2471 | if (ifsta->state != IEEE80211_STA_MLME_DIRECT_PROBE && |
2543 | ifsta->state != IEEE80211_STA_MLME_AUTHENTICATE && | 2472 | ifsta->state != IEEE80211_STA_MLME_AUTHENTICATE && |
2544 | ifsta->state != IEEE80211_STA_MLME_ASSOCIATE && | 2473 | ifsta->state != IEEE80211_STA_MLME_ASSOCIATE && |
@@ -2575,11 +2504,6 @@ void ieee80211_sta_work(struct work_struct *work) | |||
2575 | case IEEE80211_STA_MLME_IBSS_JOINED: | 2504 | case IEEE80211_STA_MLME_IBSS_JOINED: |
2576 | ieee80211_sta_merge_ibss(sdata, ifsta); | 2505 | ieee80211_sta_merge_ibss(sdata, ifsta); |
2577 | break; | 2506 | break; |
2578 | #ifdef CONFIG_MAC80211_MESH | ||
2579 | case IEEE80211_STA_MLME_MESH_UP: | ||
2580 | ieee80211_mesh_housekeeping(sdata, ifsta); | ||
2581 | break; | ||
2582 | #endif | ||
2583 | default: | 2507 | default: |
2584 | WARN_ON(1); | 2508 | WARN_ON(1); |
2585 | break; | 2509 | break; |
@@ -2596,8 +2520,7 @@ void ieee80211_sta_work(struct work_struct *work) | |||
2596 | 2520 | ||
2597 | static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata) | 2521 | static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata) |
2598 | { | 2522 | { |
2599 | if (sdata->vif.type == IEEE80211_IF_TYPE_STA || | 2523 | if (sdata->vif.type == IEEE80211_IF_TYPE_STA) |
2600 | ieee80211_vif_is_mesh(&sdata->vif)) | ||
2601 | queue_work(sdata->local->hw.workqueue, | 2524 | queue_work(sdata->local->hw.workqueue, |
2602 | &sdata->u.sta.work); | 2525 | &sdata->u.sta.work); |
2603 | } | 2526 | } |
diff --git a/net/mac80211/rc80211_pid_algo.c b/net/mac80211/rc80211_pid_algo.c index a914ba73ccf5..21e1942ea975 100644 --- a/net/mac80211/rc80211_pid_algo.c +++ b/net/mac80211/rc80211_pid_algo.c | |||
@@ -148,9 +148,7 @@ static void rate_control_pid_sample(struct rc_pid_info *pinfo, | |||
148 | struct ieee80211_local *local, | 148 | struct ieee80211_local *local, |
149 | struct sta_info *sta) | 149 | struct sta_info *sta) |
150 | { | 150 | { |
151 | #ifdef CONFIG_MAC80211_MESH | ||
152 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 151 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
153 | #endif | ||
154 | struct rc_pid_sta_info *spinfo = sta->rate_ctrl_priv; | 152 | struct rc_pid_sta_info *spinfo = sta->rate_ctrl_priv; |
155 | struct rc_pid_rateinfo *rinfo = pinfo->rinfo; | 153 | struct rc_pid_rateinfo *rinfo = pinfo->rinfo; |
156 | struct ieee80211_supported_band *sband; | 154 | struct ieee80211_supported_band *sband; |
@@ -181,11 +179,8 @@ static void rate_control_pid_sample(struct rc_pid_info *pinfo, | |||
181 | pf = spinfo->last_pf; | 179 | pf = spinfo->last_pf; |
182 | else { | 180 | else { |
183 | pf = spinfo->tx_num_failed * 100 / spinfo->tx_num_xmit; | 181 | pf = spinfo->tx_num_failed * 100 / spinfo->tx_num_xmit; |
184 | #ifdef CONFIG_MAC80211_MESH | 182 | if (ieee80211_vif_is_mesh(&sdata->vif) && pf == 100) |
185 | if (pf == 100 && | ||
186 | sdata->vif.type == IEEE80211_IF_TYPE_MESH_POINT) | ||
187 | mesh_plink_broken(sta); | 183 | mesh_plink_broken(sta); |
188 | #endif | ||
189 | pf <<= RC_PID_ARITH_SHIFT; | 184 | pf <<= RC_PID_ARITH_SHIFT; |
190 | sta->fail_avg = ((pf + (spinfo->last_pf << 3)) / 9) | 185 | sta->fail_avg = ((pf + (spinfo->last_pf << 3)) / 9) |
191 | >> RC_PID_ARITH_SHIFT; | 186 | >> RC_PID_ARITH_SHIFT; |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index d0803797902b..208563a27bc4 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -1404,7 +1404,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
1404 | 1404 | ||
1405 | if (rx->flags & IEEE80211_RX_RA_MATCH) { | 1405 | if (rx->flags & IEEE80211_RX_RA_MATCH) { |
1406 | if (!mesh_hdr->ttl) | 1406 | if (!mesh_hdr->ttl) |
1407 | IEEE80211_IFSTA_MESH_CTR_INC(&rx->sdata->u.sta, | 1407 | IEEE80211_IFSTA_MESH_CTR_INC(&rx->sdata->u.mesh, |
1408 | dropped_frames_ttl); | 1408 | dropped_frames_ttl); |
1409 | else { | 1409 | else { |
1410 | struct ieee80211_hdr *fwd_hdr; | 1410 | struct ieee80211_hdr *fwd_hdr; |
@@ -1591,9 +1591,11 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) | |||
1591 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) | 1591 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) |
1592 | return RX_DROP_MONITOR; | 1592 | return RX_DROP_MONITOR; |
1593 | 1593 | ||
1594 | if (ieee80211_vif_is_mesh(&sdata->vif)) | ||
1595 | return ieee80211_mesh_rx_mgmt(sdata, rx->skb, rx->status); | ||
1596 | |||
1594 | if (sdata->vif.type != IEEE80211_IF_TYPE_STA && | 1597 | if (sdata->vif.type != IEEE80211_IF_TYPE_STA && |
1595 | sdata->vif.type != IEEE80211_IF_TYPE_IBSS && | 1598 | sdata->vif.type != IEEE80211_IF_TYPE_IBSS) |
1596 | sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT) | ||
1597 | return RX_DROP_MONITOR; | 1599 | return RX_DROP_MONITOR; |
1598 | 1600 | ||
1599 | if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME) | 1601 | if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME) |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index f8b296bed0b9..f4399e9ac928 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -476,6 +476,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw) | |||
476 | 476 | ||
477 | done: | 477 | done: |
478 | ieee80211_mlme_notify_scan_completed(local); | 478 | ieee80211_mlme_notify_scan_completed(local); |
479 | ieee80211_mesh_notify_scan_completed(local); | ||
479 | } | 480 | } |
480 | EXPORT_SYMBOL(ieee80211_scan_completed); | 481 | EXPORT_SYMBOL(ieee80211_scan_completed); |
481 | 482 | ||
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index c413d4836afe..1059b17c83b0 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -1330,7 +1330,7 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, | |||
1330 | if (mesh_nexthop_lookup(skb, osdata)) | 1330 | if (mesh_nexthop_lookup(skb, osdata)) |
1331 | return 0; | 1331 | return 0; |
1332 | if (memcmp(odev->dev_addr, hdr->addr4, ETH_ALEN) != 0) | 1332 | if (memcmp(odev->dev_addr, hdr->addr4, ETH_ALEN) != 0) |
1333 | IEEE80211_IFSTA_MESH_CTR_INC(&osdata->u.sta, | 1333 | IEEE80211_IFSTA_MESH_CTR_INC(&osdata->u.mesh, |
1334 | fwded_frames); | 1334 | fwded_frames); |
1335 | } | 1335 | } |
1336 | } | 1336 | } |
@@ -1483,9 +1483,9 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1483 | memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); | 1483 | memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); |
1484 | memcpy(hdr.addr3, skb->data, ETH_ALEN); | 1484 | memcpy(hdr.addr3, skb->data, ETH_ALEN); |
1485 | memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN); | 1485 | memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN); |
1486 | if (!sdata->u.sta.mshcfg.dot11MeshTTL) { | 1486 | if (!sdata->u.mesh.mshcfg.dot11MeshTTL) { |
1487 | /* Do not send frames with mesh_ttl == 0 */ | 1487 | /* Do not send frames with mesh_ttl == 0 */ |
1488 | sdata->u.sta.mshstats.dropped_frames_ttl++; | 1488 | sdata->u.mesh.mshstats.dropped_frames_ttl++; |
1489 | ret = 0; | 1489 | ret = 0; |
1490 | goto fail; | 1490 | goto fail; |
1491 | } | 1491 | } |
@@ -1815,10 +1815,8 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, | |||
1815 | struct rate_selection rsel; | 1815 | struct rate_selection rsel; |
1816 | struct beacon_data *beacon; | 1816 | struct beacon_data *beacon; |
1817 | struct ieee80211_supported_band *sband; | 1817 | struct ieee80211_supported_band *sband; |
1818 | struct ieee80211_mgmt *mgmt; | ||
1819 | int *num_beacons; | 1818 | int *num_beacons; |
1820 | enum ieee80211_band band = local->hw.conf.channel->band; | 1819 | enum ieee80211_band band = local->hw.conf.channel->band; |
1821 | u8 *pos; | ||
1822 | 1820 | ||
1823 | sband = local->hw.wiphy->bands[band]; | 1821 | sband = local->hw.wiphy->bands[band]; |
1824 | 1822 | ||
@@ -1885,7 +1883,11 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, | |||
1885 | IEEE80211_STYPE_BEACON); | 1883 | IEEE80211_STYPE_BEACON); |
1886 | 1884 | ||
1887 | num_beacons = &ifsta->num_beacons; | 1885 | num_beacons = &ifsta->num_beacons; |
1886 | #ifdef CONFIG_MAC80211_MESH | ||
1888 | } else if (ieee80211_vif_is_mesh(&sdata->vif)) { | 1887 | } else if (ieee80211_vif_is_mesh(&sdata->vif)) { |
1888 | struct ieee80211_mgmt *mgmt; | ||
1889 | u8 *pos; | ||
1890 | |||
1889 | /* headroom, head length, tail length and maximum TIM length */ | 1891 | /* headroom, head length, tail length and maximum TIM length */ |
1890 | skb = dev_alloc_skb(local->tx_headroom + 400); | 1892 | skb = dev_alloc_skb(local->tx_headroom + 400); |
1891 | if (!skb) | 1893 | if (!skb) |
@@ -1910,7 +1912,8 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, | |||
1910 | 1912 | ||
1911 | mesh_mgmt_ies_add(skb, sdata); | 1913 | mesh_mgmt_ies_add(skb, sdata); |
1912 | 1914 | ||
1913 | num_beacons = &sdata->u.sta.num_beacons; | 1915 | num_beacons = &sdata->u.mesh.num_beacons; |
1916 | #endif | ||
1914 | } else { | 1917 | } else { |
1915 | WARN_ON(1); | 1918 | WARN_ON(1); |
1916 | goto out; | 1919 | goto out; |